# Licensed under a 3-clause BSD style license - see LICENSE.rst

# "core.py" is auto-generated by erfa_generator.py from the template
# "core.py.templ". Do *not* edit "core.py" directly, instead edit
# "core.py.templ" and run erfa_generator.py from the source directory to
# update it.

"""
This module uses the Python/C API to wrap the ERFA library in
numpy-vectorized equivalents.

..warning::
    This is currently *not* part of the public Astropy API, and may change in
    the future.


The key idea is that any function can be called with inputs that are arrays,
and the wrappers will automatically vectorize and call the ERFA functions for
each item using broadcasting rules for numpy.  So the return values are always
numpy arrays of some sort.

For ERFA functions that take/return vectors or matrices, the vector/matrix
dimension(s) are always the *last* dimension(s).  For example, if you
want to give ten matrices (i.e., the ERFA input type is double[3][3]),
you would pass in a (10, 3, 3) numpy array.  If the output of the ERFA
function is scalar, you'll get back a length-10 1D array.

Note that the C part of these functions are implemented in a separate
module (compiled as ``_core``), derived from the ``core.c`` file.
Splitting the wrappers into separate pure-python and C portions
dramatically reduces compilation time without notably impacting
performance. (See issue [#3063] on the github repository for more
about this.)
"""
from __future__ import absolute_import, division, print_function

import warnings

from ..utils.compat import NUMPY_LT_1_8
from ..utils.exceptions import AstropyUserWarning

import numpy
from . import _core

# TODO: remove the above variable and the code using it and make_outputs_scalar
# when numpy < 1.8 is no longer supported

__all__ = ['ErfaError', 'ErfaWarning',
           'cal2jd', 'epb', 'epb2jd', 'epj', 'epj2jd', 'jd2cal', 'jdcalf', 'ab', 'apcg', 'apcg13', 'apci', 'apci13', 'apco', 'apco13', 'apcs', 'apcs13', 'aper', 'aper13', 'apio', 'apio13', 'atci13', 'atciq', 'atciqn', 'atciqz', 'atco13', 'atic13', 'aticq', 'aticqn', 'atio13', 'atioq', 'atoc13', 'atoi13', 'atoiq', 'ld', 'ldn', 'ldsun', 'pmpx', 'pmsafe', 'pvtob', 'refco', 'epv00', 'plan94', 'fad03', 'fae03', 'faf03', 'faju03', 'fal03', 'falp03', 'fama03', 'fame03', 'fane03', 'faom03', 'fapa03', 'fasa03', 'faur03', 'fave03', 'bi00', 'bp00', 'bp06', 'bpn2xy', 'c2i00a', 'c2i00b', 'c2i06a', 'c2ibpn', 'c2ixy', 'c2ixys', 'c2t00a', 'c2t00b', 'c2t06a', 'c2tcio', 'c2teqx', 'c2tpe', 'c2txy', 'eo06a', 'eors', 'fw2m', 'fw2xy', 'ltp', 'ltpb', 'ltpecl', 'ltpequ', 'num00a', 'num00b', 'num06a', 'numat', 'nut00a', 'nut00b', 'nut06a', 'nut80', 'nutm80', 'obl06', 'obl80', 'p06e', 'pb06', 'pfw06', 'pmat00', 'pmat06', 'pmat76', 'pn00', 'pn00a', 'pn00b', 'pn06', 'pn06a', 'pnm00a', 'pnm00b', 'pnm06a', 'pnm80', 'pom00', 'pr00', 'prec76', 's00', 's00a', 's00b', 's06', 's06a', 'sp00', 'xy06', 'xys00a', 'xys00b', 'xys06a', 'ee00', 'ee00a', 'ee00b', 'ee06a', 'eect00', 'eqeq94', 'era00', 'gmst00', 'gmst06', 'gmst82', 'gst00a', 'gst00b', 'gst06', 'gst06a', 'gst94', 'pvstar', 'starpv', 'fk52h', 'fk5hip', 'fk5hz', 'h2fk5', 'hfk5z', 'starpm', 'eceq06', 'ecm06', 'eqec06', 'lteceq', 'ltecm', 'lteqec', 'g2icrs', 'icrs2g', 'eform', 'gc2gd', 'gc2gde', 'gd2gc', 'gd2gce', 'd2dtf', 'dat', 'dtdb', 'dtf2d', 'taitt', 'taiut1', 'taiutc', 'tcbtdb', 'tcgtt', 'tdbtcb', 'tdbtt', 'tttai', 'tttcg', 'tttdb', 'ttut1', 'ut1tai', 'ut1tt', 'ut1utc', 'utctai', 'utcut1', 'a2af', 'a2tf', 'af2a', 'anp', 'anpm', 'd2tf', 'tf2a', 'tf2d', 'rxp', 'rxpv', 'trxp', 'trxpv', 'c2s', 'p2s', 'pv2s', 's2c', 's2p', 's2pv',
           'DPI', 'D2PI', 'DR2D', 'DD2R', 'DR2AS', 'DAS2R', 'DS2R', 'TURNAS', 'DMAS2R', 'DTY', 'DAYSEC', 'DJY', 'DJC', 'DJM', 'DJ00', 'DJM0', 'DJM00', 'DJM77', 'TTMTAI', 'DAU', 'CMPS', 'AULT', 'DC', 'ELG', 'ELB', 'TDB0', 'SRS', 'WGS84', 'GRS80', 'WGS72',
           'dt_eraASTROM', 'dt_eraLDBODY']


#<---------------------------------Error-handling----------------------------->

class ErfaError(ValueError):
    """
    A class for errors triggered by ERFA functions (status codes < 0)
    """


class ErfaWarning(AstropyUserWarning):
    """
    A class for warnings triggered by ERFA functions (status codes > 0)
    """


STATUS_CODES = {}  # populated below before each function that returns an int

# This is a hard-coded list of status codes that need to be remapped,
# such as to turn errors into warnings.
STATUS_CODES_REMAP = {
    'cal2jd': {-3: 3}
}


def check_errwarn(statcodes, func_name):
    # Remap any errors into warnings in the STATUS_CODES_REMAP dict.
    if func_name in STATUS_CODES_REMAP:
        for before, after in STATUS_CODES_REMAP[func_name].items():
            statcodes[statcodes == before] = after
            STATUS_CODES[func_name][after] = STATUS_CODES[func_name][before]

    if numpy.any(statcodes<0):
        # errors present - only report the errors.
        if statcodes.shape:
            statcodes = statcodes[statcodes<0]

        errcodes = numpy.unique(statcodes)

        errcounts = dict([(e, numpy.sum(statcodes==e)) for e in errcodes])

        elsemsg = STATUS_CODES[func_name].get('else', None)
        if elsemsg is None:
            errmsgs = dict([(e, STATUS_CODES[func_name].get(e, 'Return code ' + str(e))) for e in errcodes])
        else:
            errmsgs = dict([(e, STATUS_CODES[func_name].get(e, elsemsg)) for e in errcodes])

        emsg = ', '.join(['{0} of "{1}"'.format(errcounts[e], errmsgs[e]) for e in errcodes])
        raise ErfaError('ERFA function "' + func_name + '" yielded ' + emsg)

    elif numpy.any(statcodes>0):
        #only warnings present
        if statcodes.shape:
            statcodes = statcodes[statcodes>0]

        warncodes = numpy.unique(statcodes)

        warncounts = dict([(w, numpy.sum(statcodes==w)) for w in warncodes])

        elsemsg = STATUS_CODES[func_name].get('else', None)
        if elsemsg is None:
            warnmsgs = dict([(w, STATUS_CODES[func_name].get(w, 'Return code ' + str(w))) for w in warncodes])
        else:
            warnmsgs = dict([(w, STATUS_CODES[func_name].get(w, elsemsg)) for w in warncodes])

        wmsg = ', '.join(['{0} of "{1}"'.format(warncounts[w], warnmsgs[w]) for w in warncodes])
        warnings.warn('ERFA function "' + func_name + '" yielded ' + wmsg, ErfaWarning)


#<-------------------------trailing shape verification------------------------>

def check_trailing_shape(arr, shape, name):
    try:
        if arr.shape[-len(shape):] != shape:
            raise Exception()
    except:
        raise ValueError("{0} must be of trailing dimensions {1}".format(name, shape))

#<--------------------------Actual ERFA-wrapping code------------------------->

dt_eraASTROM = numpy.dtype([('pmt','d'),
                         ('eb','d',(3,)),
                         ('eh','d',(3,)),
                         ('em','d'),
                         ('v','d',(3,)),
                         ('bm1','d'),
                         ('bpn','d',(3,3)),
                         ('along','d'),
                         ('phi','d'),
                         ('xpl','d'),
                         ('ypl','d'),
                         ('sphi','d'),
                         ('cphi','d'),
                         ('diurab','d'),
                         ('eral','d'),
                         ('refa','d'),
                         ('refb','d')], align=True)

dt_eraLDBODY = numpy.dtype([('bm','d'),
                         ('dl','d'),
                         ('pv','d',(2,3))], align=True)



DPI = (3.141592653589793238462643)
"""Pi"""
D2PI = (6.283185307179586476925287)
"""2Pi"""
DR2D = (57.29577951308232087679815)
"""Radians to degrees"""
DD2R = (1.745329251994329576923691e-2)
"""Degrees to radians"""
DR2AS = (206264.8062470963551564734)
"""Radians to arcseconds"""
DAS2R = (4.848136811095359935899141e-6)
"""Arcseconds to radians"""
DS2R = (7.272205216643039903848712e-5)
"""Seconds of time to radians"""
TURNAS = (1296000.0)
"""Arcseconds in a full circle"""
DMAS2R = (DAS2R / 1e3)
"""Milliarcseconds to radians"""
DTY = (365.242198781)
"""Length of tropical year B1900 (days)"""
DAYSEC = (86400.0)
"""Seconds per day."""
DJY = (365.25)
"""Days per Julian year"""
DJC = (36525.0)
"""Days per Julian century"""
DJM = (365250.0)
"""Days per Julian millennium"""
DJ00 = (2451545.0)
"""Reference epoch (J2000.0), Julian Date"""
DJM0 = (2400000.5)
"""Julian Date of Modified Julian Date zero"""
DJM00 = (51544.5)
"""Reference epoch (J2000.0), Modified Julian Date"""
DJM77 = (43144.0)
"""1977 Jan 1.0 as MJD"""
TTMTAI = (32.184)
"""TT minus TAI (s)"""
DAU = (149597870e3)
"""Astronomical unit (m)"""
CMPS = 299792458.0
"""Speed of light (m/s)"""
AULT = 499.004782
"""Light time for 1 au (s)"""
DC = (DAYSEC / AULT)
"""Speed of light (AU per day)"""
ELG = (6.969290134e-10)
"""L_G = 1 - d(TT)/d(TCG)"""
ELB = (1.550519768e-8)
"""L_B = 1 - d(TDB)/d(TCB), and TDB (s) at TAI 1977/1/1.0"""
TDB0 = (-6.55e-5)
"""L_B = 1 - d(TDB)/d(TCB), and TDB (s) at TAI 1977/1/1.0"""
SRS = 1.97412574336e-8
"""Schwarzschild radius of the Sun (au) = 2 * 1.32712440041e20 / (2.99792458e8)^2 / 1.49597870700e11"""
WGS84 = 1
"""Reference ellipsoids"""
GRS80 = 2
"""Reference ellipsoids"""
WGS72 = 3
"""Reference ellipsoids"""


def cal2jd(iy, im, id):
    """
    Wrapper for ERFA function ``eraCal2jd``.

    Parameters
    ----------
    iy : int array
    im : int array
    id : int array

    Returns
    -------
    djm0 : double array
    djm : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a C a l 2 j d
    - - - - - - - - - -

    Gregorian Calendar to Julian Date.

    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 ERFA
       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).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    iy_in = numpy.array(iy, dtype=numpy.intc, order="C", copy=False, subok=True)
    im_in = numpy.array(im, dtype=numpy.intc, order="C", copy=False, subok=True)
    id_in = numpy.array(id, dtype=numpy.intc, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if iy_in.shape == tuple():
            iy_in = iy_in.reshape((1,) + iy_in.shape)
        else:
            make_outputs_scalar = False
        if im_in.shape == tuple():
            im_in = im_in.reshape((1,) + im_in.shape)
        else:
            make_outputs_scalar = False
        if id_in.shape == tuple():
            id_in = id_in.reshape((1,) + id_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), iy_in, im_in, id_in)
    djm0_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    djm_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [iy_in, im_in, id_in, djm0_out, djm_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._cal2jd(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'cal2jd')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(djm0_out.shape) > 0 and djm0_out.shape[0] == 1
        djm0_out = djm0_out.reshape(djm0_out.shape[1:])
        assert len(djm_out.shape) > 0 and djm_out.shape[0] == 1
        djm_out = djm_out.reshape(djm_out.shape[1:])

    return djm0_out, djm_out
STATUS_CODES['cal2jd'] = {0: 'OK', -2: 'bad month  (JD not computed)', -1: 'bad year   (Note 3: JD not computed)', -3: 'bad day    (JD computed)'}



def epb(dj1, dj2):
    """
    Wrapper for ERFA function ``eraEpb``.

    Parameters
    ----------
    dj1 : double array
    dj2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - -
     e r a E p b
    - - - - - - -

    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 ERFA
       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 2451545.0
       (J2000.0).

    Reference:

       Lieske, J.H., 1979. Astron.Astrophys., 73, 282.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    dj1_in = numpy.array(dj1, dtype=numpy.double, order="C", copy=False, subok=True)
    dj2_in = numpy.array(dj2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if dj1_in.shape == tuple():
            dj1_in = dj1_in.reshape((1,) + dj1_in.shape)
        else:
            make_outputs_scalar = False
        if dj2_in.shape == tuple():
            dj2_in = dj2_in.reshape((1,) + dj2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), dj1_in, dj2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [dj1_in, dj2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._epb(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def epb2jd(epb):
    """
    Wrapper for ERFA function ``eraEpb2jd``.

    Parameters
    ----------
    epb : double array

    Returns
    -------
    djm0 : double array
    djm : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a E p b 2 j d
    - - - - - - - - - -

    Besselian Epoch to Julian Date.

    Given:
       epb      double    Besselian Epoch (e.g. 1957.3)

    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 ERFA
       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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    epb_in = numpy.array(epb, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if epb_in.shape == tuple():
            epb_in = epb_in.reshape((1,) + epb_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), epb_in)
    djm0_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    djm_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [epb_in, djm0_out, djm_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._epb2jd(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(djm0_out.shape) > 0 and djm0_out.shape[0] == 1
        djm0_out = djm0_out.reshape(djm0_out.shape[1:])
        assert len(djm_out.shape) > 0 and djm_out.shape[0] == 1
        djm_out = djm_out.reshape(djm_out.shape[1:])

    return djm0_out, djm_out


def epj(dj1, dj2):
    """
    Wrapper for ERFA function ``eraEpj``.

    Parameters
    ----------
    dj1 : double array
    dj2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - -
     e r a E p j
    - - - - - - -

    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 ERFA
       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 2451545.0
       (J2000.0).

    Reference:

       Lieske, J.H., 1979, Astron.Astrophys. 73, 282.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    dj1_in = numpy.array(dj1, dtype=numpy.double, order="C", copy=False, subok=True)
    dj2_in = numpy.array(dj2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if dj1_in.shape == tuple():
            dj1_in = dj1_in.reshape((1,) + dj1_in.shape)
        else:
            make_outputs_scalar = False
        if dj2_in.shape == tuple():
            dj2_in = dj2_in.reshape((1,) + dj2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), dj1_in, dj2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [dj1_in, dj2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._epj(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def epj2jd(epj):
    """
    Wrapper for ERFA function ``eraEpj2jd``.

    Parameters
    ----------
    epj : double array

    Returns
    -------
    djm0 : double array
    djm : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a E p j 2 j d
    - - - - - - - - - -

    Julian Epoch to Julian Date.

    Given:
       epj      double    Julian Epoch (e.g. 1996.8)

    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 ERFA
       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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    epj_in = numpy.array(epj, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if epj_in.shape == tuple():
            epj_in = epj_in.reshape((1,) + epj_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), epj_in)
    djm0_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    djm_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [epj_in, djm0_out, djm_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._epj2jd(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(djm0_out.shape) > 0 and djm0_out.shape[0] == 1
        djm0_out = djm0_out.reshape(djm0_out.shape[1:])
        assert len(djm_out.shape) > 0 and djm_out.shape[0] == 1
        djm_out = djm_out.reshape(djm_out.shape[1:])

    return djm0_out, djm_out


def jd2cal(dj1, dj2):
    """
    Wrapper for ERFA function ``eraJd2cal``.

    Parameters
    ----------
    dj1 : double array
    dj2 : double array

    Returns
    -------
    iy : int array
    im : int array
    id : int array
    fd : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a J d 2 c a l
    - - - - - - - - - -

    Julian Date to Gregorian year, month, day, and fraction of a day.

    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 1e9.

    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).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    dj1_in = numpy.array(dj1, dtype=numpy.double, order="C", copy=False, subok=True)
    dj2_in = numpy.array(dj2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if dj1_in.shape == tuple():
            dj1_in = dj1_in.reshape((1,) + dj1_in.shape)
        else:
            make_outputs_scalar = False
        if dj2_in.shape == tuple():
            dj2_in = dj2_in.reshape((1,) + dj2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), dj1_in, dj2_in)
    iy_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)
    im_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)
    id_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)
    fd_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [dj1_in, dj2_in, iy_out, im_out, id_out, fd_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*5
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._jd2cal(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'jd2cal')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(iy_out.shape) > 0 and iy_out.shape[0] == 1
        iy_out = iy_out.reshape(iy_out.shape[1:])
        assert len(im_out.shape) > 0 and im_out.shape[0] == 1
        im_out = im_out.reshape(im_out.shape[1:])
        assert len(id_out.shape) > 0 and id_out.shape[0] == 1
        id_out = id_out.reshape(id_out.shape[1:])
        assert len(fd_out.shape) > 0 and fd_out.shape[0] == 1
        fd_out = fd_out.reshape(fd_out.shape[1:])

    return iy_out, im_out, id_out, fd_out
STATUS_CODES['jd2cal'] = {0: 'OK', -1: 'unacceptable date (Note 3)'}



def jdcalf(ndp, dj1, dj2):
    """
    Wrapper for ERFA function ``eraJdcalf``.

    Parameters
    ----------
    ndp : int array
    dj1 : double array
    dj2 : double array

    Returns
    -------
    iymdf : int array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a J d c a l f
    - - - - - - - - - -

    Julian Date to Gregorian Calendar, expressed in a form convenient
    for formatting messages:  rounded to a specified precision.

    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 eraJd2cal.

    4) NDP should be 4 or less if internal overflows are to be
       avoided on machines which use 16-bit integers.

    Called:
       eraJd2cal    JD to Gregorian calendar

    Reference:

       Explanatory Supplement to the Astronomical Almanac,
       P. Kenneth Seidelmann (ed), University Science Books (1992),
       Section 12.92 (p604).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ndp_in = numpy.array(ndp, dtype=numpy.intc, order="C", copy=False, subok=True)
    dj1_in = numpy.array(dj1, dtype=numpy.double, order="C", copy=False, subok=True)
    dj2_in = numpy.array(dj2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ndp_in.shape == tuple():
            ndp_in = ndp_in.reshape((1,) + ndp_in.shape)
        else:
            make_outputs_scalar = False
        if dj1_in.shape == tuple():
            dj1_in = dj1_in.reshape((1,) + dj1_in.shape)
        else:
            make_outputs_scalar = False
        if dj2_in.shape == tuple():
            dj2_in = dj2_in.reshape((1,) + dj2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ndp_in, dj1_in, dj2_in)
    iymdf_out = numpy.empty(broadcast.shape + (4,), dtype=numpy.intc)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ndp_in, dj1_in, dj2_in, iymdf_out[...,0], c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._jdcalf(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'jdcalf')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(iymdf_out.shape) > 0 and iymdf_out.shape[0] == 1
        iymdf_out = iymdf_out.reshape(iymdf_out.shape[1:])

    return iymdf_out
STATUS_CODES['jdcalf'] = {0: 'OK', 1: 'NDP not 0-9 (interpreted as 0)', -1: 'date out of range'}



def ab(pnat, v, s, bm1):
    """
    Wrapper for ERFA function ``eraAb``.

    Parameters
    ----------
    pnat : double array
    v : double array
    s : double array
    bm1 : double array

    Returns
    -------
    ppr : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - -
     e r a A b
    - - - - - -

    Apply aberration to transform natural direction into proper
    direction.

    Given:
      pnat    double[3]   natural direction to the source (unit vector)
      v       double[3]   observer barycentric velocity in units of c
      s       double      distance between the Sun and the observer (au)
      bm1     double      sqrt(1-|v|^2): reciprocal of Lorenz factor

    Returned:
      ppr     double[3]   proper direction to source (unit vector)

    Notes:

    1) The algorithm is based on Expr. (7.40) in the Explanatory
       Supplement (Urban & Seidelmann 2013), but with the following
       changes:

       o  Rigorous rather than approximate normalization is applied.

       o  The gravitational potential term from Expr. (7) in
          Klioner (2003) is added, taking into account only the Sun's
          contribution.  This has a maximum effect of about
          0.4 microarcsecond.

    2) In almost all cases, the maximum accuracy will be limited by the
       supplied velocity.  For example, if the ERFA eraEpv00 function is
       used, errors of up to 5 microarcseconds could occur.

    References:

       Urban, S. & Seidelmann, P. K. (eds), Explanatory Supplement to
       the Astronomical Almanac, 3rd ed., University Science Books
       (2013).

       Klioner, Sergei A., "A practical relativistic model for micro-
       arcsecond astrometry in space", Astr. J. 125, 1580-1597 (2003).

    Called:
       eraPdp       scalar product of two p-vectors

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    pnat_in = numpy.array(pnat, dtype=numpy.double, order="C", copy=False, subok=True)
    v_in = numpy.array(v, dtype=numpy.double, order="C", copy=False, subok=True)
    s_in = numpy.array(s, dtype=numpy.double, order="C", copy=False, subok=True)
    bm1_in = numpy.array(bm1, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(pnat_in, (3,), "pnat")
    check_trailing_shape(v_in, (3,), "v")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if pnat_in[...,0].shape == tuple():
            pnat_in = pnat_in.reshape((1,) + pnat_in.shape)
        else:
            make_outputs_scalar = False
        if v_in[...,0].shape == tuple():
            v_in = v_in.reshape((1,) + v_in.shape)
        else:
            make_outputs_scalar = False
        if s_in.shape == tuple():
            s_in = s_in.reshape((1,) + s_in.shape)
        else:
            make_outputs_scalar = False
        if bm1_in.shape == tuple():
            bm1_in = bm1_in.reshape((1,) + bm1_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), pnat_in[...,0], v_in[...,0], s_in, bm1_in)
    ppr_out = numpy.empty(broadcast.shape + (3,), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [pnat_in[...,0], v_in[...,0], s_in, bm1_in, ppr_out[...,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ab(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(ppr_out.shape) > 0 and ppr_out.shape[0] == 1
        ppr_out = ppr_out.reshape(ppr_out.shape[1:])

    return ppr_out


def apcg(date1, date2, ebpv, ehp):
    """
    Wrapper for ERFA function ``eraApcg``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    ebpv : double array
    ehp : double array

    Returns
    -------
    astrom : eraASTROM array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a A p c g
    - - - - - - - -

    For a geocentric observer, prepare star-independent astrometry
    parameters for transformations between ICRS and GCRS coordinates.
    The Earth ephemeris is supplied by the caller.

    The parameters produced by this function are required in the
    parallax, light deflection and aberration parts of the astrometric
    transformation chain.

    Given:
       date1  double       TDB as a 2-part...
       date2  double       ...Julian Date (Note 1)
       ebpv   double[2][3] Earth barycentric pos/vel (au, au/day)
       ehp    double[3]    Earth heliocentric position (au)

    Returned:
       astrom eraASTROM*   star-independent astrometry parameters:
        pmt    double       PM time interval (SSB, Julian years)
        eb     double[3]    SSB to observer (vector, au)
        eh     double[3]    Sun to observer (unit vector)
        em     double       distance from Sun to observer (au)
        v      double[3]    barycentric observer velocity (vector, c)
        bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
        bpn    double[3][3] bias-precession-nutation matrix
        along  double       unchanged
        xpl    double       unchanged
        ypl    double       unchanged
        sphi   double       unchanged
        cphi   double       unchanged
        diurab double       unchanged
        eral   double       unchanged
        refa   double       unchanged
        refb   double       unchanged

    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.  For most
       applications of this function the choice will not be at all
       critical.

       TT can be used instead of TDB without any significant impact on
       accuracy.

    2) All the vectors are with respect to BCRS axes.

    3) This is one of several functions that inserts into the astrom
       structure star-independent parameters needed for the chain of
       astrometric transformations ICRS <-> GCRS <-> CIRS <-> observed.

       The various functions support different classes of observer and
       portions of the transformation chain:

            functions         observer        transformation

         eraApcg eraApcg13    geocentric      ICRS <-> GCRS
         eraApci eraApci13    terrestrial     ICRS <-> CIRS
         eraApco eraApco13    terrestrial     ICRS <-> observed
         eraApcs eraApcs13    space           ICRS <-> GCRS
         eraAper eraAper13    terrestrial     update Earth rotation
         eraApio eraApio13    terrestrial     CIRS <-> observed

       Those with names ending in "13" use contemporary ERFA models to
       compute the various ephemerides.  The others accept ephemerides
       supplied by the caller.

       The transformation from ICRS to GCRS covers space motion,
       parallax, light deflection, and aberration.  From GCRS to CIRS
       comprises frame bias and precession-nutation.  From CIRS to
       observed takes account of Earth rotation, polar motion, diurnal
       aberration and parallax (unless subsumed into the ICRS <-> GCRS
       transformation), and atmospheric refraction.

    4) The context structure astrom produced by this function is used by
       eraAtciq* and eraAticq*.

    Called:
       eraApcs      astrometry parameters, ICRS-GCRS, space observer

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    ebpv_in = numpy.array(ebpv, dtype=numpy.double, order="C", copy=False, subok=True)
    ehp_in = numpy.array(ehp, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(ebpv_in, (2, 3), "ebpv")
    check_trailing_shape(ehp_in, (3,), "ehp")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if ebpv_in[...,0,0].shape == tuple():
            ebpv_in = ebpv_in.reshape((1,) + ebpv_in.shape)
        else:
            make_outputs_scalar = False
        if ehp_in[...,0].shape == tuple():
            ehp_in = ehp_in.reshape((1,) + ehp_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, ebpv_in[...,0,0], ehp_in[...,0])
    astrom_out = numpy.empty(broadcast.shape + (), dtype=dt_eraASTROM)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, ebpv_in[...,0,0], ehp_in[...,0], astrom_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._apcg(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(astrom_out.shape) > 0 and astrom_out.shape[0] == 1
        astrom_out = astrom_out.reshape(astrom_out.shape[1:])

    return astrom_out


def apcg13(date1, date2):
    """
    Wrapper for ERFA function ``eraApcg13``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    astrom : eraASTROM array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a A p c g 1 3
    - - - - - - - - - -

    For a geocentric observer, prepare star-independent astrometry
    parameters for transformations between ICRS and GCRS coordinates.
    The caller supplies the date, and ERFA models are used to predict
    the Earth ephemeris.

    The parameters produced by this function are required in the
    parallax, light deflection and aberration parts of the astrometric
    transformation chain.

    Given:
       date1  double     TDB as a 2-part...
       date2  double     ...Julian Date (Note 1)

    Returned:
       astrom eraASTROM* star-independent astrometry parameters:
        pmt    double       PM time interval (SSB, Julian years)
        eb     double[3]    SSB to observer (vector, au)
        eh     double[3]    Sun to observer (unit vector)
        em     double       distance from Sun to observer (au)
        v      double[3]    barycentric observer velocity (vector, c)
        bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
        bpn    double[3][3] bias-precession-nutation matrix
        along  double       unchanged
        xpl    double       unchanged
        ypl    double       unchanged
        sphi   double       unchanged
        cphi   double       unchanged
        diurab double       unchanged
        eral   double       unchanged
        refa   double       unchanged
        refb   double       unchanged

    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.  For most
       applications of this function the choice will not be at all
       critical.

       TT can be used instead of TDB without any significant impact on
       accuracy.

    2) All the vectors are with respect to BCRS axes.

    3) In cases where the caller wishes to supply his own Earth
       ephemeris, the function eraApcg can be used instead of the present
       function.

    4) This is one of several functions that inserts into the astrom
       structure star-independent parameters needed for the chain of
       astrometric transformations ICRS <-> GCRS <-> CIRS <-> observed.

       The various functions support different classes of observer and
       portions of the transformation chain:

            functions         observer        transformation

         eraApcg eraApcg13    geocentric      ICRS <-> GCRS
         eraApci eraApci13    terrestrial     ICRS <-> CIRS
         eraApco eraApco13    terrestrial     ICRS <-> observed
         eraApcs eraApcs13    space           ICRS <-> GCRS
         eraAper eraAper13    terrestrial     update Earth rotation
         eraApio eraApio13    terrestrial     CIRS <-> observed

       Those with names ending in "13" use contemporary ERFA models to
       compute the various ephemerides.  The others accept ephemerides
       supplied by the caller.

       The transformation from ICRS to GCRS covers space motion,
       parallax, light deflection, and aberration.  From GCRS to CIRS
       comprises frame bias and precession-nutation.  From CIRS to
       observed takes account of Earth rotation, polar motion, diurnal
       aberration and parallax (unless subsumed into the ICRS <-> GCRS
       transformation), and atmospheric refraction.

    5) The context structure astrom produced by this function is used by
       eraAtciq* and eraAticq*.

    Called:
       eraEpv00     Earth position and velocity
       eraApcg      astrometry parameters, ICRS-GCRS, geocenter

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    astrom_out = numpy.empty(broadcast.shape + (), dtype=dt_eraASTROM)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, astrom_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._apcg13(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(astrom_out.shape) > 0 and astrom_out.shape[0] == 1
        astrom_out = astrom_out.reshape(astrom_out.shape[1:])

    return astrom_out


def apci(date1, date2, ebpv, ehp, x, y, s):
    """
    Wrapper for ERFA function ``eraApci``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    ebpv : double array
    ehp : double array
    x : double array
    y : double array
    s : double array

    Returns
    -------
    astrom : eraASTROM array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a A p c i
    - - - - - - - -

    For a terrestrial observer, prepare star-independent astrometry
    parameters for transformations between ICRS and geocentric CIRS
    coordinates.  The Earth ephemeris and CIP/CIO are supplied by the
    caller.

    The parameters produced by this function are required in the
    parallax, light deflection, aberration, and bias-precession-nutation
    parts of the astrometric transformation chain.

    Given:
       date1  double       TDB as a 2-part...
       date2  double       ...Julian Date (Note 1)
       ebpv   double[2][3] Earth barycentric position/velocity (au, au/day)
       ehp    double[3]    Earth heliocentric position (au)
       x,y    double       CIP X,Y (components of unit vector)
       s      double       the CIO locator s (radians)

    Returned:
       astrom eraASTROM*   star-independent astrometry parameters:
        pmt    double       PM time interval (SSB, Julian years)
        eb     double[3]    SSB to observer (vector, au)
        eh     double[3]    Sun to observer (unit vector)
        em     double       distance from Sun to observer (au)
        v      double[3]    barycentric observer velocity (vector, c)
        bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
        bpn    double[3][3] bias-precession-nutation matrix
        along  double       unchanged
        xpl    double       unchanged
        ypl    double       unchanged
        sphi   double       unchanged
        cphi   double       unchanged
        diurab double       unchanged
        eral   double       unchanged
        refa   double       unchanged
        refb   double       unchanged

    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.  For most
       applications of this function the choice will not be at all
       critical.

       TT can be used instead of TDB without any significant impact on
       accuracy.

    2) All the vectors are with respect to BCRS axes.

    3) In cases where the caller does not wish to provide the Earth
       ephemeris and CIP/CIO, the function eraApci13 can be used instead
       of the present function.  This computes the required quantities
       using other ERFA functions.

    4) This is one of several functions that inserts into the astrom
       structure star-independent parameters needed for the chain of
       astrometric transformations ICRS <-> GCRS <-> CIRS <-> observed.

       The various functions support different classes of observer and
       portions of the transformation chain:

            functions         observer        transformation

         eraApcg eraApcg13    geocentric      ICRS <-> GCRS
         eraApci eraApci13    terrestrial     ICRS <-> CIRS
         eraApco eraApco13    terrestrial     ICRS <-> observed
         eraApcs eraApcs13    space           ICRS <-> GCRS
         eraAper eraAper13    terrestrial     update Earth rotation
         eraApio eraApio13    terrestrial     CIRS <-> observed

       Those with names ending in "13" use contemporary ERFA models to
       compute the various ephemerides.  The others accept ephemerides
       supplied by the caller.

       The transformation from ICRS to GCRS covers space motion,
       parallax, light deflection, and aberration.  From GCRS to CIRS
       comprises frame bias and precession-nutation.  From CIRS to
       observed takes account of Earth rotation, polar motion, diurnal
       aberration and parallax (unless subsumed into the ICRS <-> GCRS
       transformation), and atmospheric refraction.

    5) The context structure astrom produced by this function is used by
       eraAtciq* and eraAticq*.

    Called:
       eraApcg      astrometry parameters, ICRS-GCRS, geocenter
       eraC2ixys    celestial-to-intermediate matrix, given X,Y and s

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    ebpv_in = numpy.array(ebpv, dtype=numpy.double, order="C", copy=False, subok=True)
    ehp_in = numpy.array(ehp, dtype=numpy.double, order="C", copy=False, subok=True)
    x_in = numpy.array(x, dtype=numpy.double, order="C", copy=False, subok=True)
    y_in = numpy.array(y, dtype=numpy.double, order="C", copy=False, subok=True)
    s_in = numpy.array(s, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(ebpv_in, (2, 3), "ebpv")
    check_trailing_shape(ehp_in, (3,), "ehp")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if ebpv_in[...,0,0].shape == tuple():
            ebpv_in = ebpv_in.reshape((1,) + ebpv_in.shape)
        else:
            make_outputs_scalar = False
        if ehp_in[...,0].shape == tuple():
            ehp_in = ehp_in.reshape((1,) + ehp_in.shape)
        else:
            make_outputs_scalar = False
        if x_in.shape == tuple():
            x_in = x_in.reshape((1,) + x_in.shape)
        else:
            make_outputs_scalar = False
        if y_in.shape == tuple():
            y_in = y_in.reshape((1,) + y_in.shape)
        else:
            make_outputs_scalar = False
        if s_in.shape == tuple():
            s_in = s_in.reshape((1,) + s_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, ebpv_in[...,0,0], ehp_in[...,0], x_in, y_in, s_in)
    astrom_out = numpy.empty(broadcast.shape + (), dtype=dt_eraASTROM)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, ebpv_in[...,0,0], ehp_in[...,0], x_in, y_in, s_in, astrom_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*7 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._apci(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(astrom_out.shape) > 0 and astrom_out.shape[0] == 1
        astrom_out = astrom_out.reshape(astrom_out.shape[1:])

    return astrom_out


def apci13(date1, date2):
    """
    Wrapper for ERFA function ``eraApci13``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    astrom : eraASTROM array
    eo : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a A p c i 1 3
    - - - - - - - - - -

    For a terrestrial observer, prepare star-independent astrometry
    parameters for transformations between ICRS and geocentric CIRS
    coordinates.  The caller supplies the date, and ERFA models are used
    to predict the Earth ephemeris and CIP/CIO.

    The parameters produced by this function are required in the
    parallax, light deflection, aberration, and bias-precession-nutation
    parts of the astrometric transformation chain.

    Given:
       date1  double      TDB as a 2-part...
       date2  double      ...Julian Date (Note 1)

    Returned:
       astrom eraASTROM*  star-independent astrometry parameters:
        pmt    double       PM time interval (SSB, Julian years)
        eb     double[3]    SSB to observer (vector, au)
        eh     double[3]    Sun to observer (unit vector)
        em     double       distance from Sun to observer (au)
        v      double[3]    barycentric observer velocity (vector, c)
        bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
        bpn    double[3][3] bias-precession-nutation matrix
        along  double       unchanged
        xpl    double       unchanged
        ypl    double       unchanged
        sphi   double       unchanged
        cphi   double       unchanged
        diurab double       unchanged
        eral   double       unchanged
        refa   double       unchanged
        refb   double       unchanged
       eo     double*     equation of the origins (ERA-GST)

    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.  For most
       applications of this function the choice will not be at all
       critical.

       TT can be used instead of TDB without any significant impact on
       accuracy.

    2) All the vectors are with respect to BCRS axes.

    3) In cases where the caller wishes to supply his own Earth
       ephemeris and CIP/CIO, the function eraApci can be used instead
       of the present function.

    4) This is one of several functions that inserts into the astrom
       structure star-independent parameters needed for the chain of
       astrometric transformations ICRS <-> GCRS <-> CIRS <-> observed.

       The various functions support different classes of observer and
       portions of the transformation chain:

            functions         observer        transformation

         eraApcg eraApcg13    geocentric      ICRS <-> GCRS
         eraApci eraApci13    terrestrial     ICRS <-> CIRS
         eraApco eraApco13    terrestrial     ICRS <-> observed
         eraApcs eraApcs13    space           ICRS <-> GCRS
         eraAper eraAper13    terrestrial     update Earth rotation
         eraApio eraApio13    terrestrial     CIRS <-> observed

       Those with names ending in "13" use contemporary ERFA models to
       compute the various ephemerides.  The others accept ephemerides
       supplied by the caller.

       The transformation from ICRS to GCRS covers space motion,
       parallax, light deflection, and aberration.  From GCRS to CIRS
       comprises frame bias and precession-nutation.  From CIRS to
       observed takes account of Earth rotation, polar motion, diurnal
       aberration and parallax (unless subsumed into the ICRS <-> GCRS
       transformation), and atmospheric refraction.

    5) The context structure astrom produced by this function is used by
       eraAtciq* and eraAticq*.

    Called:
       eraEpv00     Earth position and velocity
       eraPnm06a    classical NPB matrix, IAU 2006/2000A
       eraBpn2xy    extract CIP X,Y coordinates from NPB matrix
       eraS06       the CIO locator s, given X,Y, IAU 2006
       eraApci      astrometry parameters, ICRS-CIRS
       eraEors      equation of the origins, given NPB matrix and s

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    astrom_out = numpy.empty(broadcast.shape + (), dtype=dt_eraASTROM)
    eo_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, astrom_out, eo_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._apci13(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(astrom_out.shape) > 0 and astrom_out.shape[0] == 1
        astrom_out = astrom_out.reshape(astrom_out.shape[1:])
        assert len(eo_out.shape) > 0 and eo_out.shape[0] == 1
        eo_out = eo_out.reshape(eo_out.shape[1:])

    return astrom_out, eo_out


def apco(date1, date2, ebpv, ehp, x, y, s, theta, elong, phi, hm, xp, yp, sp, refa, refb):
    """
    Wrapper for ERFA function ``eraApco``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    ebpv : double array
    ehp : double array
    x : double array
    y : double array
    s : double array
    theta : double array
    elong : double array
    phi : double array
    hm : double array
    xp : double array
    yp : double array
    sp : double array
    refa : double array
    refb : double array

    Returns
    -------
    refa : double array
    refb : double array
    astrom : eraASTROM array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a A p c o
    - - - - - - - -

    For a terrestrial observer, prepare star-independent astrometry
    parameters for transformations between ICRS and observed
    coordinates.  The caller supplies the Earth ephemeris, the Earth
    rotation information and the refraction constants as well as the
    site coordinates.

    Given:
       date1  double       TDB as a 2-part...
       date2  double       ...Julian Date (Note 1)
       ebpv   double[2][3] Earth barycentric PV (au, au/day, Note 2)
       ehp    double[3]    Earth heliocentric P (au, Note 2)
       x,y    double       CIP X,Y (components of unit vector)
       s      double       the CIO locator s (radians)
       theta  double       Earth rotation angle (radians)
       elong  double       longitude (radians, east +ve, Note 3)
       phi    double       latitude (geodetic, radians, Note 3)
       hm     double       height above ellipsoid (m, geodetic, Note 3)
       xp,yp  double       polar motion coordinates (radians, Note 4)
       sp     double       the TIO locator s' (radians, Note 4)
       refa   double       refraction constant A (radians, Note 5)
       refb   double       refraction constant B (radians, Note 5)

    Returned:
       astrom eraASTROM*   star-independent astrometry parameters:
        pmt    double       PM time interval (SSB, Julian years)
        eb     double[3]    SSB to observer (vector, au)
        eh     double[3]    Sun to observer (unit vector)
        em     double       distance from Sun to observer (au)
        v      double[3]    barycentric observer velocity (vector, c)
        bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
        bpn    double[3][3] bias-precession-nutation matrix
        along  double       longitude + s' (radians)
        xpl    double       polar motion xp wrt local meridian (radians)
        ypl    double       polar motion yp wrt local meridian (radians)
        sphi   double       sine of geodetic latitude
        cphi   double       cosine of geodetic latitude
        diurab double       magnitude of diurnal aberration vector
        eral   double       "local" Earth rotation angle (radians)
        refa   double       refraction constant A (radians)
        refb   double       refraction constant B (radians)

    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.  For most
       applications of this function the choice will not be at all
       critical.

       TT can be used instead of TDB without any significant impact on
       accuracy.

    2) The vectors eb, eh, and all the astrom vectors, are with respect
       to BCRS axes.

    3) The geographical coordinates are with respect to the ERFA_WGS84
       reference ellipsoid.  TAKE CARE WITH THE LONGITUDE SIGN
       CONVENTION:  the longitude required by the present function is
       right-handed, i.e. east-positive, in accordance with geographical
       convention.

    4) xp and yp are the coordinates (in radians) of the Celestial
       Intermediate Pole with respect to the International Terrestrial
       Reference System (see IERS Conventions), measured along the
       meridians 0 and 90 deg west respectively.  sp is the TIO locator
       s', in radians, which positions the Terrestrial Intermediate
       Origin on the equator.  For many applications, xp, yp and
       (especially) sp can be set to zero.

       Internally, the polar motion is stored in a form rotated onto the
       local meridian.

    5) The refraction constants refa and refb are for use in a
       dZ = A*tan(Z)+B*tan^3(Z) model, where Z is the observed
       (i.e. refracted) zenith distance and dZ is the amount of
       refraction.

    6) It is advisable to take great care with units, as even unlikely
       values of the input parameters are accepted and processed in
       accordance with the models used.

    7) In cases where the caller does not wish to provide the Earth
       Ephemeris, the Earth rotation information and refraction
       constants, the function eraApco13 can be used instead of the
       present function.  This starts from UTC and weather readings etc.
       and computes suitable values using other ERFA functions.

    8) This is one of several functions that inserts into the astrom
       structure star-independent parameters needed for the chain of
       astrometric transformations ICRS <-> GCRS <-> CIRS <-> observed.

       The various functions support different classes of observer and
       portions of the transformation chain:

            functions         observer        transformation

         eraApcg eraApcg13    geocentric      ICRS <-> GCRS
         eraApci eraApci13    terrestrial     ICRS <-> CIRS
         eraApco eraApco13    terrestrial     ICRS <-> observed
         eraApcs eraApcs13    space           ICRS <-> GCRS
         eraAper eraAper13    terrestrial     update Earth rotation
         eraApio eraApio13    terrestrial     CIRS <-> observed

       Those with names ending in "13" use contemporary ERFA models to
       compute the various ephemerides.  The others accept ephemerides
       supplied by the caller.

       The transformation from ICRS to GCRS covers space motion,
       parallax, light deflection, and aberration.  From GCRS to CIRS
       comprises frame bias and precession-nutation.  From CIRS to
       observed takes account of Earth rotation, polar motion, diurnal
       aberration and parallax (unless subsumed into the ICRS <-> GCRS
       transformation), and atmospheric refraction.

    9) The context structure astrom produced by this function is used by
       eraAtioq, eraAtoiq, eraAtciq* and eraAticq*.

    Called:
       eraAper      astrometry parameters: update ERA
       eraC2ixys    celestial-to-intermediate matrix, given X,Y and s
       eraPvtob     position/velocity of terrestrial station
       eraTrxpv     product of transpose of r-matrix and pv-vector
       eraApcs      astrometry parameters, ICRS-GCRS, space observer
       eraCr        copy r-matrix

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    ebpv_in = numpy.array(ebpv, dtype=numpy.double, order="C", copy=False, subok=True)
    ehp_in = numpy.array(ehp, dtype=numpy.double, order="C", copy=False, subok=True)
    x_in = numpy.array(x, dtype=numpy.double, order="C", copy=False, subok=True)
    y_in = numpy.array(y, dtype=numpy.double, order="C", copy=False, subok=True)
    s_in = numpy.array(s, dtype=numpy.double, order="C", copy=False, subok=True)
    theta_in = numpy.array(theta, dtype=numpy.double, order="C", copy=False, subok=True)
    elong_in = numpy.array(elong, dtype=numpy.double, order="C", copy=False, subok=True)
    phi_in = numpy.array(phi, dtype=numpy.double, order="C", copy=False, subok=True)
    hm_in = numpy.array(hm, dtype=numpy.double, order="C", copy=False, subok=True)
    xp_in = numpy.array(xp, dtype=numpy.double, order="C", copy=False, subok=True)
    yp_in = numpy.array(yp, dtype=numpy.double, order="C", copy=False, subok=True)
    sp_in = numpy.array(sp, dtype=numpy.double, order="C", copy=False, subok=True)
    refa_in = numpy.array(refa, dtype=numpy.double, order="C", copy=False, subok=True)
    refb_in = numpy.array(refb, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(ebpv_in, (2, 3), "ebpv")
    check_trailing_shape(ehp_in, (3,), "ehp")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if ebpv_in[...,0,0].shape == tuple():
            ebpv_in = ebpv_in.reshape((1,) + ebpv_in.shape)
        else:
            make_outputs_scalar = False
        if ehp_in[...,0].shape == tuple():
            ehp_in = ehp_in.reshape((1,) + ehp_in.shape)
        else:
            make_outputs_scalar = False
        if x_in.shape == tuple():
            x_in = x_in.reshape((1,) + x_in.shape)
        else:
            make_outputs_scalar = False
        if y_in.shape == tuple():
            y_in = y_in.reshape((1,) + y_in.shape)
        else:
            make_outputs_scalar = False
        if s_in.shape == tuple():
            s_in = s_in.reshape((1,) + s_in.shape)
        else:
            make_outputs_scalar = False
        if theta_in.shape == tuple():
            theta_in = theta_in.reshape((1,) + theta_in.shape)
        else:
            make_outputs_scalar = False
        if elong_in.shape == tuple():
            elong_in = elong_in.reshape((1,) + elong_in.shape)
        else:
            make_outputs_scalar = False
        if phi_in.shape == tuple():
            phi_in = phi_in.reshape((1,) + phi_in.shape)
        else:
            make_outputs_scalar = False
        if hm_in.shape == tuple():
            hm_in = hm_in.reshape((1,) + hm_in.shape)
        else:
            make_outputs_scalar = False
        if xp_in.shape == tuple():
            xp_in = xp_in.reshape((1,) + xp_in.shape)
        else:
            make_outputs_scalar = False
        if yp_in.shape == tuple():
            yp_in = yp_in.reshape((1,) + yp_in.shape)
        else:
            make_outputs_scalar = False
        if sp_in.shape == tuple():
            sp_in = sp_in.reshape((1,) + sp_in.shape)
        else:
            make_outputs_scalar = False
        if refa_in.shape == tuple():
            refa_in = refa_in.reshape((1,) + refa_in.shape)
        else:
            make_outputs_scalar = False
        if refb_in.shape == tuple():
            refb_in = refb_in.reshape((1,) + refb_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, ebpv_in[...,0,0], ehp_in[...,0], x_in, y_in, s_in, theta_in, elong_in, phi_in, hm_in, xp_in, yp_in, sp_in, refa_in, refb_in)
    refa_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    refb_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    astrom_out = numpy.empty(broadcast.shape + (), dtype=dt_eraASTROM)
    numpy.copyto(refa_out, refa_in)
    numpy.copyto(refb_out, refb_in)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, ebpv_in[...,0,0], ehp_in[...,0], x_in, y_in, s_in, theta_in, elong_in, phi_in, hm_in, xp_in, yp_in, sp_in, refa_out, refb_out, astrom_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*14 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._apco(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(refa_out.shape) > 0 and refa_out.shape[0] == 1
        refa_out = refa_out.reshape(refa_out.shape[1:])
        assert len(refb_out.shape) > 0 and refb_out.shape[0] == 1
        refb_out = refb_out.reshape(refb_out.shape[1:])
        assert len(astrom_out.shape) > 0 and astrom_out.shape[0] == 1
        astrom_out = astrom_out.reshape(astrom_out.shape[1:])

    return refa_out, refb_out, astrom_out


def apco13(utc1, utc2, dut1, elong, phi, hm, xp, yp, phpa, tc, rh, wl):
    """
    Wrapper for ERFA function ``eraApco13``.

    Parameters
    ----------
    utc1 : double array
    utc2 : double array
    dut1 : double array
    elong : double array
    phi : double array
    hm : double array
    xp : double array
    yp : double array
    phpa : double array
    tc : double array
    rh : double array
    wl : double array

    Returns
    -------
    astrom : eraASTROM array
    eo : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a A p c o 1 3
    - - - - - - - - - -

    For a terrestrial observer, prepare star-independent astrometry
    parameters for transformations between ICRS and observed
    coordinates.  The caller supplies UTC, site coordinates, ambient air
    conditions and observing wavelength, and ERFA models are used to
    obtain the Earth ephemeris, CIP/CIO and refraction constants.

    The parameters produced by this function are required in the
    parallax, light deflection, aberration, and bias-precession-nutation
    parts of the ICRS/CIRS transformations.

    Given:
       utc1   double     UTC as a 2-part...
       utc2   double     ...quasi Julian Date (Notes 1,2)
       dut1   double     UT1-UTC (seconds, Note 3)
       elong  double     longitude (radians, east +ve, Note 4)
       phi    double     latitude (geodetic, radians, Note 4)
       hm     double     height above ellipsoid (m, geodetic, Notes 4,6)
       xp,yp  double     polar motion coordinates (radians, Note 5)
       phpa   double     pressure at the observer (hPa = mB, Note 6)
       tc     double     ambient temperature at the observer (deg C)
       rh     double     relative humidity at the observer (range 0-1)
       wl     double     wavelength (micrometers, Note 7)

    Returned:
       astrom eraASTROM* star-independent astrometry parameters:
        pmt    double       PM time interval (SSB, Julian years)
        eb     double[3]    SSB to observer (vector, au)
        eh     double[3]    Sun to observer (unit vector)
        em     double       distance from Sun to observer (au)
        v      double[3]    barycentric observer velocity (vector, c)
        bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
        bpn    double[3][3] bias-precession-nutation matrix
        along  double       longitude + s' (radians)
        xpl    double       polar motion xp wrt local meridian (radians)
        ypl    double       polar motion yp wrt local meridian (radians)
        sphi   double       sine of geodetic latitude
        cphi   double       cosine of geodetic latitude
        diurab double       magnitude of diurnal aberration vector
        eral   double       "local" Earth rotation angle (radians)
        refa   double       refraction constant A (radians)
        refb   double       refraction constant B (radians)
       eo     double*    equation of the origins (ERA-GST)

    Returned (function value):
              int        status: +1 = dubious year (Note 2)
                                  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.

        However, 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.

        Applications should use the function eraDtf2d to convert from
        calendar date and time of day into 2-part quasi Julian Date, as
        it implements the leap-second-ambiguity convention just
        described.

    2)  The warning status "dubious year" flags UTCs that predate the
        introduction of the time scale or that are too far in the
        future to be trusted.  See eraDat for further details.

    3)  UT1-UTC is tabulated in IERS bulletins.  It increases by exactly
        one second at the end of each positive UTC leap second,
        introduced in order to keep UT1-UTC within +/- 0.9s.  n.b. This
        practice is under review, and in the future UT1-UTC may grow
        essentially without limit.

    4)  The geographical coordinates are with respect to the ERFA_WGS84
        reference ellipsoid.  TAKE CARE WITH THE LONGITUDE SIGN:  the
        longitude required by the present function is east-positive
        (i.e. right-handed), in accordance with geographical convention.

    5)  The polar motion xp,yp can be obtained from IERS bulletins.  The
        values 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 0 and 90 deg west respectively.  For many
        applications, xp and yp can be set to zero.

        Internally, the polar motion is stored in a form rotated onto
        the local meridian.

    6)  If hm, the height above the ellipsoid of the observing station
        in meters, is not known but phpa, the pressure in hPa (=mB), is
        available, an adequate estimate of hm can be obtained from the
        expression

              hm = -29.3 * tsl * log ( phpa / 1013.25 );

        where tsl is the approximate sea-level air temperature in K
        (See Astrophysical Quantities, C.W.Allen, 3rd edition, section
        52).  Similarly, if the pressure phpa is not known, it can be
        estimated from the height of the observing station, hm, as
        follows:

              phpa = 1013.25 * exp ( -hm / ( 29.3 * tsl ) );

        Note, however, that the refraction is nearly proportional to
        the pressure and that an accurate phpa value is important for
        precise work.

    7)  The argument wl specifies the observing wavelength in
        micrometers.  The transition from optical to radio is assumed to
        occur at 100 micrometers (about 3000 GHz).

    8)  It is advisable to take great care with units, as even unlikely
        values of the input parameters are accepted and processed in
        accordance with the models used.

    9)  In cases where the caller wishes to supply his own Earth
        ephemeris, Earth rotation information and refraction constants,
        the function eraApco can be used instead of the present function.

    10) This is one of several functions that inserts into the astrom
        structure star-independent parameters needed for the chain of
        astrometric transformations ICRS <-> GCRS <-> CIRS <-> observed.

        The various functions support different classes of observer and
        portions of the transformation chain:

            functions         observer        transformation

         eraApcg eraApcg13    geocentric      ICRS <-> GCRS
         eraApci eraApci13    terrestrial     ICRS <-> CIRS
         eraApco eraApco13    terrestrial     ICRS <-> observed
         eraApcs eraApcs13    space           ICRS <-> GCRS
         eraAper eraAper13    terrestrial     update Earth rotation
         eraApio eraApio13    terrestrial     CIRS <-> observed

        Those with names ending in "13" use contemporary ERFA models to
        compute the various ephemerides.  The others accept ephemerides
        supplied by the caller.

        The transformation from ICRS to GCRS covers space motion,
        parallax, light deflection, and aberration.  From GCRS to CIRS
        comprises frame bias and precession-nutation.  From CIRS to
        observed takes account of Earth rotation, polar motion, diurnal
        aberration and parallax (unless subsumed into the ICRS <-> GCRS
        transformation), and atmospheric refraction.

    11) The context structure astrom produced by this function is used
        by eraAtioq, eraAtoiq, eraAtciq* and eraAticq*.

    Called:
       eraUtctai    UTC to TAI
       eraTaitt     TAI to TT
       eraUtcut1    UTC to UT1
       eraEpv00     Earth position and velocity
       eraPnm06a    classical NPB matrix, IAU 2006/2000A
       eraBpn2xy    extract CIP X,Y coordinates from NPB matrix
       eraS06       the CIO locator s, given X,Y, IAU 2006
       eraEra00     Earth rotation angle, IAU 2000
       eraSp00      the TIO locator s', IERS 2000
       eraRefco     refraction constants for given ambient conditions
       eraApco      astrometry parameters, ICRS-observed
       eraEors      equation of the origins, given NPB matrix and s

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    utc1_in = numpy.array(utc1, dtype=numpy.double, order="C", copy=False, subok=True)
    utc2_in = numpy.array(utc2, dtype=numpy.double, order="C", copy=False, subok=True)
    dut1_in = numpy.array(dut1, dtype=numpy.double, order="C", copy=False, subok=True)
    elong_in = numpy.array(elong, dtype=numpy.double, order="C", copy=False, subok=True)
    phi_in = numpy.array(phi, dtype=numpy.double, order="C", copy=False, subok=True)
    hm_in = numpy.array(hm, dtype=numpy.double, order="C", copy=False, subok=True)
    xp_in = numpy.array(xp, dtype=numpy.double, order="C", copy=False, subok=True)
    yp_in = numpy.array(yp, dtype=numpy.double, order="C", copy=False, subok=True)
    phpa_in = numpy.array(phpa, dtype=numpy.double, order="C", copy=False, subok=True)
    tc_in = numpy.array(tc, dtype=numpy.double, order="C", copy=False, subok=True)
    rh_in = numpy.array(rh, dtype=numpy.double, order="C", copy=False, subok=True)
    wl_in = numpy.array(wl, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if utc1_in.shape == tuple():
            utc1_in = utc1_in.reshape((1,) + utc1_in.shape)
        else:
            make_outputs_scalar = False
        if utc2_in.shape == tuple():
            utc2_in = utc2_in.reshape((1,) + utc2_in.shape)
        else:
            make_outputs_scalar = False
        if dut1_in.shape == tuple():
            dut1_in = dut1_in.reshape((1,) + dut1_in.shape)
        else:
            make_outputs_scalar = False
        if elong_in.shape == tuple():
            elong_in = elong_in.reshape((1,) + elong_in.shape)
        else:
            make_outputs_scalar = False
        if phi_in.shape == tuple():
            phi_in = phi_in.reshape((1,) + phi_in.shape)
        else:
            make_outputs_scalar = False
        if hm_in.shape == tuple():
            hm_in = hm_in.reshape((1,) + hm_in.shape)
        else:
            make_outputs_scalar = False
        if xp_in.shape == tuple():
            xp_in = xp_in.reshape((1,) + xp_in.shape)
        else:
            make_outputs_scalar = False
        if yp_in.shape == tuple():
            yp_in = yp_in.reshape((1,) + yp_in.shape)
        else:
            make_outputs_scalar = False
        if phpa_in.shape == tuple():
            phpa_in = phpa_in.reshape((1,) + phpa_in.shape)
        else:
            make_outputs_scalar = False
        if tc_in.shape == tuple():
            tc_in = tc_in.reshape((1,) + tc_in.shape)
        else:
            make_outputs_scalar = False
        if rh_in.shape == tuple():
            rh_in = rh_in.reshape((1,) + rh_in.shape)
        else:
            make_outputs_scalar = False
        if wl_in.shape == tuple():
            wl_in = wl_in.reshape((1,) + wl_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), utc1_in, utc2_in, dut1_in, elong_in, phi_in, hm_in, xp_in, yp_in, phpa_in, tc_in, rh_in, wl_in)
    astrom_out = numpy.empty(broadcast.shape + (), dtype=dt_eraASTROM)
    eo_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [utc1_in, utc2_in, dut1_in, elong_in, phi_in, hm_in, xp_in, yp_in, phpa_in, tc_in, rh_in, wl_in, astrom_out, eo_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*12 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._apco13(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'apco13')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(astrom_out.shape) > 0 and astrom_out.shape[0] == 1
        astrom_out = astrom_out.reshape(astrom_out.shape[1:])
        assert len(eo_out.shape) > 0 and eo_out.shape[0] == 1
        eo_out = eo_out.reshape(eo_out.shape[1:])

    return astrom_out, eo_out
STATUS_CODES['apco13'] = {0: 'OK', 1: 'dubious year (Note 2)', -1: 'unacceptable date'}



def apcs(date1, date2, pv, ebpv, ehp):
    """
    Wrapper for ERFA function ``eraApcs``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    pv : double array
    ebpv : double array
    ehp : double array

    Returns
    -------
    astrom : eraASTROM array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a A p c s
    - - - - - - - -

    For an observer whose geocentric position and velocity are known,
    prepare star-independent astrometry parameters for transformations
    between ICRS and GCRS.  The Earth ephemeris is supplied by the
    caller.

    The parameters produced by this function are required in the space
    motion, parallax, light deflection and aberration parts of the
    astrometric transformation chain.

    Given:
       date1  double       TDB as a 2-part...
       date2  double       ...Julian Date (Note 1)
       pv     double[2][3] observer's geocentric pos/vel (m, m/s)
       ebpv   double[2][3] Earth barycentric PV (au, au/day)
       ehp    double[3]    Earth heliocentric P (au)

    Returned:
       astrom eraASTROM*   star-independent astrometry parameters:
        pmt    double       PM time interval (SSB, Julian years)
        eb     double[3]    SSB to observer (vector, au)
        eh     double[3]    Sun to observer (unit vector)
        em     double       distance from Sun to observer (au)
        v      double[3]    barycentric observer velocity (vector, c)
        bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
        bpn    double[3][3] bias-precession-nutation matrix
        along  double       unchanged
        xpl    double       unchanged
        ypl    double       unchanged
        sphi   double       unchanged
        cphi   double       unchanged
        diurab double       unchanged
        eral   double       unchanged
        refa   double       unchanged
        refb   double       unchanged

    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.  For most
       applications of this function the choice will not be at all
       critical.

       TT can be used instead of TDB without any significant impact on
       accuracy.

    2) All the vectors are with respect to BCRS axes.

    3) Providing separate arguments for (i) the observer's geocentric
       position and velocity and (ii) the Earth ephemeris is done for
       convenience in the geocentric, terrestrial and Earth orbit cases.
       For deep space applications it maybe more convenient to specify
       zero geocentric position and velocity and to supply the
       observer's position and velocity information directly instead of
       with respect to the Earth.  However, note the different units:
       m and m/s for the geocentric vectors, au and au/day for the
       heliocentric and barycentric vectors.

    4) In cases where the caller does not wish to provide the Earth
       ephemeris, the function eraApcs13 can be used instead of the
       present function.  This computes the Earth ephemeris using the
       ERFA function eraEpv00.

    5) This is one of several functions that inserts into the astrom
       structure star-independent parameters needed for the chain of
       astrometric transformations ICRS <-> GCRS <-> CIRS <-> observed.

       The various functions support different classes of observer and
       portions of the transformation chain:

            functions         observer        transformation

         eraApcg eraApcg13    geocentric      ICRS <-> GCRS
         eraApci eraApci13    terrestrial     ICRS <-> CIRS
         eraApco eraApco13    terrestrial     ICRS <-> observed
         eraApcs eraApcs13    space           ICRS <-> GCRS
         eraAper eraAper13    terrestrial     update Earth rotation
         eraApio eraApio13    terrestrial     CIRS <-> observed

       Those with names ending in "13" use contemporary ERFA models to
       compute the various ephemerides.  The others accept ephemerides
       supplied by the caller.

       The transformation from ICRS to GCRS covers space motion,
       parallax, light deflection, and aberration.  From GCRS to CIRS
       comprises frame bias and precession-nutation.  From CIRS to
       observed takes account of Earth rotation, polar motion, diurnal
       aberration and parallax (unless subsumed into the ICRS <-> GCRS
       transformation), and atmospheric refraction.

    6) The context structure astrom produced by this function is used by
       eraAtciq* and eraAticq*.

    Called:
       eraCp        copy p-vector
       eraPm        modulus of p-vector
       eraPn        decompose p-vector into modulus and direction
       eraIr        initialize r-matrix to identity

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    pv_in = numpy.array(pv, dtype=numpy.double, order="C", copy=False, subok=True)
    ebpv_in = numpy.array(ebpv, dtype=numpy.double, order="C", copy=False, subok=True)
    ehp_in = numpy.array(ehp, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(pv_in, (2, 3), "pv")
    check_trailing_shape(ebpv_in, (2, 3), "ebpv")
    check_trailing_shape(ehp_in, (3,), "ehp")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if pv_in[...,0,0].shape == tuple():
            pv_in = pv_in.reshape((1,) + pv_in.shape)
        else:
            make_outputs_scalar = False
        if ebpv_in[...,0,0].shape == tuple():
            ebpv_in = ebpv_in.reshape((1,) + ebpv_in.shape)
        else:
            make_outputs_scalar = False
        if ehp_in[...,0].shape == tuple():
            ehp_in = ehp_in.reshape((1,) + ehp_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, pv_in[...,0,0], ebpv_in[...,0,0], ehp_in[...,0])
    astrom_out = numpy.empty(broadcast.shape + (), dtype=dt_eraASTROM)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, pv_in[...,0,0], ebpv_in[...,0,0], ehp_in[...,0], astrom_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*5 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._apcs(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(astrom_out.shape) > 0 and astrom_out.shape[0] == 1
        astrom_out = astrom_out.reshape(astrom_out.shape[1:])

    return astrom_out


def apcs13(date1, date2, pv):
    """
    Wrapper for ERFA function ``eraApcs13``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    pv : double array

    Returns
    -------
    astrom : eraASTROM array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a A p c s 1 3
    - - - - - - - - - -

    For an observer whose geocentric position and velocity are known,
    prepare star-independent astrometry parameters for transformations
    between ICRS and GCRS.  The Earth ephemeris is from ERFA models.

    The parameters produced by this function are required in the space
    motion, parallax, light deflection and aberration parts of the
    astrometric transformation chain.

    Given:
       date1  double       TDB as a 2-part...
       date2  double       ...Julian Date (Note 1)
       pv     double[2][3] observer's geocentric pos/vel (Note 3)

    Returned:
       astrom eraASTROM*   star-independent astrometry parameters:
        pmt    double       PM time interval (SSB, Julian years)
        eb     double[3]    SSB to observer (vector, au)
        eh     double[3]    Sun to observer (unit vector)
        em     double       distance from Sun to observer (au)
        v      double[3]    barycentric observer velocity (vector, c)
        bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
        bpn    double[3][3] bias-precession-nutation matrix
        along  double       unchanged
        xpl    double       unchanged
        ypl    double       unchanged
        sphi   double       unchanged
        cphi   double       unchanged
        diurab double       unchanged
        eral   double       unchanged
        refa   double       unchanged
        refb   double       unchanged

    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.  For most
       applications of this function the choice will not be at all
       critical.

       TT can be used instead of TDB without any significant impact on
       accuracy.

    2) All the vectors are with respect to BCRS axes.

    3) The observer's position and velocity pv are geocentric but with
       respect to BCRS axes, and in units of m and m/s.  No assumptions
       are made about proximity to the Earth, and the function can be
       used for deep space applications as well as Earth orbit and
       terrestrial.

    4) In cases where the caller wishes to supply his own Earth
       ephemeris, the function eraApcs can be used instead of the present
       function.

    5) This is one of several functions that inserts into the astrom
       structure star-independent parameters needed for the chain of
       astrometric transformations ICRS <-> GCRS <-> CIRS <-> observed.

       The various functions support different classes of observer and
       portions of the transformation chain:

            functions         observer        transformation

         eraApcg eraApcg13    geocentric      ICRS <-> GCRS
         eraApci eraApci13    terrestrial     ICRS <-> CIRS
         eraApco eraApco13    terrestrial     ICRS <-> observed
         eraApcs eraApcs13    space           ICRS <-> GCRS
         eraAper eraAper13    terrestrial     update Earth rotation
         eraApio eraApio13    terrestrial     CIRS <-> observed

       Those with names ending in "13" use contemporary ERFA models to
       compute the various ephemerides.  The others accept ephemerides
       supplied by the caller.

       The transformation from ICRS to GCRS covers space motion,
       parallax, light deflection, and aberration.  From GCRS to CIRS
       comprises frame bias and precession-nutation.  From CIRS to
       observed takes account of Earth rotation, polar motion, diurnal
       aberration and parallax (unless subsumed into the ICRS <-> GCRS
       transformation), and atmospheric refraction.

    6) The context structure astrom produced by this function is used by
       eraAtciq* and eraAticq*.

    Called:
       eraEpv00     Earth position and velocity
       eraApcs      astrometry parameters, ICRS-GCRS, space observer

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    pv_in = numpy.array(pv, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(pv_in, (2, 3), "pv")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if pv_in[...,0,0].shape == tuple():
            pv_in = pv_in.reshape((1,) + pv_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, pv_in[...,0,0])
    astrom_out = numpy.empty(broadcast.shape + (), dtype=dt_eraASTROM)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, pv_in[...,0,0], astrom_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._apcs13(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(astrom_out.shape) > 0 and astrom_out.shape[0] == 1
        astrom_out = astrom_out.reshape(astrom_out.shape[1:])

    return astrom_out


def aper(theta, astrom):
    """
    Wrapper for ERFA function ``eraAper``.

    Parameters
    ----------
    theta : double array
    astrom : eraASTROM array

    Returns
    -------
    astrom : eraASTROM array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a A p e r
    - - - - - - - -

    In the star-independent astrometry parameters, update only the
    Earth rotation angle, supplied by the caller explicitly.

    Given:
       theta   double      Earth rotation angle (radians, Note 2)
       astrom  eraASTROM*  star-independent astrometry parameters:
        pmt    double       not used
        eb     double[3]    not used
        eh     double[3]    not used
        em     double       not used
        v      double[3]    not used
        bm1    double       not used
        bpn    double[3][3] not used
        along  double       longitude + s' (radians)
        xpl    double       not used
        ypl    double       not used
        sphi   double       not used
        cphi   double       not used
        diurab double       not used
        eral   double       not used
        refa   double       not used
        refb   double       not used

    Returned:
       astrom  eraASTROM*  star-independent astrometry parameters:
        pmt    double       unchanged
        eb     double[3]    unchanged
        eh     double[3]    unchanged
        em     double       unchanged
        v      double[3]    unchanged
        bm1    double       unchanged
        bpn    double[3][3] unchanged
        along  double       unchanged
        xpl    double       unchanged
        ypl    double       unchanged
        sphi   double       unchanged
        cphi   double       unchanged
        diurab double       unchanged
        eral   double       "local" Earth rotation angle (radians)
        refa   double       unchanged
        refb   double       unchanged

    Notes:

    1) This function exists to enable sidereal-tracking applications to
       avoid wasteful recomputation of the bulk of the astrometry
       parameters:  only the Earth rotation is updated.

    2) For targets expressed as equinox based positions, such as
       classical geocentric apparent (RA,Dec), the supplied theta can be
       Greenwich apparent sidereal time rather than Earth rotation
       angle.

    3) The function eraAper13 can be used instead of the present
       function, and starts from UT1 rather than ERA itself.

    4) This is one of several functions that inserts into the astrom
       structure star-independent parameters needed for the chain of
       astrometric transformations ICRS <-> GCRS <-> CIRS <-> observed.

       The various functions support different classes of observer and
       portions of the transformation chain:

            functions         observer        transformation

         eraApcg eraApcg13    geocentric      ICRS <-> GCRS
         eraApci eraApci13    terrestrial     ICRS <-> CIRS
         eraApco eraApco13    terrestrial     ICRS <-> observed
         eraApcs eraApcs13    space           ICRS <-> GCRS
         eraAper eraAper13    terrestrial     update Earth rotation
         eraApio eraApio13    terrestrial     CIRS <-> observed

       Those with names ending in "13" use contemporary ERFA models to
       compute the various ephemerides.  The others accept ephemerides
       supplied by the caller.

       The transformation from ICRS to GCRS covers space motion,
       parallax, light deflection, and aberration.  From GCRS to CIRS
       comprises frame bias and precession-nutation.  From CIRS to
       observed takes account of Earth rotation, polar motion, diurnal
       aberration and parallax (unless subsumed into the ICRS <-> GCRS
       transformation), and atmospheric refraction.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    theta_in = numpy.array(theta, dtype=numpy.double, order="C", copy=False, subok=True)
    astrom_in = numpy.array(astrom, dtype=dt_eraASTROM, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if theta_in.shape == tuple():
            theta_in = theta_in.reshape((1,) + theta_in.shape)
        else:
            make_outputs_scalar = False
        if astrom_in.shape == tuple():
            astrom_in = astrom_in.reshape((1,) + astrom_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), theta_in, astrom_in)
    astrom_out = numpy.empty(broadcast.shape + (), dtype=dt_eraASTROM)
    numpy.copyto(astrom_out, astrom_in)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [theta_in, astrom_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._aper(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(astrom_out.shape) > 0 and astrom_out.shape[0] == 1
        astrom_out = astrom_out.reshape(astrom_out.shape[1:])

    return astrom_out


def aper13(ut11, ut12, astrom):
    """
    Wrapper for ERFA function ``eraAper13``.

    Parameters
    ----------
    ut11 : double array
    ut12 : double array
    astrom : eraASTROM array

    Returns
    -------
    astrom : eraASTROM array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a A p e r 1 3
    - - - - - - - - - -

    In the star-independent astrometry parameters, update only the
    Earth rotation angle.  The caller provides UT1, (n.b. not UTC).

    Given:
       ut11    double      UT1 as a 2-part...
       ut12    double      ...Julian Date (Note 1)
       astrom  eraASTROM*  star-independent astrometry parameters:
        pmt    double       not used
        eb     double[3]    not used
        eh     double[3]    not used
        em     double       not used
        v      double[3]    not used
        bm1    double       not used
        bpn    double[3][3] not used
        along  double       longitude + s' (radians)
        xpl    double       not used
        ypl    double       not used
        sphi   double       not used
        cphi   double       not used
        diurab double       not used
        eral   double       not used
        refa   double       not used
        refb   double       not used

    Returned:
       astrom  eraASTROM*  star-independent astrometry parameters:
        pmt    double       unchanged
        eb     double[3]    unchanged
        eh     double[3]    unchanged
        em     double       unchanged
        v      double[3]    unchanged
        bm1    double       unchanged
        bpn    double[3][3] unchanged
        along  double       unchanged
        xpl    double       unchanged
        ypl    double       unchanged
        sphi   double       unchanged
        cphi   double       unchanged
        diurab double       unchanged
        eral   double       "local" Earth rotation angle (radians)
        refa   double       unchanged
        refb   double       unchanged

    Notes:

    1) The UT1 date (n.b. not UTC) ut11+ut12 is a Julian Date,
       apportioned in any convenient way between the arguments ut11 and
       ut12.  For example, JD(UT1)=2450123.7 could be expressed in any
       of these ways, among others:

              ut11           ut12

           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 ut11 argument is for 0hrs UT1 on the day in
       question and the ut12 argument lies in the range 0 to 1, or vice
       versa.

    2) If the caller wishes to provide the Earth rotation angle itself,
       the function eraAper can be used instead.  One use of this
       technique is to substitute Greenwich apparent sidereal time and
       thereby to support equinox based transformations directly.

    3) This is one of several functions that inserts into the astrom
       structure star-independent parameters needed for the chain of
       astrometric transformations ICRS <-> GCRS <-> CIRS <-> observed.

       The various functions support different classes of observer and
       portions of the transformation chain:

            functions         observer        transformation

         eraApcg eraApcg13    geocentric      ICRS <-> GCRS
         eraApci eraApci13    terrestrial     ICRS <-> CIRS
         eraApco eraApco13    terrestrial     ICRS <-> observed
         eraApcs eraApcs13    space           ICRS <-> GCRS
         eraAper eraAper13    terrestrial     update Earth rotation
         eraApio eraApio13    terrestrial     CIRS <-> observed

       Those with names ending in "13" use contemporary ERFA models to
       compute the various ephemerides.  The others accept ephemerides
       supplied by the caller.

       The transformation from ICRS to GCRS covers space motion,
       parallax, light deflection, and aberration.  From GCRS to CIRS
       comprises frame bias and precession-nutation.  From CIRS to
       observed takes account of Earth rotation, polar motion, diurnal
       aberration and parallax (unless subsumed into the ICRS <-> GCRS
       transformation), and atmospheric refraction.

    Called:
       eraAper      astrometry parameters: update ERA
       eraEra00     Earth rotation angle, IAU 2000

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ut11_in = numpy.array(ut11, dtype=numpy.double, order="C", copy=False, subok=True)
    ut12_in = numpy.array(ut12, dtype=numpy.double, order="C", copy=False, subok=True)
    astrom_in = numpy.array(astrom, dtype=dt_eraASTROM, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ut11_in.shape == tuple():
            ut11_in = ut11_in.reshape((1,) + ut11_in.shape)
        else:
            make_outputs_scalar = False
        if ut12_in.shape == tuple():
            ut12_in = ut12_in.reshape((1,) + ut12_in.shape)
        else:
            make_outputs_scalar = False
        if astrom_in.shape == tuple():
            astrom_in = astrom_in.reshape((1,) + astrom_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ut11_in, ut12_in, astrom_in)
    astrom_out = numpy.empty(broadcast.shape + (), dtype=dt_eraASTROM)
    numpy.copyto(astrom_out, astrom_in)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ut11_in, ut12_in, astrom_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._aper13(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(astrom_out.shape) > 0 and astrom_out.shape[0] == 1
        astrom_out = astrom_out.reshape(astrom_out.shape[1:])

    return astrom_out


def apio(sp, theta, elong, phi, hm, xp, yp, refa, refb):
    """
    Wrapper for ERFA function ``eraApio``.

    Parameters
    ----------
    sp : double array
    theta : double array
    elong : double array
    phi : double array
    hm : double array
    xp : double array
    yp : double array
    refa : double array
    refb : double array

    Returns
    -------
    refa : double array
    refb : double array
    astrom : eraASTROM array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a A p i o
    - - - - - - - -

    For a terrestrial observer, prepare star-independent astrometry
    parameters for transformations between CIRS and observed
    coordinates.  The caller supplies the Earth orientation information
    and the refraction constants as well as the site coordinates.

    Given:
       sp     double      the TIO locator s' (radians, Note 1)
       theta  double      Earth rotation angle (radians)
       elong  double      longitude (radians, east +ve, Note 2)
       phi    double      geodetic latitude (radians, Note 2)
       hm     double      height above ellipsoid (m, geodetic Note 2)
       xp,yp  double      polar motion coordinates (radians, Note 3)
       refa   double      refraction constant A (radians, Note 4)
       refb   double      refraction constant B (radians, Note 4)

    Returned:
       astrom eraASTROM*  star-independent astrometry parameters:
        pmt    double       unchanged
        eb     double[3]    unchanged
        eh     double[3]    unchanged
        em     double       unchanged
        v      double[3]    unchanged
        bm1    double       unchanged
        bpn    double[3][3] unchanged
        along  double       longitude + s' (radians)
        xpl    double       polar motion xp wrt local meridian (radians)
        ypl    double       polar motion yp wrt local meridian (radians)
        sphi   double       sine of geodetic latitude
        cphi   double       cosine of geodetic latitude
        diurab double       magnitude of diurnal aberration vector
        eral   double       "local" Earth rotation angle (radians)
        refa   double       refraction constant A (radians)
        refb   double       refraction constant B (radians)

    Notes:

    1) sp, the TIO locator s', is a tiny quantity needed only by the
       most precise applications.  It can either be set to zero or
       predicted using the ERFA function eraSp00.

    2) The geographical coordinates are with respect to the ERFA_WGS84
       reference ellipsoid.  TAKE CARE WITH THE LONGITUDE SIGN:  the
       longitude required by the present function is east-positive
       (i.e. right-handed), in accordance with geographical convention.

    3) The polar motion xp,yp can be obtained from IERS bulletins.  The
       values 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 0 and 90 deg west respectively.  For many applications,
       xp and yp can be set to zero.

       Internally, the polar motion is stored in a form rotated onto the
       local meridian.

    4) The refraction constants refa and refb are for use in a
       dZ = A*tan(Z)+B*tan^3(Z) model, where Z is the observed
       (i.e. refracted) zenith distance and dZ is the amount of
       refraction.

    5) It is advisable to take great care with units, as even unlikely
       values of the input parameters are accepted and processed in
       accordance with the models used.

    6) In cases where the caller does not wish to provide the Earth
       rotation information and refraction constants, the function
       eraApio13 can be used instead of the present function.  This
       starts from UTC and weather readings etc. and computes suitable
       values using other ERFA functions.

    7) This is one of several functions that inserts into the astrom
       structure star-independent parameters needed for the chain of
       astrometric transformations ICRS <-> GCRS <-> CIRS <-> observed.

       The various functions support different classes of observer and
       portions of the transformation chain:

            functions         observer        transformation

         eraApcg eraApcg13    geocentric      ICRS <-> GCRS
         eraApci eraApci13    terrestrial     ICRS <-> CIRS
         eraApco eraApco13    terrestrial     ICRS <-> observed
         eraApcs eraApcs13    space           ICRS <-> GCRS
         eraAper eraAper13    terrestrial     update Earth rotation
         eraApio eraApio13    terrestrial     CIRS <-> observed

       Those with names ending in "13" use contemporary ERFA models to
       compute the various ephemerides.  The others accept ephemerides
       supplied by the caller.

       The transformation from ICRS to GCRS covers space motion,
       parallax, light deflection, and aberration.  From GCRS to CIRS
       comprises frame bias and precession-nutation.  From CIRS to
       observed takes account of Earth rotation, polar motion, diurnal
       aberration and parallax (unless subsumed into the ICRS <-> GCRS
       transformation), and atmospheric refraction.

    8) The context structure astrom produced by this function is used by
       eraAtioq and eraAtoiq.

    Called:
       eraPvtob     position/velocity of terrestrial station
       eraAper      astrometry parameters: update ERA

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    sp_in = numpy.array(sp, dtype=numpy.double, order="C", copy=False, subok=True)
    theta_in = numpy.array(theta, dtype=numpy.double, order="C", copy=False, subok=True)
    elong_in = numpy.array(elong, dtype=numpy.double, order="C", copy=False, subok=True)
    phi_in = numpy.array(phi, dtype=numpy.double, order="C", copy=False, subok=True)
    hm_in = numpy.array(hm, dtype=numpy.double, order="C", copy=False, subok=True)
    xp_in = numpy.array(xp, dtype=numpy.double, order="C", copy=False, subok=True)
    yp_in = numpy.array(yp, dtype=numpy.double, order="C", copy=False, subok=True)
    refa_in = numpy.array(refa, dtype=numpy.double, order="C", copy=False, subok=True)
    refb_in = numpy.array(refb, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if sp_in.shape == tuple():
            sp_in = sp_in.reshape((1,) + sp_in.shape)
        else:
            make_outputs_scalar = False
        if theta_in.shape == tuple():
            theta_in = theta_in.reshape((1,) + theta_in.shape)
        else:
            make_outputs_scalar = False
        if elong_in.shape == tuple():
            elong_in = elong_in.reshape((1,) + elong_in.shape)
        else:
            make_outputs_scalar = False
        if phi_in.shape == tuple():
            phi_in = phi_in.reshape((1,) + phi_in.shape)
        else:
            make_outputs_scalar = False
        if hm_in.shape == tuple():
            hm_in = hm_in.reshape((1,) + hm_in.shape)
        else:
            make_outputs_scalar = False
        if xp_in.shape == tuple():
            xp_in = xp_in.reshape((1,) + xp_in.shape)
        else:
            make_outputs_scalar = False
        if yp_in.shape == tuple():
            yp_in = yp_in.reshape((1,) + yp_in.shape)
        else:
            make_outputs_scalar = False
        if refa_in.shape == tuple():
            refa_in = refa_in.reshape((1,) + refa_in.shape)
        else:
            make_outputs_scalar = False
        if refb_in.shape == tuple():
            refb_in = refb_in.reshape((1,) + refb_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), sp_in, theta_in, elong_in, phi_in, hm_in, xp_in, yp_in, refa_in, refb_in)
    refa_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    refb_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    astrom_out = numpy.empty(broadcast.shape + (), dtype=dt_eraASTROM)
    numpy.copyto(refa_out, refa_in)
    numpy.copyto(refb_out, refb_in)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [sp_in, theta_in, elong_in, phi_in, hm_in, xp_in, yp_in, refa_out, refb_out, astrom_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*7 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._apio(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(refa_out.shape) > 0 and refa_out.shape[0] == 1
        refa_out = refa_out.reshape(refa_out.shape[1:])
        assert len(refb_out.shape) > 0 and refb_out.shape[0] == 1
        refb_out = refb_out.reshape(refb_out.shape[1:])
        assert len(astrom_out.shape) > 0 and astrom_out.shape[0] == 1
        astrom_out = astrom_out.reshape(astrom_out.shape[1:])

    return refa_out, refb_out, astrom_out


def apio13(utc1, utc2, dut1, elong, phi, hm, xp, yp, phpa, tc, rh, wl):
    """
    Wrapper for ERFA function ``eraApio13``.

    Parameters
    ----------
    utc1 : double array
    utc2 : double array
    dut1 : double array
    elong : double array
    phi : double array
    hm : double array
    xp : double array
    yp : double array
    phpa : double array
    tc : double array
    rh : double array
    wl : double array

    Returns
    -------
    astrom : eraASTROM array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a A p i o 1 3
    - - - - - - - - - -

    For a terrestrial observer, prepare star-independent astrometry
    parameters for transformations between CIRS and observed
    coordinates.  The caller supplies UTC, site coordinates, ambient air
    conditions and observing wavelength.

    Given:
       utc1   double      UTC as a 2-part...
       utc2   double      ...quasi Julian Date (Notes 1,2)
       dut1   double      UT1-UTC (seconds)
       elong  double      longitude (radians, east +ve, Note 3)
       phi    double      geodetic latitude (radians, Note 3)
       hm     double      height above ellipsoid (m, geodetic Notes 4,6)
       xp,yp  double      polar motion coordinates (radians, Note 5)
       phpa   double      pressure at the observer (hPa = mB, Note 6)
       tc     double      ambient temperature at the observer (deg C)
       rh     double      relative humidity at the observer (range 0-1)
       wl     double      wavelength (micrometers, Note 7)

    Returned:
       astrom eraASTROM*  star-independent astrometry parameters:
        pmt    double       unchanged
        eb     double[3]    unchanged
        eh     double[3]    unchanged
        em     double       unchanged
        v      double[3]    unchanged
        bm1    double       unchanged
        bpn    double[3][3] unchanged
        along  double       longitude + s' (radians)
        xpl    double       polar motion xp wrt local meridian (radians)
        ypl    double       polar motion yp wrt local meridian (radians)
        sphi   double       sine of geodetic latitude
        cphi   double       cosine of geodetic latitude
        diurab double       magnitude of diurnal aberration vector
        eral   double       "local" Earth rotation angle (radians)
        refa   double       refraction constant A (radians)
        refb   double       refraction constant B (radians)

    Returned (function value):
              int         status: +1 = dubious year (Note 2)
                                   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.

        However, 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.

        Applications should use the function eraDtf2d to convert from
        calendar date and time of day into 2-part quasi Julian Date, as
        it implements the leap-second-ambiguity convention just
        described.

    2)  The warning status "dubious year" flags UTCs that predate the
        introduction of the time scale or that are too far in the future
        to be trusted.  See eraDat for further details.

    3)  UT1-UTC is tabulated in IERS bulletins.  It increases by exactly
        one second at the end of each positive UTC leap second,
        introduced in order to keep UT1-UTC within +/- 0.9s.  n.b. This
        practice is under review, and in the future UT1-UTC may grow
        essentially without limit.

    4)  The geographical coordinates are with respect to the ERFA_WGS84
        reference ellipsoid.  TAKE CARE WITH THE LONGITUDE SIGN:  the
        longitude required by the present function is east-positive
        (i.e. right-handed), in accordance with geographical convention.

    5)  The polar motion xp,yp can be obtained from IERS bulletins.  The
        values 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 0 and 90 deg west respectively.  For many applications,
        xp and yp can be set to zero.

        Internally, the polar motion is stored in a form rotated onto
        the local meridian.

    6)  If hm, the height above the ellipsoid of the observing station
        in meters, is not known but phpa, the pressure in hPa (=mB), is
        available, an adequate estimate of hm can be obtained from the
        expression

              hm = -29.3 * tsl * log ( phpa / 1013.25 );

        where tsl is the approximate sea-level air temperature in K
        (See Astrophysical Quantities, C.W.Allen, 3rd edition, section
        52).  Similarly, if the pressure phpa is not known, it can be
        estimated from the height of the observing station, hm, as
        follows:

              phpa = 1013.25 * exp ( -hm / ( 29.3 * tsl ) );

        Note, however, that the refraction is nearly proportional to the
        pressure and that an accurate phpa value is important for
        precise work.

    7)  The argument wl specifies the observing wavelength in
        micrometers.  The transition from optical to radio is assumed to
        occur at 100 micrometers (about 3000 GHz).

    8)  It is advisable to take great care with units, as even unlikely
        values of the input parameters are accepted and processed in
        accordance with the models used.

    9)  In cases where the caller wishes to supply his own Earth
        rotation information and refraction constants, the function
        eraApc can be used instead of the present function.

    10) This is one of several functions that inserts into the astrom
        structure star-independent parameters needed for the chain of
        astrometric transformations ICRS <-> GCRS <-> CIRS <-> observed.

        The various functions support different classes of observer and
        portions of the transformation chain:

            functions         observer        transformation

         eraApcg eraApcg13    geocentric      ICRS <-> GCRS
         eraApci eraApci13    terrestrial     ICRS <-> CIRS
         eraApco eraApco13    terrestrial     ICRS <-> observed
         eraApcs eraApcs13    space           ICRS <-> GCRS
         eraAper eraAper13    terrestrial     update Earth rotation
         eraApio eraApio13    terrestrial     CIRS <-> observed

        Those with names ending in "13" use contemporary ERFA models to
        compute the various ephemerides.  The others accept ephemerides
        supplied by the caller.

        The transformation from ICRS to GCRS covers space motion,
        parallax, light deflection, and aberration.  From GCRS to CIRS
        comprises frame bias and precession-nutation.  From CIRS to
        observed takes account of Earth rotation, polar motion, diurnal
        aberration and parallax (unless subsumed into the ICRS <-> GCRS
        transformation), and atmospheric refraction.

    11) The context structure astrom produced by this function is used
        by eraAtioq and eraAtoiq.

    Called:
       eraUtctai    UTC to TAI
       eraTaitt     TAI to TT
       eraUtcut1    UTC to UT1
       eraSp00      the TIO locator s', IERS 2000
       eraEra00     Earth rotation angle, IAU 2000
       eraRefco     refraction constants for given ambient conditions
       eraApio      astrometry parameters, CIRS-observed

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    utc1_in = numpy.array(utc1, dtype=numpy.double, order="C", copy=False, subok=True)
    utc2_in = numpy.array(utc2, dtype=numpy.double, order="C", copy=False, subok=True)
    dut1_in = numpy.array(dut1, dtype=numpy.double, order="C", copy=False, subok=True)
    elong_in = numpy.array(elong, dtype=numpy.double, order="C", copy=False, subok=True)
    phi_in = numpy.array(phi, dtype=numpy.double, order="C", copy=False, subok=True)
    hm_in = numpy.array(hm, dtype=numpy.double, order="C", copy=False, subok=True)
    xp_in = numpy.array(xp, dtype=numpy.double, order="C", copy=False, subok=True)
    yp_in = numpy.array(yp, dtype=numpy.double, order="C", copy=False, subok=True)
    phpa_in = numpy.array(phpa, dtype=numpy.double, order="C", copy=False, subok=True)
    tc_in = numpy.array(tc, dtype=numpy.double, order="C", copy=False, subok=True)
    rh_in = numpy.array(rh, dtype=numpy.double, order="C", copy=False, subok=True)
    wl_in = numpy.array(wl, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if utc1_in.shape == tuple():
            utc1_in = utc1_in.reshape((1,) + utc1_in.shape)
        else:
            make_outputs_scalar = False
        if utc2_in.shape == tuple():
            utc2_in = utc2_in.reshape((1,) + utc2_in.shape)
        else:
            make_outputs_scalar = False
        if dut1_in.shape == tuple():
            dut1_in = dut1_in.reshape((1,) + dut1_in.shape)
        else:
            make_outputs_scalar = False
        if elong_in.shape == tuple():
            elong_in = elong_in.reshape((1,) + elong_in.shape)
        else:
            make_outputs_scalar = False
        if phi_in.shape == tuple():
            phi_in = phi_in.reshape((1,) + phi_in.shape)
        else:
            make_outputs_scalar = False
        if hm_in.shape == tuple():
            hm_in = hm_in.reshape((1,) + hm_in.shape)
        else:
            make_outputs_scalar = False
        if xp_in.shape == tuple():
            xp_in = xp_in.reshape((1,) + xp_in.shape)
        else:
            make_outputs_scalar = False
        if yp_in.shape == tuple():
            yp_in = yp_in.reshape((1,) + yp_in.shape)
        else:
            make_outputs_scalar = False
        if phpa_in.shape == tuple():
            phpa_in = phpa_in.reshape((1,) + phpa_in.shape)
        else:
            make_outputs_scalar = False
        if tc_in.shape == tuple():
            tc_in = tc_in.reshape((1,) + tc_in.shape)
        else:
            make_outputs_scalar = False
        if rh_in.shape == tuple():
            rh_in = rh_in.reshape((1,) + rh_in.shape)
        else:
            make_outputs_scalar = False
        if wl_in.shape == tuple():
            wl_in = wl_in.reshape((1,) + wl_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), utc1_in, utc2_in, dut1_in, elong_in, phi_in, hm_in, xp_in, yp_in, phpa_in, tc_in, rh_in, wl_in)
    astrom_out = numpy.empty(broadcast.shape + (), dtype=dt_eraASTROM)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [utc1_in, utc2_in, dut1_in, elong_in, phi_in, hm_in, xp_in, yp_in, phpa_in, tc_in, rh_in, wl_in, astrom_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*12 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._apio13(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'apio13')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(astrom_out.shape) > 0 and astrom_out.shape[0] == 1
        astrom_out = astrom_out.reshape(astrom_out.shape[1:])

    return astrom_out
STATUS_CODES['apio13'] = {0: 'OK', 1: 'dubious year (Note 2)', -1: 'unacceptable date'}



def atci13(rc, dc, pr, pd, px, rv, date1, date2):
    """
    Wrapper for ERFA function ``eraAtci13``.

    Parameters
    ----------
    rc : double array
    dc : double array
    pr : double array
    pd : double array
    px : double array
    rv : double array
    date1 : double array
    date2 : double array

    Returns
    -------
    ri : double array
    di : double array
    eo : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a A t c i 1 3
    - - - - - - - - - -

    Transform ICRS star data, epoch J2000.0, to CIRS.

    Given:
       rc     double   ICRS right ascension at J2000.0 (radians, Note 1)
       dc     double   ICRS declination at J2000.0 (radians, Note 1)
       pr     double   RA proper motion (radians/year; Note 2)
       pd     double   Dec proper motion (radians/year)
       px     double   parallax (arcsec)
       rv     double   radial velocity (km/s, +ve if receding)
       date1  double   TDB as a 2-part...
       date2  double   ...Julian Date (Note 3)

    Returned:
       ri,di  double*  CIRS geocentric RA,Dec (radians)
       eo     double*  equation of the origins (ERA-GST, Note 5)

    Notes:

    1) Star data for an epoch other than J2000.0 (for example from the
       Hipparcos catalog, which has an epoch of J1991.25) will require a
       preliminary call to eraPmsafe before use.

    2) The proper motion in RA is dRA/dt rather than cos(Dec)*dRA/dt.

    3) The TDB date date1+date2 is a Julian Date, apportioned in any
       convenient way between the two arguments.  For example,
       JD(TDB)=2450123.8g could be expressed in any of these ways, among
       others:

              date1          date2

           2450123.8g           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.  For most
       applications of this function the choice will not be at all
       critical.

       TT can be used instead of TDB without any significant impact on
       accuracy.

    4) The available accuracy is better than 1 milliarcsecond, limited
       mainly by the precession-nutation model that is used, namely
       IAU 2000A/2006.  Very close to solar system bodies, additional
       errors of up to several milliarcseconds can occur because of
       unmodeled light deflection;  however, the Sun's contribution is
       taken into account, to first order.  The accuracy limitations of
       the ERFA function eraEpv00 (used to compute Earth position and
       velocity) can contribute aberration errors of up to
       5 microarcseconds.  Light deflection at the Sun's limb is
       uncertain at the 0.4 mas level.

    5) Should the transformation to (equinox based) apparent place be
       required rather than (CIO based) intermediate place, subtract the
       equation of the origins from the returned right ascension:
       RA = RI - EO. (The eraAnp function can then be applied, as
       required, to keep the result in the conventional 0-2pi range.)

    Called:
       eraApci13    astrometry parameters, ICRS-CIRS, 2013
       eraAtciq     quick ICRS to CIRS

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    rc_in = numpy.array(rc, dtype=numpy.double, order="C", copy=False, subok=True)
    dc_in = numpy.array(dc, dtype=numpy.double, order="C", copy=False, subok=True)
    pr_in = numpy.array(pr, dtype=numpy.double, order="C", copy=False, subok=True)
    pd_in = numpy.array(pd, dtype=numpy.double, order="C", copy=False, subok=True)
    px_in = numpy.array(px, dtype=numpy.double, order="C", copy=False, subok=True)
    rv_in = numpy.array(rv, dtype=numpy.double, order="C", copy=False, subok=True)
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if rc_in.shape == tuple():
            rc_in = rc_in.reshape((1,) + rc_in.shape)
        else:
            make_outputs_scalar = False
        if dc_in.shape == tuple():
            dc_in = dc_in.reshape((1,) + dc_in.shape)
        else:
            make_outputs_scalar = False
        if pr_in.shape == tuple():
            pr_in = pr_in.reshape((1,) + pr_in.shape)
        else:
            make_outputs_scalar = False
        if pd_in.shape == tuple():
            pd_in = pd_in.reshape((1,) + pd_in.shape)
        else:
            make_outputs_scalar = False
        if px_in.shape == tuple():
            px_in = px_in.reshape((1,) + px_in.shape)
        else:
            make_outputs_scalar = False
        if rv_in.shape == tuple():
            rv_in = rv_in.reshape((1,) + rv_in.shape)
        else:
            make_outputs_scalar = False
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), rc_in, dc_in, pr_in, pd_in, px_in, rv_in, date1_in, date2_in)
    ri_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    di_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    eo_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [rc_in, dc_in, pr_in, pd_in, px_in, rv_in, date1_in, date2_in, ri_out, di_out, eo_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*8 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._atci13(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(ri_out.shape) > 0 and ri_out.shape[0] == 1
        ri_out = ri_out.reshape(ri_out.shape[1:])
        assert len(di_out.shape) > 0 and di_out.shape[0] == 1
        di_out = di_out.reshape(di_out.shape[1:])
        assert len(eo_out.shape) > 0 and eo_out.shape[0] == 1
        eo_out = eo_out.reshape(eo_out.shape[1:])

    return ri_out, di_out, eo_out


def atciq(rc, dc, pr, pd, px, rv, astrom):
    """
    Wrapper for ERFA function ``eraAtciq``.

    Parameters
    ----------
    rc : double array
    dc : double array
    pr : double array
    pd : double array
    px : double array
    rv : double array
    astrom : eraASTROM array

    Returns
    -------
    ri : double array
    di : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a A t c i q
    - - - - - - - - -

    Quick ICRS, epoch J2000.0, to CIRS transformation, given precomputed
    star-independent astrometry parameters.

    Use of this function is appropriate when efficiency is important and
    where many star positions are to be transformed for one date.  The
    star-independent parameters can be obtained by calling one of the
    functions eraApci[13], eraApcg[13], eraApco[13] or eraApcs[13].

    If the parallax and proper motions are zero the eraAtciqz function
    can be used instead.

    Given:
       rc,dc  double     ICRS RA,Dec at J2000.0 (radians)
       pr     double     RA proper motion (radians/year; Note 3)
       pd     double     Dec proper motion (radians/year)
       px     double     parallax (arcsec)
       rv     double     radial velocity (km/s, +ve if receding)
       astrom eraASTROM* star-independent astrometry parameters:
        pmt    double       PM time interval (SSB, Julian years)
        eb     double[3]    SSB to observer (vector, au)
        eh     double[3]    Sun to observer (unit vector)
        em     double       distance from Sun to observer (au)
        v      double[3]    barycentric observer velocity (vector, c)
        bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
        bpn    double[3][3] bias-precession-nutation matrix
        along  double       longitude + s' (radians)
        xpl    double       polar motion xp wrt local meridian (radians)
        ypl    double       polar motion yp wrt local meridian (radians)
        sphi   double       sine of geodetic latitude
        cphi   double       cosine of geodetic latitude
        diurab double       magnitude of diurnal aberration vector
        eral   double       "local" Earth rotation angle (radians)
        refa   double       refraction constant A (radians)
        refb   double       refraction constant B (radians)

    Returned:
       ri,di   double    CIRS RA,Dec (radians)

    Notes:

    1) All the vectors are with respect to BCRS axes.

    2) Star data for an epoch other than J2000.0 (for example from the
       Hipparcos catalog, which has an epoch of J1991.25) will require a
       preliminary call to eraPmsafe before use.

    3) The proper motion in RA is dRA/dt rather than cos(Dec)*dRA/dt.

    Called:
       eraPmpx      proper motion and parallax
       eraLdsun     light deflection by the Sun
       eraAb        stellar aberration
       eraRxp       product of r-matrix and pv-vector
       eraC2s       p-vector to spherical
       eraAnp       normalize angle into range 0 to 2pi

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    rc_in = numpy.array(rc, dtype=numpy.double, order="C", copy=False, subok=True)
    dc_in = numpy.array(dc, dtype=numpy.double, order="C", copy=False, subok=True)
    pr_in = numpy.array(pr, dtype=numpy.double, order="C", copy=False, subok=True)
    pd_in = numpy.array(pd, dtype=numpy.double, order="C", copy=False, subok=True)
    px_in = numpy.array(px, dtype=numpy.double, order="C", copy=False, subok=True)
    rv_in = numpy.array(rv, dtype=numpy.double, order="C", copy=False, subok=True)
    astrom_in = numpy.array(astrom, dtype=dt_eraASTROM, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if rc_in.shape == tuple():
            rc_in = rc_in.reshape((1,) + rc_in.shape)
        else:
            make_outputs_scalar = False
        if dc_in.shape == tuple():
            dc_in = dc_in.reshape((1,) + dc_in.shape)
        else:
            make_outputs_scalar = False
        if pr_in.shape == tuple():
            pr_in = pr_in.reshape((1,) + pr_in.shape)
        else:
            make_outputs_scalar = False
        if pd_in.shape == tuple():
            pd_in = pd_in.reshape((1,) + pd_in.shape)
        else:
            make_outputs_scalar = False
        if px_in.shape == tuple():
            px_in = px_in.reshape((1,) + px_in.shape)
        else:
            make_outputs_scalar = False
        if rv_in.shape == tuple():
            rv_in = rv_in.reshape((1,) + rv_in.shape)
        else:
            make_outputs_scalar = False
        if astrom_in.shape == tuple():
            astrom_in = astrom_in.reshape((1,) + astrom_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), rc_in, dc_in, pr_in, pd_in, px_in, rv_in, astrom_in)
    ri_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    di_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [rc_in, dc_in, pr_in, pd_in, px_in, rv_in, astrom_in, ri_out, di_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*7 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._atciq(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(ri_out.shape) > 0 and ri_out.shape[0] == 1
        ri_out = ri_out.reshape(ri_out.shape[1:])
        assert len(di_out.shape) > 0 and di_out.shape[0] == 1
        di_out = di_out.reshape(di_out.shape[1:])

    return ri_out, di_out


def atciqn(rc, dc, pr, pd, px, rv, astrom, n, b):
    """
    Wrapper for ERFA function ``eraAtciqn``.

    Parameters
    ----------
    rc : double array
    dc : double array
    pr : double array
    pd : double array
    px : double array
    rv : double array
    astrom : eraASTROM array
    n : int array
    b : eraLDBODY array

    Returns
    -------
    ri : double array
    di : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a A t c i q n
    - - - - - - - - - -

    Quick ICRS, epoch J2000.0, to CIRS transformation, given precomputed
    star-independent astrometry parameters plus a list of light-
    deflecting bodies.

    Use of this function is appropriate when efficiency is important and
    where many star positions are to be transformed for one date.  The
    star-independent parameters can be obtained by calling one of the
    functions eraApci[13], eraApcg[13], eraApco[13] or eraApcs[13].


    If the only light-deflecting body to be taken into account is the
    Sun, the eraAtciq function can be used instead.  If in addition the
    parallax and proper motions are zero, the eraAtciqz function can be
    used.

    Given:
       rc,dc  double       ICRS RA,Dec at J2000.0 (radians)
       pr     double       RA proper motion (radians/year; Note 3)
       pd     double       Dec proper motion (radians/year)
       px     double       parallax (arcsec)
       rv     double       radial velocity (km/s, +ve if receding)
       astrom eraASTROM*   star-independent astrometry parameters:
        pmt    double       PM time interval (SSB, Julian years)
        eb     double[3]    SSB to observer (vector, au)
        eh     double[3]    Sun to observer (unit vector)
        em     double       distance from Sun to observer (au)
        v      double[3]    barycentric observer velocity (vector, c)
        bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
        bpn    double[3][3] bias-precession-nutation matrix
        along  double       longitude + s' (radians)
        xpl    double       polar motion xp wrt local meridian (radians)
        ypl    double       polar motion yp wrt local meridian (radians)
        sphi   double       sine of geodetic latitude
        cphi   double       cosine of geodetic latitude
        diurab double       magnitude of diurnal aberration vector
        eral   double       "local" Earth rotation angle (radians)
        refa   double       refraction constant A (radians)
        refb   double       refraction constant B (radians)
        n     int           number of bodies (Note 3)
        b     eraLDBODY[n] data for each of the n bodies (Notes 3,4):
         bm    double        mass of the body (solar masses, Note 5)
         dl    double        deflection limiter (Note 6)
         pv    [2][3]        barycentric PV of the body (au, au/day)

    Returned:
       ri,di   double    CIRS RA,Dec (radians)

    Notes:

    1) Star data for an epoch other than J2000.0 (for example from the
       Hipparcos catalog, which has an epoch of J1991.25) will require a
       preliminary call to eraPmsafe before use.

    2) The proper motion in RA is dRA/dt rather than cos(Dec)*dRA/dt.

    3) The struct b contains n entries, one for each body to be
       considered.  If n = 0, no gravitational light deflection will be
       applied, not even for the Sun.

    4) The struct b should include an entry for the Sun as well as for
       any planet or other body to be taken into account.  The entries
       should be in the order in which the light passes the body.

    5) In the entry in the b struct for body i, the mass parameter
       b[i].bm can, as required, be adjusted in order to allow for such
       effects as quadrupole field.

    6) The deflection limiter parameter b[i].dl is phi^2/2, where phi is
       the angular separation (in radians) between star and body at
       which limiting is applied.  As phi shrinks below the chosen
       threshold, the deflection is artificially reduced, reaching zero
       for phi = 0.   Example values suitable for a terrestrial
       observer, together with masses, are as follows:

          body i     b[i].bm        b[i].dl

          Sun        1.0            6e-6
          Jupiter    0.00095435     3e-9
          Saturn     0.00028574     3e-10

    7) For efficiency, validation of the contents of the b array is
       omitted.  The supplied masses must be greater than zero, the
       position and velocity vectors must be right, and the deflection
       limiter greater than zero.

    Called:
       eraPmpx      proper motion and parallax
       eraLdn       light deflection by n bodies
       eraAb        stellar aberration
       eraRxp       product of r-matrix and pv-vector
       eraC2s       p-vector to spherical
       eraAnp       normalize angle into range 0 to 2pi

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    rc_in = numpy.array(rc, dtype=numpy.double, order="C", copy=False, subok=True)
    dc_in = numpy.array(dc, dtype=numpy.double, order="C", copy=False, subok=True)
    pr_in = numpy.array(pr, dtype=numpy.double, order="C", copy=False, subok=True)
    pd_in = numpy.array(pd, dtype=numpy.double, order="C", copy=False, subok=True)
    px_in = numpy.array(px, dtype=numpy.double, order="C", copy=False, subok=True)
    rv_in = numpy.array(rv, dtype=numpy.double, order="C", copy=False, subok=True)
    astrom_in = numpy.array(astrom, dtype=dt_eraASTROM, order="C", copy=False, subok=True)
    n_in = numpy.array(n, dtype=numpy.intc, order="C", copy=False, subok=True)
    b_in = numpy.array(b, dtype=dt_eraLDBODY, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if rc_in.shape == tuple():
            rc_in = rc_in.reshape((1,) + rc_in.shape)
        else:
            make_outputs_scalar = False
        if dc_in.shape == tuple():
            dc_in = dc_in.reshape((1,) + dc_in.shape)
        else:
            make_outputs_scalar = False
        if pr_in.shape == tuple():
            pr_in = pr_in.reshape((1,) + pr_in.shape)
        else:
            make_outputs_scalar = False
        if pd_in.shape == tuple():
            pd_in = pd_in.reshape((1,) + pd_in.shape)
        else:
            make_outputs_scalar = False
        if px_in.shape == tuple():
            px_in = px_in.reshape((1,) + px_in.shape)
        else:
            make_outputs_scalar = False
        if rv_in.shape == tuple():
            rv_in = rv_in.reshape((1,) + rv_in.shape)
        else:
            make_outputs_scalar = False
        if astrom_in.shape == tuple():
            astrom_in = astrom_in.reshape((1,) + astrom_in.shape)
        else:
            make_outputs_scalar = False
        if n_in.shape == tuple():
            n_in = n_in.reshape((1,) + n_in.shape)
        else:
            make_outputs_scalar = False
        if b_in.shape == tuple():
            b_in = b_in.reshape((1,) + b_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), rc_in, dc_in, pr_in, pd_in, px_in, rv_in, astrom_in, n_in, b_in)
    ri_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    di_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [rc_in, dc_in, pr_in, pd_in, px_in, rv_in, astrom_in, n_in, b_in, ri_out, di_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*9 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._atciqn(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(ri_out.shape) > 0 and ri_out.shape[0] == 1
        ri_out = ri_out.reshape(ri_out.shape[1:])
        assert len(di_out.shape) > 0 and di_out.shape[0] == 1
        di_out = di_out.reshape(di_out.shape[1:])

    return ri_out, di_out


def atciqz(rc, dc, astrom):
    """
    Wrapper for ERFA function ``eraAtciqz``.

    Parameters
    ----------
    rc : double array
    dc : double array
    astrom : eraASTROM array

    Returns
    -------
    ri : double array
    di : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a A t c i q z
    - - - - - - - - - -

    Quick ICRS to CIRS transformation, given precomputed star-
    independent astrometry parameters, and assuming zero parallax and
    proper motion.

    Use of this function is appropriate when efficiency is important and
    where many star positions are to be transformed for one date.  The
    star-independent parameters can be obtained by calling one of the
    functions eraApci[13], eraApcg[13], eraApco[13] or eraApcs[13].

    The corresponding function for the case of non-zero parallax and
    proper motion is eraAtciq.

    Given:
       rc,dc  double     ICRS astrometric RA,Dec (radians)
       astrom eraASTROM* star-independent astrometry parameters:
        pmt    double       PM time interval (SSB, Julian years)
        eb     double[3]    SSB to observer (vector, au)
        eh     double[3]    Sun to observer (unit vector)
        em     double       distance from Sun to observer (au)
        v      double[3]    barycentric observer velocity (vector, c)
        bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
        bpn    double[3][3] bias-precession-nutation matrix
        along  double       longitude + s' (radians)
        xpl    double       polar motion xp wrt local meridian (radians)
        ypl    double       polar motion yp wrt local meridian (radians)
        sphi   double       sine of geodetic latitude
        cphi   double       cosine of geodetic latitude
        diurab double       magnitude of diurnal aberration vector
        eral   double       "local" Earth rotation angle (radians)
        refa   double       refraction constant A (radians)
        refb   double       refraction constant B (radians)

    Returned:
       ri,di  double     CIRS RA,Dec (radians)

    Note:

       All the vectors are with respect to BCRS axes.

    References:

       Urban, S. & Seidelmann, P. K. (eds), Explanatory Supplement to
       the Astronomical Almanac, 3rd ed., University Science Books
       (2013).

       Klioner, Sergei A., "A practical relativistic model for micro-
       arcsecond astrometry in space", Astr. J. 125, 1580-1597 (2003).

    Called:
       eraS2c       spherical coordinates to unit vector
       eraLdsun     light deflection due to Sun
       eraAb        stellar aberration
       eraRxp       product of r-matrix and p-vector
       eraC2s       p-vector to spherical
       eraAnp       normalize angle into range +/- pi

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    rc_in = numpy.array(rc, dtype=numpy.double, order="C", copy=False, subok=True)
    dc_in = numpy.array(dc, dtype=numpy.double, order="C", copy=False, subok=True)
    astrom_in = numpy.array(astrom, dtype=dt_eraASTROM, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if rc_in.shape == tuple():
            rc_in = rc_in.reshape((1,) + rc_in.shape)
        else:
            make_outputs_scalar = False
        if dc_in.shape == tuple():
            dc_in = dc_in.reshape((1,) + dc_in.shape)
        else:
            make_outputs_scalar = False
        if astrom_in.shape == tuple():
            astrom_in = astrom_in.reshape((1,) + astrom_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), rc_in, dc_in, astrom_in)
    ri_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    di_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [rc_in, dc_in, astrom_in, ri_out, di_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._atciqz(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(ri_out.shape) > 0 and ri_out.shape[0] == 1
        ri_out = ri_out.reshape(ri_out.shape[1:])
        assert len(di_out.shape) > 0 and di_out.shape[0] == 1
        di_out = di_out.reshape(di_out.shape[1:])

    return ri_out, di_out


def atco13(rc, dc, pr, pd, px, rv, utc1, utc2, dut1, elong, phi, hm, xp, yp, phpa, tc, rh, wl):
    """
    Wrapper for ERFA function ``eraAtco13``.

    Parameters
    ----------
    rc : double array
    dc : double array
    pr : double array
    pd : double array
    px : double array
    rv : double array
    utc1 : double array
    utc2 : double array
    dut1 : double array
    elong : double array
    phi : double array
    hm : double array
    xp : double array
    yp : double array
    phpa : double array
    tc : double array
    rh : double array
    wl : double array

    Returns
    -------
    aob : double array
    zob : double array
    hob : double array
    dob : double array
    rob : double array
    eo : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a A t c o 1 3
    - - - - - - - - - -

    ICRS RA,Dec to observed place.  The caller supplies UTC, site
    coordinates, ambient air conditions and observing wavelength.

    ERFA models are used for the Earth ephemeris, bias-precession-
    nutation, Earth orientation and refraction.

    Given:
       rc,dc  double   ICRS right ascension at J2000.0 (radians, Note 1)
       pr     double   RA proper motion (radians/year; Note 2)
       pd     double   Dec proper motion (radians/year)
       px     double   parallax (arcsec)
       rv     double   radial velocity (km/s, +ve if receding)
       utc1   double   UTC as a 2-part...
       utc2   double   ...quasi Julian Date (Notes 3-4)
       dut1   double   UT1-UTC (seconds, Note 5)
       elong  double   longitude (radians, east +ve, Note 6)
       phi    double   latitude (geodetic, radians, Note 6)
       hm     double   height above ellipsoid (m, geodetic, Notes 6,8)
       xp,yp  double   polar motion coordinates (radians, Note 7)
       phpa   double   pressure at the observer (hPa = mB, Note 8)
       tc     double   ambient temperature at the observer (deg C)
       rh     double   relative humidity at the observer (range 0-1)
       wl     double   wavelength (micrometers, Note 9)

    Returned:
       aob    double*  observed azimuth (radians: N=0,E=90)
       zob    double*  observed zenith distance (radians)
       hob    double*  observed hour angle (radians)
       dob    double*  observed declination (radians)
       rob    double*  observed right ascension (CIO-based, radians)
       eo     double*  equation of the origins (ERA-GST)

    Returned (function value):
              int      status: +1 = dubious year (Note 4)
                                0 = OK
                               -1 = unacceptable date

    Notes:

    1)  Star data for an epoch other than J2000.0 (for example from the
        Hipparcos catalog, which has an epoch of J1991.25) will require
        a preliminary call to eraPmsafe before use.

    2)  The proper motion in RA is dRA/dt rather than cos(Dec)*dRA/dt.

    3)  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.

        However, 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.

        Applications should use the function eraDtf2d to convert from
        calendar date and time of day into 2-part quasi Julian Date, as
        it implements the leap-second-ambiguity convention just
        described.

    4)  The warning status "dubious year" flags UTCs that predate the
        introduction of the time scale or that are too far in the
        future to be trusted.  See eraDat for further details.

    5)  UT1-UTC is tabulated in IERS bulletins.  It increases by exactly
        one second at the end of each positive UTC leap second,
        introduced in order to keep UT1-UTC within +/- 0.9s.  n.b. This
        practice is under review, and in the future UT1-UTC may grow
        essentially without limit.

    6)  The geographical coordinates are with respect to the ERFA_WGS84
        reference ellipsoid.  TAKE CARE WITH THE LONGITUDE SIGN:  the
        longitude required by the present function is east-positive
        (i.e. right-handed), in accordance with geographical convention.

    7)  The polar motion xp,yp can be obtained from IERS bulletins.  The
        values 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 0 and 90 deg west respectively.  For many
        applications, xp and yp can be set to zero.

    8)  If hm, the height above the ellipsoid of the observing station
        in meters, is not known but phpa, the pressure in hPa (=mB),
        is available, an adequate estimate of hm can be obtained from
        the expression

              hm = -29.3 * tsl * log ( phpa / 1013.25 );

        where tsl is the approximate sea-level air temperature in K
        (See Astrophysical Quantities, C.W.Allen, 3rd edition, section
        52).  Similarly, if the pressure phpa is not known, it can be
        estimated from the height of the observing station, hm, as
        follows:

              phpa = 1013.25 * exp ( -hm / ( 29.3 * tsl ) );

        Note, however, that the refraction is nearly proportional to
        the pressure and that an accurate phpa value is important for
        precise work.

    9)  The argument wl specifies the observing wavelength in
        micrometers.  The transition from optical to radio is assumed to
        occur at 100 micrometers (about 3000 GHz).

    10) The accuracy of the result is limited by the corrections for
        refraction, which use a simple A*tan(z) + B*tan^3(z) model.
        Providing the meteorological parameters are known accurately and
        there are no gross local effects, the predicted observed
        coordinates should be within 0.05 arcsec (optical) or 1 arcsec
        (radio) for a zenith distance of less than 70 degrees, better
        than 30 arcsec (optical or radio) at 85 degrees and better
        than 20 arcmin (optical) or 30 arcmin (radio) at the horizon.

        Without refraction, the complementary functions eraAtco13 and
        eraAtoc13 are self-consistent to better than 1 microarcsecond
        all over the celestial sphere.  With refraction included,
        consistency falls off at high zenith distances, but is still
        better than 0.05 arcsec at 85 degrees.

    11) "Observed" Az,ZD means the position that would be seen by a
        perfect geodetically aligned theodolite.  (Zenith distance is
        used rather than altitude in order to reflect the fact that no
        allowance is made for depression of the horizon.)  This is
        related to the observed HA,Dec via the standard rotation, using
        the geodetic latitude (corrected for polar motion), while the
        observed HA and RA are related simply through the Earth rotation
        angle and the site longitude.  "Observed" RA,Dec or HA,Dec thus
        means the position that would be seen by a perfect equatorial
        with its polar axis aligned to the Earth's axis of rotation.

    12) It is advisable to take great care with units, as even unlikely
        values of the input parameters are accepted and processed in
        accordance with the models used.

    Called:
       eraApco13    astrometry parameters, ICRS-observed, 2013
       eraAtciq     quick ICRS to CIRS
       eraAtioq     quick CIRS to observed

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    rc_in = numpy.array(rc, dtype=numpy.double, order="C", copy=False, subok=True)
    dc_in = numpy.array(dc, dtype=numpy.double, order="C", copy=False, subok=True)
    pr_in = numpy.array(pr, dtype=numpy.double, order="C", copy=False, subok=True)
    pd_in = numpy.array(pd, dtype=numpy.double, order="C", copy=False, subok=True)
    px_in = numpy.array(px, dtype=numpy.double, order="C", copy=False, subok=True)
    rv_in = numpy.array(rv, dtype=numpy.double, order="C", copy=False, subok=True)
    utc1_in = numpy.array(utc1, dtype=numpy.double, order="C", copy=False, subok=True)
    utc2_in = numpy.array(utc2, dtype=numpy.double, order="C", copy=False, subok=True)
    dut1_in = numpy.array(dut1, dtype=numpy.double, order="C", copy=False, subok=True)
    elong_in = numpy.array(elong, dtype=numpy.double, order="C", copy=False, subok=True)
    phi_in = numpy.array(phi, dtype=numpy.double, order="C", copy=False, subok=True)
    hm_in = numpy.array(hm, dtype=numpy.double, order="C", copy=False, subok=True)
    xp_in = numpy.array(xp, dtype=numpy.double, order="C", copy=False, subok=True)
    yp_in = numpy.array(yp, dtype=numpy.double, order="C", copy=False, subok=True)
    phpa_in = numpy.array(phpa, dtype=numpy.double, order="C", copy=False, subok=True)
    tc_in = numpy.array(tc, dtype=numpy.double, order="C", copy=False, subok=True)
    rh_in = numpy.array(rh, dtype=numpy.double, order="C", copy=False, subok=True)
    wl_in = numpy.array(wl, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if rc_in.shape == tuple():
            rc_in = rc_in.reshape((1,) + rc_in.shape)
        else:
            make_outputs_scalar = False
        if dc_in.shape == tuple():
            dc_in = dc_in.reshape((1,) + dc_in.shape)
        else:
            make_outputs_scalar = False
        if pr_in.shape == tuple():
            pr_in = pr_in.reshape((1,) + pr_in.shape)
        else:
            make_outputs_scalar = False
        if pd_in.shape == tuple():
            pd_in = pd_in.reshape((1,) + pd_in.shape)
        else:
            make_outputs_scalar = False
        if px_in.shape == tuple():
            px_in = px_in.reshape((1,) + px_in.shape)
        else:
            make_outputs_scalar = False
        if rv_in.shape == tuple():
            rv_in = rv_in.reshape((1,) + rv_in.shape)
        else:
            make_outputs_scalar = False
        if utc1_in.shape == tuple():
            utc1_in = utc1_in.reshape((1,) + utc1_in.shape)
        else:
            make_outputs_scalar = False
        if utc2_in.shape == tuple():
            utc2_in = utc2_in.reshape((1,) + utc2_in.shape)
        else:
            make_outputs_scalar = False
        if dut1_in.shape == tuple():
            dut1_in = dut1_in.reshape((1,) + dut1_in.shape)
        else:
            make_outputs_scalar = False
        if elong_in.shape == tuple():
            elong_in = elong_in.reshape((1,) + elong_in.shape)
        else:
            make_outputs_scalar = False
        if phi_in.shape == tuple():
            phi_in = phi_in.reshape((1,) + phi_in.shape)
        else:
            make_outputs_scalar = False
        if hm_in.shape == tuple():
            hm_in = hm_in.reshape((1,) + hm_in.shape)
        else:
            make_outputs_scalar = False
        if xp_in.shape == tuple():
            xp_in = xp_in.reshape((1,) + xp_in.shape)
        else:
            make_outputs_scalar = False
        if yp_in.shape == tuple():
            yp_in = yp_in.reshape((1,) + yp_in.shape)
        else:
            make_outputs_scalar = False
        if phpa_in.shape == tuple():
            phpa_in = phpa_in.reshape((1,) + phpa_in.shape)
        else:
            make_outputs_scalar = False
        if tc_in.shape == tuple():
            tc_in = tc_in.reshape((1,) + tc_in.shape)
        else:
            make_outputs_scalar = False
        if rh_in.shape == tuple():
            rh_in = rh_in.reshape((1,) + rh_in.shape)
        else:
            make_outputs_scalar = False
        if wl_in.shape == tuple():
            wl_in = wl_in.reshape((1,) + wl_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), rc_in, dc_in, pr_in, pd_in, px_in, rv_in, utc1_in, utc2_in, dut1_in, elong_in, phi_in, hm_in, xp_in, yp_in, phpa_in, tc_in, rh_in, wl_in)
    aob_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    zob_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    hob_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dob_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    rob_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    eo_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [rc_in, dc_in, pr_in, pd_in, px_in, rv_in, utc1_in, utc2_in, dut1_in, elong_in, phi_in, hm_in, xp_in, yp_in, phpa_in, tc_in, rh_in, wl_in, aob_out, zob_out, hob_out, dob_out, rob_out, eo_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*18 + [['readwrite']]*7
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._atco13(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'atco13')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(aob_out.shape) > 0 and aob_out.shape[0] == 1
        aob_out = aob_out.reshape(aob_out.shape[1:])
        assert len(zob_out.shape) > 0 and zob_out.shape[0] == 1
        zob_out = zob_out.reshape(zob_out.shape[1:])
        assert len(hob_out.shape) > 0 and hob_out.shape[0] == 1
        hob_out = hob_out.reshape(hob_out.shape[1:])
        assert len(dob_out.shape) > 0 and dob_out.shape[0] == 1
        dob_out = dob_out.reshape(dob_out.shape[1:])
        assert len(rob_out.shape) > 0 and rob_out.shape[0] == 1
        rob_out = rob_out.reshape(rob_out.shape[1:])
        assert len(eo_out.shape) > 0 and eo_out.shape[0] == 1
        eo_out = eo_out.reshape(eo_out.shape[1:])

    return aob_out, zob_out, hob_out, dob_out, rob_out, eo_out
STATUS_CODES['atco13'] = {0: 'OK', 1: 'dubious year (Note 4)', -1: 'unacceptable date'}



def atic13(ri, di, date1, date2):
    """
    Wrapper for ERFA function ``eraAtic13``.

    Parameters
    ----------
    ri : double array
    di : double array
    date1 : double array
    date2 : double array

    Returns
    -------
    rc : double array
    dc : double array
    eo : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a A t i c 1 3
    - - - - - - - - - -

    Transform star RA,Dec from geocentric CIRS to ICRS astrometric.

    Given:
       ri,di  double  CIRS geocentric RA,Dec (radians)
       date1  double  TDB as a 2-part...
       date2  double  ...Julian Date (Note 1)

    Returned:
       rc,dc  double  ICRS astrometric RA,Dec (radians)
       eo     double  equation of the origins (ERA-GST, Note 4)

    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.  For most
       applications of this function the choice will not be at all
       critical.

       TT can be used instead of TDB without any significant impact on
       accuracy.

    2) Iterative techniques are used for the aberration and light
       deflection corrections so that the functions eraAtic13 (or
       eraAticq) and eraAtci13 (or eraAtciq) are accurate inverses;
       even at the edge of the Sun's disk the discrepancy is only about
       1 nanoarcsecond.

    3) The available accuracy is better than 1 milliarcsecond, limited
       mainly by the precession-nutation model that is used, namely
       IAU 2000A/2006.  Very close to solar system bodies, additional
       errors of up to several milliarcseconds can occur because of
       unmodeled light deflection;  however, the Sun's contribution is
       taken into account, to first order.  The accuracy limitations of
       the ERFA function eraEpv00 (used to compute Earth position and
       velocity) can contribute aberration errors of up to
       5 microarcseconds.  Light deflection at the Sun's limb is
       uncertain at the 0.4 mas level.

    4) Should the transformation to (equinox based) J2000.0 mean place
       be required rather than (CIO based) ICRS coordinates, subtract the
       equation of the origins from the returned right ascension:
       RA = RI - EO.  (The eraAnp function can then be applied, as
       required, to keep the result in the conventional 0-2pi range.)

    Called:
       eraApci13    astrometry parameters, ICRS-CIRS, 2013
       eraAticq     quick CIRS to ICRS astrometric

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ri_in = numpy.array(ri, dtype=numpy.double, order="C", copy=False, subok=True)
    di_in = numpy.array(di, dtype=numpy.double, order="C", copy=False, subok=True)
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ri_in.shape == tuple():
            ri_in = ri_in.reshape((1,) + ri_in.shape)
        else:
            make_outputs_scalar = False
        if di_in.shape == tuple():
            di_in = di_in.reshape((1,) + di_in.shape)
        else:
            make_outputs_scalar = False
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ri_in, di_in, date1_in, date2_in)
    rc_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dc_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    eo_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ri_in, di_in, date1_in, date2_in, rc_out, dc_out, eo_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._atic13(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc_out.shape) > 0 and rc_out.shape[0] == 1
        rc_out = rc_out.reshape(rc_out.shape[1:])
        assert len(dc_out.shape) > 0 and dc_out.shape[0] == 1
        dc_out = dc_out.reshape(dc_out.shape[1:])
        assert len(eo_out.shape) > 0 and eo_out.shape[0] == 1
        eo_out = eo_out.reshape(eo_out.shape[1:])

    return rc_out, dc_out, eo_out


def aticq(ri, di, astrom):
    """
    Wrapper for ERFA function ``eraAticq``.

    Parameters
    ----------
    ri : double array
    di : double array
    astrom : eraASTROM array

    Returns
    -------
    rc : double array
    dc : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a A t i c q
    - - - - - - - - -

    Quick CIRS RA,Dec to ICRS astrometric place, given the star-
    independent astrometry parameters.

    Use of this function is appropriate when efficiency is important and
    where many star positions are all to be transformed for one date.
    The star-independent astrometry parameters can be obtained by
    calling one of the functions eraApci[13], eraApcg[13], eraApco[13]
    or eraApcs[13].

    Given:
       ri,di  double     CIRS RA,Dec (radians)
       astrom eraASTROM* star-independent astrometry parameters:
        pmt    double       PM time interval (SSB, Julian years)
        eb     double[3]    SSB to observer (vector, au)
        eh     double[3]    Sun to observer (unit vector)
        em     double       distance from Sun to observer (au)
        v      double[3]    barycentric observer velocity (vector, c)
        bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
        bpn    double[3][3] bias-precession-nutation matrix
        along  double       longitude + s' (radians)
        xpl    double       polar motion xp wrt local meridian (radians)
        ypl    double       polar motion yp wrt local meridian (radians)
        sphi   double       sine of geodetic latitude
        cphi   double       cosine of geodetic latitude
        diurab double       magnitude of diurnal aberration vector
        eral   double       "local" Earth rotation angle (radians)
        refa   double       refraction constant A (radians)
        refb   double       refraction constant B (radians)

    Returned:
       rc,dc  double     ICRS astrometric RA,Dec (radians)

    Notes:

    1) Only the Sun is taken into account in the light deflection
       correction.

    2) Iterative techniques are used for the aberration and light
       deflection corrections so that the functions eraAtic13 (or
       eraAticq) and eraAtci13 (or eraAtciq) are accurate inverses;
       even at the edge of the Sun's disk the discrepancy is only about
       1 nanoarcsecond.

    Called:
       eraS2c       spherical coordinates to unit vector
       eraTrxp      product of transpose of r-matrix and p-vector
       eraZp        zero p-vector
       eraAb        stellar aberration
       eraLdsun     light deflection by the Sun
       eraC2s       p-vector to spherical
       eraAnp       normalize angle into range +/- pi

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ri_in = numpy.array(ri, dtype=numpy.double, order="C", copy=False, subok=True)
    di_in = numpy.array(di, dtype=numpy.double, order="C", copy=False, subok=True)
    astrom_in = numpy.array(astrom, dtype=dt_eraASTROM, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ri_in.shape == tuple():
            ri_in = ri_in.reshape((1,) + ri_in.shape)
        else:
            make_outputs_scalar = False
        if di_in.shape == tuple():
            di_in = di_in.reshape((1,) + di_in.shape)
        else:
            make_outputs_scalar = False
        if astrom_in.shape == tuple():
            astrom_in = astrom_in.reshape((1,) + astrom_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ri_in, di_in, astrom_in)
    rc_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dc_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ri_in, di_in, astrom_in, rc_out, dc_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._aticq(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc_out.shape) > 0 and rc_out.shape[0] == 1
        rc_out = rc_out.reshape(rc_out.shape[1:])
        assert len(dc_out.shape) > 0 and dc_out.shape[0] == 1
        dc_out = dc_out.reshape(dc_out.shape[1:])

    return rc_out, dc_out


def aticqn(ri, di, astrom, n, b):
    """
    Wrapper for ERFA function ``eraAticqn``.

    Parameters
    ----------
    ri : double array
    di : double array
    astrom : eraASTROM array
    n : int array
    b : eraLDBODY array

    Returns
    -------
    rc : double array
    dc : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a A t i c q n
    - - - - - - - - -

    Quick CIRS to ICRS astrometric place transformation, given the star-
    independent astrometry parameters plus a list of light-deflecting
    bodies.

    Use of this function is appropriate when efficiency is important and
    where many star positions are all to be transformed for one date.
    The star-independent astrometry parameters can be obtained by
    calling one of the functions eraApci[13], eraApcg[13], eraApco[13]
    or eraApcs[13].
*
*  If the only light-deflecting body to be taken into account is the
*  Sun, the eraAticq function can be used instead.

    Given:
       ri,di  double      CIRS RA,Dec (radians)
       astrom eraASTROM*  star-independent astrometry parameters:
        pmt    double       PM time interval (SSB, Julian years)
        eb     double[3]    SSB to observer (vector, au)
        eh     double[3]    Sun to observer (unit vector)
        em     double       distance from Sun to observer (au)
        v      double[3]    barycentric observer velocity (vector, c)
        bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
        bpn    double[3][3] bias-precession-nutation matrix
        along  double       longitude + s' (radians)
        xpl    double       polar motion xp wrt local meridian (radians)
        ypl    double       polar motion yp wrt local meridian (radians)
        sphi   double       sine of geodetic latitude
        cphi   double       cosine of geodetic latitude
        diurab double       magnitude of diurnal aberration vector
        eral   double       "local" Earth rotation angle (radians)
        refa   double       refraction constant A (radians)
        refb   double       refraction constant B (radians)
        n     int           number of bodies (Note 3)
        b     eraLDBODY[n] data for each of the n bodies (Notes 3,4):
         bm    double       mass of the body (solar masses, Note 5)
         dl    double       deflection limiter (Note 6)
         pv    [2][3]       barycentric PV of the body (au, au/day)

    Returned:
       rc,dc  double     ICRS astrometric RA,Dec (radians)

    Notes:

    1) Iterative techniques are used for the aberration and light
       deflection corrections so that the functions eraAticqn and
       eraAtciqn are accurate inverses; even at the edge of the Sun's
       disk the discrepancy is only about 1 nanoarcsecond.

    2) If the only light-deflecting body to be taken into account is the
       Sun, the eraAticq function can be used instead.

    3) The struct b contains n entries, one for each body to be
       considered.  If n = 0, no gravitational light deflection will be
       applied, not even for the Sun.

    4) The struct b should include an entry for the Sun as well as for
       any planet or other body to be taken into account.  The entries
       should be in the order in which the light passes the body.

    5) In the entry in the b struct for body i, the mass parameter
       b[i].bm can, as required, be adjusted in order to allow for such
       effects as quadrupole field.

    6) The deflection limiter parameter b[i].dl is phi^2/2, where phi is
       the angular separation (in radians) between star and body at
       which limiting is applied.  As phi shrinks below the chosen
       threshold, the deflection is artificially reduced, reaching zero
       for phi = 0.   Example values suitable for a terrestrial
       observer, together with masses, are as follows:

          body i     b[i].bm        b[i].dl

          Sun        1.0            6e-6
          Jupiter    0.00095435     3e-9
          Saturn     0.00028574     3e-10

    7) For efficiency, validation of the contents of the b array is
       omitted.  The supplied masses must be greater than zero, the
       position and velocity vectors must be right, and the deflection
       limiter greater than zero.

    Called:
       eraS2c       spherical coordinates to unit vector
       eraTrxp      product of transpose of r-matrix and p-vector
       eraZp        zero p-vector
       eraAb        stellar aberration
       eraLdn       light deflection by n bodies
       eraC2s       p-vector to spherical
       eraAnp       normalize angle into range +/- pi

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ri_in = numpy.array(ri, dtype=numpy.double, order="C", copy=False, subok=True)
    di_in = numpy.array(di, dtype=numpy.double, order="C", copy=False, subok=True)
    astrom_in = numpy.array(astrom, dtype=dt_eraASTROM, order="C", copy=False, subok=True)
    n_in = numpy.array(n, dtype=numpy.intc, order="C", copy=False, subok=True)
    b_in = numpy.array(b, dtype=dt_eraLDBODY, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ri_in.shape == tuple():
            ri_in = ri_in.reshape((1,) + ri_in.shape)
        else:
            make_outputs_scalar = False
        if di_in.shape == tuple():
            di_in = di_in.reshape((1,) + di_in.shape)
        else:
            make_outputs_scalar = False
        if astrom_in.shape == tuple():
            astrom_in = astrom_in.reshape((1,) + astrom_in.shape)
        else:
            make_outputs_scalar = False
        if n_in.shape == tuple():
            n_in = n_in.reshape((1,) + n_in.shape)
        else:
            make_outputs_scalar = False
        if b_in.shape == tuple():
            b_in = b_in.reshape((1,) + b_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ri_in, di_in, astrom_in, n_in, b_in)
    rc_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dc_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ri_in, di_in, astrom_in, n_in, b_in, rc_out, dc_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*5 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._aticqn(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc_out.shape) > 0 and rc_out.shape[0] == 1
        rc_out = rc_out.reshape(rc_out.shape[1:])
        assert len(dc_out.shape) > 0 and dc_out.shape[0] == 1
        dc_out = dc_out.reshape(dc_out.shape[1:])

    return rc_out, dc_out


def atio13(ri, di, utc1, utc2, dut1, elong, phi, hm, xp, yp, phpa, tc, rh, wl):
    """
    Wrapper for ERFA function ``eraAtio13``.

    Parameters
    ----------
    ri : double array
    di : double array
    utc1 : double array
    utc2 : double array
    dut1 : double array
    elong : double array
    phi : double array
    hm : double array
    xp : double array
    yp : double array
    phpa : double array
    tc : double array
    rh : double array
    wl : double array

    Returns
    -------
    aob : double array
    zob : double array
    hob : double array
    dob : double array
    rob : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a A t i o 1 3
    - - - - - - - - - -

    CIRS RA,Dec to observed place.  The caller supplies UTC, site
    coordinates, ambient air conditions and observing wavelength.

    Given:
       ri     double   CIRS right ascension (CIO-based, radians)
       di     double   CIRS declination (radians)
       utc1   double   UTC as a 2-part...
       utc2   double   ...quasi Julian Date (Notes 1,2)
       dut1   double   UT1-UTC (seconds, Note 3)
       elong  double   longitude (radians, east +ve, Note 4)
       phi    double   geodetic latitude (radians, Note 4)
       hm     double   height above ellipsoid (m, geodetic Notes 4,6)
       xp,yp  double   polar motion coordinates (radians, Note 5)
       phpa   double   pressure at the observer (hPa = mB, Note 6)
       tc     double   ambient temperature at the observer (deg C)
       rh     double   relative humidity at the observer (range 0-1)
       wl     double   wavelength (micrometers, Note 7)

    Returned:
       aob    double*  observed azimuth (radians: N=0,E=90)
       zob    double*  observed zenith distance (radians)
       hob    double*  observed hour angle (radians)
       dob    double*  observed declination (radians)
       rob    double*  observed right ascension (CIO-based, radians)

    Returned (function value):
              int      status: +1 = dubious year (Note 2)
                                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.

        However, 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.

        Applications should use the function eraDtf2d to convert from
        calendar date and time of day into 2-part quasi Julian Date, as
        it implements the leap-second-ambiguity convention just
        described.

    2)  The warning status "dubious year" flags UTCs that predate the
        introduction of the time scale or that are too far in the
        future to be trusted.  See eraDat for further details.

    3)  UT1-UTC is tabulated in IERS bulletins.  It increases by exactly
        one second at the end of each positive UTC leap second,
        introduced in order to keep UT1-UTC within +/- 0.9s.  n.b. This
        practice is under review, and in the future UT1-UTC may grow
        essentially without limit.

    4)  The geographical coordinates are with respect to the ERFA_WGS84
        reference ellipsoid.  TAKE CARE WITH THE LONGITUDE SIGN:  the
        longitude required by the present function is east-positive
        (i.e. right-handed), in accordance with geographical convention.

    5)  The polar motion xp,yp can be obtained from IERS bulletins.  The
        values 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 0 and 90 deg west respectively.  For many
        applications, xp and yp can be set to zero.

    6)  If hm, the height above the ellipsoid of the observing station
        in meters, is not known but phpa, the pressure in hPa (=mB), is
        available, an adequate estimate of hm can be obtained from the
        expression

              hm = -29.3 * tsl * log ( phpa / 1013.25 );

        where tsl is the approximate sea-level air temperature in K
        (See Astrophysical Quantities, C.W.Allen, 3rd edition, section
        52).  Similarly, if the pressure phpa is not known, it can be
        estimated from the height of the observing station, hm, as
        follows:

              phpa = 1013.25 * exp ( -hm / ( 29.3 * tsl ) );

        Note, however, that the refraction is nearly proportional to
        the pressure and that an accurate phpa value is important for
        precise work.

    7)  The argument wl specifies the observing wavelength in
        micrometers.  The transition from optical to radio is assumed to
        occur at 100 micrometers (about 3000 GHz).

    8)  "Observed" Az,ZD means the position that would be seen by a
        perfect geodetically aligned theodolite.  (Zenith distance is
        used rather than altitude in order to reflect the fact that no
        allowance is made for depression of the horizon.)  This is
        related to the observed HA,Dec via the standard rotation, using
        the geodetic latitude (corrected for polar motion), while the
        observed HA and RA are related simply through the Earth rotation
        angle and the site longitude.  "Observed" RA,Dec or HA,Dec thus
        means the position that would be seen by a perfect equatorial
        with its polar axis aligned to the Earth's axis of rotation.

    9)  The accuracy of the result is limited by the corrections for
        refraction, which use a simple A*tan(z) + B*tan^3(z) model.
        Providing the meteorological parameters are known accurately and
        there are no gross local effects, the predicted astrometric
        coordinates should be within 0.05 arcsec (optical) or 1 arcsec
        (radio) for a zenith distance of less than 70 degrees, better
        than 30 arcsec (optical or radio) at 85 degrees and better
        than 20 arcmin (optical) or 30 arcmin (radio) at the horizon.

    10) The complementary functions eraAtio13 and eraAtoi13 are self-
        consistent to better than 1 microarcsecond all over the
        celestial sphere.

    11) It is advisable to take great care with units, as even unlikely
        values of the input parameters are accepted and processed in
        accordance with the models used.

    Called:
       eraApio13    astrometry parameters, CIRS-observed, 2013
       eraAtioq     quick CIRS to observed

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ri_in = numpy.array(ri, dtype=numpy.double, order="C", copy=False, subok=True)
    di_in = numpy.array(di, dtype=numpy.double, order="C", copy=False, subok=True)
    utc1_in = numpy.array(utc1, dtype=numpy.double, order="C", copy=False, subok=True)
    utc2_in = numpy.array(utc2, dtype=numpy.double, order="C", copy=False, subok=True)
    dut1_in = numpy.array(dut1, dtype=numpy.double, order="C", copy=False, subok=True)
    elong_in = numpy.array(elong, dtype=numpy.double, order="C", copy=False, subok=True)
    phi_in = numpy.array(phi, dtype=numpy.double, order="C", copy=False, subok=True)
    hm_in = numpy.array(hm, dtype=numpy.double, order="C", copy=False, subok=True)
    xp_in = numpy.array(xp, dtype=numpy.double, order="C", copy=False, subok=True)
    yp_in = numpy.array(yp, dtype=numpy.double, order="C", copy=False, subok=True)
    phpa_in = numpy.array(phpa, dtype=numpy.double, order="C", copy=False, subok=True)
    tc_in = numpy.array(tc, dtype=numpy.double, order="C", copy=False, subok=True)
    rh_in = numpy.array(rh, dtype=numpy.double, order="C", copy=False, subok=True)
    wl_in = numpy.array(wl, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ri_in.shape == tuple():
            ri_in = ri_in.reshape((1,) + ri_in.shape)
        else:
            make_outputs_scalar = False
        if di_in.shape == tuple():
            di_in = di_in.reshape((1,) + di_in.shape)
        else:
            make_outputs_scalar = False
        if utc1_in.shape == tuple():
            utc1_in = utc1_in.reshape((1,) + utc1_in.shape)
        else:
            make_outputs_scalar = False
        if utc2_in.shape == tuple():
            utc2_in = utc2_in.reshape((1,) + utc2_in.shape)
        else:
            make_outputs_scalar = False
        if dut1_in.shape == tuple():
            dut1_in = dut1_in.reshape((1,) + dut1_in.shape)
        else:
            make_outputs_scalar = False
        if elong_in.shape == tuple():
            elong_in = elong_in.reshape((1,) + elong_in.shape)
        else:
            make_outputs_scalar = False
        if phi_in.shape == tuple():
            phi_in = phi_in.reshape((1,) + phi_in.shape)
        else:
            make_outputs_scalar = False
        if hm_in.shape == tuple():
            hm_in = hm_in.reshape((1,) + hm_in.shape)
        else:
            make_outputs_scalar = False
        if xp_in.shape == tuple():
            xp_in = xp_in.reshape((1,) + xp_in.shape)
        else:
            make_outputs_scalar = False
        if yp_in.shape == tuple():
            yp_in = yp_in.reshape((1,) + yp_in.shape)
        else:
            make_outputs_scalar = False
        if phpa_in.shape == tuple():
            phpa_in = phpa_in.reshape((1,) + phpa_in.shape)
        else:
            make_outputs_scalar = False
        if tc_in.shape == tuple():
            tc_in = tc_in.reshape((1,) + tc_in.shape)
        else:
            make_outputs_scalar = False
        if rh_in.shape == tuple():
            rh_in = rh_in.reshape((1,) + rh_in.shape)
        else:
            make_outputs_scalar = False
        if wl_in.shape == tuple():
            wl_in = wl_in.reshape((1,) + wl_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ri_in, di_in, utc1_in, utc2_in, dut1_in, elong_in, phi_in, hm_in, xp_in, yp_in, phpa_in, tc_in, rh_in, wl_in)
    aob_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    zob_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    hob_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dob_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    rob_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ri_in, di_in, utc1_in, utc2_in, dut1_in, elong_in, phi_in, hm_in, xp_in, yp_in, phpa_in, tc_in, rh_in, wl_in, aob_out, zob_out, hob_out, dob_out, rob_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*14 + [['readwrite']]*6
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._atio13(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'atio13')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(aob_out.shape) > 0 and aob_out.shape[0] == 1
        aob_out = aob_out.reshape(aob_out.shape[1:])
        assert len(zob_out.shape) > 0 and zob_out.shape[0] == 1
        zob_out = zob_out.reshape(zob_out.shape[1:])
        assert len(hob_out.shape) > 0 and hob_out.shape[0] == 1
        hob_out = hob_out.reshape(hob_out.shape[1:])
        assert len(dob_out.shape) > 0 and dob_out.shape[0] == 1
        dob_out = dob_out.reshape(dob_out.shape[1:])
        assert len(rob_out.shape) > 0 and rob_out.shape[0] == 1
        rob_out = rob_out.reshape(rob_out.shape[1:])

    return aob_out, zob_out, hob_out, dob_out, rob_out
STATUS_CODES['atio13'] = {0: 'OK', 1: 'dubious year (Note 2)', -1: 'unacceptable date'}



def atioq(ri, di, astrom):
    """
    Wrapper for ERFA function ``eraAtioq``.

    Parameters
    ----------
    ri : double array
    di : double array
    astrom : eraASTROM array

    Returns
    -------
    aob : double array
    zob : double array
    hob : double array
    dob : double array
    rob : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a A t i o q
    - - - - - - - - -

    Quick CIRS to observed place transformation.

    Use of this function is appropriate when efficiency is important and
    where many star positions are all to be transformed for one date.
    The star-independent astrometry parameters can be obtained by
    calling eraApio[13] or eraApco[13].

    Given:
       ri     double     CIRS right ascension
       di     double     CIRS declination
       astrom eraASTROM* star-independent astrometry parameters:
        pmt    double       PM time interval (SSB, Julian years)
        eb     double[3]    SSB to observer (vector, au)
        eh     double[3]    Sun to observer (unit vector)
        em     double       distance from Sun to observer (au)
        v      double[3]    barycentric observer velocity (vector, c)
        bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
        bpn    double[3][3] bias-precession-nutation matrix
        along  double       longitude + s' (radians)
        xpl    double       polar motion xp wrt local meridian (radians)
        ypl    double       polar motion yp wrt local meridian (radians)
        sphi   double       sine of geodetic latitude
        cphi   double       cosine of geodetic latitude
        diurab double       magnitude of diurnal aberration vector
        eral   double       "local" Earth rotation angle (radians)
        refa   double       refraction constant A (radians)
        refb   double       refraction constant B (radians)

    Returned:
       aob    double*    observed azimuth (radians: N=0,E=90)
       zob    double*    observed zenith distance (radians)
       hob    double*    observed hour angle (radians)
       dob    double*    observed declination (radians)
       rob    double*    observed right ascension (CIO-based, radians)

    Notes:

    1) This function returns zenith distance rather than altitude in
       order to reflect the fact that no allowance is made for
       depression of the horizon.

    2) The accuracy of the result is limited by the corrections for
       refraction, which use a simple A*tan(z) + B*tan^3(z) model.
       Providing the meteorological parameters are known accurately and
       there are no gross local effects, the predicted observed
       coordinates should be within 0.05 arcsec (optical) or 1 arcsec
       (radio) for a zenith distance of less than 70 degrees, better
       than 30 arcsec (optical or radio) at 85 degrees and better
       than 20 arcmin (optical) or 30 arcmin (radio) at the horizon.

       Without refraction, the complementary functions eraAtioq and
       eraAtoiq are self-consistent to better than 1 microarcsecond all
       over the celestial sphere.  With refraction included, consistency
       falls off at high zenith distances, but is still better than
       0.05 arcsec at 85 degrees.

    3) It is advisable to take great care with units, as even unlikely
       values of the input parameters are accepted and processed in
       accordance with the models used.

    4) The CIRS RA,Dec is obtained from a star catalog mean place by
       allowing for space motion, parallax, the Sun's gravitational lens
       effect, annual aberration and precession-nutation.  For star
       positions in the ICRS, these effects can be applied by means of
       the eraAtci13 (etc.) functions.  Starting from classical "mean
       place" systems, additional transformations will be needed first.

    5) "Observed" Az,El means the position that would be seen by a
       perfect geodetically aligned theodolite.  This is obtained from
       the CIRS RA,Dec by allowing for Earth orientation and diurnal
       aberration, rotating from equator to horizon coordinates, and
       then adjusting for refraction.  The HA,Dec is obtained by
       rotating back into equatorial coordinates, and is the position
       that would be seen by a perfect equatorial with its polar axis
       aligned to the Earth's axis of rotation.  Finally, the RA is
       obtained by subtracting the HA from the local ERA.

    6) The star-independent CIRS-to-observed-place parameters in ASTROM
       may be computed with eraApio[13] or eraApco[13].  If nothing has
       changed significantly except the time, eraAper[13] may be used to
       perform the requisite adjustment to the astrom structure.

    Called:
       eraS2c       spherical coordinates to unit vector
       eraC2s       p-vector to spherical
       eraAnp       normalize angle into range 0 to 2pi

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ri_in = numpy.array(ri, dtype=numpy.double, order="C", copy=False, subok=True)
    di_in = numpy.array(di, dtype=numpy.double, order="C", copy=False, subok=True)
    astrom_in = numpy.array(astrom, dtype=dt_eraASTROM, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ri_in.shape == tuple():
            ri_in = ri_in.reshape((1,) + ri_in.shape)
        else:
            make_outputs_scalar = False
        if di_in.shape == tuple():
            di_in = di_in.reshape((1,) + di_in.shape)
        else:
            make_outputs_scalar = False
        if astrom_in.shape == tuple():
            astrom_in = astrom_in.reshape((1,) + astrom_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ri_in, di_in, astrom_in)
    aob_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    zob_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    hob_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dob_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    rob_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ri_in, di_in, astrom_in, aob_out, zob_out, hob_out, dob_out, rob_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*5
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._atioq(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(aob_out.shape) > 0 and aob_out.shape[0] == 1
        aob_out = aob_out.reshape(aob_out.shape[1:])
        assert len(zob_out.shape) > 0 and zob_out.shape[0] == 1
        zob_out = zob_out.reshape(zob_out.shape[1:])
        assert len(hob_out.shape) > 0 and hob_out.shape[0] == 1
        hob_out = hob_out.reshape(hob_out.shape[1:])
        assert len(dob_out.shape) > 0 and dob_out.shape[0] == 1
        dob_out = dob_out.reshape(dob_out.shape[1:])
        assert len(rob_out.shape) > 0 and rob_out.shape[0] == 1
        rob_out = rob_out.reshape(rob_out.shape[1:])

    return aob_out, zob_out, hob_out, dob_out, rob_out


def atoc13(type, ob1, ob2, utc1, utc2, dut1, elong, phi, hm, xp, yp, phpa, tc, rh, wl):
    """
    Wrapper for ERFA function ``eraAtoc13``.

    Parameters
    ----------
    type : const char array
    ob1 : double array
    ob2 : double array
    utc1 : double array
    utc2 : double array
    dut1 : double array
    elong : double array
    phi : double array
    hm : double array
    xp : double array
    yp : double array
    phpa : double array
    tc : double array
    rh : double array
    wl : double array

    Returns
    -------
    rc : double array
    dc : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a A t o c 1 3
    - - - - - - - - - -

    Observed place at a groundbased site to to ICRS astrometric RA,Dec.
    The caller supplies UTC, site coordinates, ambient air conditions
    and observing wavelength.

    Given:
       type   char[]   type of coordinates - "R", "H" or "A" (Notes 1,2)
       ob1    double   observed Az, HA or RA (radians; Az is N=0,E=90)
       ob2    double   observed ZD or Dec (radians)
       utc1   double   UTC as a 2-part...
       utc2   double   ...quasi Julian Date (Notes 3,4)
       dut1   double   UT1-UTC (seconds, Note 5)
       elong  double   longitude (radians, east +ve, Note 6)
       phi    double   geodetic latitude (radians, Note 6)
       hm     double   height above ellipsoid (m, geodetic Notes 6,8)
       xp,yp  double   polar motion coordinates (radians, Note 7)
       phpa   double   pressure at the observer (hPa = mB, Note 8)
       tc     double   ambient temperature at the observer (deg C)
       rh     double   relative humidity at the observer (range 0-1)
       wl     double   wavelength (micrometers, Note 9)

    Returned:
       rc,dc  double   ICRS astrometric RA,Dec (radians)

    Returned (function value):
              int      status: +1 = dubious year (Note 4)
                                0 = OK
                               -1 = unacceptable date

    Notes:

    1)  "Observed" Az,ZD means the position that would be seen by a
        perfect geodetically aligned theodolite.  (Zenith distance is
        used rather than altitude in order to reflect the fact that no
        allowance is made for depression of the horizon.)  This is
        related to the observed HA,Dec via the standard rotation, using
        the geodetic latitude (corrected for polar motion), while the
        observed HA and RA are related simply through the Earth rotation
        angle and the site longitude.  "Observed" RA,Dec or HA,Dec thus
        means the position that would be seen by a perfect equatorial
        with its polar axis aligned to the Earth's axis of rotation.

    2)  Only the first character of the type argument is significant.
        "R" or "r" indicates that ob1 and ob2 are the observed right
        ascension and declination;  "H" or "h" indicates that they are
        hour angle (west +ve) and declination;  anything else ("A" or
        "a" is recommended) indicates that ob1 and ob2 are azimuth
        (north zero, east 90 deg) and zenith distance.

    3)  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.

        However, 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.

        Applications should use the function eraDtf2d to convert from
        calendar date and time of day into 2-part quasi Julian Date, as
        it implements the leap-second-ambiguity convention just
        described.

    4)  The warning status "dubious year" flags UTCs that predate the
        introduction of the time scale or that are too far in the
        future to be trusted.  See eraDat for further details.

    5)  UT1-UTC is tabulated in IERS bulletins.  It increases by exactly
        one second at the end of each positive UTC leap second,
        introduced in order to keep UT1-UTC within +/- 0.9s.  n.b. This
        practice is under review, and in the future UT1-UTC may grow
        essentially without limit.

    6)  The geographical coordinates are with respect to the ERFA_WGS84
        reference ellipsoid.  TAKE CARE WITH THE LONGITUDE SIGN:  the
        longitude required by the present function is east-positive
        (i.e. right-handed), in accordance with geographical convention.

    7)  The polar motion xp,yp can be obtained from IERS bulletins.  The
        values 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 0 and 90 deg west respectively.  For many
        applications, xp and yp can be set to zero.

    8)  If hm, the height above the ellipsoid of the observing station
        in meters, is not known but phpa, the pressure in hPa (=mB), is
        available, an adequate estimate of hm can be obtained from the
        expression

              hm = -29.3 * tsl * log ( phpa / 1013.25 );

        where tsl is the approximate sea-level air temperature in K
        (See Astrophysical Quantities, C.W.Allen, 3rd edition, section
        52).  Similarly, if the pressure phpa is not known, it can be
        estimated from the height of the observing station, hm, as
        follows:

              phpa = 1013.25 * exp ( -hm / ( 29.3 * tsl ) );

        Note, however, that the refraction is nearly proportional to
        the pressure and that an accurate phpa value is important for
        precise work.

    9)  The argument wl specifies the observing wavelength in
        micrometers.  The transition from optical to radio is assumed to
        occur at 100 micrometers (about 3000 GHz).

    10) The accuracy of the result is limited by the corrections for
        refraction, which use a simple A*tan(z) + B*tan^3(z) model.
        Providing the meteorological parameters are known accurately and
        there are no gross local effects, the predicted astrometric
        coordinates should be within 0.05 arcsec (optical) or 1 arcsec
        (radio) for a zenith distance of less than 70 degrees, better
        than 30 arcsec (optical or radio) at 85 degrees and better
        than 20 arcmin (optical) or 30 arcmin (radio) at the horizon.

        Without refraction, the complementary functions eraAtco13 and
        eraAtoc13 are self-consistent to better than 1 microarcsecond
        all over the celestial sphere.  With refraction included,
        consistency falls off at high zenith distances, but is still
        better than 0.05 arcsec at 85 degrees.

    11) It is advisable to take great care with units, as even unlikely
        values of the input parameters are accepted and processed in
        accordance with the models used.

    Called:
       eraApco13    astrometry parameters, ICRS-observed
       eraAtoiq     quick observed to CIRS
       eraAticq     quick CIRS to ICRS

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    type_in = numpy.array(type, dtype=numpy.dtype('S16'), order="C", copy=False, subok=True)
    ob1_in = numpy.array(ob1, dtype=numpy.double, order="C", copy=False, subok=True)
    ob2_in = numpy.array(ob2, dtype=numpy.double, order="C", copy=False, subok=True)
    utc1_in = numpy.array(utc1, dtype=numpy.double, order="C", copy=False, subok=True)
    utc2_in = numpy.array(utc2, dtype=numpy.double, order="C", copy=False, subok=True)
    dut1_in = numpy.array(dut1, dtype=numpy.double, order="C", copy=False, subok=True)
    elong_in = numpy.array(elong, dtype=numpy.double, order="C", copy=False, subok=True)
    phi_in = numpy.array(phi, dtype=numpy.double, order="C", copy=False, subok=True)
    hm_in = numpy.array(hm, dtype=numpy.double, order="C", copy=False, subok=True)
    xp_in = numpy.array(xp, dtype=numpy.double, order="C", copy=False, subok=True)
    yp_in = numpy.array(yp, dtype=numpy.double, order="C", copy=False, subok=True)
    phpa_in = numpy.array(phpa, dtype=numpy.double, order="C", copy=False, subok=True)
    tc_in = numpy.array(tc, dtype=numpy.double, order="C", copy=False, subok=True)
    rh_in = numpy.array(rh, dtype=numpy.double, order="C", copy=False, subok=True)
    wl_in = numpy.array(wl, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if type_in.shape == tuple():
            type_in = type_in.reshape((1,) + type_in.shape)
        else:
            make_outputs_scalar = False
        if ob1_in.shape == tuple():
            ob1_in = ob1_in.reshape((1,) + ob1_in.shape)
        else:
            make_outputs_scalar = False
        if ob2_in.shape == tuple():
            ob2_in = ob2_in.reshape((1,) + ob2_in.shape)
        else:
            make_outputs_scalar = False
        if utc1_in.shape == tuple():
            utc1_in = utc1_in.reshape((1,) + utc1_in.shape)
        else:
            make_outputs_scalar = False
        if utc2_in.shape == tuple():
            utc2_in = utc2_in.reshape((1,) + utc2_in.shape)
        else:
            make_outputs_scalar = False
        if dut1_in.shape == tuple():
            dut1_in = dut1_in.reshape((1,) + dut1_in.shape)
        else:
            make_outputs_scalar = False
        if elong_in.shape == tuple():
            elong_in = elong_in.reshape((1,) + elong_in.shape)
        else:
            make_outputs_scalar = False
        if phi_in.shape == tuple():
            phi_in = phi_in.reshape((1,) + phi_in.shape)
        else:
            make_outputs_scalar = False
        if hm_in.shape == tuple():
            hm_in = hm_in.reshape((1,) + hm_in.shape)
        else:
            make_outputs_scalar = False
        if xp_in.shape == tuple():
            xp_in = xp_in.reshape((1,) + xp_in.shape)
        else:
            make_outputs_scalar = False
        if yp_in.shape == tuple():
            yp_in = yp_in.reshape((1,) + yp_in.shape)
        else:
            make_outputs_scalar = False
        if phpa_in.shape == tuple():
            phpa_in = phpa_in.reshape((1,) + phpa_in.shape)
        else:
            make_outputs_scalar = False
        if tc_in.shape == tuple():
            tc_in = tc_in.reshape((1,) + tc_in.shape)
        else:
            make_outputs_scalar = False
        if rh_in.shape == tuple():
            rh_in = rh_in.reshape((1,) + rh_in.shape)
        else:
            make_outputs_scalar = False
        if wl_in.shape == tuple():
            wl_in = wl_in.reshape((1,) + wl_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), type_in, ob1_in, ob2_in, utc1_in, utc2_in, dut1_in, elong_in, phi_in, hm_in, xp_in, yp_in, phpa_in, tc_in, rh_in, wl_in)
    rc_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dc_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [type_in, ob1_in, ob2_in, utc1_in, utc2_in, dut1_in, elong_in, phi_in, hm_in, xp_in, yp_in, phpa_in, tc_in, rh_in, wl_in, rc_out, dc_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*15 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._atoc13(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'atoc13')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc_out.shape) > 0 and rc_out.shape[0] == 1
        rc_out = rc_out.reshape(rc_out.shape[1:])
        assert len(dc_out.shape) > 0 and dc_out.shape[0] == 1
        dc_out = dc_out.reshape(dc_out.shape[1:])

    return rc_out, dc_out
STATUS_CODES['atoc13'] = {0: 'OK', 1: 'dubious year (Note 4)', -1: 'unacceptable date'}



def atoi13(type, ob1, ob2, utc1, utc2, dut1, elong, phi, hm, xp, yp, phpa, tc, rh, wl):
    """
    Wrapper for ERFA function ``eraAtoi13``.

    Parameters
    ----------
    type : const char array
    ob1 : double array
    ob2 : double array
    utc1 : double array
    utc2 : double array
    dut1 : double array
    elong : double array
    phi : double array
    hm : double array
    xp : double array
    yp : double array
    phpa : double array
    tc : double array
    rh : double array
    wl : double array

    Returns
    -------
    ri : double array
    di : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a A t o i 1 3
    - - - - - - - - - -

    Observed place to CIRS.  The caller supplies UTC, site coordinates,
    ambient air conditions and observing wavelength.

    Given:
       type   char[]   type of coordinates - "R", "H" or "A" (Notes 1,2)
       ob1    double   observed Az, HA or RA (radians; Az is N=0,E=90)
       ob2    double   observed ZD or Dec (radians)
       utc1   double   UTC as a 2-part...
       utc2   double   ...quasi Julian Date (Notes 3,4)
       dut1   double   UT1-UTC (seconds, Note 5)
       elong  double   longitude (radians, east +ve, Note 6)
       phi    double   geodetic latitude (radians, Note 6)
       hm     double   height above the ellipsoid (meters, Notes 6,8)
       xp,yp  double   polar motion coordinates (radians, Note 7)
       phpa   double   pressure at the observer (hPa = mB, Note 8)
       tc     double   ambient temperature at the observer (deg C)
       rh     double   relative humidity at the observer (range 0-1)
       wl     double   wavelength (micrometers, Note 9)

    Returned:
       ri     double*  CIRS right ascension (CIO-based, radians)
       di     double*  CIRS declination (radians)

    Returned (function value):
              int      status: +1 = dubious year (Note 2)
                                0 = OK
                               -1 = unacceptable date

    Notes:

    1)  "Observed" Az,ZD means the position that would be seen by a
        perfect geodetically aligned theodolite.  (Zenith distance is
        used rather than altitude in order to reflect the fact that no
        allowance is made for depression of the horizon.)  This is
        related to the observed HA,Dec via the standard rotation, using
        the geodetic latitude (corrected for polar motion), while the
        observed HA and RA are related simply through the Earth rotation
        angle and the site longitude.  "Observed" RA,Dec or HA,Dec thus
        means the position that would be seen by a perfect equatorial
        with its polar axis aligned to the Earth's axis of rotation.

    2)  Only the first character of the type argument is significant.
        "R" or "r" indicates that ob1 and ob2 are the observed right
        ascension and declination;  "H" or "h" indicates that they are
        hour angle (west +ve) and declination;  anything else ("A" or
        "a" is recommended) indicates that ob1 and ob2 are azimuth
        (north zero, east 90 deg) and zenith distance.

    3)  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.

        However, 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.

        Applications should use the function eraDtf2d to convert from
        calendar date and time of day into 2-part quasi Julian Date, as
        it implements the leap-second-ambiguity convention just
        described.

    4)  The warning status "dubious year" flags UTCs that predate the
        introduction of the time scale or that are too far in the
        future to be trusted.  See eraDat for further details.

    5)  UT1-UTC is tabulated in IERS bulletins.  It increases by exactly
        one second at the end of each positive UTC leap second,
        introduced in order to keep UT1-UTC within +/- 0.9s.  n.b. This
        practice is under review, and in the future UT1-UTC may grow
        essentially without limit.

    6)  The geographical coordinates are with respect to the ERFA_WGS84
        reference ellipsoid.  TAKE CARE WITH THE LONGITUDE SIGN:  the
        longitude required by the present function is east-positive
        (i.e. right-handed), in accordance with geographical convention.

    7)  The polar motion xp,yp can be obtained from IERS bulletins.  The
        values 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 0 and 90 deg west respectively.  For many
        applications, xp and yp can be set to zero.

    8)  If hm, the height above the ellipsoid of the observing station
        in meters, is not known but phpa, the pressure in hPa (=mB), is
        available, an adequate estimate of hm can be obtained from the
        expression

              hm = -29.3 * tsl * log ( phpa / 1013.25 );

        where tsl is the approximate sea-level air temperature in K
        (See Astrophysical Quantities, C.W.Allen, 3rd edition, section
        52).  Similarly, if the pressure phpa is not known, it can be
        estimated from the height of the observing station, hm, as
        follows:

              phpa = 1013.25 * exp ( -hm / ( 29.3 * tsl ) );

        Note, however, that the refraction is nearly proportional to
        the pressure and that an accurate phpa value is important for
        precise work.

    9)  The argument wl specifies the observing wavelength in
        micrometers.  The transition from optical to radio is assumed to
        occur at 100 micrometers (about 3000 GHz).

    10) The accuracy of the result is limited by the corrections for
        refraction, which use a simple A*tan(z) + B*tan^3(z) model.
        Providing the meteorological parameters are known accurately and
        there are no gross local effects, the predicted astrometric
        coordinates should be within 0.05 arcsec (optical) or 1 arcsec
        (radio) for a zenith distance of less than 70 degrees, better
        than 30 arcsec (optical or radio) at 85 degrees and better
        than 20 arcmin (optical) or 30 arcmin (radio) at the horizon.

        Without refraction, the complementary functions eraAtio13 and
        eraAtoi13 are self-consistent to better than 1 microarcsecond
        all over the celestial sphere.  With refraction included,
        consistency falls off at high zenith distances, but is still
        better than 0.05 arcsec at 85 degrees.

    12) It is advisable to take great care with units, as even unlikely
        values of the input parameters are accepted and processed in
        accordance with the models used.

    Called:
       eraApio13    astrometry parameters, CIRS-observed, 2013
       eraAtoiq     quick observed to CIRS

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    type_in = numpy.array(type, dtype=numpy.dtype('S16'), order="C", copy=False, subok=True)
    ob1_in = numpy.array(ob1, dtype=numpy.double, order="C", copy=False, subok=True)
    ob2_in = numpy.array(ob2, dtype=numpy.double, order="C", copy=False, subok=True)
    utc1_in = numpy.array(utc1, dtype=numpy.double, order="C", copy=False, subok=True)
    utc2_in = numpy.array(utc2, dtype=numpy.double, order="C", copy=False, subok=True)
    dut1_in = numpy.array(dut1, dtype=numpy.double, order="C", copy=False, subok=True)
    elong_in = numpy.array(elong, dtype=numpy.double, order="C", copy=False, subok=True)
    phi_in = numpy.array(phi, dtype=numpy.double, order="C", copy=False, subok=True)
    hm_in = numpy.array(hm, dtype=numpy.double, order="C", copy=False, subok=True)
    xp_in = numpy.array(xp, dtype=numpy.double, order="C", copy=False, subok=True)
    yp_in = numpy.array(yp, dtype=numpy.double, order="C", copy=False, subok=True)
    phpa_in = numpy.array(phpa, dtype=numpy.double, order="C", copy=False, subok=True)
    tc_in = numpy.array(tc, dtype=numpy.double, order="C", copy=False, subok=True)
    rh_in = numpy.array(rh, dtype=numpy.double, order="C", copy=False, subok=True)
    wl_in = numpy.array(wl, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if type_in.shape == tuple():
            type_in = type_in.reshape((1,) + type_in.shape)
        else:
            make_outputs_scalar = False
        if ob1_in.shape == tuple():
            ob1_in = ob1_in.reshape((1,) + ob1_in.shape)
        else:
            make_outputs_scalar = False
        if ob2_in.shape == tuple():
            ob2_in = ob2_in.reshape((1,) + ob2_in.shape)
        else:
            make_outputs_scalar = False
        if utc1_in.shape == tuple():
            utc1_in = utc1_in.reshape((1,) + utc1_in.shape)
        else:
            make_outputs_scalar = False
        if utc2_in.shape == tuple():
            utc2_in = utc2_in.reshape((1,) + utc2_in.shape)
        else:
            make_outputs_scalar = False
        if dut1_in.shape == tuple():
            dut1_in = dut1_in.reshape((1,) + dut1_in.shape)
        else:
            make_outputs_scalar = False
        if elong_in.shape == tuple():
            elong_in = elong_in.reshape((1,) + elong_in.shape)
        else:
            make_outputs_scalar = False
        if phi_in.shape == tuple():
            phi_in = phi_in.reshape((1,) + phi_in.shape)
        else:
            make_outputs_scalar = False
        if hm_in.shape == tuple():
            hm_in = hm_in.reshape((1,) + hm_in.shape)
        else:
            make_outputs_scalar = False
        if xp_in.shape == tuple():
            xp_in = xp_in.reshape((1,) + xp_in.shape)
        else:
            make_outputs_scalar = False
        if yp_in.shape == tuple():
            yp_in = yp_in.reshape((1,) + yp_in.shape)
        else:
            make_outputs_scalar = False
        if phpa_in.shape == tuple():
            phpa_in = phpa_in.reshape((1,) + phpa_in.shape)
        else:
            make_outputs_scalar = False
        if tc_in.shape == tuple():
            tc_in = tc_in.reshape((1,) + tc_in.shape)
        else:
            make_outputs_scalar = False
        if rh_in.shape == tuple():
            rh_in = rh_in.reshape((1,) + rh_in.shape)
        else:
            make_outputs_scalar = False
        if wl_in.shape == tuple():
            wl_in = wl_in.reshape((1,) + wl_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), type_in, ob1_in, ob2_in, utc1_in, utc2_in, dut1_in, elong_in, phi_in, hm_in, xp_in, yp_in, phpa_in, tc_in, rh_in, wl_in)
    ri_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    di_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [type_in, ob1_in, ob2_in, utc1_in, utc2_in, dut1_in, elong_in, phi_in, hm_in, xp_in, yp_in, phpa_in, tc_in, rh_in, wl_in, ri_out, di_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*15 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._atoi13(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'atoi13')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(ri_out.shape) > 0 and ri_out.shape[0] == 1
        ri_out = ri_out.reshape(ri_out.shape[1:])
        assert len(di_out.shape) > 0 and di_out.shape[0] == 1
        di_out = di_out.reshape(di_out.shape[1:])

    return ri_out, di_out
STATUS_CODES['atoi13'] = {0: 'OK', 1: 'dubious year (Note 2)', -1: 'unacceptable date'}



def atoiq(type, ob1, ob2, astrom):
    """
    Wrapper for ERFA function ``eraAtoiq``.

    Parameters
    ----------
    type : const char array
    ob1 : double array
    ob2 : double array
    astrom : eraASTROM array

    Returns
    -------
    ri : double array
    di : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a A t o i q
    - - - - - - - - -

    Quick observed place to CIRS, given the star-independent astrometry
    parameters.

    Use of this function is appropriate when efficiency is important and
    where many star positions are all to be transformed for one date.
    The star-independent astrometry parameters can be obtained by
    calling eraApio[13] or eraApco[13].

    Given:
       type   char[]     type of coordinates: "R", "H" or "A" (Note 1)
       ob1    double     observed Az, HA or RA (radians; Az is N=0,E=90)
       ob2    double     observed ZD or Dec (radians)
       astrom eraASTROM* star-independent astrometry parameters:
        pmt    double       PM time interval (SSB, Julian years)
        eb     double[3]    SSB to observer (vector, au)
        eh     double[3]    Sun to observer (unit vector)
        em     double       distance from Sun to observer (au)
        v      double[3]    barycentric observer velocity (vector, c)
        bm1    double       sqrt(1-|v|^2): reciprocal of Lorenz factor
        bpn    double[3][3] bias-precession-nutation matrix
        along  double       longitude + s' (radians)
        xpl    double       polar motion xp wrt local meridian (radians)
        ypl    double       polar motion yp wrt local meridian (radians)
        sphi   double       sine of geodetic latitude
        cphi   double       cosine of geodetic latitude
        diurab double       magnitude of diurnal aberration vector
        eral   double       "local" Earth rotation angle (radians)
        refa   double       refraction constant A (radians)
        refb   double       refraction constant B (radians)

    Returned:
       ri     double*    CIRS right ascension (CIO-based, radians)
       di     double*    CIRS declination (radians)

    Notes:

    1) "Observed" Az,El means the position that would be seen by a
       perfect geodetically aligned theodolite.  This is related to
       the observed HA,Dec via the standard rotation, using the geodetic
       latitude (corrected for polar motion), while the observed HA and
       RA are related simply through the Earth rotation angle and the
       site longitude.  "Observed" RA,Dec or HA,Dec thus means the
       position that would be seen by a perfect equatorial with its
       polar axis aligned to the Earth's axis of rotation.  By removing
       from the observed place the effects of atmospheric refraction and
       diurnal aberration, the CIRS RA,Dec is obtained.

    2) Only the first character of the type argument is significant.
       "R" or "r" indicates that ob1 and ob2 are the observed right
       ascension and declination;  "H" or "h" indicates that they are
       hour angle (west +ve) and declination;  anything else ("A" or
       "a" is recommended) indicates that ob1 and ob2 are azimuth (north
       zero, east 90 deg) and zenith distance.  (Zenith distance is used
       rather than altitude in order to reflect the fact that no
       allowance is made for depression of the horizon.)

    3) The accuracy of the result is limited by the corrections for
       refraction, which use a simple A*tan(z) + B*tan^3(z) model.
       Providing the meteorological parameters are known accurately and
       there are no gross local effects, the predicted observed
       coordinates should be within 0.05 arcsec (optical) or 1 arcsec
       (radio) for a zenith distance of less than 70 degrees, better
       than 30 arcsec (optical or radio) at 85 degrees and better than
       20 arcmin (optical) or 30 arcmin (radio) at the horizon.

       Without refraction, the complementary functions eraAtioq and
       eraAtoiq are self-consistent to better than 1 microarcsecond all
       over the celestial sphere.  With refraction included, consistency
       falls off at high zenith distances, but is still better than
       0.05 arcsec at 85 degrees.

    4) It is advisable to take great care with units, as even unlikely
       values of the input parameters are accepted and processed in
       accordance with the models used.

    Called:
       eraS2c       spherical coordinates to unit vector
       eraC2s       p-vector to spherical
       eraAnp       normalize angle into range 0 to 2pi

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    type_in = numpy.array(type, dtype=numpy.dtype('S16'), order="C", copy=False, subok=True)
    ob1_in = numpy.array(ob1, dtype=numpy.double, order="C", copy=False, subok=True)
    ob2_in = numpy.array(ob2, dtype=numpy.double, order="C", copy=False, subok=True)
    astrom_in = numpy.array(astrom, dtype=dt_eraASTROM, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if type_in.shape == tuple():
            type_in = type_in.reshape((1,) + type_in.shape)
        else:
            make_outputs_scalar = False
        if ob1_in.shape == tuple():
            ob1_in = ob1_in.reshape((1,) + ob1_in.shape)
        else:
            make_outputs_scalar = False
        if ob2_in.shape == tuple():
            ob2_in = ob2_in.reshape((1,) + ob2_in.shape)
        else:
            make_outputs_scalar = False
        if astrom_in.shape == tuple():
            astrom_in = astrom_in.reshape((1,) + astrom_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), type_in, ob1_in, ob2_in, astrom_in)
    ri_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    di_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [type_in, ob1_in, ob2_in, astrom_in, ri_out, di_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._atoiq(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(ri_out.shape) > 0 and ri_out.shape[0] == 1
        ri_out = ri_out.reshape(ri_out.shape[1:])
        assert len(di_out.shape) > 0 and di_out.shape[0] == 1
        di_out = di_out.reshape(di_out.shape[1:])

    return ri_out, di_out


def ld(bm, p, q, e, em, dlim):
    """
    Wrapper for ERFA function ``eraLd``.

    Parameters
    ----------
    bm : double array
    p : double array
    q : double array
    e : double array
    em : double array
    dlim : double array

    Returns
    -------
    p1 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - -
     e r a L d
    - - - - - -

    Apply light deflection by a solar-system body, as part of
    transforming coordinate direction into natural direction.

    Given:
       bm     double     mass of the gravitating body (solar masses)
       p      double[3]  direction from observer to source (unit vector)
       q      double[3]  direction from body to source (unit vector)
       e      double[3]  direction from body to observer (unit vector)
       em     double     distance from body to observer (au)
       dlim   double     deflection limiter (Note 4)

    Returned:
       p1     double[3]  observer to deflected source (unit vector)

    Notes:

    1) The algorithm is based on Expr. (70) in Klioner (2003) and
       Expr. (7.63) in the Explanatory Supplement (Urban & Seidelmann
       2013), with some rearrangement to minimize the effects of machine
       precision.

    2) The mass parameter bm can, as required, be adjusted in order to
       allow for such effects as quadrupole field.

    3) The barycentric position of the deflecting body should ideally
       correspond to the time of closest approach of the light ray to
       the body.

    4) The deflection limiter parameter dlim is phi^2/2, where phi is
       the angular separation (in radians) between source and body at
       which limiting is applied.  As phi shrinks below the chosen
       threshold, the deflection is artificially reduced, reaching zero
       for phi = 0.

    5) The returned vector p1 is not normalized, but the consequential
       departure from unit magnitude is always negligible.

    6) The arguments p and p1 can be the same array.

    7) To accumulate total light deflection taking into account the
       contributions from several bodies, call the present function for
       each body in succession, in decreasing order of distance from the
       observer.

    8) For efficiency, validation is omitted.  The supplied vectors must
       be of unit magnitude, and the deflection limiter non-zero and
       positive.

    References:

       Urban, S. & Seidelmann, P. K. (eds), Explanatory Supplement to
       the Astronomical Almanac, 3rd ed., University Science Books
       (2013).

       Klioner, Sergei A., "A practical relativistic model for micro-
       arcsecond astrometry in space", Astr. J. 125, 1580-1597 (2003).

    Called:
       eraPdp       scalar product of two p-vectors
       eraPxp       vector product of two p-vectors

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    bm_in = numpy.array(bm, dtype=numpy.double, order="C", copy=False, subok=True)
    p_in = numpy.array(p, dtype=numpy.double, order="C", copy=False, subok=True)
    q_in = numpy.array(q, dtype=numpy.double, order="C", copy=False, subok=True)
    e_in = numpy.array(e, dtype=numpy.double, order="C", copy=False, subok=True)
    em_in = numpy.array(em, dtype=numpy.double, order="C", copy=False, subok=True)
    dlim_in = numpy.array(dlim, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(p_in, (3,), "p")
    check_trailing_shape(q_in, (3,), "q")
    check_trailing_shape(e_in, (3,), "e")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if bm_in.shape == tuple():
            bm_in = bm_in.reshape((1,) + bm_in.shape)
        else:
            make_outputs_scalar = False
        if p_in[...,0].shape == tuple():
            p_in = p_in.reshape((1,) + p_in.shape)
        else:
            make_outputs_scalar = False
        if q_in[...,0].shape == tuple():
            q_in = q_in.reshape((1,) + q_in.shape)
        else:
            make_outputs_scalar = False
        if e_in[...,0].shape == tuple():
            e_in = e_in.reshape((1,) + e_in.shape)
        else:
            make_outputs_scalar = False
        if em_in.shape == tuple():
            em_in = em_in.reshape((1,) + em_in.shape)
        else:
            make_outputs_scalar = False
        if dlim_in.shape == tuple():
            dlim_in = dlim_in.reshape((1,) + dlim_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), bm_in, p_in[...,0], q_in[...,0], e_in[...,0], em_in, dlim_in)
    p1_out = numpy.empty(broadcast.shape + (3,), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [bm_in, p_in[...,0], q_in[...,0], e_in[...,0], em_in, dlim_in, p1_out[...,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*6 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ld(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(p1_out.shape) > 0 and p1_out.shape[0] == 1
        p1_out = p1_out.reshape(p1_out.shape[1:])

    return p1_out


def ldn(n, b, ob, sc):
    """
    Wrapper for ERFA function ``eraLdn``.

    Parameters
    ----------
    n : int array
    b : eraLDBODY array
    ob : double array
    sc : double array

    Returns
    -------
    sn : double array

    Notes
    -----
    The ERFA documentation is below.

/*+
    - - - - - - -
     e r a L d n
    - - - - - - -

    For a star, apply light deflection by multiple solar-system bodies,
    as part of transforming coordinate direction into natural direction.

    Given:
       n    int           number of bodies (note 1)
       b    eraLDBODY[n]  data for each of the n bodies (Notes 1,2):
        bm   double         mass of the body (solar masses, Note 3)
        dl   double         deflection limiter (Note 4)
        pv   [2][3]         barycentric PV of the body (au, au/day)
       ob   double[3]     barycentric position of the observer (au)
       sc   double[3]     observer to star coord direction (unit vector)

    Returned:
       sn    double[3]      observer to deflected star (unit vector)

    1) The array b contains n entries, one for each body to be
       considered.  If n = 0, no gravitational light deflection will be
       applied, not even for the Sun.

    2) The array b should include an entry for the Sun as well as for
       any planet or other body to be taken into account.  The entries
       should be in the order in which the light passes the body.

    3) In the entry in the b array for body i, the mass parameter
       b[i].bm can, as required, be adjusted in order to allow for such
       effects as quadrupole field.

    4) The deflection limiter parameter b[i].dl is phi^2/2, where phi is
       the angular separation (in radians) between star and body at
       which limiting is applied.  As phi shrinks below the chosen
       threshold, the deflection is artificially reduced, reaching zero
       for phi = 0.   Example values suitable for a terrestrial
       observer, together with masses, are as follows:

          body i     b[i].bm        b[i].dl

          Sun        1.0            6e-6
          Jupiter    0.00095435     3e-9
          Saturn     0.00028574     3e-10

    5) For cases where the starlight passes the body before reaching the
       observer, the body is placed back along its barycentric track by
       the light time from that point to the observer.  For cases where
       the body is "behind" the observer no such shift is applied.  If
       a different treatment is preferred, the user has the option of
       instead using the eraLd function.  Similarly, eraLd can be used
       for cases where the source is nearby, not a star.

    6) The returned vector sn is not normalized, but the consequential
       departure from unit magnitude is always negligible.

    7) The arguments sc and sn can be the same array.

    8) For efficiency, validation is omitted.  The supplied masses must
       be greater than zero, the position and velocity vectors must be
       right, and the deflection limiter greater than zero.

    Reference:

       Urban, S. & Seidelmann, P. K. (eds), Explanatory Supplement to
       the Astronomical Almanac, 3rd ed., University Science Books
       (2013), Section 7.2.4.

    Called:
       eraCp        copy p-vector
       eraPdp       scalar product of two p-vectors
       eraPmp       p-vector minus p-vector
       eraPpsp      p-vector plus scaled p-vector
       eraPn        decompose p-vector into modulus and direction
       eraLd        light deflection by a solar-system body

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    n_in = numpy.array(n, dtype=numpy.intc, order="C", copy=False, subok=True)
    b_in = numpy.array(b, dtype=dt_eraLDBODY, order="C", copy=False, subok=True)
    ob_in = numpy.array(ob, dtype=numpy.double, order="C", copy=False, subok=True)
    sc_in = numpy.array(sc, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(ob_in, (3,), "ob")
    check_trailing_shape(sc_in, (3,), "sc")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if n_in.shape == tuple():
            n_in = n_in.reshape((1,) + n_in.shape)
        else:
            make_outputs_scalar = False
        if b_in.shape == tuple():
            b_in = b_in.reshape((1,) + b_in.shape)
        else:
            make_outputs_scalar = False
        if ob_in[...,0].shape == tuple():
            ob_in = ob_in.reshape((1,) + ob_in.shape)
        else:
            make_outputs_scalar = False
        if sc_in[...,0].shape == tuple():
            sc_in = sc_in.reshape((1,) + sc_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), n_in, b_in, ob_in[...,0], sc_in[...,0])
    sn_out = numpy.empty(broadcast.shape + (3,), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [n_in, b_in, ob_in[...,0], sc_in[...,0], sn_out[...,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ldn(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(sn_out.shape) > 0 and sn_out.shape[0] == 1
        sn_out = sn_out.reshape(sn_out.shape[1:])

    return sn_out


def ldsun(p, e, em):
    """
    Wrapper for ERFA function ``eraLdsun``.

    Parameters
    ----------
    p : double array
    e : double array
    em : double array

    Returns
    -------
    p1 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a L d s u n
    - - - - - - - - -

    Deflection of starlight by the Sun.

    Given:
       p      double[3]  direction from observer to star (unit vector)
       e      double[3]  direction from Sun to observer (unit vector)
       em     double     distance from Sun to observer (au)

    Returned:
       p1     double[3]  observer to deflected star (unit vector)

    Notes:

    1) The source is presumed to be sufficiently distant that its
       directions seen from the Sun and the observer are essentially
       the same.

    2) The deflection is restrained when the angle between the star and
       the center of the Sun is less than a threshold value, falling to
       zero deflection for zero separation.  The chosen threshold value
       is within the solar limb for all solar-system applications, and
       is about 5 arcminutes for the case of a terrestrial observer.

    3) The arguments p and p1 can be the same array.

    Called:
       eraLd        light deflection by a solar-system body

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    p_in = numpy.array(p, dtype=numpy.double, order="C", copy=False, subok=True)
    e_in = numpy.array(e, dtype=numpy.double, order="C", copy=False, subok=True)
    em_in = numpy.array(em, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(p_in, (3,), "p")
    check_trailing_shape(e_in, (3,), "e")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if p_in[...,0].shape == tuple():
            p_in = p_in.reshape((1,) + p_in.shape)
        else:
            make_outputs_scalar = False
        if e_in[...,0].shape == tuple():
            e_in = e_in.reshape((1,) + e_in.shape)
        else:
            make_outputs_scalar = False
        if em_in.shape == tuple():
            em_in = em_in.reshape((1,) + em_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), p_in[...,0], e_in[...,0], em_in)
    p1_out = numpy.empty(broadcast.shape + (3,), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [p_in[...,0], e_in[...,0], em_in, p1_out[...,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ldsun(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(p1_out.shape) > 0 and p1_out.shape[0] == 1
        p1_out = p1_out.reshape(p1_out.shape[1:])

    return p1_out


def pmpx(rc, dc, pr, pd, px, rv, pmt, pob):
    """
    Wrapper for ERFA function ``eraPmpx``.

    Parameters
    ----------
    rc : double array
    dc : double array
    pr : double array
    pd : double array
    px : double array
    rv : double array
    pmt : double array
    pob : double array

    Returns
    -------
    pco : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a P m p x
    - - - - - - - -

    Proper motion and parallax.

    Given:
       rc,dc  double     ICRS RA,Dec at catalog epoch (radians)
       pr     double     RA proper motion (radians/year; Note 1)
       pd     double     Dec proper motion (radians/year)
       px     double     parallax (arcsec)
       rv     double     radial velocity (km/s, +ve if receding)
       pmt    double     proper motion time interval (SSB, Julian years)
       pob    double[3]  SSB to observer vector (au)

    Returned:
       pco    double[3]  coordinate direction (BCRS unit vector)

    Notes:

    1) The proper motion in RA is dRA/dt rather than cos(Dec)*dRA/dt.

    2) The proper motion time interval is for when the starlight
       reaches the solar system barycenter.

    3) To avoid the need for iteration, the Roemer effect (i.e. the
       small annual modulation of the proper motion coming from the
       changing light time) is applied approximately, using the
       direction of the star at the catalog epoch.

    References:

       1984 Astronomical Almanac, pp B39-B41.

       Urban, S. & Seidelmann, P. K. (eds), Explanatory Supplement to
       the Astronomical Almanac, 3rd ed., University Science Books
       (2013), Section 7.2.

    Called:
       eraPdp       scalar product of two p-vectors
       eraPn        decompose p-vector into modulus and direction

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    rc_in = numpy.array(rc, dtype=numpy.double, order="C", copy=False, subok=True)
    dc_in = numpy.array(dc, dtype=numpy.double, order="C", copy=False, subok=True)
    pr_in = numpy.array(pr, dtype=numpy.double, order="C", copy=False, subok=True)
    pd_in = numpy.array(pd, dtype=numpy.double, order="C", copy=False, subok=True)
    px_in = numpy.array(px, dtype=numpy.double, order="C", copy=False, subok=True)
    rv_in = numpy.array(rv, dtype=numpy.double, order="C", copy=False, subok=True)
    pmt_in = numpy.array(pmt, dtype=numpy.double, order="C", copy=False, subok=True)
    pob_in = numpy.array(pob, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(pob_in, (3,), "pob")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if rc_in.shape == tuple():
            rc_in = rc_in.reshape((1,) + rc_in.shape)
        else:
            make_outputs_scalar = False
        if dc_in.shape == tuple():
            dc_in = dc_in.reshape((1,) + dc_in.shape)
        else:
            make_outputs_scalar = False
        if pr_in.shape == tuple():
            pr_in = pr_in.reshape((1,) + pr_in.shape)
        else:
            make_outputs_scalar = False
        if pd_in.shape == tuple():
            pd_in = pd_in.reshape((1,) + pd_in.shape)
        else:
            make_outputs_scalar = False
        if px_in.shape == tuple():
            px_in = px_in.reshape((1,) + px_in.shape)
        else:
            make_outputs_scalar = False
        if rv_in.shape == tuple():
            rv_in = rv_in.reshape((1,) + rv_in.shape)
        else:
            make_outputs_scalar = False
        if pmt_in.shape == tuple():
            pmt_in = pmt_in.reshape((1,) + pmt_in.shape)
        else:
            make_outputs_scalar = False
        if pob_in[...,0].shape == tuple():
            pob_in = pob_in.reshape((1,) + pob_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), rc_in, dc_in, pr_in, pd_in, px_in, rv_in, pmt_in, pob_in[...,0])
    pco_out = numpy.empty(broadcast.shape + (3,), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [rc_in, dc_in, pr_in, pd_in, px_in, rv_in, pmt_in, pob_in[...,0], pco_out[...,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*8 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pmpx(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(pco_out.shape) > 0 and pco_out.shape[0] == 1
        pco_out = pco_out.reshape(pco_out.shape[1:])

    return pco_out


def pmsafe(ra1, dec1, pmr1, pmd1, px1, rv1, ep1a, ep1b, ep2a, ep2b):
    """
    Wrapper for ERFA function ``eraPmsafe``.

    Parameters
    ----------
    ra1 : double array
    dec1 : double array
    pmr1 : double array
    pmd1 : double array
    px1 : double array
    rv1 : double array
    ep1a : double array
    ep1b : double array
    ep2a : double array
    ep2b : double array

    Returns
    -------
    ra2 : double array
    dec2 : double array
    pmr2 : double array
    pmd2 : double array
    px2 : double array
    rv2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a P m s a f e
    - - - - - - - - - -

    Star proper motion:  update star catalog data for space motion, with
    special handling to handle the zero parallax case.

    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 epochs 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 overridden
       to ensure that the object is at a finite but very large distance,
       but not so large that the proper motion is equivalent to a large
       but safe speed (about 0.1c using the chosen constant).  A warning
       status of 1 is added to the status if this action has been taken.

    7) If the space velocity is a significant fraction of c (see the
       constant VMAX in the function eraStarpv), it is arbitrarily set
       to zero.  When this action occurs, 2 is added to the status.

    8) The relativistic adjustment carried out in the eraStarpv function
       involves an iterative calculation.  If the process fails to
       converge within a set number of iterations, 4 is added to the
       status.

    Called:
       eraSeps      angle between two points
       eraStarpm    update star catalog data for space motion

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ra1_in = numpy.array(ra1, dtype=numpy.double, order="C", copy=False, subok=True)
    dec1_in = numpy.array(dec1, dtype=numpy.double, order="C", copy=False, subok=True)
    pmr1_in = numpy.array(pmr1, dtype=numpy.double, order="C", copy=False, subok=True)
    pmd1_in = numpy.array(pmd1, dtype=numpy.double, order="C", copy=False, subok=True)
    px1_in = numpy.array(px1, dtype=numpy.double, order="C", copy=False, subok=True)
    rv1_in = numpy.array(rv1, dtype=numpy.double, order="C", copy=False, subok=True)
    ep1a_in = numpy.array(ep1a, dtype=numpy.double, order="C", copy=False, subok=True)
    ep1b_in = numpy.array(ep1b, dtype=numpy.double, order="C", copy=False, subok=True)
    ep2a_in = numpy.array(ep2a, dtype=numpy.double, order="C", copy=False, subok=True)
    ep2b_in = numpy.array(ep2b, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ra1_in.shape == tuple():
            ra1_in = ra1_in.reshape((1,) + ra1_in.shape)
        else:
            make_outputs_scalar = False
        if dec1_in.shape == tuple():
            dec1_in = dec1_in.reshape((1,) + dec1_in.shape)
        else:
            make_outputs_scalar = False
        if pmr1_in.shape == tuple():
            pmr1_in = pmr1_in.reshape((1,) + pmr1_in.shape)
        else:
            make_outputs_scalar = False
        if pmd1_in.shape == tuple():
            pmd1_in = pmd1_in.reshape((1,) + pmd1_in.shape)
        else:
            make_outputs_scalar = False
        if px1_in.shape == tuple():
            px1_in = px1_in.reshape((1,) + px1_in.shape)
        else:
            make_outputs_scalar = False
        if rv1_in.shape == tuple():
            rv1_in = rv1_in.reshape((1,) + rv1_in.shape)
        else:
            make_outputs_scalar = False
        if ep1a_in.shape == tuple():
            ep1a_in = ep1a_in.reshape((1,) + ep1a_in.shape)
        else:
            make_outputs_scalar = False
        if ep1b_in.shape == tuple():
            ep1b_in = ep1b_in.reshape((1,) + ep1b_in.shape)
        else:
            make_outputs_scalar = False
        if ep2a_in.shape == tuple():
            ep2a_in = ep2a_in.reshape((1,) + ep2a_in.shape)
        else:
            make_outputs_scalar = False
        if ep2b_in.shape == tuple():
            ep2b_in = ep2b_in.reshape((1,) + ep2b_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ra1_in, dec1_in, pmr1_in, pmd1_in, px1_in, rv1_in, ep1a_in, ep1b_in, ep2a_in, ep2b_in)
    ra2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dec2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    pmr2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    pmd2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    px2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    rv2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ra1_in, dec1_in, pmr1_in, pmd1_in, px1_in, rv1_in, ep1a_in, ep1b_in, ep2a_in, ep2b_in, ra2_out, dec2_out, pmr2_out, pmd2_out, px2_out, rv2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*10 + [['readwrite']]*7
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pmsafe(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'pmsafe')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(ra2_out.shape) > 0 and ra2_out.shape[0] == 1
        ra2_out = ra2_out.reshape(ra2_out.shape[1:])
        assert len(dec2_out.shape) > 0 and dec2_out.shape[0] == 1
        dec2_out = dec2_out.reshape(dec2_out.shape[1:])
        assert len(pmr2_out.shape) > 0 and pmr2_out.shape[0] == 1
        pmr2_out = pmr2_out.reshape(pmr2_out.shape[1:])
        assert len(pmd2_out.shape) > 0 and pmd2_out.shape[0] == 1
        pmd2_out = pmd2_out.reshape(pmd2_out.shape[1:])
        assert len(px2_out.shape) > 0 and px2_out.shape[0] == 1
        px2_out = px2_out.reshape(px2_out.shape[1:])
        assert len(rv2_out.shape) > 0 and rv2_out.shape[0] == 1
        rv2_out = rv2_out.reshape(rv2_out.shape[1:])

    return ra2_out, dec2_out, pmr2_out, pmd2_out, px2_out, rv2_out
STATUS_CODES['pmsafe'] = {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', -1: 'system error (should not occur)'}



def pvtob(elong, phi, hm, xp, yp, sp, theta):
    """
    Wrapper for ERFA function ``eraPvtob``.

    Parameters
    ----------
    elong : double array
    phi : double array
    hm : double array
    xp : double array
    yp : double array
    sp : double array
    theta : double array

    Returns
    -------
    pv : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a P v t o b
    - - - - - - - - -

    Position and velocity of a terrestrial observing station.

    Given:
       elong   double       longitude (radians, east +ve, Note 1)
       phi     double       latitude (geodetic, radians, Note 1)
       hm      double       height above ref. ellipsoid (geodetic, m)
       xp,yp   double       coordinates of the pole (radians, Note 2)
       sp      double       the TIO locator s' (radians, Note 2)
       theta   double       Earth rotation angle (radians, Note 3)

    Returned:
       pv      double[2][3] position/velocity vector (m, m/s, CIRS)

    Notes:

    1) The terrestrial coordinates are with respect to the ERFA_WGS84
       reference ellipsoid.

    2) xp and yp are the coordinates (in radians) of the Celestial
       Intermediate Pole with respect to the International Terrestrial
       Reference System (see IERS Conventions), measured along the
       meridians 0 and 90 deg west respectively.  sp is the TIO locator
       s', in radians, which positions the Terrestrial Intermediate
       Origin on the equator.  For many applications, xp, yp and
       (especially) sp can be set to zero.

    3) If theta is Greenwich apparent sidereal time instead of Earth
       rotation angle, the result is with respect to the true equator
       and equinox of date, i.e. with the x-axis at the equinox rather
       than the celestial intermediate origin.

    4) The velocity units are meters per UT1 second, not per SI second.
       This is unlikely to have any practical consequences in the modern
       era.

    5) No validation is performed on the arguments.  Error cases that
       could lead to arithmetic exceptions are trapped by the eraGd2gc
       function, and the result set to zeros.

    References:

       McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
       IERS Technical Note No. 32, BKG (2004)

       Urban, S. & Seidelmann, P. K. (eds), Explanatory Supplement to
       the Astronomical Almanac, 3rd ed., University Science Books
       (2013), Section 7.4.3.3.

    Called:
       eraGd2gc     geodetic to geocentric transformation
       eraPom00     polar motion matrix
       eraTrxp      product of transpose of r-matrix and p-vector

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    elong_in = numpy.array(elong, dtype=numpy.double, order="C", copy=False, subok=True)
    phi_in = numpy.array(phi, dtype=numpy.double, order="C", copy=False, subok=True)
    hm_in = numpy.array(hm, dtype=numpy.double, order="C", copy=False, subok=True)
    xp_in = numpy.array(xp, dtype=numpy.double, order="C", copy=False, subok=True)
    yp_in = numpy.array(yp, dtype=numpy.double, order="C", copy=False, subok=True)
    sp_in = numpy.array(sp, dtype=numpy.double, order="C", copy=False, subok=True)
    theta_in = numpy.array(theta, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if elong_in.shape == tuple():
            elong_in = elong_in.reshape((1,) + elong_in.shape)
        else:
            make_outputs_scalar = False
        if phi_in.shape == tuple():
            phi_in = phi_in.reshape((1,) + phi_in.shape)
        else:
            make_outputs_scalar = False
        if hm_in.shape == tuple():
            hm_in = hm_in.reshape((1,) + hm_in.shape)
        else:
            make_outputs_scalar = False
        if xp_in.shape == tuple():
            xp_in = xp_in.reshape((1,) + xp_in.shape)
        else:
            make_outputs_scalar = False
        if yp_in.shape == tuple():
            yp_in = yp_in.reshape((1,) + yp_in.shape)
        else:
            make_outputs_scalar = False
        if sp_in.shape == tuple():
            sp_in = sp_in.reshape((1,) + sp_in.shape)
        else:
            make_outputs_scalar = False
        if theta_in.shape == tuple():
            theta_in = theta_in.reshape((1,) + theta_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), elong_in, phi_in, hm_in, xp_in, yp_in, sp_in, theta_in)
    pv_out = numpy.empty(broadcast.shape + (2, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [elong_in, phi_in, hm_in, xp_in, yp_in, sp_in, theta_in, pv_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*7 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pvtob(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(pv_out.shape) > 0 and pv_out.shape[0] == 1
        pv_out = pv_out.reshape(pv_out.shape[1:])

    return pv_out


def refco(phpa, tc, rh, wl):
    """
    Wrapper for ERFA function ``eraRefco``.

    Parameters
    ----------
    phpa : double array
    tc : double array
    rh : double array
    wl : double array

    Returns
    -------
    refa : double array
    refb : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a R e f c o
    - - - - - - - - -

    Determine the constants A and B in the atmospheric refraction model
    dZ = A tan Z + B tan^3 Z.

    Z is the "observed" zenith distance (i.e. affected by refraction)
    and dZ is what to add to Z to give the "topocentric" (i.e. in vacuo)
    zenith distance.

    Given:
      phpa   double    pressure at the observer (hPa = millibar)
      tc     double    ambient temperature at the observer (deg C)
      rh     double    relative humidity at the observer (range 0-1)
      wl     double    wavelength (micrometers)

    Returned:
      refa   double*   tan Z coefficient (radians)
      refb   double*   tan^3 Z coefficient (radians)

    Notes:

    1) The model balances speed and accuracy to give good results in
       applications where performance at low altitudes is not paramount.
       Performance is maintained across a range of conditions, and
       applies to both optical/IR and radio.

    2) The model omits the effects of (i) height above sea level (apart
       from the reduced pressure itself), (ii) latitude (i.e. the
       flattening of the Earth), (iii) variations in tropospheric lapse
       rate and (iv) dispersive effects in the radio.

       The model was tested using the following range of conditions:

         lapse rates 0.0055, 0.0065, 0.0075 deg/meter
         latitudes 0, 25, 50, 75 degrees
         heights 0, 2500, 5000 meters ASL
         pressures mean for height -10% to +5% in steps of 5%
         temperatures -10 deg to +20 deg with respect to 280 deg at SL
         relative humidity 0, 0.5, 1
         wavelengths 0.4, 0.6, ... 2 micron, + radio
         zenith distances 15, 45, 75 degrees

       The accuracy with respect to raytracing through a model
       atmosphere was as follows:

                              worst         RMS

         optical/IR           62 mas       8 mas
         radio               319 mas      49 mas

       For this particular set of conditions:

         lapse rate 0.0065 K/meter
         latitude 50 degrees
         sea level
         pressure 1005 mb
         temperature 280.15 K
         humidity 80%
         wavelength 5740 Angstroms

       the results were as follows:

         ZD       raytrace     eraRefco   Saastamoinen

         10         10.27        10.27        10.27
         20         21.19        21.20        21.19
         30         33.61        33.61        33.60
         40         48.82        48.83        48.81
         45         58.16        58.18        58.16
         50         69.28        69.30        69.27
         55         82.97        82.99        82.95
         60        100.51       100.54       100.50
         65        124.23       124.26       124.20
         70        158.63       158.68       158.61
         72        177.32       177.37       177.31
         74        200.35       200.38       200.32
         76        229.45       229.43       229.42
         78        267.44       267.29       267.41
         80        319.13       318.55       319.10

        deg        arcsec       arcsec       arcsec

       The values for Saastamoinen's formula (which includes terms
       up to tan^5) are taken from Hohenkerk and Sinclair (1985).

    3) A wl value in the range 0-100 selects the optical/IR case and is
       wavelength in micrometers.  Any value outside this range selects
       the radio case.

    4) Outlandish input parameters are silently limited to
       mathematically safe values.  Zero pressure is permissible, and
       causes zeroes to be returned.

    5) The algorithm draws on several sources, as follows:

       a) The formula for the saturation vapour pressure of water as
          a function of temperature and temperature is taken from
          Equations (A4.5-A4.7) of Gill (1982).

       b) The formula for the water vapour pressure, given the
          saturation pressure and the relative humidity, is from
          Crane (1976), Equation (2.5.5).

       c) The refractivity of air is a function of temperature,
          total pressure, water-vapour pressure and, in the case
          of optical/IR, wavelength.  The formulae for the two cases are
          developed from Hohenkerk & Sinclair (1985) and Rueger (2002).

       d) The formula for beta, the ratio of the scale height of the
          atmosphere to the geocentric distance of the observer, is
          an adaption of Equation (9) from Stone (1996).  The
          adaptations, arrived at empirically, consist of (i) a small
          adjustment to the coefficient and (ii) a humidity term for the
          radio case only.

       e) The formulae for the refraction constants as a function of
          n-1 and beta are from Green (1987), Equation (4.31).

    References:

       Crane, R.K., Meeks, M.L. (ed), "Refraction Effects in the Neutral
       Atmosphere", Methods of Experimental Physics: Astrophysics 12B,
       Academic Press, 1976.

       Gill, Adrian E., "Atmosphere-Ocean Dynamics", Academic Press,
       1982.

       Green, R.M., "Spherical Astronomy", Cambridge University Press,
       1987.

       Hohenkerk, C.Y., & Sinclair, A.T., NAO Technical Note No. 63,
       1985.

       Rueger, J.M., "Refractive Index Formulae for Electronic Distance
       Measurement with Radio and Millimetre Waves", in Unisurv Report
       S-68, School of Surveying and Spatial Information Systems,
       University of New South Wales, Sydney, Australia, 2002.

       Stone, Ronald C., P.A.S.P. 108, 1051-1058, 1996.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    phpa_in = numpy.array(phpa, dtype=numpy.double, order="C", copy=False, subok=True)
    tc_in = numpy.array(tc, dtype=numpy.double, order="C", copy=False, subok=True)
    rh_in = numpy.array(rh, dtype=numpy.double, order="C", copy=False, subok=True)
    wl_in = numpy.array(wl, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if phpa_in.shape == tuple():
            phpa_in = phpa_in.reshape((1,) + phpa_in.shape)
        else:
            make_outputs_scalar = False
        if tc_in.shape == tuple():
            tc_in = tc_in.reshape((1,) + tc_in.shape)
        else:
            make_outputs_scalar = False
        if rh_in.shape == tuple():
            rh_in = rh_in.reshape((1,) + rh_in.shape)
        else:
            make_outputs_scalar = False
        if wl_in.shape == tuple():
            wl_in = wl_in.reshape((1,) + wl_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), phpa_in, tc_in, rh_in, wl_in)
    refa_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    refb_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [phpa_in, tc_in, rh_in, wl_in, refa_out, refb_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._refco(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(refa_out.shape) > 0 and refa_out.shape[0] == 1
        refa_out = refa_out.reshape(refa_out.shape[1:])
        assert len(refb_out.shape) > 0 and refb_out.shape[0] == 1
        refb_out = refb_out.reshape(refb_out.shape[1:])

    return refa_out, refb_out


def epv00(date1, date2):
    """
    Wrapper for ERFA function ``eraEpv00``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    pvh : double array
    pvb : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a E p v 0 0
    - - - - - - - - -

    Earth position and velocity, heliocentric and barycentric, with
    respect to the Barycentric Celestial Reference System.

    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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    pvh_out = numpy.empty(broadcast.shape + (2, 3), dtype=numpy.double)
    pvb_out = numpy.empty(broadcast.shape + (2, 3), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, pvh_out[...,0,0], pvb_out[...,0,0], c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._epv00(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'epv00')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(pvh_out.shape) > 0 and pvh_out.shape[0] == 1
        pvh_out = pvh_out.reshape(pvh_out.shape[1:])
        assert len(pvb_out.shape) > 0 and pvb_out.shape[0] == 1
        pvb_out = pvb_out.reshape(pvb_out.shape[1:])

    return pvh_out, pvb_out
STATUS_CODES['epv00'] = {0: 'OK', 1: 'warning: date outsidethe range 1900-2100 AD'}



def plan94(date1, date2, np):
    """
    Wrapper for ERFA function ``eraPlan94``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    np : int array

    Returns
    -------
    pv : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a P l a n 9 4
    - - - - - - - - - -

    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[2][3] 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 ERFA function eraEpv00.

    4) On successful return, the array pv contains the following:

          pv[0][0]   x      }
          pv[0][1]   y      } heliocentric position, AU
          pv[0][2]   z      }

          pv[1][0]   xdot   }
          pv[1][1]   ydot   } heliocentric velocity, AU/d
          pv[1][2]   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 ERFA 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:
       eraAnp       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).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    np_in = numpy.array(np, dtype=numpy.intc, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if np_in.shape == tuple():
            np_in = np_in.reshape((1,) + np_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, np_in)
    pv_out = numpy.empty(broadcast.shape + (2, 3), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, np_in, pv_out[...,0,0], c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._plan94(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'plan94')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(pv_out.shape) > 0 and pv_out.shape[0] == 1
        pv_out = pv_out.reshape(pv_out.shape[1:])

    return pv_out
STATUS_CODES['plan94'] = {0: 'OK', 1: 'warning: year outside 1000-3000', 2: 'warning: failed to converge', -1: 'illegal NP (outside 1-8)'}



def fad03(t):
    """
    Wrapper for ERFA function ``eraFad03``.

    Parameters
    ----------
    t : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a F a d 0 3
    - - - - - - - - -

    Fundamental argument, IERS Conventions (2003):
    mean elongation of the Moon from the Sun.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    t_in = numpy.array(t, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if t_in.shape == tuple():
            t_in = t_in.reshape((1,) + t_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), t_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [t_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._fad03(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def fae03(t):
    """
    Wrapper for ERFA function ``eraFae03``.

    Parameters
    ----------
    t : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a F a e 0 3
    - - - - - - - - -

    Fundamental argument, IERS Conventions (2003):
    mean longitude of Earth.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    t_in = numpy.array(t, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if t_in.shape == tuple():
            t_in = t_in.reshape((1,) + t_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), t_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [t_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._fae03(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def faf03(t):
    """
    Wrapper for ERFA function ``eraFaf03``.

    Parameters
    ----------
    t : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a F a f 0 3
    - - - - - - - - -

    Fundamental argument, IERS Conventions (2003):
    mean longitude of the Moon minus mean longitude of the ascending
    node.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    t_in = numpy.array(t, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if t_in.shape == tuple():
            t_in = t_in.reshape((1,) + t_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), t_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [t_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._faf03(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def faju03(t):
    """
    Wrapper for ERFA function ``eraFaju03``.

    Parameters
    ----------
    t : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a F a j u 0 3
    - - - - - - - - - -

    Fundamental argument, IERS Conventions (2003):
    mean longitude of Jupiter.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    t_in = numpy.array(t, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if t_in.shape == tuple():
            t_in = t_in.reshape((1,) + t_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), t_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [t_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._faju03(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def fal03(t):
    """
    Wrapper for ERFA function ``eraFal03``.

    Parameters
    ----------
    t : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a F a l 0 3
    - - - - - - - - -

    Fundamental argument, IERS Conventions (2003):
    mean anomaly of the Moon.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    t_in = numpy.array(t, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if t_in.shape == tuple():
            t_in = t_in.reshape((1,) + t_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), t_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [t_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._fal03(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def falp03(t):
    """
    Wrapper for ERFA function ``eraFalp03``.

    Parameters
    ----------
    t : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a F a l p 0 3
    - - - - - - - - - -

    Fundamental argument, IERS Conventions (2003):
    mean anomaly of the Sun.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    t_in = numpy.array(t, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if t_in.shape == tuple():
            t_in = t_in.reshape((1,) + t_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), t_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [t_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._falp03(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def fama03(t):
    """
    Wrapper for ERFA function ``eraFama03``.

    Parameters
    ----------
    t : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a F a m a 0 3
    - - - - - - - - - -

    Fundamental argument, IERS Conventions (2003):
    mean longitude of Mars.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    t_in = numpy.array(t, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if t_in.shape == tuple():
            t_in = t_in.reshape((1,) + t_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), t_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [t_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._fama03(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def fame03(t):
    """
    Wrapper for ERFA function ``eraFame03``.

    Parameters
    ----------
    t : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a F a m e 0 3
    - - - - - - - - - -

    Fundamental argument, IERS Conventions (2003):
    mean longitude of Mercury.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    t_in = numpy.array(t, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if t_in.shape == tuple():
            t_in = t_in.reshape((1,) + t_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), t_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [t_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._fame03(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def fane03(t):
    """
    Wrapper for ERFA function ``eraFane03``.

    Parameters
    ----------
    t : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a F a n e 0 3
    - - - - - - - - - -

    Fundamental argument, IERS Conventions (2003):
    mean longitude of Neptune.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    t_in = numpy.array(t, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if t_in.shape == tuple():
            t_in = t_in.reshape((1,) + t_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), t_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [t_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._fane03(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def faom03(t):
    """
    Wrapper for ERFA function ``eraFaom03``.

    Parameters
    ----------
    t : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a F a o m 0 3
    - - - - - - - - - -

    Fundamental argument, IERS Conventions (2003):
    mean longitude of the Moon's ascending node.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    t_in = numpy.array(t, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if t_in.shape == tuple():
            t_in = t_in.reshape((1,) + t_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), t_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [t_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._faom03(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def fapa03(t):
    """
    Wrapper for ERFA function ``eraFapa03``.

    Parameters
    ----------
    t : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a F a p a 0 3
    - - - - - - - - - -

    Fundamental argument, IERS Conventions (2003):
    general accumulated precession in longitude.

    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    t_in = numpy.array(t, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if t_in.shape == tuple():
            t_in = t_in.reshape((1,) + t_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), t_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [t_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._fapa03(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def fasa03(t):
    """
    Wrapper for ERFA function ``eraFasa03``.

    Parameters
    ----------
    t : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a F a s a 0 3
    - - - - - - - - - -

    Fundamental argument, IERS Conventions (2003):
    mean longitude of Saturn.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    t_in = numpy.array(t, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if t_in.shape == tuple():
            t_in = t_in.reshape((1,) + t_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), t_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [t_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._fasa03(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def faur03(t):
    """
    Wrapper for ERFA function ``eraFaur03``.

    Parameters
    ----------
    t : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a F a u r 0 3
    - - - - - - - - - -

    Fundamental argument, IERS Conventions (2003):
    mean longitude of Uranus.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    t_in = numpy.array(t, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if t_in.shape == tuple():
            t_in = t_in.reshape((1,) + t_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), t_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [t_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._faur03(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def fave03(t):
    """
    Wrapper for ERFA function ``eraFave03``.

    Parameters
    ----------
    t : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a F a v e 0 3
    - - - - - - - - - -

    Fundamental argument, IERS Conventions (2003):
    mean longitude of Venus.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    t_in = numpy.array(t, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if t_in.shape == tuple():
            t_in = t_in.reshape((1,) + t_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), t_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [t_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._fave03(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def bi00():
    """
    Wrapper for ERFA function ``eraBi00``.

    Parameters
    ----------

    Returns
    -------
    dpsibi : double array
    depsbi : double array
    dra : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a B i 0 0
    - - - - - - - -

    Frame bias components of IAU 2000 precession-nutation models (part
    of MHB2000 with additions).

    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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), )
    dpsibi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    depsbi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dra_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [dpsibi_out, depsbi_out, dra_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*0 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._bi00(it)

    return dpsibi_out, depsbi_out, dra_out


def bp00(date1, date2):
    """
    Wrapper for ERFA function ``eraBp00``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rb : double array
    rp : double array
    rbp : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a B p 0 0
    - - - - - - - -

    Frame bias and precession, IAU 2000.

    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:
       eraBi00      frame bias components, IAU 2000
       eraPr00      IAU 2000 precession adjustments
       eraIr        initialize r-matrix to identity
       eraRx        rotate around X-axis
       eraRy        rotate around Y-axis
       eraRz        rotate around Z-axis
       eraCr        copy r-matrix
       eraRxr       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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rb_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rbp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rb_out[...,0,0], rp_out[...,0,0], rbp_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._bp00(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rb_out.shape) > 0 and rb_out.shape[0] == 1
        rb_out = rb_out.reshape(rb_out.shape[1:])
        assert len(rp_out.shape) > 0 and rp_out.shape[0] == 1
        rp_out = rp_out.reshape(rp_out.shape[1:])
        assert len(rbp_out.shape) > 0 and rbp_out.shape[0] == 1
        rbp_out = rbp_out.reshape(rbp_out.shape[1:])

    return rb_out, rp_out, rbp_out


def bp06(date1, date2):
    """
    Wrapper for ERFA function ``eraBp06``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rb : double array
    rp : double array
    rbp : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a B p 0 6
    - - - - - - - -

    Frame bias and precession, IAU 2006.

    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.

    5) It is permissible to re-use the same array in the returned
       arguments.  The arrays are filled in the order given.

    Called:
       eraPfw06     bias-precession F-W angles, IAU 2006
       eraFw2m      F-W angles to r-matrix
       eraPmat06    PB matrix, IAU 2006
       eraTr        transpose r-matrix
       eraRxr       product of two r-matrices
       eraCr        copy r-matrix

    References:

       Capitaine, N. & Wallace, P.T., 2006, Astron.Astrophys. 450, 855

       Wallace, P.T. & Capitaine, N., 2006, Astron.Astrophys. 459, 981

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rb_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rbp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rb_out[...,0,0], rp_out[...,0,0], rbp_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._bp06(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rb_out.shape) > 0 and rb_out.shape[0] == 1
        rb_out = rb_out.reshape(rb_out.shape[1:])
        assert len(rp_out.shape) > 0 and rp_out.shape[0] == 1
        rp_out = rp_out.reshape(rp_out.shape[1:])
        assert len(rbp_out.shape) > 0 and rbp_out.shape[0] == 1
        rbp_out = rbp_out.reshape(rbp_out.shape[1:])

    return rb_out, rp_out, rbp_out


def bpn2xy(rbpn):
    """
    Wrapper for ERFA function ``eraBpn2xy``.

    Parameters
    ----------
    rbpn : double array

    Returns
    -------
    x : double array
    y : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a B p n 2 x y
    - - - - - - - - - -

    Extract from the bias-precession-nutation matrix the X,Y coordinates
    of the Celestial Intermediate Pole.

    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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    rbpn_in = numpy.array(rbpn, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(rbpn_in, (3, 3), "rbpn")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if rbpn_in[...,0,0].shape == tuple():
            rbpn_in = rbpn_in.reshape((1,) + rbpn_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), rbpn_in[...,0,0])
    x_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    y_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [rbpn_in[...,0,0], x_out, y_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._bpn2xy(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(x_out.shape) > 0 and x_out.shape[0] == 1
        x_out = x_out.reshape(x_out.shape[1:])
        assert len(y_out.shape) > 0 and y_out.shape[0] == 1
        y_out = y_out.reshape(y_out.shape[1:])

    return x_out, y_out


def c2i00a(date1, date2):
    """
    Wrapper for ERFA function ``eraC2i00a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rc2i : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a C 2 i 0 0 a
    - - - - - - - - - -

    Form the celestial-to-intermediate matrix for a given date using the
    IAU 2000A precession-nutation model.

    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 eraC2i00b function.

    Called:
       eraPnm00a    classical NPB matrix, IAU 2000A
       eraC2ibpn    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rc2i_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rc2i_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._c2i00a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc2i_out.shape) > 0 and rc2i_out.shape[0] == 1
        rc2i_out = rc2i_out.reshape(rc2i_out.shape[1:])

    return rc2i_out


def c2i00b(date1, date2):
    """
    Wrapper for ERFA function ``eraC2i00b``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rc2i : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a C 2 i 0 0 b
    - - - - - - - - - -

    Form the celestial-to-intermediate matrix for a given date using the
    IAU 2000B precession-nutation model.

    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 eraC2i00a function.

    Called:
       eraPnm00b    classical NPB matrix, IAU 2000B
       eraC2ibpn    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rc2i_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rc2i_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._c2i00b(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc2i_out.shape) > 0 and rc2i_out.shape[0] == 1
        rc2i_out = rc2i_out.reshape(rc2i_out.shape[1:])

    return rc2i_out


def c2i06a(date1, date2):
    """
    Wrapper for ERFA function ``eraC2i06a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rc2i : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a 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.

    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:
       eraPnm06a    classical NPB matrix, IAU 2006/2000A
       eraBpn2xy    extract CIP X,Y coordinates from NPB matrix
       eraS06       the CIO locator s, given X,Y, IAU 2006
       eraC2ixys    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rc2i_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rc2i_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._c2i06a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc2i_out.shape) > 0 and rc2i_out.shape[0] == 1
        rc2i_out = rc2i_out.reshape(rc2i_out.shape[1:])

    return rc2i_out


def c2ibpn(date1, date2, rbpn):
    """
    Wrapper for ERFA function ``eraC2ibpn``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    rbpn : double array

    Returns
    -------
    rc2i : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a C 2 i b p n
    - - - - - - - - - -

    Form the celestial-to-intermediate matrix for a given date given
    the bias-precession-nutation matrix.  IAU 2000.

    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:
       eraBpn2xy    extract CIP X,Y coordinates from NPB matrix
       eraC2ixy     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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    rbpn_in = numpy.array(rbpn, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(rbpn_in, (3, 3), "rbpn")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if rbpn_in[...,0,0].shape == tuple():
            rbpn_in = rbpn_in.reshape((1,) + rbpn_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, rbpn_in[...,0,0])
    rc2i_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rbpn_in[...,0,0], rc2i_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._c2ibpn(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc2i_out.shape) > 0 and rc2i_out.shape[0] == 1
        rc2i_out = rc2i_out.reshape(rc2i_out.shape[1:])

    return rc2i_out


def c2ixy(date1, date2, x, y):
    """
    Wrapper for ERFA function ``eraC2ixy``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    x : double array
    y : double array

    Returns
    -------
    rc2i : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a 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.

    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:
       eraC2ixys    celestial-to-intermediate matrix, given X,Y and s
       eraS00       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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    x_in = numpy.array(x, dtype=numpy.double, order="C", copy=False, subok=True)
    y_in = numpy.array(y, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if x_in.shape == tuple():
            x_in = x_in.reshape((1,) + x_in.shape)
        else:
            make_outputs_scalar = False
        if y_in.shape == tuple():
            y_in = y_in.reshape((1,) + y_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, x_in, y_in)
    rc2i_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, x_in, y_in, rc2i_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._c2ixy(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc2i_out.shape) > 0 and rc2i_out.shape[0] == 1
        rc2i_out = rc2i_out.reshape(rc2i_out.shape[1:])

    return rc2i_out


def c2ixys(x, y, s):
    """
    Wrapper for ERFA function ``eraC2ixys``.

    Parameters
    ----------
    x : double array
    y : double array
    s : double array

    Returns
    -------
    rc2i : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a 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.

    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:
       eraIr        initialize r-matrix to identity
       eraRz        rotate around Z-axis
       eraRy        rotate around Y-axis

    Reference:

       McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
       IERS Technical Note No. 32, BKG (2004)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    x_in = numpy.array(x, dtype=numpy.double, order="C", copy=False, subok=True)
    y_in = numpy.array(y, dtype=numpy.double, order="C", copy=False, subok=True)
    s_in = numpy.array(s, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if x_in.shape == tuple():
            x_in = x_in.reshape((1,) + x_in.shape)
        else:
            make_outputs_scalar = False
        if y_in.shape == tuple():
            y_in = y_in.reshape((1,) + y_in.shape)
        else:
            make_outputs_scalar = False
        if s_in.shape == tuple():
            s_in = s_in.reshape((1,) + s_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), x_in, y_in, s_in)
    rc2i_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [x_in, y_in, s_in, rc2i_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._c2ixys(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc2i_out.shape) > 0 and rc2i_out.shape[0] == 1
        rc2i_out = rc2i_out.reshape(rc2i_out.shape[1:])

    return rc2i_out


def c2t00a(tta, ttb, uta, utb, xp, yp):
    """
    Wrapper for ERFA function ``eraC2t00a``.

    Parameters
    ----------
    tta : double array
    ttb : double array
    uta : double array
    utb : double array
    xp : double array
    yp : double array

    Returns
    -------
    rc2t : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a 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.

    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 eraC2t00b function.

    Called:
       eraC2i00a    celestial-to-intermediate matrix, IAU 2000A
       eraEra00     Earth rotation angle, IAU 2000
       eraSp00      the TIO locator s', IERS 2000
       eraPom00     polar motion matrix
       eraC2tcio    form CIO-based celestial-to-terrestrial matrix

    Reference:

       McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
       IERS Technical Note No. 32, BKG (2004)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tta_in = numpy.array(tta, dtype=numpy.double, order="C", copy=False, subok=True)
    ttb_in = numpy.array(ttb, dtype=numpy.double, order="C", copy=False, subok=True)
    uta_in = numpy.array(uta, dtype=numpy.double, order="C", copy=False, subok=True)
    utb_in = numpy.array(utb, dtype=numpy.double, order="C", copy=False, subok=True)
    xp_in = numpy.array(xp, dtype=numpy.double, order="C", copy=False, subok=True)
    yp_in = numpy.array(yp, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tta_in.shape == tuple():
            tta_in = tta_in.reshape((1,) + tta_in.shape)
        else:
            make_outputs_scalar = False
        if ttb_in.shape == tuple():
            ttb_in = ttb_in.reshape((1,) + ttb_in.shape)
        else:
            make_outputs_scalar = False
        if uta_in.shape == tuple():
            uta_in = uta_in.reshape((1,) + uta_in.shape)
        else:
            make_outputs_scalar = False
        if utb_in.shape == tuple():
            utb_in = utb_in.reshape((1,) + utb_in.shape)
        else:
            make_outputs_scalar = False
        if xp_in.shape == tuple():
            xp_in = xp_in.reshape((1,) + xp_in.shape)
        else:
            make_outputs_scalar = False
        if yp_in.shape == tuple():
            yp_in = yp_in.reshape((1,) + yp_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tta_in, ttb_in, uta_in, utb_in, xp_in, yp_in)
    rc2t_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tta_in, ttb_in, uta_in, utb_in, xp_in, yp_in, rc2t_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*6 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._c2t00a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc2t_out.shape) > 0 and rc2t_out.shape[0] == 1
        rc2t_out = rc2t_out.reshape(rc2t_out.shape[1:])

    return rc2t_out


def c2t00b(tta, ttb, uta, utb, xp, yp):
    """
    Wrapper for ERFA function ``eraC2t00b``.

    Parameters
    ----------
    tta : double array
    ttb : double array
    uta : double array
    utb : double array
    xp : double array
    yp : double array

    Returns
    -------
    rc2t : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a 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.

    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 eraC2t00a function.

    Called:
       eraC2i00b    celestial-to-intermediate matrix, IAU 2000B
       eraEra00     Earth rotation angle, IAU 2000
       eraPom00     polar motion matrix
       eraC2tcio    form CIO-based celestial-to-terrestrial matrix

    Reference:

       McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
       IERS Technical Note No. 32, BKG (2004)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tta_in = numpy.array(tta, dtype=numpy.double, order="C", copy=False, subok=True)
    ttb_in = numpy.array(ttb, dtype=numpy.double, order="C", copy=False, subok=True)
    uta_in = numpy.array(uta, dtype=numpy.double, order="C", copy=False, subok=True)
    utb_in = numpy.array(utb, dtype=numpy.double, order="C", copy=False, subok=True)
    xp_in = numpy.array(xp, dtype=numpy.double, order="C", copy=False, subok=True)
    yp_in = numpy.array(yp, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tta_in.shape == tuple():
            tta_in = tta_in.reshape((1,) + tta_in.shape)
        else:
            make_outputs_scalar = False
        if ttb_in.shape == tuple():
            ttb_in = ttb_in.reshape((1,) + ttb_in.shape)
        else:
            make_outputs_scalar = False
        if uta_in.shape == tuple():
            uta_in = uta_in.reshape((1,) + uta_in.shape)
        else:
            make_outputs_scalar = False
        if utb_in.shape == tuple():
            utb_in = utb_in.reshape((1,) + utb_in.shape)
        else:
            make_outputs_scalar = False
        if xp_in.shape == tuple():
            xp_in = xp_in.reshape((1,) + xp_in.shape)
        else:
            make_outputs_scalar = False
        if yp_in.shape == tuple():
            yp_in = yp_in.reshape((1,) + yp_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tta_in, ttb_in, uta_in, utb_in, xp_in, yp_in)
    rc2t_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tta_in, ttb_in, uta_in, utb_in, xp_in, yp_in, rc2t_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*6 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._c2t00b(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc2t_out.shape) > 0 and rc2t_out.shape[0] == 1
        rc2t_out = rc2t_out.reshape(rc2t_out.shape[1:])

    return rc2t_out


def c2t06a(tta, ttb, uta, utb, xp, yp):
    """
    Wrapper for ERFA function ``eraC2t06a``.

    Parameters
    ----------
    tta : double array
    ttb : double array
    uta : double array
    utb : double array
    xp : double array
    yp : double array

    Returns
    -------
    rc2t : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a 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.

    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:
       eraC2i06a    celestial-to-intermediate matrix, IAU 2006/2000A
       eraEra00     Earth rotation angle, IAU 2000
       eraSp00      the TIO locator s', IERS 2000
       eraPom00     polar motion matrix
       eraC2tcio    form CIO-based celestial-to-terrestrial matrix

    Reference:

       McCarthy, D. D., Petit, G. (eds.), 2004, IERS Conventions (2003),
       IERS Technical Note No. 32, BKG

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tta_in = numpy.array(tta, dtype=numpy.double, order="C", copy=False, subok=True)
    ttb_in = numpy.array(ttb, dtype=numpy.double, order="C", copy=False, subok=True)
    uta_in = numpy.array(uta, dtype=numpy.double, order="C", copy=False, subok=True)
    utb_in = numpy.array(utb, dtype=numpy.double, order="C", copy=False, subok=True)
    xp_in = numpy.array(xp, dtype=numpy.double, order="C", copy=False, subok=True)
    yp_in = numpy.array(yp, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tta_in.shape == tuple():
            tta_in = tta_in.reshape((1,) + tta_in.shape)
        else:
            make_outputs_scalar = False
        if ttb_in.shape == tuple():
            ttb_in = ttb_in.reshape((1,) + ttb_in.shape)
        else:
            make_outputs_scalar = False
        if uta_in.shape == tuple():
            uta_in = uta_in.reshape((1,) + uta_in.shape)
        else:
            make_outputs_scalar = False
        if utb_in.shape == tuple():
            utb_in = utb_in.reshape((1,) + utb_in.shape)
        else:
            make_outputs_scalar = False
        if xp_in.shape == tuple():
            xp_in = xp_in.reshape((1,) + xp_in.shape)
        else:
            make_outputs_scalar = False
        if yp_in.shape == tuple():
            yp_in = yp_in.reshape((1,) + yp_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tta_in, ttb_in, uta_in, utb_in, xp_in, yp_in)
    rc2t_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tta_in, ttb_in, uta_in, utb_in, xp_in, yp_in, rc2t_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*6 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._c2t06a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc2t_out.shape) > 0 and rc2t_out.shape[0] == 1
        rc2t_out = rc2t_out.reshape(rc2t_out.shape[1:])

    return rc2t_out


def c2tcio(rc2i, era, rpom):
    """
    Wrapper for ERFA function ``eraC2tcio``.

    Parameters
    ----------
    rc2i : double array
    era : double array
    rpom : double array

    Returns
    -------
    rc2t : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a 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).

    Given:
       rc2i     double[3][3]    celestial-to-intermediate matrix
       era      double          Earth rotation angle (radians)
       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:
       eraCr        copy r-matrix
       eraRz        rotate around Z-axis
       eraRxr       product of two r-matrices

    Reference:

       McCarthy, D. D., Petit, G. (eds.), 2004, IERS Conventions (2003),
       IERS Technical Note No. 32, BKG

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    rc2i_in = numpy.array(rc2i, dtype=numpy.double, order="C", copy=False, subok=True)
    era_in = numpy.array(era, dtype=numpy.double, order="C", copy=False, subok=True)
    rpom_in = numpy.array(rpom, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(rc2i_in, (3, 3), "rc2i")
    check_trailing_shape(rpom_in, (3, 3), "rpom")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if rc2i_in[...,0,0].shape == tuple():
            rc2i_in = rc2i_in.reshape((1,) + rc2i_in.shape)
        else:
            make_outputs_scalar = False
        if era_in.shape == tuple():
            era_in = era_in.reshape((1,) + era_in.shape)
        else:
            make_outputs_scalar = False
        if rpom_in[...,0,0].shape == tuple():
            rpom_in = rpom_in.reshape((1,) + rpom_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), rc2i_in[...,0,0], era_in, rpom_in[...,0,0])
    rc2t_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [rc2i_in[...,0,0], era_in, rpom_in[...,0,0], rc2t_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._c2tcio(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc2t_out.shape) > 0 and rc2t_out.shape[0] == 1
        rc2t_out = rc2t_out.reshape(rc2t_out.shape[1:])

    return rc2t_out


def c2teqx(rbpn, gst, rpom):
    """
    Wrapper for ERFA function ``eraC2teqx``.

    Parameters
    ----------
    rbpn : double array
    gst : double array
    rpom : double array

    Returns
    -------
    rc2t : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a 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).

    Given:
       rbpn   double[3][3]  celestial-to-true matrix
       gst    double        Greenwich (apparent) Sidereal Time (radians)
       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:
       eraCr        copy r-matrix
       eraRz        rotate around Z-axis
       eraRxr       product of two r-matrices

    Reference:

       McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
       IERS Technical Note No. 32, BKG (2004)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    rbpn_in = numpy.array(rbpn, dtype=numpy.double, order="C", copy=False, subok=True)
    gst_in = numpy.array(gst, dtype=numpy.double, order="C", copy=False, subok=True)
    rpom_in = numpy.array(rpom, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(rbpn_in, (3, 3), "rbpn")
    check_trailing_shape(rpom_in, (3, 3), "rpom")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if rbpn_in[...,0,0].shape == tuple():
            rbpn_in = rbpn_in.reshape((1,) + rbpn_in.shape)
        else:
            make_outputs_scalar = False
        if gst_in.shape == tuple():
            gst_in = gst_in.reshape((1,) + gst_in.shape)
        else:
            make_outputs_scalar = False
        if rpom_in[...,0,0].shape == tuple():
            rpom_in = rpom_in.reshape((1,) + rpom_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), rbpn_in[...,0,0], gst_in, rpom_in[...,0,0])
    rc2t_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [rbpn_in[...,0,0], gst_in, rpom_in[...,0,0], rc2t_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._c2teqx(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc2t_out.shape) > 0 and rc2t_out.shape[0] == 1
        rc2t_out = rc2t_out.reshape(rc2t_out.shape[1:])

    return rc2t_out


def c2tpe(tta, ttb, uta, utb, dpsi, deps, xp, yp):
    """
    Wrapper for ERFA function ``eraC2tpe``.

    Parameters
    ----------
    tta : double array
    ttb : double array
    uta : double array
    utb : double array
    dpsi : double array
    deps : double array
    xp : double array
    yp : double array

    Returns
    -------
    rc2t : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a C 2 t p e
    - - - - - - - - -

    Form the celestial to terrestrial matrix given the date, the UT1,
    the nutation and the polar motion.  IAU 2000.

    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:
       eraPn00      bias/precession/nutation results, IAU 2000
       eraGmst00    Greenwich mean sidereal time, IAU 2000
       eraSp00      the TIO locator s', IERS 2000
       eraEe00      equation of the equinoxes, IAU 2000
       eraPom00     polar motion matrix
       eraC2teqx    form equinox-based celestial-to-terrestrial matrix

    Reference:

       McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
       IERS Technical Note No. 32, BKG (2004)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tta_in = numpy.array(tta, dtype=numpy.double, order="C", copy=False, subok=True)
    ttb_in = numpy.array(ttb, dtype=numpy.double, order="C", copy=False, subok=True)
    uta_in = numpy.array(uta, dtype=numpy.double, order="C", copy=False, subok=True)
    utb_in = numpy.array(utb, dtype=numpy.double, order="C", copy=False, subok=True)
    dpsi_in = numpy.array(dpsi, dtype=numpy.double, order="C", copy=False, subok=True)
    deps_in = numpy.array(deps, dtype=numpy.double, order="C", copy=False, subok=True)
    xp_in = numpy.array(xp, dtype=numpy.double, order="C", copy=False, subok=True)
    yp_in = numpy.array(yp, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tta_in.shape == tuple():
            tta_in = tta_in.reshape((1,) + tta_in.shape)
        else:
            make_outputs_scalar = False
        if ttb_in.shape == tuple():
            ttb_in = ttb_in.reshape((1,) + ttb_in.shape)
        else:
            make_outputs_scalar = False
        if uta_in.shape == tuple():
            uta_in = uta_in.reshape((1,) + uta_in.shape)
        else:
            make_outputs_scalar = False
        if utb_in.shape == tuple():
            utb_in = utb_in.reshape((1,) + utb_in.shape)
        else:
            make_outputs_scalar = False
        if dpsi_in.shape == tuple():
            dpsi_in = dpsi_in.reshape((1,) + dpsi_in.shape)
        else:
            make_outputs_scalar = False
        if deps_in.shape == tuple():
            deps_in = deps_in.reshape((1,) + deps_in.shape)
        else:
            make_outputs_scalar = False
        if xp_in.shape == tuple():
            xp_in = xp_in.reshape((1,) + xp_in.shape)
        else:
            make_outputs_scalar = False
        if yp_in.shape == tuple():
            yp_in = yp_in.reshape((1,) + yp_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tta_in, ttb_in, uta_in, utb_in, dpsi_in, deps_in, xp_in, yp_in)
    rc2t_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tta_in, ttb_in, uta_in, utb_in, dpsi_in, deps_in, xp_in, yp_in, rc2t_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*8 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._c2tpe(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc2t_out.shape) > 0 and rc2t_out.shape[0] == 1
        rc2t_out = rc2t_out.reshape(rc2t_out.shape[1:])

    return rc2t_out


def c2txy(tta, ttb, uta, utb, x, y, xp, yp):
    """
    Wrapper for ERFA function ``eraC2txy``.

    Parameters
    ----------
    tta : double array
    ttb : double array
    uta : double array
    utb : double array
    x : double array
    y : double array
    xp : double array
    yp : double array

    Returns
    -------
    rc2t : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a 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.

    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:
       eraC2ixy     celestial-to-intermediate matrix, given X,Y
       eraEra00     Earth rotation angle, IAU 2000
       eraSp00      the TIO locator s', IERS 2000
       eraPom00     polar motion matrix
       eraC2tcio    form CIO-based celestial-to-terrestrial matrix

   Reference:

       McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
       IERS Technical Note No. 32, BKG (2004)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tta_in = numpy.array(tta, dtype=numpy.double, order="C", copy=False, subok=True)
    ttb_in = numpy.array(ttb, dtype=numpy.double, order="C", copy=False, subok=True)
    uta_in = numpy.array(uta, dtype=numpy.double, order="C", copy=False, subok=True)
    utb_in = numpy.array(utb, dtype=numpy.double, order="C", copy=False, subok=True)
    x_in = numpy.array(x, dtype=numpy.double, order="C", copy=False, subok=True)
    y_in = numpy.array(y, dtype=numpy.double, order="C", copy=False, subok=True)
    xp_in = numpy.array(xp, dtype=numpy.double, order="C", copy=False, subok=True)
    yp_in = numpy.array(yp, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tta_in.shape == tuple():
            tta_in = tta_in.reshape((1,) + tta_in.shape)
        else:
            make_outputs_scalar = False
        if ttb_in.shape == tuple():
            ttb_in = ttb_in.reshape((1,) + ttb_in.shape)
        else:
            make_outputs_scalar = False
        if uta_in.shape == tuple():
            uta_in = uta_in.reshape((1,) + uta_in.shape)
        else:
            make_outputs_scalar = False
        if utb_in.shape == tuple():
            utb_in = utb_in.reshape((1,) + utb_in.shape)
        else:
            make_outputs_scalar = False
        if x_in.shape == tuple():
            x_in = x_in.reshape((1,) + x_in.shape)
        else:
            make_outputs_scalar = False
        if y_in.shape == tuple():
            y_in = y_in.reshape((1,) + y_in.shape)
        else:
            make_outputs_scalar = False
        if xp_in.shape == tuple():
            xp_in = xp_in.reshape((1,) + xp_in.shape)
        else:
            make_outputs_scalar = False
        if yp_in.shape == tuple():
            yp_in = yp_in.reshape((1,) + yp_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tta_in, ttb_in, uta_in, utb_in, x_in, y_in, xp_in, yp_in)
    rc2t_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tta_in, ttb_in, uta_in, utb_in, x_in, y_in, xp_in, yp_in, rc2t_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*8 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._c2txy(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rc2t_out.shape) > 0 and rc2t_out.shape[0] == 1
        rc2t_out = rc2t_out.reshape(rc2t_out.shape[1:])

    return rc2t_out


def eo06a(date1, date2):
    """
    Wrapper for ERFA function ``eraEo06a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a E o 0 6 a
    - - - - - - - - -

    Equation of the origins, IAU 2006 precession and IAU 2000A nutation.

    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:
       eraPnm06a    classical NPB matrix, IAU 2006/2000A
       eraBpn2xy    extract CIP X,Y coordinates from NPB matrix
       eraS06       the CIO locator s, given X,Y, IAU 2006
       eraEors      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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._eo06a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def eors(rnpb, s):
    """
    Wrapper for ERFA function ``eraEors``.

    Parameters
    ----------
    rnpb : double array
    s : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a E o r s
    - - - - - - - -

    Equation of the origins, given the classical NPB matrix and the
    quantity s.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    rnpb_in = numpy.array(rnpb, dtype=numpy.double, order="C", copy=False, subok=True)
    s_in = numpy.array(s, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(rnpb_in, (3, 3), "rnpb")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if rnpb_in[...,0,0].shape == tuple():
            rnpb_in = rnpb_in.reshape((1,) + rnpb_in.shape)
        else:
            make_outputs_scalar = False
        if s_in.shape == tuple():
            s_in = s_in.reshape((1,) + s_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), rnpb_in[...,0,0], s_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [rnpb_in[...,0,0], s_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._eors(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def fw2m(gamb, phib, psi, eps):
    """
    Wrapper for ERFA function ``eraFw2m``.

    Parameters
    ----------
    gamb : double array
    phib : double array
    psi : double array
    eps : double array

    Returns
    -------
    r : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a F w 2 m
    - - - - - - - -

    Form rotation matrix given the Fukushima-Williams angles.

    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:
       eraIr        initialize r-matrix to identity
       eraRz        rotate around Z-axis
       eraRx        rotate around X-axis

    Reference:

       Hilton, J. et al., 2006, Celest.Mech.Dyn.Astron. 94, 351

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    gamb_in = numpy.array(gamb, dtype=numpy.double, order="C", copy=False, subok=True)
    phib_in = numpy.array(phib, dtype=numpy.double, order="C", copy=False, subok=True)
    psi_in = numpy.array(psi, dtype=numpy.double, order="C", copy=False, subok=True)
    eps_in = numpy.array(eps, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if gamb_in.shape == tuple():
            gamb_in = gamb_in.reshape((1,) + gamb_in.shape)
        else:
            make_outputs_scalar = False
        if phib_in.shape == tuple():
            phib_in = phib_in.reshape((1,) + phib_in.shape)
        else:
            make_outputs_scalar = False
        if psi_in.shape == tuple():
            psi_in = psi_in.reshape((1,) + psi_in.shape)
        else:
            make_outputs_scalar = False
        if eps_in.shape == tuple():
            eps_in = eps_in.reshape((1,) + eps_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), gamb_in, phib_in, psi_in, eps_in)
    r_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [gamb_in, phib_in, psi_in, eps_in, r_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._fw2m(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(r_out.shape) > 0 and r_out.shape[0] == 1
        r_out = r_out.reshape(r_out.shape[1:])

    return r_out


def fw2xy(gamb, phib, psi, eps):
    """
    Wrapper for ERFA function ``eraFw2xy``.

    Parameters
    ----------
    gamb : double array
    phib : double array
    psi : double array
    eps : double array

    Returns
    -------
    x : double array
    y : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a F w 2 x y
    - - - - - - - - -

    CIP X,Y given Fukushima-Williams bias-precession-nutation angles.

    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 unit vector X,Y

    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)

       The returned values x,y are elements [2][0] and [2][1] of the
       matrix.  Near J2000.0, they are essentially angles in radians.

    Called:
       eraFw2m      F-W angles to r-matrix
       eraBpn2xy    extract CIP X,Y coordinates from NPB matrix

    Reference:

       Hilton, J. et al., 2006, Celest.Mech.Dyn.Astron. 94, 351

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    gamb_in = numpy.array(gamb, dtype=numpy.double, order="C", copy=False, subok=True)
    phib_in = numpy.array(phib, dtype=numpy.double, order="C", copy=False, subok=True)
    psi_in = numpy.array(psi, dtype=numpy.double, order="C", copy=False, subok=True)
    eps_in = numpy.array(eps, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if gamb_in.shape == tuple():
            gamb_in = gamb_in.reshape((1,) + gamb_in.shape)
        else:
            make_outputs_scalar = False
        if phib_in.shape == tuple():
            phib_in = phib_in.reshape((1,) + phib_in.shape)
        else:
            make_outputs_scalar = False
        if psi_in.shape == tuple():
            psi_in = psi_in.reshape((1,) + psi_in.shape)
        else:
            make_outputs_scalar = False
        if eps_in.shape == tuple():
            eps_in = eps_in.reshape((1,) + eps_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), gamb_in, phib_in, psi_in, eps_in)
    x_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    y_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [gamb_in, phib_in, psi_in, eps_in, x_out, y_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._fw2xy(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(x_out.shape) > 0 and x_out.shape[0] == 1
        x_out = x_out.reshape(x_out.shape[1:])
        assert len(y_out.shape) > 0 and y_out.shape[0] == 1
        y_out = y_out.reshape(y_out.shape[1:])

    return x_out, y_out


def ltp(epj):
    """
    Wrapper for ERFA function ``eraLtp``.

    Parameters
    ----------
    epj : double array

    Returns
    -------
    rp : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - -
     e r a L t p
    - - - - - - -

    Long-term precession matrix.

    Given:
       epj     double         Julian epoch (TT)

    Returned:
       rp      double[3][3]   precession matrix, J2000.0 to date

    Notes:

    1) The matrix is in the sense

          P_date = rp x P_J2000,

       where P_J2000 is a vector with respect to the J2000.0 mean
       equator and equinox and P_date is the same vector with respect to
       the equator and equinox of epoch epj.

    2) The Vondrak et al. (2011, 2012) 400 millennia precession model
       agrees with the IAU 2006 precession at J2000.0 and stays within
       100 microarcseconds during the 20th and 21st centuries.  It is
       accurate to a few arcseconds throughout the historical period,
       worsening to a few tenths of a degree at the end of the
       +/- 200,000 year time span.

    Called:
       eraLtpequ    equator pole, long term
       eraLtpecl    ecliptic pole, long term
       eraPxp       vector product
       eraPn        normalize vector

    References:

      Vondrak, J., Capitaine, N. and Wallace, P., 2011, New precession
      expressions, valid for long time intervals, Astron.Astrophys. 534,
      A22

      Vondrak, J., Capitaine, N. and Wallace, P., 2012, New precession
      expressions, valid for long time intervals (Corrigendum),
      Astron.Astrophys. 541, C1

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    epj_in = numpy.array(epj, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if epj_in.shape == tuple():
            epj_in = epj_in.reshape((1,) + epj_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), epj_in)
    rp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [epj_in, rp_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ltp(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rp_out.shape) > 0 and rp_out.shape[0] == 1
        rp_out = rp_out.reshape(rp_out.shape[1:])

    return rp_out


def ltpb(epj):
    """
    Wrapper for ERFA function ``eraLtpb``.

    Parameters
    ----------
    epj : double array

    Returns
    -------
    rpb : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a L t p b
    - - - - - - - -

    Long-term precession matrix, including ICRS frame bias.

    Given:
       epj     double         Julian epoch (TT)

    Returned:
       rpb     double[3][3]   precession-bias matrix, J2000.0 to date

    Notes:

    1) The matrix is in the sense

          P_date = rpb x P_ICRS,

       where P_ICRS is a vector in the Geocentric Celestial Reference
       System, and P_date is the vector with respect to the Celestial
       Intermediate Reference System at that date but with nutation
       neglected.

    2) A first order frame bias formulation is used, of sub-
       microarcsecond accuracy compared with a full 3D rotation.

    3) The Vondrak et al. (2011, 2012) 400 millennia precession model
       agrees with the IAU 2006 precession at J2000.0 and stays within
       100 microarcseconds during the 20th and 21st centuries.  It is
       accurate to a few arcseconds throughout the historical period,
       worsening to a few tenths of a degree at the end of the
       +/- 200,000 year time span.

    References:

      Vondrak, J., Capitaine, N. and Wallace, P., 2011, New precession
      expressions, valid for long time intervals, Astron.Astrophys. 534,
      A22

      Vondrak, J., Capitaine, N. and Wallace, P., 2012, New precession
      expressions, valid for long time intervals (Corrigendum),
      Astron.Astrophys. 541, C1

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    epj_in = numpy.array(epj, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if epj_in.shape == tuple():
            epj_in = epj_in.reshape((1,) + epj_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), epj_in)
    rpb_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [epj_in, rpb_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ltpb(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rpb_out.shape) > 0 and rpb_out.shape[0] == 1
        rpb_out = rpb_out.reshape(rpb_out.shape[1:])

    return rpb_out


def ltpecl(epj):
    """
    Wrapper for ERFA function ``eraLtpecl``.

    Parameters
    ----------
    epj : double array

    Returns
    -------
    vec : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a L t p e c l
    - - - - - - - - - -

    Long-term precession of the ecliptic.

    Given:
       epj     double         Julian epoch (TT)

    Returned:
       vec     double[3]      ecliptic pole unit vector

    Notes:

    1) The returned vector is with respect to the J2000.0 mean equator
       and equinox.

    2) The Vondrak et al. (2011, 2012) 400 millennia precession model
       agrees with the IAU 2006 precession at J2000.0 and stays within
       100 microarcseconds during the 20th and 21st centuries.  It is
       accurate to a few arcseconds throughout the historical period,
       worsening to a few tenths of a degree at the end of the
       +/- 200,000 year time span.

    References:

      Vondrak, J., Capitaine, N. and Wallace, P., 2011, New precession
      expressions, valid for long time intervals, Astron.Astrophys. 534,
      A22

      Vondrak, J., Capitaine, N. and Wallace, P., 2012, New precession
      expressions, valid for long time intervals (Corrigendum),
      Astron.Astrophys. 541, C1

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    epj_in = numpy.array(epj, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if epj_in.shape == tuple():
            epj_in = epj_in.reshape((1,) + epj_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), epj_in)
    vec_out = numpy.empty(broadcast.shape + (3,), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [epj_in, vec_out[...,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ltpecl(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(vec_out.shape) > 0 and vec_out.shape[0] == 1
        vec_out = vec_out.reshape(vec_out.shape[1:])

    return vec_out


def ltpequ(epj):
    """
    Wrapper for ERFA function ``eraLtpequ``.

    Parameters
    ----------
    epj : double array

    Returns
    -------
    veq : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a L t p e q u
    - - - - - - - - - -

    Long-term precession of the equator.

    Given:
       epj     double         Julian epoch (TT)

    Returned:
       veq     double[3]      equator pole unit vector

    Notes:

    1) The returned vector is with respect to the J2000.0 mean equator
       and equinox.

    2) The Vondrak et al. (2011, 2012) 400 millennia precession model
       agrees with the IAU 2006 precession at J2000.0 and stays within
       100 microarcseconds during the 20th and 21st centuries.  It is
       accurate to a few arcseconds throughout the historical period,
       worsening to a few tenths of a degree at the end of the
       +/- 200,000 year time span.

    References:

      Vondrak, J., Capitaine, N. and Wallace, P., 2011, New precession
      expressions, valid for long time intervals, Astron.Astrophys. 534,
      A22

      Vondrak, J., Capitaine, N. and Wallace, P., 2012, New precession
      expressions, valid for long time intervals (Corrigendum),
      Astron.Astrophys. 541, C1

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    epj_in = numpy.array(epj, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if epj_in.shape == tuple():
            epj_in = epj_in.reshape((1,) + epj_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), epj_in)
    veq_out = numpy.empty(broadcast.shape + (3,), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [epj_in, veq_out[...,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ltpequ(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(veq_out.shape) > 0 and veq_out.shape[0] == 1
        veq_out = veq_out.reshape(veq_out.shape[1:])

    return veq_out


def num00a(date1, date2):
    """
    Wrapper for ERFA function ``eraNum00a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rmatn : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a N u m 0 0 a
    - - - - - - - - - -

    Form the matrix of nutation for a given date, IAU 2000A model.

    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 eraNum00b function.

    Called:
       eraPn00a     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).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rmatn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rmatn_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._num00a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rmatn_out.shape) > 0 and rmatn_out.shape[0] == 1
        rmatn_out = rmatn_out.reshape(rmatn_out.shape[1:])

    return rmatn_out


def num00b(date1, date2):
    """
    Wrapper for ERFA function ``eraNum00b``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rmatn : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a N u m 0 0 b
    - - - - - - - - - -

    Form the matrix of nutation for a given date, IAU 2000B model.

    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 eraNum00a function.

    Called:
       eraPn00b     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).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rmatn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rmatn_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._num00b(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rmatn_out.shape) > 0 and rmatn_out.shape[0] == 1
        rmatn_out = rmatn_out.reshape(rmatn_out.shape[1:])

    return rmatn_out


def num06a(date1, date2):
    """
    Wrapper for ERFA function ``eraNum06a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rmatn : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a N u m 0 6 a
    - - - - - - - - - -

    Form the matrix of nutation for a given date, IAU 2006/2000A model.

    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:
       eraObl06     mean obliquity, IAU 2006
       eraNut06a    nutation, IAU 2006/2000A
       eraNumat     form nutation matrix

    Reference:

       Explanatory Supplement to the Astronomical Almanac,
       P. Kenneth Seidelmann (ed), University Science Books (1992),
       Section 3.222-3 (p114).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rmatn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rmatn_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._num06a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rmatn_out.shape) > 0 and rmatn_out.shape[0] == 1
        rmatn_out = rmatn_out.reshape(rmatn_out.shape[1:])

    return rmatn_out


def numat(epsa, dpsi, deps):
    """
    Wrapper for ERFA function ``eraNumat``.

    Parameters
    ----------
    epsa : double array
    dpsi : double array
    deps : double array

    Returns
    -------
    rmatn : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a N u m a t
    - - - - - - - - -

    Form the matrix of nutation.

    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:
       eraIr        initialize r-matrix to identity
       eraRx        rotate around X-axis
       eraRz        rotate around Z-axis

    Reference:

       Explanatory Supplement to the Astronomical Almanac,
       P. Kenneth Seidelmann (ed), University Science Books (1992),
       Section 3.222-3 (p114).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    epsa_in = numpy.array(epsa, dtype=numpy.double, order="C", copy=False, subok=True)
    dpsi_in = numpy.array(dpsi, dtype=numpy.double, order="C", copy=False, subok=True)
    deps_in = numpy.array(deps, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if epsa_in.shape == tuple():
            epsa_in = epsa_in.reshape((1,) + epsa_in.shape)
        else:
            make_outputs_scalar = False
        if dpsi_in.shape == tuple():
            dpsi_in = dpsi_in.reshape((1,) + dpsi_in.shape)
        else:
            make_outputs_scalar = False
        if deps_in.shape == tuple():
            deps_in = deps_in.reshape((1,) + deps_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), epsa_in, dpsi_in, deps_in)
    rmatn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [epsa_in, dpsi_in, deps_in, rmatn_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._numat(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rmatn_out.shape) > 0 and rmatn_out.shape[0] == 1
        rmatn_out = rmatn_out.reshape(rmatn_out.shape[1:])

    return rmatn_out


def nut00a(date1, date2):
    """
    Wrapper for ERFA function ``eraNut00a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    dpsi : double array
    deps : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a N u t 0 0 a
    - - - - - - - - - -

    Nutation, IAU 2000A model (MHB2000 luni-solar and planetary nutation
    with free core nutation omitted).

    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 ERFA functions eraBi00  and
       eraPr00.

    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 eraPmat76,  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 ERFA functions do not generate the "total
       nutations" directly, though they can of course easily be
       generated by calling eraBi00, eraPr00 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:
       eraFal03     mean anomaly of the Moon
       eraFaf03     mean argument of the latitude of the Moon
       eraFaom03    mean longitude of the Moon's ascending node
       eraFame03    mean longitude of Mercury
       eraFave03    mean longitude of Venus
       eraFae03     mean longitude of Earth
       eraFama03    mean longitude of Mars
       eraFaju03    mean longitude of Jupiter
       eraFasa03    mean longitude of Saturn
       eraFaur03    mean longitude of Uranus
       eraFapa03    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    dpsi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    deps_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, dpsi_out, deps_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._nut00a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(dpsi_out.shape) > 0 and dpsi_out.shape[0] == 1
        dpsi_out = dpsi_out.reshape(dpsi_out.shape[1:])
        assert len(deps_out.shape) > 0 and deps_out.shape[0] == 1
        deps_out = deps_out.reshape(deps_out.shape[1:])

    return dpsi_out, deps_out


def nut00b(date1, date2):
    """
    Wrapper for ERFA function ``eraNut00b``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    dpsi : double array
    deps : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a N u t 0 0 b
    - - - - - - - - - -

    Nutation, IAU 2000B 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 eraNut00a (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 ERFA functions
       eraBi00  and eraPr00.

    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 eraPmat76,  to deliver GCRS-
       to-true predictions of mas accuracy at current epochs.  However,
       for symmetry with the eraNut00a  function (q.v. for the reasons),
       the ERFA functions do not generate the "total nutations"
       directly.  Should they be required, they could of course easily
       be generated by calling eraBi00, eraPr00 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 ERFA 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 ERFA
       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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    dpsi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    deps_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, dpsi_out, deps_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._nut00b(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(dpsi_out.shape) > 0 and dpsi_out.shape[0] == 1
        dpsi_out = dpsi_out.reshape(dpsi_out.shape[1:])
        assert len(deps_out.shape) > 0 and deps_out.shape[0] == 1
        deps_out = deps_out.reshape(deps_out.shape[1:])

    return dpsi_out, deps_out


def nut06a(date1, date2):
    """
    Wrapper for ERFA function ``eraNut06a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    dpsi : double array
    deps : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a 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)

    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:
       eraNut00a    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    dpsi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    deps_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, dpsi_out, deps_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._nut06a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(dpsi_out.shape) > 0 and dpsi_out.shape[0] == 1
        dpsi_out = dpsi_out.reshape(dpsi_out.shape[1:])
        assert len(deps_out.shape) > 0 and deps_out.shape[0] == 1
        deps_out = deps_out.reshape(deps_out.shape[1:])

    return dpsi_out, deps_out


def nut80(date1, date2):
    """
    Wrapper for ERFA function ``eraNut80``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    dpsi : double array
    deps : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a N u t 8 0
    - - - - - - - - -

    Nutation, IAU 1980 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:
       eraAnpm      normalize angle into range +/- pi

    Reference:

       Explanatory Supplement to the Astronomical Almanac,
       P. Kenneth Seidelmann (ed), University Science Books (1992),
       Section 3.222 (p111).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    dpsi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    deps_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, dpsi_out, deps_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._nut80(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(dpsi_out.shape) > 0 and dpsi_out.shape[0] == 1
        dpsi_out = dpsi_out.reshape(dpsi_out.shape[1:])
        assert len(deps_out.shape) > 0 and deps_out.shape[0] == 1
        deps_out = deps_out.reshape(deps_out.shape[1:])

    return dpsi_out, deps_out


def nutm80(date1, date2):
    """
    Wrapper for ERFA function ``eraNutm80``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rmatn : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a N u t m 8 0
    - - - - - - - - - -

    Form the matrix of nutation for a given date, IAU 1980 model.

    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:
       eraNut80     nutation, IAU 1980
       eraObl80     mean obliquity, IAU 1980
       eraNumat     form nutation matrix

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rmatn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rmatn_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._nutm80(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rmatn_out.shape) > 0 and rmatn_out.shape[0] == 1
        rmatn_out = rmatn_out.reshape(rmatn_out.shape[1:])

    return rmatn_out


def obl06(date1, date2):
    """
    Wrapper for ERFA function ``eraObl06``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a O b l 0 6
    - - - - - - - - -

    Mean obliquity of the ecliptic, IAU 2006 precession 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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._obl06(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def obl80(date1, date2):
    """
    Wrapper for ERFA function ``eraObl80``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a O b l 8 0
    - - - - - - - - -

    Mean obliquity of the ecliptic, IAU 1980 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).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._obl80(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def p06e(date1, date2):
    """
    Wrapper for ERFA function ``eraP06e``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    eps0 : double array
    psia : double array
    oma : double array
    bpa : double array
    bqa : double array
    pia : double array
    bpia : double array
    epsa : double array
    chia : double array
    za : double array
    zetaa : double array
    thetaa : double array
    pa : double array
    gam : double array
    phi : double array
    psi : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a P 0 6 e
    - - - - - - - -

    Precession angles, IAU 2006, equinox based.

    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 ERFA functions:

       . eraXy06  contains the polynomial parts of the X and Y series.

       . eraS06  contains the polynomial part of the s+XY/2 series.

       . eraPfw06  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 ERFA is the version of the Fukushima-
       Williams angles that refers directly to the GCRS pole.  These
       angles may be calculated by calling the function eraPfw06.  ERFA
       also supports the direct computation of the CIP GCRS X,Y by
       series, available by calling eraXy06.

    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:
       eraObl06     mean obliquity, IAU 2006

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    eps0_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    psia_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    oma_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    bpa_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    bqa_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    pia_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    bpia_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    epsa_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    chia_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    za_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    zetaa_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    thetaa_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    pa_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    gam_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    phi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    psi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, eps0_out, psia_out, oma_out, bpa_out, bqa_out, pia_out, bpia_out, epsa_out, chia_out, za_out, zetaa_out, thetaa_out, pa_out, gam_out, phi_out, psi_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*16
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._p06e(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(eps0_out.shape) > 0 and eps0_out.shape[0] == 1
        eps0_out = eps0_out.reshape(eps0_out.shape[1:])
        assert len(psia_out.shape) > 0 and psia_out.shape[0] == 1
        psia_out = psia_out.reshape(psia_out.shape[1:])
        assert len(oma_out.shape) > 0 and oma_out.shape[0] == 1
        oma_out = oma_out.reshape(oma_out.shape[1:])
        assert len(bpa_out.shape) > 0 and bpa_out.shape[0] == 1
        bpa_out = bpa_out.reshape(bpa_out.shape[1:])
        assert len(bqa_out.shape) > 0 and bqa_out.shape[0] == 1
        bqa_out = bqa_out.reshape(bqa_out.shape[1:])
        assert len(pia_out.shape) > 0 and pia_out.shape[0] == 1
        pia_out = pia_out.reshape(pia_out.shape[1:])
        assert len(bpia_out.shape) > 0 and bpia_out.shape[0] == 1
        bpia_out = bpia_out.reshape(bpia_out.shape[1:])
        assert len(epsa_out.shape) > 0 and epsa_out.shape[0] == 1
        epsa_out = epsa_out.reshape(epsa_out.shape[1:])
        assert len(chia_out.shape) > 0 and chia_out.shape[0] == 1
        chia_out = chia_out.reshape(chia_out.shape[1:])
        assert len(za_out.shape) > 0 and za_out.shape[0] == 1
        za_out = za_out.reshape(za_out.shape[1:])
        assert len(zetaa_out.shape) > 0 and zetaa_out.shape[0] == 1
        zetaa_out = zetaa_out.reshape(zetaa_out.shape[1:])
        assert len(thetaa_out.shape) > 0 and thetaa_out.shape[0] == 1
        thetaa_out = thetaa_out.reshape(thetaa_out.shape[1:])
        assert len(pa_out.shape) > 0 and pa_out.shape[0] == 1
        pa_out = pa_out.reshape(pa_out.shape[1:])
        assert len(gam_out.shape) > 0 and gam_out.shape[0] == 1
        gam_out = gam_out.reshape(gam_out.shape[1:])
        assert len(phi_out.shape) > 0 and phi_out.shape[0] == 1
        phi_out = phi_out.reshape(phi_out.shape[1:])
        assert len(psi_out.shape) > 0 and psi_out.shape[0] == 1
        psi_out = psi_out.reshape(psi_out.shape[1:])

    return eps0_out, psia_out, oma_out, bpa_out, bqa_out, pia_out, bpia_out, epsa_out, chia_out, za_out, zetaa_out, thetaa_out, pa_out, gam_out, phi_out, psi_out


def pb06(date1, date2):
    """
    Wrapper for ERFA function ``eraPb06``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    bzeta : double array
    bz : double array
    btheta : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a 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.

    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 ERFA
       function eraP06e.

    Called:
       eraPmat06    PB matrix, IAU 2006
       eraRz        rotate around Z-axis

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    bzeta_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    bz_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    btheta_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, bzeta_out, bz_out, btheta_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pb06(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(bzeta_out.shape) > 0 and bzeta_out.shape[0] == 1
        bzeta_out = bzeta_out.reshape(bzeta_out.shape[1:])
        assert len(bz_out.shape) > 0 and bz_out.shape[0] == 1
        bz_out = bz_out.reshape(bz_out.shape[1:])
        assert len(btheta_out.shape) > 0 and btheta_out.shape[0] == 1
        btheta_out = btheta_out.reshape(btheta_out.shape[1:])

    return bzeta_out, bz_out, btheta_out


def pfw06(date1, date2):
    """
    Wrapper for ERFA function ``eraPfw06``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    gamb : double array
    phib : double array
    psib : double array
    epsa : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a P f w 0 6
    - - - - - - - - -

    Precession angles, IAU 2006 (Fukushima-Williams 4-angle formulation).

    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:
       eraObl06     mean obliquity, IAU 2006

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    gamb_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    phib_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    psib_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    epsa_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, gamb_out, phib_out, psib_out, epsa_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*4
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pfw06(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(gamb_out.shape) > 0 and gamb_out.shape[0] == 1
        gamb_out = gamb_out.reshape(gamb_out.shape[1:])
        assert len(phib_out.shape) > 0 and phib_out.shape[0] == 1
        phib_out = phib_out.reshape(phib_out.shape[1:])
        assert len(psib_out.shape) > 0 and psib_out.shape[0] == 1
        psib_out = psib_out.reshape(psib_out.shape[1:])
        assert len(epsa_out.shape) > 0 and epsa_out.shape[0] == 1
        epsa_out = epsa_out.reshape(epsa_out.shape[1:])

    return gamb_out, phib_out, psib_out, epsa_out


def pmat00(date1, date2):
    """
    Wrapper for ERFA function ``eraPmat00``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rbp : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a P m a t 0 0
    - - - - - - - - - -

    Precession matrix (including frame bias) from GCRS to a specified
    date, IAU 2000 model.

    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:
       eraBp00      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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rbp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rbp_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pmat00(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rbp_out.shape) > 0 and rbp_out.shape[0] == 1
        rbp_out = rbp_out.reshape(rbp_out.shape[1:])

    return rbp_out


def pmat06(date1, date2):
    """
    Wrapper for ERFA function ``eraPmat06``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rbp : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a P m a t 0 6
    - - - - - - - - - -

    Precession matrix (including frame bias) from GCRS to a specified
    date, IAU 2006 model.

    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:
       eraPfw06     bias-precession F-W angles, IAU 2006
       eraFw2m      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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rbp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rbp_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pmat06(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rbp_out.shape) > 0 and rbp_out.shape[0] == 1
        rbp_out = rbp_out.reshape(rbp_out.shape[1:])

    return rbp_out


def pmat76(date1, date2):
    """
    Wrapper for ERFA function ``eraPmat76``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rmatp : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a P m a t 7 6
    - - - - - - - - - -

    Precession matrix from J2000.0 to a specified date, IAU 1976 model.

    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:
       eraPrec76    accumulated precession angles, IAU 1976
       eraIr        initialize r-matrix to identity
       eraRz        rotate around Z-axis
       eraRy        rotate around Y-axis
       eraCr        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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rmatp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rmatp_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pmat76(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rmatp_out.shape) > 0 and rmatp_out.shape[0] == 1
        rmatp_out = rmatp_out.reshape(rmatp_out.shape[1:])

    return rmatp_out


def pn00(date1, date2, dpsi, deps):
    """
    Wrapper for ERFA function ``eraPn00``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    dpsi : double array
    deps : double array

    Returns
    -------
    epsa : double array
    rb : double array
    rp : double array
    rbp : double array
    rn : double array
    rbpn : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a P n 0 0
    - - - - - - - -

    Precession-nutation, IAU 2000 model:  a multi-purpose function,
    supporting classical (equinox-based) use directly and CIO-based
    use indirectly.

    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:
       eraPr00      IAU 2000 precession adjustments
       eraObl80     mean obliquity, IAU 1980
       eraBp00      frame bias and precession matrices, IAU 2000
       eraCr        copy r-matrix
       eraNumat     form nutation matrix
       eraRxr       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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    dpsi_in = numpy.array(dpsi, dtype=numpy.double, order="C", copy=False, subok=True)
    deps_in = numpy.array(deps, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if dpsi_in.shape == tuple():
            dpsi_in = dpsi_in.reshape((1,) + dpsi_in.shape)
        else:
            make_outputs_scalar = False
        if deps_in.shape == tuple():
            deps_in = deps_in.reshape((1,) + deps_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, dpsi_in, deps_in)
    epsa_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    rb_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rbp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rbpn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, dpsi_in, deps_in, epsa_out, rb_out[...,0,0], rp_out[...,0,0], rbp_out[...,0,0], rn_out[...,0,0], rbpn_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*6
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pn00(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(epsa_out.shape) > 0 and epsa_out.shape[0] == 1
        epsa_out = epsa_out.reshape(epsa_out.shape[1:])
        assert len(rb_out.shape) > 0 and rb_out.shape[0] == 1
        rb_out = rb_out.reshape(rb_out.shape[1:])
        assert len(rp_out.shape) > 0 and rp_out.shape[0] == 1
        rp_out = rp_out.reshape(rp_out.shape[1:])
        assert len(rbp_out.shape) > 0 and rbp_out.shape[0] == 1
        rbp_out = rbp_out.reshape(rbp_out.shape[1:])
        assert len(rn_out.shape) > 0 and rn_out.shape[0] == 1
        rn_out = rn_out.reshape(rn_out.shape[1:])
        assert len(rbpn_out.shape) > 0 and rbpn_out.shape[0] == 1
        rbpn_out = rbpn_out.reshape(rbpn_out.shape[1:])

    return epsa_out, rb_out, rp_out, rbp_out, rn_out, rbpn_out


def pn00a(date1, date2):
    """
    Wrapper for ERFA function ``eraPn00a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    dpsi : double array
    deps : double array
    epsa : double array
    rb : double array
    rp : double array
    rbp : double array
    rn : double array
    rbpn : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a 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.

    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 eraPn00  function, where the
        nutation components are caller-specified.  For faster but
        slightly less accurate results, use the eraPn00b 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 2000A Celestial Intermediate
        Pole are elements (3,1-3) of the GCRS-to-true matrix,
        i.e. rbpn[2][0-2].

    10) It is permissible to re-use the same array in the returned
        arguments.  The arrays are filled in the order given.

    Called:
       eraNut00a    nutation, IAU 2000A
       eraPn00      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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    dpsi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    deps_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    epsa_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    rb_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rbp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rbpn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, dpsi_out, deps_out, epsa_out, rb_out[...,0,0], rp_out[...,0,0], rbp_out[...,0,0], rn_out[...,0,0], rbpn_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*8
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pn00a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(dpsi_out.shape) > 0 and dpsi_out.shape[0] == 1
        dpsi_out = dpsi_out.reshape(dpsi_out.shape[1:])
        assert len(deps_out.shape) > 0 and deps_out.shape[0] == 1
        deps_out = deps_out.reshape(deps_out.shape[1:])
        assert len(epsa_out.shape) > 0 and epsa_out.shape[0] == 1
        epsa_out = epsa_out.reshape(epsa_out.shape[1:])
        assert len(rb_out.shape) > 0 and rb_out.shape[0] == 1
        rb_out = rb_out.reshape(rb_out.shape[1:])
        assert len(rp_out.shape) > 0 and rp_out.shape[0] == 1
        rp_out = rp_out.reshape(rp_out.shape[1:])
        assert len(rbp_out.shape) > 0 and rbp_out.shape[0] == 1
        rbp_out = rbp_out.reshape(rbp_out.shape[1:])
        assert len(rn_out.shape) > 0 and rn_out.shape[0] == 1
        rn_out = rn_out.reshape(rn_out.shape[1:])
        assert len(rbpn_out.shape) > 0 and rbpn_out.shape[0] == 1
        rbpn_out = rbpn_out.reshape(rbpn_out.shape[1:])

    return dpsi_out, deps_out, epsa_out, rb_out, rp_out, rbp_out, rn_out, rbpn_out


def pn00b(date1, date2):
    """
    Wrapper for ERFA function ``eraPn00b``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    dpsi : double array
    deps : double array
    epsa : double array
    rb : double array
    rp : double array
    rbp : double array
    rn : double array
    rbpn : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a 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.

    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 eraPn00a function.
        For the utmost accuracy, use the eraPn00  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 GCRS-to-true matrix,
        i.e. rbpn[2][0-2].

    10) It is permissible to re-use the same array in the returned
        arguments.  The arrays are filled in the stated order.

    Called:
       eraNut00b    nutation, IAU 2000B
       eraPn00      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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    dpsi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    deps_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    epsa_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    rb_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rbp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rbpn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, dpsi_out, deps_out, epsa_out, rb_out[...,0,0], rp_out[...,0,0], rbp_out[...,0,0], rn_out[...,0,0], rbpn_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*8
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pn00b(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(dpsi_out.shape) > 0 and dpsi_out.shape[0] == 1
        dpsi_out = dpsi_out.reshape(dpsi_out.shape[1:])
        assert len(deps_out.shape) > 0 and deps_out.shape[0] == 1
        deps_out = deps_out.reshape(deps_out.shape[1:])
        assert len(epsa_out.shape) > 0 and epsa_out.shape[0] == 1
        epsa_out = epsa_out.reshape(epsa_out.shape[1:])
        assert len(rb_out.shape) > 0 and rb_out.shape[0] == 1
        rb_out = rb_out.reshape(rb_out.shape[1:])
        assert len(rp_out.shape) > 0 and rp_out.shape[0] == 1
        rp_out = rp_out.reshape(rp_out.shape[1:])
        assert len(rbp_out.shape) > 0 and rbp_out.shape[0] == 1
        rbp_out = rbp_out.reshape(rbp_out.shape[1:])
        assert len(rn_out.shape) > 0 and rn_out.shape[0] == 1
        rn_out = rn_out.reshape(rn_out.shape[1:])
        assert len(rbpn_out.shape) > 0 and rbpn_out.shape[0] == 1
        rbpn_out = rbpn_out.reshape(rbpn_out.shape[1:])

    return dpsi_out, deps_out, epsa_out, rb_out, rp_out, rbp_out, rn_out, rbpn_out


def pn06(date1, date2, dpsi, deps):
    """
    Wrapper for ERFA function ``eraPn06``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    dpsi : double array
    deps : double array

    Returns
    -------
    epsa : double array
    rb : double array
    rp : double array
    rbp : double array
    rn : double array
    rbpn : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a P n 0 6
    - - - - - - - -

    Precession-nutation, IAU 2006 model:  a multi-purpose function,
    supporting classical (equinox-based) use directly and CIO-based use
    indirectly.

    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 Celestial Intermediate Pole are
        elements (3,1-3) of the GCRS-to-true matrix, i.e. rbpn[2][0-2].

    10) It is permissible to re-use the same array in the returned
        arguments.  The arrays are filled in the stated order.

    Called:
       eraPfw06     bias-precession F-W angles, IAU 2006
       eraFw2m      F-W angles to r-matrix
       eraCr        copy r-matrix
       eraTr        transpose r-matrix
       eraRxr       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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    dpsi_in = numpy.array(dpsi, dtype=numpy.double, order="C", copy=False, subok=True)
    deps_in = numpy.array(deps, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if dpsi_in.shape == tuple():
            dpsi_in = dpsi_in.reshape((1,) + dpsi_in.shape)
        else:
            make_outputs_scalar = False
        if deps_in.shape == tuple():
            deps_in = deps_in.reshape((1,) + deps_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, dpsi_in, deps_in)
    epsa_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    rb_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rbp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rbpn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, dpsi_in, deps_in, epsa_out, rb_out[...,0,0], rp_out[...,0,0], rbp_out[...,0,0], rn_out[...,0,0], rbpn_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*6
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pn06(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(epsa_out.shape) > 0 and epsa_out.shape[0] == 1
        epsa_out = epsa_out.reshape(epsa_out.shape[1:])
        assert len(rb_out.shape) > 0 and rb_out.shape[0] == 1
        rb_out = rb_out.reshape(rb_out.shape[1:])
        assert len(rp_out.shape) > 0 and rp_out.shape[0] == 1
        rp_out = rp_out.reshape(rp_out.shape[1:])
        assert len(rbp_out.shape) > 0 and rbp_out.shape[0] == 1
        rbp_out = rbp_out.reshape(rbp_out.shape[1:])
        assert len(rn_out.shape) > 0 and rn_out.shape[0] == 1
        rn_out = rn_out.reshape(rn_out.shape[1:])
        assert len(rbpn_out.shape) > 0 and rbpn_out.shape[0] == 1
        rbpn_out = rbpn_out.reshape(rbpn_out.shape[1:])

    return epsa_out, rb_out, rp_out, rbp_out, rn_out, rbpn_out


def pn06a(date1, date2):
    """
    Wrapper for ERFA function ``eraPn06a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    dpsi : double array
    deps : double array
    epsa : double array
    rb : double array
    rp : double array
    rbp : double array
    rn : double array
    rbpn : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a 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.

    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 eraPn06 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 (3,1-3) of the GCRS-to-true
        matrix, i.e. rbpn[2][0-2].

    10) It is permissible to re-use the same array in the returned
        arguments.  The arrays are filled in the stated order.

    Called:
       eraNut06a    nutation, IAU 2006/2000A
       eraPn06      bias/precession/nutation results, IAU 2006

    Reference:

       Capitaine, N. & Wallace, P.T., 2006, Astron.Astrophys. 450, 855

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    dpsi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    deps_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    epsa_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    rb_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rbp_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    rbpn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, dpsi_out, deps_out, epsa_out, rb_out[...,0,0], rp_out[...,0,0], rbp_out[...,0,0], rn_out[...,0,0], rbpn_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*8
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pn06a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(dpsi_out.shape) > 0 and dpsi_out.shape[0] == 1
        dpsi_out = dpsi_out.reshape(dpsi_out.shape[1:])
        assert len(deps_out.shape) > 0 and deps_out.shape[0] == 1
        deps_out = deps_out.reshape(deps_out.shape[1:])
        assert len(epsa_out.shape) > 0 and epsa_out.shape[0] == 1
        epsa_out = epsa_out.reshape(epsa_out.shape[1:])
        assert len(rb_out.shape) > 0 and rb_out.shape[0] == 1
        rb_out = rb_out.reshape(rb_out.shape[1:])
        assert len(rp_out.shape) > 0 and rp_out.shape[0] == 1
        rp_out = rp_out.reshape(rp_out.shape[1:])
        assert len(rbp_out.shape) > 0 and rbp_out.shape[0] == 1
        rbp_out = rbp_out.reshape(rbp_out.shape[1:])
        assert len(rn_out.shape) > 0 and rn_out.shape[0] == 1
        rn_out = rn_out.reshape(rn_out.shape[1:])
        assert len(rbpn_out.shape) > 0 and rbpn_out.shape[0] == 1
        rbpn_out = rbpn_out.reshape(rbpn_out.shape[1:])

    return dpsi_out, deps_out, epsa_out, rb_out, rp_out, rbp_out, rn_out, rbpn_out


def pnm00a(date1, date2):
    """
    Wrapper for ERFA function ``eraPnm00a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rbpn : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a P n m 0 0 a
    - - - - - - - - - -

    Form the matrix of precession-nutation for a given date (including
    frame bias), equinox-based, IAU 2000A model.

    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 eraPnm00b function.

    Called:
       eraPn00a     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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rbpn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rbpn_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pnm00a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rbpn_out.shape) > 0 and rbpn_out.shape[0] == 1
        rbpn_out = rbpn_out.reshape(rbpn_out.shape[1:])

    return rbpn_out


def pnm00b(date1, date2):
    """
    Wrapper for ERFA function ``eraPnm00b``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rbpn : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a P n m 0 0 b
    - - - - - - - - - -

    Form the matrix of precession-nutation for a given date (including
    frame bias), equinox-based, IAU 2000B model.

    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 eraPnm00a function.

    Called:
       eraPn00b     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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rbpn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rbpn_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pnm00b(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rbpn_out.shape) > 0 and rbpn_out.shape[0] == 1
        rbpn_out = rbpn_out.reshape(rbpn_out.shape[1:])

    return rbpn_out


def pnm06a(date1, date2):
    """
    Wrapper for ERFA function ``eraPnm06a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rnpb : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a 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.

    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:
       eraPfw06     bias-precession F-W angles, IAU 2006
       eraNut06a    nutation, IAU 2006/2000A
       eraFw2m      F-W angles to r-matrix

    Reference:

       Capitaine, N. & Wallace, P.T., 2006, Astron.Astrophys. 450, 855.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rnpb_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rnpb_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pnm06a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rnpb_out.shape) > 0 and rnpb_out.shape[0] == 1
        rnpb_out = rnpb_out.reshape(rnpb_out.shape[1:])

    return rnpb_out


def pnm80(date1, date2):
    """
    Wrapper for ERFA function ``eraPnm80``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rmatpn : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a P n m 8 0
    - - - - - - - - -

    Form the matrix of precession/nutation for a given date, IAU 1976
    precession model, IAU 1980 nutation model.

    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:
       eraPmat76    precession matrix, IAU 1976
       eraNutm80    nutation matrix, IAU 1980
       eraRxr       product of two r-matrices

    Reference:

       Explanatory Supplement to the Astronomical Almanac,
       P. Kenneth Seidelmann (ed), University Science Books (1992),
       Section 3.3 (p145).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rmatpn_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rmatpn_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pnm80(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rmatpn_out.shape) > 0 and rmatpn_out.shape[0] == 1
        rmatpn_out = rmatpn_out.reshape(rmatpn_out.shape[1:])

    return rmatpn_out


def pom00(xp, yp, sp):
    """
    Wrapper for ERFA function ``eraPom00``.

    Parameters
    ----------
    xp : double array
    yp : double array
    sp : double array

    Returns
    -------
    rpom : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a P o m 0 0
    - - - - - - - - - -

    Form the matrix of polar motion for a given date, IAU 2000.

    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 eraSp00
       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:
       eraIr        initialize r-matrix to identity
       eraRz        rotate around Z-axis
       eraRy        rotate around Y-axis
       eraRx        rotate around X-axis

    Reference:

       McCarthy, D. D., Petit, G. (eds.), IERS Conventions (2003),
       IERS Technical Note No. 32, BKG (2004)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    xp_in = numpy.array(xp, dtype=numpy.double, order="C", copy=False, subok=True)
    yp_in = numpy.array(yp, dtype=numpy.double, order="C", copy=False, subok=True)
    sp_in = numpy.array(sp, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if xp_in.shape == tuple():
            xp_in = xp_in.reshape((1,) + xp_in.shape)
        else:
            make_outputs_scalar = False
        if yp_in.shape == tuple():
            yp_in = yp_in.reshape((1,) + yp_in.shape)
        else:
            make_outputs_scalar = False
        if sp_in.shape == tuple():
            sp_in = sp_in.reshape((1,) + sp_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), xp_in, yp_in, sp_in)
    rpom_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [xp_in, yp_in, sp_in, rpom_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pom00(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rpom_out.shape) > 0 and rpom_out.shape[0] == 1
        rpom_out = rpom_out.reshape(rpom_out.shape[1:])

    return rpom_out


def pr00(date1, date2):
    """
    Wrapper for ERFA function ``eraPr00``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    dpsipr : double array
    depspr : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a P r 0 0
    - - - - - - - -

    Precession-rate part of the IAU 2000 precession-nutation models
    (part of MHB2000).

    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).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    dpsipr_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    depspr_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, dpsipr_out, depspr_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pr00(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(dpsipr_out.shape) > 0 and dpsipr_out.shape[0] == 1
        dpsipr_out = dpsipr_out.reshape(dpsipr_out.shape[1:])
        assert len(depspr_out.shape) > 0 and depspr_out.shape[0] == 1
        depspr_out = depspr_out.reshape(depspr_out.shape[1:])

    return dpsipr_out, depspr_out


def prec76(date01, date02, date11, date12):
    """
    Wrapper for ERFA function ``eraPrec76``.

    Parameters
    ----------
    date01 : double array
    date02 : double array
    date11 : double array
    date12 : double array

    Returns
    -------
    zeta : double array
    z : double array
    theta : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a P r e c 7 6
    - - - - - - - - - -

    IAU 1976 precession model.

    This function forms the three Euler angles which implement general
    precession between two dates, using the IAU 1976 model (as for the
    FK5 catalog).

    Given:
       date01,date02   double    TDB starting date (Note 1)
       date11,date12   double    TDB ending date (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 dates date01+date02 and date11+date12 are Julian Dates,
       apportioned in any convenient way between the arguments daten1
       and daten2.  For example, JD(TDB)=2450123.7 could be expressed in
       any of these ways, among others:

             daten1        daten2

           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 dates 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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date01_in = numpy.array(date01, dtype=numpy.double, order="C", copy=False, subok=True)
    date02_in = numpy.array(date02, dtype=numpy.double, order="C", copy=False, subok=True)
    date11_in = numpy.array(date11, dtype=numpy.double, order="C", copy=False, subok=True)
    date12_in = numpy.array(date12, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date01_in.shape == tuple():
            date01_in = date01_in.reshape((1,) + date01_in.shape)
        else:
            make_outputs_scalar = False
        if date02_in.shape == tuple():
            date02_in = date02_in.reshape((1,) + date02_in.shape)
        else:
            make_outputs_scalar = False
        if date11_in.shape == tuple():
            date11_in = date11_in.reshape((1,) + date11_in.shape)
        else:
            make_outputs_scalar = False
        if date12_in.shape == tuple():
            date12_in = date12_in.reshape((1,) + date12_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date01_in, date02_in, date11_in, date12_in)
    zeta_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    z_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    theta_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date01_in, date02_in, date11_in, date12_in, zeta_out, z_out, theta_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._prec76(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(zeta_out.shape) > 0 and zeta_out.shape[0] == 1
        zeta_out = zeta_out.reshape(zeta_out.shape[1:])
        assert len(z_out.shape) > 0 and z_out.shape[0] == 1
        z_out = z_out.reshape(z_out.shape[1:])
        assert len(theta_out.shape) > 0 and theta_out.shape[0] == 1
        theta_out = theta_out.reshape(theta_out.shape[1:])

    return zeta_out, z_out, theta_out


def s00(date1, date2, x, y):
    """
    Wrapper for ERFA function ``eraS00``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    x : double array
    y : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - -
     e r a 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.

    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:
       eraFal03     mean anomaly of the Moon
       eraFalp03    mean anomaly of the Sun
       eraFaf03     mean argument of the latitude of the Moon
       eraFad03     mean elongation of the Moon from the Sun
       eraFaom03    mean longitude of the Moon's ascending node
       eraFave03    mean longitude of Venus
       eraFae03     mean longitude of Earth
       eraFapa03    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    x_in = numpy.array(x, dtype=numpy.double, order="C", copy=False, subok=True)
    y_in = numpy.array(y, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if x_in.shape == tuple():
            x_in = x_in.reshape((1,) + x_in.shape)
        else:
            make_outputs_scalar = False
        if y_in.shape == tuple():
            y_in = y_in.reshape((1,) + y_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, x_in, y_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, x_in, y_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._s00(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def s00a(date1, date2):
    """
    Wrapper for ERFA function ``eraS00a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a 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.

    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 eraS00b, which uses
       instead the IAU 2000B truncated model.

    Called:
       eraPnm00a    classical NPB matrix, IAU 2000A
       eraBnp2xy    extract CIP X,Y from the BPN matrix
       eraS00       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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._s00a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def s00b(date1, date2):
    """
    Wrapper for ERFA function ``eraS00b``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a 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.

    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 eraS00a uses instead
       the full IAU 2000A model, but with no significant increase in
       accuracy and at some cost in speed.

    Called:
       eraPnm00b    classical NPB matrix, IAU 2000B
       eraBnp2xy    extract CIP X,Y from the BPN matrix
       eraS00       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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._s00b(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def s06(date1, date2, x, y):
    """
    Wrapper for ERFA function ``eraS06``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    x : double array
    y : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - -
     e r a 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.

    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:
       eraFal03     mean anomaly of the Moon
       eraFalp03    mean anomaly of the Sun
       eraFaf03     mean argument of the latitude of the Moon
       eraFad03     mean elongation of the Moon from the Sun
       eraFaom03    mean longitude of the Moon's ascending node
       eraFave03    mean longitude of Venus
       eraFae03     mean longitude of Earth
       eraFapa03    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    x_in = numpy.array(x, dtype=numpy.double, order="C", copy=False, subok=True)
    y_in = numpy.array(y, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if x_in.shape == tuple():
            x_in = x_in.reshape((1,) + x_in.shape)
        else:
            make_outputs_scalar = False
        if y_in.shape == tuple():
            y_in = y_in.reshape((1,) + y_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, x_in, y_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, x_in, y_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._s06(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def s06a(date1, date2):
    """
    Wrapper for ERFA function ``eraS06a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a 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.

    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:
       eraPnm06a    classical NPB matrix, IAU 2006/2000A
       eraBpn2xy    extract CIP X,Y coordinates from NPB matrix
       eraS06       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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._s06a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def sp00(date1, date2):
    """
    Wrapper for ERFA function ``eraSp00``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a S p 0 0
    - - - - - - - -

    The TIO locator s', positioning the Terrestrial Intermediate Origin
    on the equator of the Celestial Intermediate Pole.

    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._sp00(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def xy06(date1, date2):
    """
    Wrapper for ERFA function ``eraXy06``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    x : double array
    y : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a X y 0 6
    - - - - - - - -

    X,Y coordinates of celestial intermediate pole from series based
    on IAU 2006 precession and IAU 2000A nutation.

    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 ERFA
       function eraFw2xy and as used in eraXys06a 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:
       eraFal03     mean anomaly of the Moon
       eraFalp03    mean anomaly of the Sun
       eraFaf03     mean argument of the latitude of the Moon
       eraFad03     mean elongation of the Moon from the Sun
       eraFaom03    mean longitude of the Moon's ascending node
       eraFame03    mean longitude of Mercury
       eraFave03    mean longitude of Venus
       eraFae03     mean longitude of Earth
       eraFama03    mean longitude of Mars
       eraFaju03    mean longitude of Jupiter
       eraFasa03    mean longitude of Saturn
       eraFaur03    mean longitude of Uranus
       eraFane03    mean longitude of Neptune
       eraFapa03    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    x_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    y_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, x_out, y_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._xy06(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(x_out.shape) > 0 and x_out.shape[0] == 1
        x_out = x_out.reshape(x_out.shape[1:])
        assert len(y_out.shape) > 0 and y_out.shape[0] == 1
        y_out = y_out.reshape(y_out.shape[1:])

    return x_out, y_out


def xys00a(date1, date2):
    """
    Wrapper for ERFA function ``eraXys00a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    x : double array
    y : double array
    s : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a 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.

    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 eraXys00b function.

    Called:
       eraPnm00a    classical NPB matrix, IAU 2000A
       eraBpn2xy    extract CIP X,Y coordinates from NPB matrix
       eraS00       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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    x_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    y_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    s_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, x_out, y_out, s_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._xys00a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(x_out.shape) > 0 and x_out.shape[0] == 1
        x_out = x_out.reshape(x_out.shape[1:])
        assert len(y_out.shape) > 0 and y_out.shape[0] == 1
        y_out = y_out.reshape(y_out.shape[1:])
        assert len(s_out.shape) > 0 and s_out.shape[0] == 1
        s_out = s_out.reshape(s_out.shape[1:])

    return x_out, y_out, s_out


def xys00b(date1, date2):
    """
    Wrapper for ERFA function ``eraXys00b``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    x : double array
    y : double array
    s : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a 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.

    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 eraXys00a function.

    Called:
       eraPnm00b    classical NPB matrix, IAU 2000B
       eraBpn2xy    extract CIP X,Y coordinates from NPB matrix
       eraS00       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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    x_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    y_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    s_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, x_out, y_out, s_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._xys00b(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(x_out.shape) > 0 and x_out.shape[0] == 1
        x_out = x_out.reshape(x_out.shape[1:])
        assert len(y_out.shape) > 0 and y_out.shape[0] == 1
        y_out = y_out.reshape(y_out.shape[1:])
        assert len(s_out.shape) > 0 and s_out.shape[0] == 1
        s_out = s_out.reshape(s_out.shape[1:])

    return x_out, y_out, s_out


def xys06a(date1, date2):
    """
    Wrapper for ERFA function ``eraXys06a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    x : double array
    y : double array
    s : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a 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.

    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 eraXy06.

    Called:
       eraPnm06a    classical NPB matrix, IAU 2006/2000A
       eraBpn2xy    extract CIP X,Y coordinates from NPB matrix
       eraS06       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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    x_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    y_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    s_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, x_out, y_out, s_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._xys06a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(x_out.shape) > 0 and x_out.shape[0] == 1
        x_out = x_out.reshape(x_out.shape[1:])
        assert len(y_out.shape) > 0 and y_out.shape[0] == 1
        y_out = y_out.reshape(y_out.shape[1:])
        assert len(s_out.shape) > 0 and s_out.shape[0] == 1
        s_out = s_out.reshape(s_out.shape[1:])

    return x_out, y_out, s_out


def ee00(date1, date2, epsa, dpsi):
    """
    Wrapper for ERFA function ``eraEe00``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    epsa : double array
    dpsi : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a E e 0 0
    - - - - - - - -

    The equation of the equinoxes, compatible with IAU 2000 resolutions,
    given the nutation in longitude and the mean obliquity.

    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:
       eraEect00    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    epsa_in = numpy.array(epsa, dtype=numpy.double, order="C", copy=False, subok=True)
    dpsi_in = numpy.array(dpsi, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if epsa_in.shape == tuple():
            epsa_in = epsa_in.reshape((1,) + epsa_in.shape)
        else:
            make_outputs_scalar = False
        if dpsi_in.shape == tuple():
            dpsi_in = dpsi_in.reshape((1,) + dpsi_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, epsa_in, dpsi_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, epsa_in, dpsi_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ee00(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def ee00a(date1, date2):
    """
    Wrapper for ERFA function ``eraEe00a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a E e 0 0 a
    - - - - - - - - -

    Equation of the equinoxes, compatible with IAU 2000 resolutions.

    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:
       eraPr00      IAU 2000 precession adjustments
       eraObl80     mean obliquity, IAU 1980
       eraNut00a    nutation, IAU 2000A
       eraEe00      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).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ee00a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def ee00b(date1, date2):
    """
    Wrapper for ERFA function ``eraEe00b``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a E e 0 0 b
    - - - - - - - - -

    Equation of the equinoxes, compatible with IAU 2000 resolutions but
    using the truncated nutation model IAU 2000B.

    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:
       eraPr00      IAU 2000 precession adjustments
       eraObl80     mean obliquity, IAU 1980
       eraNut00b    nutation, IAU 2000B
       eraEe00      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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ee00b(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def ee06a(date1, date2):
    """
    Wrapper for ERFA function ``eraEe06a``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a E e 0 6 a
    - - - - - - - - -

    Equation of the equinoxes, compatible with IAU 2000 resolutions and
    IAU 2006/2000A precession-nutation.

    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:
       eraAnpm      normalize angle into range +/- pi
       eraGst06a    Greenwich apparent sidereal time, IAU 2006/2000A
       eraGmst06    Greenwich mean sidereal time, IAU 2006

    Reference:

       McCarthy, D. D., Petit, G. (eds.), 2004, IERS Conventions (2003),
       IERS Technical Note No. 32, BKG

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ee06a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def eect00(date1, date2):
    """
    Wrapper for ERFA function ``eraEect00``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a E e c t 0 0
    - - - - - - - - - -

    Equation of the equinoxes complementary terms, consistent with
    IAU 2000 resolutions.

    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:
       eraFal03     mean anomaly of the Moon
       eraFalp03    mean anomaly of the Sun
       eraFaf03     mean argument of the latitude of the Moon
       eraFad03     mean elongation of the Moon from the Sun
       eraFaom03    mean longitude of the Moon's ascending node
       eraFave03    mean longitude of Venus
       eraFae03     mean longitude of Earth
       eraFapa03    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._eect00(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def eqeq94(date1, date2):
    """
    Wrapper for ERFA function ``eraEqeq94``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a E q e q 9 4
    - - - - - - - - - -

    Equation of the equinoxes, IAU 1994 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:
       eraAnpm      normalize angle into range +/- pi
       eraNut80     nutation, IAU 1980
       eraObl80     mean obliquity, IAU 1980

    References:

       IAU Resolution C7, Recommendation 3 (1994).

       Capitaine, N. & Gontier, A.-M., 1993, Astron. Astrophys., 275,
       645-650.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._eqeq94(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def era00(dj1, dj2):
    """
    Wrapper for ERFA function ``eraEra00``.

    Parameters
    ----------
    dj1 : double array
    dj2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a E r a 0 0
    - - - - - - - - -

    Earth rotation angle (IAU 2000 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:
       eraAnp       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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    dj1_in = numpy.array(dj1, dtype=numpy.double, order="C", copy=False, subok=True)
    dj2_in = numpy.array(dj2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if dj1_in.shape == tuple():
            dj1_in = dj1_in.reshape((1,) + dj1_in.shape)
        else:
            make_outputs_scalar = False
        if dj2_in.shape == tuple():
            dj2_in = dj2_in.reshape((1,) + dj2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), dj1_in, dj2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [dj1_in, dj2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._era00(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def gmst00(uta, utb, tta, ttb):
    """
    Wrapper for ERFA function ``eraGmst00``.

    Parameters
    ----------
    uta : double array
    utb : double array
    tta : double array
    ttb : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a G m s t 0 0
    - - - - - - - - - -

    Greenwich mean sidereal time (model consistent with IAU 2000
    resolutions).

    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:
       eraEra00     Earth rotation angle, IAU 2000
       eraAnp       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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    uta_in = numpy.array(uta, dtype=numpy.double, order="C", copy=False, subok=True)
    utb_in = numpy.array(utb, dtype=numpy.double, order="C", copy=False, subok=True)
    tta_in = numpy.array(tta, dtype=numpy.double, order="C", copy=False, subok=True)
    ttb_in = numpy.array(ttb, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if uta_in.shape == tuple():
            uta_in = uta_in.reshape((1,) + uta_in.shape)
        else:
            make_outputs_scalar = False
        if utb_in.shape == tuple():
            utb_in = utb_in.reshape((1,) + utb_in.shape)
        else:
            make_outputs_scalar = False
        if tta_in.shape == tuple():
            tta_in = tta_in.reshape((1,) + tta_in.shape)
        else:
            make_outputs_scalar = False
        if ttb_in.shape == tuple():
            ttb_in = ttb_in.reshape((1,) + ttb_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), uta_in, utb_in, tta_in, ttb_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [uta_in, utb_in, tta_in, ttb_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._gmst00(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def gmst06(uta, utb, tta, ttb):
    """
    Wrapper for ERFA function ``eraGmst06``.

    Parameters
    ----------
    uta : double array
    utb : double array
    tta : double array
    ttb : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a G m s t 0 6
    - - - - - - - - - -

    Greenwich mean sidereal time (consistent with IAU 2006 precession).

    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:
       eraEra00     Earth rotation angle, IAU 2000
       eraAnp       normalize angle into range 0 to 2pi

    Reference:

       Capitaine, N., Wallace, P.T. & Chapront, J., 2005,
       Astron.Astrophys. 432, 355

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    uta_in = numpy.array(uta, dtype=numpy.double, order="C", copy=False, subok=True)
    utb_in = numpy.array(utb, dtype=numpy.double, order="C", copy=False, subok=True)
    tta_in = numpy.array(tta, dtype=numpy.double, order="C", copy=False, subok=True)
    ttb_in = numpy.array(ttb, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if uta_in.shape == tuple():
            uta_in = uta_in.reshape((1,) + uta_in.shape)
        else:
            make_outputs_scalar = False
        if utb_in.shape == tuple():
            utb_in = utb_in.reshape((1,) + utb_in.shape)
        else:
            make_outputs_scalar = False
        if tta_in.shape == tuple():
            tta_in = tta_in.reshape((1,) + tta_in.shape)
        else:
            make_outputs_scalar = False
        if ttb_in.shape == tuple():
            ttb_in = ttb_in.reshape((1,) + ttb_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), uta_in, utb_in, tta_in, ttb_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [uta_in, utb_in, tta_in, ttb_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._gmst06(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def gmst82(dj1, dj2):
    """
    Wrapper for ERFA function ``eraGmst82``.

    Parameters
    ----------
    dj1 : double array
    dj2 : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a G m s t 8 2
    - - - - - - - - - -

    Universal Time to Greenwich mean sidereal time (IAU 1982 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.7          0          (JD method)
            2451545        -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 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:
       eraAnp       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).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    dj1_in = numpy.array(dj1, dtype=numpy.double, order="C", copy=False, subok=True)
    dj2_in = numpy.array(dj2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if dj1_in.shape == tuple():
            dj1_in = dj1_in.reshape((1,) + dj1_in.shape)
        else:
            make_outputs_scalar = False
        if dj2_in.shape == tuple():
            dj2_in = dj2_in.reshape((1,) + dj2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), dj1_in, dj2_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [dj1_in, dj2_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._gmst82(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def gst00a(uta, utb, tta, ttb):
    """
    Wrapper for ERFA function ``eraGst00a``.

    Parameters
    ----------
    uta : double array
    utb : double array
    tta : double array
    ttb : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a G s t 0 0 a
    - - - - - - - - - -

    Greenwich apparent sidereal time (consistent with IAU 2000
    resolutions).

    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:
       eraGmst00    Greenwich mean sidereal time, IAU 2000
       eraEe00a     equation of the equinoxes, IAU 2000A
       eraAnp       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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    uta_in = numpy.array(uta, dtype=numpy.double, order="C", copy=False, subok=True)
    utb_in = numpy.array(utb, dtype=numpy.double, order="C", copy=False, subok=True)
    tta_in = numpy.array(tta, dtype=numpy.double, order="C", copy=False, subok=True)
    ttb_in = numpy.array(ttb, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if uta_in.shape == tuple():
            uta_in = uta_in.reshape((1,) + uta_in.shape)
        else:
            make_outputs_scalar = False
        if utb_in.shape == tuple():
            utb_in = utb_in.reshape((1,) + utb_in.shape)
        else:
            make_outputs_scalar = False
        if tta_in.shape == tuple():
            tta_in = tta_in.reshape((1,) + tta_in.shape)
        else:
            make_outputs_scalar = False
        if ttb_in.shape == tuple():
            ttb_in = ttb_in.reshape((1,) + ttb_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), uta_in, utb_in, tta_in, ttb_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [uta_in, utb_in, tta_in, ttb_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._gst00a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def gst00b(uta, utb):
    """
    Wrapper for ERFA function ``eraGst00b``.

    Parameters
    ----------
    uta : double array
    utb : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a G s t 0 0 b
    - - - - - - - - - -

    Greenwich apparent sidereal time (consistent with IAU 2000
    resolutions but using the truncated nutation model IAU 2000B).

    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:
       eraGmst00    Greenwich mean sidereal time, IAU 2000
       eraEe00b     equation of the equinoxes, IAU 2000B
       eraAnp       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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    uta_in = numpy.array(uta, dtype=numpy.double, order="C", copy=False, subok=True)
    utb_in = numpy.array(utb, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if uta_in.shape == tuple():
            uta_in = uta_in.reshape((1,) + uta_in.shape)
        else:
            make_outputs_scalar = False
        if utb_in.shape == tuple():
            utb_in = utb_in.reshape((1,) + utb_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), uta_in, utb_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [uta_in, utb_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._gst00b(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def gst06(uta, utb, tta, ttb, rnpb):
    """
    Wrapper for ERFA function ``eraGst06``.

    Parameters
    ----------
    uta : double array
    utb : double array
    tta : double array
    ttb : double array
    rnpb : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a G s t 0 6
    - - - - - - - - -

    Greenwich apparent sidereal time, IAU 2006, given the NPB matrix.

    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:
       eraBpn2xy    extract CIP X,Y coordinates from NPB matrix
       eraS06       the CIO locator s, given X,Y, IAU 2006
       eraAnp       normalize angle into range 0 to 2pi
       eraEra00     Earth rotation angle, IAU 2000
       eraEors      equation of the origins, given NPB matrix and s

    Reference:

       Wallace, P.T. & Capitaine, N., 2006, Astron.Astrophys. 459, 981

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    uta_in = numpy.array(uta, dtype=numpy.double, order="C", copy=False, subok=True)
    utb_in = numpy.array(utb, dtype=numpy.double, order="C", copy=False, subok=True)
    tta_in = numpy.array(tta, dtype=numpy.double, order="C", copy=False, subok=True)
    ttb_in = numpy.array(ttb, dtype=numpy.double, order="C", copy=False, subok=True)
    rnpb_in = numpy.array(rnpb, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(rnpb_in, (3, 3), "rnpb")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if uta_in.shape == tuple():
            uta_in = uta_in.reshape((1,) + uta_in.shape)
        else:
            make_outputs_scalar = False
        if utb_in.shape == tuple():
            utb_in = utb_in.reshape((1,) + utb_in.shape)
        else:
            make_outputs_scalar = False
        if tta_in.shape == tuple():
            tta_in = tta_in.reshape((1,) + tta_in.shape)
        else:
            make_outputs_scalar = False
        if ttb_in.shape == tuple():
            ttb_in = ttb_in.reshape((1,) + ttb_in.shape)
        else:
            make_outputs_scalar = False
        if rnpb_in[...,0,0].shape == tuple():
            rnpb_in = rnpb_in.reshape((1,) + rnpb_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), uta_in, utb_in, tta_in, ttb_in, rnpb_in[...,0,0])
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [uta_in, utb_in, tta_in, ttb_in, rnpb_in[...,0,0], c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*5 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._gst06(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def gst06a(uta, utb, tta, ttb):
    """
    Wrapper for ERFA function ``eraGst06a``.

    Parameters
    ----------
    uta : double array
    utb : double array
    tta : double array
    ttb : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a G s t 0 6 a
    - - - - - - - - - -

    Greenwich apparent sidereal time (consistent with IAU 2000 and 2006
    resolutions).

    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:
       eraPnm06a    classical NPB matrix, IAU 2006/2000A
       eraGst06     Greenwich apparent ST, IAU 2006, given NPB matrix

    Reference:

       Wallace, P.T. & Capitaine, N., 2006, Astron.Astrophys. 459, 981

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    uta_in = numpy.array(uta, dtype=numpy.double, order="C", copy=False, subok=True)
    utb_in = numpy.array(utb, dtype=numpy.double, order="C", copy=False, subok=True)
    tta_in = numpy.array(tta, dtype=numpy.double, order="C", copy=False, subok=True)
    ttb_in = numpy.array(ttb, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if uta_in.shape == tuple():
            uta_in = uta_in.reshape((1,) + uta_in.shape)
        else:
            make_outputs_scalar = False
        if utb_in.shape == tuple():
            utb_in = utb_in.reshape((1,) + utb_in.shape)
        else:
            make_outputs_scalar = False
        if tta_in.shape == tuple():
            tta_in = tta_in.reshape((1,) + tta_in.shape)
        else:
            make_outputs_scalar = False
        if ttb_in.shape == tuple():
            ttb_in = ttb_in.reshape((1,) + ttb_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), uta_in, utb_in, tta_in, ttb_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [uta_in, utb_in, tta_in, ttb_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._gst06a(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def gst94(uta, utb):
    """
    Wrapper for ERFA function ``eraGst94``.

    Parameters
    ----------
    uta : double array
    utb : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a G s t 9 4
    - - - - - - - - -

    Greenwich apparent sidereal time (consistent with IAU 1982/94
    resolutions).

    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:
       eraGmst82    Greenwich mean sidereal time, IAU 1982
       eraEqeq94    equation of the equinoxes, IAU 1994
       eraAnp       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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    uta_in = numpy.array(uta, dtype=numpy.double, order="C", copy=False, subok=True)
    utb_in = numpy.array(utb, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if uta_in.shape == tuple():
            uta_in = uta_in.reshape((1,) + uta_in.shape)
        else:
            make_outputs_scalar = False
        if utb_in.shape == tuple():
            utb_in = utb_in.reshape((1,) + utb_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), uta_in, utb_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [uta_in, utb_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._gst94(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def pvstar(pv):
    """
    Wrapper for ERFA function ``eraPvstar``.

    Parameters
    ----------
    pv : double array

    Returns
    -------
    ra : double array
    dec : double array
    pmr : double array
    pmd : double array
    px : double array
    rv : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a P v s t a r
    - - - - - - - - - -

    Convert star position+velocity vector to catalog coordinates.

    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 eraStarpv), 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 eraStarpv.

    Called:
       eraPn        decompose p-vector into modulus and direction
       eraPdp       scalar product of two p-vectors
       eraSxp       multiply p-vector by scalar
       eraPmp       p-vector minus p-vector
       eraPm        modulus of p-vector
       eraPpp       p-vector plus p-vector
       eraPv2s      pv-vector to spherical
       eraAnp       normalize angle into range 0 to 2pi

    Reference:

       Stumpff, P., 1985, Astron.Astrophys. 144, 232-240.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    pv_in = numpy.array(pv, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(pv_in, (2, 3), "pv")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if pv_in[...,0,0].shape == tuple():
            pv_in = pv_in.reshape((1,) + pv_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), pv_in[...,0,0])
    ra_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dec_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    pmr_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    pmd_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    px_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    rv_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [pv_in[...,0,0], ra_out, dec_out, pmr_out, pmd_out, px_out, rv_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*7
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pvstar(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'pvstar')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(ra_out.shape) > 0 and ra_out.shape[0] == 1
        ra_out = ra_out.reshape(ra_out.shape[1:])
        assert len(dec_out.shape) > 0 and dec_out.shape[0] == 1
        dec_out = dec_out.reshape(dec_out.shape[1:])
        assert len(pmr_out.shape) > 0 and pmr_out.shape[0] == 1
        pmr_out = pmr_out.reshape(pmr_out.shape[1:])
        assert len(pmd_out.shape) > 0 and pmd_out.shape[0] == 1
        pmd_out = pmd_out.reshape(pmd_out.shape[1:])
        assert len(px_out.shape) > 0 and px_out.shape[0] == 1
        px_out = px_out.reshape(px_out.shape[1:])
        assert len(rv_out.shape) > 0 and rv_out.shape[0] == 1
        rv_out = rv_out.reshape(rv_out.shape[1:])

    return ra_out, dec_out, pmr_out, pmd_out, px_out, rv_out
STATUS_CODES['pvstar'] = {0: 'OK', -2: 'null position vector', -1: 'superluminal speed (Note 5)'}



def starpv(ra, dec, pmr, pmd, px, rv):
    """
    Wrapper for ERFA function ``eraStarpv``.

    Parameters
    ----------
    ra : double array
    dec : double array
    pmr : double array
    pmd : double array
    px : double array
    rv : double array

    Returns
    -------
    pv : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a S t a r p v
    - - - - - - - - - -

    Convert star catalog coordinates to position+velocity vector.

    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
       eraPvstar.

    Called:
       eraS2pv      spherical coordinates to pv-vector
       eraPm        modulus of p-vector
       eraZp        zero p-vector
       eraPn        decompose p-vector into modulus and direction
       eraPdp       scalar product of two p-vectors
       eraSxp       multiply p-vector by scalar
       eraPmp       p-vector minus p-vector
       eraPpp       p-vector plus p-vector

    Reference:

       Stumpff, P., 1985, Astron.Astrophys. 144, 232-240.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ra_in = numpy.array(ra, dtype=numpy.double, order="C", copy=False, subok=True)
    dec_in = numpy.array(dec, dtype=numpy.double, order="C", copy=False, subok=True)
    pmr_in = numpy.array(pmr, dtype=numpy.double, order="C", copy=False, subok=True)
    pmd_in = numpy.array(pmd, dtype=numpy.double, order="C", copy=False, subok=True)
    px_in = numpy.array(px, dtype=numpy.double, order="C", copy=False, subok=True)
    rv_in = numpy.array(rv, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ra_in.shape == tuple():
            ra_in = ra_in.reshape((1,) + ra_in.shape)
        else:
            make_outputs_scalar = False
        if dec_in.shape == tuple():
            dec_in = dec_in.reshape((1,) + dec_in.shape)
        else:
            make_outputs_scalar = False
        if pmr_in.shape == tuple():
            pmr_in = pmr_in.reshape((1,) + pmr_in.shape)
        else:
            make_outputs_scalar = False
        if pmd_in.shape == tuple():
            pmd_in = pmd_in.reshape((1,) + pmd_in.shape)
        else:
            make_outputs_scalar = False
        if px_in.shape == tuple():
            px_in = px_in.reshape((1,) + px_in.shape)
        else:
            make_outputs_scalar = False
        if rv_in.shape == tuple():
            rv_in = rv_in.reshape((1,) + rv_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ra_in, dec_in, pmr_in, pmd_in, px_in, rv_in)
    pv_out = numpy.empty(broadcast.shape + (2, 3), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ra_in, dec_in, pmr_in, pmd_in, px_in, rv_in, pv_out[...,0,0], c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*6 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._starpv(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'starpv')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(pv_out.shape) > 0 and pv_out.shape[0] == 1
        pv_out = pv_out.reshape(pv_out.shape[1:])

    return pv_out
STATUS_CODES['starpv'] = {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'}



def fk52h(r5, d5, dr5, dd5, px5, rv5):
    """
    Wrapper for ERFA function ``eraFk52h``.

    Parameters
    ----------
    r5 : double array
    d5 : double array
    dr5 : double array
    dd5 : double array
    px5 : double array
    rv5 : double array

    Returns
    -------
    rh : double array
    dh : double array
    drh : double array
    ddh : double array
    pxh : double array
    rvh : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a F k 5 2 h
    - - - - - - - - -

    Transform FK5 (J2000.0) star data into the Hipparcos system.

    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 eraH2fk5, eraFk5hz, eraHfk5z.

    Called:
       eraStarpv    star catalog data to space motion pv-vector
       eraFk5hip    FK5 to Hipparcos rotation and spin
       eraRxp       product of r-matrix and p-vector
       eraPxp       vector product of two p-vectors
       eraPpp       p-vector plus p-vector
       eraPvstar    space motion pv-vector to star catalog data

    Reference:

       F.Mignard & M.Froeschle, Astron. Astrophys. 354, 732-739 (2000).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    r5_in = numpy.array(r5, dtype=numpy.double, order="C", copy=False, subok=True)
    d5_in = numpy.array(d5, dtype=numpy.double, order="C", copy=False, subok=True)
    dr5_in = numpy.array(dr5, dtype=numpy.double, order="C", copy=False, subok=True)
    dd5_in = numpy.array(dd5, dtype=numpy.double, order="C", copy=False, subok=True)
    px5_in = numpy.array(px5, dtype=numpy.double, order="C", copy=False, subok=True)
    rv5_in = numpy.array(rv5, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if r5_in.shape == tuple():
            r5_in = r5_in.reshape((1,) + r5_in.shape)
        else:
            make_outputs_scalar = False
        if d5_in.shape == tuple():
            d5_in = d5_in.reshape((1,) + d5_in.shape)
        else:
            make_outputs_scalar = False
        if dr5_in.shape == tuple():
            dr5_in = dr5_in.reshape((1,) + dr5_in.shape)
        else:
            make_outputs_scalar = False
        if dd5_in.shape == tuple():
            dd5_in = dd5_in.reshape((1,) + dd5_in.shape)
        else:
            make_outputs_scalar = False
        if px5_in.shape == tuple():
            px5_in = px5_in.reshape((1,) + px5_in.shape)
        else:
            make_outputs_scalar = False
        if rv5_in.shape == tuple():
            rv5_in = rv5_in.reshape((1,) + rv5_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), r5_in, d5_in, dr5_in, dd5_in, px5_in, rv5_in)
    rh_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dh_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    drh_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    ddh_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    pxh_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    rvh_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [r5_in, d5_in, dr5_in, dd5_in, px5_in, rv5_in, rh_out, dh_out, drh_out, ddh_out, pxh_out, rvh_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*6 + [['readwrite']]*6
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._fk52h(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rh_out.shape) > 0 and rh_out.shape[0] == 1
        rh_out = rh_out.reshape(rh_out.shape[1:])
        assert len(dh_out.shape) > 0 and dh_out.shape[0] == 1
        dh_out = dh_out.reshape(dh_out.shape[1:])
        assert len(drh_out.shape) > 0 and drh_out.shape[0] == 1
        drh_out = drh_out.reshape(drh_out.shape[1:])
        assert len(ddh_out.shape) > 0 and ddh_out.shape[0] == 1
        ddh_out = ddh_out.reshape(ddh_out.shape[1:])
        assert len(pxh_out.shape) > 0 and pxh_out.shape[0] == 1
        pxh_out = pxh_out.reshape(pxh_out.shape[1:])
        assert len(rvh_out.shape) > 0 and rvh_out.shape[0] == 1
        rvh_out = rvh_out.reshape(rvh_out.shape[1:])

    return rh_out, dh_out, drh_out, ddh_out, pxh_out, rvh_out


def fk5hip():
    """
    Wrapper for ERFA function ``eraFk5hip``.

    Parameters
    ----------

    Returns
    -------
    r5h : double array
    s5h : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a F k 5 h i p
    - - - - - - - - - -

    FK5 to Hipparcos rotation and spin.

    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:
       eraRv2m      r-vector to r-matrix

    Reference:

       F.Mignard & M.Froeschle, Astron. Astrophys. 354, 732-739 (2000).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), )
    r5h_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)
    s5h_out = numpy.empty(broadcast.shape + (3,), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [r5h_out[...,0,0], s5h_out[...,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*0 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._fk5hip(it)

    return r5h_out, s5h_out


def fk5hz(r5, d5, date1, date2):
    """
    Wrapper for ERFA function ``eraFk5hz``.

    Parameters
    ----------
    r5 : double array
    d5 : double array
    date1 : double array
    date2 : double array

    Returns
    -------
    rh : double array
    dh : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a F k 5 h z
    - - - - - - - - -

    Transform an FK5 (J2000.0) star position into the system of the
    Hipparcos catalogue, assuming zero Hipparcos proper motion.

    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 eraFk52h, eraH2fk5, eraHfk5z.

    Called:
       eraS2c       spherical coordinates to unit vector
       eraFk5hip    FK5 to Hipparcos rotation and spin
       eraSxp       multiply p-vector by scalar
       eraRv2m      r-vector to r-matrix
       eraTrxp      product of transpose of r-matrix and p-vector
       eraPxp       vector product of two p-vectors
       eraC2s       p-vector to spherical
       eraAnp       normalize angle into range 0 to 2pi

    Reference:

       F.Mignard & M.Froeschle, 2000, Astron.Astrophys. 354, 732-739.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    r5_in = numpy.array(r5, dtype=numpy.double, order="C", copy=False, subok=True)
    d5_in = numpy.array(d5, dtype=numpy.double, order="C", copy=False, subok=True)
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if r5_in.shape == tuple():
            r5_in = r5_in.reshape((1,) + r5_in.shape)
        else:
            make_outputs_scalar = False
        if d5_in.shape == tuple():
            d5_in = d5_in.reshape((1,) + d5_in.shape)
        else:
            make_outputs_scalar = False
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), r5_in, d5_in, date1_in, date2_in)
    rh_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dh_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [r5_in, d5_in, date1_in, date2_in, rh_out, dh_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._fk5hz(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rh_out.shape) > 0 and rh_out.shape[0] == 1
        rh_out = rh_out.reshape(rh_out.shape[1:])
        assert len(dh_out.shape) > 0 and dh_out.shape[0] == 1
        dh_out = dh_out.reshape(dh_out.shape[1:])

    return rh_out, dh_out


def h2fk5(rh, dh, drh, ddh, pxh, rvh):
    """
    Wrapper for ERFA function ``eraH2fk5``.

    Parameters
    ----------
    rh : double array
    dh : double array
    drh : double array
    ddh : double array
    pxh : double array
    rvh : double array

    Returns
    -------
    r5 : double array
    d5 : double array
    dr5 : double array
    dd5 : double array
    px5 : double array
    rv5 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a H 2 f k 5
    - - - - - - - - -

    Transform Hipparcos star data into the FK5 (J2000.0) system.

    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 eraFk52h, eraFk5hz, eraHfk5z.

    Called:
       eraStarpv    star catalog data to space motion pv-vector
       eraFk5hip    FK5 to Hipparcos rotation and spin
       eraRv2m      r-vector to r-matrix
       eraRxp       product of r-matrix and p-vector
       eraTrxp      product of transpose of r-matrix and p-vector
       eraPxp       vector product of two p-vectors
       eraPmp       p-vector minus p-vector
       eraPvstar    space motion pv-vector to star catalog data

    Reference:

       F.Mignard & M.Froeschle, Astron. Astrophys. 354, 732-739 (2000).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    rh_in = numpy.array(rh, dtype=numpy.double, order="C", copy=False, subok=True)
    dh_in = numpy.array(dh, dtype=numpy.double, order="C", copy=False, subok=True)
    drh_in = numpy.array(drh, dtype=numpy.double, order="C", copy=False, subok=True)
    ddh_in = numpy.array(ddh, dtype=numpy.double, order="C", copy=False, subok=True)
    pxh_in = numpy.array(pxh, dtype=numpy.double, order="C", copy=False, subok=True)
    rvh_in = numpy.array(rvh, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if rh_in.shape == tuple():
            rh_in = rh_in.reshape((1,) + rh_in.shape)
        else:
            make_outputs_scalar = False
        if dh_in.shape == tuple():
            dh_in = dh_in.reshape((1,) + dh_in.shape)
        else:
            make_outputs_scalar = False
        if drh_in.shape == tuple():
            drh_in = drh_in.reshape((1,) + drh_in.shape)
        else:
            make_outputs_scalar = False
        if ddh_in.shape == tuple():
            ddh_in = ddh_in.reshape((1,) + ddh_in.shape)
        else:
            make_outputs_scalar = False
        if pxh_in.shape == tuple():
            pxh_in = pxh_in.reshape((1,) + pxh_in.shape)
        else:
            make_outputs_scalar = False
        if rvh_in.shape == tuple():
            rvh_in = rvh_in.reshape((1,) + rvh_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), rh_in, dh_in, drh_in, ddh_in, pxh_in, rvh_in)
    r5_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    d5_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dr5_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dd5_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    px5_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    rv5_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [rh_in, dh_in, drh_in, ddh_in, pxh_in, rvh_in, r5_out, d5_out, dr5_out, dd5_out, px5_out, rv5_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*6 + [['readwrite']]*6
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._h2fk5(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(r5_out.shape) > 0 and r5_out.shape[0] == 1
        r5_out = r5_out.reshape(r5_out.shape[1:])
        assert len(d5_out.shape) > 0 and d5_out.shape[0] == 1
        d5_out = d5_out.reshape(d5_out.shape[1:])
        assert len(dr5_out.shape) > 0 and dr5_out.shape[0] == 1
        dr5_out = dr5_out.reshape(dr5_out.shape[1:])
        assert len(dd5_out.shape) > 0 and dd5_out.shape[0] == 1
        dd5_out = dd5_out.reshape(dd5_out.shape[1:])
        assert len(px5_out.shape) > 0 and px5_out.shape[0] == 1
        px5_out = px5_out.reshape(px5_out.shape[1:])
        assert len(rv5_out.shape) > 0 and rv5_out.shape[0] == 1
        rv5_out = rv5_out.reshape(rv5_out.shape[1:])

    return r5_out, d5_out, dr5_out, dd5_out, px5_out, rv5_out


def hfk5z(rh, dh, date1, date2):
    """
    Wrapper for ERFA function ``eraHfk5z``.

    Parameters
    ----------
    rh : double array
    dh : double array
    date1 : double array
    date2 : double array

    Returns
    -------
    r5 : double array
    d5 : double array
    dr5 : double array
    dd5 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a H f k 5 z
    - - - - - - - - -

    Transform a Hipparcos star position into FK5 J2000.0, assuming
    zero Hipparcos proper motion.

    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 eraFk52h, eraH2fk5, eraFk5zhz.

    Called:
       eraS2c       spherical coordinates to unit vector
       eraFk5hip    FK5 to Hipparcos rotation and spin
       eraRxp       product of r-matrix and p-vector
       eraSxp       multiply p-vector by scalar
       eraRxr       product of two r-matrices
       eraTrxp      product of transpose of r-matrix and p-vector
       eraPxp       vector product of two p-vectors
       eraPv2s      pv-vector to spherical
       eraAnp       normalize angle into range 0 to 2pi

    Reference:

       F.Mignard & M.Froeschle, 2000, Astron.Astrophys. 354, 732-739.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    rh_in = numpy.array(rh, dtype=numpy.double, order="C", copy=False, subok=True)
    dh_in = numpy.array(dh, dtype=numpy.double, order="C", copy=False, subok=True)
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if rh_in.shape == tuple():
            rh_in = rh_in.reshape((1,) + rh_in.shape)
        else:
            make_outputs_scalar = False
        if dh_in.shape == tuple():
            dh_in = dh_in.reshape((1,) + dh_in.shape)
        else:
            make_outputs_scalar = False
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), rh_in, dh_in, date1_in, date2_in)
    r5_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    d5_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dr5_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dd5_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [rh_in, dh_in, date1_in, date2_in, r5_out, d5_out, dr5_out, dd5_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*4
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._hfk5z(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(r5_out.shape) > 0 and r5_out.shape[0] == 1
        r5_out = r5_out.reshape(r5_out.shape[1:])
        assert len(d5_out.shape) > 0 and d5_out.shape[0] == 1
        d5_out = d5_out.reshape(d5_out.shape[1:])
        assert len(dr5_out.shape) > 0 and dr5_out.shape[0] == 1
        dr5_out = dr5_out.reshape(dr5_out.shape[1:])
        assert len(dd5_out.shape) > 0 and dd5_out.shape[0] == 1
        dd5_out = dd5_out.reshape(dd5_out.shape[1:])

    return r5_out, d5_out, dr5_out, dd5_out


def starpm(ra1, dec1, pmr1, pmd1, px1, rv1, ep1a, ep1b, ep2a, ep2b):
    """
    Wrapper for ERFA function ``eraStarpm``.

    Parameters
    ----------
    ra1 : double array
    dec1 : double array
    pmr1 : double array
    pmd1 : double array
    px1 : double array
    rv1 : double array
    ep1a : double array
    ep1b : double array
    ep2a : double array
    ep2b : double array

    Returns
    -------
    ra2 : double array
    dec2 : double array
    pmr2 : double array
    pmd2 : double array
    px2 : double array
    rv2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a S t a r p m
    - - - - - - - - - -

    Star proper motion:  update star catalog data for space motion.

    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 eraStarpv
       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 eraStarpv), it is arbitrarily set
       to zero.  When this action occurs, 2 is added to the status.

    8) The relativistic adjustment carried out in the eraStarpv function
       involves an iterative calculation.  If the process fails to
       converge within a set number of iterations, 4 is added to the
       status.

    Called:
       eraStarpv    star catalog data to space motion pv-vector
       eraPvu       update a pv-vector
       eraPdp       scalar product of two p-vectors
       eraPvstar    space motion pv-vector to star catalog data

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ra1_in = numpy.array(ra1, dtype=numpy.double, order="C", copy=False, subok=True)
    dec1_in = numpy.array(dec1, dtype=numpy.double, order="C", copy=False, subok=True)
    pmr1_in = numpy.array(pmr1, dtype=numpy.double, order="C", copy=False, subok=True)
    pmd1_in = numpy.array(pmd1, dtype=numpy.double, order="C", copy=False, subok=True)
    px1_in = numpy.array(px1, dtype=numpy.double, order="C", copy=False, subok=True)
    rv1_in = numpy.array(rv1, dtype=numpy.double, order="C", copy=False, subok=True)
    ep1a_in = numpy.array(ep1a, dtype=numpy.double, order="C", copy=False, subok=True)
    ep1b_in = numpy.array(ep1b, dtype=numpy.double, order="C", copy=False, subok=True)
    ep2a_in = numpy.array(ep2a, dtype=numpy.double, order="C", copy=False, subok=True)
    ep2b_in = numpy.array(ep2b, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ra1_in.shape == tuple():
            ra1_in = ra1_in.reshape((1,) + ra1_in.shape)
        else:
            make_outputs_scalar = False
        if dec1_in.shape == tuple():
            dec1_in = dec1_in.reshape((1,) + dec1_in.shape)
        else:
            make_outputs_scalar = False
        if pmr1_in.shape == tuple():
            pmr1_in = pmr1_in.reshape((1,) + pmr1_in.shape)
        else:
            make_outputs_scalar = False
        if pmd1_in.shape == tuple():
            pmd1_in = pmd1_in.reshape((1,) + pmd1_in.shape)
        else:
            make_outputs_scalar = False
        if px1_in.shape == tuple():
            px1_in = px1_in.reshape((1,) + px1_in.shape)
        else:
            make_outputs_scalar = False
        if rv1_in.shape == tuple():
            rv1_in = rv1_in.reshape((1,) + rv1_in.shape)
        else:
            make_outputs_scalar = False
        if ep1a_in.shape == tuple():
            ep1a_in = ep1a_in.reshape((1,) + ep1a_in.shape)
        else:
            make_outputs_scalar = False
        if ep1b_in.shape == tuple():
            ep1b_in = ep1b_in.reshape((1,) + ep1b_in.shape)
        else:
            make_outputs_scalar = False
        if ep2a_in.shape == tuple():
            ep2a_in = ep2a_in.reshape((1,) + ep2a_in.shape)
        else:
            make_outputs_scalar = False
        if ep2b_in.shape == tuple():
            ep2b_in = ep2b_in.reshape((1,) + ep2b_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ra1_in, dec1_in, pmr1_in, pmd1_in, px1_in, rv1_in, ep1a_in, ep1b_in, ep2a_in, ep2b_in)
    ra2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dec2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    pmr2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    pmd2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    px2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    rv2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ra1_in, dec1_in, pmr1_in, pmd1_in, px1_in, rv1_in, ep1a_in, ep1b_in, ep2a_in, ep2b_in, ra2_out, dec2_out, pmr2_out, pmd2_out, px2_out, rv2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*10 + [['readwrite']]*7
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._starpm(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'starpm')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(ra2_out.shape) > 0 and ra2_out.shape[0] == 1
        ra2_out = ra2_out.reshape(ra2_out.shape[1:])
        assert len(dec2_out.shape) > 0 and dec2_out.shape[0] == 1
        dec2_out = dec2_out.reshape(dec2_out.shape[1:])
        assert len(pmr2_out.shape) > 0 and pmr2_out.shape[0] == 1
        pmr2_out = pmr2_out.reshape(pmr2_out.shape[1:])
        assert len(pmd2_out.shape) > 0 and pmd2_out.shape[0] == 1
        pmd2_out = pmd2_out.reshape(pmd2_out.shape[1:])
        assert len(px2_out.shape) > 0 and px2_out.shape[0] == 1
        px2_out = px2_out.reshape(px2_out.shape[1:])
        assert len(rv2_out.shape) > 0 and rv2_out.shape[0] == 1
        rv2_out = rv2_out.reshape(rv2_out.shape[1:])

    return ra2_out, dec2_out, pmr2_out, pmd2_out, px2_out, rv2_out
STATUS_CODES['starpm'] = {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', -1: 'system error (should not occur)'}



def eceq06(date1, date2, dl, db):
    """
    Wrapper for ERFA function ``eraEceq06``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    dl : double array
    db : double array

    Returns
    -------
    dr : double array
    dd : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a E c e q 0 6
    - - - - - - - - - -

    Transformation from ecliptic coordinates (mean equinox and ecliptic
    of date) to ICRS RA,Dec, using the IAU 2006 precession model.

    Given:
       date1,date2 double TT as a 2-part Julian date (Note 1)
       dl,db       double ecliptic longitude and latitude (radians)

    Returned:
       dr,dd       double ICRS right ascension and declination (radians)

    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) No assumptions are made about whether the coordinates represent
       starlight and embody astrometric effects such as parallax or
       aberration.

    3) The transformation is approximately that from ecliptic longitude
       and latitude (mean equinox and ecliptic of date) to mean J2000.0
       right ascension and declination, with only frame bias (always
       less than 25 mas) to disturb this classical picture.

    Called:
       eraS2c       spherical coordinates to unit vector
       eraEcm06     J2000.0 to ecliptic rotation matrix, IAU 2006
       eraTrxp      product of transpose of r-matrix and p-vector
       eraC2s       unit vector to spherical coordinates
       eraAnp       normalize angle into range 0 to 2pi
       eraAnpm      normalize angle into range +/- pi

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    dl_in = numpy.array(dl, dtype=numpy.double, order="C", copy=False, subok=True)
    db_in = numpy.array(db, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if dl_in.shape == tuple():
            dl_in = dl_in.reshape((1,) + dl_in.shape)
        else:
            make_outputs_scalar = False
        if db_in.shape == tuple():
            db_in = db_in.reshape((1,) + db_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, dl_in, db_in)
    dr_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dd_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, dl_in, db_in, dr_out, dd_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._eceq06(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(dr_out.shape) > 0 and dr_out.shape[0] == 1
        dr_out = dr_out.reshape(dr_out.shape[1:])
        assert len(dd_out.shape) > 0 and dd_out.shape[0] == 1
        dd_out = dd_out.reshape(dd_out.shape[1:])

    return dr_out, dd_out


def ecm06(date1, date2):
    """
    Wrapper for ERFA function ``eraEcm06``.

    Parameters
    ----------
    date1 : double array
    date2 : double array

    Returns
    -------
    rm : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a E c m 0 6
    - - - - - - - - -

    ICRS equatorial to ecliptic rotation matrix, IAU 2006.

    Given:
       date1,date2  double         TT as a 2-part Julian date (Note 1)

    Returned:
       rm           double[3][3]   ICRS to ecliptic rotation 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.

    1) The matrix is in the sense

          E_ep = rm x P_ICRS,

       where P_ICRS is a vector with respect to ICRS right ascension
       and declination axes and E_ep is the same vector with respect to
       the (inertial) ecliptic and equinox of date.

    2) P_ICRS is a free vector, merely a direction, typically of unit
       magnitude, and not bound to any particular spatial origin, such
       as the Earth, Sun or SSB.  No assumptions are made about whether
       it represents starlight and embodies astrometric effects such as
       parallax or aberration.  The transformation is approximately that
       between mean J2000.0 right ascension and declination and ecliptic
       longitude and latitude, with only frame bias (always less than
       25 mas) to disturb this classical picture.

    Called:
       eraObl06     mean obliquity, IAU 2006
       eraPmat06    PB matrix, IAU 2006
       eraIr        initialize r-matrix to identity
       eraRx        rotate around X-axis
       eraRxr       product of two r-matrices

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in)
    rm_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, rm_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ecm06(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rm_out.shape) > 0 and rm_out.shape[0] == 1
        rm_out = rm_out.reshape(rm_out.shape[1:])

    return rm_out


def eqec06(date1, date2, dr, dd):
    """
    Wrapper for ERFA function ``eraEqec06``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    dr : double array
    dd : double array

    Returns
    -------
    dl : double array
    db : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a E q e c 0 6
    - - - - - - - - - -

    Transformation from ICRS equatorial coordinates to ecliptic
    coordinates (mean equinox and ecliptic of date) using IAU 2006
    precession model.

    Given:
       date1,date2 double TT as a 2-part Julian date (Note 1)
       dr,dd       double ICRS right ascension and declination (radians)

    Returned:
       dl,db       double ecliptic longitude and latitude (radians)

    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) No assumptions are made about whether the coordinates represent
       starlight and embody astrometric effects such as parallax or
       aberration.

    3) The transformation is approximately that from mean J2000.0 right
       ascension and declination to ecliptic longitude and latitude
       (mean equinox and ecliptic of date), with only frame bias (always
       less than 25 mas) to disturb this classical picture.

    Called:
       eraS2c       spherical coordinates to unit vector
       eraEcm06     J2000.0 to ecliptic rotation matrix, IAU 2006
       eraRxp       product of r-matrix and p-vector
       eraC2s       unit vector to spherical coordinates
       eraAnp       normalize angle into range 0 to 2pi
       eraAnpm      normalize angle into range +/- pi

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    dr_in = numpy.array(dr, dtype=numpy.double, order="C", copy=False, subok=True)
    dd_in = numpy.array(dd, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if dr_in.shape == tuple():
            dr_in = dr_in.reshape((1,) + dr_in.shape)
        else:
            make_outputs_scalar = False
        if dd_in.shape == tuple():
            dd_in = dd_in.reshape((1,) + dd_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, dr_in, dd_in)
    dl_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    db_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, dr_in, dd_in, dl_out, db_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._eqec06(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(dl_out.shape) > 0 and dl_out.shape[0] == 1
        dl_out = dl_out.reshape(dl_out.shape[1:])
        assert len(db_out.shape) > 0 and db_out.shape[0] == 1
        db_out = db_out.reshape(db_out.shape[1:])

    return dl_out, db_out


def lteceq(epj, dl, db):
    """
    Wrapper for ERFA function ``eraLteceq``.

    Parameters
    ----------
    epj : double array
    dl : double array
    db : double array

    Returns
    -------
    dr : double array
    dd : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a L t e c e q
    - - - - - - - - - -

    Transformation from ecliptic coordinates (mean equinox and ecliptic
    of date) to ICRS RA,Dec, using a long-term precession model.

    Given:
       epj     double     Julian epoch (TT)
       dl,db   double     ecliptic longitude and latitude (radians)

    Returned:
       dr,dd   double     ICRS right ascension and declination (radians)

    1) No assumptions are made about whether the coordinates represent
       starlight and embody astrometric effects such as parallax or
       aberration.

    2) The transformation is approximately that from ecliptic longitude
       and latitude (mean equinox and ecliptic of date) to mean J2000.0
       right ascension and declination, with only frame bias (always
       less than 25 mas) to disturb this classical picture.

    3) The Vondrak et al. (2011, 2012) 400 millennia precession model
       agrees with the IAU 2006 precession at J2000.0 and stays within
       100 microarcseconds during the 20th and 21st centuries.  It is
       accurate to a few arcseconds throughout the historical period,
       worsening to a few tenths of a degree at the end of the
       +/- 200,000 year time span.

    Called:
       eraS2c       spherical coordinates to unit vector
       eraLtecm     J2000.0 to ecliptic rotation matrix, long term
       eraTrxp      product of transpose of r-matrix and p-vector
       eraC2s       unit vector to spherical coordinates
       eraAnp       normalize angle into range 0 to 2pi
       eraAnpm      normalize angle into range +/- pi

    References:

      Vondrak, J., Capitaine, N. and Wallace, P., 2011, New precession
      expressions, valid for long time intervals, Astron.Astrophys. 534,
      A22

      Vondrak, J., Capitaine, N. and Wallace, P., 2012, New precession
      expressions, valid for long time intervals (Corrigendum),
      Astron.Astrophys. 541, C1

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    epj_in = numpy.array(epj, dtype=numpy.double, order="C", copy=False, subok=True)
    dl_in = numpy.array(dl, dtype=numpy.double, order="C", copy=False, subok=True)
    db_in = numpy.array(db, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if epj_in.shape == tuple():
            epj_in = epj_in.reshape((1,) + epj_in.shape)
        else:
            make_outputs_scalar = False
        if dl_in.shape == tuple():
            dl_in = dl_in.reshape((1,) + dl_in.shape)
        else:
            make_outputs_scalar = False
        if db_in.shape == tuple():
            db_in = db_in.reshape((1,) + db_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), epj_in, dl_in, db_in)
    dr_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dd_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [epj_in, dl_in, db_in, dr_out, dd_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._lteceq(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(dr_out.shape) > 0 and dr_out.shape[0] == 1
        dr_out = dr_out.reshape(dr_out.shape[1:])
        assert len(dd_out.shape) > 0 and dd_out.shape[0] == 1
        dd_out = dd_out.reshape(dd_out.shape[1:])

    return dr_out, dd_out


def ltecm(epj):
    """
    Wrapper for ERFA function ``eraLtecm``.

    Parameters
    ----------
    epj : double array

    Returns
    -------
    rm : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a L t e c m
    - - - - - - - - -

    ICRS equatorial to ecliptic rotation matrix, long-term.

    Given:
       epj     double         Julian epoch (TT)

    Returned:
       rm      double[3][3]   ICRS to ecliptic rotation matrix

    Notes:

    1) The matrix is in the sense

          E_ep = rm x P_ICRS,

       where P_ICRS is a vector with respect to ICRS right ascension
       and declination axes and E_ep is the same vector with respect to
       the (inertial) ecliptic and equinox of epoch epj.

    2) P_ICRS is a free vector, merely a direction, typically of unit
       magnitude, and not bound to any particular spatial origin, such
       as the Earth, Sun or SSB.  No assumptions are made about whether
       it represents starlight and embodies astrometric effects such as
       parallax or aberration.  The transformation is approximately that
       between mean J2000.0 right ascension and declination and ecliptic
       longitude and latitude, with only frame bias (always less than
       25 mas) to disturb this classical picture.

    3) The Vondrak et al. (2011, 2012) 400 millennia precession model
       agrees with the IAU 2006 precession at J2000.0 and stays within
       100 microarcseconds during the 20th and 21st centuries.  It is
       accurate to a few arcseconds throughout the historical period,
       worsening to a few tenths of a degree at the end of the
       +/- 200,000 year time span.

    Called:
       eraLtpequ    equator pole, long term
       eraLtpecl    ecliptic pole, long term
       eraPxp       vector product
       eraPn        normalize vector

    References:

      Vondrak, J., Capitaine, N. and Wallace, P., 2011, New precession
      expressions, valid for long time intervals, Astron.Astrophys. 534,
      A22

      Vondrak, J., Capitaine, N. and Wallace, P., 2012, New precession
      expressions, valid for long time intervals (Corrigendum),
      Astron.Astrophys. 541, C1

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    epj_in = numpy.array(epj, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if epj_in.shape == tuple():
            epj_in = epj_in.reshape((1,) + epj_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), epj_in)
    rm_out = numpy.empty(broadcast.shape + (3, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [epj_in, rm_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ltecm(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rm_out.shape) > 0 and rm_out.shape[0] == 1
        rm_out = rm_out.reshape(rm_out.shape[1:])

    return rm_out


def lteqec(epj, dr, dd):
    """
    Wrapper for ERFA function ``eraLteqec``.

    Parameters
    ----------
    epj : double array
    dr : double array
    dd : double array

    Returns
    -------
    dl : double array
    db : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a L t e q e c
    - - - - - - - - - -

    Transformation from ICRS equatorial coordinates to ecliptic
    coordinates (mean equinox and ecliptic of date) using a long-term
    precession model.

    Given:
       epj     double     Julian epoch (TT)
       dr,dd   double     ICRS right ascension and declination (radians)

    Returned:
       dl,db   double     ecliptic longitude and latitude (radians)

    1) No assumptions are made about whether the coordinates represent
       starlight and embody astrometric effects such as parallax or
       aberration.

    2) The transformation is approximately that from mean J2000.0 right
       ascension and declination to ecliptic longitude and latitude
       (mean equinox and ecliptic of date), with only frame bias (always
       less than 25 mas) to disturb this classical picture.

    3) The Vondrak et al. (2011, 2012) 400 millennia precession model
       agrees with the IAU 2006 precession at J2000.0 and stays within
       100 microarcseconds during the 20th and 21st centuries.  It is
       accurate to a few arcseconds throughout the historical period,
       worsening to a few tenths of a degree at the end of the
       +/- 200,000 year time span.

    Called:
       eraS2c       spherical coordinates to unit vector
       eraLtecm     J2000.0 to ecliptic rotation matrix, long term
       eraRxp       product of r-matrix and p-vector
       eraC2s       unit vector to spherical coordinates
       eraAnp       normalize angle into range 0 to 2pi
       eraAnpm      normalize angle into range +/- pi

    References:

      Vondrak, J., Capitaine, N. and Wallace, P., 2011, New precession
      expressions, valid for long time intervals, Astron.Astrophys. 534,
      A22

      Vondrak, J., Capitaine, N. and Wallace, P., 2012, New precession
      expressions, valid for long time intervals (Corrigendum),
      Astron.Astrophys. 541, C1

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    epj_in = numpy.array(epj, dtype=numpy.double, order="C", copy=False, subok=True)
    dr_in = numpy.array(dr, dtype=numpy.double, order="C", copy=False, subok=True)
    dd_in = numpy.array(dd, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if epj_in.shape == tuple():
            epj_in = epj_in.reshape((1,) + epj_in.shape)
        else:
            make_outputs_scalar = False
        if dr_in.shape == tuple():
            dr_in = dr_in.reshape((1,) + dr_in.shape)
        else:
            make_outputs_scalar = False
        if dd_in.shape == tuple():
            dd_in = dd_in.reshape((1,) + dd_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), epj_in, dr_in, dd_in)
    dl_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    db_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [epj_in, dr_in, dd_in, dl_out, db_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._lteqec(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(dl_out.shape) > 0 and dl_out.shape[0] == 1
        dl_out = dl_out.reshape(dl_out.shape[1:])
        assert len(db_out.shape) > 0 and db_out.shape[0] == 1
        db_out = db_out.reshape(db_out.shape[1:])

    return dl_out, db_out


def g2icrs(dl, db):
    """
    Wrapper for ERFA function ``eraG2icrs``.

    Parameters
    ----------
    dl : double array
    db : double array

    Returns
    -------
    dr : double array
    dd : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a G 2 i c r s
    - - - - - - - - - -

    Transformation from Galactic Coordinates to ICRS.

    Given:
       dl     double      galactic longitude (radians)
       db     double      galactic latitude (radians)

    Returned:
       dr     double      ICRS right ascension (radians)
       dd     double      ICRS declination (radians)

    Notes:

    1) The IAU 1958 system of Galactic coordinates was defined with
       respect to the now obsolete reference system FK4 B1950.0.  When
       interpreting the system in a modern context, several factors have
       to be taken into account:

       . The inclusion in FK4 positions of the E-terms of aberration.

       . The distortion of the FK4 proper motion system by differential
         Galactic rotation.

       . The use of the B1950.0 equinox rather than the now-standard
         J2000.0.

       . The frame bias between ICRS and the J2000.0 mean place system.

       The Hipparcos Catalogue (Perryman & ESA 1997) provides a rotation
       matrix that transforms directly between ICRS and Galactic
       coordinates with the above factors taken into account.  The
       matrix is derived from three angles, namely the ICRS coordinates
       of the Galactic pole and the longitude of the ascending node of
       the galactic equator on the ICRS equator.  They are given in
       degrees to five decimal places and for canonical purposes are
       regarded as exact.  In the Hipparcos Catalogue the matrix
       elements are given to 10 decimal places (about 20 microarcsec).
       In the present ERFA function the matrix elements have been
       recomputed from the canonical three angles and are given to 30
       decimal places.

    2) The inverse transformation is performed by the function eraIcrs2g.

    Called:
       eraAnp       normalize angle into range 0 to 2pi
       eraAnpm      normalize angle into range +/- pi
       eraS2c       spherical coordinates to unit vector
       eraTrxp      product of transpose of r-matrix and p-vector
       eraC2s       p-vector to spherical

    Reference:
       Perryman M.A.C. & ESA, 1997, ESA SP-1200, The Hipparcos and Tycho
       catalogues.  Astrometric and photometric star catalogues
       derived from the ESA Hipparcos Space Astrometry Mission.  ESA
       Publications Division, Noordwijk, Netherlands.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    dl_in = numpy.array(dl, dtype=numpy.double, order="C", copy=False, subok=True)
    db_in = numpy.array(db, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if dl_in.shape == tuple():
            dl_in = dl_in.reshape((1,) + dl_in.shape)
        else:
            make_outputs_scalar = False
        if db_in.shape == tuple():
            db_in = db_in.reshape((1,) + db_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), dl_in, db_in)
    dr_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    dd_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [dl_in, db_in, dr_out, dd_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._g2icrs(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(dr_out.shape) > 0 and dr_out.shape[0] == 1
        dr_out = dr_out.reshape(dr_out.shape[1:])
        assert len(dd_out.shape) > 0 and dd_out.shape[0] == 1
        dd_out = dd_out.reshape(dd_out.shape[1:])

    return dr_out, dd_out


def icrs2g(dr, dd):
    """
    Wrapper for ERFA function ``eraIcrs2g``.

    Parameters
    ----------
    dr : double array
    dd : double array

    Returns
    -------
    dl : double array
    db : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a I c r s 2 g
    - - - - - - - - - -

    Transformation from ICRS to Galactic Coordinates.

    Given:
       dr     double      ICRS right ascension (radians)
       dd     double      ICRS declination (radians)

    Returned:
       dl     double      galactic longitude (radians)
       db     double      galactic latitude (radians)

    Notes:

    1) The IAU 1958 system of Galactic coordinates was defined with
       respect to the now obsolete reference system FK4 B1950.0.  When
       interpreting the system in a modern context, several factors have
       to be taken into account:

       . The inclusion in FK4 positions of the E-terms of aberration.

       . The distortion of the FK4 proper motion system by differential
         Galactic rotation.

       . The use of the B1950.0 equinox rather than the now-standard
         J2000.0.

       . The frame bias between ICRS and the J2000.0 mean place system.

       The Hipparcos Catalogue (Perryman & ESA 1997) provides a rotation
       matrix that transforms directly between ICRS and Galactic
       coordinates with the above factors taken into account.  The
       matrix is derived from three angles, namely the ICRS coordinates
       of the Galactic pole and the longitude of the ascending node of
       the galactic equator on the ICRS equator.  They are given in
       degrees to five decimal places and for canonical purposes are
       regarded as exact.  In the Hipparcos Catalogue the matrix
       elements are given to 10 decimal places (about 20 microarcsec).
       In the present ERFA function the matrix elements have been
       recomputed from the canonical three angles and are given to 30
       decimal places.

    2) The inverse transformation is performed by the function eraG2icrs.

    Called:
       eraAnp       normalize angle into range 0 to 2pi
       eraAnpm      normalize angle into range +/- pi
       eraS2c       spherical coordinates to unit vector
       eraRxp       product of r-matrix and p-vector
       eraC2s       p-vector to spherical

    Reference:
       Perryman M.A.C. & ESA, 1997, ESA SP-1200, The Hipparcos and Tycho
       catalogues.  Astrometric and photometric star catalogues
       derived from the ESA Hipparcos Space Astrometry Mission.  ESA
       Publications Division, Noordwijk, Netherlands.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    dr_in = numpy.array(dr, dtype=numpy.double, order="C", copy=False, subok=True)
    dd_in = numpy.array(dd, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if dr_in.shape == tuple():
            dr_in = dr_in.reshape((1,) + dr_in.shape)
        else:
            make_outputs_scalar = False
        if dd_in.shape == tuple():
            dd_in = dd_in.reshape((1,) + dd_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), dr_in, dd_in)
    dl_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    db_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [dr_in, dd_in, dl_out, db_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._icrs2g(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(dl_out.shape) > 0 and dl_out.shape[0] == 1
        dl_out = dl_out.reshape(dl_out.shape[1:])
        assert len(db_out.shape) > 0 and db_out.shape[0] == 1
        db_out = db_out.reshape(db_out.shape[1:])

    return dl_out, db_out


def eform(n):
    """
    Wrapper for ERFA function ``eraEform``.

    Parameters
    ----------
    n : int array

    Returns
    -------
    a : double array
    f : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a E f o r m
    - - - - - - - - -

    Earth reference ellipsoids.

    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     ERFA_WGS84
          2     ERFA_GRS80
          3     ERFA_WGS72

       The n value has no significance outside the ERFA software.  For
       convenience, symbols ERFA_WGS84 etc. are defined in erfam.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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    n_in = numpy.array(n, dtype=numpy.intc, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if n_in.shape == tuple():
            n_in = n_in.reshape((1,) + n_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), n_in)
    a_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    f_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [n_in, a_out, f_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._eform(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'eform')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(a_out.shape) > 0 and a_out.shape[0] == 1
        a_out = a_out.reshape(a_out.shape[1:])
        assert len(f_out.shape) > 0 and f_out.shape[0] == 1
        f_out = f_out.reshape(f_out.shape[1:])

    return a_out, f_out
STATUS_CODES['eform'] = {0: 'OK', -1: 'illegal identifier (Note 3)'}



def gc2gd(n, xyz):
    """
    Wrapper for ERFA function ``eraGc2gd``.

    Parameters
    ----------
    n : int array
    xyz : double array

    Returns
    -------
    elong : double array
    phi : double array
    height : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a G c 2 g d
    - - - - - - - - -

    Transform geocentric coordinates to geodetic using the specified
    reference ellipsoid.

    Given:
       n       int        ellipsoid identifier (Note 1)
       xyz     double[3]  geocentric vector (Note 2)

    Returned:
       elong   double     longitude (radians, east +ve, Note 3)
       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     ERFA_WGS84
          2     ERFA_GRS80
          3     ERFA_WGS72

       The n value has no significance outside the ERFA software.  For
       convenience, symbols ERFA_WGS84 etc. are defined in erfam.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,
       all three results are set to -1e9.

    4) The inverse transformation is performed in the function eraGd2gc.

    Called:
       eraEform     Earth reference ellipsoids
       eraGc2gde    geocentric to geodetic transformation, general

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    n_in = numpy.array(n, dtype=numpy.intc, order="C", copy=False, subok=True)
    xyz_in = numpy.array(xyz, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(xyz_in, (3,), "xyz")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if n_in.shape == tuple():
            n_in = n_in.reshape((1,) + n_in.shape)
        else:
            make_outputs_scalar = False
        if xyz_in[...,0].shape == tuple():
            xyz_in = xyz_in.reshape((1,) + xyz_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), n_in, xyz_in[...,0])
    elong_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    phi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    height_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [n_in, xyz_in[...,0], elong_out, phi_out, height_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*4
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._gc2gd(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'gc2gd')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(elong_out.shape) > 0 and elong_out.shape[0] == 1
        elong_out = elong_out.reshape(elong_out.shape[1:])
        assert len(phi_out.shape) > 0 and phi_out.shape[0] == 1
        phi_out = phi_out.reshape(phi_out.shape[1:])
        assert len(height_out.shape) > 0 and height_out.shape[0] == 1
        height_out = height_out.reshape(height_out.shape[1:])

    return elong_out, phi_out, height_out
STATUS_CODES['gc2gd'] = {0: 'OK', -2: 'internal error (Note 3)', -1: 'illegal identifier (Note 3)'}



def gc2gde(a, f, xyz):
    """
    Wrapper for ERFA function ``eraGc2gde``.

    Parameters
    ----------
    a : double array
    f : double array
    xyz : double array

    Returns
    -------
    elong : double array
    phi : double array
    height : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a G c 2 g d e
    - - - - - - - - - -

    Transform geocentric coordinates to geodetic for a reference
    ellipsoid of specified form.

    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
       eraGd2gce.

    7) The transformation for a standard ellipsoid (such as ERFA_WGS84) can
       more conveniently be performed by calling eraGc2gd, 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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    a_in = numpy.array(a, dtype=numpy.double, order="C", copy=False, subok=True)
    f_in = numpy.array(f, dtype=numpy.double, order="C", copy=False, subok=True)
    xyz_in = numpy.array(xyz, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(xyz_in, (3,), "xyz")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if a_in.shape == tuple():
            a_in = a_in.reshape((1,) + a_in.shape)
        else:
            make_outputs_scalar = False
        if f_in.shape == tuple():
            f_in = f_in.reshape((1,) + f_in.shape)
        else:
            make_outputs_scalar = False
        if xyz_in[...,0].shape == tuple():
            xyz_in = xyz_in.reshape((1,) + xyz_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), a_in, f_in, xyz_in[...,0])
    elong_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    phi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    height_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [a_in, f_in, xyz_in[...,0], elong_out, phi_out, height_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*4
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._gc2gde(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'gc2gde')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(elong_out.shape) > 0 and elong_out.shape[0] == 1
        elong_out = elong_out.reshape(elong_out.shape[1:])
        assert len(phi_out.shape) > 0 and phi_out.shape[0] == 1
        phi_out = phi_out.reshape(phi_out.shape[1:])
        assert len(height_out.shape) > 0 and height_out.shape[0] == 1
        height_out = height_out.reshape(height_out.shape[1:])

    return elong_out, phi_out, height_out
STATUS_CODES['gc2gde'] = {0: 'OK', -2: 'illegal a', -1: 'illegal f'}



def gd2gc(n, elong, phi, height):
    """
    Wrapper for ERFA function ``eraGd2gc``.

    Parameters
    ----------
    n : int array
    elong : double array
    phi : double array
    height : double array

    Returns
    -------
    xyz : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a G d 2 g c
    - - - - - - - - -

    Transform geodetic coordinates to geocentric using the specified
    reference ellipsoid.

    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     ERFA_WGS84
          2     ERFA_GRS80
          3     ERFA_WGS72

       The n value has no significance outside the ERFA software.  For
       convenience, symbols ERFA_WGS84 etc. are defined in erfam.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 eraGc2gd.

    Called:
       eraEform     Earth reference ellipsoids
       eraGd2gce    geodetic to geocentric transformation, general
       eraZp        zero p-vector

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    n_in = numpy.array(n, dtype=numpy.intc, order="C", copy=False, subok=True)
    elong_in = numpy.array(elong, dtype=numpy.double, order="C", copy=False, subok=True)
    phi_in = numpy.array(phi, dtype=numpy.double, order="C", copy=False, subok=True)
    height_in = numpy.array(height, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if n_in.shape == tuple():
            n_in = n_in.reshape((1,) + n_in.shape)
        else:
            make_outputs_scalar = False
        if elong_in.shape == tuple():
            elong_in = elong_in.reshape((1,) + elong_in.shape)
        else:
            make_outputs_scalar = False
        if phi_in.shape == tuple():
            phi_in = phi_in.reshape((1,) + phi_in.shape)
        else:
            make_outputs_scalar = False
        if height_in.shape == tuple():
            height_in = height_in.reshape((1,) + height_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), n_in, elong_in, phi_in, height_in)
    xyz_out = numpy.empty(broadcast.shape + (3,), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [n_in, elong_in, phi_in, height_in, xyz_out[...,0], c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._gd2gc(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'gd2gc')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(xyz_out.shape) > 0 and xyz_out.shape[0] == 1
        xyz_out = xyz_out.reshape(xyz_out.shape[1:])

    return xyz_out
STATUS_CODES['gd2gc'] = {0: 'OK', -2: 'illegal case (Note 3)', -1: 'illegal identifier (Note 3)'}



def gd2gce(a, f, elong, phi, height):
    """
    Wrapper for ERFA function ``eraGd2gce``.

    Parameters
    ----------
    a : double array
    f : double array
    elong : double array
    phi : double array
    height : double array

    Returns
    -------
    xyz : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a G d 2 g c e
    - - - - - - - - - -

    Transform geodetic coordinates to geocentric for a reference
    ellipsoid of specified form.

    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
       eraGc2gde.

    6) The transformation for a standard ellipsoid (such as ERFA_WGS84) can
       more conveniently be performed by calling eraGd2gc,  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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    a_in = numpy.array(a, dtype=numpy.double, order="C", copy=False, subok=True)
    f_in = numpy.array(f, dtype=numpy.double, order="C", copy=False, subok=True)
    elong_in = numpy.array(elong, dtype=numpy.double, order="C", copy=False, subok=True)
    phi_in = numpy.array(phi, dtype=numpy.double, order="C", copy=False, subok=True)
    height_in = numpy.array(height, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if a_in.shape == tuple():
            a_in = a_in.reshape((1,) + a_in.shape)
        else:
            make_outputs_scalar = False
        if f_in.shape == tuple():
            f_in = f_in.reshape((1,) + f_in.shape)
        else:
            make_outputs_scalar = False
        if elong_in.shape == tuple():
            elong_in = elong_in.reshape((1,) + elong_in.shape)
        else:
            make_outputs_scalar = False
        if phi_in.shape == tuple():
            phi_in = phi_in.reshape((1,) + phi_in.shape)
        else:
            make_outputs_scalar = False
        if height_in.shape == tuple():
            height_in = height_in.reshape((1,) + height_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), a_in, f_in, elong_in, phi_in, height_in)
    xyz_out = numpy.empty(broadcast.shape + (3,), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [a_in, f_in, elong_in, phi_in, height_in, xyz_out[...,0], c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*5 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._gd2gce(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'gd2gce')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(xyz_out.shape) > 0 and xyz_out.shape[0] == 1
        xyz_out = xyz_out.reshape(xyz_out.shape[1:])

    return xyz_out
STATUS_CODES['gd2gce'] = {0: 'OK', -1: 'illegal case (Note 4)Notes:'}



def d2dtf(scale, ndp, d1, d2):
    """
    Wrapper for ERFA function ``eraD2dtf``.

    Parameters
    ----------
    scale : const char array
    ndp : int array
    d1 : double array
    d2 : double array

    Returns
    -------
    iy : int array
    im : int array
    id : int array
    ihmsf : int array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a 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).

    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 ERFA internal convention is that
       the quasi-JD day represents UTC days whether the length is 86399,
       86400 or 86401 SI seconds.  In the 1960-1972 era there were
       smaller jumps (in either direction) each time the linear UTC(TAI)
       expression was changed, and these "mini-leaps" are also included
       in the ERFA convention.

    5) The warning status "dubious year" flags UTCs that predate the
       introduction of the time scale or that are too far in the future
       to be trusted.  See eraDat for further details.

    6) For calendar conventions and limitations, see eraCal2jd.

    Called:
       eraJd2cal    JD to Gregorian calendar
       eraD2tf      decompose days to hms
       eraDat       delta(AT) = TAI-UTC

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    scale_in = numpy.array(scale, dtype=numpy.dtype('S16'), order="C", copy=False, subok=True)
    ndp_in = numpy.array(ndp, dtype=numpy.intc, order="C", copy=False, subok=True)
    d1_in = numpy.array(d1, dtype=numpy.double, order="C", copy=False, subok=True)
    d2_in = numpy.array(d2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if scale_in.shape == tuple():
            scale_in = scale_in.reshape((1,) + scale_in.shape)
        else:
            make_outputs_scalar = False
        if ndp_in.shape == tuple():
            ndp_in = ndp_in.reshape((1,) + ndp_in.shape)
        else:
            make_outputs_scalar = False
        if d1_in.shape == tuple():
            d1_in = d1_in.reshape((1,) + d1_in.shape)
        else:
            make_outputs_scalar = False
        if d2_in.shape == tuple():
            d2_in = d2_in.reshape((1,) + d2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), scale_in, ndp_in, d1_in, d2_in)
    iy_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)
    im_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)
    id_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)
    ihmsf_out = numpy.empty(broadcast.shape + (4,), dtype=numpy.intc)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [scale_in, ndp_in, d1_in, d2_in, iy_out, im_out, id_out, ihmsf_out[...,0], c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*5
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._d2dtf(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'd2dtf')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(iy_out.shape) > 0 and iy_out.shape[0] == 1
        iy_out = iy_out.reshape(iy_out.shape[1:])
        assert len(im_out.shape) > 0 and im_out.shape[0] == 1
        im_out = im_out.reshape(im_out.shape[1:])
        assert len(id_out.shape) > 0 and id_out.shape[0] == 1
        id_out = id_out.reshape(id_out.shape[1:])
        assert len(ihmsf_out.shape) > 0 and ihmsf_out.shape[0] == 1
        ihmsf_out = ihmsf_out.reshape(ihmsf_out.shape[1:])

    return iy_out, im_out, id_out, ihmsf_out
STATUS_CODES['d2dtf'] = {0: 'OK', 1: 'dubious year (Note 5)', -1: 'unacceptable date (Note 6)'}



def dat(iy, im, id, fd):
    """
    Wrapper for ERFA function ``eraDat``.

    Parameters
    ----------
    iy : int array
    im : int array
    id : int array
    fd : double array

    Returns
    -------
    deltat : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - -
     e r a 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 constant 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:  2016 December 31   :
       :                                          :
       :__________________________________________:

    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)
                        -5 = internal error (Note 5)

    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 the constant
       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 +1.
       This is distinct from the error status -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 (0 to 1 is the valid
       range) even if not used;  if invalid, zero is used and status -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, status -2 (bad month)
       will be returned.  The "internal error" status refers to a
       case that is impossible but causes some compilers to issue a
       warning.

    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:
       eraCal2jd    Gregorian calendar to JD

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    iy_in = numpy.array(iy, dtype=numpy.intc, order="C", copy=False, subok=True)
    im_in = numpy.array(im, dtype=numpy.intc, order="C", copy=False, subok=True)
    id_in = numpy.array(id, dtype=numpy.intc, order="C", copy=False, subok=True)
    fd_in = numpy.array(fd, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if iy_in.shape == tuple():
            iy_in = iy_in.reshape((1,) + iy_in.shape)
        else:
            make_outputs_scalar = False
        if im_in.shape == tuple():
            im_in = im_in.reshape((1,) + im_in.shape)
        else:
            make_outputs_scalar = False
        if id_in.shape == tuple():
            id_in = id_in.reshape((1,) + id_in.shape)
        else:
            make_outputs_scalar = False
        if fd_in.shape == tuple():
            fd_in = fd_in.reshape((1,) + fd_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), iy_in, im_in, id_in, fd_in)
    deltat_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [iy_in, im_in, id_in, fd_in, deltat_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._dat(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'dat')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(deltat_out.shape) > 0 and deltat_out.shape[0] == 1
        deltat_out = deltat_out.reshape(deltat_out.shape[1:])

    return deltat_out
STATUS_CODES['dat'] = {0: 'OK', 1: 'dubious year (Note 1)', -1: 'bad year', -5: 'internal error (Note 5)', -4: 'bad fraction (Note 4)', -3: 'bad day (Note 3)', -2: 'bad month'}



def dtdb(date1, date2, ut, elong, u, v):
    """
    Wrapper for ERFA function ``eraDtdb``.

    Parameters
    ----------
    date1 : double array
    date2 : double array
    ut : double array
    elong : double array
    u : double array
    v : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a 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      <-  eraDtdb  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      <-  -eraDtdb is an approximation
               :
              TT              <-  terrestrial time

    Adopted values for the various constants can be found in the IERS
    Conventions (McCarthy & Petit 2003).

    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).

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    date1_in = numpy.array(date1, dtype=numpy.double, order="C", copy=False, subok=True)
    date2_in = numpy.array(date2, dtype=numpy.double, order="C", copy=False, subok=True)
    ut_in = numpy.array(ut, dtype=numpy.double, order="C", copy=False, subok=True)
    elong_in = numpy.array(elong, dtype=numpy.double, order="C", copy=False, subok=True)
    u_in = numpy.array(u, dtype=numpy.double, order="C", copy=False, subok=True)
    v_in = numpy.array(v, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if date1_in.shape == tuple():
            date1_in = date1_in.reshape((1,) + date1_in.shape)
        else:
            make_outputs_scalar = False
        if date2_in.shape == tuple():
            date2_in = date2_in.reshape((1,) + date2_in.shape)
        else:
            make_outputs_scalar = False
        if ut_in.shape == tuple():
            ut_in = ut_in.reshape((1,) + ut_in.shape)
        else:
            make_outputs_scalar = False
        if elong_in.shape == tuple():
            elong_in = elong_in.reshape((1,) + elong_in.shape)
        else:
            make_outputs_scalar = False
        if u_in.shape == tuple():
            u_in = u_in.reshape((1,) + u_in.shape)
        else:
            make_outputs_scalar = False
        if v_in.shape == tuple():
            v_in = v_in.reshape((1,) + v_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), date1_in, date2_in, ut_in, elong_in, u_in, v_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [date1_in, date2_in, ut_in, elong_in, u_in, v_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*6 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._dtdb(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def dtf2d(scale, iy, im, id, ihr, imn, sec):
    """
    Wrapper for ERFA function ``eraDtf2d``.

    Parameters
    ----------
    scale : const char array
    iy : int array
    im : int array
    id : int array
    ihr : int array
    imn : int array
    sec : double array

    Returns
    -------
    d1 : double array
    d2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a 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).

    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 eraCal2jd.

    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 ERFA internal convention is that
       the quasi-JD day represents UTC days whether the length is 86399,
       86400 or 86401 SI seconds.  In the 1960-1972 era there were
       smaller jumps (in either direction) each time the linear UTC(TAI)
       expression was changed, and these "mini-leaps" are also included
       in the ERFA convention.

    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 or that are too far in the future
       to be trusted.  See eraDat 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:
       eraCal2jd    Gregorian calendar to JD
       eraDat       delta(AT) = TAI-UTC
       eraJd2cal    JD to Gregorian calendar

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    scale_in = numpy.array(scale, dtype=numpy.dtype('S16'), order="C", copy=False, subok=True)
    iy_in = numpy.array(iy, dtype=numpy.intc, order="C", copy=False, subok=True)
    im_in = numpy.array(im, dtype=numpy.intc, order="C", copy=False, subok=True)
    id_in = numpy.array(id, dtype=numpy.intc, order="C", copy=False, subok=True)
    ihr_in = numpy.array(ihr, dtype=numpy.intc, order="C", copy=False, subok=True)
    imn_in = numpy.array(imn, dtype=numpy.intc, order="C", copy=False, subok=True)
    sec_in = numpy.array(sec, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if scale_in.shape == tuple():
            scale_in = scale_in.reshape((1,) + scale_in.shape)
        else:
            make_outputs_scalar = False
        if iy_in.shape == tuple():
            iy_in = iy_in.reshape((1,) + iy_in.shape)
        else:
            make_outputs_scalar = False
        if im_in.shape == tuple():
            im_in = im_in.reshape((1,) + im_in.shape)
        else:
            make_outputs_scalar = False
        if id_in.shape == tuple():
            id_in = id_in.reshape((1,) + id_in.shape)
        else:
            make_outputs_scalar = False
        if ihr_in.shape == tuple():
            ihr_in = ihr_in.reshape((1,) + ihr_in.shape)
        else:
            make_outputs_scalar = False
        if imn_in.shape == tuple():
            imn_in = imn_in.reshape((1,) + imn_in.shape)
        else:
            make_outputs_scalar = False
        if sec_in.shape == tuple():
            sec_in = sec_in.reshape((1,) + sec_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), scale_in, iy_in, im_in, id_in, ihr_in, imn_in, sec_in)
    d1_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    d2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [scale_in, iy_in, im_in, id_in, ihr_in, imn_in, sec_in, d1_out, d2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*7 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._dtf2d(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'dtf2d')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(d1_out.shape) > 0 and d1_out.shape[0] == 1
        d1_out = d1_out.reshape(d1_out.shape[1:])
        assert len(d2_out.shape) > 0 and d2_out.shape[0] == 1
        d2_out = d2_out.reshape(d2_out.shape[1:])

    return d1_out, d2_out
STATUS_CODES['dtf2d'] = {0: 'OK', 1: 'dubious year (Note 6)', 2: 'time is after end of day (Note 5)', 3: 'both of next two', -2: 'bad month', -6: 'bad second (<0)', -5: 'bad minute', -4: 'bad hour', -3: 'bad day', -1: 'bad year'}



def taitt(tai1, tai2):
    """
    Wrapper for ERFA function ``eraTaitt``.

    Parameters
    ----------
    tai1 : double array
    tai2 : double array

    Returns
    -------
    tt1 : double array
    tt2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a T a i t t
    - - - - - - - - -

    Time scale transformation:  International Atomic Time, TAI, to
    Terrestrial Time, TT.

    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tai1_in = numpy.array(tai1, dtype=numpy.double, order="C", copy=False, subok=True)
    tai2_in = numpy.array(tai2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tai1_in.shape == tuple():
            tai1_in = tai1_in.reshape((1,) + tai1_in.shape)
        else:
            make_outputs_scalar = False
        if tai2_in.shape == tuple():
            tai2_in = tai2_in.reshape((1,) + tai2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tai1_in, tai2_in)
    tt1_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    tt2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tai1_in, tai2_in, tt1_out, tt2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._taitt(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'taitt')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(tt1_out.shape) > 0 and tt1_out.shape[0] == 1
        tt1_out = tt1_out.reshape(tt1_out.shape[1:])
        assert len(tt2_out.shape) > 0 and tt2_out.shape[0] == 1
        tt2_out = tt2_out.reshape(tt2_out.shape[1:])

    return tt1_out, tt2_out
STATUS_CODES['taitt'] = {0: 'OK'}



def taiut1(tai1, tai2, dta):
    """
    Wrapper for ERFA function ``eraTaiut1``.

    Parameters
    ----------
    tai1 : double array
    tai2 : double array
    dta : double array

    Returns
    -------
    ut11 : double array
    ut12 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a T a i u t 1
    - - - - - - - - - -

    Time scale transformation:  International Atomic Time, TAI, to
    Universal Time, UT1.

    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tai1_in = numpy.array(tai1, dtype=numpy.double, order="C", copy=False, subok=True)
    tai2_in = numpy.array(tai2, dtype=numpy.double, order="C", copy=False, subok=True)
    dta_in = numpy.array(dta, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tai1_in.shape == tuple():
            tai1_in = tai1_in.reshape((1,) + tai1_in.shape)
        else:
            make_outputs_scalar = False
        if tai2_in.shape == tuple():
            tai2_in = tai2_in.reshape((1,) + tai2_in.shape)
        else:
            make_outputs_scalar = False
        if dta_in.shape == tuple():
            dta_in = dta_in.reshape((1,) + dta_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tai1_in, tai2_in, dta_in)
    ut11_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    ut12_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tai1_in, tai2_in, dta_in, ut11_out, ut12_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._taiut1(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'taiut1')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(ut11_out.shape) > 0 and ut11_out.shape[0] == 1
        ut11_out = ut11_out.reshape(ut11_out.shape[1:])
        assert len(ut12_out.shape) > 0 and ut12_out.shape[0] == 1
        ut12_out = ut12_out.reshape(ut12_out.shape[1:])

    return ut11_out, ut12_out
STATUS_CODES['taiut1'] = {0: 'OK'}



def taiutc(tai1, tai2):
    """
    Wrapper for ERFA function ``eraTaiutc``.

    Parameters
    ----------
    tai1 : double array
    tai2 : double array

    Returns
    -------
    utc1 : double array
    utc2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a T a i u t c
    - - - - - - - - - -

    Time scale transformation:  International Atomic Time, TAI, to
    Coordinated Universal Time, UTC.

    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.  In the 1960-1972 era
       there were smaller jumps (in either direction) each time the
       linear UTC(TAI) expression was changed, and these "mini-leaps"
       are also included in the ERFA convention.

    3) The function eraD2dtf 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 or that are too far in the future
       to be trusted.  See eraDat for further details.

    Called:
       eraUtctai    UTC to TAI

    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tai1_in = numpy.array(tai1, dtype=numpy.double, order="C", copy=False, subok=True)
    tai2_in = numpy.array(tai2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tai1_in.shape == tuple():
            tai1_in = tai1_in.reshape((1,) + tai1_in.shape)
        else:
            make_outputs_scalar = False
        if tai2_in.shape == tuple():
            tai2_in = tai2_in.reshape((1,) + tai2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tai1_in, tai2_in)
    utc1_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    utc2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tai1_in, tai2_in, utc1_out, utc2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._taiutc(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'taiutc')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(utc1_out.shape) > 0 and utc1_out.shape[0] == 1
        utc1_out = utc1_out.reshape(utc1_out.shape[1:])
        assert len(utc2_out.shape) > 0 and utc2_out.shape[0] == 1
        utc2_out = utc2_out.reshape(utc2_out.shape[1:])

    return utc1_out, utc2_out
STATUS_CODES['taiutc'] = {0: 'OK', 1: 'dubious year (Note 4)', -1: 'unacceptable date'}



def tcbtdb(tcb1, tcb2):
    """
    Wrapper for ERFA function ``eraTcbtdb``.

    Parameters
    ----------
    tcb1 : double array
    tcb2 : double array

    Returns
    -------
    tdb1 : double array
    tdb2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a T c b t d b
    - - - - - - - - - -

    Time scale transformation:  Barycentric Coordinate Time, TCB, to
    Barycentric Dynamical Time, TDB.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tcb1_in = numpy.array(tcb1, dtype=numpy.double, order="C", copy=False, subok=True)
    tcb2_in = numpy.array(tcb2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tcb1_in.shape == tuple():
            tcb1_in = tcb1_in.reshape((1,) + tcb1_in.shape)
        else:
            make_outputs_scalar = False
        if tcb2_in.shape == tuple():
            tcb2_in = tcb2_in.reshape((1,) + tcb2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tcb1_in, tcb2_in)
    tdb1_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    tdb2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tcb1_in, tcb2_in, tdb1_out, tdb2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._tcbtdb(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'tcbtdb')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(tdb1_out.shape) > 0 and tdb1_out.shape[0] == 1
        tdb1_out = tdb1_out.reshape(tdb1_out.shape[1:])
        assert len(tdb2_out.shape) > 0 and tdb2_out.shape[0] == 1
        tdb2_out = tdb2_out.reshape(tdb2_out.shape[1:])

    return tdb1_out, tdb2_out
STATUS_CODES['tcbtdb'] = {0: 'OK'}



def tcgtt(tcg1, tcg2):
    """
    Wrapper for ERFA function ``eraTcgtt``.

    Parameters
    ----------
    tcg1 : double array
    tcg2 : double array

    Returns
    -------
    tt1 : double array
    tt2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a T c g t t
    - - - - - - - - -

    Time scale transformation:  Geocentric Coordinate Time, TCG, to
    Terrestrial Time, TT.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tcg1_in = numpy.array(tcg1, dtype=numpy.double, order="C", copy=False, subok=True)
    tcg2_in = numpy.array(tcg2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tcg1_in.shape == tuple():
            tcg1_in = tcg1_in.reshape((1,) + tcg1_in.shape)
        else:
            make_outputs_scalar = False
        if tcg2_in.shape == tuple():
            tcg2_in = tcg2_in.reshape((1,) + tcg2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tcg1_in, tcg2_in)
    tt1_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    tt2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tcg1_in, tcg2_in, tt1_out, tt2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._tcgtt(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'tcgtt')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(tt1_out.shape) > 0 and tt1_out.shape[0] == 1
        tt1_out = tt1_out.reshape(tt1_out.shape[1:])
        assert len(tt2_out.shape) > 0 and tt2_out.shape[0] == 1
        tt2_out = tt2_out.reshape(tt2_out.shape[1:])

    return tt1_out, tt2_out
STATUS_CODES['tcgtt'] = {0: 'OK'}



def tdbtcb(tdb1, tdb2):
    """
    Wrapper for ERFA function ``eraTdbtcb``.

    Parameters
    ----------
    tdb1 : double array
    tdb2 : double array

    Returns
    -------
    tcb1 : double array
    tcb2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a T d b t c b
    - - - - - - - - - -

    Time scale transformation:  Barycentric Dynamical Time, TDB, to
    Barycentric Coordinate Time, TCB.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tdb1_in = numpy.array(tdb1, dtype=numpy.double, order="C", copy=False, subok=True)
    tdb2_in = numpy.array(tdb2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tdb1_in.shape == tuple():
            tdb1_in = tdb1_in.reshape((1,) + tdb1_in.shape)
        else:
            make_outputs_scalar = False
        if tdb2_in.shape == tuple():
            tdb2_in = tdb2_in.reshape((1,) + tdb2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tdb1_in, tdb2_in)
    tcb1_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    tcb2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tdb1_in, tdb2_in, tcb1_out, tcb2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._tdbtcb(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'tdbtcb')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(tcb1_out.shape) > 0 and tcb1_out.shape[0] == 1
        tcb1_out = tcb1_out.reshape(tcb1_out.shape[1:])
        assert len(tcb2_out.shape) > 0 and tcb2_out.shape[0] == 1
        tcb2_out = tcb2_out.reshape(tcb2_out.shape[1:])

    return tcb1_out, tcb2_out
STATUS_CODES['tdbtcb'] = {0: 'OK'}



def tdbtt(tdb1, tdb2, dtr):
    """
    Wrapper for ERFA function ``eraTdbtt``.

    Parameters
    ----------
    tdb1 : double array
    tdb2 : double array
    dtr : double array

    Returns
    -------
    tt1 : double array
    tt2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a T d b t t
    - - - - - - - - -

    Time scale transformation:  Barycentric Dynamical Time, TDB, to
    Terrestrial Time, TT.

    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 ERFA function
       eraDtdb.   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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tdb1_in = numpy.array(tdb1, dtype=numpy.double, order="C", copy=False, subok=True)
    tdb2_in = numpy.array(tdb2, dtype=numpy.double, order="C", copy=False, subok=True)
    dtr_in = numpy.array(dtr, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tdb1_in.shape == tuple():
            tdb1_in = tdb1_in.reshape((1,) + tdb1_in.shape)
        else:
            make_outputs_scalar = False
        if tdb2_in.shape == tuple():
            tdb2_in = tdb2_in.reshape((1,) + tdb2_in.shape)
        else:
            make_outputs_scalar = False
        if dtr_in.shape == tuple():
            dtr_in = dtr_in.reshape((1,) + dtr_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tdb1_in, tdb2_in, dtr_in)
    tt1_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    tt2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tdb1_in, tdb2_in, dtr_in, tt1_out, tt2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._tdbtt(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'tdbtt')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(tt1_out.shape) > 0 and tt1_out.shape[0] == 1
        tt1_out = tt1_out.reshape(tt1_out.shape[1:])
        assert len(tt2_out.shape) > 0 and tt2_out.shape[0] == 1
        tt2_out = tt2_out.reshape(tt2_out.shape[1:])

    return tt1_out, tt2_out
STATUS_CODES['tdbtt'] = {0: 'OK'}



def tttai(tt1, tt2):
    """
    Wrapper for ERFA function ``eraTttai``.

    Parameters
    ----------
    tt1 : double array
    tt2 : double array

    Returns
    -------
    tai1 : double array
    tai2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a T t t a i
    - - - - - - - - -

    Time scale transformation:  Terrestrial Time, TT, to International
    Atomic Time, TAI.

    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tt1_in = numpy.array(tt1, dtype=numpy.double, order="C", copy=False, subok=True)
    tt2_in = numpy.array(tt2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tt1_in.shape == tuple():
            tt1_in = tt1_in.reshape((1,) + tt1_in.shape)
        else:
            make_outputs_scalar = False
        if tt2_in.shape == tuple():
            tt2_in = tt2_in.reshape((1,) + tt2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tt1_in, tt2_in)
    tai1_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    tai2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tt1_in, tt2_in, tai1_out, tai2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._tttai(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'tttai')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(tai1_out.shape) > 0 and tai1_out.shape[0] == 1
        tai1_out = tai1_out.reshape(tai1_out.shape[1:])
        assert len(tai2_out.shape) > 0 and tai2_out.shape[0] == 1
        tai2_out = tai2_out.reshape(tai2_out.shape[1:])

    return tai1_out, tai2_out
STATUS_CODES['tttai'] = {0: 'OK'}



def tttcg(tt1, tt2):
    """
    Wrapper for ERFA function ``eraTttcg``.

    Parameters
    ----------
    tt1 : double array
    tt2 : double array

    Returns
    -------
    tcg1 : double array
    tcg2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a T t t c g
    - - - - - - - - -

    Time scale transformation:  Terrestrial Time, TT, to Geocentric
    Coordinate Time, TCG.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tt1_in = numpy.array(tt1, dtype=numpy.double, order="C", copy=False, subok=True)
    tt2_in = numpy.array(tt2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tt1_in.shape == tuple():
            tt1_in = tt1_in.reshape((1,) + tt1_in.shape)
        else:
            make_outputs_scalar = False
        if tt2_in.shape == tuple():
            tt2_in = tt2_in.reshape((1,) + tt2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tt1_in, tt2_in)
    tcg1_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    tcg2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tt1_in, tt2_in, tcg1_out, tcg2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._tttcg(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'tttcg')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(tcg1_out.shape) > 0 and tcg1_out.shape[0] == 1
        tcg1_out = tcg1_out.reshape(tcg1_out.shape[1:])
        assert len(tcg2_out.shape) > 0 and tcg2_out.shape[0] == 1
        tcg2_out = tcg2_out.reshape(tcg2_out.shape[1:])

    return tcg1_out, tcg2_out
STATUS_CODES['tttcg'] = {0: 'OK'}



def tttdb(tt1, tt2, dtr):
    """
    Wrapper for ERFA function ``eraTttdb``.

    Parameters
    ----------
    tt1 : double array
    tt2 : double array
    dtr : double array

    Returns
    -------
    tdb1 : double array
    tdb2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a T t t d b
    - - - - - - - - -

    Time scale transformation:  Terrestrial Time, TT, to Barycentric
    Dynamical Time, TDB.

    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 ERFA function
       eraDtdb.   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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tt1_in = numpy.array(tt1, dtype=numpy.double, order="C", copy=False, subok=True)
    tt2_in = numpy.array(tt2, dtype=numpy.double, order="C", copy=False, subok=True)
    dtr_in = numpy.array(dtr, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tt1_in.shape == tuple():
            tt1_in = tt1_in.reshape((1,) + tt1_in.shape)
        else:
            make_outputs_scalar = False
        if tt2_in.shape == tuple():
            tt2_in = tt2_in.reshape((1,) + tt2_in.shape)
        else:
            make_outputs_scalar = False
        if dtr_in.shape == tuple():
            dtr_in = dtr_in.reshape((1,) + dtr_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tt1_in, tt2_in, dtr_in)
    tdb1_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    tdb2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tt1_in, tt2_in, dtr_in, tdb1_out, tdb2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._tttdb(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'tttdb')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(tdb1_out.shape) > 0 and tdb1_out.shape[0] == 1
        tdb1_out = tdb1_out.reshape(tdb1_out.shape[1:])
        assert len(tdb2_out.shape) > 0 and tdb2_out.shape[0] == 1
        tdb2_out = tdb2_out.reshape(tdb2_out.shape[1:])

    return tdb1_out, tdb2_out
STATUS_CODES['tttdb'] = {0: 'OK'}



def ttut1(tt1, tt2, dt):
    """
    Wrapper for ERFA function ``eraTtut1``.

    Parameters
    ----------
    tt1 : double array
    tt2 : double array
    dt : double array

    Returns
    -------
    ut11 : double array
    ut12 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a T t u t 1
    - - - - - - - - -

    Time scale transformation:  Terrestrial Time, TT, to Universal Time,
    UT1.

    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    tt1_in = numpy.array(tt1, dtype=numpy.double, order="C", copy=False, subok=True)
    tt2_in = numpy.array(tt2, dtype=numpy.double, order="C", copy=False, subok=True)
    dt_in = numpy.array(dt, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if tt1_in.shape == tuple():
            tt1_in = tt1_in.reshape((1,) + tt1_in.shape)
        else:
            make_outputs_scalar = False
        if tt2_in.shape == tuple():
            tt2_in = tt2_in.reshape((1,) + tt2_in.shape)
        else:
            make_outputs_scalar = False
        if dt_in.shape == tuple():
            dt_in = dt_in.reshape((1,) + dt_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), tt1_in, tt2_in, dt_in)
    ut11_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    ut12_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [tt1_in, tt2_in, dt_in, ut11_out, ut12_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ttut1(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'ttut1')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(ut11_out.shape) > 0 and ut11_out.shape[0] == 1
        ut11_out = ut11_out.reshape(ut11_out.shape[1:])
        assert len(ut12_out.shape) > 0 and ut12_out.shape[0] == 1
        ut12_out = ut12_out.reshape(ut12_out.shape[1:])

    return ut11_out, ut12_out
STATUS_CODES['ttut1'] = {0: 'OK'}



def ut1tai(ut11, ut12, dta):
    """
    Wrapper for ERFA function ``eraUt1tai``.

    Parameters
    ----------
    ut11 : double array
    ut12 : double array
    dta : double array

    Returns
    -------
    tai1 : double array
    tai2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a U t 1 t a i
    - - - - - - - - - -

    Time scale transformation:  Universal Time, UT1, to International
    Atomic Time, TAI.

    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ut11_in = numpy.array(ut11, dtype=numpy.double, order="C", copy=False, subok=True)
    ut12_in = numpy.array(ut12, dtype=numpy.double, order="C", copy=False, subok=True)
    dta_in = numpy.array(dta, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ut11_in.shape == tuple():
            ut11_in = ut11_in.reshape((1,) + ut11_in.shape)
        else:
            make_outputs_scalar = False
        if ut12_in.shape == tuple():
            ut12_in = ut12_in.reshape((1,) + ut12_in.shape)
        else:
            make_outputs_scalar = False
        if dta_in.shape == tuple():
            dta_in = dta_in.reshape((1,) + dta_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ut11_in, ut12_in, dta_in)
    tai1_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    tai2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ut11_in, ut12_in, dta_in, tai1_out, tai2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ut1tai(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'ut1tai')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(tai1_out.shape) > 0 and tai1_out.shape[0] == 1
        tai1_out = tai1_out.reshape(tai1_out.shape[1:])
        assert len(tai2_out.shape) > 0 and tai2_out.shape[0] == 1
        tai2_out = tai2_out.reshape(tai2_out.shape[1:])

    return tai1_out, tai2_out
STATUS_CODES['ut1tai'] = {0: 'OK'}



def ut1tt(ut11, ut12, dt):
    """
    Wrapper for ERFA function ``eraUt1tt``.

    Parameters
    ----------
    ut11 : double array
    ut12 : double array
    dt : double array

    Returns
    -------
    tt1 : double array
    tt2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a U t 1 t t
    - - - - - - - - -

    Time scale transformation:  Universal Time, UT1, to Terrestrial
    Time, TT.

    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ut11_in = numpy.array(ut11, dtype=numpy.double, order="C", copy=False, subok=True)
    ut12_in = numpy.array(ut12, dtype=numpy.double, order="C", copy=False, subok=True)
    dt_in = numpy.array(dt, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ut11_in.shape == tuple():
            ut11_in = ut11_in.reshape((1,) + ut11_in.shape)
        else:
            make_outputs_scalar = False
        if ut12_in.shape == tuple():
            ut12_in = ut12_in.reshape((1,) + ut12_in.shape)
        else:
            make_outputs_scalar = False
        if dt_in.shape == tuple():
            dt_in = dt_in.reshape((1,) + dt_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ut11_in, ut12_in, dt_in)
    tt1_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    tt2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ut11_in, ut12_in, dt_in, tt1_out, tt2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ut1tt(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'ut1tt')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(tt1_out.shape) > 0 and tt1_out.shape[0] == 1
        tt1_out = tt1_out.reshape(tt1_out.shape[1:])
        assert len(tt2_out.shape) > 0 and tt2_out.shape[0] == 1
        tt2_out = tt2_out.reshape(tt2_out.shape[1:])

    return tt1_out, tt2_out
STATUS_CODES['ut1tt'] = {0: 'OK'}



def ut1utc(ut11, ut12, dut1):
    """
    Wrapper for ERFA function ``eraUt1utc``.

    Parameters
    ----------
    ut11 : double array
    ut12 : double array
    dut1 : double array

    Returns
    -------
    utc1 : double array
    utc2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a U t 1 u t c
    - - - - - - - - - -

    Time scale transformation:  Universal Time, UT1, to Coordinated
    Universal Time, UTC.

    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 eraD2dtf 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 or that are too far in the future
       to be trusted.  See eraDat for further details.

    Called:
       eraJd2cal    JD to Gregorian calendar
       eraDat       delta(AT) = TAI-UTC
       eraCal2jd    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ut11_in = numpy.array(ut11, dtype=numpy.double, order="C", copy=False, subok=True)
    ut12_in = numpy.array(ut12, dtype=numpy.double, order="C", copy=False, subok=True)
    dut1_in = numpy.array(dut1, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ut11_in.shape == tuple():
            ut11_in = ut11_in.reshape((1,) + ut11_in.shape)
        else:
            make_outputs_scalar = False
        if ut12_in.shape == tuple():
            ut12_in = ut12_in.reshape((1,) + ut12_in.shape)
        else:
            make_outputs_scalar = False
        if dut1_in.shape == tuple():
            dut1_in = dut1_in.reshape((1,) + dut1_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ut11_in, ut12_in, dut1_in)
    utc1_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    utc2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ut11_in, ut12_in, dut1_in, utc1_out, utc2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._ut1utc(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'ut1utc')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(utc1_out.shape) > 0 and utc1_out.shape[0] == 1
        utc1_out = utc1_out.reshape(utc1_out.shape[1:])
        assert len(utc2_out.shape) > 0 and utc2_out.shape[0] == 1
        utc2_out = utc2_out.reshape(utc2_out.shape[1:])

    return utc1_out, utc2_out
STATUS_CODES['ut1utc'] = {0: 'OK', 1: 'dubious year (Note 5)', -1: 'unacceptable date'}



def utctai(utc1, utc2):
    """
    Wrapper for ERFA function ``eraUtctai``.

    Parameters
    ----------
    utc1 : double array
    utc2 : double array

    Returns
    -------
    tai1 : double array
    tai2 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a U t c t a i
    - - - - - - - - - -

    Time scale transformation:  Coordinated Universal Time, UTC, to
    International Atomic Time, TAI.

    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.  In the 1960-1972 era
       there were smaller jumps (in either direction) each time the
       linear UTC(TAI) expression was changed, and these "mini-leaps"
       are also included in the ERFA convention.

    3) The warning status "dubious year" flags UTCs that predate the
       introduction of the time scale or that are too far in the future
       to be trusted.  See eraDat for further details.

    4) The function eraDtf2d 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:
       eraJd2cal    JD to Gregorian calendar
       eraDat       delta(AT) = TAI-UTC
       eraCal2jd    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)

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    utc1_in = numpy.array(utc1, dtype=numpy.double, order="C", copy=False, subok=True)
    utc2_in = numpy.array(utc2, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if utc1_in.shape == tuple():
            utc1_in = utc1_in.reshape((1,) + utc1_in.shape)
        else:
            make_outputs_scalar = False
        if utc2_in.shape == tuple():
            utc2_in = utc2_in.reshape((1,) + utc2_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), utc1_in, utc2_in)
    tai1_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    tai2_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [utc1_in, utc2_in, tai1_out, tai2_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._utctai(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'utctai')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(tai1_out.shape) > 0 and tai1_out.shape[0] == 1
        tai1_out = tai1_out.reshape(tai1_out.shape[1:])
        assert len(tai2_out.shape) > 0 and tai2_out.shape[0] == 1
        tai2_out = tai2_out.reshape(tai2_out.shape[1:])

    return tai1_out, tai2_out
STATUS_CODES['utctai'] = {0: 'OK', 1: 'dubious year (Note 3)', -1: 'unacceptable date'}



def utcut1(utc1, utc2, dut1):
    """
    Wrapper for ERFA function ``eraUtcut1``.

    Parameters
    ----------
    utc1 : double array
    utc2 : double array
    dut1 : double array

    Returns
    -------
    ut11 : double array
    ut12 : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - - -
     e r a U t c u t 1
    - - - - - - - - - -

    Time scale transformation:  Coordinated Universal Time, UTC, to
    Universal Time, UT1.

    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 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 or that are too far in the future
       to be trusted.  See eraDat for further details.

    4) The function eraDtf2d 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 is the caller's responsibility to supply a dut1 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.

    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:
       eraJd2cal    JD to Gregorian calendar
       eraDat       delta(AT) = TAI-UTC
       eraUtctai    UTC to TAI
       eraTaiut1    TAI to UT1

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    utc1_in = numpy.array(utc1, dtype=numpy.double, order="C", copy=False, subok=True)
    utc2_in = numpy.array(utc2, dtype=numpy.double, order="C", copy=False, subok=True)
    dut1_in = numpy.array(dut1, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if utc1_in.shape == tuple():
            utc1_in = utc1_in.reshape((1,) + utc1_in.shape)
        else:
            make_outputs_scalar = False
        if utc2_in.shape == tuple():
            utc2_in = utc2_in.reshape((1,) + utc2_in.shape)
        else:
            make_outputs_scalar = False
        if dut1_in.shape == tuple():
            dut1_in = dut1_in.reshape((1,) + dut1_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), utc1_in, utc2_in, dut1_in)
    ut11_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    ut12_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [utc1_in, utc2_in, dut1_in, ut11_out, ut12_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._utcut1(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'utcut1')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(ut11_out.shape) > 0 and ut11_out.shape[0] == 1
        ut11_out = ut11_out.reshape(ut11_out.shape[1:])
        assert len(ut12_out.shape) > 0 and ut12_out.shape[0] == 1
        ut12_out = ut12_out.reshape(ut12_out.shape[1:])

    return ut11_out, ut12_out
STATUS_CODES['utcut1'] = {0: 'OK', 1: 'dubious year (Note 3)', -1: 'unacceptable date'}



def a2af(ndp, angle):
    """
    Wrapper for ERFA function ``eraA2af``.

    Parameters
    ----------
    ndp : int array
    angle : double array

    Returns
    -------
    sign : char array
    idmsf : int array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a A 2 a f
    - - - - - - - -

    Decompose radians into degrees, arcminutes, arcseconds, fraction.

    Given:
       ndp     int     resolution (Note 1)
       angle   double  angle in radians

    Returned:
       sign    char    '+' or '-'
       idmsf   int[4]  degrees, arcminutes, arcseconds, fraction

    Called:
       eraD2tf      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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ndp_in = numpy.array(ndp, dtype=numpy.intc, order="C", copy=False, subok=True)
    angle_in = numpy.array(angle, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ndp_in.shape == tuple():
            ndp_in = ndp_in.reshape((1,) + ndp_in.shape)
        else:
            make_outputs_scalar = False
        if angle_in.shape == tuple():
            angle_in = angle_in.reshape((1,) + angle_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ndp_in, angle_in)
    sign_out = numpy.empty(broadcast.shape + (), dtype=numpy.dtype('S1'))
    idmsf_out = numpy.empty(broadcast.shape + (4,), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ndp_in, angle_in, sign_out, idmsf_out[...,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._a2af(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(sign_out.shape) > 0 and sign_out.shape[0] == 1
        sign_out = sign_out.reshape(sign_out.shape[1:])
        assert len(idmsf_out.shape) > 0 and idmsf_out.shape[0] == 1
        idmsf_out = idmsf_out.reshape(idmsf_out.shape[1:])

    return sign_out, idmsf_out


def a2tf(ndp, angle):
    """
    Wrapper for ERFA function ``eraA2tf``.

    Parameters
    ----------
    ndp : int array
    angle : double array

    Returns
    -------
    sign : char array
    ihmsf : int array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a A 2 t f
    - - - - - - - -

    Decompose radians into hours, minutes, seconds, fraction.

    Given:
       ndp     int     resolution (Note 1)
       angle   double  angle in radians

    Returned:
       sign    char    '+' or '-'
       ihmsf   int[4]  hours, minutes, seconds, fraction

    Called:
       eraD2tf      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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ndp_in = numpy.array(ndp, dtype=numpy.intc, order="C", copy=False, subok=True)
    angle_in = numpy.array(angle, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ndp_in.shape == tuple():
            ndp_in = ndp_in.reshape((1,) + ndp_in.shape)
        else:
            make_outputs_scalar = False
        if angle_in.shape == tuple():
            angle_in = angle_in.reshape((1,) + angle_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ndp_in, angle_in)
    sign_out = numpy.empty(broadcast.shape + (), dtype=numpy.dtype('S1'))
    ihmsf_out = numpy.empty(broadcast.shape + (4,), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ndp_in, angle_in, sign_out, ihmsf_out[...,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._a2tf(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(sign_out.shape) > 0 and sign_out.shape[0] == 1
        sign_out = sign_out.reshape(sign_out.shape[1:])
        assert len(ihmsf_out.shape) > 0 and ihmsf_out.shape[0] == 1
        ihmsf_out = ihmsf_out.reshape(ihmsf_out.shape[1:])

    return sign_out, ihmsf_out


def af2a(s, ideg, iamin, asec):
    """
    Wrapper for ERFA function ``eraAf2a``.

    Parameters
    ----------
    s : char array
    ideg : int array
    iamin : int array
    asec : double array

    Returns
    -------
    rad : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a A f 2 a
    - - - - - - - -

    Convert degrees, arcminutes, arcseconds to radians.

    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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    s_in = numpy.array(s, dtype=numpy.dtype('S1'), order="C", copy=False, subok=True)
    ideg_in = numpy.array(ideg, dtype=numpy.intc, order="C", copy=False, subok=True)
    iamin_in = numpy.array(iamin, dtype=numpy.intc, order="C", copy=False, subok=True)
    asec_in = numpy.array(asec, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if s_in.shape == tuple():
            s_in = s_in.reshape((1,) + s_in.shape)
        else:
            make_outputs_scalar = False
        if ideg_in.shape == tuple():
            ideg_in = ideg_in.reshape((1,) + ideg_in.shape)
        else:
            make_outputs_scalar = False
        if iamin_in.shape == tuple():
            iamin_in = iamin_in.reshape((1,) + iamin_in.shape)
        else:
            make_outputs_scalar = False
        if asec_in.shape == tuple():
            asec_in = asec_in.reshape((1,) + asec_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), s_in, ideg_in, iamin_in, asec_in)
    rad_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [s_in, ideg_in, iamin_in, asec_in, rad_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._af2a(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'af2a')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rad_out.shape) > 0 and rad_out.shape[0] == 1
        rad_out = rad_out.reshape(rad_out.shape[1:])

    return rad_out
STATUS_CODES['af2a'] = {0: 'OK', 1: 'ideg outside range 0-359', 2: 'iamin outside range 0-59', 3: 'asec outside range 0-59.999...'}



def anp(a):
    """
    Wrapper for ERFA function ``eraAnp``.

    Parameters
    ----------
    a : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - -
     e r a A n p
    - - - - - - -

    Normalize angle into the range 0 <= a < 2pi.

    Given:
       a        double     angle (radians)

    Returned (function value):
                double     angle in range 0-2pi

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    a_in = numpy.array(a, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if a_in.shape == tuple():
            a_in = a_in.reshape((1,) + a_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), a_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [a_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._anp(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def anpm(a):
    """
    Wrapper for ERFA function ``eraAnpm``.

    Parameters
    ----------
    a : double array

    Returns
    -------
    c_retval : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a A n p m
    - - - - - - - -

    Normalize angle into the range -pi <= a < +pi.

    Given:
       a        double     angle (radians)

    Returned (function value):
                double     angle in range +/-pi

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    a_in = numpy.array(a, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if a_in.shape == tuple():
            a_in = a_in.reshape((1,) + a_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), a_in)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [a_in, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._anpm(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_retval_out.shape) > 0 and c_retval_out.shape[0] == 1
        c_retval_out = c_retval_out.reshape(c_retval_out.shape[1:])

    return c_retval_out


def d2tf(ndp, days):
    """
    Wrapper for ERFA function ``eraD2tf``.

    Parameters
    ----------
    ndp : int array
    days : double array

    Returns
    -------
    sign : char array
    ihmsf : int array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a D 2 t f
    - - - - - - - -

    Decompose days to hours, minutes, seconds, fraction.

    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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    ndp_in = numpy.array(ndp, dtype=numpy.intc, order="C", copy=False, subok=True)
    days_in = numpy.array(days, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if ndp_in.shape == tuple():
            ndp_in = ndp_in.reshape((1,) + ndp_in.shape)
        else:
            make_outputs_scalar = False
        if days_in.shape == tuple():
            days_in = days_in.reshape((1,) + days_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), ndp_in, days_in)
    sign_out = numpy.empty(broadcast.shape + (), dtype=numpy.dtype('S1'))
    ihmsf_out = numpy.empty(broadcast.shape + (4,), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [ndp_in, days_in, sign_out, ihmsf_out[...,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._d2tf(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(sign_out.shape) > 0 and sign_out.shape[0] == 1
        sign_out = sign_out.reshape(sign_out.shape[1:])
        assert len(ihmsf_out.shape) > 0 and ihmsf_out.shape[0] == 1
        ihmsf_out = ihmsf_out.reshape(ihmsf_out.shape[1:])

    return sign_out, ihmsf_out


def tf2a(s, ihour, imin, sec):
    """
    Wrapper for ERFA function ``eraTf2a``.

    Parameters
    ----------
    s : char array
    ihour : int array
    imin : int array
    sec : double array

    Returns
    -------
    rad : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a T f 2 a
    - - - - - - - -

    Convert hours, minutes, seconds to radians.

    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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    s_in = numpy.array(s, dtype=numpy.dtype('S1'), order="C", copy=False, subok=True)
    ihour_in = numpy.array(ihour, dtype=numpy.intc, order="C", copy=False, subok=True)
    imin_in = numpy.array(imin, dtype=numpy.intc, order="C", copy=False, subok=True)
    sec_in = numpy.array(sec, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if s_in.shape == tuple():
            s_in = s_in.reshape((1,) + s_in.shape)
        else:
            make_outputs_scalar = False
        if ihour_in.shape == tuple():
            ihour_in = ihour_in.reshape((1,) + ihour_in.shape)
        else:
            make_outputs_scalar = False
        if imin_in.shape == tuple():
            imin_in = imin_in.reshape((1,) + imin_in.shape)
        else:
            make_outputs_scalar = False
        if sec_in.shape == tuple():
            sec_in = sec_in.reshape((1,) + sec_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), s_in, ihour_in, imin_in, sec_in)
    rad_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [s_in, ihour_in, imin_in, sec_in, rad_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._tf2a(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'tf2a')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rad_out.shape) > 0 and rad_out.shape[0] == 1
        rad_out = rad_out.reshape(rad_out.shape[1:])

    return rad_out
STATUS_CODES['tf2a'] = {0: 'OK', 1: 'ihour outside range 0-23', 2: 'imin outside range 0-59', 3: 'sec outside range 0-59.999...'}



def tf2d(s, ihour, imin, sec):
    """
    Wrapper for ERFA function ``eraTf2d``.

    Parameters
    ----------
    s : char array
    ihour : int array
    imin : int array
    sec : double array

    Returns
    -------
    days : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a T f 2 d
    - - - - - - - -

    Convert hours, minutes, seconds to days.

    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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    s_in = numpy.array(s, dtype=numpy.dtype('S1'), order="C", copy=False, subok=True)
    ihour_in = numpy.array(ihour, dtype=numpy.intc, order="C", copy=False, subok=True)
    imin_in = numpy.array(imin, dtype=numpy.intc, order="C", copy=False, subok=True)
    sec_in = numpy.array(sec, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if s_in.shape == tuple():
            s_in = s_in.reshape((1,) + s_in.shape)
        else:
            make_outputs_scalar = False
        if ihour_in.shape == tuple():
            ihour_in = ihour_in.reshape((1,) + ihour_in.shape)
        else:
            make_outputs_scalar = False
        if imin_in.shape == tuple():
            imin_in = imin_in.reshape((1,) + imin_in.shape)
        else:
            make_outputs_scalar = False
        if sec_in.shape == tuple():
            sec_in = sec_in.reshape((1,) + sec_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), s_in, ihour_in, imin_in, sec_in)
    days_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    c_retval_out = numpy.empty(broadcast.shape + (), dtype=numpy.intc)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [s_in, ihour_in, imin_in, sec_in, days_out, c_retval_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*4 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._tf2d(it)

    if not stat_ok:
        check_errwarn(c_retval_out, 'tf2d')
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(days_out.shape) > 0 and days_out.shape[0] == 1
        days_out = days_out.reshape(days_out.shape[1:])

    return days_out
STATUS_CODES['tf2d'] = {0: 'OK', 1: 'ihour outside range 0-23', 2: 'imin outside range 0-59', 3: 'sec outside range 0-59.999...'}



def rxp(r, p):
    """
    Wrapper for ERFA function ``eraRxp``.

    Parameters
    ----------
    r : double array
    p : double array

    Returns
    -------
    rp : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - -
     e r a R x p
    - - - - - - -

    Multiply a p-vector by an r-matrix.

    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:
       eraCp        copy p-vector

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    r_in = numpy.array(r, dtype=numpy.double, order="C", copy=False, subok=True)
    p_in = numpy.array(p, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(r_in, (3, 3), "r")
    check_trailing_shape(p_in, (3,), "p")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if r_in[...,0,0].shape == tuple():
            r_in = r_in.reshape((1,) + r_in.shape)
        else:
            make_outputs_scalar = False
        if p_in[...,0].shape == tuple():
            p_in = p_in.reshape((1,) + p_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), r_in[...,0,0], p_in[...,0])
    rp_out = numpy.empty(broadcast.shape + (3,), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [r_in[...,0,0], p_in[...,0], rp_out[...,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._rxp(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rp_out.shape) > 0 and rp_out.shape[0] == 1
        rp_out = rp_out.reshape(rp_out.shape[1:])

    return rp_out


def rxpv(r, pv):
    """
    Wrapper for ERFA function ``eraRxpv``.

    Parameters
    ----------
    r : double array
    pv : double array

    Returns
    -------
    rpv : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a R x p v
    - - - - - - - -

    Multiply a pv-vector by an r-matrix.

    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:
       eraRxp       product of r-matrix and p-vector

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    r_in = numpy.array(r, dtype=numpy.double, order="C", copy=False, subok=True)
    pv_in = numpy.array(pv, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(r_in, (3, 3), "r")
    check_trailing_shape(pv_in, (2, 3), "pv")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if r_in[...,0,0].shape == tuple():
            r_in = r_in.reshape((1,) + r_in.shape)
        else:
            make_outputs_scalar = False
        if pv_in[...,0,0].shape == tuple():
            pv_in = pv_in.reshape((1,) + pv_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), r_in[...,0,0], pv_in[...,0,0])
    rpv_out = numpy.empty(broadcast.shape + (2, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [r_in[...,0,0], pv_in[...,0,0], rpv_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._rxpv(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(rpv_out.shape) > 0 and rpv_out.shape[0] == 1
        rpv_out = rpv_out.reshape(rpv_out.shape[1:])

    return rpv_out


def trxp(r, p):
    """
    Wrapper for ERFA function ``eraTrxp``.

    Parameters
    ----------
    r : double array
    p : double array

    Returns
    -------
    trp : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a T r x p
    - - - - - - - -

    Multiply a p-vector by the transpose of an r-matrix.

    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:
       eraTr        transpose r-matrix
       eraRxp       product of r-matrix and p-vector

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    r_in = numpy.array(r, dtype=numpy.double, order="C", copy=False, subok=True)
    p_in = numpy.array(p, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(r_in, (3, 3), "r")
    check_trailing_shape(p_in, (3,), "p")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if r_in[...,0,0].shape == tuple():
            r_in = r_in.reshape((1,) + r_in.shape)
        else:
            make_outputs_scalar = False
        if p_in[...,0].shape == tuple():
            p_in = p_in.reshape((1,) + p_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), r_in[...,0,0], p_in[...,0])
    trp_out = numpy.empty(broadcast.shape + (3,), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [r_in[...,0,0], p_in[...,0], trp_out[...,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._trxp(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(trp_out.shape) > 0 and trp_out.shape[0] == 1
        trp_out = trp_out.reshape(trp_out.shape[1:])

    return trp_out


def trxpv(r, pv):
    """
    Wrapper for ERFA function ``eraTrxpv``.

    Parameters
    ----------
    r : double array
    pv : double array

    Returns
    -------
    trpv : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - - -
     e r a T r x p v
    - - - - - - - - -

    Multiply a pv-vector by the transpose of an r-matrix.

    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:
       eraTr        transpose r-matrix
       eraRxpv      product of r-matrix and pv-vector

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    r_in = numpy.array(r, dtype=numpy.double, order="C", copy=False, subok=True)
    pv_in = numpy.array(pv, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(r_in, (3, 3), "r")
    check_trailing_shape(pv_in, (2, 3), "pv")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if r_in[...,0,0].shape == tuple():
            r_in = r_in.reshape((1,) + r_in.shape)
        else:
            make_outputs_scalar = False
        if pv_in[...,0,0].shape == tuple():
            pv_in = pv_in.reshape((1,) + pv_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), r_in[...,0,0], pv_in[...,0,0])
    trpv_out = numpy.empty(broadcast.shape + (2, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [r_in[...,0,0], pv_in[...,0,0], trpv_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._trxpv(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(trpv_out.shape) > 0 and trpv_out.shape[0] == 1
        trpv_out = trpv_out.reshape(trpv_out.shape[1:])

    return trpv_out


def c2s(p):
    """
    Wrapper for ERFA function ``eraC2s``.

    Parameters
    ----------
    p : double array

    Returns
    -------
    theta : double array
    phi : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - -
     e r a C 2 s
    - - - - - - -

    P-vector to spherical coordinates.

    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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    p_in = numpy.array(p, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(p_in, (3,), "p")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if p_in[...,0].shape == tuple():
            p_in = p_in.reshape((1,) + p_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), p_in[...,0])
    theta_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    phi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [p_in[...,0], theta_out, phi_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*2
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._c2s(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(theta_out.shape) > 0 and theta_out.shape[0] == 1
        theta_out = theta_out.reshape(theta_out.shape[1:])
        assert len(phi_out.shape) > 0 and phi_out.shape[0] == 1
        phi_out = phi_out.reshape(phi_out.shape[1:])

    return theta_out, phi_out


def p2s(p):
    """
    Wrapper for ERFA function ``eraP2s``.

    Parameters
    ----------
    p : double array

    Returns
    -------
    theta : double array
    phi : double array
    r : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - -
     e r a P 2 s
    - - - - - - -

    P-vector to spherical polar coordinates.

    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:
       eraC2s       p-vector to spherical
       eraPm        modulus of p-vector

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    p_in = numpy.array(p, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(p_in, (3,), "p")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if p_in[...,0].shape == tuple():
            p_in = p_in.reshape((1,) + p_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), p_in[...,0])
    theta_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    phi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    r_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [p_in[...,0], theta_out, phi_out, r_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*3
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._p2s(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(theta_out.shape) > 0 and theta_out.shape[0] == 1
        theta_out = theta_out.reshape(theta_out.shape[1:])
        assert len(phi_out.shape) > 0 and phi_out.shape[0] == 1
        phi_out = phi_out.reshape(phi_out.shape[1:])
        assert len(r_out.shape) > 0 and r_out.shape[0] == 1
        r_out = r_out.reshape(r_out.shape[1:])

    return theta_out, phi_out, r_out


def pv2s(pv):
    """
    Wrapper for ERFA function ``eraPv2s``.

    Parameters
    ----------
    pv : double array

    Returns
    -------
    theta : double array
    phi : double array
    r : double array
    td : double array
    pd : double array
    rd : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a P v 2 s
    - - - - - - - -

    Convert position/velocity from Cartesian to spherical coordinates.

    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.

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    pv_in = numpy.array(pv, dtype=numpy.double, order="C", copy=False, subok=True)
    check_trailing_shape(pv_in, (2, 3), "pv")
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if pv_in[...,0,0].shape == tuple():
            pv_in = pv_in.reshape((1,) + pv_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), pv_in[...,0,0])
    theta_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    phi_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    r_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    td_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    pd_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)
    rd_out = numpy.empty(broadcast.shape + (), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [pv_in[...,0,0], theta_out, phi_out, r_out, td_out, pd_out, rd_out]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*1 + [['readwrite']]*6
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._pv2s(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(theta_out.shape) > 0 and theta_out.shape[0] == 1
        theta_out = theta_out.reshape(theta_out.shape[1:])
        assert len(phi_out.shape) > 0 and phi_out.shape[0] == 1
        phi_out = phi_out.reshape(phi_out.shape[1:])
        assert len(r_out.shape) > 0 and r_out.shape[0] == 1
        r_out = r_out.reshape(r_out.shape[1:])
        assert len(td_out.shape) > 0 and td_out.shape[0] == 1
        td_out = td_out.reshape(td_out.shape[1:])
        assert len(pd_out.shape) > 0 and pd_out.shape[0] == 1
        pd_out = pd_out.reshape(pd_out.shape[1:])
        assert len(rd_out.shape) > 0 and rd_out.shape[0] == 1
        rd_out = rd_out.reshape(rd_out.shape[1:])

    return theta_out, phi_out, r_out, td_out, pd_out, rd_out


def s2c(theta, phi):
    """
    Wrapper for ERFA function ``eraS2c``.

    Parameters
    ----------
    theta : double array
    phi : double array

    Returns
    -------
    c : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - -
     e r a S 2 c
    - - - - - - -

    Convert spherical coordinates to Cartesian.

    Given:
       theta    double       longitude angle (radians)
       phi      double       latitude angle (radians)

    Returned:
       c        double[3]    direction cosines

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    theta_in = numpy.array(theta, dtype=numpy.double, order="C", copy=False, subok=True)
    phi_in = numpy.array(phi, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if theta_in.shape == tuple():
            theta_in = theta_in.reshape((1,) + theta_in.shape)
        else:
            make_outputs_scalar = False
        if phi_in.shape == tuple():
            phi_in = phi_in.reshape((1,) + phi_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), theta_in, phi_in)
    c_out = numpy.empty(broadcast.shape + (3,), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [theta_in, phi_in, c_out[...,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*2 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._s2c(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(c_out.shape) > 0 and c_out.shape[0] == 1
        c_out = c_out.reshape(c_out.shape[1:])

    return c_out


def s2p(theta, phi, r):
    """
    Wrapper for ERFA function ``eraS2p``.

    Parameters
    ----------
    theta : double array
    phi : double array
    r : double array

    Returns
    -------
    p : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - -
     e r a S 2 p
    - - - - - - -

    Convert spherical polar coordinates to p-vector.

    Given:
       theta   double       longitude angle (radians)
       phi     double       latitude angle (radians)
       r       double       radial distance

    Returned:
       p       double[3]    Cartesian coordinates

    Called:
       eraS2c       spherical coordinates to unit vector
       eraSxp       multiply p-vector by scalar

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    theta_in = numpy.array(theta, dtype=numpy.double, order="C", copy=False, subok=True)
    phi_in = numpy.array(phi, dtype=numpy.double, order="C", copy=False, subok=True)
    r_in = numpy.array(r, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if theta_in.shape == tuple():
            theta_in = theta_in.reshape((1,) + theta_in.shape)
        else:
            make_outputs_scalar = False
        if phi_in.shape == tuple():
            phi_in = phi_in.reshape((1,) + phi_in.shape)
        else:
            make_outputs_scalar = False
        if r_in.shape == tuple():
            r_in = r_in.reshape((1,) + r_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), theta_in, phi_in, r_in)
    p_out = numpy.empty(broadcast.shape + (3,), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [theta_in, phi_in, r_in, p_out[...,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*3 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._s2p(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(p_out.shape) > 0 and p_out.shape[0] == 1
        p_out = p_out.reshape(p_out.shape[1:])

    return p_out


def s2pv(theta, phi, r, td, pd, rd):
    """
    Wrapper for ERFA function ``eraS2pv``.

    Parameters
    ----------
    theta : double array
    phi : double array
    r : double array
    td : double array
    pd : double array
    rd : double array

    Returns
    -------
    pv : double array

    Notes
    -----
    The ERFA documentation is below.

    - - - - - - - -
     e r a S 2 p v
    - - - - - - - -

    Convert position/velocity from spherical to Cartesian coordinates.

    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

    Copyright (C) 2013-2016, NumFOCUS Foundation.
    Derived, with permission, from the SOFA library.  See notes at end of file.

    """

    #Turn all inputs into arrays
    theta_in = numpy.array(theta, dtype=numpy.double, order="C", copy=False, subok=True)
    phi_in = numpy.array(phi, dtype=numpy.double, order="C", copy=False, subok=True)
    r_in = numpy.array(r, dtype=numpy.double, order="C", copy=False, subok=True)
    td_in = numpy.array(td, dtype=numpy.double, order="C", copy=False, subok=True)
    pd_in = numpy.array(pd, dtype=numpy.double, order="C", copy=False, subok=True)
    rd_in = numpy.array(rd, dtype=numpy.double, order="C", copy=False, subok=True)
    make_outputs_scalar = False
    if NUMPY_LT_1_8:
        # in numpy < 1.8, the iterator used below doesn't work with 0d/scalar arrays
        # so we replace all scalars with 1d arrays
        make_outputs_scalar = True
        if theta_in.shape == tuple():
            theta_in = theta_in.reshape((1,) + theta_in.shape)
        else:
            make_outputs_scalar = False
        if phi_in.shape == tuple():
            phi_in = phi_in.reshape((1,) + phi_in.shape)
        else:
            make_outputs_scalar = False
        if r_in.shape == tuple():
            r_in = r_in.reshape((1,) + r_in.shape)
        else:
            make_outputs_scalar = False
        if td_in.shape == tuple():
            td_in = td_in.reshape((1,) + td_in.shape)
        else:
            make_outputs_scalar = False
        if pd_in.shape == tuple():
            pd_in = pd_in.reshape((1,) + pd_in.shape)
        else:
            make_outputs_scalar = False
        if rd_in.shape == tuple():
            rd_in = rd_in.reshape((1,) + rd_in.shape)
        else:
            make_outputs_scalar = False

    #Create the output array, based on the broadcasted shape, adding the generated dimensions if needed
    broadcast = numpy.broadcast(numpy.int32(0.0), numpy.int32(0.0), theta_in, phi_in, r_in, td_in, pd_in, rd_in)
    pv_out = numpy.empty(broadcast.shape + (2, 3), dtype=numpy.double)

    #Create the iterator, broadcasting on all but the consumed dimensions
    arrs = [theta_in, phi_in, r_in, td_in, pd_in, rd_in, pv_out[...,0,0]]
    op_axes = [[-1]*(broadcast.nd-arr.ndim) + list(range(arr.ndim)) for arr in arrs]
    op_flags = [['readonly']]*6 + [['readwrite']]*1
    it = numpy.nditer(arrs, op_axes=op_axes, op_flags=op_flags)

    #Iterate
    stat_ok = _core._s2pv(it)
    #need to convert the outputs back to scalars if all the inputs were scalars but we made them 1d
    if make_outputs_scalar:
        assert len(pv_out.shape) > 0 and pv_out.shape[0] == 1
        pv_out = pv_out.reshape(pv_out.shape[1:])

    return pv_out

