Source code for naginterfaces

# -*- coding: utf-8 -*-
u"""
Package Summary
---------------
Python interfaces for the NAG Library Engine, which is the
software implementation of NAG's collection of several
hundred mathematical and statistical routines serving a
diverse range of application areas.

Subpackage Summary
------------------
Interfaces to the NAG Library are provided in the :mod:`~naginterfaces.library`
subpackage.

The ``base.utils`` submodule contains a number of core utilities for
working with the supplied Library interfaces. See the documentation
for the :mod:`~naginterfaces.base` subpackage for more information.

Some utilities for interacting with the NAG Kusari licence-management
system are in a :mod:`~naginterfaces.kusari` submodule.

Submodules must be imported separately:

>>> from naginterfaces.library import opt, roots

for instance, and module entities may be imported using, for example

>>> from naginterfaces.base.utils import NagException

For brevity, support entities appear with unqualified names in the
documentation for the package. For example, the ``base.utils.Handle``
data type is referenced merely as ``Handle``. In code these entities must
still be imported from their host module using any of the regular python
idioms, such as

>>> from naginterfaces.base.utils import Handle

Attributes
----------
ENGINE_LIBDIR : str
    The absolute path to the underlying directory housing the NAG library and
    its dependent binaries.

Algorithmic Contents
--------------------
The package supplies all algorithmic functionality from the NAG Engine except:

- there is only one ‘implementation details’ function supplied in the `info`
  (a00) Chapter;

- the `stat` (g01) line-print functions ``plot_stem_leaf`` and
  ``plot_box_whisker`` are deemed redundant in Python;

- the `file` (x04) and `time` (x05) Chapters are not required so are absent.

For detailed documentation on the algorithms provided by this package
refer to the NAG Library document

https://www.nag.com/numeric/nl/nagdoc_28.5/flhtml/frontmatter/manconts.html

LAPACK functions are supplied as a single variant within a given installation
of the package. An installation of the vendor math library version of
`naginterfaces` only supplies the vendor-enabled variants of LAPACK functions,
and conversely a self-contained `naginterfaces` only supplies the NAG variants
of LAPACK functions.

Functions or submodules that are scheduled for withdrawal at some future
release will issue a warning, class ``NagWithdrawalWarning``, when called or
imported, respectively. The documentation for a deprecated object also provides
a note of the pending withdrawal. Both the warning and the documentation give
advice on how to make a replacement.

Interface Features
------------------
In what follows we describe the calling conventions used by functions in
the package. Because Python is dynamically typed there is naturally a great
amount of flexibility in how the interfaces might be used. This makes an
accurate description of the behaviour and allowed usage of the interfaces be
quite extensive. Nevertheless, the interfaces are designed so that common-sense
usage expectations should in most cases be met.

The package's documentation uses a type-classification scheme that differs
slightly from Python terminology. The discussion of types is divided into:
‘Intrinsic Types’ for built-in scalar numeric types, Booleans and also strings;
and ‘Non-intrinsic Types’ for NAG-defined classes required for certain
arguments. We use the term ‘container’ for sequence types (``list``,
``numpy.ndarray``, ...) excluding strings, including ``dict``. ‘Array’ means
any non-``dict`` container, and ‘scalar’ is used to encompass any non-container
type.

Output data is generally always returned on the left-hand side of function
calls, apart from in those special cases (primarily, communication—see
below) when it is modified in place on the right-hand side of the call.

When a function returns a ``tuple`` (i.e., when it has more than one
return argument on the left-hand side), the returned entity is always
a ``collections.namedtuple`` (with a class name reflecting the
associated NAG function, for example ``Dim1FinWellReturnData``). The
field names in the ``namedtuple`` correspond to the names of the
output arguments.

Optional keyword dummy arguments are used whenever a reasonable default value
is known, or whenever an algorithm has modes of operation that can be triggered
by the absence or presence of supplied data in the call.

Some routines allow certain output arguments to be suppressed or declined. In
these cases the respective output entity is present in the return data from the
routine, but is set to ``None``.

Intrinsic Types
~~~~~~~~~~~~~~~
For maximum flexibility the interfaces in the package allow intrinsic-typed
arguments to be typed using one of a number of synonyms or equivalent types.

Integer data is always permitted to be supplied as the native ``int``.

In a number of cases, floating-point data may be supplied as an integer. Such
values will be promoted internally to floats. Note that some very large integer
values are not exactly representable as floating-point values. The NAG
wrappers make no diagnosis of this, so it is the responsibility of the caller
to be aware of this possibility.

For brevity of documentation the individual function signature annotations in
the package refer to numeric types by category, with the following meanings:

`str`
  Native ``bytes`` or ``str``, NumPy types ``numpy.bytes_`` or ``numpy.str_``.

  Input string data is treated in a case-insensitive manner by the NAG Library;
  that is, the following are considered equivalent ::

    nag_fun('Spam', ...)
    nag_fun('spaM', ...)

  Therefore, in documented constraints for string input it is implicit that
  the constraint is independent of the string's case.

`complex64`
  NumPy type ``numpy.complex64``.

`complex`
  Native ``complex``, NumPy type ``numpy.complex128``.

`float32`
  Native ``int``;

  ``ctypes.c_float``;

  NumPy types ``numpy.float32``, ``numpy.int32`` or ``numpy.int64``.

`float`
  Native ``float`` or ``int``;

  ``ctypes.c_double``;

  NumPy types ``numpy.float64``, ``numpy.int32`` or ``numpy.int64``.

`int`
  Native ``int``;

  If on Windows the ``ctypes`` types ``ctypes.c_long`` or
  ``ctypes.c_longlong``, if not on Windows the ``ctypes`` types
  ``ctypes.c_int`` or ``ctypes.c_long``;

  NumPy types ``numpy.int32`` or ``numpy.int64``.

`bool`
  Native ``bool``, NumPy ``np.bool_``.

Some of the intrinsic types have additional constraints enforced on them as
follows:

`str`
  Must be ASCII data. The package will raise ``NagValueError`` if this is
  not the case. Some `str` arguments have an expected string length.
  Data shorter than such a specified length will be blank padded on
  the right before being passed to the NAG Engine. Longer data will be
  truncated.

`int`
  Must be in range for the underlying NAG Engine integer type. The
  package will raise ``NagOverflowError`` if an out-of-range `int` is
  supplied. The size of the NAG Engine integer is available for reference by
  calling the implementation-details function from the ``info``
  submodule. Additionally, the ``base.utils`` submodule supplies two
  classes—:class:`~naginterfaces.base.utils.EngineIntNumPyType` and
  :class:`~naginterfaces.base.utils.EngineIntCType`—that can be used as
  integer data types to ensure compatibility with the NAG Engine integer.

The package will raise ``NagTypeError`` if an incorrectly-typed argument is
supplied.

Non-intrinsic Types
~~~~~~~~~~~~~~~~~~~
Instances of a ``Handle`` class (which is supplied by the ``base.utils``
submodule) must be used for arguments in some routines. Generally an instance
will be constructed by an initialization function for the suite of which the
handle is a part.

In some NAG functions a ‘null Handle’ is permitted to be supplied on input,
or may be returned on output. By ‘null Handle’ we mean a ``Handle`` instance
having ``value`` attribute set to ``None``. On input, a freshly-constructed
``Handle`` instance will suffice for such an argument.

It is prohibited to use the Python ``copy`` module to copy ``Handle``
instances. The package will raise ``NagAttributeError`` if this is attempted.

Input/Output
~~~~~~~~~~~~
The ``base.utils`` submodule also supplies a class called
:class:`~naginterfaces.base.utils.FileObjManager` that must be used with some
NAG functions when I/O is being performed. Instances of the class help
translate between Python file objects and NAG Engine I/O units.

Scalars
~~~~~~~
Scalars are always returned on the left-hand side of calls. This also applies
in the signatures of callback functions.

Scalars returned from NAG functions use native Python types when one exists,
else the NumPy type is used according to the type scheme above.

Arrays
~~~~~~
Arrays not of ``Handle`` data can be passed as (subclasses of)
``numpy.ndarray``.

Some arguments are permitted to be any ‘array-like’ container. The
documentation for the ``numpy.array`` function defines this term in detail, but
for simple purposes an ‘array-like’ container is an instance of
``numpy.ndarray`` or a (nested) sequence (for example, ``[[42, 43], [44, 45]]``
used to represent a 2 by 2 matrix). Additionally, NAG functions accept scalars
being supplied where rank-1 arrays are expected. In such a case the scalar
is promoted internally to a length-1 one-dimensional array. In the NAG
documentation ‘array-like’ should be understood to include this special case.

When a NAG function will modify array data in place (e.g., in communication
contexts, see below) ``numpy.ndarray`` (or subclass) is the only allowed
container. Furthermore, automatic promotion of integer data to floating point
will not be made for these arrays because doing so requires an array copy;
that is, floating-point arrays that are to be modified in place must use
a compatible floating-point data type.

The package will raise ``NagTypeError`` if an illegal container is supplied for
an argument.

When a dummy argument has a documented expected shape, the corresponding actual
argument must match this shape precisely. Oversized arrays are not
permitted. The package will raise ``NagShapeError`` if an actual argument has
an incorrect shape. The shape match restriction is relaxed slightly for
zero-sized dummy arrays (having expected extent zero in one or more dimension),
for which any zero-sized actual array argument is permitted irrespective of its
precise shape.

On occasion an array element may need to be accessed by a NAG wrapper before a
shape check can be performed for the array. In these situations an index
validation will be made for the element. The package will raise
``NagIndexError`` when such a requested index is out of range.

The contents of containers of `str` or `int` data are subject to the same
constraints as the corresponding scalars; i.e., being ASCII, or not overflowing
the NAG Engine integer, respectively. The checking is omitted if the data is
output only.

All multi-dimensional array arguments supplied on the right-hand side to a NAG
function or returned from user-supplied callback functions must be contiguous
in either the C or Fortran sense, or both. The package will raise
``NagTypeError`` if this is not the case. Most arrays will usually satisfy this
requirement, but care must be taken when slicing ``numpy.ndarray`` data: for
example, a ‘reversed’ two-dimensional array becomes discontiguous:

>>> import numpy as np
>>> is_discontig = lambda a: not (
...     a.flags.c_contiguous or a.flags.f_contiguous
... )
>>> z = np.array([[42, 43], [44, 45]])
>>> z_r = z[::-1, ::-1]
>>> is_discontig(z_r)
True

The NumPy utilities ``numpy.ascontiguousarray`` and ``numpy.asfortranarray``
can be used to convert to contiguous arrays in the desired sense:

>>> z_r_c = np.ascontiguousarray(z_r)
>>> is_discontig(z_r_c)
False
>>> z_r_f = np.asfortranarray(z_r)
>>> is_discontig(z_r_f)
False

If more than one multi-dimensional argument is to be supplied on the right-hand
side of a function, these arguments must use a mutually consistent storage
order in memory. The package will raise ``NagTypeError`` if this is not the
case.

NumPy treats ‘spiked’ arrays (that is, with unit extent in all but one
dimension, or with total size 1) as being contiguous in both the Fortran and C
senses. If all multi-dimensional input arguments are spiked and hence dually
contiguous in this manner, and there are no callbacks that return
multi-dimensional arrays in the interface of the NAG function, then Fortran
storage is assumed for efficiency in the NAG Engine.

In some interfaces an output array is semantically an updated copy of an input
array: for example, when factorizing a matrix. This is usually apparent in the
API description for the interface, where the input and output arrays will have
the same name.

The return type for array data on the left-hand side of function calls is
always as ``numpy.ndarray`` with a NumPy-type ``dtype``. When such data is an
updated copy of an input argument, subclasses of ``numpy.ndarray`` will be
preserved in the output.

When an array is returned on the left-hand side of a call it will use the
mutual storage order inferred from input arrays in the call, or NumPy's default
storage order (C contiguous) if there were no multi-dimensional input arrays.

A returned array that has an input equivalent will use the same ``dtype`` as
that input equivalent. Otherwise the ``dtype`` will be the NumPy type for the
array's data-type category according to the type scheme above. Output-only
`str` arrays use ``numpy.str_`` ``dtype``, and output-only `int` arrays use the
NAG Engine integer data type.

Arguments representing index values (e.g. pivot indices defining a permutation
matrix) always contain or are expected to contain (if supplied on input)
elements relating to the mathematical entity that is being indexed,
as base-1 (not base-0) values.

Some error messages in exceptions raised by the package mention ‘dimensions’
of arrays, which should also be understood to be indexed from 1.

Certain routines describe ‘increment‘ parameters for arrays (e.g., a parameter
called ``incx``). These are legacy features of the underlying linear algebra,
useful for languages which lack native slicing of arrays. In this package such
increments are suppressed from the user interface and set internally to 1.

Communication
~~~~~~~~~~~~~
Some NAG routines or suites of routines use arrays for self or suite
communication. In argument lists in `naginterfaces` these arrays are merged
together into a single ``dict``, usually called ``comm``.

The keys of a communication ``dict`` are the names of the arrays that were
merged to form the ``dict``. In cases where part of a communication array is
documented as having some direct significance, the original array can be
referenced using the corresponding key in the ``dict``.

For a suite having a distinct initialization function the communication
``dict`` is returned on the initializer's left-hand side.

Functions that modify a communication ``dict`` do so in place on the right-hand
side of the call.

The package will raise ``NagTypeError`` if a communication ``dict`` dummy
argument receives an actual argument of a different type. It will raise
``NagKeyError`` if the ``dict`` is not a valid communication structure for the
context in which it is being used (for example, if it is being used with the
wrong suite of routines).

Individual array arguments used in communication contexts are always modified
in place on the right-hand side of calls. This includes in calls to
reverse-communication functions. Arguments of the special ``Handle`` data type
are also modified in this manner.

Consequently, communication arguments must be mutable, and in particular must
be named entities (and not literals). It is the responsibility of the caller to
ensure this: it is not possible for the NAG wrappers to detect when a literal
or an expression has been supplied.

When a distinct initializer for the function does not exist communication
arguments must be pre-declared before calling the NAG function. In
particular a communication ``dict`` must be declared as an empty ``dict``
(i.e., ``comm = {}``, say) which will signal to the NAG function that an
initialization call (as opposed to a continuation call) is being made.

After initialization and as long as communication between NAG functions is
still required, unless you are instructed otherwise you must not modify
communication arguments directly in your own code, only by calls to associated
NAG functions.

Arbitrary communication data can be passed to a callback function through its
argument list if so desired via an optional ``data`` argument. When this
facility is not needed the ``data`` argument can be omitted from the definition
of the callback. The ``None``-ness of the corresponding ``data`` argument
supplied in the call to the NAG function is used to determine whether
to invoke all callback functions with ``data`` supplied, or to omit this
argument from all callback invocations. That is, in a call like ::

  nag_fun(callback1, callback2, data=something)

in which ``callback1`` wishes to use the none-``None`` communication data
``something`` but ``callback2`` does not need to, both ``callback1`` and
``callback2`` will be called by the NAG wrapper with ``something`` supplied as
a ``data`` dummy argument. Both callbacks must therefore be defined to have
such a dummy argument.

The example
:func:`naginterfaces.library.examples.tsa.kalman_unscented_state_ex.main`
demonstrates passing user-defined communication data to callback functions.

.. _cb_iface_feats:

User-supplied Function Arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

It is permitted to raise exceptions in callback functions if desired.

The package uses the following general calling conventions for user-supplied
callbacks:

- input scalars use native Python types when one exists, else the NumPy type is
  used according to the type scheme above;

- output scalars are checked using the same rules as input scalars in wrappers
  (e.g., strings must be ASCII);

- array input data is always supplied as ``numpy.ndarray`` with a NumPy-type
  ``dtype``;

- array integer data uses the same data type as the NAG Engine integer, and
  for efficiency output values are not individually checked for overflow: the
  callback is responsible for ensuring that the elements of output integer
  arrays are in range;

- likewise, string data is passed as byte strings for efficiency;

- output arrays returned from callback functions can be as any array-like
  container. Documented requirements for expected data type, expected shape,
  etc., still apply. The storage order used by these arrays must be the same as
  the overall storage order used by the enclosing NAG wrapper.

  When only spiked arrays have been supplied to the enclosing NAG function
  (see `Arrays`_ above) then you may specify the storage order to use for
  multi-dimensional arrays returned by callbacks via the outer
  ``spiked_sorder`` argument, which defaults to requesting C contiguous
  storage.

Some NAG Python functions have ``NagCallbackTerminateWarning`` warning exits.
The callbacks associated with these exits permit you to request early
termination of the algorithm if you raise the special exception
``UserCallbackTerminate``. If you do this then the NAG Python function will
interpret that exception in such a way that the appropriate corresponding
``NagCallbackTerminateWarning`` is raised for you after the NAG Engine has
exited. If you use the Python ``warnings`` module to promote the warning to an
exception then you can retrieve your original exception(s) via the exception's
``cb_excs`` attribute.

The example
:func:`naginterfaces.library.examples.opt.handle_solve_dfno_ex.main`
demonstrates terminating early in a callback function.

Initialization of Input Data
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Functions in this package may document that certain arguments are not
referenced in some situations: for example, ‘under a cold start
`istate` is not referenced’. Being referenced or not referenced is meant
in the sense of the underlying algorithm in the NAG Library Engine.
There are circumstances where the NAG Python wrapper may still copy the
data, or type check it (if the type is `str` or `int`, say).

For arguments that are documented as sometimes not being referenced by
the NAG Library Engine, we recommend always initializing the data to a
valid Python value (such as `0` for `int` data, or blank for `str`).

Optional Algorithmic Parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Some NAG functions allow additional configurability via optional algorithmic
parameters, to control aspects of the algorithm, methodology used, logic or
output. Such a function will be associated with one or more option-handling
utilities, which will be listed in the preamble of the function's
documentation. These option-handling utilities can be used to change or query
the values of the main solver's optional parameters. The parameters are usually
communicated between the utilities and the main solver through a communication
``dict`` or ``Handle`` argument. Each optional parameter has an associated
default value, so option setting is only necessary when a default is not
suitable for your particular problem. The list of optional parameters
recognized by a given solver is supplied in the solver's documentation.

Please consult the individual documentation for your required option-handling
utilities for usage information on interacting with optional parameters; some
utilities allow optional parameters to be specified as a single string
``'option_name = option_value'`` while some may have distinct utilities for
setting only option names of a certain numeric type.

The example
:func:`naginterfaces.library.examples.opt.handle_solve_dfls_ex.main`
demonstrates setting optional parameters in a problem handle for solving an
optimization problem.

Error Handling
~~~~~~~~~~~~~~
Error and warning cases in the package are managed using subclasses of the
core Python ``Exception`` and ``Warning`` classes. See the documentation of
the :mod:`base.utils <naginterfaces.base.utils>` submodule for more
information---specifically the classes :class:`~base.utils.NagException` and
:class:`~base.utils.NagWarning`, and their descendants and ancestors.

Documentation Structure
-----------------------
Each individual wrapper contains a docstring showing its API description.

The general structure of a function docstring is ::

  (Short description.)

  (Link to the document for the function in the NAG Library Manual.)

  Parameters
  ----------
  ...

  Returns
  -------
  ...

  Other Parameters
  ----------------
  ...

  Raises
  ------
  ...

  Warns
  -----
  ...

  Notes
  -----
  ...

  References
  ----------
  ...

  See Also
  --------
  ...

Each of the subsections is optional.

Within the ``Parameters`` and ``Returns`` sections, arguments are annotated in
the following manner (square brackets denote text that may not be present in
all circumstances, and ellipses denote a continued line for this document).

For data ::

  arg-name : type-category[, communication object] ...
             ... [, [container-restriction, ] shape shape-tuple] ...
             ... [, optional][, modified in place]

with the type and container categories as covered above.

For procedures ::

  proc-name : callable rtn-data = proc-name(proc-arg-name-list, ...
                                        ... proc-kwarg-name-list)
      (Short description.)

      Parameters
          arg-name : annotation
              ...

          ...

      Returns
          rtn-name : annotation
              ...

          ...

Annotation strings for wrapper arguments and callback arguments are identical
apart from the ‘modification’ substring: for wrapper arguments ``modified in
place`` obviously denotes that the argument will have been modified on exit
from the wrapper; in user-supplied procedures the term used is ``modifiable in
place`` to indicate when changes must be made directly to the dummy entity from
the argument list in order for those changes to have any effect once the
procedure exits.

When a function uses optional algorithmic parameters, these are documented in
an ``Other Parameters`` section using the following format ::

  opt-name : type-category
     [Default[ = def-value]]

     Description.

``opt-name`` is documented as a string. The ``type-category`` may be any of the
standard categories as covered previously, or it could be ``valueless``. The
latter indicates that the ``opt-name`` itself will act as a toggle. An example
of this is ``'Defaults'``, used by some functions to reset all optional
parameters to their initial default values.

The default value for an optional parameter, which will be used by the solver
unless you have explicitly set a new value using one of the option-handling
utilities, is given in the ``Default`` line if it is meaningful to do so.
When ``def-value`` is omitted this is because the optional parameter is
valueless but the control aspect supplied by it is the default for the solver.

The symbol :math:`\\epsilon` (epsilon) in an ``Other Parameters`` section
denotes the machine precision (see
:meth:`~naginterfaces.library.machine.precision`).

The ``Raises`` (respectively ``Warns``) section in a function's docstring lists
error (resp. warning) cases (if any) that may be raised. The entries are
limited specifically to algorithmic cases that the routine may diagnose. No
attempt is made to document every possible Python exception that could
occur. Each list is sorted by the corresponding error number or expression as
used by the Library. In some text for exit cases a ‘<value>’ placeholder
appears, which is used to indicate text that will be filled in at runtime by
the NAG wrapper.

``Notes`` gives details of any special considerations that may need to be
made if porting Python calls over to calls to C functions in the NAG Library,
and then covers expanded algorithmic details for the routine.

``References`` lists any external publications that complement the text
in the NAG document.

The ``See Also`` section is used to cross reference to example files that
call the function.

Performance Tips
----------------
Setting up array data as a (homogenous) ``numpy.ndarray`` (or a subclass
thereof) before calling a NAG function may be slightly more efficient than
supplying an array-like container instead and having the NAG function make
the conversion. Any performance loss when using the latter would be especially
acute in a callback function, so the recommendation there would be to always
return array data as an instance of ``numpy.ndarray``.

For ``numpy.ndarray`` input where the NAG wrapper expects floating-point
values, note that supplying such data as integer values requires a copy to be
made of the array. Therefore supplying the data with a compatible
floating-point ``dtype`` from the offset will be more efficient.

The NAG Engine operates in such a way that supplying multi-dimensional data
in Fortran contiguous (column-major) storage order will always be more
efficient than using C contiguous data. The storage order of a
``numpy.ndarray`` instance can be configured using the ``order`` argument in
many of the NumPy array-creation routines. For dually contiguous spiked
arrays (see the `Arrays`_ section above) setting the optional
argument ``spiked_sorder`` to ``'F'`` when this is present in a NAG routine's
interface (see the `User-supplied Function Arguments`_ section above) requests
that Fortran storage order is to be used.

It may be more efficient to supply string data as byte strings, although this
is likely to give only small gains since the data must still be checked for
being ASCII.

Likewise, I/O from NAG routines should perform better through file objects
opened in binary mode.

If convenient then supplying integer data using one of the NAG-provided
``EngineInt*Type`` data-type classes
(:class:`~naginterfaces.base.utils.EngineIntNumPyType` or
:class:`~naginterfaces.base.utils.EngineIntCType`) should prove more efficient,
particularly when used instead of the unlimited-precision ``int`` from
Python 3.

Thread Safety Considerations
----------------------------
The underlying NAG Engine is thread safe when accessed from this package
unless explicitly stated otherwise in an entity's documentation.

In routines which take ``Handle`` arguments, the internal data
structures referenced by the handles may be freely read from and
written to by the NAG Engine. As such, when calling a routine that has
a handle argument in a threaded region each thread must have its own
(deep) copy of the handle, either initialized directly on the thread
or explicitly copied via a call to a relevant Library routine where
one exists.

In the context of the purely-Python parts of the package, special care must be
taken if using the ``data`` mechanism to pass communication data to callback
functions---the ``data`` object you supply to the `naginterfaces` function you
call is shared by all instances of your callback function.

Porting to other NAG Libraries
------------------------------
If you are prototyping in Python but developing production compiled code
that uses the NAG Library there is usually a simple
correspondence between a given Python function in this package and its
compiled alternative. The correspondence is by the Python routine's
unqualified name.

For example, the unqualified name for optimizer
:meth:`~naginterfaces.library.opt.nlp1_solve` is ``nlp1_solve``.
Performing a keyword search for ``nlp1_solve`` in the
documentation for the secondary NAG product you are
using should locate the corresponding routine(s).

In case of problems using the unqualified name, a secondary correspondence
to try is by the unique five-letter short
routine name that is given in the introductory section of the Python
function's documentation.

For example, the short name for optimizer
:meth:`~naginterfaces.library.opt.nlp1_solve` is seen from the
routine's Python documentation to be ``e04uc``. Performing a keyword search for
``e04uc`` in the documentation for the secondary NAG product you are
using will locate the corresponding routine(s).

The NAG Technical Support Service will gladly assist in case of difficulties.
See also section :ref:`Technical Support <support>`.

NAG C Interfaces
~~~~~~~~~~~~~~~~
In some cases there is no equivalent NAG C interface for a given NAG
Python function. When an equivalent does exist there are also cases
where the NAG C function uses a different algorithmic base.
The Python function's documentation will contain a note whenever these
situations occur.
The corresponding algorithm that uses the same base can still be accessed from
C via the NAG FL Interface and associated C header files.

NAG Fortran Interfaces
~~~~~~~~~~~~~~~~~~~~~~
Apart from the exceptions given in the `Algorithmic Contents`_ section above,
all NAG Python functions have equivalents in the NAG FL Interfaces,
each of which uses the same algorithmic base.

Migrating from Earlier Releases of the NAG Library `for Python`
---------------------------------------------------------------
The NAG Library `for Python` at Mark 26.0 and earlier supplied a package
called `nag4py`, which was a set of Python interfaces to the NAG C Library.

For algorithmic functionality and usability, `nag4py` is superseded by the
`naginterfaces` package.

The canonical algorithmic base supplied by `naginterfaces` significantly
overlaps the NAG C Library in terms of numerics, thus in many cases when
moving from `nag4py` to `naginterfaces` there should be a clear
function-to-function upgrade path.

However, the interfaces to matching algorithms as supplied by `naginterfaces`
compared to `nag4py` are likely to be noticeably different.

The best general advice on how to successfully migrate to `naginterfaces` is to
identify the `naginterfaces` function (or functions) semantically most close to
the functions you are using from `nag4py`, then carefully reconstruct the call
sequence.

Given a ‘short’ `nag4py` function name (using the NAG C Library form, such
as ``z99zzc``), the corresponding `naginterfaces` function can be located by
searching for the initial five-letter prefix (``z99zz`` in this case) in the
`naginterfaces` documentation.

No general guarantee can be given about equal performance or bitwise
reproducibility of results across the two packages.

The NAG Technical Support Service will gladly assist in case of difficulties.
See also section :ref:`Technical Support <support>`.

Numbering Scheme
----------------
This package uses a modification of the well-known Semantic Versioning scheme,
extended to a sequence of four digits (``X.W.Y.Z``) instead of the usual three.

The initial pair—``X.W``—denotes the algorithmic functionality
available from the underlying NAG Library. With the exception of
any listed unsupported Python interfaces described by the `naginterfaces`
subpackages, all routines from Mark X.W of the NAG Library are available.

The penultimate and final digits—``Y`` and ``Z``—have the same meaning
as with Semantic Versioning; that is, within the X.W release series ``Y``
tracks backwards-compatible functionality additions and ``Z`` tracks
backwards-compatible bug fixes.
"""

# NAG Copyright 2017-2021.

import doctest as _doctest
import os as _os
import platform as _platform
import struct as _struct
import sys as _sys
import traceback as _traceback

_THE_SYSTEM = _platform.system()

ENGINE_LIBDIR = _os.path.join(
    _os.path.abspath(_os.path.dirname(__file__)),
    '_'.join([
        'naglib',
        ('Windows' if _THE_SYSTEM.startswith('CYGWIN') else _THE_SYSTEM) +
        ('_32' if _struct.calcsize('P') == 4 else ''),
    ])
)

with open(
    _os.path.join(
        _os.path.dirname(__file__),
        'version.txt'
    ),
    'r',
    encoding='ascii',
) as _fo:
    __version__ = _fo.readline().rstrip('\n')

[docs]def quick_check(): """ Sanity check for the package. Checks availability of a licence, and correct loading and basic operation of the underlying compiled libraries. Returns zero on success and non-zero on failure. """ line_prefix = 'QUICK CHECK: ' print(line_prefix + 'checking availability of a licence:') try: from .kusari import _has_lic, _main # pylint:disable=bad-option-value,import-outside-toplevel except: # pylint: disable=bare-except _traceback.print_exc() _sys.stderr.write(line_prefix + 'FAILED\n') return 1 _main() if not _has_lic(): _sys.stderr.write(line_prefix + 'FAILED\n') return 1 print(line_prefix + 'checking retrieval of implementation details') print(' using the info.impl_details example script:') from .library.examples.info import impl_details_ex # pylint:disable=bad-option-value,import-outside-toplevel n_fails = _doctest.testmod( impl_details_ex, verbose=True, report=False, optionflags=_doctest.ELLIPSIS, ).failed if n_fails: # pragma: no cover _sys.stderr.write(line_prefix + 'FAILED\n') return n_fails print(line_prefix + 'solving a small system of linear equations') print(' using the lapacklin.dgesv example script:') from .library.examples.lapacklin import dgesv_ex # pylint:disable=bad-option-value,import-outside-toplevel n_fails = _doctest.testmod(dgesv_ex, verbose=True, report=False).failed if n_fails: # pragma: no cover _sys.stderr.write(line_prefix + 'FAILED\n') return n_fails print(line_prefix + 'all ok') return 0