diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..682e46b2c5b3cd9bb31fdfd033431665bd57dba6 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_array_api.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_array_api.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7c3a40b3a6ae5bf2047e6086dd6bf283a7aecb71 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_array_api.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_array_api_compat_vendor.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_array_api_compat_vendor.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d7532016891f0c51fb9e7fe20ea00feeaa400d77 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_array_api_compat_vendor.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_array_api_docs_tables.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_array_api_docs_tables.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9477266b03dc881d128b339f814bc4189eb0faf4 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_array_api_docs_tables.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_array_api_no_0d.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_array_api_no_0d.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08d3d2f84a90b1895565cac4096e27411c439275 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_array_api_no_0d.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_array_api_override.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_array_api_override.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6643f51465969b9279689f2751055a7e8f9de3ec Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_array_api_override.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_bunch.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_bunch.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1ca48d91850cbdaaf43401772311629007867ef5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_bunch.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_ccallback.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_ccallback.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac5cbaa1e2bc7e26989490e77d63ff610be1a57f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_ccallback.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_disjoint_set.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_disjoint_set.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f89238a0d7a856d99e47939e4503401ace0f1cec Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_disjoint_set.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_docscrape.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_docscrape.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..60830d70c8c458bf076340b2555ea19652fd469c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_docscrape.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_elementwise_iterative_method.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_elementwise_iterative_method.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..89daca9f6c74964e76a97222dd59ff5df11f6d56 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_elementwise_iterative_method.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_gcutils.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_gcutils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e64a6d147fb23ad5e3686e665edb7f10adb3040 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_gcutils.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_pep440.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_pep440.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c637c15d13dfed404822024a38a2786a75b0ad84 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_pep440.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_public_api.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_public_api.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c258a98e650eea71e2b837eb5f54c1b9969f59dd Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_public_api.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_sparse.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_sparse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..24ee1ce3a36a10e9a9b5877908f5e205bb2d341d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_sparse.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_testutils.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_testutils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0f7637cd94bad4a40e7d0889cc148cb0f1ae46b8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_testutils.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_tmpdirs.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_tmpdirs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e3551fd4a0e185668a3c6c5a861483dff26d0c0a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_tmpdirs.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_util.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_util.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5566e4de98e87df42ed672ee1dd197eb5c8b1e5f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/_util.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/deprecation.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/deprecation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..54fb83cd2d3068812efa6c1f97109305f0414dc0 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/deprecation.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/doccer.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/doccer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6d0b0174da0e8fcb685aa626addc79ee8c866116 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/doccer.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/uarray.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/uarray.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..855572cc5b56eb298f7e8cb3e845232f60eb05dc Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/__pycache__/uarray.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/_uarray/LICENSE b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/_uarray/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..5f2b90a026aaecbdc090b3d3234954ab29fce8ae --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/_uarray/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2018, Quansight-Labs +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/_uarray/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/_uarray/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..91afdcedb180599a41758cdd8c03416cf6c20d76 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/_uarray/__init__.py @@ -0,0 +1,116 @@ +""" +.. note: + If you are looking for overrides for NumPy-specific methods, see the + documentation for :obj:`unumpy`. This page explains how to write + back-ends and multimethods. + +``uarray`` is built around a back-end protocol, and overridable multimethods. +It is necessary to define multimethods for back-ends to be able to override them. +See the documentation of :obj:`generate_multimethod` on how to write multimethods. + + + +Let's start with the simplest: + +``__ua_domain__`` defines the back-end *domain*. The domain consists of period- +separated string consisting of the modules you extend plus the submodule. For +example, if a submodule ``module2.submodule`` extends ``module1`` +(i.e., it exposes dispatchables marked as types available in ``module1``), +then the domain string should be ``"module1.module2.submodule"``. + + +For the purpose of this demonstration, we'll be creating an object and setting +its attributes directly. However, note that you can use a module or your own type +as a backend as well. + +>>> class Backend: pass +>>> be = Backend() +>>> be.__ua_domain__ = "ua_examples" + +It might be useful at this point to sidetrack to the documentation of +:obj:`generate_multimethod` to find out how to generate a multimethod +overridable by :obj:`uarray`. Needless to say, writing a backend and +creating multimethods are mostly orthogonal activities, and knowing +one doesn't necessarily require knowledge of the other, although it +is certainly helpful. We expect core API designers/specifiers to write the +multimethods, and implementors to override them. But, as is often the case, +similar people write both. + +Without further ado, here's an example multimethod: + +>>> import uarray as ua +>>> from uarray import Dispatchable +>>> def override_me(a, b): +... return Dispatchable(a, int), +>>> def override_replacer(args, kwargs, dispatchables): +... return (dispatchables[0], args[1]), {} +>>> overridden_me = ua.generate_multimethod( +... override_me, override_replacer, "ua_examples" +... ) + +Next comes the part about overriding the multimethod. This requires +the ``__ua_function__`` protocol, and the ``__ua_convert__`` +protocol. The ``__ua_function__`` protocol has the signature +``(method, args, kwargs)`` where ``method`` is the passed +multimethod, ``args``/``kwargs`` specify the arguments and ``dispatchables`` +is the list of converted dispatchables passed in. + +>>> def __ua_function__(method, args, kwargs): +... return method.__name__, args, kwargs +>>> be.__ua_function__ = __ua_function__ + +The other protocol of interest is the ``__ua_convert__`` protocol. It has the +signature ``(dispatchables, coerce)``. When ``coerce`` is ``False``, conversion +between the formats should ideally be an ``O(1)`` operation, but it means that +no memory copying should be involved, only views of the existing data. + +>>> def __ua_convert__(dispatchables, coerce): +... for d in dispatchables: +... if d.type is int: +... if coerce and d.coercible: +... yield str(d.value) +... else: +... yield d.value +>>> be.__ua_convert__ = __ua_convert__ + +Now that we have defined the backend, the next thing to do is to call the multimethod. + +>>> with ua.set_backend(be): +... overridden_me(1, "2") +('override_me', (1, '2'), {}) + +Note that the marked type has no effect on the actual type of the passed object. +We can also coerce the type of the input. + +>>> with ua.set_backend(be, coerce=True): +... overridden_me(1, "2") +... overridden_me(1.0, "2") +('override_me', ('1', '2'), {}) +('override_me', ('1.0', '2'), {}) + +Another feature is that if you remove ``__ua_convert__``, the arguments are not +converted at all and it's up to the backend to handle that. + +>>> del be.__ua_convert__ +>>> with ua.set_backend(be): +... overridden_me(1, "2") +('override_me', (1, '2'), {}) + +You also have the option to return ``NotImplemented``, in which case processing moves on +to the next back-end, which in this case, doesn't exist. The same applies to +``__ua_convert__``. + +>>> be.__ua_function__ = lambda *a, **kw: NotImplemented +>>> with ua.set_backend(be): +... overridden_me(1, "2") +Traceback (most recent call last): + ... +uarray.BackendNotImplementedError: ... + +The last possibility is if we don't have ``__ua_convert__``, in which case the job is +left up to ``__ua_function__``, but putting things back into arrays after conversion +will not be possible. +""" + +from ._backend import * +__version__ = '0.8.8.dev0+aa94c5a4.scipy' diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/_uarray/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/_uarray/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a86d3b636a6db4534e9684373cfae3a97247b7f8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/_uarray/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/_uarray/__pycache__/_backend.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/_uarray/__pycache__/_backend.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f23e6e17f3d56328cbfc45f0b49b4f2fa5ab800b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/_uarray/__pycache__/_backend.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/_uarray/_backend.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/_uarray/_backend.py new file mode 100644 index 0000000000000000000000000000000000000000..87ea71965761ca6916485828ee23d3402bfb1b7d --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/_uarray/_backend.py @@ -0,0 +1,707 @@ +import typing +import types +import inspect +import functools +from . import _uarray +import copyreg +import pickle +import contextlib +import threading + +from ._uarray import ( # type: ignore + BackendNotImplementedError, + _Function, + _SkipBackendContext, + _SetBackendContext, + _BackendState, +) + +__all__ = [ + "set_backend", + "set_global_backend", + "skip_backend", + "register_backend", + "determine_backend", + "determine_backend_multi", + "clear_backends", + "create_multimethod", + "generate_multimethod", + "_Function", + "BackendNotImplementedError", + "Dispatchable", + "wrap_single_convertor", + "wrap_single_convertor_instance", + "all_of_type", + "mark_as", + "set_state", + "get_state", + "reset_state", + "_BackendState", + "_SkipBackendContext", + "_SetBackendContext", +] + +ArgumentExtractorType = typing.Callable[..., tuple["Dispatchable", ...]] +ArgumentReplacerType = typing.Callable[ + [tuple, dict, tuple], tuple[tuple, dict] +] + +def unpickle_function(mod_name, qname, self_): + import importlib + + try: + module = importlib.import_module(mod_name) + qname = qname.split(".") + func = module + for q in qname: + func = getattr(func, q) + + if self_ is not None: + func = types.MethodType(func, self_) + + return func + except (ImportError, AttributeError) as e: + from pickle import UnpicklingError + + raise UnpicklingError from e + + +def pickle_function(func): + mod_name = getattr(func, "__module__", None) + qname = getattr(func, "__qualname__", None) + self_ = getattr(func, "__self__", None) + + try: + test = unpickle_function(mod_name, qname, self_) + except pickle.UnpicklingError: + test = None + + if test is not func: + raise pickle.PicklingError( + f"Can't pickle {func}: it's not the same object as {test}" + ) + + return unpickle_function, (mod_name, qname, self_) + + +def pickle_state(state): + return _uarray._BackendState._unpickle, state._pickle() + + +def pickle_set_backend_context(ctx): + return _SetBackendContext, ctx._pickle() + + +def pickle_skip_backend_context(ctx): + return _SkipBackendContext, ctx._pickle() + + +copyreg.pickle(_Function, pickle_function) +copyreg.pickle(_uarray._BackendState, pickle_state) +copyreg.pickle(_SetBackendContext, pickle_set_backend_context) +copyreg.pickle(_SkipBackendContext, pickle_skip_backend_context) + + +def get_state(): + """ + Returns an opaque object containing the current state of all the backends. + + Can be used for synchronization between threads/processes. + + See Also + -------- + set_state + Sets the state returned by this function. + """ + return _uarray.get_state() + + +@contextlib.contextmanager +def reset_state(): + """ + Returns a context manager that resets all state once exited. + + See Also + -------- + set_state + Context manager that sets the backend state. + get_state + Gets a state to be set by this context manager. + """ + with set_state(get_state()): + yield + + +@contextlib.contextmanager +def set_state(state): + """ + A context manager that sets the state of the backends to one returned by :obj:`get_state`. + + See Also + -------- + get_state + Gets a state to be set by this context manager. + """ # noqa: E501 + old_state = get_state() + _uarray.set_state(state) + try: + yield + finally: + _uarray.set_state(old_state, True) + + +def create_multimethod(*args, **kwargs): + """ + Creates a decorator for generating multimethods. + + This function creates a decorator that can be used with an argument + extractor in order to generate a multimethod. Other than for the + argument extractor, all arguments are passed on to + :obj:`generate_multimethod`. + + See Also + -------- + generate_multimethod + Generates a multimethod. + """ + + def wrapper(a): + return generate_multimethod(a, *args, **kwargs) + + return wrapper + + +def generate_multimethod( + argument_extractor: ArgumentExtractorType, + argument_replacer: ArgumentReplacerType, + domain: str, + default: typing.Callable | None = None, +): + """ + Generates a multimethod. + + Parameters + ---------- + argument_extractor : ArgumentExtractorType + A callable which extracts the dispatchable arguments. Extracted arguments + should be marked by the :obj:`Dispatchable` class. It has the same signature + as the desired multimethod. + argument_replacer : ArgumentReplacerType + A callable with the signature (args, kwargs, dispatchables), which should also + return an (args, kwargs) pair with the dispatchables replaced inside the + args/kwargs. + domain : str + A string value indicating the domain of this multimethod. + default: Optional[Callable], optional + The default implementation of this multimethod, where ``None`` (the default) + specifies there is no default implementation. + + Examples + -------- + In this example, ``a`` is to be dispatched over, so we return it, while marking it + as an ``int``. + The trailing comma is needed because the args have to be returned as an iterable. + + >>> def override_me(a, b): + ... return Dispatchable(a, int), + + Next, we define the argument replacer that replaces the dispatchables inside + args/kwargs with the supplied ones. + + >>> def override_replacer(args, kwargs, dispatchables): + ... return (dispatchables[0], args[1]), {} + + Next, we define the multimethod. + + >>> overridden_me = generate_multimethod( + ... override_me, override_replacer, "ua_examples" + ... ) + + Notice that there's no default implementation, unless you supply one. + + >>> overridden_me(1, "a") + Traceback (most recent call last): + ... + uarray.BackendNotImplementedError: ... + + >>> overridden_me2 = generate_multimethod( + ... override_me, override_replacer, "ua_examples", default=lambda x, y: (x, y) + ... ) + >>> overridden_me2(1, "a") + (1, 'a') + + See Also + -------- + uarray + See the module documentation for how to override the method by creating + backends. + """ + kw_defaults, arg_defaults, opts = get_defaults(argument_extractor) + ua_func = _Function( + argument_extractor, + argument_replacer, + domain, + arg_defaults, + kw_defaults, + default, + ) + + return functools.update_wrapper(ua_func, argument_extractor) + + +def set_backend(backend, coerce=False, only=False): + """ + A context manager that sets the preferred backend. + + Parameters + ---------- + backend + The backend to set. + coerce + Whether or not to coerce to a specific backend's types. Implies ``only``. + only + Whether or not this should be the last backend to try. + + See Also + -------- + skip_backend: A context manager that allows skipping of backends. + set_global_backend: Set a single, global backend for a domain. + """ + tid = threading.get_native_id() + try: + return backend.__ua_cache__[tid, "set", coerce, only] + except AttributeError: + backend.__ua_cache__ = {} + except KeyError: + pass + + ctx = _SetBackendContext(backend, coerce, only) + backend.__ua_cache__[tid, "set", coerce, only] = ctx + return ctx + + +def skip_backend(backend): + """ + A context manager that allows one to skip a given backend from processing + entirely. This allows one to use another backend's code in a library that + is also a consumer of the same backend. + + Parameters + ---------- + backend + The backend to skip. + + See Also + -------- + set_backend: A context manager that allows setting of backends. + set_global_backend: Set a single, global backend for a domain. + """ + tid = threading.get_native_id() + try: + return backend.__ua_cache__[tid, "skip"] + except AttributeError: + backend.__ua_cache__ = {} + except KeyError: + pass + + ctx = _SkipBackendContext(backend) + backend.__ua_cache__[tid, "skip"] = ctx + return ctx + + +def get_defaults(f): + sig = inspect.signature(f) + kw_defaults = {} + arg_defaults = [] + opts = set() + for k, v in sig.parameters.items(): + if v.default is not inspect.Parameter.empty: + kw_defaults[k] = v.default + if v.kind in ( + inspect.Parameter.POSITIONAL_ONLY, + inspect.Parameter.POSITIONAL_OR_KEYWORD, + ): + arg_defaults.append(v.default) + opts.add(k) + + return kw_defaults, tuple(arg_defaults), opts + + +def set_global_backend(backend, coerce=False, only=False, *, try_last=False): + """ + This utility method replaces the default backend for permanent use. It + will be tried in the list of backends automatically, unless the + ``only`` flag is set on a backend. This will be the first tried + backend outside the :obj:`set_backend` context manager. + + Note that this method is not thread-safe. + + .. warning:: + We caution library authors against using this function in + their code. We do *not* support this use-case. This function + is meant to be used only by users themselves, or by a reference + implementation, if one exists. + + Parameters + ---------- + backend + The backend to register. + coerce : bool + Whether to coerce input types when trying this backend. + only : bool + If ``True``, no more backends will be tried if this fails. + Implied by ``coerce=True``. + try_last : bool + If ``True``, the global backend is tried after registered backends. + + See Also + -------- + set_backend: A context manager that allows setting of backends. + skip_backend: A context manager that allows skipping of backends. + """ + _uarray.set_global_backend(backend, coerce, only, try_last) + + +def register_backend(backend): + """ + This utility method sets registers backend for permanent use. It + will be tried in the list of backends automatically, unless the + ``only`` flag is set on a backend. + + Note that this method is not thread-safe. + + Parameters + ---------- + backend + The backend to register. + """ + _uarray.register_backend(backend) + + +def clear_backends(domain, registered=True, globals=False): + """ + This utility method clears registered backends. + + .. warning:: + We caution library authors against using this function in + their code. We do *not* support this use-case. This function + is meant to be used only by users themselves. + + .. warning:: + Do NOT use this method inside a multimethod call, or the + program is likely to crash. + + Parameters + ---------- + domain : Optional[str] + The domain for which to de-register backends. ``None`` means + de-register for all domains. + registered : bool + Whether or not to clear registered backends. See :obj:`register_backend`. + globals : bool + Whether or not to clear global backends. See :obj:`set_global_backend`. + + See Also + -------- + register_backend : Register a backend globally. + set_global_backend : Set a global backend. + """ + _uarray.clear_backends(domain, registered, globals) + + +class Dispatchable: + """ + A utility class which marks an argument with a specific dispatch type. + + + Attributes + ---------- + value + The value of the Dispatchable. + + type + The type of the Dispatchable. + + Examples + -------- + >>> x = Dispatchable(1, str) + >>> x + , value=1> + + See Also + -------- + all_of_type + Marks all unmarked parameters of a function. + + mark_as + Allows one to create a utility function to mark as a given type. + """ + + def __init__(self, value, dispatch_type, coercible=True): + self.value = value + self.type = dispatch_type + self.coercible = coercible + + def __getitem__(self, index): + return (self.type, self.value)[index] + + def __str__(self): + return f"<{type(self).__name__}: type={self.type!r}, value={self.value!r}>" + + __repr__ = __str__ + + +def mark_as(dispatch_type): + """ + Creates a utility function to mark something as a specific type. + + Examples + -------- + >>> mark_int = mark_as(int) + >>> mark_int(1) + , value=1> + """ + return functools.partial(Dispatchable, dispatch_type=dispatch_type) + + +def all_of_type(arg_type): + """ + Marks all unmarked arguments as a given type. + + Examples + -------- + >>> @all_of_type(str) + ... def f(a, b): + ... return a, Dispatchable(b, int) + >>> f('a', 1) + (, value='a'>, + , value=1>) + """ + + def outer(func): + @functools.wraps(func) + def inner(*args, **kwargs): + extracted_args = func(*args, **kwargs) + return tuple( + Dispatchable(arg, arg_type) + if not isinstance(arg, Dispatchable) + else arg + for arg in extracted_args + ) + + return inner + + return outer + + +def wrap_single_convertor(convert_single): + """ + Wraps a ``__ua_convert__`` defined for a single element to all elements. + If any of them return ``NotImplemented``, the operation is assumed to be + undefined. + + Accepts a signature of (value, type, coerce). + """ + + @functools.wraps(convert_single) + def __ua_convert__(dispatchables, coerce): + converted = [] + for d in dispatchables: + c = convert_single(d.value, d.type, coerce and d.coercible) + + if c is NotImplemented: + return NotImplemented + + converted.append(c) + + return converted + + return __ua_convert__ + + +def wrap_single_convertor_instance(convert_single): + """ + Wraps a ``__ua_convert__`` defined for a single element to all elements. + If any of them return ``NotImplemented``, the operation is assumed to be + undefined. + + Accepts a signature of (value, type, coerce). + """ + + @functools.wraps(convert_single) + def __ua_convert__(self, dispatchables, coerce): + converted = [] + for d in dispatchables: + c = convert_single(self, d.value, d.type, coerce and d.coercible) + + if c is NotImplemented: + return NotImplemented + + converted.append(c) + + return converted + + return __ua_convert__ + + +def determine_backend(value, dispatch_type, *, domain, only=True, coerce=False): + """Set the backend to the first active backend that supports ``value`` + + This is useful for functions that call multimethods without any dispatchable + arguments. You can use :func:`determine_backend` to ensure the same backend + is used everywhere in a block of multimethod calls. + + Parameters + ---------- + value + The value being tested + dispatch_type + The dispatch type associated with ``value``, aka + ":ref:`marking `". + domain: string + The domain to query for backends and set. + coerce: bool + Whether or not to allow coercion to the backend's types. Implies ``only``. + only: bool + Whether or not this should be the last backend to try. + + See Also + -------- + set_backend: For when you know which backend to set + + Notes + ----- + + Support is determined by the ``__ua_convert__`` protocol. Backends not + supporting the type must return ``NotImplemented`` from their + ``__ua_convert__`` if they don't support input of that type. + + Examples + -------- + + Suppose we have two backends ``BackendA`` and ``BackendB`` each supporting + different types, ``TypeA`` and ``TypeB``. Neither supporting the other type: + + >>> with ua.set_backend(ex.BackendA): + ... ex.call_multimethod(ex.TypeB(), ex.TypeB()) + Traceback (most recent call last): + ... + uarray.BackendNotImplementedError: ... + + Now consider a multimethod that creates a new object of ``TypeA``, or + ``TypeB`` depending on the active backend. + + >>> with ua.set_backend(ex.BackendA), ua.set_backend(ex.BackendB): + ... res = ex.creation_multimethod() + ... ex.call_multimethod(res, ex.TypeA()) + Traceback (most recent call last): + ... + uarray.BackendNotImplementedError: ... + + ``res`` is an object of ``TypeB`` because ``BackendB`` is set in the + innermost with statement. So, ``call_multimethod`` fails since the types + don't match. + + Instead, we need to first find a backend suitable for all of our objects. + + >>> with ua.set_backend(ex.BackendA), ua.set_backend(ex.BackendB): + ... x = ex.TypeA() + ... with ua.determine_backend(x, "mark", domain="ua_examples"): + ... res = ex.creation_multimethod() + ... ex.call_multimethod(res, x) + TypeA + + """ + dispatchables = (Dispatchable(value, dispatch_type, coerce),) + backend = _uarray.determine_backend(domain, dispatchables, coerce) + + return set_backend(backend, coerce=coerce, only=only) + + +def determine_backend_multi( + dispatchables, *, domain, only=True, coerce=False, **kwargs +): + """Set a backend supporting all ``dispatchables`` + + This is useful for functions that call multimethods without any dispatchable + arguments. You can use :func:`determine_backend_multi` to ensure the same + backend is used everywhere in a block of multimethod calls involving + multiple arrays. + + Parameters + ---------- + dispatchables: Sequence[Union[uarray.Dispatchable, Any]] + The dispatchables that must be supported + domain: string + The domain to query for backends and set. + coerce: bool + Whether or not to allow coercion to the backend's types. Implies ``only``. + only: bool + Whether or not this should be the last backend to try. + dispatch_type: Optional[Any] + The default dispatch type associated with ``dispatchables``, aka + ":ref:`marking `". + + See Also + -------- + determine_backend: For a single dispatch value + set_backend: For when you know which backend to set + + Notes + ----- + + Support is determined by the ``__ua_convert__`` protocol. Backends not + supporting the type must return ``NotImplemented`` from their + ``__ua_convert__`` if they don't support input of that type. + + Examples + -------- + + :func:`determine_backend` allows the backend to be set from a single + object. :func:`determine_backend_multi` allows multiple objects to be + checked simultaneously for support in the backend. Suppose we have a + ``BackendAB`` which supports ``TypeA`` and ``TypeB`` in the same call, + and a ``BackendBC`` that doesn't support ``TypeA``. + + >>> with ua.set_backend(ex.BackendAB), ua.set_backend(ex.BackendBC): + ... a, b = ex.TypeA(), ex.TypeB() + ... with ua.determine_backend_multi( + ... [ua.Dispatchable(a, "mark"), ua.Dispatchable(b, "mark")], + ... domain="ua_examples" + ... ): + ... res = ex.creation_multimethod() + ... ex.call_multimethod(res, a, b) + TypeA + + This won't call ``BackendBC`` because it doesn't support ``TypeA``. + + We can also use leave out the ``ua.Dispatchable`` if we specify the + default ``dispatch_type`` for the ``dispatchables`` argument. + + >>> with ua.set_backend(ex.BackendAB), ua.set_backend(ex.BackendBC): + ... a, b = ex.TypeA(), ex.TypeB() + ... with ua.determine_backend_multi( + ... [a, b], dispatch_type="mark", domain="ua_examples" + ... ): + ... res = ex.creation_multimethod() + ... ex.call_multimethod(res, a, b) + TypeA + + """ + if "dispatch_type" in kwargs: + disp_type = kwargs.pop("dispatch_type") + dispatchables = tuple( + d if isinstance(d, Dispatchable) else Dispatchable(d, disp_type) + for d in dispatchables + ) + else: + dispatchables = tuple(dispatchables) + if not all(isinstance(d, Dispatchable) for d in dispatchables): + raise TypeError("dispatchables must be instances of uarray.Dispatchable") + + if len(kwargs) != 0: + raise TypeError(f"Received unexpected keyword arguments: {kwargs}") + + backend = _uarray.determine_backend(domain, dispatchables, coerce) + + return set_backend(backend, coerce=coerce, only=only) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..4abca400a24f71dd59876488e4cf9fde89de9489 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/__init__.py @@ -0,0 +1,22 @@ +""" +NumPy Array API compatibility library + +This is a small wrapper around NumPy, CuPy, JAX, sparse and others that are +compatible with the Array API standard https://data-apis.org/array-api/latest/. +See also NEP 47 https://numpy.org/neps/nep-0047-array-api-standard.html. + +Unlike array_api_strict, this is not a strict minimal implementation of the +Array API, but rather just an extension of the main NumPy namespace with +changes needed to be compliant with the Array API. See +https://numpy.org/doc/stable/reference/array_api.html for a full list of +changes. In particular, unlike array_api_strict, this package does not use a +separate Array object, but rather just uses numpy.ndarray directly. + +Library authors using the Array API may wish to test against array_api_strict +to ensure they are not using functionality outside of the standard, but prefer +this implementation for the default when working with NumPy arrays. + +""" +__version__ = '1.13.0' + +from .common import * # noqa: F401, F403 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c5c0583219ca7f4394aadaf57c84b79eb0cf2c79 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/__pycache__/_internal.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/__pycache__/_internal.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..238657ad939dd0ebfe50f1ca46abb388c3b425c2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/__pycache__/_internal.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/_internal.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/_internal.py new file mode 100644 index 0000000000000000000000000000000000000000..baa39ded8decf2837540837ebc7b49c7b6971b82 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/_internal.py @@ -0,0 +1,77 @@ +""" +Internal helpers +""" + +import importlib +from collections.abc import Callable +from functools import wraps +from inspect import signature +from types import ModuleType +from typing import TypeVar + +_T = TypeVar("_T") + + +def get_xp(xp: ModuleType) -> Callable[[Callable[..., _T]], Callable[..., _T]]: + """ + Decorator to automatically replace xp with the corresponding array module. + + Use like + + import numpy as np + + @get_xp(np) + def func(x, /, xp, kwarg=None): + return xp.func(x, kwarg=kwarg) + + Note that xp must be a keyword argument and come after all non-keyword + arguments. + + """ + + def inner(f: Callable[..., _T], /) -> Callable[..., _T]: + @wraps(f) + def wrapped_f(*args: object, **kwargs: object) -> object: + return f(*args, xp=xp, **kwargs) + + sig = signature(f) + new_sig = sig.replace( + parameters=[par for i, par in sig.parameters.items() if i != "xp"] + ) + + if wrapped_f.__doc__ is None: + wrapped_f.__doc__ = f"""\ +Array API compatibility wrapper for {f.__name__}. + +See the corresponding documentation in NumPy/CuPy and/or the array API +specification for more details. + +""" + wrapped_f.__signature__ = new_sig # type: ignore[attr-defined] # pyright: ignore[reportAttributeAccessIssue] + return wrapped_f # type: ignore[return-value] # pyright: ignore[reportReturnType] + + return inner + + +def clone_module(mod_name: str, globals_: dict[str, object]) -> list[str]: + """Import everything from module, updating globals(). + Returns __all__. + """ + mod = importlib.import_module(mod_name) + # Neither of these two methods is sufficient by itself, + # depending on various idiosyncrasies of the libraries we're wrapping. + objs = {} + exec(f"from {mod.__name__} import *", objs) + + for n in dir(mod): + if not n.startswith("_") and hasattr(mod, n): + objs[n] = getattr(mod, n) + + globals_.update(objs) + return list(objs) + + +__all__ = ["get_xp", "clone_module"] + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8236080738175f0fb7d1f47fcc52522306b43050 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__init__.py @@ -0,0 +1 @@ +from ._helpers import * # noqa: F403 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7732e4aeffdd41dd9d7b121d1a4ba1bf91513a1e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/_aliases.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/_aliases.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d1f80702cda6755a8dcfaab69ff411cdc834e6cb Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/_aliases.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/_fft.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/_fft.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f630948628ec4358dcc6c19104cfd78b6a51f2f9 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/_fft.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/_helpers.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/_helpers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..52151c00051fa909dfdfd3db20a99d8f01e86dc5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/_helpers.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/_linalg.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/_linalg.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..edc5ef550990cea78a551fab32bc1cc8774d2263 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/_linalg.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/_typing.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/_typing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f413df3f6a937cf5fae477dc6e3c9c2e6c13bbc3 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/__pycache__/_typing.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/_aliases.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/_aliases.py new file mode 100644 index 0000000000000000000000000000000000000000..3587ef16fa18b22081770ecbd13335a4fed5ac0c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/_aliases.py @@ -0,0 +1,702 @@ +""" +These are functions that are just aliases of existing functions in NumPy. +""" + +from __future__ import annotations + +import inspect +from collections.abc import Sequence +from typing import TYPE_CHECKING, Any, NamedTuple, cast + +from ._helpers import _check_device, array_namespace +from ._helpers import device as _get_device +from ._helpers import is_cupy_namespace +from ._typing import Array, Device, DType, Namespace + +if TYPE_CHECKING: + # TODO: import from typing (requires Python >=3.13) + from typing_extensions import TypeIs + +# These functions are modified from the NumPy versions. + +# Creation functions add the device keyword (which does nothing for NumPy and Dask) + + +def arange( + start: float, + /, + stop: float | None = None, + step: float = 1, + *, + xp: Namespace, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object, +) -> Array: + _check_device(xp, device) + return xp.arange(start, stop=stop, step=step, dtype=dtype, **kwargs) + + +def empty( + shape: int | tuple[int, ...], + xp: Namespace, + *, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object, +) -> Array: + _check_device(xp, device) + return xp.empty(shape, dtype=dtype, **kwargs) + + +def empty_like( + x: Array, + /, + xp: Namespace, + *, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object, +) -> Array: + _check_device(xp, device) + return xp.empty_like(x, dtype=dtype, **kwargs) + + +def eye( + n_rows: int, + n_cols: int | None = None, + /, + *, + xp: Namespace, + k: int = 0, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object, +) -> Array: + _check_device(xp, device) + return xp.eye(n_rows, M=n_cols, k=k, dtype=dtype, **kwargs) + + +def full( + shape: int | tuple[int, ...], + fill_value: complex, + xp: Namespace, + *, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object, +) -> Array: + _check_device(xp, device) + return xp.full(shape, fill_value, dtype=dtype, **kwargs) + + +def full_like( + x: Array, + /, + fill_value: complex, + *, + xp: Namespace, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object, +) -> Array: + _check_device(xp, device) + return xp.full_like(x, fill_value, dtype=dtype, **kwargs) + + +def linspace( + start: float, + stop: float, + /, + num: int, + *, + xp: Namespace, + dtype: DType | None = None, + device: Device | None = None, + endpoint: bool = True, + **kwargs: object, +) -> Array: + _check_device(xp, device) + return xp.linspace(start, stop, num, dtype=dtype, endpoint=endpoint, **kwargs) + + +def ones( + shape: int | tuple[int, ...], + xp: Namespace, + *, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object, +) -> Array: + _check_device(xp, device) + return xp.ones(shape, dtype=dtype, **kwargs) + + +def ones_like( + x: Array, + /, + xp: Namespace, + *, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object, +) -> Array: + _check_device(xp, device) + return xp.ones_like(x, dtype=dtype, **kwargs) + + +def zeros( + shape: int | tuple[int, ...], + xp: Namespace, + *, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object, +) -> Array: + _check_device(xp, device) + return xp.zeros(shape, dtype=dtype, **kwargs) + + +def zeros_like( + x: Array, + /, + xp: Namespace, + *, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object, +) -> Array: + _check_device(xp, device) + return xp.zeros_like(x, dtype=dtype, **kwargs) + + +# np.unique() is split into four functions in the array API: +# unique_all, unique_counts, unique_inverse, and unique_values (this is done +# to remove polymorphic return types). + +# The functions here return namedtuples (np.unique() returns a normal +# tuple). + + +# Note that these named tuples aren't actually part of the standard namespace, +# but I don't see any issue with exporting the names here regardless. +class UniqueAllResult(NamedTuple): + values: Array + indices: Array + inverse_indices: Array + counts: Array + + +class UniqueCountsResult(NamedTuple): + values: Array + counts: Array + + +class UniqueInverseResult(NamedTuple): + values: Array + inverse_indices: Array + + +def _unique_kwargs(xp: Namespace) -> dict[str, bool]: + # Older versions of NumPy and CuPy do not have equal_nan. Rather than + # trying to parse version numbers, just check if equal_nan is in the + # signature. + s = inspect.signature(xp.unique) + if "equal_nan" in s.parameters: + return {"equal_nan": False} + return {} + + +def unique_all(x: Array, /, xp: Namespace) -> UniqueAllResult: + kwargs = _unique_kwargs(xp) + values, indices, inverse_indices, counts = xp.unique( + x, + return_counts=True, + return_index=True, + return_inverse=True, + **kwargs, + ) + # np.unique() flattens inverse indices, but they need to share x's shape + # See https://github.com/numpy/numpy/issues/20638 + inverse_indices = inverse_indices.reshape(x.shape) + return UniqueAllResult( + values, + indices, + inverse_indices, + counts, + ) + + +def unique_counts(x: Array, /, xp: Namespace) -> UniqueCountsResult: + kwargs = _unique_kwargs(xp) + res = xp.unique( + x, return_counts=True, return_index=False, return_inverse=False, **kwargs + ) + + return UniqueCountsResult(*res) + + +def unique_inverse(x: Array, /, xp: Namespace) -> UniqueInverseResult: + kwargs = _unique_kwargs(xp) + values, inverse_indices = xp.unique( + x, + return_counts=False, + return_index=False, + return_inverse=True, + **kwargs, + ) + # xp.unique() flattens inverse indices, but they need to share x's shape + # See https://github.com/numpy/numpy/issues/20638 + inverse_indices = inverse_indices.reshape(x.shape) + return UniqueInverseResult(values, inverse_indices) + + +def unique_values(x: Array, /, xp: Namespace) -> Array: + kwargs = _unique_kwargs(xp) + return xp.unique( + x, + return_counts=False, + return_index=False, + return_inverse=False, + **kwargs, + ) + + +# These functions have different keyword argument names + + +def std( + x: Array, + /, + xp: Namespace, + *, + axis: int | tuple[int, ...] | None = None, + correction: float = 0.0, # correction instead of ddof + keepdims: bool = False, + **kwargs: object, +) -> Array: + return xp.std(x, axis=axis, ddof=correction, keepdims=keepdims, **kwargs) + + +def var( + x: Array, + /, + xp: Namespace, + *, + axis: int | tuple[int, ...] | None = None, + correction: float = 0.0, # correction instead of ddof + keepdims: bool = False, + **kwargs: object, +) -> Array: + return xp.var(x, axis=axis, ddof=correction, keepdims=keepdims, **kwargs) + + +# cumulative_sum is renamed from cumsum, and adds the include_initial keyword +# argument + + +def cumulative_sum( + x: Array, + /, + xp: Namespace, + *, + axis: int | None = None, + dtype: DType | None = None, + include_initial: bool = False, + **kwargs: object, +) -> Array: + wrapped_xp = array_namespace(x) + + # TODO: The standard is not clear about what should happen when x.ndim == 0. + if axis is None: + if x.ndim > 1: + raise ValueError( + "axis must be specified in cumulative_sum for more than one dimension" + ) + axis = 0 + + res = xp.cumsum(x, axis=axis, dtype=dtype, **kwargs) + + # np.cumsum does not support include_initial + if include_initial: + initial_shape = list(x.shape) + initial_shape[axis] = 1 + res = xp.concatenate( + [ + wrapped_xp.zeros( + shape=initial_shape, dtype=res.dtype, device=_get_device(res) + ), + res, + ], + axis=axis, + ) + return res + + +def cumulative_prod( + x: Array, + /, + xp: Namespace, + *, + axis: int | None = None, + dtype: DType | None = None, + include_initial: bool = False, + **kwargs: object, +) -> Array: + wrapped_xp = array_namespace(x) + + if axis is None: + if x.ndim > 1: + raise ValueError( + "axis must be specified in cumulative_prod for more than one dimension" + ) + axis = 0 + + res = xp.cumprod(x, axis=axis, dtype=dtype, **kwargs) + + # np.cumprod does not support include_initial + if include_initial: + initial_shape = list(x.shape) + initial_shape[axis] = 1 + res = xp.concatenate( + [ + wrapped_xp.ones( + shape=initial_shape, dtype=res.dtype, device=_get_device(res) + ), + res, + ], + axis=axis, + ) + return res + + +# The min and max argument names in clip are different and not optional in numpy, and type +# promotion behavior is different. +def clip( + x: Array, + /, + min: float | Array | None = None, + max: float | Array | None = None, + *, + xp: Namespace, + # TODO: np.clip has other ufunc kwargs + out: Array | None = None, +) -> Array: + def _isscalar(a: object) -> TypeIs[float | None]: + return isinstance(a, int | float) or a is None + + min_shape = () if _isscalar(min) else min.shape + max_shape = () if _isscalar(max) else max.shape + + wrapped_xp = array_namespace(x) + + result_shape = xp.broadcast_shapes(x.shape, min_shape, max_shape) + + # np.clip does type promotion but the array API clip requires that the + # output have the same dtype as x. We do this instead of just downcasting + # the result of xp.clip() to handle some corner cases better (e.g., + # avoiding uint64 -> float64 promotion). + + # Note: cases where min or max overflow (integer) or round (float) in the + # wrong direction when downcasting to x.dtype are unspecified. This code + # just does whatever NumPy does when it downcasts in the assignment, but + # other behavior could be preferred, especially for integers. For example, + # this code produces: + + # >>> clip(asarray(0, dtype=int8), asarray(128, dtype=int16), None) + # -128 + + # but an answer of 0 might be preferred. See + # https://github.com/numpy/numpy/issues/24976 for more discussion on this issue. + + # At least handle the case of Python integers correctly (see + # https://github.com/numpy/numpy/pull/26892). + if wrapped_xp.isdtype(x.dtype, "integral"): + if type(min) is int and min <= wrapped_xp.iinfo(x.dtype).min: + min = None + if type(max) is int and max >= wrapped_xp.iinfo(x.dtype).max: + max = None + + dev = _get_device(x) + if out is None: + out = wrapped_xp.empty(result_shape, dtype=x.dtype, device=dev) + assert out is not None # workaround for a type-narrowing issue in pyright + out[()] = x + + if min is not None: + a = wrapped_xp.asarray(min, dtype=x.dtype, device=dev) + a = xp.broadcast_to(a, result_shape) + ia = (out < a) | xp.isnan(a) + out[ia] = a[ia] + + if max is not None: + b = wrapped_xp.asarray(max, dtype=x.dtype, device=dev) + b = xp.broadcast_to(b, result_shape) + ib = (out > b) | xp.isnan(b) + out[ib] = b[ib] + + # Return a scalar for 0-D + return out[()] + + +# Unlike transpose(), the axes argument to permute_dims() is required. +def permute_dims(x: Array, /, axes: tuple[int, ...], xp: Namespace) -> Array: + return xp.transpose(x, axes) + + +# np.reshape calls the keyword argument 'newshape' instead of 'shape' +def reshape( + x: Array, + /, + shape: tuple[int, ...], + xp: Namespace, + *, + copy: bool | None = None, + **kwargs: object, +) -> Array: + if copy is True: + x = x.copy() + elif copy is False: + y = x.view() + y.shape = shape + return y + return xp.reshape(x, shape, **kwargs) + + +# The descending keyword is new in sort and argsort, and 'kind' replaced with +# 'stable' +def argsort( + x: Array, + /, + xp: Namespace, + *, + axis: int = -1, + descending: bool = False, + stable: bool = True, + **kwargs: object, +) -> Array: + # Note: this keyword argument is different, and the default is different. + # We set it in kwargs like this because numpy.sort uses kind='quicksort' + # as the default whereas cupy.sort uses kind=None. + if stable: + kwargs["kind"] = "stable" + if not descending: + res = xp.argsort(x, axis=axis, **kwargs) + else: + # As NumPy has no native descending sort, we imitate it here. Note that + # simply flipping the results of xp.argsort(x, ...) would not + # respect the relative order like it would in native descending sorts. + res = xp.flip( + xp.argsort(xp.flip(x, axis=axis), axis=axis, **kwargs), + axis=axis, + ) + # Rely on flip()/argsort() to validate axis + normalised_axis = axis if axis >= 0 else x.ndim + axis + max_i = x.shape[normalised_axis] - 1 + res = max_i - res + return res + + +def sort( + x: Array, + /, + xp: Namespace, + *, + axis: int = -1, + descending: bool = False, + stable: bool = True, + **kwargs: object, +) -> Array: + # Note: this keyword argument is different, and the default is different. + # We set it in kwargs like this because numpy.sort uses kind='quicksort' + # as the default whereas cupy.sort uses kind=None. + if stable: + kwargs["kind"] = "stable" + res = xp.sort(x, axis=axis, **kwargs) + if descending: + res = xp.flip(res, axis=axis) + return res + + +# nonzero should error for zero-dimensional arrays +def nonzero(x: Array, /, xp: Namespace, **kwargs: object) -> tuple[Array, ...]: + if x.ndim == 0: + raise ValueError("nonzero() does not support zero-dimensional arrays") + return xp.nonzero(x, **kwargs) + + +# linear algebra functions + + +def matmul(x1: Array, x2: Array, /, xp: Namespace, **kwargs: object) -> Array: + return xp.matmul(x1, x2, **kwargs) + + +# Unlike transpose, matrix_transpose only transposes the last two axes. +def matrix_transpose(x: Array, /, xp: Namespace) -> Array: + if x.ndim < 2: + raise ValueError("x must be at least 2-dimensional for matrix_transpose") + return xp.swapaxes(x, -1, -2) + + +def tensordot( + x1: Array, + x2: Array, + /, + xp: Namespace, + *, + axes: int | tuple[Sequence[int], Sequence[int]] = 2, + **kwargs: object, +) -> Array: + return xp.tensordot(x1, x2, axes=axes, **kwargs) + + +def vecdot(x1: Array, x2: Array, /, xp: Namespace, *, axis: int = -1) -> Array: + if x1.shape[axis] != x2.shape[axis]: + raise ValueError("x1 and x2 must have the same size along the given axis") + + if hasattr(xp, "broadcast_tensors"): + _broadcast = xp.broadcast_tensors + else: + _broadcast = xp.broadcast_arrays + + x1_ = xp.moveaxis(x1, axis, -1) + x2_ = xp.moveaxis(x2, axis, -1) + x1_, x2_ = _broadcast(x1_, x2_) + + res = xp.conj(x1_[..., None, :]) @ x2_[..., None] + return res[..., 0, 0] + + +# isdtype is a new function in the 2022.12 array API specification. + + +def isdtype( + dtype: DType, + kind: DType | str | tuple[DType | str, ...], + xp: Namespace, + *, + _tuple: bool = True, # Disallow nested tuples +) -> bool: + """ + Returns a boolean indicating whether a provided dtype is of a specified data type ``kind``. + + Note that outside of this function, this compat library does not yet fully + support complex numbers. + + See + https://data-apis.org/array-api/latest/API_specification/generated/array_api.isdtype.html + for more details + """ + if isinstance(kind, tuple) and _tuple: + return any( + isdtype(dtype, k, xp, _tuple=False) + for k in cast("tuple[DType | str, ...]", kind) + ) + elif isinstance(kind, str): + if kind == "bool": + return dtype == xp.bool_ + elif kind == "signed integer": + return xp.issubdtype(dtype, xp.signedinteger) + elif kind == "unsigned integer": + return xp.issubdtype(dtype, xp.unsignedinteger) + elif kind == "integral": + return xp.issubdtype(dtype, xp.integer) + elif kind == "real floating": + return xp.issubdtype(dtype, xp.floating) + elif kind == "complex floating": + return xp.issubdtype(dtype, xp.complexfloating) + elif kind == "numeric": + return xp.issubdtype(dtype, xp.number) + else: + raise ValueError(f"Unrecognized data type kind: {kind!r}") + else: + # This will allow things that aren't required by the spec, like + # isdtype(np.float64, float) or isdtype(np.int64, 'l'). Should we be + # more strict here to match the type annotation? Note that the + # array_api_strict implementation will be very strict. + return dtype == kind + + +# unstack is a new function in the 2023.12 array API standard +def unstack(x: Array, /, xp: Namespace, *, axis: int = 0) -> tuple[Array, ...]: + if x.ndim == 0: + raise ValueError("Input array must be at least 1-d.") + return tuple(xp.moveaxis(x, axis, 0)) + + +# numpy 1.26 does not use the standard definition for sign on complex numbers + + +def sign(x: Array, /, xp: Namespace, **kwargs: object) -> Array: + if isdtype(x.dtype, "complex floating", xp=xp): + out = (x / xp.abs(x, **kwargs))[...] + # sign(0) = 0 but the above formula would give nan + out[x == 0j] = 0j + else: + out = xp.sign(x, **kwargs) + # CuPy sign() does not propagate nans. See + # https://github.com/data-apis/array-api-compat/issues/136 + if is_cupy_namespace(xp) and isdtype(x.dtype, "real floating", xp=xp): + out[xp.isnan(x)] = xp.nan + return out[()] + + +def finfo(type_: DType | Array, /, xp: Namespace) -> Any: + # It is surprisingly difficult to recognize a dtype apart from an array. + # np.int64 is not the same as np.asarray(1).dtype! + try: + return xp.finfo(type_) + except (ValueError, TypeError): + return xp.finfo(type_.dtype) + + +def iinfo(type_: DType | Array, /, xp: Namespace) -> Any: + try: + return xp.iinfo(type_) + except (ValueError, TypeError): + return xp.iinfo(type_.dtype) + + +__all__ = [ + "arange", + "empty", + "empty_like", + "eye", + "full", + "full_like", + "linspace", + "ones", + "ones_like", + "zeros", + "zeros_like", + "UniqueAllResult", + "UniqueCountsResult", + "UniqueInverseResult", + "unique_all", + "unique_counts", + "unique_inverse", + "unique_values", + "std", + "var", + "cumulative_sum", + "cumulative_prod", + "clip", + "permute_dims", + "reshape", + "argsort", + "sort", + "nonzero", + "matmul", + "matrix_transpose", + "tensordot", + "vecdot", + "isdtype", + "unstack", + "sign", + "finfo", + "iinfo", +] + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/_fft.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/_fft.py new file mode 100644 index 0000000000000000000000000000000000000000..18839d37f84949ec2bf851b548c2e13b5179e04e --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/_fft.py @@ -0,0 +1,213 @@ +from __future__ import annotations + +from collections.abc import Sequence +from typing import Literal, TypeAlias + +from ._typing import Array, Device, DType, Namespace + +_Norm: TypeAlias = Literal["backward", "ortho", "forward"] + +# Note: NumPy fft functions improperly upcast float32 and complex64 to +# complex128, which is why we require wrapping them all here. + +def fft( + x: Array, + /, + xp: Namespace, + *, + n: int | None = None, + axis: int = -1, + norm: _Norm = "backward", +) -> Array: + res = xp.fft.fft(x, n=n, axis=axis, norm=norm) + if x.dtype in [xp.float32, xp.complex64]: + return res.astype(xp.complex64) + return res + +def ifft( + x: Array, + /, + xp: Namespace, + *, + n: int | None = None, + axis: int = -1, + norm: _Norm = "backward", +) -> Array: + res = xp.fft.ifft(x, n=n, axis=axis, norm=norm) + if x.dtype in [xp.float32, xp.complex64]: + return res.astype(xp.complex64) + return res + +def fftn( + x: Array, + /, + xp: Namespace, + *, + s: Sequence[int] | None = None, + axes: Sequence[int] | None = None, + norm: _Norm = "backward", +) -> Array: + res = xp.fft.fftn(x, s=s, axes=axes, norm=norm) + if x.dtype in [xp.float32, xp.complex64]: + return res.astype(xp.complex64) + return res + +def ifftn( + x: Array, + /, + xp: Namespace, + *, + s: Sequence[int] | None = None, + axes: Sequence[int] | None = None, + norm: _Norm = "backward", +) -> Array: + res = xp.fft.ifftn(x, s=s, axes=axes, norm=norm) + if x.dtype in [xp.float32, xp.complex64]: + return res.astype(xp.complex64) + return res + +def rfft( + x: Array, + /, + xp: Namespace, + *, + n: int | None = None, + axis: int = -1, + norm: _Norm = "backward", +) -> Array: + res = xp.fft.rfft(x, n=n, axis=axis, norm=norm) + if x.dtype == xp.float32: + return res.astype(xp.complex64) + return res + +def irfft( + x: Array, + /, + xp: Namespace, + *, + n: int | None = None, + axis: int = -1, + norm: _Norm = "backward", +) -> Array: + res = xp.fft.irfft(x, n=n, axis=axis, norm=norm) + if x.dtype == xp.complex64: + return res.astype(xp.float32) + return res + +def rfftn( + x: Array, + /, + xp: Namespace, + *, + s: Sequence[int] | None = None, + axes: Sequence[int] | None = None, + norm: _Norm = "backward", +) -> Array: + res = xp.fft.rfftn(x, s=s, axes=axes, norm=norm) + if x.dtype == xp.float32: + return res.astype(xp.complex64) + return res + +def irfftn( + x: Array, + /, + xp: Namespace, + *, + s: Sequence[int] | None = None, + axes: Sequence[int] | None = None, + norm: _Norm = "backward", +) -> Array: + res = xp.fft.irfftn(x, s=s, axes=axes, norm=norm) + if x.dtype == xp.complex64: + return res.astype(xp.float32) + return res + +def hfft( + x: Array, + /, + xp: Namespace, + *, + n: int | None = None, + axis: int = -1, + norm: _Norm = "backward", +) -> Array: + res = xp.fft.hfft(x, n=n, axis=axis, norm=norm) + if x.dtype in [xp.float32, xp.complex64]: + return res.astype(xp.float32) + return res + +def ihfft( + x: Array, + /, + xp: Namespace, + *, + n: int | None = None, + axis: int = -1, + norm: _Norm = "backward", +) -> Array: + res = xp.fft.ihfft(x, n=n, axis=axis, norm=norm) + if x.dtype in [xp.float32, xp.complex64]: + return res.astype(xp.complex64) + return res + +def fftfreq( + n: int, + /, + xp: Namespace, + *, + d: float = 1.0, + dtype: DType | None = None, + device: Device | None = None, +) -> Array: + if device not in ["cpu", None]: + raise ValueError(f"Unsupported device {device!r}") + res = xp.fft.fftfreq(n, d=d) + if dtype is not None: + return res.astype(dtype) + return res + +def rfftfreq( + n: int, + /, + xp: Namespace, + *, + d: float = 1.0, + dtype: DType | None = None, + device: Device | None = None, +) -> Array: + if device not in ["cpu", None]: + raise ValueError(f"Unsupported device {device!r}") + res = xp.fft.rfftfreq(n, d=d) + if dtype is not None: + return res.astype(dtype) + return res + +def fftshift( + x: Array, /, xp: Namespace, *, axes: int | Sequence[int] | None = None +) -> Array: + return xp.fft.fftshift(x, axes=axes) + +def ifftshift( + x: Array, /, xp: Namespace, *, axes: int | Sequence[int] | None = None +) -> Array: + return xp.fft.ifftshift(x, axes=axes) + +__all__ = [ + "fft", + "ifft", + "fftn", + "ifftn", + "rfft", + "irfft", + "rfftn", + "irfftn", + "hfft", + "ihfft", + "fftfreq", + "rfftfreq", + "fftshift", + "ifftshift", +] + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/_helpers.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/_helpers.py new file mode 100644 index 0000000000000000000000000000000000000000..8194a083db92fc2c09f93062d4b13d23ed0b611f --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/_helpers.py @@ -0,0 +1,1079 @@ +""" +Various helper functions which are not part of the spec. + +Functions which start with an underscore are for internal use only but helpers +that are in __all__ are intended as additional helper functions for use by end +users of the compat library. +""" + +from __future__ import annotations + +import enum +import inspect +import math +import sys +import warnings +from collections.abc import Collection, Hashable +from functools import lru_cache +from typing import ( + TYPE_CHECKING, + Any, + Final, + Literal, + SupportsIndex, + TypeAlias, + TypeGuard, + cast, + overload, +) + +from ._typing import Array, Device, HasShape, Namespace, SupportsArrayNamespace + +if TYPE_CHECKING: + import cupy as cp + import dask.array as da + import jax + import ndonnx as ndx + import numpy as np + import numpy.typing as npt + import sparse + import torch + + # TODO: import from typing (requires Python >=3.13) + from typing_extensions import TypeIs + + _ZeroGradientArray: TypeAlias = npt.NDArray[np.void] + + _ArrayApiObj: TypeAlias = ( + npt.NDArray[Any] + | cp.ndarray + | da.Array + | jax.Array + | ndx.Array + | sparse.SparseArray + | torch.Tensor + | SupportsArrayNamespace[Any] + ) + +_API_VERSIONS_OLD: Final = frozenset({"2021.12", "2022.12", "2023.12"}) +_API_VERSIONS: Final = _API_VERSIONS_OLD | frozenset({"2024.12"}) + + +@lru_cache(100) +def _issubclass_fast(cls: type, modname: str, clsname: str) -> bool: + try: + mod = sys.modules[modname] + except KeyError: + return False + parent_cls = getattr(mod, clsname) + return issubclass(cls, parent_cls) + + +def _is_jax_zero_gradient_array(x: object) -> TypeGuard[_ZeroGradientArray]: + """Return True if `x` is a zero-gradient array. + + These arrays are a design quirk of Jax that may one day be removed. + See https://github.com/google/jax/issues/20620. + """ + # Fast exit + try: + dtype = x.dtype # type: ignore[attr-defined] + except AttributeError: + return False + cls = cast(Hashable, type(dtype)) + if not _issubclass_fast(cls, "numpy.dtypes", "VoidDType"): + return False + + if "jax" not in sys.modules: + return False + + import jax + # jax.float0 is a np.dtype([('float0', 'V')]) + return dtype == jax.float0 + + +def is_numpy_array(x: object) -> TypeIs[npt.NDArray[Any]]: + """ + Return True if `x` is a NumPy array. + + This function does not import NumPy if it has not already been imported + and is therefore cheap to use. + + This also returns True for `ndarray` subclasses and NumPy scalar objects. + + See Also + -------- + + array_namespace + is_array_api_obj + is_cupy_array + is_torch_array + is_ndonnx_array + is_dask_array + is_jax_array + is_pydata_sparse_array + """ + # TODO: Should we reject ndarray subclasses? + cls = cast(Hashable, type(x)) + return ( + _issubclass_fast(cls, "numpy", "ndarray") + or _issubclass_fast(cls, "numpy", "generic") + ) and not _is_jax_zero_gradient_array(x) + + +def is_cupy_array(x: object) -> bool: + """ + Return True if `x` is a CuPy array. + + This function does not import CuPy if it has not already been imported + and is therefore cheap to use. + + This also returns True for `cupy.ndarray` subclasses and CuPy scalar objects. + + See Also + -------- + + array_namespace + is_array_api_obj + is_numpy_array + is_torch_array + is_ndonnx_array + is_dask_array + is_jax_array + is_pydata_sparse_array + """ + cls = cast(Hashable, type(x)) + return _issubclass_fast(cls, "cupy", "ndarray") + + +def is_torch_array(x: object) -> TypeIs[torch.Tensor]: + """ + Return True if `x` is a PyTorch tensor. + + This function does not import PyTorch if it has not already been imported + and is therefore cheap to use. + + See Also + -------- + + array_namespace + is_array_api_obj + is_numpy_array + is_cupy_array + is_dask_array + is_jax_array + is_pydata_sparse_array + """ + cls = cast(Hashable, type(x)) + return _issubclass_fast(cls, "torch", "Tensor") + + +def is_ndonnx_array(x: object) -> TypeIs[ndx.Array]: + """ + Return True if `x` is a ndonnx Array. + + This function does not import ndonnx if it has not already been imported + and is therefore cheap to use. + + See Also + -------- + + array_namespace + is_array_api_obj + is_numpy_array + is_cupy_array + is_ndonnx_array + is_dask_array + is_jax_array + is_pydata_sparse_array + """ + cls = cast(Hashable, type(x)) + return _issubclass_fast(cls, "ndonnx", "Array") + + +def is_dask_array(x: object) -> TypeIs[da.Array]: + """ + Return True if `x` is a dask.array Array. + + This function does not import dask if it has not already been imported + and is therefore cheap to use. + + See Also + -------- + + array_namespace + is_array_api_obj + is_numpy_array + is_cupy_array + is_torch_array + is_ndonnx_array + is_jax_array + is_pydata_sparse_array + """ + cls = cast(Hashable, type(x)) + return _issubclass_fast(cls, "dask.array", "Array") + + +def is_jax_array(x: object) -> TypeIs[jax.Array]: + """ + Return True if `x` is a JAX array. + + This function does not import JAX if it has not already been imported + and is therefore cheap to use. + + + See Also + -------- + + array_namespace + is_array_api_obj + is_numpy_array + is_cupy_array + is_torch_array + is_ndonnx_array + is_dask_array + is_pydata_sparse_array + """ + cls = cast(Hashable, type(x)) + # We test for jax.core.Tracer here to identify jax arrays during jit tracing. From jax 0.8.2 on, + # tracers are not a subclass of jax.Array anymore. Note that tracers can also represent + # non-array values and a fully correct implementation would need to use isinstance checks. Since + # we use hash-based caching with type names as keys, we cannot use instance checks without + # losing performance here. For more information, see + # https://github.com/data-apis/array-api-compat/pull/369 and the corresponding issue. + return ( + _issubclass_fast(cls, "jax", "Array") + or _issubclass_fast(cls, "jax.core", "Tracer") + or _is_jax_zero_gradient_array(x) + ) + + +def is_pydata_sparse_array(x: object) -> TypeIs[sparse.SparseArray]: + """ + Return True if `x` is an array from the `sparse` package. + + This function does not import `sparse` if it has not already been imported + and is therefore cheap to use. + + + See Also + -------- + + array_namespace + is_array_api_obj + is_numpy_array + is_cupy_array + is_torch_array + is_ndonnx_array + is_dask_array + is_jax_array + """ + # TODO: Account for other backends. + cls = cast(Hashable, type(x)) + return _issubclass_fast(cls, "sparse", "SparseArray") + + +def is_array_api_obj(x: object) -> TypeGuard[_ArrayApiObj]: + """ + Return True if `x` is an array API compatible array object. + + See Also + -------- + + array_namespace + is_numpy_array + is_cupy_array + is_torch_array + is_ndonnx_array + is_dask_array + is_jax_array + """ + return ( + hasattr(x, '__array_namespace__') + or _is_array_api_cls(cast(Hashable, type(x))) + ) + + +@lru_cache(100) +def _is_array_api_cls(cls: type) -> bool: + return ( + # TODO: drop support for numpy<2 which didn't have __array_namespace__ + _issubclass_fast(cls, "numpy", "ndarray") + or _issubclass_fast(cls, "numpy", "generic") + or _issubclass_fast(cls, "cupy", "ndarray") + or _issubclass_fast(cls, "torch", "Tensor") + or _issubclass_fast(cls, "dask.array", "Array") + or _issubclass_fast(cls, "sparse", "SparseArray") + # TODO: drop support for jax<0.4.32 which didn't have __array_namespace__ + or _issubclass_fast(cls, "jax", "Array") + or _issubclass_fast(cls, "jax.core", "Tracer") # see is_jax_array for limitations + ) + + +def _compat_module_name() -> str: + assert __name__.endswith(".common._helpers") + return __name__.removesuffix(".common._helpers") + + +@lru_cache(100) +def is_numpy_namespace(xp: Namespace) -> bool: + """ + Returns True if `xp` is a NumPy namespace. + + This includes both NumPy itself and the version wrapped by array-api-compat. + + See Also + -------- + + array_namespace + is_cupy_namespace + is_torch_namespace + is_ndonnx_namespace + is_dask_namespace + is_jax_namespace + is_pydata_sparse_namespace + is_array_api_strict_namespace + """ + return xp.__name__ in {"numpy", _compat_module_name() + ".numpy"} + + +@lru_cache(100) +def is_cupy_namespace(xp: Namespace) -> bool: + """ + Returns True if `xp` is a CuPy namespace. + + This includes both CuPy itself and the version wrapped by array-api-compat. + + See Also + -------- + + array_namespace + is_numpy_namespace + is_torch_namespace + is_ndonnx_namespace + is_dask_namespace + is_jax_namespace + is_pydata_sparse_namespace + is_array_api_strict_namespace + """ + return xp.__name__ in {"cupy", _compat_module_name() + ".cupy"} + + +@lru_cache(100) +def is_torch_namespace(xp: Namespace) -> bool: + """ + Returns True if `xp` is a PyTorch namespace. + + This includes both PyTorch itself and the version wrapped by array-api-compat. + + See Also + -------- + + array_namespace + is_numpy_namespace + is_cupy_namespace + is_ndonnx_namespace + is_dask_namespace + is_jax_namespace + is_pydata_sparse_namespace + is_array_api_strict_namespace + """ + return xp.__name__ in {"torch", _compat_module_name() + ".torch"} + + +def is_ndonnx_namespace(xp: Namespace) -> bool: + """ + Returns True if `xp` is an NDONNX namespace. + + See Also + -------- + + array_namespace + is_numpy_namespace + is_cupy_namespace + is_torch_namespace + is_dask_namespace + is_jax_namespace + is_pydata_sparse_namespace + is_array_api_strict_namespace + """ + return xp.__name__ == "ndonnx" + + +@lru_cache(100) +def is_dask_namespace(xp: Namespace) -> bool: + """ + Returns True if `xp` is a Dask namespace. + + This includes both ``dask.array`` itself and the version wrapped by array-api-compat. + + See Also + -------- + + array_namespace + is_numpy_namespace + is_cupy_namespace + is_torch_namespace + is_ndonnx_namespace + is_jax_namespace + is_pydata_sparse_namespace + is_array_api_strict_namespace + """ + return xp.__name__ in {"dask.array", _compat_module_name() + ".dask.array"} + + +def is_jax_namespace(xp: Namespace) -> bool: + """ + Returns True if `xp` is a JAX namespace. + + This includes ``jax.numpy`` and ``jax.experimental.array_api`` which existed in + older versions of JAX. + + See Also + -------- + + array_namespace + is_numpy_namespace + is_cupy_namespace + is_torch_namespace + is_ndonnx_namespace + is_dask_namespace + is_pydata_sparse_namespace + is_array_api_strict_namespace + """ + return xp.__name__ in {"jax.numpy", "jax.experimental.array_api"} + + +def is_pydata_sparse_namespace(xp: Namespace) -> bool: + """ + Returns True if `xp` is a pydata/sparse namespace. + + See Also + -------- + + array_namespace + is_numpy_namespace + is_cupy_namespace + is_torch_namespace + is_ndonnx_namespace + is_dask_namespace + is_jax_namespace + is_array_api_strict_namespace + """ + return xp.__name__ == "sparse" + + +def is_array_api_strict_namespace(xp: Namespace) -> bool: + """ + Returns True if `xp` is an array-api-strict namespace. + + See Also + -------- + + array_namespace + is_numpy_namespace + is_cupy_namespace + is_torch_namespace + is_ndonnx_namespace + is_dask_namespace + is_jax_namespace + is_pydata_sparse_namespace + """ + return xp.__name__ == "array_api_strict" + + +def _check_api_version(api_version: str | None) -> None: + if api_version in _API_VERSIONS_OLD: + warnings.warn( + f"The {api_version} version of the array API specification was requested but the returned namespace is actually version 2024.12" + ) + elif api_version is not None and api_version not in _API_VERSIONS: + raise ValueError( + "Only the 2024.12 version of the array API specification is currently supported" + ) + + +class _ClsToXPInfo(enum.Enum): + SCALAR = 0 + MAYBE_JAX_ZERO_GRADIENT = 1 + + +@lru_cache(100) +def _cls_to_namespace( + cls: type, + api_version: str | None, + use_compat: bool | None, +) -> tuple[Namespace | None, _ClsToXPInfo | None]: + if use_compat not in (None, True, False): + raise ValueError("use_compat must be None, True, or False") + _use_compat = use_compat in (None, True) + cls_ = cast(Hashable, cls) # Make mypy happy + + if ( + _issubclass_fast(cls_, "numpy", "ndarray") + or _issubclass_fast(cls_, "numpy", "generic") + ): + if use_compat is True: + _check_api_version(api_version) + from .. import numpy as xp + elif use_compat is False: + import numpy as xp # type: ignore[no-redef] + else: + # NumPy 2.0+ have __array_namespace__; however they are not + # yet fully array API compatible. + from .. import numpy as xp # type: ignore[no-redef] + return xp, _ClsToXPInfo.MAYBE_JAX_ZERO_GRADIENT + + # Note: this must happen _after_ the test for np.generic, + # because np.float64 and np.complex128 are subclasses of float and complex. + if issubclass(cls, int | float | complex | type(None)): + return None, _ClsToXPInfo.SCALAR + + if _issubclass_fast(cls_, "cupy", "ndarray"): + if _use_compat: + _check_api_version(api_version) + from .. import cupy as xp # type: ignore[no-redef] + else: + import cupy as xp # type: ignore[no-redef] + return xp, None + + if _issubclass_fast(cls_, "torch", "Tensor"): + if _use_compat: + _check_api_version(api_version) + from .. import torch as xp # type: ignore[no-redef] + else: + import torch as xp # type: ignore[no-redef] + return xp, None + + if _issubclass_fast(cls_, "dask.array", "Array"): + if _use_compat: + _check_api_version(api_version) + from ..dask import array as xp # type: ignore[no-redef] + else: + import dask.array as xp # type: ignore[no-redef] + return xp, None + + # Backwards compatibility for jax<0.4.32 + if _issubclass_fast(cls_, "jax", "Array"): + return _jax_namespace(api_version, use_compat), None + + return None, None + + +def _jax_namespace(api_version: str | None, use_compat: bool | None) -> Namespace: + if use_compat: + raise ValueError("JAX does not have an array-api-compat wrapper") + import jax.numpy as jnp + if not hasattr(jnp, "__array_namespace_info__"): + # JAX v0.4.32 and newer implements the array API directly in jax.numpy. + # For older JAX versions, it is available via jax.experimental.array_api. + # jnp.Array objects gain the __array_namespace__ method. + import jax.experimental.array_api # noqa: F401 + # Test api_version + return jnp.empty(0).__array_namespace__(api_version=api_version) + + +def array_namespace( + *xs: Array | complex | None, + api_version: str | None = None, + use_compat: bool | None = None, +) -> Namespace: + """ + Get the array API compatible namespace for the arrays `xs`. + + Parameters + ---------- + xs: arrays + one or more arrays. xs can also be Python scalars (bool, int, float, + complex, or None), which are ignored. + + api_version: str + The newest version of the spec that you need support for (currently + the compat library wrapped APIs support v2024.12). + + use_compat: bool or None + If None (the default), the native namespace will be returned if it is + already array API compatible, otherwise a compat wrapper is used. If + True, the compat library wrapped library will be returned. If False, + the native library namespace is returned. + + Returns + ------- + + out: namespace + The array API compatible namespace corresponding to the arrays in `xs`. + + Raises + ------ + TypeError + If `xs` contains arrays from different array libraries or contains a + non-array. + + + Typical usage is to pass the arguments of a function to + `array_namespace()` at the top of a function to get the corresponding + array API namespace: + + .. code:: python + + def your_function(x, y): + xp = array_api_compat.array_namespace(x, y) + # Now use xp as the array library namespace + return xp.mean(x, axis=0) + 2*xp.std(y, axis=0) + + + Wrapped array namespaces can also be imported directly. For example, + `array_namespace(np.array(...))` will return `array_api_compat.numpy`. + This function will also work for any array library not wrapped by + array-api-compat if it explicitly defines `__array_namespace__ + `__ + (the wrapped namespace is always preferred if it exists). + + See Also + -------- + + is_array_api_obj + is_numpy_array + is_cupy_array + is_torch_array + is_dask_array + is_jax_array + is_pydata_sparse_array + + """ + namespaces: set[Namespace] = set() + for x in xs: + xp, info = _cls_to_namespace(cast(Hashable, type(x)), api_version, use_compat) + if info is _ClsToXPInfo.SCALAR: + continue + + if ( + info is _ClsToXPInfo.MAYBE_JAX_ZERO_GRADIENT + and _is_jax_zero_gradient_array(x) + ): + xp = _jax_namespace(api_version, use_compat) + + if xp is None: + get_ns = getattr(x, "__array_namespace__", None) + if get_ns is None: + raise TypeError(f"{type(x).__name__} is not a supported array type") + if use_compat: + raise ValueError( + "The given array does not have an array-api-compat wrapper" + ) + xp = get_ns(api_version=api_version) + + namespaces.add(xp) + + try: + (xp,) = namespaces + return xp + except ValueError: + if not namespaces: + raise TypeError( + "array_namespace requires at least one non-scalar array input" + ) + raise TypeError(f"Multiple namespaces for array inputs: {namespaces}") + + +# backwards compatibility alias +get_namespace = array_namespace + + +def _check_device(bare_xp: Namespace, device: Device) -> None: # pyright: ignore[reportUnusedFunction] + """ + Validate dummy device on device-less array backends. + + Notes + ----- + This function is also invoked by CuPy, which does have multiple devices + if there are multiple GPUs available. + However, CuPy multi-device support is currently impossible + without using the global device or a context manager: + + https://github.com/data-apis/array-api-compat/pull/293 + """ + if bare_xp is sys.modules.get("numpy"): + if device not in ("cpu", None): + raise ValueError(f"Unsupported device for NumPy: {device!r}") + + elif bare_xp is sys.modules.get("dask.array"): + if device not in ("cpu", _DASK_DEVICE, None): + raise ValueError(f"Unsupported device for Dask: {device!r}") + + +# Placeholder object to represent the dask device +# when the array backend is not the CPU. +# (since it is not easy to tell which device a dask array is on) +class _dask_device: + def __repr__(self) -> Literal["DASK_DEVICE"]: + return "DASK_DEVICE" + + +_DASK_DEVICE = _dask_device() + + +# device() is not on numpy.ndarray or dask.array and to_device() is not on numpy.ndarray +# or cupy.ndarray. They are not included in array objects of this library +# because this library just reuses the respective ndarray classes without +# wrapping or subclassing them. These helper functions can be used instead of +# the wrapper functions for libraries that need to support both NumPy/CuPy and +# other libraries that use devices. +def device(x: _ArrayApiObj, /) -> Device: + """ + Hardware device the array data resides on. + + This is equivalent to `x.device` according to the `standard + `__. + This helper is included because some array libraries either do not have + the `device` attribute or include it with an incompatible API. + + Parameters + ---------- + x: array + array instance from an array API compatible library. + + Returns + ------- + out: device + a ``device`` object (see the `Device Support `__ + section of the array API specification). + + Notes + ----- + + For NumPy the device is always `"cpu"`. For Dask, the device is always a + special `DASK_DEVICE` object. + + See Also + -------- + + to_device : Move array data to a different device. + + """ + if is_numpy_array(x): + return "cpu" + elif is_dask_array(x): + # Peek at the metadata of the Dask array to determine type + if is_numpy_array(x._meta): + # Must be on CPU since backed by numpy + return "cpu" + return _DASK_DEVICE + elif is_jax_array(x): + # FIXME Jitted JAX arrays do not have a device attribute + # https://github.com/jax-ml/jax/issues/26000 + # Return None in this case. Note that this workaround breaks + # the standard and will result in new arrays being created on the + # default device instead of the same device as the input array(s). + x_device = getattr(x, "device", None) + # Older JAX releases had .device() as a method, which has been replaced + # with a property in accordance with the standard. + if inspect.ismethod(x_device): + return x_device() + else: + return x_device + elif is_pydata_sparse_array(x): + # `sparse` will gain `.device`, so check for this first. + x_device = getattr(x, "device", None) + if x_device is not None: + return x_device + # Everything but DOK has this attr. + try: + inner = x.data # pyright: ignore + except AttributeError: + return "cpu" + # Return the device of the constituent array + return device(inner) # pyright: ignore + return x.device # type: ignore # pyright: ignore + + +# Prevent shadowing, used below +_device = device + + +# Based on cupy.array_api.Array.to_device +def _cupy_to_device( + x: cp.ndarray, + device: Device, + /, + stream: int | Any | None = None, +) -> cp.ndarray: + import cupy as cp + + if device == "cpu": + # allowing us to use `to_device(x, "cpu")` + # is useful for portable test swapping between + # host and device backends + return x.get() + if not isinstance(device, cp.cuda.Device): + raise TypeError(f"Unsupported device type {device!r}") + + if stream is None: + with device: + return cp.asarray(x) + + # stream can be an int as specified in __dlpack__, or a CuPy stream + if isinstance(stream, int): + stream = cp.cuda.ExternalStream(stream) + elif not isinstance(stream, cp.cuda.Stream): + raise TypeError(f"Unsupported stream type {stream!r}") + + with device, stream: + return cp.asarray(x) + + +def _torch_to_device( + x: torch.Tensor, + device: torch.device | str | int, + /, + stream: int | Any | None = None, +) -> torch.Tensor: + if stream is not None: + raise NotImplementedError + return x.to(device) + + +def to_device(x: Array, device: Device, /, *, stream: int | Any | None = None) -> Array: + """ + Copy the array from the device on which it currently resides to the specified ``device``. + + This is equivalent to `x.to_device(device, stream=stream)` according to + the `standard + `__. + This helper is included because some array libraries do not have the + `to_device` method. + + Parameters + ---------- + + x: array + array instance from an array API compatible library. + + device: device + a ``device`` object (see the `Device Support `__ + section of the array API specification). + + stream: int | Any | None + stream object to use during copy. In addition to the types supported + in ``array.__dlpack__``, implementations may choose to support any + library-specific stream object with the caveat that any code using + such an object would not be portable. + + Returns + ------- + + out: array + an array with the same data and data type as ``x`` and located on the + specified ``device``. + + Notes + ----- + + For NumPy, this function effectively does nothing since the only supported + device is the CPU. For CuPy, this method supports CuPy CUDA + :external+cupy:class:`Device ` and + :external+cupy:class:`Stream ` objects. For PyTorch, + this is the same as :external+torch:meth:`x.to(device) ` + (the ``stream`` argument is not supported in PyTorch). + + See Also + -------- + + device : Hardware device the array data resides on. + + """ + if is_numpy_array(x): + if stream is not None: + raise ValueError("The stream argument to to_device() is not supported") + if device == "cpu": + return x + raise ValueError(f"Unsupported device {device!r}") + elif is_cupy_array(x): + # cupy does not yet have to_device + return _cupy_to_device(x, device, stream=stream) + elif is_torch_array(x): + return _torch_to_device(x, device, stream=stream) + elif is_dask_array(x): + if stream is not None: + raise ValueError("The stream argument to to_device() is not supported") + # TODO: What if our array is on the GPU already? + if device == "cpu": + return x + raise ValueError(f"Unsupported device {device!r}") + elif is_jax_array(x): + if not hasattr(x, "__array_namespace__"): + # In JAX v0.4.31 and older, this import adds to_device method to x... + import jax.experimental.array_api # noqa: F401 # pyright: ignore + + # ... but only on eager JAX. It won't work inside jax.jit. + if not hasattr(x, "to_device"): + return x + return x.to_device(device, stream=stream) + elif is_pydata_sparse_array(x) and device == _device(x): + # Perform trivial check to return the same array if + # device is same instead of err-ing. + return x + return x.to_device(device, stream=stream) # pyright: ignore + + +@overload +def size(x: HasShape[Collection[SupportsIndex]]) -> int: ... +@overload +def size(x: HasShape[Collection[SupportsIndex | None]]) -> int | None: ... +def size(x: HasShape[Collection[SupportsIndex | None]]) -> int | None: + """ + Return the total number of elements of x. + + This is equivalent to `x.size` according to the `standard + `__. + + This helper is included because PyTorch defines `size` in an + :external+torch:meth:`incompatible way `. + It also fixes dask.array's behaviour which returns nan for unknown sizes, whereas + the standard requires None. + """ + # Lazy API compliant arrays, such as ndonnx, can contain None in their shape + if None in x.shape: + return None + out = math.prod(cast("Collection[SupportsIndex]", x.shape)) + # dask.array.Array.shape can contain NaN + return None if math.isnan(out) else out + + +@lru_cache(100) +def _is_writeable_cls(cls: type) -> bool | None: + if ( + _issubclass_fast(cls, "numpy", "generic") + or _issubclass_fast(cls, "jax", "Array") + or _issubclass_fast(cls, "jax.core", "Tracer") # see is_jax_array for limitations + or _issubclass_fast(cls, "sparse", "SparseArray") + ): + return False + if _is_array_api_cls(cls): + return True + return None + + +def is_writeable_array(x: object) -> TypeGuard[_ArrayApiObj]: + """ + Return False if ``x.__setitem__`` is expected to raise; True otherwise. + Return False if `x` is not an array API compatible object. + + Warning + ------- + As there is no standard way to check if an array is writeable without actually + writing to it, this function blindly returns True for all unknown array types. + """ + cls = cast(Hashable, type(x)) + if _issubclass_fast(cls, "numpy", "ndarray"): + return cast("npt.NDArray", x).flags.writeable + res = _is_writeable_cls(cls) + if res is not None: + return res + return hasattr(x, '__array_namespace__') + + +@lru_cache(100) +def _is_lazy_cls(cls: type) -> bool | None: + if ( + _issubclass_fast(cls, "numpy", "ndarray") + or _issubclass_fast(cls, "numpy", "generic") + or _issubclass_fast(cls, "cupy", "ndarray") + or _issubclass_fast(cls, "torch", "Tensor") + or _issubclass_fast(cls, "sparse", "SparseArray") + ): + return False + if ( + _issubclass_fast(cls, "jax", "Array") + or _issubclass_fast(cls, "jax.core", "Tracer") # see is_jax_array for limitations + or _issubclass_fast(cls, "dask.array", "Array") + or _issubclass_fast(cls, "ndonnx", "Array") + ): + return True + return None + + +def is_lazy_array(x: object) -> TypeGuard[_ArrayApiObj]: + """Return True if x is potentially a future or it may be otherwise impossible or + expensive to eagerly read its contents, regardless of their size, e.g. by + calling ``bool(x)`` or ``float(x)``. + + Return False otherwise; e.g. ``bool(x)`` etc. is guaranteed to succeed and to be + cheap as long as the array has the right dtype and size. + + Note + ---- + This function errs on the side of caution for array types that may or may not be + lazy, e.g. JAX arrays, by always returning True for them. + """ + # **JAX note:** while it is possible to determine if you're inside or outside + # jax.jit by testing the subclass of a jax.Array object, as well as testing bool() + # as we do below for unknown arrays, this is not recommended by JAX best practices. + + # **Dask note:** Dask eagerly computes the graph on __bool__, __float__, and so on. + # This behaviour, while impossible to change without breaking backwards + # compatibility, is highly detrimental to performance as the whole graph will end + # up being computed multiple times. + + # Note: skipping reclassification of JAX zero gradient arrays, as one will + # exclusively get them once they leave a jax.grad JIT context. + cls = cast(Hashable, type(x)) + res = _is_lazy_cls(cls) + if res is not None: + return res + + if not hasattr(x, "__array_namespace__"): + return False + + # Unknown Array API compatible object. Note that this test may have dire consequences + # in terms of performance, e.g. for a lazy object that eagerly computes the graph + # on __bool__ (dask is one such example, which however is special-cased above). + + # Select a single point of the array + s = size(cast("HasShape[Collection[SupportsIndex | None]]", x)) + if s is None: + return True + xp = array_namespace(x) + if s > 1: + x = xp.reshape(x, (-1,))[0] + # Cast to dtype=bool and deal with size 0 arrays + x = xp.any(x) + + try: + bool(x) + return False + # The Array API standard dictactes that __bool__ should raise TypeError if the + # output cannot be defined. + # Here we allow for it to raise arbitrary exceptions, e.g. like Dask does. + except Exception: + return True + + +__all__ = [ + "array_namespace", + "device", + "get_namespace", + "is_array_api_obj", + "is_array_api_strict_namespace", + "is_cupy_array", + "is_cupy_namespace", + "is_dask_array", + "is_dask_namespace", + "is_jax_array", + "is_jax_namespace", + "is_numpy_array", + "is_numpy_namespace", + "is_torch_array", + "is_torch_namespace", + "is_ndonnx_array", + "is_ndonnx_namespace", + "is_pydata_sparse_array", + "is_pydata_sparse_namespace", + "is_writeable_array", + "is_lazy_array", + "size", + "to_device", +] + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/_linalg.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/_linalg.py new file mode 100644 index 0000000000000000000000000000000000000000..69672af768d065a3a7507e0a5ea84d6238ff174d --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/_linalg.py @@ -0,0 +1,230 @@ +from __future__ import annotations + +import math +from typing import Literal, NamedTuple, cast + +import numpy as np + +if np.__version__[0] == "2": + from numpy.lib.array_utils import normalize_axis_tuple +else: + from numpy.core.numeric import normalize_axis_tuple # type: ignore[no-redef] + +from .._internal import get_xp +from ._aliases import isdtype, matmul, matrix_transpose, tensordot, vecdot +from ._typing import Array, DType, JustFloat, JustInt, Namespace + + +# These are in the main NumPy namespace but not in numpy.linalg +def cross( + x1: Array, + x2: Array, + /, + xp: Namespace, + *, + axis: int = -1, + **kwargs: object, +) -> Array: + return xp.cross(x1, x2, axis=axis, **kwargs) + +def outer(x1: Array, x2: Array, /, xp: Namespace, **kwargs: object) -> Array: + return xp.outer(x1, x2, **kwargs) + +class EighResult(NamedTuple): + eigenvalues: Array + eigenvectors: Array + +class QRResult(NamedTuple): + Q: Array + R: Array + +class SlogdetResult(NamedTuple): + sign: Array + logabsdet: Array + +class SVDResult(NamedTuple): + U: Array + S: Array + Vh: Array + +# These functions are the same as their NumPy counterparts except they return +# a namedtuple. +def eigh(x: Array, /, xp: Namespace, **kwargs: object) -> EighResult: + return EighResult(*xp.linalg.eigh(x, **kwargs)) + +def qr( + x: Array, + /, + xp: Namespace, + *, + mode: Literal["reduced", "complete"] = "reduced", + **kwargs: object, +) -> QRResult: + return QRResult(*xp.linalg.qr(x, mode=mode, **kwargs)) + +def slogdet(x: Array, /, xp: Namespace, **kwargs: object) -> SlogdetResult: + return SlogdetResult(*xp.linalg.slogdet(x, **kwargs)) + +def svd( + x: Array, + /, + xp: Namespace, + *, + full_matrices: bool = True, + **kwargs: object, +) -> SVDResult: + return SVDResult(*xp.linalg.svd(x, full_matrices=full_matrices, **kwargs)) + +# These functions have additional keyword arguments + +# The upper keyword argument is new from NumPy +def cholesky( + x: Array, + /, + xp: Namespace, + *, + upper: bool = False, + **kwargs: object, +) -> Array: + L = xp.linalg.cholesky(x, **kwargs) + if upper: + U = get_xp(xp)(matrix_transpose)(L) + if get_xp(xp)(isdtype)(U.dtype, 'complex floating'): + U = xp.conj(U) # pyright: ignore[reportConstantRedefinition] + return U + return L + +# The rtol keyword argument of matrix_rank() and pinv() is new from NumPy. +# Note that it has a different semantic meaning from tol and rcond. +def matrix_rank( + x: Array, + /, + xp: Namespace, + *, + rtol: float | Array | None = None, + **kwargs: object, +) -> Array: + # this is different from xp.linalg.matrix_rank, which supports 1 + # dimensional arrays. + if x.ndim < 2: + raise xp.linalg.LinAlgError("1-dimensional array given. Array must be at least two-dimensional") + S: Array = get_xp(xp)(svdvals)(x, **kwargs) + if rtol is None: + tol = S.max(axis=-1, keepdims=True) * max(x.shape[-2:]) * xp.finfo(S.dtype).eps + else: + # this is different from xp.linalg.matrix_rank, which does not + # multiply the tolerance by the largest singular value. + tol = S.max(axis=-1, keepdims=True)*xp.asarray(rtol)[..., xp.newaxis] + return xp.count_nonzero(S > tol, axis=-1) + +def pinv( + x: Array, + /, + xp: Namespace, + *, + rtol: float | Array | None = None, + **kwargs: object, +) -> Array: + # this is different from xp.linalg.pinv, which does not multiply the + # default tolerance by max(M, N). + if rtol is None: + rtol = max(x.shape[-2:]) * xp.finfo(x.dtype).eps + return xp.linalg.pinv(x, rcond=rtol, **kwargs) + +# These functions are new in the array API spec + +def matrix_norm( + x: Array, + /, + xp: Namespace, + *, + keepdims: bool = False, + ord: Literal[1, 2, -1, -2] | JustFloat | Literal["fro", "nuc"] | None = "fro", +) -> Array: + return xp.linalg.norm(x, axis=(-2, -1), keepdims=keepdims, ord=ord) + +# svdvals is not in NumPy (but it is in SciPy). It is equivalent to +# xp.linalg.svd(compute_uv=False). +def svdvals(x: Array, /, xp: Namespace) -> Array | tuple[Array, ...]: + return xp.linalg.svd(x, compute_uv=False) + +def vector_norm( + x: Array, + /, + xp: Namespace, + *, + axis: int | tuple[int, ...] | None = None, + keepdims: bool = False, + ord: JustInt | JustFloat = 2, +) -> Array: + # xp.linalg.norm tries to do a matrix norm whenever axis is a 2-tuple or + # when axis=None and the input is 2-D, so to force a vector norm, we make + # it so the input is 1-D (for axis=None), or reshape so that norm is done + # on a single dimension. + if axis is None: + # Note: xp.linalg.norm() doesn't handle 0-D arrays + _x = x.ravel() + _axis = 0 + elif isinstance(axis, tuple): + # Note: The axis argument supports any number of axes, whereas + # xp.linalg.norm() only supports a single axis for vector norm. + normalized_axis = cast( + "tuple[int, ...]", + normalize_axis_tuple(axis, x.ndim), # pyright: ignore[reportCallIssue] + ) + rest = tuple(i for i in range(x.ndim) if i not in normalized_axis) + newshape = axis + rest + _x = xp.transpose(x, newshape).reshape( + (math.prod([x.shape[i] for i in axis]), *[x.shape[i] for i in rest])) + _axis = 0 + else: + _x = x + _axis = axis + + res = xp.linalg.norm(_x, axis=_axis, ord=ord) + + if keepdims: + # We can't reuse xp.linalg.norm(keepdims) because of the reshape hacks + # above to avoid matrix norm logic. + shape = list(x.shape) + axes = cast( + "tuple[int, ...]", + normalize_axis_tuple( # pyright: ignore[reportCallIssue] + range(x.ndim) if axis is None else axis, + x.ndim, + ), + ) + for i in axes: + shape[i] = 1 + res = xp.reshape(res, tuple(shape)) + + return res + +# xp.diagonal and xp.trace operate on the first two axes whereas these +# operates on the last two + +def diagonal(x: Array, /, xp: Namespace, *, offset: int = 0, **kwargs: object) -> Array: + return xp.diagonal(x, offset=offset, axis1=-2, axis2=-1, **kwargs) + +def trace( + x: Array, + /, + xp: Namespace, + *, + offset: int = 0, + dtype: DType | None = None, + **kwargs: object, +) -> Array: + return xp.asarray( + xp.trace(x, offset=offset, dtype=dtype, axis1=-2, axis2=-1, **kwargs) + ) + +__all__ = ['cross', 'matmul', 'outer', 'tensordot', 'EighResult', + 'QRResult', 'SlogdetResult', 'SVDResult', 'eigh', 'qr', 'slogdet', + 'svd', 'cholesky', 'matrix_rank', 'pinv', 'matrix_norm', + 'matrix_transpose', 'svdvals', 'vecdot', 'vector_norm', 'diagonal', + 'trace'] + + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/_typing.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/_typing.py new file mode 100644 index 0000000000000000000000000000000000000000..11b00bd10395f43bf71e008d09aad5dffaf2f98a --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/common/_typing.py @@ -0,0 +1,189 @@ +from __future__ import annotations + +from collections.abc import Mapping +from types import ModuleType as Namespace +from typing import ( + TYPE_CHECKING, + Literal, + Protocol, + TypeAlias, + TypedDict, + TypeVar, + final, +) + +if TYPE_CHECKING: + from _typeshed import Incomplete + + SupportsBufferProtocol: TypeAlias = Incomplete + Array: TypeAlias = Incomplete + Device: TypeAlias = Incomplete + DType: TypeAlias = Incomplete +else: + SupportsBufferProtocol = object + Array = object + Device = object + DType = object + + +_T_co = TypeVar("_T_co", covariant=True) + + +# These "Just" types are equivalent to the `Just` type from the `optype` library, +# apart from them not being `@runtime_checkable`. +# - docs: https://github.com/jorenham/optype/blob/master/README.md#just +# - code: https://github.com/jorenham/optype/blob/master/optype/_core/_just.py +@final +class JustInt(Protocol): # type: ignore[misc] + @property # type: ignore[override] + def __class__(self, /) -> type[int]: ... + @__class__.setter + def __class__(self, value: type[int], /) -> None: ... # pyright: ignore[reportIncompatibleMethodOverride] + + +@final +class JustFloat(Protocol): # type: ignore[misc] + @property # type: ignore[override] + def __class__(self, /) -> type[float]: ... + @__class__.setter + def __class__(self, value: type[float], /) -> None: ... # pyright: ignore[reportIncompatibleMethodOverride] + + +@final +class JustComplex(Protocol): # type: ignore[misc] + @property # type: ignore[override] + def __class__(self, /) -> type[complex]: ... + @__class__.setter + def __class__(self, value: type[complex], /) -> None: ... # pyright: ignore[reportIncompatibleMethodOverride] + + +class NestedSequence(Protocol[_T_co]): + def __getitem__(self, key: int, /) -> _T_co | NestedSequence[_T_co]: ... + def __len__(self, /) -> int: ... + + +class SupportsArrayNamespace(Protocol[_T_co]): + def __array_namespace__(self, /, *, api_version: str | None) -> _T_co: ... + + +class HasShape(Protocol[_T_co]): + @property + def shape(self, /) -> _T_co: ... + + +# Return type of `__array_namespace_info__.default_dtypes` +Capabilities = TypedDict( + "Capabilities", + { + "boolean indexing": bool, + "data-dependent shapes": bool, + "max dimensions": int, + }, +) + +# Return type of `__array_namespace_info__.default_dtypes` +DefaultDTypes = TypedDict( + "DefaultDTypes", + { + "real floating": DType, + "complex floating": DType, + "integral": DType, + "indexing": DType, + }, +) + + +_DTypeKind: TypeAlias = Literal[ + "bool", + "signed integer", + "unsigned integer", + "integral", + "real floating", + "complex floating", + "numeric", +] +# Type of the `kind` parameter in `__array_namespace_info__.dtypes` +DTypeKind: TypeAlias = _DTypeKind | tuple[_DTypeKind, ...] + + +# `__array_namespace_info__.dtypes(kind="bool")` +class DTypesBool(TypedDict): + bool: DType + + +# `__array_namespace_info__.dtypes(kind="signed integer")` +class DTypesSigned(TypedDict): + int8: DType + int16: DType + int32: DType + int64: DType + + +# `__array_namespace_info__.dtypes(kind="unsigned integer")` +class DTypesUnsigned(TypedDict): + uint8: DType + uint16: DType + uint32: DType + uint64: DType + + +# `__array_namespace_info__.dtypes(kind="integral")` +class DTypesIntegral(DTypesSigned, DTypesUnsigned): + pass + + +# `__array_namespace_info__.dtypes(kind="real floating")` +class DTypesReal(TypedDict): + float32: DType + float64: DType + + +# `__array_namespace_info__.dtypes(kind="complex floating")` +class DTypesComplex(TypedDict): + complex64: DType + complex128: DType + + +# `__array_namespace_info__.dtypes(kind="numeric")` +class DTypesNumeric(DTypesIntegral, DTypesReal, DTypesComplex): + pass + + +# `__array_namespace_info__.dtypes(kind=None)` (default) +class DTypesAll(DTypesBool, DTypesNumeric): + pass + + +# `__array_namespace_info__.dtypes(kind=?)` (fallback) +DTypesAny: TypeAlias = Mapping[str, DType] + + +__all__ = [ + "Array", + "Capabilities", + "DType", + "DTypeKind", + "DTypesAny", + "DTypesAll", + "DTypesBool", + "DTypesNumeric", + "DTypesIntegral", + "DTypesSigned", + "DTypesUnsigned", + "DTypesReal", + "DTypesComplex", + "DefaultDTypes", + "Device", + "HasShape", + "Namespace", + "JustInt", + "JustFloat", + "JustComplex", + "NestedSequence", + "SupportsArrayNamespace", + "SupportsBufferProtocol", +] + + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..af003c5adaa52992bb673259d882098a499753e9 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__init__.py @@ -0,0 +1,24 @@ +from typing import Final +from cupy import * # noqa: F403 + +# from cupy import * doesn't overwrite these builtin names +from cupy import abs, max, min, round # noqa: F401 + +# These imports may overwrite names from the import * above. +from ._aliases import * # noqa: F403 +from ._info import __array_namespace_info__ # noqa: F401 + +# See the comment in the numpy __init__.py +__import__(__package__ + '.linalg') +__import__(__package__ + '.fft') + +__array_api_version__: Final = '2024.12' + +__all__ = sorted( + {name for name in globals() if not name.startswith("__")} + - {"Final", "_aliases", "_info", "_typing"} + | {"__array_api_version__", "__array_namespace_info__", "linalg", "fft"} +) + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e0709cb578facfaba02223727b01e5fb3f82dbf0 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/_aliases.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/_aliases.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0bfea73086b87267345df782d42f3e6c3c5c64c1 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/_aliases.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/_info.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/_info.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b21ef2c9b543abd1fd8ab54dbe56e9275fc2a6d5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/_info.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/_typing.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/_typing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f10da1ac423495aaeda83fb869cbb7a2f0ae3286 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/_typing.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/fft.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/fft.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0cfc234d40ff72831866879c4ec833f56848db9e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/fft.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/linalg.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/linalg.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3ccfa076a6b72170ed57e80df6fff27f6626eb9d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/__pycache__/linalg.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/_aliases.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/_aliases.py new file mode 100644 index 0000000000000000000000000000000000000000..2e512fc896399bae466f3b9a7803ce280c06f551 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/_aliases.py @@ -0,0 +1,168 @@ +from __future__ import annotations + +from builtins import bool as py_bool + +import cupy as cp + +from ..common import _aliases, _helpers +from ..common._typing import NestedSequence, SupportsBufferProtocol +from .._internal import get_xp +from ._typing import Array, Device, DType + +bool = cp.bool_ + +# Basic renames +acos = cp.arccos +acosh = cp.arccosh +asin = cp.arcsin +asinh = cp.arcsinh +atan = cp.arctan +atan2 = cp.arctan2 +atanh = cp.arctanh +bitwise_left_shift = cp.left_shift +bitwise_invert = cp.invert +bitwise_right_shift = cp.right_shift +concat = cp.concatenate +pow = cp.power + +arange = get_xp(cp)(_aliases.arange) +empty = get_xp(cp)(_aliases.empty) +empty_like = get_xp(cp)(_aliases.empty_like) +eye = get_xp(cp)(_aliases.eye) +full = get_xp(cp)(_aliases.full) +full_like = get_xp(cp)(_aliases.full_like) +linspace = get_xp(cp)(_aliases.linspace) +ones = get_xp(cp)(_aliases.ones) +ones_like = get_xp(cp)(_aliases.ones_like) +zeros = get_xp(cp)(_aliases.zeros) +zeros_like = get_xp(cp)(_aliases.zeros_like) +UniqueAllResult = get_xp(cp)(_aliases.UniqueAllResult) +UniqueCountsResult = get_xp(cp)(_aliases.UniqueCountsResult) +UniqueInverseResult = get_xp(cp)(_aliases.UniqueInverseResult) +unique_all = get_xp(cp)(_aliases.unique_all) +unique_counts = get_xp(cp)(_aliases.unique_counts) +unique_inverse = get_xp(cp)(_aliases.unique_inverse) +unique_values = get_xp(cp)(_aliases.unique_values) +std = get_xp(cp)(_aliases.std) +var = get_xp(cp)(_aliases.var) +cumulative_sum = get_xp(cp)(_aliases.cumulative_sum) +cumulative_prod = get_xp(cp)(_aliases.cumulative_prod) +clip = get_xp(cp)(_aliases.clip) +permute_dims = get_xp(cp)(_aliases.permute_dims) +reshape = get_xp(cp)(_aliases.reshape) +argsort = get_xp(cp)(_aliases.argsort) +sort = get_xp(cp)(_aliases.sort) +nonzero = get_xp(cp)(_aliases.nonzero) +matmul = get_xp(cp)(_aliases.matmul) +matrix_transpose = get_xp(cp)(_aliases.matrix_transpose) +tensordot = get_xp(cp)(_aliases.tensordot) +sign = get_xp(cp)(_aliases.sign) +finfo = get_xp(cp)(_aliases.finfo) +iinfo = get_xp(cp)(_aliases.iinfo) + + +# asarray also adds the copy keyword, which is not present in numpy 1.0. +def asarray( + obj: Array | complex | NestedSequence[complex] | SupportsBufferProtocol, + /, + *, + dtype: DType | None = None, + device: Device | None = None, + copy: py_bool | None = None, + **kwargs: object, +) -> Array: + """ + Array API compatibility wrapper for asarray(). + + See the corresponding documentation in the array library and/or the array API + specification for more details. + """ + with cp.cuda.Device(device): + if copy is None: + return cp.asarray(obj, dtype=dtype, **kwargs) + else: + res = cp.array(obj, dtype=dtype, copy=copy, **kwargs) + if not copy and res is not obj: + raise ValueError("Unable to avoid copy while creating an array as requested") + return res + + +def astype( + x: Array, + dtype: DType, + /, + *, + copy: py_bool = True, + device: Device | None = None, +) -> Array: + if device is None: + return x.astype(dtype=dtype, copy=copy) + out = _helpers.to_device(x.astype(dtype=dtype, copy=False), device) + return out.copy() if copy and out is x else out + + +# cupy.count_nonzero does not have keepdims +def count_nonzero( + x: Array, + axis: int | tuple[int, ...] | None = None, + keepdims: py_bool = False, +) -> Array: + result = cp.count_nonzero(x, axis) + if keepdims: + if axis is None: + return cp.reshape(result, [1]*x.ndim) + return cp.expand_dims(result, axis) + return result + +# ceil, floor, and trunc return integers for integer inputs + +def ceil(x: Array, /) -> Array: + if cp.issubdtype(x.dtype, cp.integer): + return x.copy() + return cp.ceil(x) + + +def floor(x: Array, /) -> Array: + if cp.issubdtype(x.dtype, cp.integer): + return x.copy() + return cp.floor(x) + + +def trunc(x: Array, /) -> Array: + if cp.issubdtype(x.dtype, cp.integer): + return x.copy() + return cp.trunc(x) + + +# take_along_axis: axis defaults to -1 but in cupy (and numpy) axis is a required arg +def take_along_axis(x: Array, indices: Array, /, *, axis: int = -1) -> Array: + return cp.take_along_axis(x, indices, axis=axis) + + +# These functions are completely new here. If the library already has them +# (i.e., numpy 2.0), use the library version instead of our wrapper. +if hasattr(cp, 'vecdot'): + vecdot = cp.vecdot +else: + vecdot = get_xp(cp)(_aliases.vecdot) + +if hasattr(cp, 'isdtype'): + isdtype = cp.isdtype +else: + isdtype = get_xp(cp)(_aliases.isdtype) + +if hasattr(cp, 'unstack'): + unstack = cp.unstack +else: + unstack = get_xp(cp)(_aliases.unstack) + +__all__ = _aliases.__all__ + ['asarray', 'astype', + 'acos', 'acosh', 'asin', 'asinh', 'atan', + 'atan2', 'atanh', 'bitwise_left_shift', + 'bitwise_invert', 'bitwise_right_shift', + 'bool', 'concat', 'count_nonzero', 'pow', 'sign', + 'ceil', 'floor', 'trunc', 'take_along_axis'] + + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/_info.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/_info.py new file mode 100644 index 0000000000000000000000000000000000000000..78e48a3358cf547a9a77c5ebdc95fa81c3d4e144 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/_info.py @@ -0,0 +1,336 @@ +""" +Array API Inspection namespace + +This is the namespace for inspection functions as defined by the array API +standard. See +https://data-apis.org/array-api/latest/API_specification/inspection.html for +more details. + +""" +from cupy import ( + dtype, + cuda, + bool_ as bool, + intp, + int8, + int16, + int32, + int64, + uint8, + uint16, + uint32, + uint64, + float32, + float64, + complex64, + complex128, +) + + +class __array_namespace_info__: + """ + Get the array API inspection namespace for CuPy. + + The array API inspection namespace defines the following functions: + + - capabilities() + - default_device() + - default_dtypes() + - dtypes() + - devices() + + See + https://data-apis.org/array-api/latest/API_specification/inspection.html + for more details. + + Returns + ------- + info : ModuleType + The array API inspection namespace for CuPy. + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.default_dtypes() + {'real floating': cupy.float64, + 'complex floating': cupy.complex128, + 'integral': cupy.int64, + 'indexing': cupy.int64} + + """ + + __module__ = 'cupy' + + def capabilities(self): + """ + Return a dictionary of array API library capabilities. + + The resulting dictionary has the following keys: + + - **"boolean indexing"**: boolean indicating whether an array library + supports boolean indexing. Always ``True`` for CuPy. + + - **"data-dependent shapes"**: boolean indicating whether an array + library supports data-dependent output shapes. Always ``True`` for + CuPy. + + See + https://data-apis.org/array-api/latest/API_specification/generated/array_api.info.capabilities.html + for more details. + + See Also + -------- + __array_namespace_info__.default_device, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.dtypes, + __array_namespace_info__.devices + + Returns + ------- + capabilities : dict + A dictionary of array API library capabilities. + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.capabilities() + {'boolean indexing': True, + 'data-dependent shapes': True, + 'max dimensions': 64} + + """ + return { + "boolean indexing": True, + "data-dependent shapes": True, + "max dimensions": 64, + } + + def default_device(self): + """ + The default device used for new CuPy arrays. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.dtypes, + __array_namespace_info__.devices + + Returns + ------- + device : Device + The default device used for new CuPy arrays. + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.default_device() + Device(0) + + Notes + ----- + This method returns the static default device when CuPy is initialized. + However, the *current* device used by creation functions (``empty`` etc.) + can be changed globally or with a context manager. + + See Also + -------- + https://github.com/data-apis/array-api/issues/835 + """ + return cuda.Device(0) + + def default_dtypes(self, *, device=None): + """ + The default data types used for new CuPy arrays. + + For CuPy, this always returns the following dictionary: + + - **"real floating"**: ``cupy.float64`` + - **"complex floating"**: ``cupy.complex128`` + - **"integral"**: ``cupy.intp`` + - **"indexing"**: ``cupy.intp`` + + Parameters + ---------- + device : str, optional + The device to get the default data types for. + + Returns + ------- + dtypes : dict + A dictionary describing the default data types used for new CuPy + arrays. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_device, + __array_namespace_info__.dtypes, + __array_namespace_info__.devices + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.default_dtypes() + {'real floating': cupy.float64, + 'complex floating': cupy.complex128, + 'integral': cupy.int64, + 'indexing': cupy.int64} + + """ + # TODO: Does this depend on device? + return { + "real floating": dtype(float64), + "complex floating": dtype(complex128), + "integral": dtype(intp), + "indexing": dtype(intp), + } + + def dtypes(self, *, device=None, kind=None): + """ + The array API data types supported by CuPy. + + Note that this function only returns data types that are defined by + the array API. + + Parameters + ---------- + device : str, optional + The device to get the data types for. + kind : str or tuple of str, optional + The kind of data types to return. If ``None``, all data types are + returned. If a string, only data types of that kind are returned. + If a tuple, a dictionary containing the union of the given kinds + is returned. The following kinds are supported: + + - ``'bool'``: boolean data types (i.e., ``bool``). + - ``'signed integer'``: signed integer data types (i.e., ``int8``, + ``int16``, ``int32``, ``int64``). + - ``'unsigned integer'``: unsigned integer data types (i.e., + ``uint8``, ``uint16``, ``uint32``, ``uint64``). + - ``'integral'``: integer data types. Shorthand for ``('signed + integer', 'unsigned integer')``. + - ``'real floating'``: real-valued floating-point data types + (i.e., ``float32``, ``float64``). + - ``'complex floating'``: complex floating-point data types (i.e., + ``complex64``, ``complex128``). + - ``'numeric'``: numeric data types. Shorthand for ``('integral', + 'real floating', 'complex floating')``. + + Returns + ------- + dtypes : dict + A dictionary mapping the names of data types to the corresponding + CuPy data types. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_device, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.devices + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.dtypes(kind='signed integer') + {'int8': cupy.int8, + 'int16': cupy.int16, + 'int32': cupy.int32, + 'int64': cupy.int64} + + """ + # TODO: Does this depend on device? + if kind is None: + return { + "bool": dtype(bool), + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + "float32": dtype(float32), + "float64": dtype(float64), + "complex64": dtype(complex64), + "complex128": dtype(complex128), + } + if kind == "bool": + return {"bool": bool} + if kind == "signed integer": + return { + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + } + if kind == "unsigned integer": + return { + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + } + if kind == "integral": + return { + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + } + if kind == "real floating": + return { + "float32": dtype(float32), + "float64": dtype(float64), + } + if kind == "complex floating": + return { + "complex64": dtype(complex64), + "complex128": dtype(complex128), + } + if kind == "numeric": + return { + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + "float32": dtype(float32), + "float64": dtype(float64), + "complex64": dtype(complex64), + "complex128": dtype(complex128), + } + if isinstance(kind, tuple): + res = {} + for k in kind: + res.update(self.dtypes(kind=k)) + return res + raise ValueError(f"unsupported kind: {kind!r}") + + def devices(self): + """ + The devices supported by CuPy. + + Returns + ------- + devices : list[Device] + The devices supported by CuPy. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_device, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.dtypes + + """ + return [cuda.Device(i) for i in range(cuda.runtime.getDeviceCount())] diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/_typing.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/_typing.py new file mode 100644 index 0000000000000000000000000000000000000000..e5c202dc53e097936671115943072ad58dd8d389 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/_typing.py @@ -0,0 +1,30 @@ +from __future__ import annotations + +__all__ = ["Array", "DType", "Device"] + +from typing import TYPE_CHECKING + +import cupy as cp +from cupy import ndarray as Array +from cupy.cuda.device import Device + +if TYPE_CHECKING: + # NumPy 1.x on Python 3.10 fails to parse np.dtype[] + DType = cp.dtype[ + cp.intp + | cp.int8 + | cp.int16 + | cp.int32 + | cp.int64 + | cp.uint8 + | cp.uint16 + | cp.uint32 + | cp.uint64 + | cp.float32 + | cp.float64 + | cp.complex64 + | cp.complex128 + | cp.bool_ + ] +else: + DType = cp.dtype diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/fft.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/fft.py new file mode 100644 index 0000000000000000000000000000000000000000..53a9a45438651bc2adc7bc19884fe9361ef99580 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/fft.py @@ -0,0 +1,36 @@ +from cupy.fft import * # noqa: F403 + +# cupy.fft doesn't have __all__. If it is added, replace this with +# +# from cupy.fft import __all__ as linalg_all +_n: dict[str, object] = {} +exec("from cupy.fft import *", _n) +del _n["__builtins__"] +fft_all = list(_n) +del _n + +from ..common import _fft +from .._internal import get_xp + +import cupy as cp + +fft = get_xp(cp)(_fft.fft) +ifft = get_xp(cp)(_fft.ifft) +fftn = get_xp(cp)(_fft.fftn) +ifftn = get_xp(cp)(_fft.ifftn) +rfft = get_xp(cp)(_fft.rfft) +irfft = get_xp(cp)(_fft.irfft) +rfftn = get_xp(cp)(_fft.rfftn) +irfftn = get_xp(cp)(_fft.irfftn) +hfft = get_xp(cp)(_fft.hfft) +ihfft = get_xp(cp)(_fft.ihfft) +fftfreq = get_xp(cp)(_fft.fftfreq) +rfftfreq = get_xp(cp)(_fft.rfftfreq) +fftshift = get_xp(cp)(_fft.fftshift) +ifftshift = get_xp(cp)(_fft.ifftshift) + +__all__ = fft_all + _fft.__all__ + +def __dir__() -> list[str]: + return __all__ + diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/linalg.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/linalg.py new file mode 100644 index 0000000000000000000000000000000000000000..da301574728a70665dbb6728488ac2ce75e619e0 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/cupy/linalg.py @@ -0,0 +1,47 @@ +from cupy.linalg import * # noqa: F403 +# cupy.linalg doesn't have __all__. If it is added, replace this with +# +# from cupy.linalg import __all__ as linalg_all +_n: dict[str, object] = {} +exec('from cupy.linalg import *', _n) +del _n['__builtins__'] +linalg_all = list(_n) +del _n + +from ..common import _linalg +from .._internal import get_xp + +import cupy as cp + +# These functions are in both the main and linalg namespaces +from ._aliases import matmul, matrix_transpose, tensordot, vecdot # noqa: F401 + +cross = get_xp(cp)(_linalg.cross) +outer = get_xp(cp)(_linalg.outer) +EighResult = _linalg.EighResult +QRResult = _linalg.QRResult +SlogdetResult = _linalg.SlogdetResult +SVDResult = _linalg.SVDResult +eigh = get_xp(cp)(_linalg.eigh) +qr = get_xp(cp)(_linalg.qr) +slogdet = get_xp(cp)(_linalg.slogdet) +svd = get_xp(cp)(_linalg.svd) +cholesky = get_xp(cp)(_linalg.cholesky) +matrix_rank = get_xp(cp)(_linalg.matrix_rank) +pinv = get_xp(cp)(_linalg.pinv) +matrix_norm = get_xp(cp)(_linalg.matrix_norm) +svdvals = get_xp(cp)(_linalg.svdvals) +diagonal = get_xp(cp)(_linalg.diagonal) +trace = get_xp(cp)(_linalg.trace) + +# These functions are completely new here. If the library already has them +# (i.e., numpy 2.0), use the library version instead of our wrapper. +if hasattr(cp.linalg, 'vector_norm'): + vector_norm = cp.linalg.vector_norm +else: + vector_norm = get_xp(cp)(_linalg.vector_norm) + +__all__ = linalg_all + _linalg.__all__ + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d481ea7ca6336d7c3836aa83ee3044f9dd59f7d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..f78aa8b378444aa486519b06f6d81daa45cb8f67 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__init__.py @@ -0,0 +1,26 @@ +from typing import Final + +from ..._internal import clone_module + +__all__ = clone_module("dask.array", globals()) + +# These imports may overwrite names from the import * above. +from . import _aliases +from ._aliases import * # type: ignore[assignment] # noqa: F403 +from ._info import __array_namespace_info__ # noqa: F401 + +__array_api_version__: Final = "2024.12" +del Final + +# See the comment in the numpy __init__.py +__import__(__package__ + '.linalg') +__import__(__package__ + '.fft') + +__all__ = sorted( + set(__all__) + | set(_aliases.__all__) + | {"__array_api_version__", "__array_namespace_info__", "linalg", "fft"} +) + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b1f901ced158bb07f93004b587a1888742180f72 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__pycache__/_aliases.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__pycache__/_aliases.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce67eadb3514f861a26b2d15c0469bc91d086fd4 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__pycache__/_aliases.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__pycache__/_info.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__pycache__/_info.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..be769b20aec9748cd38c98b31b8369afb49c44e2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__pycache__/_info.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__pycache__/fft.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__pycache__/fft.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..44abcccf907aa2dff36e1e2bf5221cb30364d992 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__pycache__/fft.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__pycache__/linalg.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__pycache__/linalg.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d1dfbd79ed1d24529b9d7619d585fca4ecf61595 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/__pycache__/linalg.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/_aliases.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/_aliases.py new file mode 100644 index 0000000000000000000000000000000000000000..54d323b2a5b6fd933ce8db39e584dff4877a2daa --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/_aliases.py @@ -0,0 +1,369 @@ +# pyright: reportPrivateUsage=false +# pyright: reportUnknownArgumentType=false +# pyright: reportUnknownMemberType=false +# pyright: reportUnknownVariableType=false + +from __future__ import annotations + +from builtins import bool as py_bool +from collections.abc import Callable +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from typing_extensions import TypeIs + +import dask.array as da +import numpy as np +from numpy import bool_ as bool +from numpy import ( + can_cast, + complex64, + complex128, + float32, + float64, + int8, + int16, + int32, + int64, + result_type, + uint8, + uint16, + uint32, + uint64, +) + +from ..._internal import get_xp +from ...common import _aliases, _helpers, array_namespace +from ...common._typing import ( + Array, + Device, + DType, + NestedSequence, + SupportsBufferProtocol, +) + +isdtype = get_xp(np)(_aliases.isdtype) +unstack = get_xp(da)(_aliases.unstack) + + +# da.astype doesn't respect copy=True +def astype( + x: Array, + dtype: DType, + /, + *, + copy: py_bool = True, + device: Device | None = None, +) -> Array: + """ + Array API compatibility wrapper for astype(). + + See the corresponding documentation in the array library and/or the array API + specification for more details. + """ + # TODO: respect device keyword? + _helpers._check_device(da, device) + + if not copy and dtype == x.dtype: + return x + x = x.astype(dtype) + return x.copy() if copy else x + + +# Common aliases + + +# This arange func is modified from the common one to +# not pass stop/step as keyword arguments, which will cause +# an error with dask +def arange( + start: float, + /, + stop: float | None = None, + step: float = 1, + *, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object, +) -> Array: + """ + Array API compatibility wrapper for arange(). + + See the corresponding documentation in the array library and/or the array API + specification for more details. + """ + # TODO: respect device keyword? + _helpers._check_device(da, device) + + args: list[Any] = [start] + if stop is not None: + args.append(stop) + else: + # stop is None, so start is actually stop + # prepend the default value for start which is 0 + args.insert(0, 0) + args.append(step) + + return da.arange(*args, dtype=dtype, **kwargs) + + +eye = get_xp(da)(_aliases.eye) +linspace = get_xp(da)(_aliases.linspace) +UniqueAllResult = get_xp(da)(_aliases.UniqueAllResult) +UniqueCountsResult = get_xp(da)(_aliases.UniqueCountsResult) +UniqueInverseResult = get_xp(da)(_aliases.UniqueInverseResult) +unique_all = get_xp(da)(_aliases.unique_all) +unique_counts = get_xp(da)(_aliases.unique_counts) +unique_inverse = get_xp(da)(_aliases.unique_inverse) +unique_values = get_xp(da)(_aliases.unique_values) +permute_dims = get_xp(da)(_aliases.permute_dims) +std = get_xp(da)(_aliases.std) +var = get_xp(da)(_aliases.var) +cumulative_sum = get_xp(da)(_aliases.cumulative_sum) +cumulative_prod = get_xp(da)(_aliases.cumulative_prod) +empty = get_xp(da)(_aliases.empty) +empty_like = get_xp(da)(_aliases.empty_like) +full = get_xp(da)(_aliases.full) +full_like = get_xp(da)(_aliases.full_like) +ones = get_xp(da)(_aliases.ones) +ones_like = get_xp(da)(_aliases.ones_like) +zeros = get_xp(da)(_aliases.zeros) +zeros_like = get_xp(da)(_aliases.zeros_like) +reshape = get_xp(da)(_aliases.reshape) +matrix_transpose = get_xp(da)(_aliases.matrix_transpose) +vecdot = get_xp(da)(_aliases.vecdot) +nonzero = get_xp(da)(_aliases.nonzero) +matmul = get_xp(np)(_aliases.matmul) +tensordot = get_xp(np)(_aliases.tensordot) +sign = get_xp(np)(_aliases.sign) +finfo = get_xp(np)(_aliases.finfo) +iinfo = get_xp(np)(_aliases.iinfo) + + +# asarray also adds the copy keyword, which is not present in numpy 1.0. +def asarray( + obj: Array | complex | NestedSequence[complex] | SupportsBufferProtocol, + /, + *, + dtype: DType | None = None, + device: Device | None = None, + copy: py_bool | None = None, + **kwargs: object, +) -> Array: + """ + Array API compatibility wrapper for asarray(). + + See the corresponding documentation in the array library and/or the array API + specification for more details. + """ + # TODO: respect device keyword? + _helpers._check_device(da, device) + + if isinstance(obj, da.Array): + if dtype is not None and dtype != obj.dtype: + if copy is False: + raise ValueError("Unable to avoid copy when changing dtype") + obj = obj.astype(dtype) + return obj.copy() if copy else obj # pyright: ignore[reportAttributeAccessIssue] + + if copy is False: + raise ValueError( + "Unable to avoid copy when converting a non-dask object to dask" + ) + + # copy=None to be uniform across dask < 2024.12 and >= 2024.12 + # see https://github.com/dask/dask/pull/11524/ + obj = np.array(obj, dtype=dtype, copy=True) + return da.from_array(obj) + + +# Element wise aliases +from dask.array import arccos as acos +from dask.array import arccosh as acosh +from dask.array import arcsin as asin +from dask.array import arcsinh as asinh +from dask.array import arctan as atan +from dask.array import arctan2 as atan2 +from dask.array import arctanh as atanh + +# Other +from dask.array import concatenate as concat +from dask.array import invert as bitwise_invert +from dask.array import left_shift as bitwise_left_shift +from dask.array import power as pow +from dask.array import right_shift as bitwise_right_shift + + +# dask.array.clip does not work unless all three arguments are provided. +# Furthermore, the masking workaround in common._aliases.clip cannot work with +# dask (meaning uint64 promoting to float64 is going to just be unfixed for +# now). +def clip( + x: Array, + /, + min: float | Array | None = None, + max: float | Array | None = None, +) -> Array: + """ + Array API compatibility wrapper for clip(). + + See the corresponding documentation in the array library and/or the array API + specification for more details. + """ + + def _isscalar(a: float | Array | None, /) -> TypeIs[float | None]: + return a is None or isinstance(a, (int, float)) + + min_shape = () if _isscalar(min) else min.shape + max_shape = () if _isscalar(max) else max.shape + + # TODO: This won't handle dask unknown shapes + result_shape = np.broadcast_shapes(x.shape, min_shape, max_shape) + + if min is not None: + min = da.broadcast_to(da.asarray(min), result_shape) + if max is not None: + max = da.broadcast_to(da.asarray(max), result_shape) + + if min is None and max is None: + return da.positive(x) + + if min is None: + return astype(da.minimum(x, max), x.dtype) + if max is None: + return astype(da.maximum(x, min), x.dtype) + + return astype(da.minimum(da.maximum(x, min), max), x.dtype) + + +def _ensure_single_chunk(x: Array, axis: int) -> tuple[Array, Callable[[Array], Array]]: + """ + Make sure that Array is not broken into multiple chunks along axis. + + Returns + ------- + x : Array + The input Array with a single chunk along axis. + restore : Callable[Array, Array] + function to apply to the output to rechunk it back into reasonable chunks + """ + if axis < 0: + axis += x.ndim + if x.numblocks[axis] < 2: + return x, lambda x: x + + # Break chunks on other axes in an attempt to keep chunk size low + x = x.rechunk({i: -1 if i == axis else "auto" for i in range(x.ndim)}) + + # Rather than reconstructing the original chunks, which can be a + # very expensive affair, just break down oversized chunks without + # incurring in any transfers over the network. + # This has the downside of a risk of overchunking if the array is + # then used in operations against other arrays that match the + # original chunking pattern. + return x, lambda x: x.rechunk() + + +def sort( + x: Array, + /, + *, + axis: int = -1, + descending: py_bool = False, + stable: py_bool = True, +) -> Array: + """ + Array API compatibility layer around the lack of sort() in Dask. + + Warnings + -------- + This function temporarily rechunks the array along `axis` to a single chunk. + This can be extremely inefficient and can lead to out-of-memory errors. + + See the corresponding documentation in the array library and/or the array API + specification for more details. + """ + x, restore = _ensure_single_chunk(x, axis) + + meta_xp = array_namespace(x._meta) + x = da.map_blocks( + meta_xp.sort, + x, + axis=axis, + meta=x._meta, + dtype=x.dtype, + descending=descending, + stable=stable, + ) + + return restore(x) + + +def argsort( + x: Array, + /, + *, + axis: int = -1, + descending: py_bool = False, + stable: py_bool = True, +) -> Array: + """ + Array API compatibility layer around the lack of argsort() in Dask. + + See the corresponding documentation in the array library and/or the array API + specification for more details. + + Warnings + -------- + This function temporarily rechunks the array along `axis` into a single chunk. + This can be extremely inefficient and can lead to out-of-memory errors. + """ + x, restore = _ensure_single_chunk(x, axis) + + meta_xp = array_namespace(x._meta) + dtype = meta_xp.argsort(x._meta).dtype + meta = meta_xp.astype(x._meta, dtype) + x = da.map_blocks( + meta_xp.argsort, + x, + axis=axis, + meta=meta, + dtype=dtype, + descending=descending, + stable=stable, + ) + + return restore(x) + + +# dask.array.count_nonzero does not have keepdims +def count_nonzero( + x: Array, + axis: int | None = None, + keepdims: py_bool = False, +) -> Array: + result = da.count_nonzero(x, axis) + if keepdims: + if axis is None: + return da.reshape(result, [1] * x.ndim) + return da.expand_dims(result, axis) + return result + + +__all__ = [ + "count_nonzero", + "bool", + "int8", "int16", "int32", "int64", + "uint8", "uint16", "uint32", "uint64", + "float32", "float64", + "complex64", "complex128", + "asarray", "astype", "can_cast", "result_type", + "pow", + "concat", + "acos", "acosh", "asin", "asinh", "atan", "atan2", "atanh", + "bitwise_left_shift", "bitwise_right_shift", "bitwise_invert", +] # fmt: skip +__all__ += _aliases.__all__ + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/_info.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/_info.py new file mode 100644 index 0000000000000000000000000000000000000000..2f39fc4b17ef730b8063b8ff10146731924244ba --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/_info.py @@ -0,0 +1,407 @@ +""" +Array API Inspection namespace + +This is the namespace for inspection functions as defined by the array API +standard. See +https://data-apis.org/array-api/latest/API_specification/inspection.html for +more details. + +""" + +# pyright: reportPrivateUsage=false + +from __future__ import annotations + +from typing import Literal, TypeAlias, overload + +import dask.array as da +from numpy import bool_ as bool +from numpy import ( + complex64, + complex128, + dtype, + float32, + float64, + int8, + int16, + int32, + int64, + intp, + uint8, + uint16, + uint32, + uint64, +) + +from ...common._helpers import _DASK_DEVICE, _check_device, _dask_device +from ...common._typing import ( + Capabilities, + DefaultDTypes, + DType, + DTypeKind, + DTypesAll, + DTypesAny, + DTypesBool, + DTypesComplex, + DTypesIntegral, + DTypesNumeric, + DTypesReal, + DTypesSigned, + DTypesUnsigned, +) +Device: TypeAlias = Literal["cpu"] | _dask_device + + +class __array_namespace_info__: + """ + Get the array API inspection namespace for Dask. + + The array API inspection namespace defines the following functions: + + - capabilities() + - default_device() + - default_dtypes() + - dtypes() + - devices() + + See + https://data-apis.org/array-api/latest/API_specification/inspection.html + for more details. + + Returns + ------- + info : ModuleType + The array API inspection namespace for Dask. + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.default_dtypes() + {'real floating': dask.float64, + 'complex floating': dask.complex128, + 'integral': dask.int64, + 'indexing': dask.int64} + + """ + + __module__ = "dask.array" + + def capabilities(self) -> Capabilities: + """ + Return a dictionary of array API library capabilities. + + The resulting dictionary has the following keys: + + - **"boolean indexing"**: boolean indicating whether an array library + supports boolean indexing. + + Dask support boolean indexing as long as both the index + and the indexed arrays have known shapes. + Note however that the output .shape and .size properties + will contain a non-compliant math.nan instead of None. + + - **"data-dependent shapes"**: boolean indicating whether an array + library supports data-dependent output shapes. + + Dask implements unique_values et.al. + Note however that the output .shape and .size properties + will contain a non-compliant math.nan instead of None. + + - **"max dimensions"**: integer indicating the maximum number of + dimensions supported by the array library. + + See + https://data-apis.org/array-api/latest/API_specification/generated/array_api.info.capabilities.html + for more details. + + See Also + -------- + __array_namespace_info__.default_device, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.dtypes, + __array_namespace_info__.devices + + Returns + ------- + capabilities : dict + A dictionary of array API library capabilities. + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.capabilities() + {'boolean indexing': True, + 'data-dependent shapes': True, + 'max dimensions': 64} + + """ + return { + "boolean indexing": True, + "data-dependent shapes": True, + "max dimensions": 64, + } + + def default_device(self) -> Device: + """ + The default device used for new Dask arrays. + + For Dask, this always returns ``'cpu'``. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.dtypes, + __array_namespace_info__.devices + + Returns + ------- + device : Device + The default device used for new Dask arrays. + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.default_device() + 'cpu' + + """ + return "cpu" + + def default_dtypes(self, /, *, device: Device | None = None) -> DefaultDTypes: + """ + The default data types used for new Dask arrays. + + For Dask, this always returns the following dictionary: + + - **"real floating"**: ``numpy.float64`` + - **"complex floating"**: ``numpy.complex128`` + - **"integral"**: ``numpy.intp`` + - **"indexing"**: ``numpy.intp`` + + Parameters + ---------- + device : str, optional + The device to get the default data types for. + + Returns + ------- + dtypes : dict + A dictionary describing the default data types used for new Dask + arrays. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_device, + __array_namespace_info__.dtypes, + __array_namespace_info__.devices + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.default_dtypes() + {'real floating': dask.float64, + 'complex floating': dask.complex128, + 'integral': dask.int64, + 'indexing': dask.int64} + + """ + _check_device(da, device) + return { + "real floating": dtype(float64), + "complex floating": dtype(complex128), + "integral": dtype(intp), + "indexing": dtype(intp), + } + + @overload + def dtypes( + self, /, *, device: Device | None = None, kind: None = None + ) -> DTypesAll: ... + @overload + def dtypes( + self, /, *, device: Device | None = None, kind: Literal["bool"] + ) -> DTypesBool: ... + @overload + def dtypes( + self, /, *, device: Device | None = None, kind: Literal["signed integer"] + ) -> DTypesSigned: ... + @overload + def dtypes( + self, /, *, device: Device | None = None, kind: Literal["unsigned integer"] + ) -> DTypesUnsigned: ... + @overload + def dtypes( + self, /, *, device: Device | None = None, kind: Literal["integral"] + ) -> DTypesIntegral: ... + @overload + def dtypes( + self, /, *, device: Device | None = None, kind: Literal["real floating"] + ) -> DTypesReal: ... + @overload + def dtypes( + self, /, *, device: Device | None = None, kind: Literal["complex floating"] + ) -> DTypesComplex: ... + @overload + def dtypes( + self, /, *, device: Device | None = None, kind: Literal["numeric"] + ) -> DTypesNumeric: ... + def dtypes( + self, /, *, device: Device | None = None, kind: DTypeKind | None = None + ) -> DTypesAny: + """ + The array API data types supported by Dask. + + Note that this function only returns data types that are defined by + the array API. + + Parameters + ---------- + device : str, optional + The device to get the data types for. + kind : str or tuple of str, optional + The kind of data types to return. If ``None``, all data types are + returned. If a string, only data types of that kind are returned. + If a tuple, a dictionary containing the union of the given kinds + is returned. The following kinds are supported: + + - ``'bool'``: boolean data types (i.e., ``bool``). + - ``'signed integer'``: signed integer data types (i.e., ``int8``, + ``int16``, ``int32``, ``int64``). + - ``'unsigned integer'``: unsigned integer data types (i.e., + ``uint8``, ``uint16``, ``uint32``, ``uint64``). + - ``'integral'``: integer data types. Shorthand for ``('signed + integer', 'unsigned integer')``. + - ``'real floating'``: real-valued floating-point data types + (i.e., ``float32``, ``float64``). + - ``'complex floating'``: complex floating-point data types (i.e., + ``complex64``, ``complex128``). + - ``'numeric'``: numeric data types. Shorthand for ``('integral', + 'real floating', 'complex floating')``. + + Returns + ------- + dtypes : dict + A dictionary mapping the names of data types to the corresponding + Dask data types. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_device, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.devices + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.dtypes(kind='signed integer') + {'int8': dask.int8, + 'int16': dask.int16, + 'int32': dask.int32, + 'int64': dask.int64} + + """ + _check_device(da, device) + if kind is None: + return { + "bool": dtype(bool), + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + "float32": dtype(float32), + "float64": dtype(float64), + "complex64": dtype(complex64), + "complex128": dtype(complex128), + } + if kind == "bool": + return {"bool": bool} + if kind == "signed integer": + return { + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + } + if kind == "unsigned integer": + return { + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + } + if kind == "integral": + return { + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + } + if kind == "real floating": + return { + "float32": dtype(float32), + "float64": dtype(float64), + } + if kind == "complex floating": + return { + "complex64": dtype(complex64), + "complex128": dtype(complex128), + } + if kind == "numeric": + return { + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + "float32": dtype(float32), + "float64": dtype(float64), + "complex64": dtype(complex64), + "complex128": dtype(complex128), + } + if isinstance(kind, tuple): + res: dict[str, DType] = {} + for k in kind: + res.update(self.dtypes(kind=k)) + return res + raise ValueError(f"unsupported kind: {kind!r}") + + def devices(self) -> list[Device]: + """ + The devices supported by Dask. + + For Dask, this always returns ``['cpu', DASK_DEVICE]``. + + Returns + ------- + devices : list[Device] + The devices supported by Dask. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_device, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.dtypes + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.devices() + ['cpu', DASK_DEVICE] + + """ + return ["cpu", _DASK_DEVICE] diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/fft.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/fft.py new file mode 100644 index 0000000000000000000000000000000000000000..44b68e733984f1f2da11cdd3b892e84b7bd5e797 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/fft.py @@ -0,0 +1,16 @@ +from ..._internal import clone_module + +__all__ = clone_module("dask.array.fft", globals()) + +from ...common import _fft +from ..._internal import get_xp + +import dask.array as da + +fftfreq = get_xp(da)(_fft.fftfreq) +rfftfreq = get_xp(da)(_fft.rfftfreq) + +__all__ += ["fftfreq", "rfftfreq"] + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/linalg.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/linalg.py new file mode 100644 index 0000000000000000000000000000000000000000..6b3c10117b10b9a8b3bb494415f6711bd3db19d1 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/dask/array/linalg.py @@ -0,0 +1,64 @@ +from __future__ import annotations + +from typing import Literal + +import dask.array as da + +# The `matmul` and `tensordot` functions are in both the main and linalg namespaces +from dask.array import matmul, outer, tensordot + +# Exports +from ..._internal import clone_module, get_xp +from ...common import _linalg +from ...common._typing import Array + +__all__ = clone_module("dask.array.linalg", globals()) + +from ._aliases import matrix_transpose, vecdot + +EighResult = _linalg.EighResult +QRResult = _linalg.QRResult +SlogdetResult = _linalg.SlogdetResult +SVDResult = _linalg.SVDResult +# TODO: use the QR wrapper once dask +# supports the mode keyword on QR +# https://github.com/dask/dask/issues/10388 +#qr = get_xp(da)(_linalg.qr) +def qr( # type: ignore[no-redef] + x: Array, + mode: Literal["reduced", "complete"] = "reduced", + **kwargs: object, +) -> QRResult: + if mode != "reduced": + raise ValueError("dask arrays only support using mode='reduced'") + return QRResult(*da.linalg.qr(x, **kwargs)) +trace = get_xp(da)(_linalg.trace) +cholesky = get_xp(da)(_linalg.cholesky) +matrix_rank = get_xp(da)(_linalg.matrix_rank) +matrix_norm = get_xp(da)(_linalg.matrix_norm) + + +# Wrap the svd functions to not pass full_matrices to dask +# when full_matrices=False (as that is the default behavior for dask), +# and dask doesn't have the full_matrices keyword +def svd(x: Array, full_matrices: bool = True, **kwargs: object) -> SVDResult: # type: ignore[no-redef] + if full_matrices: + raise ValueError("full_matrics=True is not supported by dask.") + return da.linalg.svd(x, coerce_signs=False, **kwargs) + +def svdvals(x: Array) -> Array: + # TODO: can't avoid computing U or V for dask + _, s, _ = svd(x) + return s + +vector_norm = get_xp(da)(_linalg.vector_norm) +diagonal = get_xp(da)(_linalg.diagonal) + +__all__ += ["trace", "outer", "matmul", "tensordot", + "matrix_transpose", "vecdot", "EighResult", + "QRResult", "SlogdetResult", "SVDResult", "qr", + "cholesky", "matrix_rank", "matrix_norm", "svdvals", + "vector_norm", "diagonal"] + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..23379e44db6e70eae64d4987d90d5b5bc6f8d51c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__init__.py @@ -0,0 +1,38 @@ +# ruff: noqa: PLC0414 +from typing import Final + +from .._internal import clone_module + +# This needs to be loaded explicitly before cloning +import numpy.typing # noqa: F401 + +__all__ = clone_module("numpy", globals()) + +# These imports may overwrite names from the import * above. +from . import _aliases +from ._aliases import * # type: ignore[assignment,no-redef] # noqa: F403 +from ._info import __array_namespace_info__ # noqa: F401 + +# Don't know why, but we have to do an absolute import to import linalg. If we +# instead do +# +# from . import linalg +# +# It doesn't overwrite np.linalg from above. The import is generated +# dynamically so that the library can be vendored. +__import__(__package__ + ".linalg") + +__import__(__package__ + ".fft") + +from .linalg import matrix_transpose, vecdot # type: ignore[no-redef] # noqa: F401 + +__array_api_version__: Final = "2024.12" + +__all__ = sorted( + set(__all__) + | set(_aliases.__all__) + | {"__array_api_version__", "__array_namespace_info__", "linalg", "fft"} +) + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..57c6421b9ce701ec44803eb407d8bde286a25306 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/_aliases.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/_aliases.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80a3a99726419deae435277e754e0926ade30ad7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/_aliases.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/_info.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/_info.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e282c3c6af2e5794191844b61e9d68cdb57380c7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/_info.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/_typing.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/_typing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b41e2294b18d71e2ea0635b8599e3fe01043b54 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/_typing.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/fft.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/fft.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..362ab3b5607c8ca38374422e731a99e77d480560 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/fft.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/linalg.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/linalg.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f4a5bad05128e0f11dc860561e8a0cf1eb2d2604 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/__pycache__/linalg.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/_aliases.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/_aliases.py new file mode 100644 index 0000000000000000000000000000000000000000..87b3c2f398af09fc8065aa05a1bfccd679e639d4 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/_aliases.py @@ -0,0 +1,191 @@ +# pyright: reportPrivateUsage=false +from __future__ import annotations + +from builtins import bool as py_bool +from typing import Any, cast + +import numpy as np + +from .._internal import get_xp +from ..common import _aliases, _helpers +from ..common._typing import NestedSequence, SupportsBufferProtocol +from ._typing import Array, Device, DType + +bool = np.bool_ + +# Basic renames +acos = np.arccos +acosh = np.arccosh +asin = np.arcsin +asinh = np.arcsinh +atan = np.arctan +atan2 = np.arctan2 +atanh = np.arctanh +bitwise_left_shift = np.left_shift +bitwise_invert = np.invert +bitwise_right_shift = np.right_shift +concat = np.concatenate +pow = np.power + +arange = get_xp(np)(_aliases.arange) +empty = get_xp(np)(_aliases.empty) +empty_like = get_xp(np)(_aliases.empty_like) +eye = get_xp(np)(_aliases.eye) +full = get_xp(np)(_aliases.full) +full_like = get_xp(np)(_aliases.full_like) +linspace = get_xp(np)(_aliases.linspace) +ones = get_xp(np)(_aliases.ones) +ones_like = get_xp(np)(_aliases.ones_like) +zeros = get_xp(np)(_aliases.zeros) +zeros_like = get_xp(np)(_aliases.zeros_like) +UniqueAllResult = get_xp(np)(_aliases.UniqueAllResult) +UniqueCountsResult = get_xp(np)(_aliases.UniqueCountsResult) +UniqueInverseResult = get_xp(np)(_aliases.UniqueInverseResult) +unique_all = get_xp(np)(_aliases.unique_all) +unique_counts = get_xp(np)(_aliases.unique_counts) +unique_inverse = get_xp(np)(_aliases.unique_inverse) +unique_values = get_xp(np)(_aliases.unique_values) +std = get_xp(np)(_aliases.std) +var = get_xp(np)(_aliases.var) +cumulative_sum = get_xp(np)(_aliases.cumulative_sum) +cumulative_prod = get_xp(np)(_aliases.cumulative_prod) +clip = get_xp(np)(_aliases.clip) +permute_dims = get_xp(np)(_aliases.permute_dims) +reshape = get_xp(np)(_aliases.reshape) +argsort = get_xp(np)(_aliases.argsort) +sort = get_xp(np)(_aliases.sort) +nonzero = get_xp(np)(_aliases.nonzero) +matmul = get_xp(np)(_aliases.matmul) +matrix_transpose = get_xp(np)(_aliases.matrix_transpose) +tensordot = get_xp(np)(_aliases.tensordot) +sign = get_xp(np)(_aliases.sign) +finfo = get_xp(np)(_aliases.finfo) +iinfo = get_xp(np)(_aliases.iinfo) + + +# asarray also adds the copy keyword, which is not present in numpy 1.0. +# asarray() is different enough between numpy, cupy, and dask, the logic +# complicated enough that it's easier to define it separately for each module +# rather than trying to combine everything into one function in common/ +def asarray( + obj: Array | complex | NestedSequence[complex] | SupportsBufferProtocol, + /, + *, + dtype: DType | None = None, + device: Device | None = None, + copy: py_bool | None = None, + **kwargs: Any, +) -> Array: + """ + Array API compatibility wrapper for asarray(). + + See the corresponding documentation in the array library and/or the array API + specification for more details. + """ + _helpers._check_device(np, device) + + # None is unsupported in NumPy 1.0, but we can use an internal enum + # False in NumPy 1.0 means None in NumPy 2.0 and in the Array API + if copy is None: + copy = np._CopyMode.IF_NEEDED # type: ignore[assignment,attr-defined] + elif copy is False: + copy = np._CopyMode.NEVER # type: ignore[assignment,attr-defined] + + return np.array(obj, copy=copy, dtype=dtype, **kwargs) + + +def astype( + x: Array, + dtype: DType, + /, + *, + copy: py_bool = True, + device: Device | None = None, +) -> Array: + _helpers._check_device(np, device) + return x.astype(dtype=dtype, copy=copy) + + +# count_nonzero returns a python int for axis=None and keepdims=False +# https://github.com/numpy/numpy/issues/17562 +def count_nonzero( + x: Array, + axis: int | tuple[int, ...] | None = None, + keepdims: py_bool = False, +) -> Array: + # NOTE: this is currently incorrectly typed in numpy, but will be fixed in + # numpy 2.2.5 and 2.3.0: https://github.com/numpy/numpy/pull/28750 + result = cast("Any", np.count_nonzero(x, axis=axis, keepdims=keepdims)) # pyright: ignore[reportArgumentType, reportCallIssue] + if axis is None and not keepdims: + return np.asarray(result) + return result + + +# take_along_axis: axis defaults to -1 but in numpy axis is a required arg +def take_along_axis(x: Array, indices: Array, /, *, axis: int = -1) -> Array: + return np.take_along_axis(x, indices, axis=axis) + + +# ceil, floor, and trunc return integers for integer inputs in NumPy < 2 + +def ceil(x: Array, /) -> Array: + if np.__version__ < '2' and np.issubdtype(x.dtype, np.integer): + return x.copy() + return np.ceil(x) + + +def floor(x: Array, /) -> Array: + if np.__version__ < '2' and np.issubdtype(x.dtype, np.integer): + return x.copy() + return np.floor(x) + + +def trunc(x: Array, /) -> Array: + if np.__version__ < '2' and np.issubdtype(x.dtype, np.integer): + return x.copy() + return np.trunc(x) + + +# These functions are completely new here. If the library already has them +# (i.e., numpy 2.0), use the library version instead of our wrapper. +if hasattr(np, "vecdot"): + vecdot = np.vecdot +else: + vecdot = get_xp(np)(_aliases.vecdot) # type: ignore[assignment] + +if hasattr(np, "isdtype"): + isdtype = np.isdtype +else: + isdtype = get_xp(np)(_aliases.isdtype) + +if hasattr(np, "unstack"): + unstack = np.unstack +else: + unstack = get_xp(np)(_aliases.unstack) + +__all__ = _aliases.__all__ + [ + "asarray", + "astype", + "acos", + "acosh", + "asin", + "asinh", + "atan", + "atan2", + "atanh", + "ceil", + "floor", + "trunc", + "bitwise_left_shift", + "bitwise_invert", + "bitwise_right_shift", + "bool", + "concat", + "count_nonzero", + "pow", + "take_along_axis" +] + + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/_info.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/_info.py new file mode 100644 index 0000000000000000000000000000000000000000..c625c13e36942286a83ee3290c93208d8818bedd --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/_info.py @@ -0,0 +1,367 @@ +""" +Array API Inspection namespace + +This is the namespace for inspection functions as defined by the array API +standard. See +https://data-apis.org/array-api/latest/API_specification/inspection.html for +more details. + +""" +from __future__ import annotations + +from numpy import bool_ as bool +from numpy import ( + complex64, + complex128, + dtype, + float32, + float64, + int8, + int16, + int32, + int64, + intp, + uint8, + uint16, + uint32, + uint64, +) + +from ..common._typing import DefaultDTypes +from ._typing import Device, DType + + +class __array_namespace_info__: + """ + Get the array API inspection namespace for NumPy. + + The array API inspection namespace defines the following functions: + + - capabilities() + - default_device() + - default_dtypes() + - dtypes() + - devices() + + See + https://data-apis.org/array-api/latest/API_specification/inspection.html + for more details. + + Returns + ------- + info : ModuleType + The array API inspection namespace for NumPy. + + Examples + -------- + >>> info = np.__array_namespace_info__() + >>> info.default_dtypes() + {'real floating': numpy.float64, + 'complex floating': numpy.complex128, + 'integral': numpy.int64, + 'indexing': numpy.int64} + + """ + + __module__ = 'numpy' + + def capabilities(self): + """ + Return a dictionary of array API library capabilities. + + The resulting dictionary has the following keys: + + - **"boolean indexing"**: boolean indicating whether an array library + supports boolean indexing. Always ``True`` for NumPy. + + - **"data-dependent shapes"**: boolean indicating whether an array + library supports data-dependent output shapes. Always ``True`` for + NumPy. + + See + https://data-apis.org/array-api/latest/API_specification/generated/array_api.info.capabilities.html + for more details. + + See Also + -------- + __array_namespace_info__.default_device, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.dtypes, + __array_namespace_info__.devices + + Returns + ------- + capabilities : dict + A dictionary of array API library capabilities. + + Examples + -------- + >>> info = np.__array_namespace_info__() + >>> info.capabilities() + {'boolean indexing': True, + 'data-dependent shapes': True, + 'max dimensions': 64} + + """ + return { + "boolean indexing": True, + "data-dependent shapes": True, + "max dimensions": 64, + } + + def default_device(self): + """ + The default device used for new NumPy arrays. + + For NumPy, this always returns ``'cpu'``. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.dtypes, + __array_namespace_info__.devices + + Returns + ------- + device : Device + The default device used for new NumPy arrays. + + Examples + -------- + >>> info = np.__array_namespace_info__() + >>> info.default_device() + 'cpu' + + """ + return "cpu" + + def default_dtypes( + self, + *, + device: Device | None = None, + ) -> DefaultDTypes: + """ + The default data types used for new NumPy arrays. + + For NumPy, this always returns the following dictionary: + + - **"real floating"**: ``numpy.float64`` + - **"complex floating"**: ``numpy.complex128`` + - **"integral"**: ``numpy.intp`` + - **"indexing"**: ``numpy.intp`` + + Parameters + ---------- + device : str, optional + The device to get the default data types for. For NumPy, only + ``'cpu'`` is allowed. + + Returns + ------- + dtypes : dict + A dictionary describing the default data types used for new NumPy + arrays. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_device, + __array_namespace_info__.dtypes, + __array_namespace_info__.devices + + Examples + -------- + >>> info = np.__array_namespace_info__() + >>> info.default_dtypes() + {'real floating': numpy.float64, + 'complex floating': numpy.complex128, + 'integral': numpy.int64, + 'indexing': numpy.int64} + + """ + if device not in ["cpu", None]: + raise ValueError( + 'Device not understood. Only "cpu" is allowed, but received:' + f' {device}' + ) + return { + "real floating": dtype(float64), + "complex floating": dtype(complex128), + "integral": dtype(intp), + "indexing": dtype(intp), + } + + def dtypes( + self, + *, + device: Device | None = None, + kind: str | tuple[str, ...] | None = None, + ) -> dict[str, DType]: + """ + The array API data types supported by NumPy. + + Note that this function only returns data types that are defined by + the array API. + + Parameters + ---------- + device : str, optional + The device to get the data types for. For NumPy, only ``'cpu'`` is + allowed. + kind : str or tuple of str, optional + The kind of data types to return. If ``None``, all data types are + returned. If a string, only data types of that kind are returned. + If a tuple, a dictionary containing the union of the given kinds + is returned. The following kinds are supported: + + - ``'bool'``: boolean data types (i.e., ``bool``). + - ``'signed integer'``: signed integer data types (i.e., ``int8``, + ``int16``, ``int32``, ``int64``). + - ``'unsigned integer'``: unsigned integer data types (i.e., + ``uint8``, ``uint16``, ``uint32``, ``uint64``). + - ``'integral'``: integer data types. Shorthand for ``('signed + integer', 'unsigned integer')``. + - ``'real floating'``: real-valued floating-point data types + (i.e., ``float32``, ``float64``). + - ``'complex floating'``: complex floating-point data types (i.e., + ``complex64``, ``complex128``). + - ``'numeric'``: numeric data types. Shorthand for ``('integral', + 'real floating', 'complex floating')``. + + Returns + ------- + dtypes : dict + A dictionary mapping the names of data types to the corresponding + NumPy data types. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_device, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.devices + + Examples + -------- + >>> info = np.__array_namespace_info__() + >>> info.dtypes(kind='signed integer') + {'int8': numpy.int8, + 'int16': numpy.int16, + 'int32': numpy.int32, + 'int64': numpy.int64} + + """ + if device not in ["cpu", None]: + raise ValueError( + 'Device not understood. Only "cpu" is allowed, but received:' + f' {device}' + ) + if kind is None: + return { + "bool": dtype(bool), + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + "float32": dtype(float32), + "float64": dtype(float64), + "complex64": dtype(complex64), + "complex128": dtype(complex128), + } + if kind == "bool": + return {"bool": dtype(bool)} + if kind == "signed integer": + return { + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + } + if kind == "unsigned integer": + return { + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + } + if kind == "integral": + return { + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + } + if kind == "real floating": + return { + "float32": dtype(float32), + "float64": dtype(float64), + } + if kind == "complex floating": + return { + "complex64": dtype(complex64), + "complex128": dtype(complex128), + } + if kind == "numeric": + return { + "int8": dtype(int8), + "int16": dtype(int16), + "int32": dtype(int32), + "int64": dtype(int64), + "uint8": dtype(uint8), + "uint16": dtype(uint16), + "uint32": dtype(uint32), + "uint64": dtype(uint64), + "float32": dtype(float32), + "float64": dtype(float64), + "complex64": dtype(complex64), + "complex128": dtype(complex128), + } + if isinstance(kind, tuple): + res: dict[str, DType] = {} + for k in kind: + res.update(self.dtypes(kind=k)) + return res + raise ValueError(f"unsupported kind: {kind!r}") + + def devices(self) -> list[Device]: + """ + The devices supported by NumPy. + + For NumPy, this always returns ``['cpu']``. + + Returns + ------- + devices : list[Device] + The devices supported by NumPy. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_device, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.dtypes + + Examples + -------- + >>> info = np.__array_namespace_info__() + >>> info.devices() + ['cpu'] + + """ + return ["cpu"] + + +__all__ = ["__array_namespace_info__"] + + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/_typing.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/_typing.py new file mode 100644 index 0000000000000000000000000000000000000000..b5fa188c52b69c16a1fa088026720fee9390e640 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/_typing.py @@ -0,0 +1,29 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Literal, TypeAlias + +import numpy as np + +Device: TypeAlias = Literal["cpu"] + +if TYPE_CHECKING: + + # NumPy 1.x on Python 3.10 fails to parse np.dtype[] + DType: TypeAlias = np.dtype[ + np.bool_ + | np.integer[Any] + | np.float32 + | np.float64 + | np.complex64 + | np.complex128 + ] + Array: TypeAlias = np.ndarray[Any, DType] +else: + DType: TypeAlias = np.dtype + Array: TypeAlias = np.ndarray + +__all__ = ["Array", "DType", "Device"] + + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/fft.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/fft.py new file mode 100644 index 0000000000000000000000000000000000000000..a492feb8cf69085a3a6617fbee13a8ac236701fa --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/fft.py @@ -0,0 +1,30 @@ +import numpy as np + +from .._internal import clone_module + +__all__ = clone_module("numpy.fft", globals()) + +from .._internal import get_xp +from ..common import _fft + +fft = get_xp(np)(_fft.fft) +ifft = get_xp(np)(_fft.ifft) +fftn = get_xp(np)(_fft.fftn) +ifftn = get_xp(np)(_fft.ifftn) +rfft = get_xp(np)(_fft.rfft) +irfft = get_xp(np)(_fft.irfft) +rfftn = get_xp(np)(_fft.rfftn) +irfftn = get_xp(np)(_fft.irfftn) +hfft = get_xp(np)(_fft.hfft) +ihfft = get_xp(np)(_fft.ihfft) +fftfreq = get_xp(np)(_fft.fftfreq) +rfftfreq = get_xp(np)(_fft.rfftfreq) +fftshift = get_xp(np)(_fft.fftshift) +ifftshift = get_xp(np)(_fft.ifftshift) + + +__all__ = sorted(set(__all__) | set(_fft.__all__)) + +def __dir__() -> list[str]: + return __all__ + diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/linalg.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/linalg.py new file mode 100644 index 0000000000000000000000000000000000000000..7168441c7517ee2d8e4b03d534531a832d292f43 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/numpy/linalg.py @@ -0,0 +1,128 @@ +# pyright: reportAttributeAccessIssue=false +# pyright: reportUnknownArgumentType=false +# pyright: reportUnknownMemberType=false +# pyright: reportUnknownVariableType=false + +from __future__ import annotations + +import numpy as np + +from .._internal import clone_module, get_xp +from ..common import _linalg + +__all__ = clone_module("numpy.linalg", globals()) + +# These functions are in both the main and linalg namespaces +from ._aliases import matmul, matrix_transpose, tensordot, vecdot # noqa: F401 +from ._typing import Array + +cross = get_xp(np)(_linalg.cross) +outer = get_xp(np)(_linalg.outer) +EighResult = _linalg.EighResult +QRResult = _linalg.QRResult +SlogdetResult = _linalg.SlogdetResult +SVDResult = _linalg.SVDResult +eigh = get_xp(np)(_linalg.eigh) +qr = get_xp(np)(_linalg.qr) +slogdet = get_xp(np)(_linalg.slogdet) +svd = get_xp(np)(_linalg.svd) +cholesky = get_xp(np)(_linalg.cholesky) +matrix_rank = get_xp(np)(_linalg.matrix_rank) +pinv = get_xp(np)(_linalg.pinv) +matrix_norm = get_xp(np)(_linalg.matrix_norm) +svdvals = get_xp(np)(_linalg.svdvals) +diagonal = get_xp(np)(_linalg.diagonal) +trace = get_xp(np)(_linalg.trace) + +# Note: unlike np.linalg.solve, the array API solve() only accepts x2 as a +# vector when it is exactly 1-dimensional. All other cases treat x2 as a stack +# of matrices. The np.linalg.solve behavior of allowing stacks of both +# matrices and vectors is ambiguous c.f. +# https://github.com/numpy/numpy/issues/15349 and +# https://github.com/data-apis/array-api/issues/285. + +# To workaround this, the below is the code from np.linalg.solve except +# only calling solve1 in the exactly 1D case. + + +# This code is here instead of in common because it is numpy specific. Also +# note that CuPy's solve() does not currently support broadcasting (see +# https://github.com/cupy/cupy/blob/main/cupy/cublas.py#L43). +def solve(x1: Array, x2: Array, /) -> Array: + try: + from numpy.linalg._linalg import ( # type: ignore[attr-defined] + _assert_stacked_2d, + _assert_stacked_square, + _commonType, + _makearray, + _raise_linalgerror_singular, + isComplexType, + ) + except ImportError: + from numpy.linalg.linalg import ( # type: ignore[attr-defined] + _assert_stacked_2d, + _assert_stacked_square, + _commonType, + _makearray, + _raise_linalgerror_singular, + isComplexType, + ) + from numpy.linalg import _umath_linalg + + x1, _ = _makearray(x1) + _assert_stacked_2d(x1) + _assert_stacked_square(x1) + x2, wrap = _makearray(x2) + t, result_t = _commonType(x1, x2) + + # This part is different from np.linalg.solve + gufunc: np.ufunc + if x2.ndim == 1: + gufunc = _umath_linalg.solve1 + else: + gufunc = _umath_linalg.solve + + # This does nothing currently but is left in because it will be relevant + # when complex dtype support is added to the spec in 2022. + signature = "DD->D" if isComplexType(t) else "dd->d" + with np.errstate( + call=_raise_linalgerror_singular, + invalid="call", + over="ignore", + divide="ignore", + under="ignore", + ): + r: Array = gufunc(x1, x2, signature=signature) + + return wrap(r.astype(result_t, copy=False)) + + +# These functions are completely new here. If the library already has them +# (i.e., numpy 2.0), use the library version instead of our wrapper. +if hasattr(np.linalg, "vector_norm"): + vector_norm = np.linalg.vector_norm +else: + vector_norm = get_xp(np)(_linalg.vector_norm) + + +_all = [ + "LinAlgError", + "cond", + "det", + "eig", + "eigvals", + "eigvalsh", + "inv", + "lstsq", + "matrix_power", + "multi_dot", + "norm", + "solve", + "tensorinv", + "tensorsolve", + "vector_norm", +] +__all__ = sorted(set(__all__) | set(_linalg.__all__) | set(_all)) + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..6cbb6ec264869090e888e6631df86ab2e99ca36a --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__init__.py @@ -0,0 +1,25 @@ +from typing import Final + +from .._internal import clone_module + +__all__ = clone_module("torch", globals()) + +# These imports may overwrite names from the import * above. +from . import _aliases +from ._aliases import * # noqa: F403 +from ._info import __array_namespace_info__ # noqa: F401 + +# See the comment in the numpy __init__.py +__import__(__package__ + '.linalg') +__import__(__package__ + '.fft') + +__array_api_version__: Final = '2024.12' + +__all__ = sorted( + set(__all__) + | set(_aliases.__all__) + | {"__array_api_version__", "__array_namespace_info__", "linalg", "fft"} +) + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..37b77bdbaa60d41bc4db3e8f116bedbd733d3dd9 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/_aliases.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/_aliases.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a18e245902c83e118ad73219d8b6699aad6884e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/_aliases.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/_info.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/_info.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9a1cb0bfb8241263bed82f75da9f343f711d339c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/_info.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/_typing.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/_typing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac6ffb711635bae95f64d11f92896121d8acc2dc Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/_typing.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/fft.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/fft.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eb68cc69dc94a61e7a590500fd99be8d963fd3b0 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/fft.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/linalg.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/linalg.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b3065aade9b979e69e59032a627bdd560a92f2f5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/__pycache__/linalg.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/_aliases.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/_aliases.py new file mode 100644 index 0000000000000000000000000000000000000000..4e8533f95e839f7ccfce2ef83a810edf2cf9662c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/_aliases.py @@ -0,0 +1,875 @@ +from __future__ import annotations + +from collections.abc import Sequence +from functools import reduce as _reduce, wraps as _wraps +from builtins import all as _builtin_all, any as _builtin_any +from typing import Any, Literal + +import torch + +from .._internal import get_xp +from ..common import _aliases +from ..common._typing import NestedSequence, SupportsBufferProtocol +from ._typing import Array, Device, DType + +_int_dtypes = { + torch.uint8, + torch.int8, + torch.int16, + torch.int32, + torch.int64, +} +try: + # torch >=2.3 + _int_dtypes |= {torch.uint16, torch.uint32, torch.uint64} +except AttributeError: + pass + + +_array_api_dtypes = { + torch.bool, + *_int_dtypes, + torch.float32, + torch.float64, + torch.complex64, + torch.complex128, +} + +_promotion_table = { + # ints + (torch.int8, torch.int16): torch.int16, + (torch.int8, torch.int32): torch.int32, + (torch.int8, torch.int64): torch.int64, + (torch.int16, torch.int32): torch.int32, + (torch.int16, torch.int64): torch.int64, + (torch.int32, torch.int64): torch.int64, + # ints and uints (mixed sign) + (torch.uint8, torch.int8): torch.int16, + (torch.uint8, torch.int16): torch.int16, + (torch.uint8, torch.int32): torch.int32, + (torch.uint8, torch.int64): torch.int64, + # floats + (torch.float32, torch.float64): torch.float64, + # complexes + (torch.complex64, torch.complex128): torch.complex128, + # Mixed float and complex + (torch.float32, torch.complex64): torch.complex64, + (torch.float32, torch.complex128): torch.complex128, + (torch.float64, torch.complex64): torch.complex128, + (torch.float64, torch.complex128): torch.complex128, +} + +_promotion_table.update({(b, a): c for (a, b), c in _promotion_table.items()}) +_promotion_table.update({(a, a): a for a in _array_api_dtypes}) + + +def _two_arg(f): + @_wraps(f) + def _f(x1, x2, /, **kwargs): + x1, x2 = _fix_promotion(x1, x2) + return f(x1, x2, **kwargs) + if _f.__doc__ is None: + _f.__doc__ = f"""\ +Array API compatibility wrapper for torch.{f.__name__}. + +See the corresponding PyTorch documentation and/or the array API specification +for more details. + +""" + return _f + +def _fix_promotion(x1, x2, only_scalar=True): + if not isinstance(x1, torch.Tensor) or not isinstance(x2, torch.Tensor): + return x1, x2 + if x1.dtype not in _array_api_dtypes or x2.dtype not in _array_api_dtypes: + return x1, x2 + # If an argument is 0-D pytorch downcasts the other argument + if not only_scalar or x1.shape == (): + dtype = result_type(x1, x2) + x2 = x2.to(dtype) + if not only_scalar or x2.shape == (): + dtype = result_type(x1, x2) + x1 = x1.to(dtype) + return x1, x2 + + +_py_scalars = (bool, int, float, complex) + + +def result_type(*arrays_and_dtypes: Array | DType | complex) -> DType: + num = len(arrays_and_dtypes) + + if num == 0: + raise ValueError("At least one array or dtype must be provided") + + elif num == 1: + x = arrays_and_dtypes[0] + if isinstance(x, torch.dtype): + return x + return x.dtype + + if num == 2: + x, y = arrays_and_dtypes + return _result_type(x, y) + + else: + # sort scalars so that they are treated last + scalars, others = [], [] + for x in arrays_and_dtypes: + if isinstance(x, _py_scalars): + scalars.append(x) + else: + others.append(x) + if not others: + raise ValueError("At least one array or dtype must be provided") + + # combine left-to-right + return _reduce(_result_type, others + scalars) + + +def _result_type(x: Array | DType | complex, y: Array | DType | complex) -> DType: + if not (isinstance(x, _py_scalars) or isinstance(y, _py_scalars)): + xdt = x if isinstance(x, torch.dtype) else x.dtype + ydt = y if isinstance(y, torch.dtype) else y.dtype + + try: + return _promotion_table[xdt, ydt] + except KeyError: + pass + + # This doesn't result_type(dtype, dtype) for non-array API dtypes + # because torch.result_type only accepts tensors. This does however, allow + # cross-kind promotion. + x = torch.tensor([], dtype=x) if isinstance(x, torch.dtype) else x + y = torch.tensor([], dtype=y) if isinstance(y, torch.dtype) else y + return torch.result_type(x, y) + + +def can_cast(from_: DType | Array, to: DType, /) -> bool: + if not isinstance(from_, torch.dtype): + from_ = from_.dtype + return torch.can_cast(from_, to) + +# Basic renames +bitwise_invert = torch.bitwise_not +newaxis = None +# torch.conj sets the conjugation bit, which breaks conversion to other +# libraries. See https://github.com/data-apis/array-api-compat/issues/173 +conj = torch.conj_physical + +# Two-arg elementwise functions +# These require a wrapper to do the correct type promotion on 0-D tensors +add = _two_arg(torch.add) +atan2 = _two_arg(torch.atan2) +bitwise_and = _two_arg(torch.bitwise_and) +bitwise_left_shift = _two_arg(torch.bitwise_left_shift) +bitwise_or = _two_arg(torch.bitwise_or) +bitwise_right_shift = _two_arg(torch.bitwise_right_shift) +bitwise_xor = _two_arg(torch.bitwise_xor) +copysign = _two_arg(torch.copysign) +divide = _two_arg(torch.divide) +# Also a rename. torch.equal does not broadcast +equal = _two_arg(torch.eq) +floor_divide = _two_arg(torch.floor_divide) +greater = _two_arg(torch.greater) +greater_equal = _two_arg(torch.greater_equal) +hypot = _two_arg(torch.hypot) +less = _two_arg(torch.less) +less_equal = _two_arg(torch.less_equal) +logaddexp = _two_arg(torch.logaddexp) +# logical functions are not included here because they only accept bool in the +# spec, so type promotion is irrelevant. +maximum = _two_arg(torch.maximum) +minimum = _two_arg(torch.minimum) +multiply = _two_arg(torch.multiply) +not_equal = _two_arg(torch.not_equal) +pow = _two_arg(torch.pow) +remainder = _two_arg(torch.remainder) +subtract = _two_arg(torch.subtract) + + +def asarray( + obj: Array | complex | NestedSequence[complex] | SupportsBufferProtocol, + /, + *, + dtype: DType | None = None, + device: Device | None = None, + copy: bool | None = None, + **kwargs: Any, +) -> Array: + # torch.asarray does not respect input->output device propagation + # https://github.com/pytorch/pytorch/issues/150199 + if device is None and isinstance(obj, torch.Tensor): + device = obj.device + return torch.asarray(obj, dtype=dtype, device=device, copy=copy, **kwargs) + + +# These wrappers are mostly based on the fact that pytorch uses 'dim' instead +# of 'axis'. + +# torch.min and torch.max return a tuple and don't support multiple axes https://github.com/pytorch/pytorch/issues/58745 +def max(x: Array, /, *, axis: int | tuple[int, ...] | None = None, keepdims: bool = False) -> Array: + # https://github.com/pytorch/pytorch/issues/29137 + if axis == (): + return torch.clone(x) + return torch.amax(x, axis, keepdims=keepdims) + +def min(x: Array, /, *, axis: int | tuple[int, ...] |None = None, keepdims: bool = False) -> Array: + # https://github.com/pytorch/pytorch/issues/29137 + if axis == (): + return torch.clone(x) + return torch.amin(x, axis, keepdims=keepdims) + +clip = get_xp(torch)(_aliases.clip) +unstack = get_xp(torch)(_aliases.unstack) +cumulative_sum = get_xp(torch)(_aliases.cumulative_sum) +cumulative_prod = get_xp(torch)(_aliases.cumulative_prod) +finfo = get_xp(torch)(_aliases.finfo) +iinfo = get_xp(torch)(_aliases.iinfo) + + +# torch.sort also returns a tuple +# https://github.com/pytorch/pytorch/issues/70921 +def sort( + x: Array, + /, + *, + axis: int = -1, + descending: bool = False, + stable: bool = True, + **kwargs: object, +) -> Array: + return torch.sort(x, dim=axis, descending=descending, stable=stable, **kwargs).values + + +# Wrap torch.argsort to set stable=True by default +def argsort( + x: Array, + /, + *, + axis: int = -1, + descending: bool = False, + stable: bool = True, + **kwargs: object, +) -> Array: + return torch.argsort(x, dim=axis, descending=descending, stable=stable, **kwargs) + + +def _normalize_axes(axis, ndim): + axes = [] + if ndim == 0 and axis: + # Better error message in this case + raise IndexError(f"Dimension out of range: {axis[0]}") + lower, upper = -ndim, ndim - 1 + for a in axis: + if a < lower or a > upper: + # Match torch error message (e.g., from sum()) + raise IndexError(f"Dimension out of range (expected to be in range of [{lower}, {upper}], but got {a}") + if a < 0: + a = a + ndim + if a in axes: + # Use IndexError instead of RuntimeError, and "axis" instead of "dim" + raise IndexError(f"Axis {a} appears multiple times in the list of axes") + axes.append(a) + return sorted(axes) + +def _axis_none_keepdims(x, ndim, keepdims): + # Apply keepdims when axis=None + # (https://github.com/pytorch/pytorch/issues/71209) + # Note that this is only valid for the axis=None case. + if keepdims: + for i in range(ndim): + x = torch.unsqueeze(x, 0) + return x + +def _reduce_multiple_axes(f, x, axis, keepdims=False, **kwargs): + # Some reductions don't support multiple axes + # (https://github.com/pytorch/pytorch/issues/56586). + axes = _normalize_axes(axis, x.ndim) + for a in reversed(axes): + x = torch.movedim(x, a, -1) + x = torch.flatten(x, -len(axes)) + + out = f(x, -1, **kwargs) + + if keepdims: + for a in axes: + out = torch.unsqueeze(out, a) + return out + + +def _sum_prod_no_axis(x: Array, dtype: DType | None) -> Array: + """ + Implements `sum(..., axis=())` and `prod(..., axis=())`. + + Works around https://github.com/pytorch/pytorch/issues/29137 + """ + if dtype is not None: + return x.clone() if dtype == x.dtype else x.to(dtype) + + # We can't upcast uint8 according to the spec because there is no + # torch.uint64, so at least upcast to int64 which is what prod does + # when axis=None. + if x.dtype in (torch.uint8, torch.int8, torch.int16, torch.int32): + return x.to(torch.int64) + + return x.clone() + + +def prod(x: Array, + /, + *, + axis: int | tuple[int, ...] | None = None, + dtype: DType | None = None, + keepdims: bool = False, + **kwargs: object) -> Array: + + if axis == (): + return _sum_prod_no_axis(x, dtype) + # torch.prod doesn't support multiple axes + # (https://github.com/pytorch/pytorch/issues/56586). + if isinstance(axis, tuple): + return _reduce_multiple_axes(torch.prod, x, axis, keepdims=keepdims, dtype=dtype, **kwargs) + if axis is None: + # torch doesn't support keepdims with axis=None + # (https://github.com/pytorch/pytorch/issues/71209) + res = torch.prod(x, dtype=dtype, **kwargs) + res = _axis_none_keepdims(res, x.ndim, keepdims) + return res + + return torch.prod(x, axis, dtype=dtype, keepdims=keepdims, **kwargs) + + +def sum(x: Array, + /, + *, + axis: int | tuple[int, ...] | None = None, + dtype: DType | None = None, + keepdims: bool = False, + **kwargs: object) -> Array: + + if axis == (): + return _sum_prod_no_axis(x, dtype) + if axis is None: + # torch doesn't support keepdims with axis=None + # (https://github.com/pytorch/pytorch/issues/71209) + res = torch.sum(x, dtype=dtype, **kwargs) + res = _axis_none_keepdims(res, x.ndim, keepdims) + return res + + return torch.sum(x, axis, dtype=dtype, keepdims=keepdims, **kwargs) + +def any(x: Array, + /, + *, + axis: int | tuple[int, ...] | None = None, + keepdims: bool = False, + **kwargs: object) -> Array: + + if axis == (): + return x.to(torch.bool) + # torch.any doesn't support multiple axes + # (https://github.com/pytorch/pytorch/issues/56586). + if isinstance(axis, tuple): + res = _reduce_multiple_axes(torch.any, x, axis, keepdims=keepdims, **kwargs) + return res.to(torch.bool) + if axis is None: + # torch doesn't support keepdims with axis=None + # (https://github.com/pytorch/pytorch/issues/71209) + res = torch.any(x, **kwargs) + res = _axis_none_keepdims(res, x.ndim, keepdims) + return res.to(torch.bool) + + # torch.any doesn't return bool for uint8 + return torch.any(x, axis, keepdims=keepdims).to(torch.bool) + +def all(x: Array, + /, + *, + axis: int | tuple[int, ...] | None = None, + keepdims: bool = False, + **kwargs: object) -> Array: + + if axis == (): + return x.to(torch.bool) + # torch.all doesn't support multiple axes + # (https://github.com/pytorch/pytorch/issues/56586). + if isinstance(axis, tuple): + res = _reduce_multiple_axes(torch.all, x, axis, keepdims=keepdims, **kwargs) + return res.to(torch.bool) + if axis is None: + # torch doesn't support keepdims with axis=None + # (https://github.com/pytorch/pytorch/issues/71209) + res = torch.all(x, **kwargs) + res = _axis_none_keepdims(res, x.ndim, keepdims) + return res.to(torch.bool) + + # torch.all doesn't return bool for uint8 + return torch.all(x, axis, keepdims=keepdims).to(torch.bool) + +def mean(x: Array, + /, + *, + axis: int | tuple[int, ...] | None = None, + keepdims: bool = False, + **kwargs: object) -> Array: + # https://github.com/pytorch/pytorch/issues/29137 + if axis == (): + return torch.clone(x) + if axis is None: + # torch doesn't support keepdims with axis=None + # (https://github.com/pytorch/pytorch/issues/71209) + res = torch.mean(x, **kwargs) + res = _axis_none_keepdims(res, x.ndim, keepdims) + return res + return torch.mean(x, axis, keepdims=keepdims, **kwargs) + +def std(x: Array, + /, + *, + axis: int | tuple[int, ...] | None = None, + correction: float = 0.0, + keepdims: bool = False, + **kwargs: object) -> Array: + # Note, float correction is not supported + # https://github.com/pytorch/pytorch/issues/61492. We don't try to + # implement it here for now. + + if isinstance(correction, float): + _correction = int(correction) + if correction != _correction: + raise NotImplementedError("float correction in torch std() is not yet supported") + else: + _correction = correction + + # https://github.com/pytorch/pytorch/issues/29137 + if axis == (): + return torch.zeros_like(x) + if isinstance(axis, int): + axis = (axis,) + if axis is None: + # torch doesn't support keepdims with axis=None + # (https://github.com/pytorch/pytorch/issues/71209) + res = torch.std(x, tuple(range(x.ndim)), correction=_correction, **kwargs) + res = _axis_none_keepdims(res, x.ndim, keepdims) + return res + return torch.std(x, axis, correction=_correction, keepdims=keepdims, **kwargs) + +def var(x: Array, + /, + *, + axis: int | tuple[int, ...] | None = None, + correction: float = 0.0, + keepdims: bool = False, + **kwargs: object) -> Array: + # Note, float correction is not supported + # https://github.com/pytorch/pytorch/issues/61492. We don't try to + # implement it here for now. + + # if isinstance(correction, float): + # correction = int(correction) + + # https://github.com/pytorch/pytorch/issues/29137 + if axis == (): + return torch.zeros_like(x) + if isinstance(axis, int): + axis = (axis,) + if axis is None: + # torch doesn't support keepdims with axis=None + # (https://github.com/pytorch/pytorch/issues/71209) + res = torch.var(x, tuple(range(x.ndim)), correction=correction, **kwargs) + res = _axis_none_keepdims(res, x.ndim, keepdims) + return res + return torch.var(x, axis, correction=correction, keepdims=keepdims, **kwargs) + +# torch.concat doesn't support dim=None +# https://github.com/pytorch/pytorch/issues/70925 +def concat(arrays: tuple[Array, ...] | list[Array], + /, + *, + axis: int | None = 0, + **kwargs: object) -> Array: + if axis is None: + arrays = tuple(ar.flatten() for ar in arrays) + axis = 0 + return torch.concat(arrays, axis, **kwargs) + +# torch.squeeze only accepts int dim and doesn't require it +# https://github.com/pytorch/pytorch/issues/70924. Support for tuple dim was +# added at https://github.com/pytorch/pytorch/pull/89017. +def squeeze(x: Array, /, axis: int | tuple[int, ...]) -> Array: + if isinstance(axis, int): + axis = (axis,) + for a in axis: + if x.shape[a] != 1: + raise ValueError("squeezed dimensions must be equal to 1") + axes = _normalize_axes(axis, x.ndim) + # Remove this once pytorch 1.14 is released with the above PR #89017. + sequence = [a - i for i, a in enumerate(axes)] + for a in sequence: + x = torch.squeeze(x, a) + return x + +# torch.broadcast_to uses size instead of shape +def broadcast_to(x: Array, /, shape: tuple[int, ...], **kwargs: object) -> Array: + return torch.broadcast_to(x, shape, **kwargs) + +# torch.permute uses dims instead of axes +def permute_dims(x: Array, /, axes: tuple[int, ...]) -> Array: + return torch.permute(x, axes) + +# The axis parameter doesn't work for flip() and roll() +# https://github.com/pytorch/pytorch/issues/71210. Also torch.flip() doesn't +# accept axis=None +def flip(x: Array, /, *, axis: int | tuple[int, ...] | None = None, **kwargs: object) -> Array: + if axis is None: + axis = tuple(range(x.ndim)) + # torch.flip doesn't accept dim as an int but the method does + # https://github.com/pytorch/pytorch/issues/18095 + return x.flip(axis, **kwargs) + +def roll(x: Array, /, shift: int | tuple[int, ...], *, axis: int | tuple[int, ...] | None = None, **kwargs: object) -> Array: + return torch.roll(x, shift, axis, **kwargs) + +def nonzero(x: Array, /, **kwargs: object) -> tuple[Array, ...]: + if x.ndim == 0: + raise ValueError("nonzero() does not support zero-dimensional arrays") + return torch.nonzero(x, as_tuple=True, **kwargs) + + +# torch uses `dim` instead of `axis` +def diff( + x: Array, + /, + *, + axis: int = -1, + n: int = 1, + prepend: Array | None = None, + append: Array | None = None, +) -> Array: + return torch.diff(x, dim=axis, n=n, prepend=prepend, append=append) + + +# torch uses `dim` instead of `axis`, does not have keepdims +def count_nonzero( + x: Array, + /, + *, + axis: int | tuple[int, ...] | None = None, + keepdims: bool = False, +) -> Array: + result = torch.count_nonzero(x, dim=axis) + if keepdims: + if isinstance(axis, int): + return result.unsqueeze(axis) + elif isinstance(axis, tuple): + n_axis = [x.ndim + ax if ax < 0 else ax for ax in axis] + sh = [1 if i in n_axis else x.shape[i] for i in range(x.ndim)] + return torch.reshape(result, sh) + return _axis_none_keepdims(result, x.ndim, keepdims) + else: + return result + + +# "repeat" is torch.repeat_interleave; also the dim argument +def repeat(x: Array, repeats: int | Array, /, *, axis: int | None = None) -> Array: + return torch.repeat_interleave(x, repeats, axis) + + +def where(condition: Array, x1: Array | complex, x2: Array | complex, /) -> Array: + x1, x2 = _fix_promotion(x1, x2) + return torch.where(condition, x1, x2) + + +# torch.reshape doesn't have the copy keyword +def reshape(x: Array, + /, + shape: tuple[int, ...], + *, + copy: bool | None = None, + **kwargs: object) -> Array: + if copy is not None: + raise NotImplementedError("torch.reshape doesn't yet support the copy keyword") + return torch.reshape(x, shape, **kwargs) + +# torch.arange doesn't support returning empty arrays +# (https://github.com/pytorch/pytorch/issues/70915), and doesn't support some +# keyword argument combinations +# (https://github.com/pytorch/pytorch/issues/70914) +def arange(start: float, + /, + stop: float | None = None, + step: float = 1, + *, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object) -> Array: + if stop is None: + start, stop = 0, start + if step > 0 and stop <= start or step < 0 and stop >= start: + if dtype is None: + if _builtin_all(isinstance(i, int) for i in [start, stop, step]): + dtype = torch.int64 + else: + dtype = torch.float32 + return torch.empty(0, dtype=dtype, device=device, **kwargs) + return torch.arange(start, stop, step, dtype=dtype, device=device, **kwargs) + +# torch.eye does not accept None as a default for the second argument and +# doesn't support off-diagonals (https://github.com/pytorch/pytorch/issues/70910) +def eye(n_rows: int, + n_cols: int | None = None, + /, + *, + k: int = 0, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object) -> Array: + if n_cols is None: + n_cols = n_rows + z = torch.zeros(n_rows, n_cols, dtype=dtype, device=device, **kwargs) + if abs(k) <= n_rows + n_cols: + z.diagonal(k).fill_(1) + return z + +# torch.linspace doesn't have the endpoint parameter +def linspace(start: float, + stop: float, + /, + num: int, + *, + dtype: DType | None = None, + device: Device | None = None, + endpoint: bool = True, + **kwargs: object) -> Array: + if not endpoint: + return torch.linspace(start, stop, num+1, dtype=dtype, device=device, **kwargs)[:-1] + return torch.linspace(start, stop, num, dtype=dtype, device=device, **kwargs) + +# torch.full does not accept an int size +# https://github.com/pytorch/pytorch/issues/70906 +def full(shape: int | tuple[int, ...], + fill_value: complex, + *, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object) -> Array: + if isinstance(shape, int): + shape = (shape,) + + return torch.full(shape, fill_value, dtype=dtype, device=device, **kwargs) + +# ones, zeros, and empty do not accept shape as a keyword argument +def ones(shape: int | tuple[int, ...], + *, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object) -> Array: + return torch.ones(shape, dtype=dtype, device=device, **kwargs) + +def zeros(shape: int | tuple[int, ...], + *, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object) -> Array: + return torch.zeros(shape, dtype=dtype, device=device, **kwargs) + +def empty(shape: int | tuple[int, ...], + *, + dtype: DType | None = None, + device: Device | None = None, + **kwargs: object) -> Array: + return torch.empty(shape, dtype=dtype, device=device, **kwargs) + +# tril and triu do not call the keyword argument k + +def tril(x: Array, /, *, k: int = 0) -> Array: + return torch.tril(x, k) + +def triu(x: Array, /, *, k: int = 0) -> Array: + return torch.triu(x, k) + +# Functions that aren't in torch https://github.com/pytorch/pytorch/issues/58742 +def expand_dims(x: Array, /, *, axis: int = 0) -> Array: + return torch.unsqueeze(x, axis) + + +def astype( + x: Array, + dtype: DType, + /, + *, + copy: bool = True, + device: Device | None = None, +) -> Array: + if device is not None: + return x.to(device, dtype=dtype, copy=copy) + return x.to(dtype=dtype, copy=copy) + + +def broadcast_arrays(*arrays: Array) -> list[Array]: + shape = torch.broadcast_shapes(*[a.shape for a in arrays]) + return [torch.broadcast_to(a, shape) for a in arrays] + +# Note that these named tuples aren't actually part of the standard namespace, +# but I don't see any issue with exporting the names here regardless. +from ..common._aliases import (UniqueAllResult, UniqueCountsResult, + UniqueInverseResult) + +# https://github.com/pytorch/pytorch/issues/70920 +def unique_all(x: Array) -> UniqueAllResult: + # torch.unique doesn't support returning indices. + # https://github.com/pytorch/pytorch/issues/36748. The workaround + # suggested in that issue doesn't actually function correctly (it relies + # on non-deterministic behavior of scatter()). + raise NotImplementedError("unique_all() not yet implemented for pytorch (see https://github.com/pytorch/pytorch/issues/36748)") + + # values, inverse_indices, counts = torch.unique(x, return_counts=True, return_inverse=True) + # # torch.unique incorrectly gives a 0 count for nan values. + # # https://github.com/pytorch/pytorch/issues/94106 + # counts[torch.isnan(values)] = 1 + # return UniqueAllResult(values, indices, inverse_indices, counts) + +def unique_counts(x: Array) -> UniqueCountsResult: + values, counts = torch.unique(x, return_counts=True) + + # torch.unique incorrectly gives a 0 count for nan values. + # https://github.com/pytorch/pytorch/issues/94106 + counts[torch.isnan(values)] = 1 + return UniqueCountsResult(values, counts) + +def unique_inverse(x: Array) -> UniqueInverseResult: + values, inverse = torch.unique(x, return_inverse=True) + return UniqueInverseResult(values, inverse) + +def unique_values(x: Array) -> Array: + return torch.unique(x) + +def matmul(x1: Array, x2: Array, /, **kwargs: object) -> Array: + # torch.matmul doesn't type promote (but differently from _fix_promotion) + x1, x2 = _fix_promotion(x1, x2, only_scalar=False) + return torch.matmul(x1, x2, **kwargs) + +matrix_transpose = get_xp(torch)(_aliases.matrix_transpose) +_vecdot = get_xp(torch)(_aliases.vecdot) + +def vecdot(x1: Array, x2: Array, /, *, axis: int = -1) -> Array: + x1, x2 = _fix_promotion(x1, x2, only_scalar=False) + return _vecdot(x1, x2, axis=axis) + +# torch.tensordot uses dims instead of axes +def tensordot( + x1: Array, + x2: Array, + /, + *, + axes: int | tuple[Sequence[int], Sequence[int]] = 2, + **kwargs: object, +) -> Array: + # Note: torch.tensordot fails with integer dtypes when there is only 1 + # element in the axis (https://github.com/pytorch/pytorch/issues/84530). + x1, x2 = _fix_promotion(x1, x2, only_scalar=False) + return torch.tensordot(x1, x2, dims=axes, **kwargs) + + +def isdtype( + dtype: DType, + kind: DType | str | tuple[DType | str, ...], + *, + _tuple: bool = True, # Disallow nested tuples +) -> bool: + """ + Returns a boolean indicating whether a provided dtype is of a specified data type ``kind``. + + Note that outside of this function, this compat library does not yet fully + support complex numbers. + + See + https://data-apis.org/array-api/latest/API_specification/generated/array_api.isdtype.html + for more details + """ + if isinstance(kind, tuple) and _tuple: + return _builtin_any(isdtype(dtype, k, _tuple=False) for k in kind) + elif isinstance(kind, str): + if kind == 'bool': + return dtype == torch.bool + elif kind == 'signed integer': + return dtype in _int_dtypes and dtype.is_signed + elif kind == 'unsigned integer': + return dtype in _int_dtypes and not dtype.is_signed + elif kind == 'integral': + return dtype in _int_dtypes + elif kind == 'real floating': + return dtype.is_floating_point + elif kind == 'complex floating': + return dtype.is_complex + elif kind == 'numeric': + return isdtype(dtype, ('integral', 'real floating', 'complex floating')) + else: + raise ValueError(f"Unrecognized data type kind: {kind!r}") + else: + return dtype == kind + +def take(x: Array, indices: Array, /, *, axis: int | None = None, **kwargs: object) -> Array: + if axis is None: + if x.ndim != 1: + raise ValueError("axis must be specified when ndim > 1") + axis = 0 + # torch does not support negative indices, + # see https://github.com/pytorch/pytorch/issues/146211 + return torch.index_select( + x, + axis, + torch.where(indices < 0, indices + x.shape[axis], indices), + **kwargs + ) + + +def take_along_axis(x: Array, indices: Array, /, *, axis: int = -1) -> Array: + # torch does not support negative indices, + # see https://github.com/pytorch/pytorch/issues/146211 + return torch.take_along_dim( + x, + torch.where(indices < 0, indices + x.shape[axis], indices), + dim=axis + ) + + +def sign(x: Array, /) -> Array: + # torch sign() does not support complex numbers and does not propagate + # nans. See https://github.com/data-apis/array-api-compat/issues/136 + if x.dtype.is_complex: + out = x/torch.abs(x) + # sign(0) = 0 but the above formula would give nan + out[x == 0+0j] = 0+0j + return out + else: + out = torch.sign(x) + if x.dtype.is_floating_point: + out[torch.isnan(x)] = torch.nan + return out + + +def meshgrid(*arrays: Array, indexing: Literal['xy', 'ij'] = 'xy') -> list[Array]: + # enforce the default of 'xy' + # TODO: is the return type a list or a tuple + return list(torch.meshgrid(*arrays, indexing=indexing)) + + +__all__ = ['asarray', 'result_type', 'can_cast', + 'permute_dims', 'bitwise_invert', 'newaxis', 'conj', 'add', + 'atan2', 'bitwise_and', 'bitwise_left_shift', 'bitwise_or', + 'bitwise_right_shift', 'bitwise_xor', 'copysign', 'count_nonzero', + 'diff', 'divide', + 'equal', 'floor_divide', 'greater', 'greater_equal', 'hypot', + 'less', 'less_equal', 'logaddexp', 'maximum', 'minimum', + 'multiply', 'not_equal', 'pow', 'remainder', 'subtract', 'max', + 'min', 'clip', 'unstack', 'cumulative_sum', 'cumulative_prod', 'sort', + 'argsort', 'prod', 'sum', 'any', 'all', 'mean', 'std', 'var', 'concat', + 'squeeze', 'broadcast_to', 'flip', 'roll', 'nonzero', 'where', 'reshape', + 'arange', 'eye', 'linspace', 'full', 'ones', 'zeros', 'empty', + 'tril', 'triu', 'expand_dims', 'astype', 'broadcast_arrays', + 'UniqueAllResult', 'UniqueCountsResult', 'UniqueInverseResult', + 'unique_all', 'unique_counts', 'unique_inverse', 'unique_values', + 'matmul', 'matrix_transpose', 'vecdot', 'tensordot', 'isdtype', + 'take', 'take_along_axis', 'sign', 'finfo', 'iinfo', 'repeat', 'meshgrid'] diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/_info.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/_info.py new file mode 100644 index 0000000000000000000000000000000000000000..818e5d3702e38281a607e1d4462a0819c8594a1e --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/_info.py @@ -0,0 +1,369 @@ +""" +Array API Inspection namespace + +This is the namespace for inspection functions as defined by the array API +standard. See +https://data-apis.org/array-api/latest/API_specification/inspection.html for +more details. + +""" +import torch + +from functools import cache + +class __array_namespace_info__: + """ + Get the array API inspection namespace for PyTorch. + + The array API inspection namespace defines the following functions: + + - capabilities() + - default_device() + - default_dtypes() + - dtypes() + - devices() + + See + https://data-apis.org/array-api/latest/API_specification/inspection.html + for more details. + + Returns + ------- + info : ModuleType + The array API inspection namespace for PyTorch. + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.default_dtypes() + {'real floating': numpy.float64, + 'complex floating': numpy.complex128, + 'integral': numpy.int64, + 'indexing': numpy.int64} + + """ + + __module__ = 'torch' + + def capabilities(self): + """ + Return a dictionary of array API library capabilities. + + The resulting dictionary has the following keys: + + - **"boolean indexing"**: boolean indicating whether an array library + supports boolean indexing. Always ``True`` for PyTorch. + + - **"data-dependent shapes"**: boolean indicating whether an array + library supports data-dependent output shapes. Always ``True`` for + PyTorch. + + See + https://data-apis.org/array-api/latest/API_specification/generated/array_api.info.capabilities.html + for more details. + + See Also + -------- + __array_namespace_info__.default_device, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.dtypes, + __array_namespace_info__.devices + + Returns + ------- + capabilities : dict + A dictionary of array API library capabilities. + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.capabilities() + {'boolean indexing': True, + 'data-dependent shapes': True, + 'max dimensions': 64} + + """ + return { + "boolean indexing": True, + "data-dependent shapes": True, + "max dimensions": 64, + } + + def default_device(self): + """ + The default device used for new PyTorch arrays. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.dtypes, + __array_namespace_info__.devices + + Returns + ------- + device : Device + The default device used for new PyTorch arrays. + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.default_device() + device(type='cpu') + + Notes + ----- + This method returns the static default device when PyTorch is initialized. + However, the *current* device used by creation functions (``empty`` etc.) + can be changed at runtime. + + See Also + -------- + https://github.com/data-apis/array-api/issues/835 + """ + return torch.device("cpu") + + def default_dtypes(self, *, device=None): + """ + The default data types used for new PyTorch arrays. + + Parameters + ---------- + device : Device, optional + The device to get the default data types for. + Unused for PyTorch, as all devices use the same default dtypes. + + Returns + ------- + dtypes : dict + A dictionary describing the default data types used for new PyTorch + arrays. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_device, + __array_namespace_info__.dtypes, + __array_namespace_info__.devices + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.default_dtypes() + {'real floating': torch.float32, + 'complex floating': torch.complex64, + 'integral': torch.int64, + 'indexing': torch.int64} + + """ + # Note: if the default is set to float64, the devices like MPS that + # don't support float64 will error. We still return the default_dtype + # value here because this error doesn't represent a different default + # per-device. + default_floating = torch.get_default_dtype() + default_complex = torch.complex64 if default_floating == torch.float32 else torch.complex128 + default_integral = torch.int64 + return { + "real floating": default_floating, + "complex floating": default_complex, + "integral": default_integral, + "indexing": default_integral, + } + + + def _dtypes(self, kind): + bool = torch.bool + int8 = torch.int8 + int16 = torch.int16 + int32 = torch.int32 + int64 = torch.int64 + uint8 = torch.uint8 + # uint16, uint32, and uint64 are present in newer versions of pytorch, + # but they aren't generally supported by the array API functions, so + # we omit them from this function. + float32 = torch.float32 + float64 = torch.float64 + complex64 = torch.complex64 + complex128 = torch.complex128 + + if kind is None: + return { + "bool": bool, + "int8": int8, + "int16": int16, + "int32": int32, + "int64": int64, + "uint8": uint8, + "float32": float32, + "float64": float64, + "complex64": complex64, + "complex128": complex128, + } + if kind == "bool": + return {"bool": bool} + if kind == "signed integer": + return { + "int8": int8, + "int16": int16, + "int32": int32, + "int64": int64, + } + if kind == "unsigned integer": + return { + "uint8": uint8, + } + if kind == "integral": + return { + "int8": int8, + "int16": int16, + "int32": int32, + "int64": int64, + "uint8": uint8, + } + if kind == "real floating": + return { + "float32": float32, + "float64": float64, + } + if kind == "complex floating": + return { + "complex64": complex64, + "complex128": complex128, + } + if kind == "numeric": + return { + "int8": int8, + "int16": int16, + "int32": int32, + "int64": int64, + "uint8": uint8, + "float32": float32, + "float64": float64, + "complex64": complex64, + "complex128": complex128, + } + if isinstance(kind, tuple): + res = {} + for k in kind: + res.update(self.dtypes(kind=k)) + return res + raise ValueError(f"unsupported kind: {kind!r}") + + @cache + def dtypes(self, *, device=None, kind=None): + """ + The array API data types supported by PyTorch. + + Note that this function only returns data types that are defined by + the array API. + + Parameters + ---------- + device : Device, optional + The device to get the data types for. + Unused for PyTorch, as all devices use the same dtypes. + kind : str or tuple of str, optional + The kind of data types to return. If ``None``, all data types are + returned. If a string, only data types of that kind are returned. + If a tuple, a dictionary containing the union of the given kinds + is returned. The following kinds are supported: + + - ``'bool'``: boolean data types (i.e., ``bool``). + - ``'signed integer'``: signed integer data types (i.e., ``int8``, + ``int16``, ``int32``, ``int64``). + - ``'unsigned integer'``: unsigned integer data types (i.e., + ``uint8``, ``uint16``, ``uint32``, ``uint64``). + - ``'integral'``: integer data types. Shorthand for ``('signed + integer', 'unsigned integer')``. + - ``'real floating'``: real-valued floating-point data types + (i.e., ``float32``, ``float64``). + - ``'complex floating'``: complex floating-point data types (i.e., + ``complex64``, ``complex128``). + - ``'numeric'``: numeric data types. Shorthand for ``('integral', + 'real floating', 'complex floating')``. + + Returns + ------- + dtypes : dict + A dictionary mapping the names of data types to the corresponding + PyTorch data types. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_device, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.devices + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.dtypes(kind='signed integer') + {'int8': numpy.int8, + 'int16': numpy.int16, + 'int32': numpy.int32, + 'int64': numpy.int64} + + """ + res = self._dtypes(kind) + for k, v in res.copy().items(): + try: + torch.empty((0,), dtype=v, device=device) + except: + del res[k] + return res + + @cache + def devices(self): + """ + The devices supported by PyTorch. + + Returns + ------- + devices : list[Device] + The devices supported by PyTorch. + + See Also + -------- + __array_namespace_info__.capabilities, + __array_namespace_info__.default_device, + __array_namespace_info__.default_dtypes, + __array_namespace_info__.dtypes + + Examples + -------- + >>> info = xp.__array_namespace_info__() + >>> info.devices() + [device(type='cpu'), device(type='mps', index=0), device(type='meta')] + + """ + # Torch doesn't have a straightforward way to get the list of all + # currently supported devices. To do this, we first parse the error + # message of torch.device to get the list of all possible types of + # device: + try: + torch.device('notadevice') + raise AssertionError("unreachable") # pragma: nocover + except RuntimeError as e: + # The error message is something like: + # "Expected one of cpu, cuda, ipu, xpu, mkldnn, opengl, opencl, ideep, hip, ve, fpga, ort, xla, lazy, vulkan, mps, meta, hpu, mtia, privateuseone device type at start of device string: notadevice" + devices_names = e.args[0].split('Expected one of ')[1].split(' device type')[0].split(', ') + + # Next we need to check for different indices for different devices. + # device(device_name, index=index) doesn't actually check if the + # device name or index is valid. We have to try to create a tensor + # with it (which is why this function is cached). + devices = [] + for device_name in devices_names: + i = 0 + while True: + try: + a = torch.empty((0,), device=torch.device(device_name, index=i)) + if a.device in devices: + break + devices.append(a.device) + except: + break + i += 1 + + return devices diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/_typing.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/_typing.py new file mode 100644 index 0000000000000000000000000000000000000000..52670871563710d326b0a114a7a517bf87098bf0 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/_typing.py @@ -0,0 +1,3 @@ +__all__ = ["Array", "Device", "DType"] + +from torch import device as Device, dtype as DType, Tensor as Array diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/fft.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/fft.py new file mode 100644 index 0000000000000000000000000000000000000000..f11b3eb5975639150c6add018c7ac36e1205b9e8 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/fft.py @@ -0,0 +1,82 @@ +from __future__ import annotations + +from collections.abc import Sequence +from typing import Literal + +import torch # noqa: F401 +import torch.fft + +from ._typing import Array +from .._internal import clone_module + +__all__ = clone_module("torch.fft", globals()) + +# Several torch fft functions do not map axes to dim + +def fftn( + x: Array, + /, + *, + s: Sequence[int] = None, + axes: Sequence[int] = None, + norm: Literal["backward", "ortho", "forward"] = "backward", + **kwargs: object, +) -> Array: + return torch.fft.fftn(x, s=s, dim=axes, norm=norm, **kwargs) + +def ifftn( + x: Array, + /, + *, + s: Sequence[int] = None, + axes: Sequence[int] = None, + norm: Literal["backward", "ortho", "forward"] = "backward", + **kwargs: object, +) -> Array: + return torch.fft.ifftn(x, s=s, dim=axes, norm=norm, **kwargs) + +def rfftn( + x: Array, + /, + *, + s: Sequence[int] = None, + axes: Sequence[int] = None, + norm: Literal["backward", "ortho", "forward"] = "backward", + **kwargs: object, +) -> Array: + return torch.fft.rfftn(x, s=s, dim=axes, norm=norm, **kwargs) + +def irfftn( + x: Array, + /, + *, + s: Sequence[int] = None, + axes: Sequence[int] = None, + norm: Literal["backward", "ortho", "forward"] = "backward", + **kwargs: object, +) -> Array: + return torch.fft.irfftn(x, s=s, dim=axes, norm=norm, **kwargs) + +def fftshift( + x: Array, + /, + *, + axes: int | Sequence[int] = None, + **kwargs: object, +) -> Array: + return torch.fft.fftshift(x, dim=axes, **kwargs) + +def ifftshift( + x: Array, + /, + *, + axes: int | Sequence[int] = None, + **kwargs: object, +) -> Array: + return torch.fft.ifftshift(x, dim=axes, **kwargs) + + +__all__ += ["fftn", "ifftn", "rfftn", "irfftn", "fftshift", "ifftshift"] + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/linalg.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/linalg.py new file mode 100644 index 0000000000000000000000000000000000000000..08271d226734b64212a8cd687617f9ecb3197b41 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_compat/torch/linalg.py @@ -0,0 +1,114 @@ +from __future__ import annotations + +import torch +import torch.linalg + +from .._internal import clone_module + +__all__ = clone_module("torch.linalg", globals()) + +# outer is implemented in torch but aren't in the linalg namespace +from torch import outer +from ._aliases import _fix_promotion, sum +# These functions are in both the main and linalg namespaces +from ._aliases import matmul, matrix_transpose, tensordot +from ._typing import Array, DType +from ..common._typing import JustInt, JustFloat + +# Note: torch.linalg.cross does not default to axis=-1 (it defaults to the +# first axis with size 3), see https://github.com/pytorch/pytorch/issues/58743 + +# torch.cross also does not support broadcasting when it would add new +# dimensions https://github.com/pytorch/pytorch/issues/39656 +def cross(x1: Array, x2: Array, /, *, axis: int = -1) -> Array: + x1, x2 = _fix_promotion(x1, x2, only_scalar=False) + if not (-min(x1.ndim, x2.ndim) <= axis < max(x1.ndim, x2.ndim)): + raise ValueError(f"axis {axis} out of bounds for cross product of arrays with shapes {x1.shape} and {x2.shape}") + if not (x1.shape[axis] == x2.shape[axis] == 3): + raise ValueError(f"cross product axis must have size 3, got {x1.shape[axis]} and {x2.shape[axis]}") + x1, x2 = torch.broadcast_tensors(x1, x2) + return torch.linalg.cross(x1, x2, dim=axis) + +def vecdot(x1: Array, x2: Array, /, *, axis: int = -1, **kwargs: object) -> Array: + from ._aliases import isdtype + + x1, x2 = _fix_promotion(x1, x2, only_scalar=False) + + # torch.linalg.vecdot incorrectly allows broadcasting along the contracted dimension + if x1.shape[axis] != x2.shape[axis]: + raise ValueError("x1 and x2 must have the same size along the given axis") + + # torch.linalg.vecdot doesn't support integer dtypes + if isdtype(x1.dtype, 'integral') or isdtype(x2.dtype, 'integral'): + if kwargs: + raise RuntimeError("vecdot kwargs not supported for integral dtypes") + + x1_ = torch.moveaxis(x1, axis, -1) + x2_ = torch.moveaxis(x2, axis, -1) + x1_, x2_ = torch.broadcast_tensors(x1_, x2_) + + res = x1_[..., None, :] @ x2_[..., None] + return res[..., 0, 0] + return torch.linalg.vecdot(x1, x2, dim=axis, **kwargs) + +def solve(x1: Array, x2: Array, /, **kwargs: object) -> Array: + x1, x2 = _fix_promotion(x1, x2, only_scalar=False) + # Torch tries to emulate NumPy 1 solve behavior by using batched 1-D solve + # whenever + # 1. x1.ndim - 1 == x2.ndim + # 2. x1.shape[:-1] == x2.shape + # + # See linalg_solve_is_vector_rhs in + # aten/src/ATen/native/LinearAlgebraUtils.h and + # TORCH_META_FUNC(_linalg_solve_ex) in + # aten/src/ATen/native/BatchLinearAlgebra.cpp in the PyTorch source code. + # + # The easiest way to work around this is to prepend a size 1 dimension to + # x2, since x2 is already one dimension less than x1. + # + # See https://github.com/pytorch/pytorch/issues/52915 + if x2.ndim != 1 and x1.ndim - 1 == x2.ndim and x1.shape[:-1] == x2.shape: + x2 = x2[None] + return torch.linalg.solve(x1, x2, **kwargs) + +# torch.trace doesn't support the offset argument and doesn't support stacking +def trace(x: Array, /, *, offset: int = 0, dtype: DType | None = None) -> Array: + # Use our wrapped sum to make sure it does upcasting correctly + return sum(torch.diagonal(x, offset=offset, dim1=-2, dim2=-1), axis=-1, dtype=dtype) + +def vector_norm( + x: Array, + /, + *, + axis: int | tuple[int, ...] | None = None, + keepdims: bool = False, + # JustFloat stands for inf | -inf, which are not valid for Literal + ord: JustInt | JustFloat = 2, + **kwargs: object, +) -> Array: + # torch.vector_norm incorrectly treats axis=() the same as axis=None + if axis == (): + out = kwargs.get('out') + if out is None: + dtype = None + if x.dtype == torch.complex64: + dtype = torch.float32 + elif x.dtype == torch.complex128: + dtype = torch.float64 + + out = torch.zeros_like(x, dtype=dtype) + + # The norm of a single scalar works out to abs(x) in every case except + # for ord=0, which is x != 0. + if ord == 0: + out[:] = (x != 0) + else: + out[:] = torch.abs(x) + return out + return torch.linalg.vector_norm(x, ord=ord, axis=axis, keepdim=keepdims, **kwargs) + +__all__ += ['outer', 'matmul', 'matrix_transpose', 'tensordot', + 'cross', 'vecdot', 'solve', 'trace', 'vector_norm'] + +def __dir__() -> list[str]: + return __all__ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..649e304b23d86a85f294108366a312ff544fb4e1 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/__init__.py @@ -0,0 +1,53 @@ +"""Extra array functions built on top of the array API standard.""" + +from ._delegation import ( + argpartition, + atleast_nd, + cov, + create_diagonal, + expand_dims, + isclose, + isin, + nan_to_num, + one_hot, + pad, + partition, + setdiff1d, + sinc, +) +from ._lib._at import at +from ._lib._funcs import ( + apply_where, + broadcast_shapes, + default_dtype, + kron, + nunique, +) +from ._lib._lazy import lazy_apply + +__version__ = "0.9.1" + +# pylint: disable=duplicate-code +__all__ = [ + "__version__", + "apply_where", + "argpartition", + "at", + "atleast_nd", + "broadcast_shapes", + "cov", + "create_diagonal", + "default_dtype", + "expand_dims", + "isclose", + "isin", + "kron", + "lazy_apply", + "nan_to_num", + "nunique", + "one_hot", + "pad", + "partition", + "setdiff1d", + "sinc", +] diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..be2db20535eff057226684e33865c6cd99e55b5a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/__pycache__/_delegation.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/__pycache__/_delegation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5524ca9c8aec7ac6a3ce939acec5928c9c361053 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/__pycache__/_delegation.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/__pycache__/testing.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/__pycache__/testing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cc8c52bb6bc92c6f73e770f79ac066216ab161e7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/__pycache__/testing.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_delegation.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_delegation.py new file mode 100644 index 0000000000000000000000000000000000000000..cb7f21cbbf91ef7ea58017928286d692a530a61c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_delegation.py @@ -0,0 +1,1028 @@ +"""Delegation to existing implementations for Public API Functions.""" + +from collections.abc import Sequence +from types import ModuleType +from typing import Literal + +from ._lib import _funcs +from ._lib._utils._compat import ( + array_namespace, + is_cupy_namespace, + is_dask_namespace, + is_jax_namespace, + is_numpy_namespace, + is_pydata_sparse_namespace, + is_torch_namespace, +) +from ._lib._utils._compat import device as get_device +from ._lib._utils._helpers import asarrays, eager_shape +from ._lib._utils._typing import Array, DType + +__all__ = [ + "atleast_nd", + "cov", + "create_diagonal", + "expand_dims", + "isclose", + "nan_to_num", + "one_hot", + "pad", + "sinc", +] + + +def atleast_nd(x: Array, /, *, ndim: int, xp: ModuleType | None = None) -> Array: + """ + Recursively expand the dimension of an array to at least `ndim`. + + Parameters + ---------- + x : array + Input array. + ndim : int + The minimum number of dimensions for the result. + xp : array_namespace, optional + The standard-compatible namespace for `x`. Default: infer. + + Returns + ------- + array + An array with ``res.ndim`` >= `ndim`. + If ``x.ndim`` >= `ndim`, `x` is returned. + If ``x.ndim`` < `ndim`, `x` is expanded by prepending new axes + until ``res.ndim`` equals `ndim`. + + Examples + -------- + >>> import array_api_strict as xp + >>> import array_api_extra as xpx + >>> x = xp.asarray([1]) + >>> xpx.atleast_nd(x, ndim=3, xp=xp) + Array([[[1]]], dtype=array_api_strict.int64) + + >>> x = xp.asarray([[[1, 2], + ... [3, 4]]]) + >>> xpx.atleast_nd(x, ndim=1, xp=xp) is x + True + """ + if xp is None: + xp = array_namespace(x) + + if 1 <= ndim <= 2 and ( + is_numpy_namespace(xp) + or is_jax_namespace(xp) + or is_dask_namespace(xp) + or is_cupy_namespace(xp) + or is_torch_namespace(xp) + ): + return getattr(xp, f"atleast_{ndim}d")(x) + + return _funcs.atleast_nd(x, ndim=ndim, xp=xp) + + +def cov(m: Array, /, *, xp: ModuleType | None = None) -> Array: + """ + Estimate a covariance matrix (or a stack of covariance matrices). + + Covariance indicates the level to which two variables vary together. + If we examine *N*-dimensional samples, :math:`X = [x_1, x_2, ... x_N]^T`, + each with *M* observations, then element :math:`C_{ij}` of the + :math:`N \times N` covariance matrix is the covariance of + :math:`x_i` and :math:`x_j`. The element :math:`C_{ii}` is the variance + of :math:`x_i`. + + With the exception of supporting batch input, this provides a subset of + the functionality of ``numpy.cov``. + + Parameters + ---------- + m : array + An array of shape ``(..., N, M)`` whose innermost two dimensions + contain *M* observations of *N* variables. That is, + each row of `m` represents a variable, and each column a single + observation of all those variables. + xp : array_namespace, optional + The standard-compatible namespace for `m`. Default: infer. + + Returns + ------- + array + An array having shape (..., N, N) whose innermost two dimensions represent + the covariance matrix of the variables. + + Examples + -------- + >>> import array_api_strict as xp + >>> import array_api_extra as xpx + + Consider two variables, :math:`x_0` and :math:`x_1`, which + correlate perfectly, but in opposite directions: + + >>> x = xp.asarray([[0, 2], [1, 1], [2, 0]]).T + >>> x + Array([[0, 1, 2], + [2, 1, 0]], dtype=array_api_strict.int64) + + Note how :math:`x_0` increases while :math:`x_1` decreases. The covariance + matrix shows this clearly: + + >>> xpx.cov(x, xp=xp) + Array([[ 1., -1.], + [-1., 1.]], dtype=array_api_strict.float64) + + Note that element :math:`C_{0,1}`, which shows the correlation between + :math:`x_0` and :math:`x_1`, is negative. + + Further, note how `x` and `y` are combined: + + >>> x = xp.asarray([-2.1, -1, 4.3]) + >>> y = xp.asarray([3, 1.1, 0.12]) + >>> X = xp.stack((x, y), axis=0) + >>> xpx.cov(X, xp=xp) + Array([[11.71 , -4.286 ], + [-4.286 , 2.14413333]], dtype=array_api_strict.float64) + + >>> xpx.cov(x, xp=xp) + Array(11.71, dtype=array_api_strict.float64) + + >>> xpx.cov(y, xp=xp) + Array(2.14413333, dtype=array_api_strict.float64) + + Input with more than two dimensions is treated as a stack of + two-dimensional input. + + >>> stack = xp.stack((X, 2*X)) + >>> xpx.cov(stack) + Array([[[ 11.71 , -4.286 ], + [ -4.286 , 2.14413333]], + + [[ 46.84 , -17.144 ], + [-17.144 , 8.57653333]]], dtype=array_api_strict.float64) + """ + + if xp is None: + xp = array_namespace(m) + + if ( + is_numpy_namespace(xp) + or is_cupy_namespace(xp) + or is_torch_namespace(xp) + or is_dask_namespace(xp) + or is_jax_namespace(xp) + ) and m.ndim <= 2: + return xp.cov(m) + + return _funcs.cov(m, xp=xp) + + +def create_diagonal( + x: Array, /, *, offset: int = 0, xp: ModuleType | None = None +) -> Array: + """ + Construct a diagonal array. + + Parameters + ---------- + x : array + An array having shape ``(*batch_dims, k)``. + offset : int, optional + Offset from the leading diagonal (default is ``0``). + Use positive ints for diagonals above the leading diagonal, + and negative ints for diagonals below the leading diagonal. + xp : array_namespace, optional + The standard-compatible namespace for `x`. Default: infer. + + Returns + ------- + array + An array having shape ``(*batch_dims, k+abs(offset), k+abs(offset))`` with `x` + on the diagonal (offset by `offset`). + + Examples + -------- + >>> import array_api_strict as xp + >>> import array_api_extra as xpx + >>> x = xp.asarray([2, 4, 8]) + + >>> xpx.create_diagonal(x, xp=xp) + Array([[2, 0, 0], + [0, 4, 0], + [0, 0, 8]], dtype=array_api_strict.int64) + + >>> xpx.create_diagonal(x, offset=-2, xp=xp) + Array([[0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [2, 0, 0, 0, 0], + [0, 4, 0, 0, 0], + [0, 0, 8, 0, 0]], dtype=array_api_strict.int64) + """ + if xp is None: + xp = array_namespace(x) + + if x.ndim == 0: + err_msg = "`x` must be at least 1-dimensional." + raise ValueError(err_msg) + + if is_torch_namespace(xp): + return xp.diag_embed(x, offset=offset, dim1=-2, dim2=-1) + + if (is_dask_namespace(xp) or is_cupy_namespace(xp)) and x.ndim < 2: + return xp.diag(x, k=offset) + + if (is_jax_namespace(xp) or is_numpy_namespace(xp)) and x.ndim < 3: + batch_dim, n = eager_shape(x)[:-1], eager_shape(x, -1)[0] + abs(offset) + return xp.reshape(xp.diag(x, k=offset), (*batch_dim, n, n)) + + return _funcs.create_diagonal(x, offset=offset, xp=xp) + + +def expand_dims( + a: Array, /, *, axis: int | tuple[int, ...] = (0,), xp: ModuleType | None = None +) -> Array: + """ + Expand the shape of an array. + + Insert (a) new axis/axes that will appear at the position(s) specified by + `axis` in the expanded array shape. + + This is ``xp.expand_dims`` for `axis` an int *or a tuple of ints*. + Roughly equivalent to ``numpy.expand_dims`` for NumPy arrays. + + Parameters + ---------- + a : array + Array to have its shape expanded. + axis : int or tuple of ints, optional + Position(s) in the expanded axes where the new axis (or axes) is/are placed. + If multiple positions are provided, they should be unique (note that a position + given by a positive index could also be referred to by a negative index - + that will also result in an error). + Default: ``(0,)``. + xp : array_namespace, optional + The standard-compatible namespace for `a`. Default: infer. + + Returns + ------- + array + `a` with an expanded shape. + + Examples + -------- + >>> import array_api_strict as xp + >>> import array_api_extra as xpx + >>> x = xp.asarray([1, 2]) + >>> x.shape + (2,) + + The following is equivalent to ``x[xp.newaxis, :]`` or ``x[xp.newaxis]``: + + >>> y = xpx.expand_dims(x, axis=0, xp=xp) + >>> y + Array([[1, 2]], dtype=array_api_strict.int64) + >>> y.shape + (1, 2) + + The following is equivalent to ``x[:, xp.newaxis]``: + + >>> y = xpx.expand_dims(x, axis=1, xp=xp) + >>> y + Array([[1], + [2]], dtype=array_api_strict.int64) + >>> y.shape + (2, 1) + + ``axis`` may also be a tuple: + + >>> y = xpx.expand_dims(x, axis=(0, 1), xp=xp) + >>> y + Array([[[1, 2]]], dtype=array_api_strict.int64) + + >>> y = xpx.expand_dims(x, axis=(2, 0), xp=xp) + >>> y + Array([[[1], + [2]]], dtype=array_api_strict.int64) + """ + if xp is None: + xp = array_namespace(a) + + if not isinstance(axis, tuple): + axis = (axis,) + ndim = a.ndim + len(axis) + if axis != () and (min(axis) < -ndim or max(axis) >= ndim): + err_msg = ( + f"a provided axis position is out of bounds for array of dimension {a.ndim}" + ) + raise IndexError(err_msg) + axis = tuple(dim % ndim for dim in axis) + if len(set(axis)) != len(axis): + err_msg = "Duplicate dimensions specified in `axis`." + raise ValueError(err_msg) + + if is_numpy_namespace(xp) or is_dask_namespace(xp) or is_jax_namespace(xp): + return xp.expand_dims(a, axis=axis) + + return _funcs.expand_dims(a, axis=axis, xp=xp) + + +def isclose( + a: Array | complex, + b: Array | complex, + *, + rtol: float = 1e-05, + atol: float = 1e-08, + equal_nan: bool = False, + xp: ModuleType | None = None, +) -> Array: + """ + Return a boolean array where two arrays are element-wise equal within a tolerance. + + The tolerance values are positive, typically very small numbers. The relative + difference ``(rtol * abs(b))`` and the absolute difference `atol` are added together + to compare against the absolute difference between `a` and `b`. + + NaNs are treated as equal if they are in the same place and if ``equal_nan=True``. + Infs are treated as equal if they are in the same place and of the same sign in both + arrays. + + Parameters + ---------- + a, b : Array | int | float | complex | bool + Input objects to compare. At least one must be an array. + rtol : array_like, optional + The relative tolerance parameter (see Notes). + atol : array_like, optional + The absolute tolerance parameter (see Notes). + equal_nan : bool, optional + Whether to compare NaN's as equal. If True, NaN's in `a` will be considered + equal to NaN's in `b` in the output array. + xp : array_namespace, optional + The standard-compatible namespace for `a` and `b`. Default: infer. + + Returns + ------- + Array + A boolean array of shape broadcasted from `a` and `b`, containing ``True`` where + `a` is close to `b`, and ``False`` otherwise. + + Warnings + -------- + The default `atol` is not appropriate for comparing numbers with magnitudes much + smaller than one (see notes). + + See Also + -------- + math.isclose : Similar function in stdlib for Python scalars. + + Notes + ----- + For finite values, `isclose` uses the following equation to test whether two + floating point values are equivalent:: + + absolute(a - b) <= (atol + rtol * absolute(b)) + + Unlike the built-in `math.isclose`, + the above equation is not symmetric in `a` and `b`, + so that ``isclose(a, b)`` might be different from ``isclose(b, a)`` in some rare + cases. + + The default value of `atol` is not appropriate when the reference value `b` has + magnitude smaller than one. For example, it is unlikely that ``a = 1e-9`` and + ``b = 2e-9`` should be considered "close", yet ``isclose(1e-9, 2e-9)`` is ``True`` + with default settings. Be sure to select `atol` for the use case at hand, especially + for defining the threshold below which a non-zero value in `a` will be considered + "close" to a very small or zero value in `b`. + + The comparison of `a` and `b` uses standard broadcasting, which means that `a` and + `b` need not have the same shape in order for ``isclose(a, b)`` to evaluate to + ``True``. + + `isclose` is not defined for non-numeric data types. + ``bool`` is considered a numeric data-type for this purpose. + """ + xp = array_namespace(a, b) if xp is None else xp + + if ( + is_numpy_namespace(xp) + or is_cupy_namespace(xp) + or is_dask_namespace(xp) + or is_jax_namespace(xp) + ): + return xp.isclose(a, b, rtol=rtol, atol=atol, equal_nan=equal_nan) + + if is_torch_namespace(xp): + a, b = asarrays(a, b, xp=xp) # Array API 2024.12 support + return xp.isclose(a, b, rtol=rtol, atol=atol, equal_nan=equal_nan) + + return _funcs.isclose(a, b, rtol=rtol, atol=atol, equal_nan=equal_nan, xp=xp) + + +def nan_to_num( + x: Array | float | complex, + /, + *, + fill_value: int | float = 0.0, + xp: ModuleType | None = None, +) -> Array: + """ + Replace NaN with zero and infinity with large finite numbers (default behaviour). + + If `x` is inexact, NaN is replaced by zero or by the user defined value in the + `fill_value` keyword, infinity is replaced by the largest finite floating + point value representable by ``x.dtype``, and -infinity is replaced by the + most negative finite floating point value representable by ``x.dtype``. + + For complex dtypes, the above is applied to each of the real and + imaginary components of `x` separately. + + Parameters + ---------- + x : array | float | complex + Input data. + fill_value : int | float, optional + Value to be used to fill NaN values. If no value is passed + then NaN values will be replaced with 0.0. + xp : array_namespace, optional + The standard-compatible namespace for `x`. Default: infer. + + Returns + ------- + array + `x`, with the non-finite values replaced. + + See Also + -------- + array_api.isnan : Shows which elements are Not a Number (NaN). + + Examples + -------- + >>> import array_api_extra as xpx + >>> import array_api_strict as xp + >>> xpx.nan_to_num(xp.inf) + 1.7976931348623157e+308 + >>> xpx.nan_to_num(-xp.inf) + -1.7976931348623157e+308 + >>> xpx.nan_to_num(xp.nan) + 0.0 + >>> x = xp.asarray([xp.inf, -xp.inf, xp.nan, -128, 128]) + >>> xpx.nan_to_num(x) + array([ 1.79769313e+308, -1.79769313e+308, 0.00000000e+000, # may vary + -1.28000000e+002, 1.28000000e+002]) + >>> y = xp.asarray([complex(xp.inf, xp.nan), xp.nan, complex(xp.nan, xp.inf)]) + array([ 1.79769313e+308, -1.79769313e+308, 0.00000000e+000, # may vary + -1.28000000e+002, 1.28000000e+002]) + >>> xpx.nan_to_num(y) + array([ 1.79769313e+308 +0.00000000e+000j, # may vary + 0.00000000e+000 +0.00000000e+000j, + 0.00000000e+000 +1.79769313e+308j]) + """ + if isinstance(fill_value, complex): + msg = "Complex fill values are not supported." + raise TypeError(msg) + + xp = array_namespace(x) if xp is None else xp + + # for scalars we want to output an array + y = xp.asarray(x) + + if ( + is_cupy_namespace(xp) + or is_jax_namespace(xp) + or is_numpy_namespace(xp) + or is_torch_namespace(xp) + ): + return xp.nan_to_num(y, nan=fill_value) + + return _funcs.nan_to_num(y, fill_value=fill_value, xp=xp) + + +def one_hot( + x: Array, + /, + num_classes: int, + *, + dtype: DType | None = None, + axis: int = -1, + xp: ModuleType | None = None, +) -> Array: + """ + One-hot encode the given indices. + + Each index in the input `x` is encoded as a vector of zeros of length `num_classes` + with the element at the given index set to one. + + Parameters + ---------- + x : array + An array with integral dtype whose values are between `0` and `num_classes - 1`. + num_classes : int + Number of classes in the one-hot dimension. + dtype : DType, optional + The dtype of the return value. Defaults to the default float dtype (usually + float64). + axis : int, optional + Position in the expanded axes where the new axis is placed. Default: -1. + xp : array_namespace, optional + The standard-compatible namespace for `x`. Default: infer. + + Returns + ------- + array + An array having the same shape as `x` except for a new axis at the position + given by `axis` having size `num_classes`. If `axis` is unspecified, it + defaults to -1, which appends a new axis. + + If ``x < 0`` or ``x >= num_classes``, then the result is undefined, may raise + an exception, or may even cause a bad state. `x` is not checked. + + Examples + -------- + >>> import array_api_extra as xpx + >>> import array_api_strict as xp + >>> xpx.one_hot(xp.asarray([1, 2, 0]), 3) + Array([[0., 1., 0.], + [0., 0., 1.], + [1., 0., 0.]], dtype=array_api_strict.float64) + """ + # Validate inputs. + if xp is None: + xp = array_namespace(x) + if not xp.isdtype(x.dtype, "integral"): + msg = "x must have an integral dtype." + raise TypeError(msg) + if dtype is None: + dtype = _funcs.default_dtype(xp, device=get_device(x)) + # Delegate where possible. + if is_jax_namespace(xp): + from jax.nn import one_hot as jax_one_hot + + return jax_one_hot(x, num_classes, dtype=dtype, axis=axis) + if is_torch_namespace(xp): + from torch.nn.functional import one_hot as torch_one_hot + + x = xp.astype(x, xp.int64) # PyTorch only supports int64 here. + try: + out = torch_one_hot(x, num_classes) + except RuntimeError as e: + raise IndexError from e + else: + out = _funcs.one_hot(x, num_classes, xp=xp) + out = xp.astype(out, dtype, copy=False) + if axis != -1: + out = xp.moveaxis(out, -1, axis) + return out + + +def pad( + x: Array, + pad_width: int | tuple[int, int] | Sequence[tuple[int, int]], + mode: Literal["constant"] = "constant", + *, + constant_values: complex = 0, + xp: ModuleType | None = None, +) -> Array: + """ + Pad the input array. + + Parameters + ---------- + x : array + Input array. + pad_width : int or tuple of ints or sequence of pairs of ints + Pad the input array with this many elements from each side. + If a sequence of tuples, ``[(before_0, after_0), ... (before_N, after_N)]``, + each pair applies to the corresponding axis of ``x``. + A single tuple, ``(before, after)``, is equivalent to a list of ``x.ndim`` + copies of this tuple. + mode : str, optional + Only "constant" mode is currently supported, which pads with + the value passed to `constant_values`. + constant_values : python scalar, optional + Use this value to pad the input. Default is zero. + xp : array_namespace, optional + The standard-compatible namespace for `x`. Default: infer. + + Returns + ------- + array + The input array, + padded with ``pad_width`` elements equal to ``constant_values``. + """ + xp = array_namespace(x) if xp is None else xp + + if mode != "constant": + msg = "Only `'constant'` mode is currently supported" + raise NotImplementedError(msg) + + if ( + is_numpy_namespace(xp) + or is_cupy_namespace(xp) + or is_jax_namespace(xp) + or is_pydata_sparse_namespace(xp) + ): + return xp.pad(x, pad_width, mode, constant_values=constant_values) + + # https://github.com/pytorch/pytorch/blob/cf76c05b4dc629ac989d1fb8e789d4fac04a095a/torch/_numpy/_funcs_impl.py#L2045-L2056 + if is_torch_namespace(xp): + pad_width = xp.asarray(pad_width) + pad_width = xp.broadcast_to(pad_width, (x.ndim, 2)) + pad_width = xp.flip(pad_width, axis=(0,)).flatten() + return xp.nn.functional.pad(x, tuple(pad_width), value=constant_values) # type: ignore[arg-type] # pyright: ignore[reportArgumentType] + + return _funcs.pad(x, pad_width, constant_values=constant_values, xp=xp) + + +def setdiff1d( + x1: Array | complex, + x2: Array | complex, + /, + *, + assume_unique: bool = False, + xp: ModuleType | None = None, +) -> Array: + """ + Find the set difference of two arrays. + + Return the unique values in `x1` that are not in `x2`. + + Parameters + ---------- + x1 : array | int | float | complex | bool + Input array. + x2 : array + Input comparison array. + assume_unique : bool + If ``True``, the input arrays are both assumed to be unique, which + can speed up the calculation. Default is ``False``. + xp : array_namespace, optional + The standard-compatible namespace for `x1` and `x2`. Default: infer. + + Returns + ------- + array + 1D array of values in `x1` that are not in `x2`. The result + is sorted when `assume_unique` is ``False``, but otherwise only sorted + if the input is sorted. + + Examples + -------- + >>> import array_api_strict as xp + >>> import array_api_extra as xpx + + >>> x1 = xp.asarray([1, 2, 3, 2, 4, 1]) + >>> x2 = xp.asarray([3, 4, 5, 6]) + >>> xpx.setdiff1d(x1, x2, xp=xp) + Array([1, 2], dtype=array_api_strict.int64) + """ + + if xp is None: + xp = array_namespace(x1, x2) + + if is_numpy_namespace(xp) or is_cupy_namespace(xp) or is_jax_namespace(xp): + x1, x2 = asarrays(x1, x2, xp=xp) + return xp.setdiff1d(x1, x2, assume_unique=assume_unique) + + return _funcs.setdiff1d(x1, x2, assume_unique=assume_unique, xp=xp) + + +def sinc(x: Array, /, *, xp: ModuleType | None = None) -> Array: + r""" + Return the normalized sinc function. + + The sinc function is equal to :math:`\sin(\pi x)/(\pi x)` for any argument + :math:`x\ne 0`. ``sinc(0)`` takes the limit value 1, making ``sinc`` not + only everywhere continuous but also infinitely differentiable. + + .. note:: + + Note the normalization factor of ``pi`` used in the definition. + This is the most commonly used definition in signal processing. + Use ``sinc(x / xp.pi)`` to obtain the unnormalized sinc function + :math:`\sin(x)/x` that is more common in mathematics. + + Parameters + ---------- + x : array + Array (possibly multi-dimensional) of values for which to calculate + ``sinc(x)``. Must have a real floating point dtype. + xp : array_namespace, optional + The standard-compatible namespace for `x`. Default: infer. + + Returns + ------- + array + ``sinc(x)`` calculated elementwise, which has the same shape as the input. + + Notes + ----- + The name sinc is short for "sine cardinal" or "sinus cardinalis". + + The sinc function is used in various signal processing applications, + including in anti-aliasing, in the construction of a Lanczos resampling + filter, and in interpolation. + + For bandlimited interpolation of discrete-time signals, the ideal + interpolation kernel is proportional to the sinc function. + + References + ---------- + #. Weisstein, Eric W. "Sinc Function." From MathWorld--A Wolfram Web + Resource. https://mathworld.wolfram.com/SincFunction.html + #. Wikipedia, "Sinc function", + https://en.wikipedia.org/wiki/Sinc_function + + Examples + -------- + >>> import array_api_strict as xp + >>> import array_api_extra as xpx + >>> x = xp.linspace(-4, 4, 41) + >>> xpx.sinc(x, xp=xp) + Array([-3.89817183e-17, -4.92362781e-02, + -8.40918587e-02, -8.90384387e-02, + -5.84680802e-02, 3.89817183e-17, + 6.68206631e-02, 1.16434881e-01, + 1.26137788e-01, 8.50444803e-02, + -3.89817183e-17, -1.03943254e-01, + -1.89206682e-01, -2.16236208e-01, + -1.55914881e-01, 3.89817183e-17, + 2.33872321e-01, 5.04551152e-01, + 7.56826729e-01, 9.35489284e-01, + 1.00000000e+00, 9.35489284e-01, + 7.56826729e-01, 5.04551152e-01, + 2.33872321e-01, 3.89817183e-17, + -1.55914881e-01, -2.16236208e-01, + -1.89206682e-01, -1.03943254e-01, + -3.89817183e-17, 8.50444803e-02, + 1.26137788e-01, 1.16434881e-01, + 6.68206631e-02, 3.89817183e-17, + -5.84680802e-02, -8.90384387e-02, + -8.40918587e-02, -4.92362781e-02, + -3.89817183e-17], dtype=array_api_strict.float64) + """ + + if xp is None: + xp = array_namespace(x) + + if not xp.isdtype(x.dtype, "real floating"): + err_msg = "`x` must have a real floating data type." + raise ValueError(err_msg) + + if ( + is_numpy_namespace(xp) + or is_cupy_namespace(xp) + or is_jax_namespace(xp) + or is_torch_namespace(xp) + or is_dask_namespace(xp) + ): + return xp.sinc(x) + + return _funcs.sinc(x, xp=xp) + + +def partition( + a: Array, + kth: int, + /, + axis: int | None = -1, + *, + xp: ModuleType | None = None, +) -> Array: + """ + Return a partitioned copy of an array. + + Creates a copy of the array and partially sorts it in such a way that the value + of the element in k-th position is in the position it would be in a sorted array. + In the output array, all elements smaller than the k-th element are located to + the left of this element and all equal or greater are located to its right. + The ordering of the elements in the two partitions on the either side of + the k-th element in the output array is undefined. + + Parameters + ---------- + a : Array + Input array. + kth : int + Element index to partition by. + axis : int, optional + Axis along which to partition. The default is ``-1`` (the last axis). + If ``None``, the flattened array is used. + xp : array_namespace, optional + The standard-compatible namespace for `x`. Default: infer. + + Returns + ------- + partitioned_array + Array of the same type and shape as `a`. + + Notes + ----- + If `xp` implements ``partition`` or an equivalent function + (e.g. ``topk`` for torch), complexity will likely be O(n). + If not, this function simply calls ``xp.sort`` and complexity is O(n log n). + """ + # Validate inputs. + if xp is None: + xp = array_namespace(a) + if a.ndim < 1: + msg = "`a` must be at least 1-dimensional" + raise TypeError(msg) + if axis is None: + return partition(xp.reshape(a, (-1,)), kth, axis=0, xp=xp) + (size,) = eager_shape(a, axis) + if not (0 <= kth < size): + msg = f"kth(={kth}) out of bounds [0 {size})" + raise ValueError(msg) + + # Delegate where possible. + if is_numpy_namespace(xp) or is_cupy_namespace(xp) or is_jax_namespace(xp): + return xp.partition(a, kth, axis=axis) + + # Use top-k when possible: + if is_torch_namespace(xp): + if not (axis == -1 or axis == a.ndim - 1): + a = xp.transpose(a, axis, -1) + + out = xp.empty_like(a) + ranks = xp.arange(a.shape[-1]).expand_as(a) + + split_value, indices = xp.kthvalue(a, kth + 1, keepdim=True) + del indices # indices won't be used => del ASAP to reduce peak memory usage + + # fill the left-side of the partition + mask_src = a < split_value + n_left = mask_src.sum(dim=-1, keepdim=True) + mask_dest = ranks < n_left + out[mask_dest] = a[mask_src] + + # fill the middle of the partition + mask_src = a == split_value + n_left += mask_src.sum(dim=-1, keepdim=True) + mask_dest ^= ranks < n_left + out[mask_dest] = a[mask_src] + + # fill the right-side of the partition + mask_src = a > split_value + mask_dest = ranks >= n_left + out[mask_dest] = a[mask_src] + + if not (axis == -1 or axis == a.ndim - 1): + out = xp.transpose(out, axis, -1) + return out + + # Note: dask topk/argtopk sort the return values, so it's + # not much more efficient than sorting everything when + # kth is not small compared to x.size + + return _funcs.partition(a, kth, axis=axis, xp=xp) + + +def argpartition( + a: Array, + kth: int, + /, + axis: int | None = -1, + *, + xp: ModuleType | None = None, +) -> Array: + """ + Perform an indirect partition along the given axis. + + It returns an array of indices of the same shape as `a` that + index data along the given axis in partitioned order. + + Parameters + ---------- + a : Array + Input array. + kth : int + Element index to partition by. + axis : int, optional + Axis along which to partition. The default is ``-1`` (the last axis). + If ``None``, the flattened array is used. + xp : array_namespace, optional + The standard-compatible namespace for `x`. Default: infer. + + Returns + ------- + index_array + Array of indices that partition `a` along the specified axis. + + Notes + ----- + If `xp` implements ``argpartition`` or an equivalent function + e.g. ``topk`` for torch), complexity will likely be O(n). + If not, this function simply calls ``xp.argsort`` and complexity is O(n log n). + """ + # Validate inputs. + if xp is None: + xp = array_namespace(a) + if is_pydata_sparse_namespace(xp): + msg = "Not implemented for sparse backend: no argsort" + raise NotImplementedError(msg) + if a.ndim < 1: + msg = "`a` must be at least 1-dimensional" + raise TypeError(msg) + if axis is None: + return argpartition(xp.reshape(a, (-1,)), kth, axis=0, xp=xp) + (size,) = eager_shape(a, axis) + if not (0 <= kth < size): + msg = f"kth(={kth}) out of bounds [0 {size})" + raise ValueError(msg) + + # Delegate where possible. + if is_numpy_namespace(xp) or is_cupy_namespace(xp) or is_jax_namespace(xp): + return xp.argpartition(a, kth, axis=axis) + + # Use top-k when possible: + if is_torch_namespace(xp): + # see `partition` above for commented details of those steps: + if not (axis == -1 or axis == a.ndim - 1): + a = xp.transpose(a, axis, -1) + + ranks = xp.arange(a.shape[-1]).expand_as(a) + out = xp.empty_like(ranks) + + split_value, indices = xp.kthvalue(a, kth + 1, keepdim=True) + del indices # indices won't be used => del ASAP to reduce peak memory usage + + mask_src = a < split_value + n_left = mask_src.sum(dim=-1, keepdim=True) + mask_dest = ranks < n_left + out[mask_dest] = ranks[mask_src] + + mask_src = a == split_value + n_left += mask_src.sum(dim=-1, keepdim=True) + mask_dest ^= ranks < n_left + out[mask_dest] = ranks[mask_src] + + mask_src = a > split_value + mask_dest = ranks >= n_left + out[mask_dest] = ranks[mask_src] + + if not (axis == -1 or axis == a.ndim - 1): + out = xp.transpose(out, axis, -1) + return out + + # Note: dask topk/argtopk sort the return values, so it's + # not much more efficient than sorting everything when + # kth is not small compared to x.size + + return _funcs.argpartition(a, kth, axis=axis, xp=xp) + + +def isin( + a: Array, + b: Array, + /, + *, + assume_unique: bool = False, + invert: bool = False, + kind: str | None = None, + xp: ModuleType | None = None, +) -> Array: + """ + Determine whether each element in `a` is present in `b`. + + Return a boolean array of the same shape as `a` that is True for elements + that are in `b` and False otherwise. + + Parameters + ---------- + a : array + Input elements. + b : array + The elements against which to test each element of `a`. + assume_unique : bool, optional + If True, the input arrays are both assumed to be unique which can speed + up the calculation. Default: False. + invert : bool, optional + If True, the values in the returned array are inverted. Default: False. + kind : str | None, optional + The algorithm or method to use. This will not affect the final result, + but will affect the speed and memory use. + For NumPy the options are {None, "sort", "table"}. + For Jax the mapped parameter is instead `method` and the options are + {"compare_all", "binary_search", "sort", and "auto" (default)} + For CuPy, Dask, Torch and the default case this parameter is not present and + thus ignored. Default: None. + xp : array_namespace, optional + The standard-compatible namespace for `a` and `b`. Default: infer. + + Returns + ------- + array + An array having the same shape as that of `a` that is True for elements + that are in `b` and False otherwise. + """ + if xp is None: + xp = array_namespace(a, b) + + if is_numpy_namespace(xp): + return xp.isin(a, b, assume_unique=assume_unique, invert=invert, kind=kind) + if is_jax_namespace(xp): + if kind is None: + kind = "auto" + return xp.isin(a, b, assume_unique=assume_unique, invert=invert, method=kind) + if is_cupy_namespace(xp) or is_torch_namespace(xp) or is_dask_namespace(xp): + return xp.isin(a, b, assume_unique=assume_unique, invert=invert) + + return _funcs.isin(a, b, assume_unique=assume_unique, invert=invert, xp=xp) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..d7b3203346da0006f89216d15670be62452d8571 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__init__.py @@ -0,0 +1 @@ +"""Internals of array-api-extra.""" diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d32898906d0e8768e5e465dc11dcc8f23a4d7a8f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/_at.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/_at.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9b6bacfa50f3cde49b733db438a81edaed0b7a81 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/_at.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/_backends.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/_backends.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e4c61f5067168029c98930fd8347fd0fdfe81095 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/_backends.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/_funcs.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/_funcs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..13c47bc79d2cfd49c41d52e3fa5099905a4937c1 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/_funcs.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/_lazy.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/_lazy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e472420fb6c3506fb61ab284ae59e72ec8abec14 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/_lazy.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/_testing.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/_testing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a909be81447626127e2d05b02d638f4dfac63860 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/__pycache__/_testing.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_at.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_at.py new file mode 100644 index 0000000000000000000000000000000000000000..fb2d6ab7e192d1915cfb25808532e26cbacfd655 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_at.py @@ -0,0 +1,463 @@ +"""Update operations for read-only arrays.""" + +from __future__ import annotations + +import operator +from collections.abc import Callable +from enum import Enum +from types import ModuleType +from typing import TYPE_CHECKING, ClassVar, cast + +from ._utils import _compat +from ._utils._compat import ( + array_namespace, + is_dask_array, + is_jax_array, + is_torch_array, + is_writeable_array, +) +from ._utils._helpers import meta_namespace +from ._utils._typing import Array, SetIndex + +if TYPE_CHECKING: # pragma: no cover + # TODO import from typing (requires Python >=3.11) + from typing_extensions import Self + + +class _AtOp(Enum): + """Operations for use in `xpx.at`.""" + + SET = "set" + ADD = "add" + SUBTRACT = "subtract" + MULTIPLY = "multiply" + DIVIDE = "divide" + POWER = "power" + MIN = "min" + MAX = "max" + + # @override from Python 3.12 + def __str__(self) -> str: # pyright: ignore[reportImplicitOverride] + """ + Return string representation (useful for pytest logs). + + Returns + ------- + str + The operation's name. + """ + return self.value + + +class Undef(Enum): + """Sentinel for undefined values.""" + + UNDEF = 0 + + +_undef = Undef.UNDEF + + +class at: # pylint: disable=invalid-name # numpydoc ignore=PR02 + """ + Update operations for read-only arrays. + + This implements ``jax.numpy.ndarray.at`` for all writeable + backends (those that support ``__setitem__``) and routes + to the ``.at[]`` method for JAX arrays. + + Parameters + ---------- + x : array + Input array. + idx : index, optional + Only `array API standard compliant indices + `_ + are supported. + + You may use two alternate syntaxes:: + + >>> import array_api_extra as xpx + >>> xpx.at(x, idx).set(value) # or add(value), etc. + >>> xpx.at(x)[idx].set(value) + + copy : bool, optional + None (default) + The array parameter *may* be modified in place if it is + possible and beneficial for performance. + You should not reuse it after calling this function. + True + Ensure that the inputs are not modified. + False + Ensure that the update operation writes back to the input. + Raise ``ValueError`` if a copy cannot be avoided. + + xp : array_namespace, optional + The standard-compatible namespace for `x`. Default: infer. + + Returns + ------- + Updated input array. + + Warnings + -------- + (a) When you omit the ``copy`` parameter, you should never reuse the parameter + array later on; ideally, you should reassign it immediately:: + + >>> import array_api_extra as xpx + >>> x = xpx.at(x, 0).set(2) + + The above best practice pattern ensures that the behaviour won't change depending + on whether ``x`` is writeable or not, as the original ``x`` object is dereferenced + as soon as ``xpx.at`` returns; this way there is no risk to accidentally update it + twice. + + On the reverse, the anti-pattern below must be avoided, as it will result in + different behaviour on read-only versus writeable arrays:: + + >>> x = xp.asarray([0, 0, 0]) + >>> y = xpx.at(x, 0).set(2) + >>> z = xpx.at(x, 1).set(3) + + In the above example, both calls to ``xpx.at`` update ``x`` in place *if possible*. + This causes the behaviour to diverge depending on whether ``x`` is writeable or not: + + - If ``x`` is writeable, then after the snippet above you'll have + ``x == y == z == [2, 3, 0]`` + - If ``x`` is read-only, then you'll end up with + ``x == [0, 0, 0]``, ``y == [2, 0, 0]`` and ``z == [0, 3, 0]``. + + The correct pattern to use if you want diverging outputs from the same input is + to enforce copies:: + + >>> x = xp.asarray([0, 0, 0]) + >>> y = xpx.at(x, 0).set(2, copy=True) # Never updates x + >>> z = xpx.at(x, 1).set(3) # May or may not update x in place + >>> del x # avoid accidental reuse of x as we don't know its state anymore + + (b) The array API standard does not support integer array indices. + The behaviour of update methods when the index is an array of integers is + undefined and will vary between backends; this is particularly true when the + index contains multiple occurrences of the same index, e.g.:: + + >>> import numpy as np + >>> import jax.numpy as jnp + >>> import array_api_extra as xpx + >>> xpx.at(np.asarray([123]), np.asarray([0, 0])).add(1) + array([124]) + >>> xpx.at(jnp.asarray([123]), jnp.asarray([0, 0])).add(1) + Array([125], dtype=int32) + + See Also + -------- + jax.numpy.ndarray.at : Equivalent array method in JAX. + + Notes + ----- + `sparse `_, as well as read-only arrays from libraries + not explicitly covered by ``array-api-compat``, are not supported by update + methods. + + Boolean masks are supported on Dask and jitted JAX arrays exclusively + when `idx` has the same shape as `x` and `y` is 0-dimensional. + Note that this support is not available in JAX's native + ``x.at[mask].set(y)``. + + This pattern:: + + >>> mask = m(x) + >>> x[mask] = f(x[mask]) + + Can't be replaced by `at`, as it won't work on Dask and JAX inside jax.jit:: + + >>> mask = m(x) + >>> x = xpx.at(x, mask).set(f(x[mask]) # Crash on Dask and jax.jit + + You should instead use:: + + >>> x = xp.where(m(x), f(x), x) + + Examples + -------- + Given either of these equivalent expressions:: + + >>> import array_api_extra as xpx + >>> x = xpx.at(x)[1].add(2) + >>> x = xpx.at(x, 1).add(2) + + If x is a JAX array, they are the same as:: + + >>> x = x.at[1].add(2) + + If x is a read-only NumPy array, they are the same as:: + + >>> x = x.copy() + >>> x[1] += 2 + + For other known backends, they are the same as:: + + >>> x[1] += 2 + """ + + _x: Array + _idx: SetIndex | Undef + __slots__: ClassVar[tuple[str, ...]] = ("_idx", "_x") + + def __init__( + self, x: Array, idx: SetIndex | Undef = _undef, / + ) -> None: # numpydoc ignore=GL08 + self._x = x + self._idx = idx + + def __getitem__(self, idx: SetIndex, /) -> Self: # numpydoc ignore=PR01,RT01 + """ + Allow for the alternate syntax ``at(x)[start:stop:step]``. + + It looks prettier than ``at(x, slice(start, stop, step))`` + and feels more intuitive coming from the JAX documentation. + """ + if self._idx is not _undef: + msg = "Index has already been set" + raise ValueError(msg) + return type(self)(self._x, idx) + + def _op( + self, + at_op: _AtOp, + in_place_op: Callable[[Array, Array | complex], Array] | None, + out_of_place_op: Callable[[Array, Array], Array] | None, + y: Array | complex, + /, + copy: bool | None, + xp: ModuleType | None, + ) -> Array: + """ + Implement all update operations. + + Parameters + ---------- + at_op : _AtOp + Method of JAX's Array.at[]. + in_place_op : Callable[[Array, Array | complex], Array] | None + In-place operation to apply on mutable backends:: + + x[idx] = in_place_op(x[idx], y) + + If None:: + + x[idx] = y + + out_of_place_op : Callable[[Array, Array], Array] | None + Out-of-place operation to apply when idx is a boolean mask and the backend + doesn't support in-place updates:: + + x = xp.where(idx, out_of_place_op(x, y), x) + + If None:: + + x = xp.where(idx, y, x) + + y : array or complex + Right-hand side of the operation. + copy : bool or None + Whether to copy the input array. See the class docstring for details. + xp : array_namespace, optional + The array namespace for the input array. Default: infer. + + Returns + ------- + Array + Updated `x`. + """ + from ._funcs import apply_where # pylint: disable=cyclic-import + + x, idx = self._x, self._idx + xp = array_namespace(x, y) if xp is None else xp + + if isinstance(idx, Undef): + msg = ( + "Index has not been set.\n" + "Usage: either\n" + " at(x, idx).set(value)\n" + "or\n" + " at(x)[idx].set(value)\n" + "(same for all other methods)." + ) + raise ValueError(msg) + + if copy not in (True, False, None): + msg = f"copy must be True, False, or None; got {copy!r}" + raise ValueError(msg) + + writeable = None if copy else is_writeable_array(x) + + # JAX inside jax.jit doesn't support in-place updates with boolean + # masks; Dask exclusively supports __setitem__ but not iops. + # We can handle the common special case of 0-dimensional y + # with where(idx, y, x) instead. + if ( + (is_dask_array(idx) or is_jax_array(idx)) + and idx.dtype == xp.bool + and idx.shape == x.shape + ): + y_xp = xp.asarray(y, dtype=x.dtype, device=_compat.device(x)) + if y_xp.ndim == 0: + if out_of_place_op: # add(), subtract(), ... + # suppress inf warnings on Dask + out = apply_where( + idx, (x, y_xp), out_of_place_op, fill_value=x, xp=xp + ) + # Undo int->float promotion on JAX after _AtOp.DIVIDE + out = xp.astype(out, x.dtype, copy=False) + else: # set() + out = xp.where(idx, y_xp, x) + + if copy is False: + x[()] = out + return x + return out + + # else: this will work on eager JAX and crash on jax.jit and Dask + + if copy or (copy is None and not writeable): + if is_jax_array(x): + # Use JAX's at[] + func = cast( + Callable[[Array | complex], Array], + getattr(x.at[idx], at_op.value), # type: ignore[attr-defined] # pyright: ignore[reportAttributeAccessIssue,reportUnknownArgumentType] + ) + out = func(y) + # Undo int->float promotion on JAX after _AtOp.DIVIDE + return xp.astype(out, x.dtype, copy=False) + + # Emulate at[] behaviour for non-JAX arrays + # with a copy followed by an update + + x = xp.asarray(x, copy=True) + # A copy of a read-only numpy array is writeable + # Note: this assumes that a copy of a writeable array is writeable + assert not writeable + writeable = None + + if writeable is None: + writeable = is_writeable_array(x) + if not writeable: + # sparse crashes here + msg = f"Can't update read-only array {x}" + raise ValueError(msg) + + # Work around bug in PyTorch where __setitem__ doesn't + # always support mismatched dtypes + # https://github.com/pytorch/pytorch/issues/150017 + if is_torch_array(y): + y = xp.astype(y, x.dtype, copy=False) + + # Backends without boolean indexing (other than JAX) crash here + if in_place_op: # add(), subtract(), ... + x[idx] = in_place_op(x[idx], y) + else: # set() + x[idx] = y + return x + + def set( + self, + y: Array | complex, + /, + copy: bool | None = None, + xp: ModuleType | None = None, + ) -> Array: # numpydoc ignore=PR01,RT01 + """Apply ``x[idx] = y`` and return the update array.""" + return self._op(_AtOp.SET, None, None, y, copy=copy, xp=xp) + + def add( + self, + y: Array | complex, + /, + copy: bool | None = None, + xp: ModuleType | None = None, + ) -> Array: # numpydoc ignore=PR01,RT01 + """Apply ``x[idx] += y`` and return the updated array.""" + + # Note for this and all other methods based on _iop: + # operator.iadd and operator.add subtly differ in behaviour, as + # only iadd will trigger exceptions when y has an incompatible dtype. + return self._op(_AtOp.ADD, operator.iadd, operator.add, y, copy=copy, xp=xp) + + def subtract( + self, + y: Array | complex, + /, + copy: bool | None = None, + xp: ModuleType | None = None, + ) -> Array: # numpydoc ignore=PR01,RT01 + """Apply ``x[idx] -= y`` and return the updated array.""" + return self._op( + _AtOp.SUBTRACT, operator.isub, operator.sub, y, copy=copy, xp=xp + ) + + def multiply( + self, + y: Array | complex, + /, + copy: bool | None = None, + xp: ModuleType | None = None, + ) -> Array: # numpydoc ignore=PR01,RT01 + """Apply ``x[idx] *= y`` and return the updated array.""" + return self._op( + _AtOp.MULTIPLY, operator.imul, operator.mul, y, copy=copy, xp=xp + ) + + def divide( + self, + y: Array | complex, + /, + copy: bool | None = None, + xp: ModuleType | None = None, + ) -> Array: # numpydoc ignore=PR01,RT01 + """Apply ``x[idx] /= y`` and return the updated array.""" + return self._op( + _AtOp.DIVIDE, operator.itruediv, operator.truediv, y, copy=copy, xp=xp + ) + + def power( + self, + y: Array | complex, + /, + copy: bool | None = None, + xp: ModuleType | None = None, + ) -> Array: # numpydoc ignore=PR01,RT01 + """Apply ``x[idx] **= y`` and return the updated array.""" + return self._op(_AtOp.POWER, operator.ipow, operator.pow, y, copy=copy, xp=xp) + + def min( + self, + y: Array | complex, + /, + copy: bool | None = None, + xp: ModuleType | None = None, + ) -> Array: # numpydoc ignore=PR01,RT01 + """Apply ``x[idx] = minimum(x[idx], y)`` and return the updated array.""" + # On Dask, this function runs on the chunks, so we need to determine the + # namespace that Dask is wrapping. + # Note that da.minimum _incidentally_ works on NumPy, CuPy, and sparse + # thanks to all these meta-namespaces implementing the __array_ufunc__ + # interface, but there's no guarantee that it will work for other + # wrapped libraries in the future. + xp = array_namespace(self._x) if xp is None else xp + mxp = meta_namespace(self._x, xp=xp) + y = xp.asarray(y) + return self._op(_AtOp.MIN, mxp.minimum, mxp.minimum, y, copy=copy, xp=xp) + + def max( + self, + y: Array | complex, + /, + copy: bool | None = None, + xp: ModuleType | None = None, + ) -> Array: # numpydoc ignore=PR01,RT01 + """Apply ``x[idx] = maximum(x[idx], y)`` and return the updated array.""" + # See note on min() + xp = array_namespace(self._x) if xp is None else xp + mxp = meta_namespace(self._x, xp=xp) + y = xp.asarray(y) + return self._op(_AtOp.MAX, mxp.maximum, mxp.maximum, y, copy=copy, xp=xp) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_backends.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_backends.py new file mode 100644 index 0000000000000000000000000000000000000000..936f5dd0a88618099d66e00de7a49d97b65d159e --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_backends.py @@ -0,0 +1,72 @@ +"""Backends against which array-api-extra runs its tests.""" + +from __future__ import annotations + +from enum import Enum +from typing import Any + +import numpy as np +import pytest + +__all__ = ["NUMPY_VERSION", "Backend"] + +NUMPY_VERSION = tuple(int(v) for v in np.__version__.split(".")[:3]) # pyright: ignore[reportUnknownArgumentType] + + +class Backend(Enum): # numpydoc ignore=PR02 + """ + All array library backends explicitly tested by array-api-extra. + + Parameters + ---------- + value : str + Tag of the backend's module, in the format ``[:]``. + """ + + # Use : to prevent Enum from deduplicating items with the same value + ARRAY_API_STRICT = "array_api_strict" + ARRAY_API_STRICTEST = "array_api_strict:strictest" + NUMPY = "numpy" + NUMPY_READONLY = "numpy:readonly" + CUPY = "cupy" + TORCH = "torch" + TORCH_GPU = "torch:gpu" + DASK = "dask.array" + SPARSE = "sparse" + JAX = "jax.numpy" + JAX_GPU = "jax.numpy:gpu" + + @property + def modname(self) -> str: # numpydoc ignore=RT01 + """Module name to be imported.""" + return self.value.split(":")[0] + + def like(self, *others: Backend) -> bool: # numpydoc ignore=PR01,RT01 + """Check if this backend uses the same module as others.""" + return any(self.modname == other.modname for other in others) + + def pytest_param(self) -> Any: + """ + Backend as a pytest parameter + + Returns + ------- + pytest.mark.ParameterSet + """ + id_ = ( + self.name.lower().replace("_gpu", ":gpu").replace("_readonly", ":readonly") + ) + + marks = [] + if self.like(Backend.ARRAY_API_STRICT): + marks.append( + pytest.mark.skipif( + NUMPY_VERSION < (1, 26), + reason="array_api_strict is untested on NumPy <1.26", + ) + ) + if self.like(Backend.DASK, Backend.JAX): + # Monkey-patched by lazy_xp_function + marks.append(pytest.mark.thread_unsafe) + + return pytest.param(self, id=id_, marks=marks) # pyright: ignore[reportUnknownArgumentType] diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_funcs.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_funcs.py new file mode 100644 index 0000000000000000000000000000000000000000..6e50ce95c80c83eb61f3d3b91d92e05f06186e9c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_funcs.py @@ -0,0 +1,744 @@ +"""Array-agnostic implementations for the public API.""" + +import math +import warnings +from collections.abc import Callable, Sequence +from types import ModuleType, NoneType +from typing import Literal, cast, overload + +from ._at import at +from ._utils import _compat, _helpers +from ._utils._compat import array_namespace, is_dask_namespace, is_jax_array +from ._utils._helpers import ( + asarrays, + capabilities, + eager_shape, + meta_namespace, + ndindex, +) +from ._utils._typing import Array, Device, DType + +__all__ = [ + "apply_where", + "atleast_nd", + "broadcast_shapes", + "cov", + "create_diagonal", + "expand_dims", + "kron", + "nunique", + "pad", + "setdiff1d", + "sinc", +] + + +@overload +def apply_where( # numpydoc ignore=GL08 + cond: Array, + args: Array | tuple[Array, ...], + f1: Callable[..., Array], + f2: Callable[..., Array], + /, + *, + xp: ModuleType | None = None, +) -> Array: ... + + +@overload +def apply_where( # numpydoc ignore=GL08 + cond: Array, + args: Array | tuple[Array, ...], + f1: Callable[..., Array], + /, + *, + fill_value: Array | complex, + xp: ModuleType | None = None, +) -> Array: ... + + +def apply_where( # numpydoc ignore=PR01,PR02 + cond: Array, + args: Array | tuple[Array, ...], + f1: Callable[..., Array], + f2: Callable[..., Array] | None = None, + /, + *, + fill_value: Array | complex | None = None, + xp: ModuleType | None = None, +) -> Array: + """ + Run one of two elementwise functions depending on a condition. + + Equivalent to ``f1(*args) if cond else fill_value`` performed elementwise + when `fill_value` is defined, otherwise to ``f1(*args) if cond else f2(*args)``. + + Parameters + ---------- + cond : array + The condition, expressed as a boolean array. + args : Array or tuple of Arrays + Argument(s) to `f1` (and `f2`). Must be broadcastable with `cond`. + f1 : callable + Elementwise function of `args`, returning a single array. + Where `cond` is True, output will be ``f1(arg0[cond], arg1[cond], ...)``. + f2 : callable, optional + Elementwise function of `args`, returning a single array. + Where `cond` is False, output will be ``f2(arg0[cond], arg1[cond], ...)``. + Mutually exclusive with `fill_value`. + fill_value : Array or scalar, optional + If provided, value with which to fill output array where `cond` is False. + It does not need to be scalar; it needs however to be broadcastable with + `cond` and `args`. + Mutually exclusive with `f2`. You must provide one or the other. + xp : array_namespace, optional + The standard-compatible namespace for `cond` and `args`. Default: infer. + + Returns + ------- + Array + An array with elements from the output of `f1` where `cond` is True and either + the output of `f2` or `fill_value` where `cond` is False. The returned array has + data type determined by type promotion rules between the output of `f1` and + either `fill_value` or the output of `f2`. + + Notes + ----- + ``xp.where(cond, f1(*args), f2(*args))`` requires explicitly evaluating `f1` even + when `cond` is False, and `f2` when cond is True. This function evaluates each + function only for their matching condition, if the backend allows for it. + + On Dask, `f1` and `f2` are applied to the individual chunks and should use functions + from the namespace of the chunks. + + Examples + -------- + >>> import array_api_strict as xp + >>> import array_api_extra as xpx + >>> a = xp.asarray([5, 4, 3]) + >>> b = xp.asarray([0, 2, 2]) + >>> def f(a, b): + ... return a // b + >>> xpx.apply_where(b != 0, (a, b), f, fill_value=xp.nan) + array([ nan, 2., 1.]) + """ + # Parse and normalize arguments + if (f2 is None) == (fill_value is None): + msg = "Exactly one of `fill_value` or `f2` must be given." + raise TypeError(msg) + args_ = list(args) if isinstance(args, tuple) else [args] + del args + + xp = array_namespace(cond, fill_value, *args_) if xp is None else xp + + if isinstance(fill_value, int | float | complex | NoneType): + cond, *args_ = xp.broadcast_arrays(cond, *args_) + else: + cond, fill_value, *args_ = xp.broadcast_arrays(cond, fill_value, *args_) + + if is_dask_namespace(xp): + meta_xp = meta_namespace(cond, fill_value, *args_, xp=xp) + # map_blocks doesn't descend into tuples of Arrays + return xp.map_blocks(_apply_where, cond, f1, f2, fill_value, *args_, xp=meta_xp) + return _apply_where(cond, f1, f2, fill_value, *args_, xp=xp) + + +def _apply_where( # numpydoc ignore=PR01,RT01 + cond: Array, + f1: Callable[..., Array], + f2: Callable[..., Array] | None, + fill_value: Array | int | float | complex | bool | None, + *args: Array, + xp: ModuleType, +) -> Array: + """Helper of `apply_where`. On Dask, this runs on a single chunk.""" + + if not capabilities(xp, device=_compat.device(cond))["boolean indexing"]: + # jax.jit does not support assignment by boolean mask + return xp.where(cond, f1(*args), f2(*args) if f2 is not None else fill_value) + + temp1 = f1(*(arr[cond] for arr in args)) + + if f2 is None: + dtype = xp.result_type(temp1, fill_value) + if isinstance(fill_value, int | float | complex): + out = xp.full_like(cond, dtype=dtype, fill_value=fill_value) + else: + out = xp.astype(fill_value, dtype, copy=True) + else: + ncond = ~cond + temp2 = f2(*(arr[ncond] for arr in args)) + dtype = xp.result_type(temp1, temp2) + out = xp.empty_like(cond, dtype=dtype) + out = at(out, ncond).set(temp2) + + return at(out, cond).set(temp1) + + +def atleast_nd(x: Array, /, *, ndim: int, xp: ModuleType) -> Array: + # numpydoc ignore=PR01,RT01 + """See docstring in array_api_extra._delegation.""" + + if x.ndim < ndim: + x = xp.expand_dims(x, axis=0) + x = atleast_nd(x, ndim=ndim, xp=xp) + return x + + +# `float` in signature to accept `math.nan` for Dask. +# `int`s are still accepted as `float` is a superclass of `int` in typing +def broadcast_shapes(*shapes: tuple[float | None, ...]) -> tuple[int | None, ...]: + """ + Compute the shape of the broadcasted arrays. + + Duplicates :func:`numpy.broadcast_shapes`, with additional support for + None and NaN sizes. + + This is equivalent to ``xp.broadcast_arrays(arr1, arr2, ...)[0].shape`` + without needing to worry about the backend potentially deep copying + the arrays. + + Parameters + ---------- + *shapes : tuple[int | None, ...] + Shapes of the arrays to broadcast. + + Returns + ------- + tuple[int | None, ...] + The shape of the broadcasted arrays. + + See Also + -------- + numpy.broadcast_shapes : Equivalent NumPy function. + array_api.broadcast_arrays : Function to broadcast actual arrays. + + Notes + ----- + This function accepts the Array API's ``None`` for unknown sizes, + as well as Dask's non-standard ``math.nan``. + Regardless of input, the output always contains ``None`` for unknown sizes. + + Examples + -------- + >>> import array_api_extra as xpx + >>> xpx.broadcast_shapes((2, 3), (2, 1)) + (2, 3) + >>> xpx.broadcast_shapes((4, 2, 3), (2, 1), (1, 3)) + (4, 2, 3) + """ + if not shapes: + return () # Match NumPy output + + ndim = max(len(shape) for shape in shapes) + out: list[int | None] = [] + for axis in range(-ndim, 0): + sizes = {shape[axis] for shape in shapes if axis >= -len(shape)} + # Dask uses NaN for unknown shape, which predates the Array API spec for None + none_size = None in sizes or math.nan in sizes # noqa: PLW0177 + sizes -= {1, None, math.nan} + if len(sizes) > 1: + msg = ( + "shape mismatch: objects cannot be broadcast to a single shape: " + f"{shapes}." + ) + raise ValueError(msg) + out.append(None if none_size else cast(int, sizes.pop()) if sizes else 1) + + return tuple(out) + + +def cov(m: Array, /, *, xp: ModuleType) -> Array: # numpydoc ignore=PR01,RT01 + """See docstring in array_api_extra._delegation.""" + m = xp.asarray(m, copy=True) + dtype = ( + xp.float64 if xp.isdtype(m.dtype, "integral") else xp.result_type(m, xp.float64) + ) + + m = atleast_nd(m, ndim=2, xp=xp) + m = xp.astype(m, dtype) + + avg = _helpers.mean(m, axis=-1, keepdims=True, xp=xp) + + m_shape = eager_shape(m) + fact = m_shape[-1] - 1 + + if fact <= 0: + warnings.warn("Degrees of freedom <= 0 for slice", RuntimeWarning, stacklevel=2) + fact = 0 + + m -= avg + m_transpose = xp.matrix_transpose(m) + if xp.isdtype(m_transpose.dtype, "complex floating"): + m_transpose = xp.conj(m_transpose) + c = xp.matmul(m, m_transpose) + c /= fact + axes = tuple(axis for axis, length in enumerate(c.shape) if length == 1) + return xp.squeeze(c, axis=axes) + + +def one_hot( + x: Array, + /, + num_classes: int, + *, + xp: ModuleType, +) -> Array: # numpydoc ignore=PR01,RT01 + """See docstring in `array_api_extra._delegation.py`.""" + # TODO: Benchmark whether this is faster on the NumPy backend: + # if is_numpy_array(x): + # out = xp.zeros((x.size, num_classes), dtype=dtype) + # out[xp.arange(x.size), xp.reshape(x, (-1,))] = 1 + # return xp.reshape(out, (*x.shape, num_classes)) + range_num_classes = xp.arange(num_classes, dtype=x.dtype, device=_compat.device(x)) + return x[..., xp.newaxis] == range_num_classes + + +def create_diagonal( + x: Array, /, *, offset: int = 0, xp: ModuleType +) -> Array: # numpydoc ignore=PR01,RT01 + """See docstring in array_api_extra._delegation.""" + x_shape = eager_shape(x) + batch_dims = x_shape[:-1] + n = x_shape[-1] + abs(offset) + diag = xp.zeros((*batch_dims, n**2), dtype=x.dtype, device=_compat.device(x)) + + target_slice = slice( + offset if offset >= 0 else abs(offset) * n, + min(n * (n - offset), diag.shape[-1]), + n + 1, + ) + for index in ndindex(*batch_dims): + diag = at(diag)[(*index, target_slice)].set(x[(*index, slice(None))]) + return xp.reshape(diag, (*batch_dims, n, n)) + + +def default_dtype( + xp: ModuleType, + kind: Literal[ + "real floating", "complex floating", "integral", "indexing" + ] = "real floating", + *, + device: Device | None = None, +) -> DType: + """ + Return the default dtype for the given namespace and device. + + This is a convenience shorthand for + ``xp.__array_namespace_info__().default_dtypes(device=device)[kind]``. + + Parameters + ---------- + xp : array_namespace + The standard-compatible namespace for which to get the default dtype. + kind : {'real floating', 'complex floating', 'integral', 'indexing'}, optional + The kind of dtype to return. Default is 'real floating'. + device : Device, optional + The device for which to get the default dtype. Default: current device. + + Returns + ------- + dtype + The default dtype for the given namespace, kind, and device. + """ + dtypes = xp.__array_namespace_info__().default_dtypes(device=device) + try: + return dtypes[kind] + except KeyError as e: + domain = ("real floating", "complex floating", "integral", "indexing") + assert set(dtypes) == set(domain), f"Non-compliant namespace: {dtypes}" + msg = f"Unknown kind '{kind}'. Expected one of {domain}." + raise ValueError(msg) from e + + +def expand_dims(a: Array, /, *, axis: tuple[int, ...] = (0,), xp: ModuleType) -> Array: + # numpydoc ignore=PR01,RT01 + """See docstring in array_api_extra._delegation.""" + for i in sorted(axis): + a = xp.expand_dims(a, axis=i) + return a + + +def isclose( + a: Array | complex, + b: Array | complex, + *, + rtol: float = 1e-05, + atol: float = 1e-08, + equal_nan: bool = False, + xp: ModuleType, +) -> Array: # numpydoc ignore=PR01,RT01 + """See docstring in array_api_extra._delegation.""" + a, b = asarrays(a, b, xp=xp) + + a_inexact = xp.isdtype(a.dtype, ("real floating", "complex floating")) + b_inexact = xp.isdtype(b.dtype, ("real floating", "complex floating")) + if a_inexact or b_inexact: + # prevent warnings on NumPy and Dask on inf - inf + mxp = meta_namespace(a, b, xp=xp) + out = apply_where( + xp.isinf(a) | xp.isinf(b), + (a, b), + lambda a, b: mxp.isinf(a) & mxp.isinf(b) & (mxp.sign(a) == mxp.sign(b)), # pyright: ignore[reportUnknownArgumentType] + # Note: inf <= inf is True! + lambda a, b: mxp.abs(a - b) <= (atol + rtol * mxp.abs(b)), # pyright: ignore[reportUnknownArgumentType] + xp=xp, + ) + if equal_nan: + out = xp.where(xp.isnan(a) & xp.isnan(b), True, out) + return out + + if xp.isdtype(a.dtype, "bool") or xp.isdtype(b.dtype, "bool"): + if atol >= 1 or rtol >= 1: + return xp.ones_like(a == b) + return a == b + + # integer types + atol = int(atol) + if rtol == 0: + return xp.abs(a - b) <= atol + + # Don't rely on OverflowError, as it is not guaranteed by the Array API. + nrtol = int(1.0 / rtol) + if nrtol > xp.iinfo(b.dtype).max: + # rtol * max_int < 1, so it's inconsequential + return xp.abs(a - b) <= atol + return xp.abs(a - b) <= (atol + xp.abs(b) // nrtol) + + +def kron( + a: Array | complex, + b: Array | complex, + /, + *, + xp: ModuleType | None = None, +) -> Array: + """ + Kronecker product of two arrays. + + Computes the Kronecker product, a composite array made of blocks of the + second array scaled by the first. + + Equivalent to ``numpy.kron`` for NumPy arrays. + + Parameters + ---------- + a, b : Array | int | float | complex + Input arrays or scalars. At least one must be an array. + xp : array_namespace, optional + The standard-compatible namespace for `a` and `b`. Default: infer. + + Returns + ------- + array + The Kronecker product of `a` and `b`. + + Notes + ----- + The function assumes that the number of dimensions of `a` and `b` + are the same, if necessary prepending the smallest with ones. + If ``a.shape = (r0,r1,..,rN)`` and ``b.shape = (s0,s1,...,sN)``, + the Kronecker product has shape ``(r0*s0, r1*s1, ..., rN*SN)``. + The elements are products of elements from `a` and `b`, organized + explicitly by:: + + kron(a,b)[k0,k1,...,kN] = a[i0,i1,...,iN] * b[j0,j1,...,jN] + + where:: + + kt = it * st + jt, t = 0,...,N + + In the common 2-D case (N=1), the block structure can be visualized:: + + [[ a[0,0]*b, a[0,1]*b, ... , a[0,-1]*b ], + [ ... ... ], + [ a[-1,0]*b, a[-1,1]*b, ... , a[-1,-1]*b ]] + + Examples + -------- + >>> import array_api_strict as xp + >>> import array_api_extra as xpx + >>> xpx.kron(xp.asarray([1, 10, 100]), xp.asarray([5, 6, 7]), xp=xp) + Array([ 5, 6, 7, 50, 60, 70, 500, + 600, 700], dtype=array_api_strict.int64) + + >>> xpx.kron(xp.asarray([5, 6, 7]), xp.asarray([1, 10, 100]), xp=xp) + Array([ 5, 50, 500, 6, 60, 600, 7, + 70, 700], dtype=array_api_strict.int64) + + >>> xpx.kron(xp.eye(2), xp.ones((2, 2)), xp=xp) + Array([[1., 1., 0., 0.], + [1., 1., 0., 0.], + [0., 0., 1., 1.], + [0., 0., 1., 1.]], dtype=array_api_strict.float64) + + >>> a = xp.reshape(xp.arange(100), (2, 5, 2, 5)) + >>> b = xp.reshape(xp.arange(24), (2, 3, 4)) + >>> c = xpx.kron(a, b, xp=xp) + >>> c.shape + (2, 10, 6, 20) + >>> I = (1, 3, 0, 2) + >>> J = (0, 2, 1) + >>> J1 = (0,) + J # extend to ndim=4 + >>> S1 = (1,) + b.shape + >>> K = tuple(xp.asarray(I) * xp.asarray(S1) + xp.asarray(J1)) + >>> c[K] == a[I]*b[J] + Array(True, dtype=array_api_strict.bool) + """ + if xp is None: + xp = array_namespace(a, b) + a, b = asarrays(a, b, xp=xp) + + singletons = (1,) * (b.ndim - a.ndim) + a = cast(Array, xp.broadcast_to(a, singletons + a.shape)) + + nd_b, nd_a = b.ndim, a.ndim + nd_max = max(nd_b, nd_a) + if nd_a == 0 or nd_b == 0: + return xp.multiply(a, b) + + a_shape = eager_shape(a) + b_shape = eager_shape(b) + + # Equalise the shapes by prepending smaller one with 1s + a_shape = (1,) * max(0, nd_b - nd_a) + a_shape + b_shape = (1,) * max(0, nd_a - nd_b) + b_shape + + # Insert empty dimensions + a_arr = expand_dims(a, axis=tuple(range(nd_b - nd_a)), xp=xp) + b_arr = expand_dims(b, axis=tuple(range(nd_a - nd_b)), xp=xp) + + # Compute the product + a_arr = expand_dims(a_arr, axis=tuple(range(1, nd_max * 2, 2)), xp=xp) + b_arr = expand_dims(b_arr, axis=tuple(range(0, nd_max * 2, 2)), xp=xp) + result = xp.multiply(a_arr, b_arr) + + # Reshape back and return + res_shape = tuple(a_s * b_s for a_s, b_s in zip(a_shape, b_shape, strict=True)) + return xp.reshape(result, res_shape) + + +def nan_to_num( # numpydoc ignore=PR01,RT01 + x: Array, + /, + fill_value: int | float = 0.0, + *, + xp: ModuleType, +) -> Array: + """See docstring in `array_api_extra._delegation.py`.""" + + def perform_replacements( # numpydoc ignore=PR01,RT01 + x: Array, + fill_value: int | float, + xp: ModuleType, + ) -> Array: + """Internal function to perform the replacements.""" + x = xp.where(xp.isnan(x), fill_value, x) + + # convert infinities to finite values + finfo = xp.finfo(x.dtype) + idx_posinf = xp.isinf(x) & ~xp.signbit(x) + idx_neginf = xp.isinf(x) & xp.signbit(x) + x = xp.where(idx_posinf, finfo.max, x) + return xp.where(idx_neginf, finfo.min, x) + + if xp.isdtype(x.dtype, "complex floating"): + return perform_replacements( + xp.real(x), + fill_value, + xp, + ) + 1j * perform_replacements( + xp.imag(x), + fill_value, + xp, + ) + + if xp.isdtype(x.dtype, "numeric"): + return perform_replacements(x, fill_value, xp) + + return x + + +def nunique(x: Array, /, *, xp: ModuleType | None = None) -> Array: + """ + Count the number of unique elements in an array. + + Compatible with JAX and Dask, whose laziness would be otherwise + problematic. + + Parameters + ---------- + x : Array + Input array. + xp : array_namespace, optional + The standard-compatible namespace for `x`. Default: infer. + + Returns + ------- + array: 0-dimensional integer array + The number of unique elements in `x`. It can be lazy. + """ + if xp is None: + xp = array_namespace(x) + + if is_jax_array(x): + # size= is JAX-specific + # https://github.com/data-apis/array-api/issues/883 + _, counts = xp.unique_counts(x, size=_compat.size(x)) + return (counts > 0).sum() + + # There are 3 general use cases: + # 1. backend has unique_counts and it returns an array with known shape + # 2. backend has unique_counts and it returns a None-sized array; + # e.g. Dask, ndonnx + # 3. backend does not have unique_counts; e.g. wrapped JAX + if capabilities(xp, device=_compat.device(x))["data-dependent shapes"]: + # xp has unique_counts; O(n) complexity + _, counts = xp.unique_counts(x) + n = _compat.size(counts) + if n is None: + return xp.sum(xp.ones_like(counts)) + return xp.asarray(n, device=_compat.device(x)) + + # xp does not have unique_counts; O(n*logn) complexity + x = xp.reshape(x, (-1,)) + x = xp.sort(x, stable=False) + mask = x != xp.roll(x, -1) + default_int = default_dtype(xp, "integral", device=_compat.device(x)) + return xp.maximum( + # Special cases: + # - array is size 0 + # - array has all elements equal to each other + xp.astype(xp.any(~mask), default_int), + xp.sum(xp.astype(mask, default_int)), + ) + + +def pad( + x: Array, + pad_width: int | tuple[int, int] | Sequence[tuple[int, int]], + *, + constant_values: complex = 0, + xp: ModuleType, +) -> Array: # numpydoc ignore=PR01,RT01 + """See docstring in `array_api_extra._delegation.py`.""" + # make pad_width a list of length-2 tuples of ints + if isinstance(pad_width, int): + pad_width_seq = [(pad_width, pad_width)] * x.ndim + elif ( + isinstance(pad_width, tuple) + and len(pad_width) == 2 + and all(isinstance(i, int) for i in pad_width) + ): + pad_width_seq = [cast(tuple[int, int], pad_width)] * x.ndim + else: + pad_width_seq = cast(list[tuple[int, int]], list(pad_width)) + + slices: list[slice] = [] + newshape: list[int] = [] + for ax, w_tpl in enumerate(pad_width_seq): + if len(w_tpl) != 2: + msg = f"expect a 2-tuple (before, after), got {w_tpl}." + raise ValueError(msg) + + sh = eager_shape(x)[ax] + + if w_tpl[0] == 0 and w_tpl[1] == 0: + sl = slice(None, None, None) + else: + stop: int | None + start, stop = w_tpl + stop = None if stop == 0 else -stop + + sl = slice(start, stop, None) + sh += w_tpl[0] + w_tpl[1] + + newshape.append(sh) + slices.append(sl) + + padded = xp.full( + tuple(newshape), + fill_value=constant_values, + dtype=x.dtype, + device=_compat.device(x), + ) + return at(padded, tuple(slices)).set(x) + + +def setdiff1d( + x1: Array | complex, + x2: Array | complex, + /, + *, + assume_unique: bool = False, + xp: ModuleType, +) -> Array: # numpydoc ignore=PR01,RT01 + """See docstring in `array_api_extra._delegation.py`.""" + + # https://github.com/microsoft/pyright/issues/10103 + x1_, x2_ = asarrays(x1, x2, xp=xp) + + if assume_unique: + x1_ = xp.reshape(x1_, (-1,)) + x2_ = xp.reshape(x2_, (-1,)) + else: + x1_ = xp.unique_values(x1_) + x2_ = xp.unique_values(x2_) + + return x1_[_helpers.in1d(x1_, x2_, assume_unique=True, invert=True, xp=xp)] + + +def sinc(x: Array, /, *, xp: ModuleType) -> Array: + # numpydoc ignore=PR01,RT01 + """See docstring in `array_api_extra._delegation.py`.""" + + # no scalars in `where` - array-api#807 + y = xp.pi * xp.where( + xp.astype(x, xp.bool), + x, + xp.asarray(xp.finfo(x.dtype).eps, dtype=x.dtype, device=_compat.device(x)), + ) + return xp.sin(y) / y + + +def partition( # numpydoc ignore=PR01,RT01 + x: Array, + kth: int, # noqa: ARG001 + /, + axis: int = -1, + *, + xp: ModuleType, +) -> Array: + """See docstring in `array_api_extra._delegation.py`.""" + return xp.sort(x, axis=axis, stable=False) + + +def argpartition( # numpydoc ignore=PR01,RT01 + x: Array, + kth: int, # noqa: ARG001 + /, + axis: int = -1, + *, + xp: ModuleType, +) -> Array: + """See docstring in `array_api_extra._delegation.py`.""" + return xp.argsort(x, axis=axis, stable=False) + + +def isin( # numpydoc ignore=PR01,RT01 + a: Array, + b: Array, + /, + *, + assume_unique: bool = False, + invert: bool = False, + xp: ModuleType, +) -> Array: + """See docstring in `array_api_extra._delegation.py`.""" + original_a_shape = a.shape + a = xp.reshape(a, (-1,)) + b = xp.reshape(b, (-1,)) + return xp.reshape( + _helpers.in1d(a, b, assume_unique=assume_unique, invert=invert, xp=xp), + original_a_shape, + ) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_lazy.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_lazy.py new file mode 100644 index 0000000000000000000000000000000000000000..d509500132a4b8886f5ccca93d7d6bd2aa25b4dc --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_lazy.py @@ -0,0 +1,357 @@ +"""Public API Functions.""" + +from __future__ import annotations + +import math +from collections.abc import Callable, Sequence +from functools import partial, wraps +from types import ModuleType +from typing import TYPE_CHECKING, Any, ParamSpec, TypeAlias, cast, overload + +from ._funcs import broadcast_shapes +from ._utils import _compat +from ._utils._compat import ( + array_namespace, + is_dask_namespace, + is_jax_namespace, +) +from ._utils._helpers import is_python_scalar +from ._utils._typing import Array, DType + +if TYPE_CHECKING: # pragma: no cover + import numpy as np + from numpy.typing import ArrayLike + + NumPyObject: TypeAlias = np.ndarray[Any, Any] | np.generic +else: + # Sphinx hack + NumPyObject = Any + +P = ParamSpec("P") + + +@overload +def lazy_apply( # type: ignore[valid-type] + func: Callable[P, Array | ArrayLike], + *args: Array | complex | None, + shape: tuple[int | None, ...] | None = None, + dtype: DType | None = None, + as_numpy: bool = False, + xp: ModuleType | None = None, + **kwargs: P.kwargs, # pyright: ignore[reportGeneralTypeIssues] +) -> Array: ... # numpydoc ignore=GL08 + + +@overload +def lazy_apply( # type: ignore[valid-type] + func: Callable[P, Sequence[Array | ArrayLike]], + *args: Array | complex | None, + shape: Sequence[tuple[int | None, ...]], + dtype: Sequence[DType] | None = None, + as_numpy: bool = False, + xp: ModuleType | None = None, + **kwargs: P.kwargs, # pyright: ignore[reportGeneralTypeIssues] +) -> tuple[Array, ...]: ... # numpydoc ignore=GL08 + + +def lazy_apply( # type: ignore[valid-type] # numpydoc ignore=GL07,SA04 + func: Callable[P, Array | ArrayLike | Sequence[Array | ArrayLike]], + *args: Array | complex | None, + shape: tuple[int | None, ...] | Sequence[tuple[int | None, ...]] | None = None, + dtype: DType | Sequence[DType] | None = None, + as_numpy: bool = False, + xp: ModuleType | None = None, + **kwargs: P.kwargs, # pyright: ignore[reportGeneralTypeIssues] +) -> Array | tuple[Array, ...]: + """ + Lazily apply an eager function. + + If the backend of the input arrays is lazy, e.g. Dask or jitted JAX, the execution + of the function is delayed until the graph is materialized; if it's eager, the + function is executed immediately. + + Parameters + ---------- + func : callable + The function to apply. + + It must accept one or more array API compliant arrays as positional arguments. + If `as_numpy=True`, inputs are converted to NumPy before they are passed to + `func`. + It must return either a single array-like or a sequence of array-likes. + + `func` must be a pure function, i.e. without side effects, as depending on the + backend it may be executed more than once or never. + *args : Array | int | float | complex | bool | None + One or more Array API compliant arrays, Python scalars, or None's. + + If `as_numpy=True`, you need to be able to apply :func:`numpy.asarray` to + non-None args to convert them to NumPy; read notes below about specific + backends. + shape : tuple[int | None, ...] | Sequence[tuple[int | None, ...]], optional + Output shape or sequence of output shapes, one for each output of `func`. + Default: assume single output and broadcast shapes of the input arrays. + dtype : DType | Sequence[DType], optional + Output dtype or sequence of output dtypes, one for each output of `func`. + dtype(s) must belong to the same array namespace as the input arrays. + Default: infer the result type(s) from the input arrays. + as_numpy : bool, optional + If True, convert the input arrays to NumPy before passing them to `func`. + This is particularly useful to make NumPy-only functions, e.g. written in Cython + or Numba, work transparently with array API-compliant arrays. + Default: False. + xp : array_namespace, optional + The standard-compatible namespace for `args`. Default: infer. + **kwargs : Any, optional + Additional keyword arguments to pass verbatim to `func`. + They cannot contain Array objects. + + Returns + ------- + Array | tuple[Array, ...] + The result(s) of `func` applied to the input arrays, wrapped in the same + array namespace as the inputs. + If shape is omitted or a single `tuple[int | None, ...]`, return a single array. + Otherwise, return a tuple of arrays. + + Notes + ----- + JAX + This allows applying eager functions to jitted JAX arrays, which are lazy. + The function won't be applied until the JAX array is materialized. + When running inside ``jax.jit``, `shape` must be fully known, i.e. it cannot + contain any `None` elements. + + .. warning:: + + `func` must never raise inside ``jax.jit``, as the resulting behavior is + undefined. + + Using this with `as_numpy=False` is particularly useful to apply non-jittable + JAX functions to arrays on GPU devices. + If ``as_numpy=True``, the :doc:`jax:transfer_guard` may prevent arrays on a GPU + device from being transferred back to CPU. This is treated as an implicit + transfer. + + PyTorch, CuPy + If ``as_numpy=True``, these backends raise by default if you attempt to convert + arrays on a GPU device to NumPy. + + Sparse + If ``as_numpy=True``, by default sparse prevents implicit densification through + :func:`numpy.asarray`. `This safety mechanism can be disabled + `_. + + Dask + This allows applying eager functions to Dask arrays. + The Dask graph won't be computed until the user calls ``compute()`` or + ``persist()`` down the line. + + The function name will be prominently visible on the user-facing Dask + dashboard and on Prometheus metrics, so it is recommended for it to be + meaningful. + + `lazy_apply` doesn't know if `func` reduces along any axes; also, shape + changes are non-trivial in chunked Dask arrays. For these reasons, all inputs + will be rechunked into a single chunk. + + .. warning:: + + The whole operation needs to fit in memory all at once on a single worker. + + The outputs will also be returned as a single chunk and you should consider + rechunking them into smaller chunks afterwards. + + If you want to distribute the calculation across multiple workers, you + should use :func:`dask.array.map_blocks`, :func:`dask.array.map_overlap`, + :func:`dask.array.blockwise`, or a native Dask wrapper instead of + `lazy_apply`. + + Dask wrapping around other backends + If ``as_numpy=False``, `func` will receive in input eager arrays of the meta + namespace, as defined by the ``._meta`` attribute of the input Dask arrays. + The outputs of `func` will be wrapped by the meta namespace, and then wrapped + again by Dask. + + Raises + ------ + ValueError + When ``xp=jax.numpy``, the output `shape` is unknown (it contains ``None`` on + one or more axes) and this function was called inside ``jax.jit``. + RuntimeError + When ``xp=sparse`` and auto-densification is disabled. + Exception (backend-specific) + When the backend disallows implicit device to host transfers and the input + arrays are on a non-CPU device, e.g. on GPU. + + See Also + -------- + jax.transfer_guard + jax.pure_callback + dask.array.map_blocks + dask.array.map_overlap + dask.array.blockwise + """ + args_not_none = [arg for arg in args if arg is not None] + array_args = [arg for arg in args_not_none if not is_python_scalar(arg)] + if not array_args: + msg = "Must have at least one argument array" + raise ValueError(msg) + if xp is None: + xp = array_namespace(*args) + + # Normalize and validate shape and dtype + shapes: list[tuple[int | None, ...]] + dtypes: list[DType] + multi_output = False + + if shape is None: + shapes = [broadcast_shapes(*(arg.shape for arg in array_args))] + elif all(isinstance(s, int | None) for s in shape): + # Do not test for shape to be a tuple + # https://github.com/data-apis/array-api/issues/891#issuecomment-2637430522 + shapes = [cast(tuple[int | None, ...], shape)] + else: + shapes = list(shape) # type: ignore[arg-type] # pyright: ignore[reportAssignmentType] + multi_output = True + + if dtype is None: + dtypes = [xp.result_type(*args_not_none)] * len(shapes) + elif multi_output: + if not isinstance(dtype, Sequence): + msg = "Got multiple shapes but only one dtype" + raise ValueError(msg) + dtypes = list(dtype) # pyright: ignore[reportUnknownArgumentType] + else: + if isinstance(dtype, Sequence): + msg = "Got single shape but multiple dtypes" + raise ValueError(msg) + + dtypes = [dtype] + + if len(shapes) != len(dtypes): + msg = f"Got {len(shapes)} shapes and {len(dtypes)} dtypes" + raise ValueError(msg) + del shape + del dtype + # End of shape and dtype parsing + + # Backend-specific branches + if is_dask_namespace(xp): + import dask + + metas: list[Array] = [arg._meta for arg in array_args] # pylint: disable=protected-access # pyright: ignore[reportAttributeAccessIssue] + meta_xp = array_namespace(*metas) + + wrapped = dask.delayed( # type: ignore[attr-defined] # pyright: ignore[reportPrivateImportUsage] + _lazy_apply_wrapper(func, as_numpy, multi_output, meta_xp), + pure=True, + ) + # This finalizes each arg, which is the same as arg.rechunk(-1). + # Please read docstring above for why we're not using + # dask.array.map_blocks or dask.array.blockwise! + delayed_out = wrapped(*args, **kwargs) + + out = tuple( + xp.from_delayed( + delayed_out[i], # pyright: ignore[reportIndexIssue] + # Dask's unknown shapes diverge from the Array API specification + shape=tuple(math.nan if s is None else s for s in shape), + dtype=dtype, + meta=metas[0], + ) + for i, (shape, dtype) in enumerate(zip(shapes, dtypes, strict=True)) + ) + + elif is_jax_namespace(xp) and _is_jax_jit_enabled(xp): + # Delay calling func with jax.pure_callback, which will forward to func eager + # JAX arrays. Do not use jax.pure_callback when running outside of the JIT, + # as it does not support raising exceptions: + # https://github.com/jax-ml/jax/issues/26102 + import jax + + if any(None in shape for shape in shapes): + msg = "Output shape must be fully known when running inside jax.jit" + raise ValueError(msg) + + # Shield kwargs from being coerced into JAX arrays. + # jax.pure_callback calls jax.jit under the hood, but without the chance of + # passing static_argnames / static_argnums. + wrapped = _lazy_apply_wrapper( + partial(func, **kwargs), as_numpy, multi_output, xp + ) + + # suppress unused-ignore to run mypy in -e lint as well as -e dev + out = cast( # type: ignore[bad-cast,unused-ignore] + tuple[Array, ...], + jax.pure_callback( + wrapped, + tuple( + jax.ShapeDtypeStruct(shape, dtype) # pyright: ignore[reportUnknownArgumentType] + for shape, dtype in zip(shapes, dtypes, strict=True) + ), + *args, + ), + ) + + else: + # Eager backends, including non-jitted JAX + wrapped = _lazy_apply_wrapper(func, as_numpy, multi_output, xp) + out = wrapped(*args, **kwargs) + + return out if multi_output else out[0] + + +def _is_jax_jit_enabled(xp: ModuleType) -> bool: # numpydoc ignore=PR01,RT01 + """Return True if this function is being called inside ``jax.jit``.""" + import jax # pylint: disable=import-outside-toplevel + + x = xp.asarray(False) + try: + return bool(x) + except jax.errors.TracerBoolConversionError: + return True + + +def _lazy_apply_wrapper( # numpydoc ignore=PR01,RT01 + func: Callable[..., Array | ArrayLike | Sequence[Array | ArrayLike]], + as_numpy: bool, + multi_output: bool, + xp: ModuleType, +) -> Callable[..., tuple[Array, ...]]: + """ + Helper of `lazy_apply`. + + Given a function that accepts one or more arrays as positional arguments and returns + a single array-like or a sequence of array-likes, return a function that accepts the + same number of Array API arrays and always returns a tuple of Array API array. + + Any keyword arguments are passed through verbatim to the wrapped function. + """ + + # On Dask, @wraps causes the graph key to contain the wrapped function's name + @wraps(func) + def wrapper( + *args: Array | complex | None, **kwargs: Any + ) -> tuple[Array, ...]: # numpydoc ignore=GL08 + args_list = [] + device = None + for arg in args: + if arg is not None and not is_python_scalar(arg): + if device is None: + device = _compat.device(arg) + if as_numpy: + import numpy as np + + arg = cast(Array, np.asarray(arg)) # pyright: ignore[reportInvalidCast] # noqa: PLW2901 + args_list.append(arg) + assert device is not None + + out = func(*args_list, **kwargs) + + if multi_output: + assert isinstance(out, Sequence) + return tuple(xp.asarray(o, device=device) for o in out) + return (xp.asarray(out, device=device),) + + return wrapper diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_testing.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_testing.py new file mode 100644 index 0000000000000000000000000000000000000000..30e2f1efb7b0e017673c871acddd2bb6a74522cf --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_testing.py @@ -0,0 +1,304 @@ +""" +Testing utilities. + +Note that this is private API; don't expect it to be stable. +See also ..testing for public testing utilities. +""" + +from __future__ import annotations + +import math +from types import ModuleType +from typing import Any, cast + +import numpy as np +import pytest + +from ._utils._compat import ( + array_namespace, + is_array_api_strict_namespace, + is_cupy_namespace, + is_dask_namespace, + is_jax_namespace, + is_numpy_namespace, + is_pydata_sparse_namespace, + is_torch_array, + is_torch_namespace, + to_device, +) +from ._utils._typing import Array, Device + +__all__ = ["as_numpy_array", "xp_assert_close", "xp_assert_equal", "xp_assert_less"] + + +def _check_ns_shape_dtype( + actual: Array, + desired: Array, + check_dtype: bool, + check_shape: bool, + check_scalar: bool, +) -> ModuleType: # numpydoc ignore=RT03 + """ + Assert that namespace, shape and dtype of the two arrays match. + + Parameters + ---------- + actual : Array + The array produced by the tested function. + desired : Array + The expected array (typically hardcoded). + check_dtype, check_shape : bool, default: True + Whether to check agreement between actual and desired dtypes and shapes + check_scalar : bool, default: False + NumPy only: whether to check agreement between actual and desired types - + 0d array vs scalar. + + Returns + ------- + Arrays namespace. + """ + actual_xp = array_namespace(actual) # Raises on scalars and lists + desired_xp = array_namespace(desired) + + msg = f"namespaces do not match: {actual_xp} != f{desired_xp}" + assert actual_xp == desired_xp, msg + + # Dask uses nan instead of None for unknown shapes + actual_shape = cast(tuple[float, ...], actual.shape) + desired_shape = cast(tuple[float, ...], desired.shape) + assert None not in actual_shape # Requires explicit support + assert None not in desired_shape + if is_dask_namespace(desired_xp): + if any(math.isnan(i) for i in actual_shape): + actual_shape = actual.compute().shape # type: ignore[attr-defined] # pyright: ignore[reportAttributeAccessIssue] + if any(math.isnan(i) for i in desired_shape): + desired_shape = desired.compute().shape # type: ignore[attr-defined] # pyright: ignore[reportAttributeAccessIssue] + + if check_shape: + msg = f"shapes do not match: {actual_shape} != f{desired_shape}" + assert actual_shape == desired_shape, msg + else: + # Ignore shape, but check flattened size. This is normally done by + # np.testing.assert_array_equal etc even when strict=False, but not for + # non-materializable arrays. + actual_size = math.prod(actual_shape) # pyright: ignore[reportUnknownArgumentType] + desired_size = math.prod(desired_shape) # pyright: ignore[reportUnknownArgumentType] + msg = f"sizes do not match: {actual_size} != f{desired_size}" + assert actual_size == desired_size, msg + + if check_dtype: + msg = f"dtypes do not match: {actual.dtype} != {desired.dtype}" + assert actual.dtype == desired.dtype, msg + + if is_numpy_namespace(actual_xp) and check_scalar: + # only NumPy distinguishes between scalars and arrays; we do if check_scalar. + _msg = ( + "array-ness does not match:\n Actual: " + f"{type(actual)}\n Desired: {type(desired)}" + ) + assert np.isscalar(actual) == np.isscalar(desired), _msg + + return desired_xp + + +def _is_materializable(x: Array) -> bool: + """ + Return True if you can call `as_numpy_array(x)`; False otherwise. + """ + # Important: here we assume that we're not tracing - + # e.g. we're not inside `jax.jit`` nor `cupy.cuda.Stream.begin_capture`. + return not is_torch_array(x) or x.device.type != "meta" # type: ignore[attr-defined] # pyright: ignore[reportAttributeAccessIssue] + + +def as_numpy_array(array: Array, *, xp: ModuleType) -> np.typing.NDArray[Any]: + """ + Convert array to NumPy, bypassing GPU-CPU transfer guards and densification guards. + """ + if is_cupy_namespace(xp): + return xp.asnumpy(array) + if is_pydata_sparse_namespace(xp): + return array.todense() # type: ignore[attr-defined] # pyright: ignore[reportAttributeAccessIssue] + + if is_torch_namespace(xp): + array = to_device(array, "cpu") + if is_array_api_strict_namespace(xp): + cpu: Device = xp.Device("CPU_DEVICE") + array = to_device(array, cpu) + if is_jax_namespace(xp): + import jax + + # Note: only needed if the transfer guard is enabled + cpu = cast(Device, jax.devices("cpu")[0]) + array = to_device(array, cpu) + + return np.asarray(array) + + +def xp_assert_equal( + actual: Array, + desired: Array, + *, + err_msg: str = "", + check_dtype: bool = True, + check_shape: bool = True, + check_scalar: bool = False, +) -> None: + """ + Array-API compatible version of `np.testing.assert_array_equal`. + + Parameters + ---------- + actual : Array + The array produced by the tested function. + desired : Array + The expected array (typically hardcoded). + err_msg : str, optional + Error message to display on failure. + check_dtype, check_shape : bool, default: True + Whether to check agreement between actual and desired dtypes and shapes + check_scalar : bool, default: False + NumPy only: whether to check agreement between actual and desired types - + 0d array vs scalar. + + See Also + -------- + xp_assert_close : Similar function for inexact equality checks. + numpy.testing.assert_array_equal : Similar function for NumPy arrays. + """ + xp = _check_ns_shape_dtype(actual, desired, check_dtype, check_shape, check_scalar) + if not _is_materializable(actual): + return + actual_np = as_numpy_array(actual, xp=xp) + desired_np = as_numpy_array(desired, xp=xp) + np.testing.assert_array_equal(actual_np, desired_np, err_msg=err_msg) + + +def xp_assert_less( + x: Array, + y: Array, + *, + err_msg: str = "", + check_dtype: bool = True, + check_shape: bool = True, + check_scalar: bool = False, +) -> None: + """ + Array-API compatible version of `np.testing.assert_array_less`. + + Parameters + ---------- + x, y : Array + The arrays to compare according to ``x < y`` (elementwise). + err_msg : str, optional + Error message to display on failure. + check_dtype, check_shape : bool, default: True + Whether to check agreement between actual and desired dtypes and shapes + check_scalar : bool, default: False + NumPy only: whether to check agreement between actual and desired types - + 0d array vs scalar. + + See Also + -------- + xp_assert_close : Similar function for inexact equality checks. + numpy.testing.assert_array_equal : Similar function for NumPy arrays. + """ + xp = _check_ns_shape_dtype(x, y, check_dtype, check_shape, check_scalar) + if not _is_materializable(x): + return + x_np = as_numpy_array(x, xp=xp) + y_np = as_numpy_array(y, xp=xp) + np.testing.assert_array_less(x_np, y_np, err_msg=err_msg) + + +def xp_assert_close( + actual: Array, + desired: Array, + *, + rtol: float | None = None, + atol: float = 0, + err_msg: str = "", + check_dtype: bool = True, + check_shape: bool = True, + check_scalar: bool = False, +) -> None: + """ + Array-API compatible version of `np.testing.assert_allclose`. + + Parameters + ---------- + actual : Array + The array produced by the tested function. + desired : Array + The expected array (typically hardcoded). + rtol : float, optional + Relative tolerance. Default: dtype-dependent. + atol : float, optional + Absolute tolerance. Default: 0. + err_msg : str, optional + Error message to display on failure. + check_dtype, check_shape : bool, default: True + Whether to check agreement between actual and desired dtypes and shapes + check_scalar : bool, default: False + NumPy only: whether to check agreement between actual and desired types - + 0d array vs scalar. + + See Also + -------- + xp_assert_equal : Similar function for exact equality checks. + isclose : Public function for checking closeness. + numpy.testing.assert_allclose : Similar function for NumPy arrays. + + Notes + ----- + The default `atol` and `rtol` differ from `xp.all(xpx.isclose(a, b))`. + """ + xp = _check_ns_shape_dtype(actual, desired, check_dtype, check_shape, check_scalar) + if not _is_materializable(actual): + return + + if rtol is None: + if xp.isdtype(actual.dtype, ("real floating", "complex floating")): + # multiplier of 4 is used as for `np.float64` this puts the default `rtol` + # roughly half way between sqrt(eps) and the default for + # `numpy.testing.assert_allclose`, 1e-7 + rtol = xp.finfo(actual.dtype).eps ** 0.5 * 4 + else: + rtol = 1e-7 + + actual_np = as_numpy_array(actual, xp=xp) + desired_np = as_numpy_array(desired, xp=xp) + np.testing.assert_allclose( # pyright: ignore[reportCallIssue] + actual_np, + desired_np, + rtol=rtol, # pyright: ignore[reportArgumentType] + atol=atol, + err_msg=err_msg, + ) + + +def xfail( + request: pytest.FixtureRequest, *, reason: str, strict: bool | None = None +) -> None: + """ + XFAIL the currently running test. + + Unlike ``pytest.xfail``, allow rest of test to execute instead of immediately + halting it, so that it may result in a XPASS. + xref https://github.com/pandas-dev/pandas/issues/38902 + + Parameters + ---------- + request : pytest.FixtureRequest + ``request`` argument of the test function. + reason : str + Reason for the expected failure. + strict: bool, optional + If True, the test will be marked as failed if it passes. + If False, the test will be marked as passed if it fails. + Default: ``xfail_strict`` value in ``pyproject.toml``, or False if absent. + """ + if strict is not None: + marker = pytest.mark.xfail(reason=reason, strict=strict) + else: + marker = pytest.mark.xfail(reason=reason) + request.node.add_marker(marker) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3628c45f0e0a48ba403abd0ba4a6bec76dc8a9f1 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/__init__.py @@ -0,0 +1 @@ +"""Modules housing private utility functions.""" diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef71eb90d611295bce73b69d1481471f483b966f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/__pycache__/_compat.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/__pycache__/_compat.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9776418e52c70c25df0ac57b07d2f3b048c04b79 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/__pycache__/_compat.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/__pycache__/_helpers.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/__pycache__/_helpers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7dadbb67c5237cc602d32c3ad49ba4966d9e2f68 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/__pycache__/_helpers.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/__pycache__/_typing.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/__pycache__/_typing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9c2cd420471ee83e969f1fe1326e93d30589bc09 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/__pycache__/_typing.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/_compat.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/_compat.py new file mode 100644 index 0000000000000000000000000000000000000000..82ce76b8ecbcd506c639beb2c9b5b3934d94b67d --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/_compat.py @@ -0,0 +1,74 @@ +"""Acquire helpers from array-api-compat.""" +# Allow packages that vendor both `array-api-extra` and +# `array-api-compat` to override the import location + +# pylint: disable=duplicate-code +try: + from ...._array_api_compat_vendor import ( + array_namespace, + device, + is_array_api_obj, + is_array_api_strict_namespace, + is_cupy_array, + is_cupy_namespace, + is_dask_array, + is_dask_namespace, + is_jax_array, + is_jax_namespace, + is_lazy_array, + is_numpy_array, + is_numpy_namespace, + is_pydata_sparse_array, + is_pydata_sparse_namespace, + is_torch_array, + is_torch_namespace, + is_writeable_array, + size, + to_device, + ) +except ImportError: + from array_api_compat import ( + array_namespace, + device, + is_array_api_obj, + is_array_api_strict_namespace, + is_cupy_array, + is_cupy_namespace, + is_dask_array, + is_dask_namespace, + is_jax_array, + is_jax_namespace, + is_lazy_array, + is_numpy_array, + is_numpy_namespace, + is_pydata_sparse_array, + is_pydata_sparse_namespace, + is_torch_array, + is_torch_namespace, + is_writeable_array, + size, + to_device, + ) + +__all__ = [ + "array_namespace", + "device", + "is_array_api_obj", + "is_array_api_strict_namespace", + "is_cupy_array", + "is_cupy_namespace", + "is_dask_array", + "is_dask_namespace", + "is_jax_array", + "is_jax_namespace", + "is_lazy_array", + "is_numpy_array", + "is_numpy_namespace", + "is_pydata_sparse_array", + "is_pydata_sparse_namespace", + "is_torch_array", + "is_torch_namespace", + "is_writeable_array", + "size", + "to_device", +] diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/_compat.pyi b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/_compat.pyi new file mode 100644 index 0000000000000000000000000000000000000000..95c6bc8a1baed1f083d907994e5c939d6cc325f2 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/_compat.pyi @@ -0,0 +1,45 @@ +"""Static type stubs for `_compat.py`.""" + +# https://github.com/scikit-learn/scikit-learn/pull/27910#issuecomment-2568023972 +from __future__ import annotations + +from types import ModuleType +from typing import Any, TypeGuard + +# TODO import from typing (requires Python >=3.13) +from typing_extensions import TypeIs + +from ._typing import Array, Device + +# pylint: disable=missing-class-docstring,unused-argument + +def array_namespace( + *xs: Array | complex | None, + api_version: str | None = None, + use_compat: bool | None = None, +) -> ModuleType: ... +def device(x: Array, /) -> Device: ... +def is_array_api_obj(x: object, /) -> TypeIs[Array]: ... +def is_array_api_strict_namespace(xp: ModuleType, /) -> bool: ... +def is_cupy_namespace(xp: ModuleType, /) -> bool: ... +def is_dask_namespace(xp: ModuleType, /) -> bool: ... +def is_jax_namespace(xp: ModuleType, /) -> bool: ... +def is_numpy_namespace(xp: ModuleType, /) -> bool: ... +def is_pydata_sparse_namespace(xp: ModuleType, /) -> bool: ... +def is_torch_namespace(xp: ModuleType, /) -> bool: ... +def is_cupy_array(x: object, /) -> TypeGuard[Array]: ... +def is_dask_array(x: object, /) -> TypeGuard[Array]: ... +def is_jax_array(x: object, /) -> TypeGuard[Array]: ... +def is_numpy_array(x: object, /) -> TypeGuard[Array]: ... +def is_pydata_sparse_array(x: object, /) -> TypeGuard[Array]: ... +def is_torch_array(x: object, /) -> TypeGuard[Array]: ... +def is_lazy_array(x: object, /) -> TypeGuard[Array]: ... +def is_writeable_array(x: object, /) -> TypeGuard[Array]: ... +def size(x: Array, /) -> int | None: ... +def to_device( + x: Array, + device: Device, # pylint: disable=redefined-outer-name + /, + *, + stream: int | Any | None = None, +) -> Array: ... diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/_helpers.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/_helpers.py new file mode 100644 index 0000000000000000000000000000000000000000..22da8259eff73d6d0cecfba6d25514de70c23d3b --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/_helpers.py @@ -0,0 +1,619 @@ +"""Helper functions used by `array_api_extra/_funcs.py`.""" + +from __future__ import annotations + +import io +import math +import pickle +import types +from collections.abc import Callable, Generator, Iterable, Iterator +from functools import wraps +from types import ModuleType +from typing import ( + TYPE_CHECKING, + Any, + ClassVar, + Generic, + Literal, + ParamSpec, + TypeAlias, + TypeVar, + cast, +) + +from . import _compat +from ._compat import ( + array_namespace, + is_array_api_obj, + is_dask_namespace, + is_jax_namespace, + is_numpy_array, + is_pydata_sparse_namespace, + is_torch_namespace, +) +from ._typing import Array, Device + +if TYPE_CHECKING: # pragma: no cover + # TODO import from typing (requires Python >=3.12 and >=3.13) + from typing_extensions import TypeIs, override +else: + + def override(func): + return func + + +P = ParamSpec("P") +T = TypeVar("T") + + +__all__ = [ + "asarrays", + "capabilities", + "eager_shape", + "in1d", + "is_python_scalar", + "jax_autojit", + "mean", + "meta_namespace", + "pickle_flatten", + "pickle_unflatten", +] + + +def in1d( + x1: Array, + x2: Array, + /, + *, + assume_unique: bool = False, + invert: bool = False, + xp: ModuleType | None = None, +) -> Array: # numpydoc ignore=PR01,RT01 + """ + Check whether each element of an array is also present in a second array. + + Returns a boolean array the same length as `x1` that is True + where an element of `x1` is in `x2` and False otherwise. + + This function has been adapted using the original implementation + present in numpy: + https://github.com/numpy/numpy/blob/v1.26.0/numpy/lib/arraysetops.py#L524-L758 + """ + if xp is None: + xp = array_namespace(x1, x2) + + x1_shape = eager_shape(x1) + x2_shape = eager_shape(x2) + + # This code is run to make the code significantly faster + if x2_shape[0] < 10 * x1_shape[0] ** 0.145 and isinstance(x2, Iterable): + if invert: + mask = xp.ones(x1_shape[0], dtype=xp.bool, device=_compat.device(x1)) + for a in x2: + mask &= x1 != a + else: + mask = xp.zeros(x1_shape[0], dtype=xp.bool, device=_compat.device(x1)) + for a in x2: + mask |= x1 == a + return mask + + rev_idx = xp.empty(0) # placeholder + if not assume_unique: + x1, rev_idx = xp.unique_inverse(x1) + x2 = xp.unique_values(x2) + + ar = xp.concat((x1, x2)) + device_ = _compat.device(ar) + # We need this to be a stable sort. + order = xp.argsort(ar, stable=True) + reverse_order = xp.argsort(order, stable=True) + sar = xp.take(ar, order, axis=0) + ar_size = _compat.size(sar) + assert ar_size is not None, "xp.unique*() on lazy backends raises" + if ar_size >= 1: + bool_ar = sar[1:] != sar[:-1] if invert else sar[1:] == sar[:-1] + else: + bool_ar = xp.asarray([False]) if invert else xp.asarray([True]) + flag = xp.concat((bool_ar, xp.asarray([invert], device=device_))) + ret = xp.take(flag, reverse_order, axis=0) + + if assume_unique: + return ret[: x1.shape[0]] + return xp.take(ret, rev_idx, axis=0) + + +def mean( + x: Array, + /, + *, + axis: int | tuple[int, ...] | None = None, + keepdims: bool = False, + xp: ModuleType | None = None, +) -> Array: # numpydoc ignore=PR01,RT01 + """ + Complex mean, https://github.com/data-apis/array-api/issues/846. + """ + if xp is None: + xp = array_namespace(x) + + if xp.isdtype(x.dtype, "complex floating"): + x_real = xp.real(x) + x_imag = xp.imag(x) + mean_real = xp.mean(x_real, axis=axis, keepdims=keepdims) + mean_imag = xp.mean(x_imag, axis=axis, keepdims=keepdims) + return mean_real + (mean_imag * xp.asarray(1j)) + return xp.mean(x, axis=axis, keepdims=keepdims) + + +def is_python_scalar(x: object) -> TypeIs[complex]: # numpydoc ignore=PR01,RT01 + """Return True if `x` is a Python scalar, False otherwise.""" + # isinstance(x, float) returns True for np.float64 + # isinstance(x, complex) returns True for np.complex128 + # bool is a subclass of int + return isinstance(x, int | float | complex) and not is_numpy_array(x) + + +def asarrays( + a: Array | complex, + b: Array | complex, + xp: ModuleType, +) -> tuple[Array, Array]: + """ + Ensure both `a` and `b` are arrays. + + If `b` is a python scalar, it is converted to the same dtype as `a`, and vice versa. + + Behavior is not specified when mixing a Python ``float`` and an array with an + integer data type; this may give ``float32``, ``float64``, or raise an exception. + Behavior is implementation-specific. + + Similarly, behavior is not specified when mixing a Python ``complex`` and an array + with a real-valued data type; this may give ``complex64``, ``complex128``, or raise + an exception. Behavior is implementation-specific. + + Parameters + ---------- + a, b : Array | int | float | complex | bool + Input arrays or scalars. At least one must be an array. + xp : array_namespace, optional + The standard-compatible namespace for `x`. Default: infer. + + Returns + ------- + Array, Array + The input arrays, possibly converted to arrays if they were scalars. + + See Also + -------- + mixing-arrays-with-python-scalars : Array API specification for the behavior. + """ + a_scalar = is_python_scalar(a) + b_scalar = is_python_scalar(b) + if not a_scalar and not b_scalar: + # This includes misc. malformed input e.g. str + return a, b # type: ignore[return-value] + + swap = False + if a_scalar: + swap = True + b, a = a, b + + if is_array_api_obj(a): + # a is an Array API object + # b is a int | float | complex | bool + xa = a + + # https://data-apis.org/array-api/draft/API_specification/type_promotion.html#mixing-arrays-with-python-scalars + same_dtype = { + bool: "bool", + int: ("integral", "real floating", "complex floating"), + float: ("real floating", "complex floating"), + complex: "complex floating", + } + kind = same_dtype[type(cast(complex, b))] + if xp.isdtype(a.dtype, kind): + xb = xp.asarray(b, dtype=a.dtype, device=_compat.device(a)) + else: + # Undefined behaviour. Let the function deal with it, if it can. + xb = xp.asarray(b, device=_compat.device(a)) + + else: + # Neither a nor b are Array API objects. + # Note: we can only reach this point when one explicitly passes + # xp=xp to the calling function; otherwise we fail earlier on + # array_namespace(a, b). + xa, xb = xp.asarray(a), xp.asarray(b) + + return (xb, xa) if swap else (xa, xb) + + +def ndindex(*x: int) -> Generator[tuple[int, ...]]: + """ + Generate all N-dimensional indices for a given array shape. + + Given the shape of an array, an ndindex instance iterates over the N-dimensional + index of the array. At each iteration a tuple of indices is returned, the last + dimension is iterated over first. + + This has an identical API to numpy.ndindex. + + Parameters + ---------- + *x : int + The shape of the array. + """ + if not x: + yield () + return + for i in ndindex(*x[:-1]): + for j in range(x[-1]): + yield *i, j + + +def eager_shape(x: Array, /, axis: int | None = None) -> tuple[int, ...]: + """ + Return shape of an array. Raise if shape is not fully defined. + + Parameters + ---------- + x : Array + Input array. + axis : int, optional + If provided, only returns the tuple (shape[axis],). + + Returns + ------- + tuple[int, ...] + Shape of the array. + """ + shape = x.shape + if axis is not None: + s = shape[axis] + # Dask arrays uses non-standard NaN instead of None + if s is None or math.isnan(s): + msg = f"Unsupported lazy shape for axis {axis}" + raise TypeError(msg) + return (s,) + + if any(s is None or math.isnan(s) for s in shape): + msg = "Unsupported lazy shape" + raise TypeError(msg) + return cast(tuple[int, ...], shape) + + +def meta_namespace( + *arrays: Array | complex | None, xp: ModuleType | None = None +) -> ModuleType: + """ + Get the namespace of Dask chunks. + + On all other backends, just return the namespace of the arrays. + + Parameters + ---------- + *arrays : Array | int | float | complex | bool | None + Input arrays. + xp : array_namespace, optional + The standard-compatible namespace for the input arrays. Default: infer. + + Returns + ------- + array_namespace + If xp is Dask, the namespace of the Dask chunks; + otherwise, the namespace of the arrays. + """ + xp = array_namespace(*arrays) if xp is None else xp + if not is_dask_namespace(xp): + return xp + # Quietly skip scalars and None's + metas = [cast(Array | None, getattr(a, "_meta", None)) for a in arrays] + return array_namespace(*metas) + + +def capabilities( + xp: ModuleType, *, device: Device | None = None +) -> dict[str, int | None]: + """ + Return patched ``xp.__array_namespace_info__().capabilities()``. + + TODO this helper should be eventually removed once all the special cases + it handles are fixed in the respective backends. + + Parameters + ---------- + xp : array_namespace + The standard-compatible namespace. + device : Device, optional + The device to use. + + Returns + ------- + dict + Capabilities of the namespace. + """ + out = xp.__array_namespace_info__().capabilities() + if is_pydata_sparse_namespace(xp): + if out["boolean indexing"]: + # FIXME https://github.com/pydata/sparse/issues/876 + # boolean indexing is supported, but not when the index is a sparse array. + # boolean indexing by list or numpy array is not part of the Array API. + out = out.copy() + out["boolean indexing"] = False + elif is_jax_namespace(xp): + if out["boolean indexing"]: # pragma: no cover + # Backwards compatibility with jax <0.6.0 + # https://github.com/jax-ml/jax/issues/27418 + out = out.copy() + out["boolean indexing"] = False + elif is_torch_namespace(xp): + # FIXME https://github.com/data-apis/array-api/issues/945 + device = xp.get_default_device() if device is None else xp.device(device) + if device.type == "meta": # type: ignore[union-attr] # pyright: ignore[reportAttributeAccessIssue,reportOptionalMemberAccess] + out = out.copy() + out["boolean indexing"] = False + out["data-dependent shapes"] = False + + return out + + +_BASIC_PICKLED_TYPES = frozenset(( + bool, int, float, complex, str, bytes, bytearray, + list, tuple, dict, set, frozenset, range, slice, + types.NoneType, types.EllipsisType, +)) # fmt: skip +_BASIC_REST_TYPES = frozenset(( + type, types.BuiltinFunctionType, types.FunctionType, types.ModuleType +)) # fmt: skip + +FlattenRest: TypeAlias = tuple[object, ...] + + +def pickle_flatten( + obj: object, cls: type[T] | tuple[type[T], ...] +) -> tuple[list[T], FlattenRest]: + """ + Use the pickle machinery to extract objects out of an arbitrary container. + + Unlike regular ``pickle.dumps``, this function always succeeds. + + Parameters + ---------- + obj : object + The object to pickle. + cls : type | tuple[type, ...] + One or multiple classes to extract from the object. + The instances of these classes inside ``obj`` will not be pickled. + + Returns + ------- + instances : list[cls] + All instances of ``cls`` found inside ``obj`` (not pickled). + rest + Opaque object containing the pickled bytes plus all other objects where + ``__reduce__`` / ``__reduce_ex__`` is either not implemented or raised. + These are unpickleable objects, types, modules, and functions. + + This object is *typically* hashable save for fairly exotic objects + that are neither pickleable nor hashable. + + This object is pickleable if everything except ``instances`` was pickleable + in the input object. + + See Also + -------- + pickle_unflatten : Reverse function. + + Examples + -------- + >>> class A: + ... def __repr__(self): + ... return "" + >>> class NS: + ... def __repr__(self): + ... return "" + ... def __reduce__(self): + ... assert False, "not serializable" + >>> obj = {1: A(), 2: [A(), NS(), A()]} + >>> instances, rest = pickle_flatten(obj, A) + >>> instances + [, , ] + >>> pickle_unflatten(instances, rest) + {1: , 2: [, , ]} + + This can be also used to swap inner objects; the only constraint is that + the number of objects in and out must be the same: + + >>> pickle_unflatten(["foo", "bar", "baz"], rest) + {1: "foo", 2: ["bar", , "baz"]} + """ + instances: list[T] = [] + rest: list[object] = [] + + class Pickler(pickle.Pickler): # numpydoc ignore=GL08 + """ + Use the `pickle.Pickler.persistent_id` hook to extract objects. + """ + + @override + def persistent_id( + self, obj: object + ) -> Literal[0, 1, None]: # numpydoc ignore=GL08 + if isinstance(obj, cls): + instances.append(obj) # type: ignore[arg-type] + return 0 + + typ_ = type(obj) + if typ_ in _BASIC_PICKLED_TYPES: # No subclasses! + # If obj is a collection, recursively descend inside it + return None + if typ_ in _BASIC_REST_TYPES: + rest.append(obj) + return 1 + + try: + # Note: a class that defines __slots__ without defining __getstate__ + # cannot be pickled with __reduce__(), but can with __reduce_ex__(5) + _ = obj.__reduce_ex__(pickle.HIGHEST_PROTOCOL) + except Exception: # pylint: disable=broad-exception-caught + rest.append(obj) + return 1 + + # Object can be pickled. Let the Pickler recursively descend inside it. + return None + + f = io.BytesIO() + p = Pickler(f, protocol=pickle.HIGHEST_PROTOCOL) + p.dump(obj) + return instances, (f.getvalue(), *rest) + + +def pickle_unflatten(instances: Iterable[object], rest: FlattenRest) -> Any: + """ + Reverse of ``pickle_flatten``. + + Parameters + ---------- + instances : Iterable + Inner objects to be reinserted into the flattened container. + rest : FlattenRest + Extra bits, as returned by ``pickle_flatten``. + + Returns + ------- + object + The outer object originally passed to ``pickle_flatten`` after a + pickle->unpickle round-trip. + + See Also + -------- + pickle_flatten : Serializing function. + pickle.loads : Standard unpickle function. + + Notes + ----- + The `instances` iterable must yield at least the same number of elements as the ones + returned by ``pickle_flatten``, but the elements do not need to be the same objects + or even the same types of objects. Excess elements, if any, will be left untouched. + """ + iters = iter(instances), iter(rest) + pik = cast(bytes, next(iters[1])) + + class Unpickler(pickle.Unpickler): # numpydoc ignore=GL08 + """Mirror of the overridden Pickler in pickle_flatten.""" + + @override + def persistent_load(self, pid: Literal[0, 1]) -> object: # numpydoc ignore=GL08 + try: + return next(iters[pid]) + except StopIteration as e: + msg = "Not enough objects to unpickle" + raise ValueError(msg) from e + + f = io.BytesIO(pik) + return Unpickler(f).load() + + +class _AutoJITWrapper(Generic[T]): # numpydoc ignore=PR01 + """ + Helper of :func:`jax_autojit`. + + Wrap arbitrary inputs and outputs of the jitted function and + convert them to/from PyTrees. + """ + + _obj: Any + _is_iter: bool + _registered: ClassVar[bool] = False + __slots__: tuple[str, ...] = ("_is_iter", "_obj") + + def __init__(self, obj: T) -> None: # numpydoc ignore=GL08 + self._register() + if isinstance(obj, Iterator): + self._obj = list(obj) + self._is_iter = True + else: + self._obj = obj + self._is_iter = False + + @property + def obj(self) -> T: # numpydoc ignore=RT01 + """Return wrapped object.""" + return iter(self._obj) if self._is_iter else self._obj + + @classmethod + def _register(cls) -> None: # numpydoc ignore=SS06 + """ + Register upon first use instead of at import time, to avoid + globally importing JAX. + """ + if not cls._registered: + import jax + + jax.tree_util.register_pytree_node( + cls, + lambda instance: pickle_flatten(instance, jax.Array), # pyright: ignore[reportUnknownArgumentType] + lambda aux_data, children: pickle_unflatten(children, aux_data), # pyright: ignore[reportUnknownArgumentType] + ) + cls._registered = True + + +def jax_autojit( + func: Callable[P, T], +) -> Callable[P, T]: # numpydoc ignore=PR01,RT01,SS03 + """ + Wrap `func` with ``jax.jit``, with the following differences: + + - Python scalar arguments and return values are not automatically converted to + ``jax.Array`` objects. + - All non-array arguments are automatically treated as static. + Unlike ``jax.jit``, static arguments must be either hashable or serializable with + ``pickle``. + - Unlike ``jax.jit``, non-array arguments and return values are not limited to + tuple/list/dict, but can be any object serializable with ``pickle``. + - Automatically descend into non-array arguments and find ``jax.Array`` objects + inside them, then rebuild the arguments when entering `func`, swapping the JAX + concrete arrays with tracer objects. + - Automatically descend into non-array return values and find ``jax.Array`` objects + inside them, then rebuild them downstream of exiting the JIT, swapping the JAX + tracer objects with concrete arrays. + - Returned iterators are immediately completely consumed. + + See Also + -------- + jax.jit : JAX JIT compilation function. + + Notes + ----- + These are useful choices *for testing purposes only*, which is how this function is + intended to be used. The output of ``jax.jit`` is a C++ level callable, that + directly dispatches to the compiled kernel after the initial call. In comparison, + ``jax_autojit`` incurs a much higher dispatch time. + + Additionally, consider:: + + def f(x: Array, y: float, plus: bool) -> Array: + return x + y if plus else x - y + + j1 = jax.jit(f, static_argnames="plus") + j2 = jax_autojit(f) + + In the above example, ``j2`` requires a lot less setup to be tested effectively than + ``j1``, but on the flip side it means that it will be re-traced for every different + value of ``y``, which likely makes it not fit for purpose in production. + """ + import jax + + @jax.jit # type: ignore[misc] # pyright: ignore[reportUntypedFunctionDecorator] + def inner( # numpydoc ignore=GL08 + wargs: _AutoJITWrapper[Any], + ) -> _AutoJITWrapper[T]: + args, kwargs = wargs.obj + res = func(*args, **kwargs) # pyright: ignore[reportCallIssue] + return _AutoJITWrapper(res) + + @wraps(func) + def outer(*args: P.args, **kwargs: P.kwargs) -> T: # numpydoc ignore=GL08 + wargs = _AutoJITWrapper((args, kwargs)) + return inner(wargs).obj + + return outer diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/_typing.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/_typing.py new file mode 100644 index 0000000000000000000000000000000000000000..8204be4759610b1ddb33b3579ccaa5f3a1f0866a --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/_typing.py @@ -0,0 +1,10 @@ +# numpydoc ignore=GL08 +# pylint: disable=missing-module-docstring,duplicate-code + +Array = object +DType = object +Device = object +GetIndex = object +SetIndex = object + +__all__ = ["Array", "DType", "Device", "GetIndex", "SetIndex"] diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/_typing.pyi b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/_typing.pyi new file mode 100644 index 0000000000000000000000000000000000000000..35c255fc9ad5c6c93e1b988dc9fe1fc6543ee0a6 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/_lib/_utils/_typing.pyi @@ -0,0 +1,105 @@ +"""Static typing helpers.""" + +from __future__ import annotations + +from types import EllipsisType +from typing import Protocol, TypeAlias + +# TODO import from typing (requires Python >=3.12) +from typing_extensions import override + +# TODO: use array-api-typing once it is available + +class Array(Protocol): # pylint: disable=missing-class-docstring + # Unary operations + def __abs__(self) -> Array: ... + def __pos__(self) -> Array: ... + def __neg__(self) -> Array: ... + def __invert__(self) -> Array: ... + # Binary operations + def __add__(self, other: Array | complex, /) -> Array: ... + def __sub__(self, other: Array | complex, /) -> Array: ... + def __mul__(self, other: Array | complex, /) -> Array: ... + def __truediv__(self, other: Array | complex, /) -> Array: ... + def __floordiv__(self, other: Array | complex, /) -> Array: ... + def __mod__(self, other: Array | complex, /) -> Array: ... + def __pow__(self, other: Array | complex, /) -> Array: ... + def __matmul__(self, other: Array, /) -> Array: ... + def __and__(self, other: Array | int, /) -> Array: ... + def __or__(self, other: Array | int, /) -> Array: ... + def __xor__(self, other: Array | int, /) -> Array: ... + def __lshift__(self, other: Array | int, /) -> Array: ... + def __rshift__(self, other: Array | int, /) -> Array: ... + def __lt__(self, other: Array | complex, /) -> Array: ... + def __le__(self, other: Array | complex, /) -> Array: ... + def __gt__(self, other: Array | complex, /) -> Array: ... + def __ge__(self, other: Array | complex, /) -> Array: ... + @override + def __eq__(self, other: Array | complex, /) -> Array: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + @override + def __ne__(self, other: Array | complex, /) -> Array: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + # Reflected operations + def __radd__(self, other: Array | complex, /) -> Array: ... + def __rsub__(self, other: Array | complex, /) -> Array: ... + def __rmul__(self, other: Array | complex, /) -> Array: ... + def __rtruediv__(self, other: Array | complex, /) -> Array: ... + def __rfloordiv__(self, other: Array | complex, /) -> Array: ... + def __rmod__(self, other: Array | complex, /) -> Array: ... + def __rpow__(self, other: Array | complex, /) -> Array: ... + def __rmatmul__(self, other: Array, /) -> Array: ... + def __rand__(self, other: Array | int, /) -> Array: ... + def __ror__(self, other: Array | int, /) -> Array: ... + def __rxor__(self, other: Array | int, /) -> Array: ... + def __rlshift__(self, other: Array | int, /) -> Array: ... + def __rrshift__(self, other: Array | int, /) -> Array: ... + # Attributes + @property + def dtype(self) -> DType: ... + @property + def device(self) -> Device: ... + @property + def mT(self) -> Array: ... # pylint: disable=invalid-name + @property + def ndim(self) -> int: ... + @property + def shape(self) -> tuple[int | None, ...]: ... + @property + def size(self) -> int | None: ... + @property + def T(self) -> Array: ... # pylint: disable=invalid-name + # Collection operations (note: an Array does not have to be Sized or Iterable) + def __getitem__(self, key: GetIndex, /) -> Array: ... + def __setitem__(self, key: SetIndex, value: Array | complex, /) -> None: ... + # Materialization methods (may raise on lazy arrays) + def __bool__(self) -> bool: ... + def __complex__(self) -> complex: ... + def __float__(self) -> float: ... + def __index__(self) -> int: ... + def __int__(self) -> int: ... + + # Misc methods (frequently not implemented in Arrays wrapped by array-api-compat) + # def __array_namespace__(*, api_version: str | None) -> ModuleType: ... + # def __dlpack__( + # *, + # stream: int | Any | None = None, + # max_version: tuple[int, int] | None = None, + # dl_device: tuple[int, int] | None = None, # tuple[Enum, int] + # copy: bool | None = None, + # ) -> Any: ... + # def __dlpack_device__() -> tuple[int, int]: ... # tuple[Enum, int] + # def to_device(device: Device, /, *, stream: int | Any | None = None) -> Array: ... + +class DType(Protocol): # pylint: disable=missing-class-docstring + pass + +class Device(Protocol): # pylint: disable=missing-class-docstring + pass + +SetIndex: TypeAlias = ( + int | slice | EllipsisType | Array | tuple[int | slice | EllipsisType | Array, ...] +) +GetIndex: TypeAlias = ( + SetIndex | None | tuple[int | slice | EllipsisType | None | Array, ...] +) + +__all__ = ["Array", "DType", "Device", "GetIndex", "SetIndex"] diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/testing.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/testing.py new file mode 100644 index 0000000000000000000000000000000000000000..d40fea1a085319c82a7d89e21f2182b5be5ad3c9 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/array_api_extra/testing.py @@ -0,0 +1,415 @@ +""" +Public testing utilities. + +See also _lib._testing for additional private testing utilities. +""" + +from __future__ import annotations + +import contextlib +import enum +import warnings +from collections.abc import Callable, Generator, Iterator, Sequence +from functools import wraps +from types import ModuleType +from typing import TYPE_CHECKING, Any, ParamSpec, TypeVar, cast + +from ._lib._utils._compat import is_dask_namespace, is_jax_namespace +from ._lib._utils._helpers import jax_autojit, pickle_flatten, pickle_unflatten + +__all__ = ["lazy_xp_function", "patch_lazy_xp_functions"] + +if TYPE_CHECKING: # pragma: no cover + # TODO import override from typing (requires Python >=3.12) + import pytest + from dask.typing import Graph, Key, SchedulerGetCallable + from typing_extensions import override + +else: + # Sphinx hacks + SchedulerGetCallable = object + + def override(func): + return func + + +P = ParamSpec("P") +T = TypeVar("T") + +_ufuncs_tags: dict[object, dict[str, Any]] = {} + + +class Deprecated(enum.Enum): + """Unique type for deprecated parameters.""" + + DEPRECATED = 1 + + +DEPRECATED = Deprecated.DEPRECATED + + +def lazy_xp_function( + func: Callable[..., Any], + *, + allow_dask_compute: bool | int = False, + jax_jit: bool = True, + static_argnums: Deprecated = DEPRECATED, + static_argnames: Deprecated = DEPRECATED, +) -> None: # numpydoc ignore=GL07 + """ + Tag a function to be tested on lazy backends. + + Tag a function so that when any tests are executed with ``xp=jax.numpy`` the + function is replaced with a jitted version of itself, and when it is executed with + ``xp=dask.array`` the function will raise if it attempts to materialize the graph. + This will be later expanded to provide test coverage for other lazy backends. + + In order for the tag to be effective, the test or a fixture must call + :func:`patch_lazy_xp_functions`. + + Parameters + ---------- + func : callable + Function to be tested. + allow_dask_compute : bool | int, optional + Whether `func` is allowed to internally materialize the Dask graph, or maximum + number of times it is allowed to do so. This is typically triggered by + ``bool()``, ``float()``, or ``np.asarray()``. + + Set to 1 if you are aware that `func` converts the input parameters to NumPy and + want to let it do so at least for the time being, knowing that it is going to be + extremely detrimental for performance. + + If a test needs values higher than 1 to pass, it is a canary that the conversion + to NumPy/bool/float is happening multiple times, which translates to multiple + computations of the whole graph. Short of making the function fully lazy, you + should at least add explicit calls to ``np.asarray()`` early in the function. + *Note:* the counter of `allow_dask_compute` resets after each call to `func`, so + a test function that invokes `func` multiple times should still work with this + parameter set to 1. + + Set to True to allow `func` to materialize the graph an unlimited number + of times. + + Default: False, meaning that `func` must be fully lazy and never materialize the + graph. + jax_jit : bool, optional + Set to True to replace `func` with a smart variant of ``jax.jit(func)`` after + calling the :func:`patch_lazy_xp_functions` test helper with ``xp=jax.numpy``. + This is the default behaviour. + Set to False if `func` is only compatible with eager (non-jitted) JAX. + + Unlike with vanilla ``jax.jit``, all arguments and return types that are not JAX + arrays are treated as static; the function can accept and return arbitrary + wrappers around JAX arrays. This difference is because, in real life, most users + won't wrap the function directly with ``jax.jit`` but rather they will use it + within their own code, which is itself then wrapped by ``jax.jit``, and + internally consume the function's outputs. + + In other words, the pattern that is being tested is:: + + >>> @jax.jit + ... def user_func(x): + ... y = user_prepares_inputs(x) + ... z = func(y, some_static_arg=True) + ... return user_consumes(z) + + Default: True. + static_argnums : + Deprecated; ignored + static_argnames : + Deprecated; ignored + + See Also + -------- + patch_lazy_xp_functions : Companion function to call from the test or fixture. + jax.jit : JAX function to compile a function for performance. + + Examples + -------- + In ``test_mymodule.py``:: + + from array_api_extra.testing import lazy_xp_function from mymodule import myfunc + + lazy_xp_function(myfunc) + + def test_myfunc(xp): + a = xp.asarray([1, 2]) + # When xp=jax.numpy, this is similar to `b = jax.jit(myfunc)(a)` + # When xp=dask.array, crash on compute() or persist() + b = myfunc(a) + + Notes + ----- + In order for this tag to be effective, the test function must be imported into the + test module globals without its namespace; alternatively its namespace must be + declared in a ``lazy_xp_modules`` list in the test module globals. + + Example 1:: + + from mymodule import myfunc + + lazy_xp_function(myfunc) + + def test_myfunc(xp): + x = myfunc(xp.asarray([1, 2])) + + Example 2:: + + import mymodule + + lazy_xp_modules = [mymodule] + lazy_xp_function(mymodule.myfunc) + + def test_myfunc(xp): + x = mymodule.myfunc(xp.asarray([1, 2])) + + A test function can circumvent this monkey-patching system by using a namespace + outside of the two above patterns. You need to sanitize your code to make sure this + only happens intentionally. + + Example 1:: + + import mymodule + from mymodule import myfunc + + lazy_xp_function(myfunc) + + def test_myfunc(xp): + a = xp.asarray([1, 2]) + b = myfunc(a) # This is wrapped when xp=jax.numpy or xp=dask.array + c = mymodule.myfunc(a) # This is not + + Example 2:: + + import mymodule + + class naked: + myfunc = mymodule.myfunc + + lazy_xp_modules = [mymodule] + lazy_xp_function(mymodule.myfunc) + + def test_myfunc(xp): + a = xp.asarray([1, 2]) + b = mymodule.myfunc(a) # This is wrapped when xp=jax.numpy or xp=dask.array + c = naked.myfunc(a) # This is not + """ + if static_argnums is not DEPRECATED or static_argnames is not DEPRECATED: + warnings.warn( + ( + "The `static_argnums` and `static_argnames` parameters are deprecated " + "and ignored. They will be removed in a future version." + ), + DeprecationWarning, + stacklevel=2, + ) + tags = { + "allow_dask_compute": allow_dask_compute, + "jax_jit": jax_jit, + } + + try: + func._lazy_xp_function = tags # type: ignore[attr-defined] # pylint: disable=protected-access # pyright: ignore[reportFunctionMemberAccess] + except AttributeError: # @cython.vectorize + _ufuncs_tags[func] = tags + + +def patch_lazy_xp_functions( + request: pytest.FixtureRequest, + monkeypatch: pytest.MonkeyPatch | None = None, + *, + xp: ModuleType, +) -> contextlib.AbstractContextManager[None]: + """ + Test lazy execution of functions tagged with :func:`lazy_xp_function`. + + If ``xp==jax.numpy``, search for all functions which have been tagged with + :func:`lazy_xp_function` in the globals of the module that defines the current test, + as well as in the ``lazy_xp_modules`` list in the globals of the same module, + and wrap them with :func:`jax.jit`. Unwrap them at the end of the test. + + If ``xp==dask.array``, wrap the functions with a decorator that disables + ``compute()`` and ``persist()`` and ensures that exceptions and warnings are raised + eagerly. + + This function should be typically called by your library's `xp` fixture that runs + tests on multiple backends:: + + @pytest.fixture(params=[ + numpy, + array_api_strict, + pytest.param(jax.numpy, marks=pytest.mark.thread_unsafe), + pytest.param(dask.array, marks=pytest.mark.thread_unsafe), + ]) + def xp(request): + with patch_lazy_xp_functions(request, xp=request.param): + yield request.param + + but it can be otherwise be called by the test itself too. + + Parameters + ---------- + request : pytest.FixtureRequest + Pytest fixture, as acquired by the test itself or by one of its fixtures. + monkeypatch : pytest.MonkeyPatch + Deprecated + xp : array_namespace + Array namespace to be tested. + + See Also + -------- + lazy_xp_function : Tag a function to be tested on lazy backends. + pytest.FixtureRequest : `request` test function parameter. + + Notes + ----- + This context manager monkey-patches modules and as such is thread unsafe + on Dask and JAX. If you run your test suite with + `pytest-run-parallel `_, + you should mark these backends with ``@pytest.mark.thread_unsafe``, as shown in + the example above. + """ + mod = cast(ModuleType, request.module) + mods = [mod, *cast(list[ModuleType], getattr(mod, "lazy_xp_modules", []))] + + to_revert: list[tuple[ModuleType, str, object]] = [] + + def temp_setattr(mod: ModuleType, name: str, func: object) -> None: + """ + Variant of monkeypatch.setattr, which allows monkey-patching only selected + parameters of a test so that pytest-run-parallel can run on the remainder. + """ + assert hasattr(mod, name) + to_revert.append((mod, name, getattr(mod, name))) + setattr(mod, name, func) + + if monkeypatch is not None: + warnings.warn( + ( + "The `monkeypatch` parameter is deprecated and will be removed in a " + "future version. " + "Use `patch_lazy_xp_function` as a context manager instead." + ), + DeprecationWarning, + stacklevel=2, + ) + # Enable using patch_lazy_xp_function not as a context manager + temp_setattr = monkeypatch.setattr # type: ignore[assignment] # pyright: ignore[reportAssignmentType] + + def iter_tagged() -> Iterator[ + tuple[ModuleType, str, Callable[..., Any], dict[str, Any]] + ]: + for mod in mods: + for name, func in mod.__dict__.items(): + tags: dict[str, Any] | None = None + with contextlib.suppress(AttributeError): + tags = func._lazy_xp_function # pylint: disable=protected-access + if tags is None: + with contextlib.suppress(KeyError, TypeError): + tags = _ufuncs_tags[func] + if tags is not None: + yield mod, name, func, tags + + if is_dask_namespace(xp): + for mod, name, func, tags in iter_tagged(): + n = tags["allow_dask_compute"] + if n is True: + n = 1_000_000 + elif n is False: + n = 0 + wrapped = _dask_wrap(func, n) + temp_setattr(mod, name, wrapped) + + elif is_jax_namespace(xp): + for mod, name, func, tags in iter_tagged(): + if tags["jax_jit"]: + wrapped = jax_autojit(func) + temp_setattr(mod, name, wrapped) + + # We can't just decorate patch_lazy_xp_functions with + # @contextlib.contextmanager because it would not work with the + # deprecated monkeypatch when not used as a context manager. + @contextlib.contextmanager + def revert_on_exit() -> Generator[None]: + try: + yield + finally: + for mod, name, orig_func in to_revert: + setattr(mod, name, orig_func) + + return revert_on_exit() + + +class CountingDaskScheduler(SchedulerGetCallable): + """ + Dask scheduler that counts how many times `dask.compute` is called. + + If the number of times exceeds 'max_count', it raises an error. + This is a wrapper around Dask's own 'synchronous' scheduler. + + Parameters + ---------- + max_count : int + Maximum number of allowed calls to `dask.compute`. + msg : str + Assertion to raise when the count exceeds `max_count`. + """ + + count: int + max_count: int + msg: str + + def __init__(self, max_count: int, msg: str): # numpydoc ignore=GL08 + self.count = 0 + self.max_count = max_count + self.msg = msg + + @override + def __call__( + self, dsk: Graph, keys: Sequence[Key] | Key, **kwargs: Any + ) -> Any: # numpydoc ignore=GL08 + import dask + + self.count += 1 + # This should yield a nice traceback to the + # offending line in the user's code + assert self.count <= self.max_count, self.msg + + return dask.get(dsk, keys, **kwargs) # type: ignore[attr-defined] # pyright: ignore[reportPrivateImportUsage] + + +def _dask_wrap( + func: Callable[P, T], n: int +) -> Callable[P, T]: # numpydoc ignore=PR01,RT01 + """ + Wrap `func` to raise if it attempts to call `dask.compute` more than `n` times. + + After the function returns, materialize the graph in order to re-raise exceptions. + """ + import dask + import dask.array as da + + func_name = getattr(func, "__name__", str(func)) + n_str = f"only up to {n}" if n else "no" + msg = ( + f"Called `dask.compute()` or `dask.persist()` {n + 1} times, " + f"but {n_str} calls are allowed. Set " + f"`lazy_xp_function({func_name}, allow_dask_compute={n + 1})` " + "to allow for more (but note that this will harm performance). " + ) + + @wraps(func) + def wrapper(*args: P.args, **kwargs: P.kwargs) -> T: # numpydoc ignore=GL08 + scheduler = CountingDaskScheduler(n, msg) + with dask.config.set({"scheduler": scheduler}): # pyright: ignore[reportPrivateImportUsage] + out = func(*args, **kwargs) + + # Block until the graph materializes and reraise exceptions. This allows + # `pytest.raises` and `pytest.warns` to work as expected. Note that this would + # not work on scheduler='distributed', as it would not block. + arrays, rest = pickle_flatten(out, da.Array) + arrays = dask.persist(arrays, scheduler="threads")[0] # type: ignore[attr-defined,no-untyped-call] # pyright: ignore[reportPrivateImportUsage] + return pickle_unflatten(arrays, rest) # pyright: ignore[reportUnknownArgumentType] + + return wrapper diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..2654c8a3d21ed3db207f6204816d852e6b4c0efc --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__init__.py @@ -0,0 +1,20 @@ +from .main import minimize +from .utils import show_versions + +# PEP0440 compatible formatted version, see: +# https://www.python.org/dev/peps/pep-0440/ +# +# Final release markers: +# X.Y.0 # For first release after an increment in Y +# X.Y.Z # For bugfix releases +# +# Admissible pre-release markers: +# X.YaN # Alpha release +# X.YbN # Beta release +# X.YrcN # Release Candidate +# +# Dev branch marker is: 'X.Y.dev' or 'X.Y.devN' where N is an integer. +# 'X.Y.dev0' is the canonical version of 'X.Y.dev'. +__version__ = "1.1.3" + +__all__ = ["minimize", "show_versions"] diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5fce31f6e8fefd2deb356350d6c9773c4bd45e18 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/framework.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/framework.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..875f4d4a3f38687655be1e36f04f212694b13e33 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/framework.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/main.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/main.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2030fd65dae03cd0054974768f9590e2e1ea2702 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/main.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/models.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/models.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4c922843203100d29bd802df291ddc353a349c1d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/models.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/problem.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/problem.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a4efdd0bdea54504eb04daff4cf801aa3b8e7d2c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/problem.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/settings.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/settings.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..335557eb6e66d64d2814b4b198028e9764217eb2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/__pycache__/settings.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/framework.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/framework.py new file mode 100644 index 0000000000000000000000000000000000000000..9afea66281067e27a486ff317a4bffa03ec3e68b --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/framework.py @@ -0,0 +1,1240 @@ +import warnings + +import numpy as np +from scipy.optimize import lsq_linear + +from .models import Models, Quadratic +from .settings import Options, Constants +from .subsolvers import ( + cauchy_geometry, + spider_geometry, + normal_byrd_omojokun, + tangential_byrd_omojokun, + constrained_tangential_byrd_omojokun, +) +from .subsolvers.optim import qr_tangential_byrd_omojokun +from .utils import get_arrays_tol + + +TINY = np.finfo(float).tiny +EPS = np.finfo(float).eps + + +class TrustRegion: + """ + Trust-region framework. + """ + + def __init__(self, pb, options, constants): + """ + Initialize the trust-region framework. + + Parameters + ---------- + pb : `cobyqa.problem.Problem` + Problem to solve. + options : dict + Options of the solver. + constants : dict + Constants of the solver. + + Raises + ------ + `cobyqa.utils.MaxEvalError` + If the maximum number of evaluations is reached. + `cobyqa.utils.TargetSuccess` + If a nearly feasible point has been found with an objective + function value below the target. + `cobyqa.utils.FeasibleSuccess` + If a feasible point has been found for a feasibility problem. + `numpy.linalg.LinAlgError` + If the initial interpolation system is ill-defined. + """ + # Set the initial penalty parameter. + self._penalty = 0.0 + + # Initialize the models. + self._pb = pb + self._models = Models(self._pb, options, self.penalty) + self._constants = constants + + # Set the index of the best interpolation point. + self._best_index = 0 + self.set_best_index() + + # Set the initial Lagrange multipliers. + self._lm_linear_ub = np.zeros(self.m_linear_ub) + self._lm_linear_eq = np.zeros(self.m_linear_eq) + self._lm_nonlinear_ub = np.zeros(self.m_nonlinear_ub) + self._lm_nonlinear_eq = np.zeros(self.m_nonlinear_eq) + self.set_multipliers(self.x_best) + + # Set the initial trust-region radius and the resolution. + self._resolution = options[Options.RHOBEG] + self._radius = self.resolution + + @property + def n(self): + """ + Number of variables. + + Returns + ------- + int + Number of variables. + """ + return self._pb.n + + @property + def m_linear_ub(self): + """ + Number of linear inequality constraints. + + Returns + ------- + int + Number of linear inequality constraints. + """ + return self._pb.m_linear_ub + + @property + def m_linear_eq(self): + """ + Number of linear equality constraints. + + Returns + ------- + int + Number of linear equality constraints. + """ + return self._pb.m_linear_eq + + @property + def m_nonlinear_ub(self): + """ + Number of nonlinear inequality constraints. + + Returns + ------- + int + Number of nonlinear inequality constraints. + """ + return self._pb.m_nonlinear_ub + + @property + def m_nonlinear_eq(self): + """ + Number of nonlinear equality constraints. + + Returns + ------- + int + Number of nonlinear equality constraints. + """ + return self._pb.m_nonlinear_eq + + @property + def radius(self): + """ + Trust-region radius. + + Returns + ------- + float + Trust-region radius. + """ + return self._radius + + @radius.setter + def radius(self, radius): + """ + Set the trust-region radius. + + Parameters + ---------- + radius : float + New trust-region radius. + """ + self._radius = radius + if ( + self.radius + <= self._constants[Constants.DECREASE_RADIUS_THRESHOLD] + * self.resolution + ): + self._radius = self.resolution + + @property + def resolution(self): + """ + Resolution of the trust-region framework. + + The resolution is a lower bound on the trust-region radius. + + Returns + ------- + float + Resolution of the trust-region framework. + """ + return self._resolution + + @resolution.setter + def resolution(self, resolution): + """ + Set the resolution of the trust-region framework. + + Parameters + ---------- + resolution : float + New resolution of the trust-region framework. + """ + self._resolution = resolution + + @property + def penalty(self): + """ + Penalty parameter. + + Returns + ------- + float + Penalty parameter. + """ + return self._penalty + + @property + def models(self): + """ + Models of the objective function and constraints. + + Returns + ------- + `cobyqa.models.Models` + Models of the objective function and constraints. + """ + return self._models + + @property + def best_index(self): + """ + Index of the best interpolation point. + + Returns + ------- + int + Index of the best interpolation point. + """ + return self._best_index + + @property + def x_best(self): + """ + Best interpolation point. + + Its value is interpreted as relative to the origin, not the base point. + + Returns + ------- + `numpy.ndarray` + Best interpolation point. + """ + return self.models.interpolation.point(self.best_index) + + @property + def fun_best(self): + """ + Value of the objective function at `x_best`. + + Returns + ------- + float + Value of the objective function at `x_best`. + """ + return self.models.fun_val[self.best_index] + + @property + def cub_best(self): + """ + Values of the nonlinear inequality constraints at `x_best`. + + Returns + ------- + `numpy.ndarray`, shape (m_nonlinear_ub,) + Values of the nonlinear inequality constraints at `x_best`. + """ + return self.models.cub_val[self.best_index, :] + + @property + def ceq_best(self): + """ + Values of the nonlinear equality constraints at `x_best`. + + Returns + ------- + `numpy.ndarray`, shape (m_nonlinear_eq,) + Values of the nonlinear equality constraints at `x_best`. + """ + return self.models.ceq_val[self.best_index, :] + + def lag_model(self, x): + """ + Evaluate the Lagrangian model at a given point. + + Parameters + ---------- + x : `numpy.ndarray`, shape (n,) + Point at which the Lagrangian model is evaluated. + + Returns + ------- + float + Value of the Lagrangian model at `x`. + """ + return ( + self.models.fun(x) + + self._lm_linear_ub + @ (self._pb.linear.a_ub @ x - self._pb.linear.b_ub) + + self._lm_linear_eq + @ (self._pb.linear.a_eq @ x - self._pb.linear.b_eq) + + self._lm_nonlinear_ub @ self.models.cub(x) + + self._lm_nonlinear_eq @ self.models.ceq(x) + ) + + def lag_model_grad(self, x): + """ + Evaluate the gradient of the Lagrangian model at a given point. + + Parameters + ---------- + x : `numpy.ndarray`, shape (n,) + Point at which the gradient of the Lagrangian model is evaluated. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Gradient of the Lagrangian model at `x`. + """ + return ( + self.models.fun_grad(x) + + self._lm_linear_ub @ self._pb.linear.a_ub + + self._lm_linear_eq @ self._pb.linear.a_eq + + self._lm_nonlinear_ub @ self.models.cub_grad(x) + + self._lm_nonlinear_eq @ self.models.ceq_grad(x) + ) + + def lag_model_hess(self): + """ + Evaluate the Hessian matrix of the Lagrangian model at a given point. + + Returns + ------- + `numpy.ndarray`, shape (n, n) + Hessian matrix of the Lagrangian model at `x`. + """ + hess = self.models.fun_hess() + if self.m_nonlinear_ub > 0: + hess += self._lm_nonlinear_ub @ self.models.cub_hess() + if self.m_nonlinear_eq > 0: + hess += self._lm_nonlinear_eq @ self.models.ceq_hess() + return hess + + def lag_model_hess_prod(self, v): + """ + Evaluate the right product of the Hessian matrix of the Lagrangian + model with a given vector. + + Parameters + ---------- + v : `numpy.ndarray`, shape (n,) + Vector with which the Hessian matrix of the Lagrangian model is + multiplied from the right. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Right product of the Hessian matrix of the Lagrangian model with + `v`. + """ + return ( + self.models.fun_hess_prod(v) + + self._lm_nonlinear_ub @ self.models.cub_hess_prod(v) + + self._lm_nonlinear_eq @ self.models.ceq_hess_prod(v) + ) + + def lag_model_curv(self, v): + """ + Evaluate the curvature of the Lagrangian model along a given direction. + + Parameters + ---------- + v : `numpy.ndarray`, shape (n,) + Direction along which the curvature of the Lagrangian model is + evaluated. + + Returns + ------- + float + Curvature of the Lagrangian model along `v`. + """ + return ( + self.models.fun_curv(v) + + self._lm_nonlinear_ub @ self.models.cub_curv(v) + + self._lm_nonlinear_eq @ self.models.ceq_curv(v) + ) + + def sqp_fun(self, step): + """ + Evaluate the objective function of the SQP subproblem. + + Parameters + ---------- + step : `numpy.ndarray`, shape (n,) + Step along which the objective function of the SQP subproblem is + evaluated. + + Returns + ------- + float + Value of the objective function of the SQP subproblem along `step`. + """ + return step @ ( + self.models.fun_grad(self.x_best) + + 0.5 * self.lag_model_hess_prod(step) + ) + + def sqp_cub(self, step): + """ + Evaluate the linearization of the nonlinear inequality constraints. + + Parameters + ---------- + step : `numpy.ndarray`, shape (n,) + Step along which the linearization of the nonlinear inequality + constraints is evaluated. + + Returns + ------- + `numpy.ndarray`, shape (m_nonlinear_ub,) + Value of the linearization of the nonlinear inequality constraints + along `step`. + """ + return ( + self.models.cub(self.x_best) + + self.models.cub_grad(self.x_best) @ step + ) + + def sqp_ceq(self, step): + """ + Evaluate the linearization of the nonlinear equality constraints. + + Parameters + ---------- + step : `numpy.ndarray`, shape (n,) + Step along which the linearization of the nonlinear equality + constraints is evaluated. + + Returns + ------- + `numpy.ndarray`, shape (m_nonlinear_ub,) + Value of the linearization of the nonlinear equality constraints + along `step`. + """ + return ( + self.models.ceq(self.x_best) + + self.models.ceq_grad(self.x_best) @ step + ) + + def merit(self, x, fun_val=None, cub_val=None, ceq_val=None): + """ + Evaluate the merit function at a given point. + + Parameters + ---------- + x : `numpy.ndarray`, shape (n,) + Point at which the merit function is evaluated. + fun_val : float, optional + Value of the objective function at `x`. If not provided, the + objective function is evaluated at `x`. + cub_val : `numpy.ndarray`, shape (m_nonlinear_ub,), optional + Values of the nonlinear inequality constraints. If not provided, + the nonlinear inequality constraints are evaluated at `x`. + ceq_val : `numpy.ndarray`, shape (m_nonlinear_eq,), optional + Values of the nonlinear equality constraints. If not provided, + the nonlinear equality constraints are evaluated at `x`. + + Returns + ------- + float + Value of the merit function at `x`. + """ + if fun_val is None or cub_val is None or ceq_val is None: + fun_val, cub_val, ceq_val = self._pb(x, self.penalty) + m_val = fun_val + if self._penalty > 0.0: + c_val = self._pb.violation(x, cub_val=cub_val, ceq_val=ceq_val) + if np.count_nonzero(c_val): + m_val += self._penalty * np.linalg.norm(c_val) + return m_val + + def get_constraint_linearizations(self, x): + """ + Get the linearizations of the constraints at a given point. + + Parameters + ---------- + x : `numpy.ndarray`, shape (n,) + Point at which the linearizations of the constraints are evaluated. + + Returns + ------- + `numpy.ndarray`, shape (m_linear_ub + m_nonlinear_ub, n) + Left-hand side matrix of the linearized inequality constraints. + `numpy.ndarray`, shape (m_linear_ub + m_nonlinear_ub,) + Right-hand side vector of the linearized inequality constraints. + `numpy.ndarray`, shape (m_linear_eq + m_nonlinear_eq, n) + Left-hand side matrix of the linearized equality constraints. + `numpy.ndarray`, shape (m_linear_eq + m_nonlinear_eq,) + Right-hand side vector of the linearized equality constraints. + """ + aub = np.block( + [ + [self._pb.linear.a_ub], + [self.models.cub_grad(x)], + ] + ) + bub = np.block( + [ + self._pb.linear.b_ub - self._pb.linear.a_ub @ x, + -self.models.cub(x), + ] + ) + aeq = np.block( + [ + [self._pb.linear.a_eq], + [self.models.ceq_grad(x)], + ] + ) + beq = np.block( + [ + self._pb.linear.b_eq - self._pb.linear.a_eq @ x, + -self.models.ceq(x), + ] + ) + return aub, bub, aeq, beq + + def get_trust_region_step(self, options): + """ + Get the trust-region step. + + The trust-region step is computed by solving the derivative-free + trust-region SQP subproblem using a Byrd-Omojokun composite-step + approach. For more details, see Section 5.2.3 of [1]_. + + Parameters + ---------- + options : dict + Options of the solver. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Normal step. + `numpy.ndarray`, shape (n,) + Tangential step. + + References + ---------- + .. [1] T. M. Ragonneau. *Model-Based Derivative-Free Optimization + Methods and Software*. PhD thesis, Department of Applied + Mathematics, The Hong Kong Polytechnic University, Hong Kong, China, + 2022. URL: https://theses.lib.polyu.edu.hk/handle/200/12294. + """ + # Evaluate the linearizations of the constraints. + aub, bub, aeq, beq = self.get_constraint_linearizations(self.x_best) + xl = self._pb.bounds.xl - self.x_best + xu = self._pb.bounds.xu - self.x_best + + # Evaluate the normal step. + radius = self._constants[Constants.BYRD_OMOJOKUN_FACTOR] * self.radius + normal_step = normal_byrd_omojokun( + aub, + bub, + aeq, + beq, + xl, + xu, + radius, + options[Options.DEBUG], + **self._constants, + ) + if options[Options.DEBUG]: + tol = get_arrays_tol(xl, xu) + if (np.any(normal_step + tol < xl) + or np.any(xu < normal_step - tol)): + warnings.warn( + "the normal step does not respect the bound constraint.", + RuntimeWarning, + 2, + ) + if np.linalg.norm(normal_step) > 1.1 * radius: + warnings.warn( + "the normal step does not respect the trust-region " + "constraint.", + RuntimeWarning, + 2, + ) + + # Evaluate the tangential step. + radius = np.sqrt(self.radius**2.0 - normal_step @ normal_step) + xl -= normal_step + xu -= normal_step + bub = np.maximum(bub - aub @ normal_step, 0.0) + g_best = self.models.fun_grad(self.x_best) + self.lag_model_hess_prod( + normal_step + ) + if self._pb.type in ["unconstrained", "bound-constrained"]: + tangential_step = tangential_byrd_omojokun( + g_best, + self.lag_model_hess_prod, + xl, + xu, + radius, + options[Options.DEBUG], + **self._constants, + ) + else: + tangential_step = constrained_tangential_byrd_omojokun( + g_best, + self.lag_model_hess_prod, + xl, + xu, + aub, + bub, + aeq, + radius, + options["debug"], + **self._constants, + ) + if options[Options.DEBUG]: + tol = get_arrays_tol(xl, xu) + if np.any(tangential_step + tol < xl) or np.any( + xu < tangential_step - tol + ): + warnings.warn( + "The tangential step does not respect the bound " + "constraints.", + RuntimeWarning, + 2, + ) + if ( + np.linalg.norm(normal_step + tangential_step) + > 1.1 * np.sqrt(2.0) * self.radius + ): + warnings.warn( + "The trial step does not respect the trust-region " + "constraint.", + RuntimeWarning, + 2, + ) + return normal_step, tangential_step + + def get_geometry_step(self, k_new, options): + """ + Get the geometry-improving step. + + Three different geometry-improving steps are computed and the best one + is returned. For more details, see Section 5.2.7 of [1]_. + + Parameters + ---------- + k_new : int + Index of the interpolation point to be modified. + options : dict + Options of the solver. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Geometry-improving step. + + Raises + ------ + `numpy.linalg.LinAlgError` + If the computation of a determinant fails. + + References + ---------- + .. [1] T. M. Ragonneau. *Model-Based Derivative-Free Optimization + Methods and Software*. PhD thesis, Department of Applied + Mathematics, The Hong Kong Polytechnic University, Hong Kong, China, + 2022. URL: https://theses.lib.polyu.edu.hk/handle/200/12294. + """ + if options[Options.DEBUG]: + assert ( + k_new != self.best_index + ), "The index `k_new` must be different from the best index." + + # Build the k_new-th Lagrange polynomial. + coord_vec = np.squeeze(np.eye(1, self.models.npt, k_new)) + lag = Quadratic( + self.models.interpolation, + coord_vec, + options[Options.DEBUG], + ) + g_lag = lag.grad(self.x_best, self.models.interpolation) + + # Compute a simple constrained Cauchy step. + xl = self._pb.bounds.xl - self.x_best + xu = self._pb.bounds.xu - self.x_best + step = cauchy_geometry( + 0.0, + g_lag, + lambda v: lag.curv(v, self.models.interpolation), + xl, + xu, + self.radius, + options[Options.DEBUG], + ) + sigma = self.models.determinants(self.x_best + step, k_new) + + # Compute the solution on the straight lines joining the interpolation + # points to the k-th one, and choose it if it provides a larger value + # of the determinant of the interpolation system in absolute value. + xpt = ( + self.models.interpolation.xpt + - self.models.interpolation.xpt[:, self.best_index, np.newaxis] + ) + xpt[:, [0, self.best_index]] = xpt[:, [self.best_index, 0]] + step_alt = spider_geometry( + 0.0, + g_lag, + lambda v: lag.curv(v, self.models.interpolation), + xpt[:, 1:], + xl, + xu, + self.radius, + options[Options.DEBUG], + ) + sigma_alt = self.models.determinants(self.x_best + step_alt, k_new) + if abs(sigma_alt) > abs(sigma): + step = step_alt + sigma = sigma_alt + + # Compute a Cauchy step on the tangent space of the active constraints. + if self._pb.type in [ + "linearly constrained", + "nonlinearly constrained", + ]: + aub, bub, aeq, beq = ( + self.get_constraint_linearizations(self.x_best)) + tol_bd = get_arrays_tol(xl, xu) + tol_ub = get_arrays_tol(bub) + free_xl = xl <= -tol_bd + free_xu = xu >= tol_bd + free_ub = bub >= tol_ub + + # Compute the Cauchy step. + n_act, q = qr_tangential_byrd_omojokun( + aub, + aeq, + free_xl, + free_xu, + free_ub, + ) + g_lag_proj = q[:, n_act:] @ (q[:, n_act:].T @ g_lag) + norm_g_lag_proj = np.linalg.norm(g_lag_proj) + if 0 < n_act < self._pb.n and norm_g_lag_proj > TINY * self.radius: + step_alt = (self.radius / norm_g_lag_proj) * g_lag_proj + if lag.curv(step_alt, self.models.interpolation) < 0.0: + step_alt = -step_alt + + # Evaluate the constraint violation at the Cauchy step. + cbd = np.block([xl - step_alt, step_alt - xu]) + cub = aub @ step_alt - bub + ceq = aeq @ step_alt - beq + maxcv_val = max( + np.max(array, initial=0.0) + for array in [cbd, cub, np.abs(ceq)] + ) + + # Accept the new step if it is nearly feasible and do not + # drastically worsen the determinant of the interpolation + # system in absolute value. + tol = np.max(np.abs(step_alt[~free_xl]), initial=0.0) + tol = np.max(np.abs(step_alt[~free_xu]), initial=tol) + tol = np.max(np.abs(aub[~free_ub, :] @ step_alt), initial=tol) + tol = min(10.0 * tol, 1e-2 * np.linalg.norm(step_alt)) + if maxcv_val <= tol: + sigma_alt = self.models.determinants( + self.x_best + step_alt, k_new + ) + if abs(sigma_alt) >= 0.1 * abs(sigma): + step = np.clip(step_alt, xl, xu) + + if options[Options.DEBUG]: + tol = get_arrays_tol(xl, xu) + if np.any(step + tol < xl) or np.any(xu < step - tol): + warnings.warn( + "The geometry step does not respect the bound " + "constraints.", + RuntimeWarning, + 2, + ) + if np.linalg.norm(step) > 1.1 * self.radius: + warnings.warn( + "The geometry step does not respect the " + "trust-region constraint.", + RuntimeWarning, + 2, + ) + return step + + def get_second_order_correction_step(self, step, options): + """ + Get the second-order correction step. + + Parameters + ---------- + step : `numpy.ndarray`, shape (n,) + Trust-region step. + options : dict + Options of the solver. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Second-order correction step. + """ + # Evaluate the linearizations of the constraints. + aub, bub, aeq, beq = self.get_constraint_linearizations(self.x_best) + xl = self._pb.bounds.xl - self.x_best + xu = self._pb.bounds.xu - self.x_best + radius = np.linalg.norm(step) + soc_step = normal_byrd_omojokun( + aub, + bub, + aeq, + beq, + xl, + xu, + radius, + options[Options.DEBUG], + **self._constants, + ) + if options[Options.DEBUG]: + tol = get_arrays_tol(xl, xu) + if np.any(soc_step + tol < xl) or np.any(xu < soc_step - tol): + warnings.warn( + "The second-order correction step does not " + "respect the bound constraints.", + RuntimeWarning, + 2, + ) + if np.linalg.norm(soc_step) > 1.1 * radius: + warnings.warn( + "The second-order correction step does not " + "respect the trust-region constraint.", + RuntimeWarning, + 2, + ) + return soc_step + + def get_reduction_ratio(self, step, fun_val, cub_val, ceq_val): + """ + Get the reduction ratio. + + Parameters + ---------- + step : `numpy.ndarray`, shape (n,) + Trust-region step. + fun_val : float + Objective function value at the trial point. + cub_val : `numpy.ndarray`, shape (m_nonlinear_ub,) + Nonlinear inequality constraint values at the trial point. + ceq_val : `numpy.ndarray`, shape (m_nonlinear_eq,) + Nonlinear equality constraint values at the trial point. + + Returns + ------- + float + Reduction ratio. + """ + merit_old = self.merit( + self.x_best, + self.fun_best, + self.cub_best, + self.ceq_best, + ) + merit_new = self.merit(self.x_best + step, fun_val, cub_val, ceq_val) + merit_model_old = self.merit( + self.x_best, + 0.0, + self.models.cub(self.x_best), + self.models.ceq(self.x_best), + ) + merit_model_new = self.merit( + self.x_best + step, + self.sqp_fun(step), + self.sqp_cub(step), + self.sqp_ceq(step), + ) + if abs(merit_model_old - merit_model_new) > TINY * abs( + merit_old - merit_new + ): + return (merit_old - merit_new) / abs( + merit_model_old - merit_model_new + ) + else: + return -1.0 + + def increase_penalty(self, step): + """ + Increase the penalty parameter. + + Parameters + ---------- + step : `numpy.ndarray`, shape (n,) + Trust-region step. + """ + aub, bub, aeq, beq = self.get_constraint_linearizations(self.x_best) + viol_diff = max( + np.linalg.norm( + np.block( + [ + np.maximum(0.0, -bub), + beq, + ] + ) + ) + - np.linalg.norm( + np.block( + [ + np.maximum(0.0, aub @ step - bub), + aeq @ step - beq, + ] + ) + ), + 0.0, + ) + sqp_val = self.sqp_fun(step) + + threshold = np.linalg.norm( + np.block( + [ + self._lm_linear_ub, + self._lm_linear_eq, + self._lm_nonlinear_ub, + self._lm_nonlinear_eq, + ] + ) + ) + if abs(viol_diff) > TINY * abs(sqp_val): + threshold = max(threshold, sqp_val / viol_diff) + best_index_save = self.best_index + if ( + self._penalty + <= self._constants[Constants.PENALTY_INCREASE_THRESHOLD] + * threshold + ): + self._penalty = max( + self._constants[Constants.PENALTY_INCREASE_FACTOR] * threshold, + 1.0, + ) + self.set_best_index() + return best_index_save == self.best_index + + def decrease_penalty(self): + """ + Decrease the penalty parameter. + """ + self._penalty = min(self._penalty, self._get_low_penalty()) + self.set_best_index() + + def set_best_index(self): + """ + Set the index of the best point. + """ + best_index = self.best_index + m_best = self.merit( + self.x_best, + self.models.fun_val[best_index], + self.models.cub_val[best_index, :], + self.models.ceq_val[best_index, :], + ) + r_best = self._pb.maxcv( + self.x_best, + self.models.cub_val[best_index, :], + self.models.ceq_val[best_index, :], + ) + tol = ( + 10.0 + * EPS + * max(self.models.n, self.models.npt) + * max(abs(m_best), 1.0) + ) + for k in range(self.models.npt): + if k != self.best_index: + x_val = self.models.interpolation.point(k) + m_val = self.merit( + x_val, + self.models.fun_val[k], + self.models.cub_val[k, :], + self.models.ceq_val[k, :], + ) + r_val = self._pb.maxcv( + x_val, + self.models.cub_val[k, :], + self.models.ceq_val[k, :], + ) + if m_val < m_best or (m_val < m_best + tol and r_val < r_best): + best_index = k + m_best = m_val + r_best = r_val + self._best_index = best_index + + def get_index_to_remove(self, x_new=None): + """ + Get the index of the interpolation point to remove. + + If `x_new` is not provided, the index returned should be used during + the geometry-improvement phase. Otherwise, the index returned is the + best index for included `x_new` in the interpolation set. + + Parameters + ---------- + x_new : `numpy.ndarray`, shape (n,), optional + New point to be included in the interpolation set. + + Returns + ------- + int + Index of the interpolation point to remove. + float + Distance between `x_best` and the removed point. + + Raises + ------ + `numpy.linalg.LinAlgError` + If the computation of a determinant fails. + """ + dist_sq = np.sum( + ( + self.models.interpolation.xpt + - self.models.interpolation.xpt[:, self.best_index, np.newaxis] + ) + ** 2.0, + axis=0, + ) + if x_new is None: + sigma = 1.0 + weights = dist_sq + else: + sigma = self.models.determinants(x_new) + weights = ( + np.maximum( + 1.0, + dist_sq + / max( + self._constants[Constants.LOW_RADIUS_FACTOR] + * self.radius, + self.resolution, + ) + ** 2.0, + ) + ** 3.0 + ) + weights[self.best_index] = -1.0 # do not remove the best point + k_max = np.argmax(weights * np.abs(sigma)) + return k_max, np.sqrt(dist_sq[k_max]) + + def update_radius(self, step, ratio): + """ + Update the trust-region radius. + + Parameters + ---------- + step : `numpy.ndarray`, shape (n,) + Trust-region step. + ratio : float + Reduction ratio. + """ + s_norm = np.linalg.norm(step) + if ratio <= self._constants[Constants.LOW_RATIO]: + self.radius *= self._constants[Constants.DECREASE_RADIUS_FACTOR] + elif ratio <= self._constants[Constants.HIGH_RATIO]: + self.radius = max( + self._constants[Constants.DECREASE_RADIUS_FACTOR] + * self.radius, + s_norm, + ) + else: + self.radius = min( + self._constants[Constants.INCREASE_RADIUS_FACTOR] + * self.radius, + max( + self._constants[Constants.DECREASE_RADIUS_FACTOR] + * self.radius, + self._constants[Constants.INCREASE_RADIUS_THRESHOLD] + * s_norm, + ), + ) + + def enhance_resolution(self, options): + """ + Enhance the resolution of the trust-region framework. + + Parameters + ---------- + options : dict + Options of the solver. + """ + if ( + self._constants[Constants.LARGE_RESOLUTION_THRESHOLD] + * options[Options.RHOEND] + < self.resolution + ): + self.resolution *= self._constants[ + Constants.DECREASE_RESOLUTION_FACTOR + ] + elif ( + self._constants[Constants.MODERATE_RESOLUTION_THRESHOLD] + * options[Options.RHOEND] + < self.resolution + ): + self.resolution = np.sqrt(self.resolution + * options[Options.RHOEND]) + else: + self.resolution = options[Options.RHOEND] + + # Reduce the trust-region radius. + self._radius = max( + self._constants[Constants.DECREASE_RADIUS_FACTOR] * self._radius, + self.resolution, + ) + + def shift_x_base(self, options): + """ + Shift the base point to `x_best`. + + Parameters + ---------- + options : dict + Options of the solver. + """ + self.models.shift_x_base(np.copy(self.x_best), options) + + def set_multipliers(self, x): + """ + Set the Lagrange multipliers. + + This method computes and set the Lagrange multipliers of the linear and + nonlinear constraints to be the QP multipliers. + + Parameters + ---------- + x : `numpy.ndarray`, shape (n,) + Point at which the Lagrange multipliers are computed. + """ + # Build the constraints of the least-squares problem. + incl_linear_ub = self._pb.linear.a_ub @ x >= self._pb.linear.b_ub + incl_nonlinear_ub = self.cub_best >= 0.0 + incl_xl = self._pb.bounds.xl >= x + incl_xu = self._pb.bounds.xu <= x + m_linear_ub = np.count_nonzero(incl_linear_ub) + m_nonlinear_ub = np.count_nonzero(incl_nonlinear_ub) + m_xl = np.count_nonzero(incl_xl) + m_xu = np.count_nonzero(incl_xu) + + if ( + m_linear_ub + m_nonlinear_ub + self.m_linear_eq + + self.m_nonlinear_eq > 0 + ): + identity = np.eye(self._pb.n) + c_jac = np.r_[ + -identity[incl_xl, :], + identity[incl_xu, :], + self._pb.linear.a_ub[incl_linear_ub, :], + self.models.cub_grad(x, incl_nonlinear_ub), + self._pb.linear.a_eq, + self.models.ceq_grad(x), + ] + + # Solve the least-squares problem. + g_best = self.models.fun_grad(x) + xl_lm = np.full(c_jac.shape[0], -np.inf) + xl_lm[: m_xl + m_xu + m_linear_ub + m_nonlinear_ub] = 0.0 + res = lsq_linear( + c_jac.T, + -g_best, + bounds=(xl_lm, np.inf), + method="bvls", + ) + + # Extract the Lagrange multipliers. + self._lm_linear_ub[incl_linear_ub] = res.x[ + m_xl + m_xu:m_xl + m_xu + m_linear_ub + ] + self._lm_linear_ub[~incl_linear_ub] = 0.0 + self._lm_nonlinear_ub[incl_nonlinear_ub] = res.x[ + m_xl + + m_xu + + m_linear_ub:m_xl + + m_xu + + m_linear_ub + + m_nonlinear_ub + ] + self._lm_nonlinear_ub[~incl_nonlinear_ub] = 0.0 + self._lm_linear_eq[:] = res.x[ + m_xl + + m_xu + + m_linear_ub + + m_nonlinear_ub:m_xl + + m_xu + + m_linear_ub + + m_nonlinear_ub + + self.m_linear_eq + ] + self._lm_nonlinear_eq[:] = res.x[ + m_xl + m_xu + m_linear_ub + m_nonlinear_ub + self.m_linear_eq: + ] + + def _get_low_penalty(self): + r_val_ub = np.c_[ + ( + self.models.interpolation.x_base[np.newaxis, :] + + self.models.interpolation.xpt.T + ) + @ self._pb.linear.a_ub.T + - self._pb.linear.b_ub[np.newaxis, :], + self.models.cub_val, + ] + r_val_eq = ( + self.models.interpolation.x_base[np.newaxis, :] + + self.models.interpolation.xpt.T + ) @ self._pb.linear.a_eq.T - self._pb.linear.b_eq[np.newaxis, :] + r_val_eq = np.block( + [ + r_val_eq, + -r_val_eq, + self.models.ceq_val, + -self.models.ceq_val, + ] + ) + r_val = np.block([r_val_ub, r_val_eq]) + c_min = np.nanmin(r_val, axis=0) + c_max = np.nanmax(r_val, axis=0) + indices = ( + c_min + < self._constants[Constants.THRESHOLD_RATIO_CONSTRAINTS] * c_max + ) + if np.any(indices): + f_min = np.nanmin(self.models.fun_val) + f_max = np.nanmax(self.models.fun_val) + c_min_neg = np.minimum(0.0, c_min[indices]) + c_diff = np.min(c_max[indices] - c_min_neg) + if c_diff > TINY * (f_max - f_min): + penalty = (f_max - f_min) / c_diff + else: + penalty = np.inf + else: + penalty = 0.0 + return penalty diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/main.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/main.py new file mode 100644 index 0000000000000000000000000000000000000000..01e5159e0dfebed9a78c6948cb99bfb1d744b6c7 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/main.py @@ -0,0 +1,1506 @@ +import warnings + +import numpy as np +from scipy.optimize import ( + Bounds, + LinearConstraint, + NonlinearConstraint, + OptimizeResult, +) + +from .framework import TrustRegion +from .problem import ( + ObjectiveFunction, + BoundConstraints, + LinearConstraints, + NonlinearConstraints, + Problem, +) +from .utils import ( + MaxEvalError, + TargetSuccess, + CallbackSuccess, + FeasibleSuccess, + exact_1d_array, +) +from .settings import ( + ExitStatus, + Options, + Constants, + DEFAULT_OPTIONS, + DEFAULT_CONSTANTS, + PRINT_OPTIONS, +) + + +def minimize( + fun, + x0, + args=(), + bounds=None, + constraints=(), + callback=None, + options=None, + **kwargs, +): + r""" + Minimize a scalar function using the COBYQA method. + + The Constrained Optimization BY Quadratic Approximations (COBYQA) method is + a derivative-free optimization method designed to solve general nonlinear + optimization problems. A complete description of COBYQA is given in [3]_. + + Parameters + ---------- + fun : {callable, None} + Objective function to be minimized. + + ``fun(x, *args) -> float`` + + where ``x`` is an array with shape (n,) and `args` is a tuple. If `fun` + is ``None``, the objective function is assumed to be the zero function, + resulting in a feasibility problem. + x0 : array_like, shape (n,) + Initial guess. + args : tuple, optional + Extra arguments passed to the objective function. + bounds : {`scipy.optimize.Bounds`, array_like, shape (n, 2)}, optional + Bound constraints of the problem. It can be one of the cases below. + + #. An instance of `scipy.optimize.Bounds`. For the time being, the + argument ``keep_feasible`` is disregarded, and all the constraints + are considered unrelaxable and will be enforced. + #. An array with shape (n, 2). The bound constraints for ``x[i]`` are + ``bounds[i][0] <= x[i] <= bounds[i][1]``. Set ``bounds[i][0]`` to + :math:`-\infty` if there is no lower bound, and set ``bounds[i][1]`` + to :math:`\infty` if there is no upper bound. + + The COBYQA method always respect the bound constraints. + constraints : {Constraint, list}, optional + General constraints of the problem. It can be one of the cases below. + + #. An instance of `scipy.optimize.LinearConstraint`. The argument + ``keep_feasible`` is disregarded. + #. An instance of `scipy.optimize.NonlinearConstraint`. The arguments + ``jac``, ``hess``, ``keep_feasible``, ``finite_diff_rel_step``, and + ``finite_diff_jac_sparsity`` are disregarded. + + #. A list, each of whose elements are described in the cases above. + + callback : callable, optional + A callback executed at each objective function evaluation. The method + terminates if a ``StopIteration`` exception is raised by the callback + function. Its signature can be one of the following: + + ``callback(intermediate_result)`` + + where ``intermediate_result`` is a keyword parameter that contains an + instance of `scipy.optimize.OptimizeResult`, with attributes ``x`` + and ``fun``, being the point at which the objective function is + evaluated and the value of the objective function, respectively. The + name of the parameter must be ``intermediate_result`` for the callback + to be passed an instance of `scipy.optimize.OptimizeResult`. + + Alternatively, the callback function can have the signature: + + ``callback(xk)`` + + where ``xk`` is the point at which the objective function is evaluated. + Introspection is used to determine which of the signatures to invoke. + options : dict, optional + Options passed to the solver. Accepted keys are: + + disp : bool, optional + Whether to print information about the optimization procedure. + Default is ``False``. + maxfev : int, optional + Maximum number of function evaluations. Default is ``500 * n``. + maxiter : int, optional + Maximum number of iterations. Default is ``1000 * n``. + target : float, optional + Target on the objective function value. The optimization + procedure is terminated when the objective function value of a + feasible point is less than or equal to this target. Default is + ``-numpy.inf``. + feasibility_tol : float, optional + Tolerance on the constraint violation. If the maximum + constraint violation at a point is less than or equal to this + tolerance, the point is considered feasible. Default is + ``numpy.sqrt(numpy.finfo(float).eps)``. + radius_init : float, optional + Initial trust-region radius. Typically, this value should be in + the order of one tenth of the greatest expected change to `x0`. + Default is ``1.0``. + radius_final : float, optional + Final trust-region radius. It should indicate the accuracy + required in the final values of the variables. Default is + ``1e-6``. + nb_points : int, optional + Number of interpolation points used to build the quadratic + models of the objective and constraint functions. Default is + ``2 * n + 1``. + scale : bool, optional + Whether to scale the variables according to the bounds. Default + is ``False``. + filter_size : int, optional + Maximum number of points in the filter. The filter is used to + select the best point returned by the optimization procedure. + Default is ``sys.maxsize``. + store_history : bool, optional + Whether to store the history of the function evaluations. + Default is ``False``. + history_size : int, optional + Maximum number of function evaluations to store in the history. + Default is ``sys.maxsize``. + debug : bool, optional + Whether to perform additional checks during the optimization + procedure. This option should be used only for debugging + purposes and is highly discouraged to general users. Default is + ``False``. + + Other constants (from the keyword arguments) are described below. They + are not intended to be changed by general users. They should only be + changed by users with a deep understanding of the algorithm, who want + to experiment with different settings. + + Returns + ------- + `scipy.optimize.OptimizeResult` + Result of the optimization procedure, with the following fields: + + message : str + Description of the cause of the termination. + success : bool + Whether the optimization procedure terminated successfully. + status : int + Termination status of the optimization procedure. + x : `numpy.ndarray`, shape (n,) + Solution point. + fun : float + Objective function value at the solution point. + maxcv : float + Maximum constraint violation at the solution point. + nfev : int + Number of function evaluations. + nit : int + Number of iterations. + + If ``store_history`` is True, the result also has the following fields: + + fun_history : `numpy.ndarray`, shape (nfev,) + History of the objective function values. + maxcv_history : `numpy.ndarray`, shape (nfev,) + History of the maximum constraint violations. + + A description of the termination statuses is given below. + + .. list-table:: + :widths: 25 75 + :header-rows: 1 + + * - Exit status + - Description + * - 0 + - The lower bound for the trust-region radius has been reached. + * - 1 + - The target objective function value has been reached. + * - 2 + - All variables are fixed by the bound constraints. + * - 3 + - The callback requested to stop the optimization procedure. + * - 4 + - The feasibility problem received has been solved successfully. + * - 5 + - The maximum number of function evaluations has been exceeded. + * - 6 + - The maximum number of iterations has been exceeded. + * - -1 + - The bound constraints are infeasible. + * - -2 + - A linear algebra error occurred. + + Other Parameters + ---------------- + decrease_radius_factor : float, optional + Factor by which the trust-region radius is reduced when the reduction + ratio is low or negative. Default is ``0.5``. + increase_radius_factor : float, optional + Factor by which the trust-region radius is increased when the reduction + ratio is large. Default is ``numpy.sqrt(2.0)``. + increase_radius_threshold : float, optional + Threshold that controls the increase of the trust-region radius when + the reduction ratio is large. Default is ``2.0``. + decrease_radius_threshold : float, optional + Threshold used to determine whether the trust-region radius should be + reduced to the resolution. Default is ``1.4``. + decrease_resolution_factor : float, optional + Factor by which the resolution is reduced when the current value is far + from its final value. Default is ``0.1``. + large_resolution_threshold : float, optional + Threshold used to determine whether the resolution is far from its + final value. Default is ``250.0``. + moderate_resolution_threshold : float, optional + Threshold used to determine whether the resolution is close to its + final value. Default is ``16.0``. + low_ratio : float, optional + Threshold used to determine whether the reduction ratio is low. Default + is ``0.1``. + high_ratio : float, optional + Threshold used to determine whether the reduction ratio is high. + Default is ``0.7``. + very_low_ratio : float, optional + Threshold used to determine whether the reduction ratio is very low. + This is used to determine whether the models should be reset. Default + is ``0.01``. + penalty_increase_threshold : float, optional + Threshold used to determine whether the penalty parameter should be + increased. Default is ``1.5``. + penalty_increase_factor : float, optional + Factor by which the penalty parameter is increased. Default is ``2.0``. + short_step_threshold : float, optional + Factor used to determine whether the trial step is too short. Default + is ``0.5``. + low_radius_factor : float, optional + Factor used to determine which interpolation point should be removed + from the interpolation set at each iteration. Default is ``0.1``. + byrd_omojokun_factor : float, optional + Factor by which the trust-region radius is reduced for the computations + of the normal step in the Byrd-Omojokun composite-step approach. + Default is ``0.8``. + threshold_ratio_constraints : float, optional + Threshold used to determine which constraints should be taken into + account when decreasing the penalty parameter. Default is ``2.0``. + large_shift_factor : float, optional + Factor used to determine whether the point around which the quadratic + models are built should be updated. Default is ``10.0``. + large_gradient_factor : float, optional + Factor used to determine whether the models should be reset. Default is + ``10.0``. + resolution_factor : float, optional + Factor by which the resolution is decreased. Default is ``2.0``. + improve_tcg : bool, optional + Whether to improve the steps computed by the truncated conjugate + gradient method when the trust-region boundary is reached. Default is + ``True``. + + References + ---------- + .. [1] J. Nocedal and S. J. Wright. *Numerical Optimization*. Springer Ser. + Oper. Res. Financ. Eng. Springer, New York, NY, USA, second edition, + 2006. `doi:10.1007/978-0-387-40065-5 + `_. + .. [2] M. J. D. Powell. A direct search optimization method that models the + objective and constraint functions by linear interpolation. In S. Gomez + and J.-P. Hennart, editors, *Advances in Optimization and Numerical + Analysis*, volume 275 of Math. Appl., pages 51--67. Springer, Dordrecht, + Netherlands, 1994. `doi:10.1007/978-94-015-8330-5_4 + `_. + .. [3] T. M. Ragonneau. *Model-Based Derivative-Free Optimization Methods + and Software*. PhD thesis, Department of Applied Mathematics, The Hong + Kong Polytechnic University, Hong Kong, China, 2022. URL: + https://theses.lib.polyu.edu.hk/handle/200/12294. + + Examples + -------- + To demonstrate how to use `minimize`, we first minimize the Rosenbrock + function implemented in `scipy.optimize` in an unconstrained setting. + + .. testsetup:: + + import numpy as np + np.set_printoptions(precision=3, suppress=True) + + >>> from cobyqa import minimize + >>> from scipy.optimize import rosen + + To solve the problem using COBYQA, run: + + >>> x0 = [1.3, 0.7, 0.8, 1.9, 1.2] + >>> res = minimize(rosen, x0) + >>> res.x + array([1., 1., 1., 1., 1.]) + + To see how bound and constraints are handled using `minimize`, we solve + Example 16.4 of [1]_, defined as + + .. math:: + + \begin{aligned} + \min_{x \in \mathbb{R}^2} & \quad (x_1 - 1)^2 + (x_2 - 2.5)^2\\ + \text{s.t.} & \quad -x_1 + 2x_2 \le 2,\\ + & \quad x_1 + 2x_2 \le 6,\\ + & \quad x_1 - 2x_2 \le 2,\\ + & \quad x_1 \ge 0,\\ + & \quad x_2 \ge 0. + \end{aligned} + + >>> import numpy as np + >>> from scipy.optimize import Bounds, LinearConstraint + + Its objective function can be implemented as: + + >>> def fun(x): + ... return (x[0] - 1.0)**2 + (x[1] - 2.5)**2 + + This problem can be solved using `minimize` as: + + >>> x0 = [2.0, 0.0] + >>> bounds = Bounds([0.0, 0.0], np.inf) + >>> constraints = LinearConstraint([ + ... [-1.0, 2.0], + ... [1.0, 2.0], + ... [1.0, -2.0], + ... ], -np.inf, [2.0, 6.0, 2.0]) + >>> res = minimize(fun, x0, bounds=bounds, constraints=constraints) + >>> res.x + array([1.4, 1.7]) + + To see how nonlinear constraints are handled, we solve Problem (F) of [2]_, + defined as + + .. math:: + + \begin{aligned} + \min_{x \in \mathbb{R}^2} & \quad -x_1 - x_2\\ + \text{s.t.} & \quad x_1^2 - x_2 \le 0,\\ + & \quad x_1^2 + x_2^2 \le 1. + \end{aligned} + + >>> from scipy.optimize import NonlinearConstraint + + Its objective and constraint functions can be implemented as: + + >>> def fun(x): + ... return -x[0] - x[1] + >>> + >>> def cub(x): + ... return [x[0]**2 - x[1], x[0]**2 + x[1]**2] + + This problem can be solved using `minimize` as: + + >>> x0 = [1.0, 1.0] + >>> constraints = NonlinearConstraint(cub, -np.inf, [0.0, 1.0]) + >>> res = minimize(fun, x0, constraints=constraints) + >>> res.x + array([0.707, 0.707]) + + Finally, to see how to supply linear and nonlinear constraints + simultaneously, we solve Problem (G) of [2]_, defined as + + .. math:: + + \begin{aligned} + \min_{x \in \mathbb{R}^3} & \quad x_3\\ + \text{s.t.} & \quad 5x_1 - x_2 + x_3 \ge 0,\\ + & \quad -5x_1 - x_2 + x_3 \ge 0,\\ + & \quad x_1^2 + x_2^2 + 4x_2 \le x_3. + \end{aligned} + + Its objective and nonlinear constraint functions can be implemented as: + + >>> def fun(x): + ... return x[2] + >>> + >>> def cub(x): + ... return x[0]**2 + x[1]**2 + 4.0*x[1] - x[2] + + This problem can be solved using `minimize` as: + + >>> x0 = [1.0, 1.0, 1.0] + >>> constraints = [ + ... LinearConstraint( + ... [[5.0, -1.0, 1.0], [-5.0, -1.0, 1.0]], + ... [0.0, 0.0], + ... np.inf, + ... ), + ... NonlinearConstraint(cub, -np.inf, 0.0), + ... ] + >>> res = minimize(fun, x0, constraints=constraints) + >>> res.x + array([ 0., -3., -3.]) + """ + # Get basic options that are needed for the initialization. + if options is None: + options = {} + else: + options = dict(options) + verbose = options.get(Options.VERBOSE, DEFAULT_OPTIONS[Options.VERBOSE]) + verbose = bool(verbose) + feasibility_tol = options.get( + Options.FEASIBILITY_TOL, + DEFAULT_OPTIONS[Options.FEASIBILITY_TOL], + ) + feasibility_tol = float(feasibility_tol) + scale = options.get(Options.SCALE, DEFAULT_OPTIONS[Options.SCALE]) + scale = bool(scale) + store_history = options.get( + Options.STORE_HISTORY, + DEFAULT_OPTIONS[Options.STORE_HISTORY], + ) + store_history = bool(store_history) + if Options.HISTORY_SIZE in options and options[Options.HISTORY_SIZE] <= 0: + raise ValueError("The size of the history must be positive.") + history_size = options.get( + Options.HISTORY_SIZE, + DEFAULT_OPTIONS[Options.HISTORY_SIZE], + ) + history_size = int(history_size) + if Options.FILTER_SIZE in options and options[Options.FILTER_SIZE] <= 0: + raise ValueError("The size of the filter must be positive.") + filter_size = options.get( + Options.FILTER_SIZE, + DEFAULT_OPTIONS[Options.FILTER_SIZE], + ) + filter_size = int(filter_size) + debug = options.get(Options.DEBUG, DEFAULT_OPTIONS[Options.DEBUG]) + debug = bool(debug) + + # Initialize the objective function. + if not isinstance(args, tuple): + args = (args,) + obj = ObjectiveFunction(fun, verbose, debug, *args) + + # Initialize the bound constraints. + if not hasattr(x0, "__len__"): + x0 = [x0] + n_orig = len(x0) + bounds = BoundConstraints(_get_bounds(bounds, n_orig)) + + # Initialize the constraints. + linear_constraints, nonlinear_constraints = _get_constraints(constraints) + linear = LinearConstraints(linear_constraints, n_orig, debug) + nonlinear = NonlinearConstraints(nonlinear_constraints, verbose, debug) + + # Initialize the problem (and remove the fixed variables). + pb = Problem( + obj, + x0, + bounds, + linear, + nonlinear, + callback, + feasibility_tol, + scale, + store_history, + history_size, + filter_size, + debug, + ) + + # Set the default options. + _set_default_options(options, pb.n) + constants = _set_default_constants(**kwargs) + + # Initialize the models and skip the computations whenever possible. + if not pb.bounds.is_feasible: + # The bound constraints are infeasible. + return _build_result( + pb, + 0.0, + False, + ExitStatus.INFEASIBLE_ERROR, + 0, + options, + ) + elif pb.n == 0: + # All variables are fixed by the bound constraints. + return _build_result( + pb, + 0.0, + True, + ExitStatus.FIXED_SUCCESS, + 0, + options, + ) + if verbose: + print("Starting the optimization procedure.") + print(f"Initial trust-region radius: {options[Options.RHOBEG]}.") + print(f"Final trust-region radius: {options[Options.RHOEND]}.") + print( + f"Maximum number of function evaluations: " + f"{options[Options.MAX_EVAL]}." + ) + print(f"Maximum number of iterations: {options[Options.MAX_ITER]}.") + print() + try: + framework = TrustRegion(pb, options, constants) + except TargetSuccess: + # The target on the objective function value has been reached + return _build_result( + pb, + 0.0, + True, + ExitStatus.TARGET_SUCCESS, + 0, + options, + ) + except CallbackSuccess: + # The callback raised a StopIteration exception. + return _build_result( + pb, + 0.0, + True, + ExitStatus.CALLBACK_SUCCESS, + 0, + options, + ) + except FeasibleSuccess: + # The feasibility problem has been solved successfully. + return _build_result( + pb, + 0.0, + True, + ExitStatus.FEASIBLE_SUCCESS, + 0, + options, + ) + except MaxEvalError: + # The maximum number of function evaluations has been exceeded. + return _build_result( + pb, + 0.0, + False, + ExitStatus.MAX_ITER_WARNING, + 0, + options, + ) + except np.linalg.LinAlgError: + # The construction of the initial interpolation set failed. + return _build_result( + pb, + 0.0, + False, + ExitStatus.LINALG_ERROR, + 0, + options, + ) + + # Start the optimization procedure. + success = False + n_iter = 0 + k_new = None + n_short_steps = 0 + n_very_short_steps = 0 + n_alt_models = 0 + while True: + # Stop the optimization procedure if the maximum number of iterations + # has been exceeded. We do not write the main loop as a for loop + # because we want to access the number of iterations outside the loop. + if n_iter >= options[Options.MAX_ITER]: + status = ExitStatus.MAX_ITER_WARNING + break + n_iter += 1 + + # Update the point around which the quadratic models are built. + if ( + np.linalg.norm( + framework.x_best - framework.models.interpolation.x_base + ) + >= constants[Constants.LARGE_SHIFT_FACTOR] * framework.radius + ): + framework.shift_x_base(options) + + # Evaluate the trial step. + radius_save = framework.radius + normal_step, tangential_step = framework.get_trust_region_step(options) + step = normal_step + tangential_step + s_norm = np.linalg.norm(step) + + # If the trial step is too short, we do not attempt to evaluate the + # objective and constraint functions. Instead, we reduce the + # trust-region radius and check whether the resolution should be + # enhanced and whether the geometry of the interpolation set should be + # improved. Otherwise, we entertain a classical iteration. The + # criterion for performing an exceptional jump is taken from NEWUOA. + if ( + s_norm + <= constants[Constants.SHORT_STEP_THRESHOLD] * framework.resolution + ): + framework.radius *= constants[Constants.DECREASE_RESOLUTION_FACTOR] + if radius_save > framework.resolution: + n_short_steps = 0 + n_very_short_steps = 0 + else: + n_short_steps += 1 + n_very_short_steps += 1 + if s_norm > 0.1 * framework.resolution: + n_very_short_steps = 0 + enhance_resolution = n_short_steps >= 5 or n_very_short_steps >= 3 + if enhance_resolution: + n_short_steps = 0 + n_very_short_steps = 0 + improve_geometry = False + else: + try: + k_new, dist_new = framework.get_index_to_remove() + except np.linalg.LinAlgError: + status = ExitStatus.LINALG_ERROR + break + improve_geometry = dist_new > max( + framework.radius, + constants[Constants.RESOLUTION_FACTOR] + * framework.resolution, + ) + else: + # Increase the penalty parameter if necessary. + same_best_point = framework.increase_penalty(step) + if same_best_point: + # Evaluate the objective and constraint functions. + try: + fun_val, cub_val, ceq_val = _eval( + pb, + framework, + step, + options, + ) + except TargetSuccess: + status = ExitStatus.TARGET_SUCCESS + success = True + break + except FeasibleSuccess: + status = ExitStatus.FEASIBLE_SUCCESS + success = True + break + except CallbackSuccess: + status = ExitStatus.CALLBACK_SUCCESS + success = True + break + except MaxEvalError: + status = ExitStatus.MAX_EVAL_WARNING + break + + # Perform a second-order correction step if necessary. + merit_old = framework.merit( + framework.x_best, + framework.fun_best, + framework.cub_best, + framework.ceq_best, + ) + merit_new = framework.merit( + framework.x_best + step, fun_val, cub_val, ceq_val + ) + if ( + pb.type == "nonlinearly constrained" + and merit_new > merit_old + and np.linalg.norm(normal_step) + > constants[Constants.BYRD_OMOJOKUN_FACTOR] ** 2.0 + * framework.radius + ): + soc_step = framework.get_second_order_correction_step( + step, options + ) + if np.linalg.norm(soc_step) > 0.0: + step += soc_step + + # Evaluate the objective and constraint functions. + try: + fun_val, cub_val, ceq_val = _eval( + pb, + framework, + step, + options, + ) + except TargetSuccess: + status = ExitStatus.TARGET_SUCCESS + success = True + break + except FeasibleSuccess: + status = ExitStatus.FEASIBLE_SUCCESS + success = True + break + except CallbackSuccess: + status = ExitStatus.CALLBACK_SUCCESS + success = True + break + except MaxEvalError: + status = ExitStatus.MAX_EVAL_WARNING + break + + # Calculate the reduction ratio. + ratio = framework.get_reduction_ratio( + step, + fun_val, + cub_val, + ceq_val, + ) + + # Choose an interpolation point to remove. + try: + k_new = framework.get_index_to_remove( + framework.x_best + step + )[0] + except np.linalg.LinAlgError: + status = ExitStatus.LINALG_ERROR + break + + # Update the interpolation set. + try: + ill_conditioned = framework.models.update_interpolation( + k_new, framework.x_best + step, fun_val, cub_val, + ceq_val + ) + except np.linalg.LinAlgError: + status = ExitStatus.LINALG_ERROR + break + framework.set_best_index() + + # Update the trust-region radius. + framework.update_radius(step, ratio) + + # Attempt to replace the models by the alternative ones. + if framework.radius <= framework.resolution: + if ratio >= constants[Constants.VERY_LOW_RATIO]: + n_alt_models = 0 + else: + n_alt_models += 1 + grad = framework.models.fun_grad(framework.x_best) + try: + grad_alt = framework.models.fun_alt_grad( + framework.x_best + ) + except np.linalg.LinAlgError: + status = ExitStatus.LINALG_ERROR + break + if np.linalg.norm(grad) < constants[ + Constants.LARGE_GRADIENT_FACTOR + ] * np.linalg.norm(grad_alt): + n_alt_models = 0 + if n_alt_models >= 3: + try: + framework.models.reset_models() + except np.linalg.LinAlgError: + status = ExitStatus.LINALG_ERROR + break + n_alt_models = 0 + + # Update the Lagrange multipliers. + framework.set_multipliers(framework.x_best + step) + + # Check whether the resolution should be enhanced. + try: + k_new, dist_new = framework.get_index_to_remove() + except np.linalg.LinAlgError: + status = ExitStatus.LINALG_ERROR + break + improve_geometry = ( + ill_conditioned + or ratio <= constants[Constants.LOW_RATIO] + and dist_new + > max( + framework.radius, + constants[Constants.RESOLUTION_FACTOR] + * framework.resolution, + ) + ) + enhance_resolution = ( + radius_save <= framework.resolution + and ratio <= constants[Constants.LOW_RATIO] + and not improve_geometry + ) + else: + # When increasing the penalty parameter, the best point so far + # may change. In this case, we restart the iteration. + enhance_resolution = False + improve_geometry = False + + # Reduce the resolution if necessary. + if enhance_resolution: + if framework.resolution <= options[Options.RHOEND]: + success = True + status = ExitStatus.RADIUS_SUCCESS + break + framework.enhance_resolution(options) + framework.decrease_penalty() + + if verbose: + maxcv_val = pb.maxcv( + framework.x_best, framework.cub_best, framework.ceq_best + ) + _print_step( + f"New trust-region radius: {framework.resolution}", + pb, + pb.build_x(framework.x_best), + framework.fun_best, + maxcv_val, + pb.n_eval, + n_iter, + ) + print() + + # Improve the geometry of the interpolation set if necessary. + if improve_geometry: + try: + step = framework.get_geometry_step(k_new, options) + except np.linalg.LinAlgError: + status = ExitStatus.LINALG_ERROR + break + + # Evaluate the objective and constraint functions. + try: + fun_val, cub_val, ceq_val = _eval(pb, framework, step, options) + except TargetSuccess: + status = ExitStatus.TARGET_SUCCESS + success = True + break + except FeasibleSuccess: + status = ExitStatus.FEASIBLE_SUCCESS + success = True + break + except CallbackSuccess: + status = ExitStatus.CALLBACK_SUCCESS + success = True + break + except MaxEvalError: + status = ExitStatus.MAX_EVAL_WARNING + break + + # Update the interpolation set. + try: + framework.models.update_interpolation( + k_new, + framework.x_best + step, + fun_val, + cub_val, + ceq_val, + ) + except np.linalg.LinAlgError: + status = ExitStatus.LINALG_ERROR + break + framework.set_best_index() + + return _build_result( + pb, + framework.penalty, + success, + status, + n_iter, + options, + ) + + +def _get_bounds(bounds, n): + """ + Uniformize the bounds. + """ + if bounds is None: + return Bounds(np.full(n, -np.inf), np.full(n, np.inf)) + elif isinstance(bounds, Bounds): + if bounds.lb.shape != (n,) or bounds.ub.shape != (n,): + raise ValueError(f"The bounds must have {n} elements.") + return Bounds(bounds.lb, bounds.ub) + elif hasattr(bounds, "__len__"): + bounds = np.asarray(bounds) + if bounds.shape != (n, 2): + raise ValueError( + "The shape of the bounds is not compatible with " + "the number of variables." + ) + return Bounds(bounds[:, 0], bounds[:, 1]) + else: + raise TypeError( + "The bounds must be an instance of " + "scipy.optimize.Bounds or an array-like object." + ) + + +def _get_constraints(constraints): + """ + Extract the linear and nonlinear constraints. + """ + if isinstance(constraints, dict) or not hasattr(constraints, "__len__"): + constraints = (constraints,) + + # Extract the linear and nonlinear constraints. + linear_constraints = [] + nonlinear_constraints = [] + for constraint in constraints: + if isinstance(constraint, LinearConstraint): + lb = exact_1d_array( + constraint.lb, + "The lower bound of the linear constraints must be a vector.", + ) + ub = exact_1d_array( + constraint.ub, + "The upper bound of the linear constraints must be a vector.", + ) + linear_constraints.append( + LinearConstraint( + constraint.A, + *np.broadcast_arrays(lb, ub), + ) + ) + elif isinstance(constraint, NonlinearConstraint): + lb = exact_1d_array( + constraint.lb, + "The lower bound of the " + "nonlinear constraints must be a " + "vector.", + ) + ub = exact_1d_array( + constraint.ub, + "The upper bound of the " + "nonlinear constraints must be a " + "vector.", + ) + nonlinear_constraints.append( + NonlinearConstraint( + constraint.fun, + *np.broadcast_arrays(lb, ub), + ) + ) + elif isinstance(constraint, dict): + if "type" not in constraint or constraint["type"] not in ( + "eq", + "ineq", + ): + raise ValueError('The constraint type must be "eq" or "ineq".') + if "fun" not in constraint or not callable(constraint["fun"]): + raise ValueError("The constraint function must be callable.") + nonlinear_constraints.append( + { + "fun": constraint["fun"], + "type": constraint["type"], + "args": constraint.get("args", ()), + } + ) + else: + raise TypeError( + "The constraints must be instances of " + "scipy.optimize.LinearConstraint, " + "scipy.optimize.NonlinearConstraint, or dict." + ) + return linear_constraints, nonlinear_constraints + + +def _set_default_options(options, n): + """ + Set the default options. + """ + if Options.RHOBEG in options and options[Options.RHOBEG] <= 0.0: + raise ValueError("The initial trust-region radius must be positive.") + if Options.RHOEND in options and options[Options.RHOEND] < 0.0: + raise ValueError("The final trust-region radius must be nonnegative.") + if Options.RHOBEG in options and Options.RHOEND in options: + if options[Options.RHOBEG] < options[Options.RHOEND]: + raise ValueError( + "The initial trust-region radius must be greater " + "than or equal to the final trust-region radius." + ) + elif Options.RHOBEG in options: + options[Options.RHOEND.value] = np.min( + [ + DEFAULT_OPTIONS[Options.RHOEND], + options[Options.RHOBEG], + ] + ) + elif Options.RHOEND in options: + options[Options.RHOBEG.value] = np.max( + [ + DEFAULT_OPTIONS[Options.RHOBEG], + options[Options.RHOEND], + ] + ) + else: + options[Options.RHOBEG.value] = DEFAULT_OPTIONS[Options.RHOBEG] + options[Options.RHOEND.value] = DEFAULT_OPTIONS[Options.RHOEND] + options[Options.RHOBEG.value] = float(options[Options.RHOBEG]) + options[Options.RHOEND.value] = float(options[Options.RHOEND]) + if Options.NPT in options and options[Options.NPT] <= 0: + raise ValueError("The number of interpolation points must be " + "positive.") + if ( + Options.NPT in options + and options[Options.NPT] > ((n + 1) * (n + 2)) // 2 + ): + raise ValueError( + f"The number of interpolation points must be at most " + f"{((n + 1) * (n + 2)) // 2}." + ) + options.setdefault(Options.NPT.value, DEFAULT_OPTIONS[Options.NPT](n)) + options[Options.NPT.value] = int(options[Options.NPT]) + if Options.MAX_EVAL in options and options[Options.MAX_EVAL] <= 0: + raise ValueError( + "The maximum number of function evaluations must be positive." + ) + options.setdefault( + Options.MAX_EVAL.value, + np.max( + [ + DEFAULT_OPTIONS[Options.MAX_EVAL](n), + options[Options.NPT] + 1, + ] + ), + ) + options[Options.MAX_EVAL.value] = int(options[Options.MAX_EVAL]) + if Options.MAX_ITER in options and options[Options.MAX_ITER] <= 0: + raise ValueError("The maximum number of iterations must be positive.") + options.setdefault( + Options.MAX_ITER.value, + DEFAULT_OPTIONS[Options.MAX_ITER](n), + ) + options[Options.MAX_ITER.value] = int(options[Options.MAX_ITER]) + options.setdefault(Options.TARGET.value, DEFAULT_OPTIONS[Options.TARGET]) + options[Options.TARGET.value] = float(options[Options.TARGET]) + options.setdefault( + Options.FEASIBILITY_TOL.value, + DEFAULT_OPTIONS[Options.FEASIBILITY_TOL], + ) + options[Options.FEASIBILITY_TOL.value] = float( + options[Options.FEASIBILITY_TOL] + ) + options.setdefault(Options.VERBOSE.value, DEFAULT_OPTIONS[Options.VERBOSE]) + options[Options.VERBOSE.value] = bool(options[Options.VERBOSE]) + options.setdefault(Options.SCALE.value, DEFAULT_OPTIONS[Options.SCALE]) + options[Options.SCALE.value] = bool(options[Options.SCALE]) + options.setdefault( + Options.FILTER_SIZE.value, + DEFAULT_OPTIONS[Options.FILTER_SIZE], + ) + options[Options.FILTER_SIZE.value] = int(options[Options.FILTER_SIZE]) + options.setdefault( + Options.STORE_HISTORY.value, + DEFAULT_OPTIONS[Options.STORE_HISTORY], + ) + options[Options.STORE_HISTORY.value] = bool(options[Options.STORE_HISTORY]) + options.setdefault( + Options.HISTORY_SIZE.value, + DEFAULT_OPTIONS[Options.HISTORY_SIZE], + ) + options[Options.HISTORY_SIZE.value] = int(options[Options.HISTORY_SIZE]) + options.setdefault(Options.DEBUG.value, DEFAULT_OPTIONS[Options.DEBUG]) + options[Options.DEBUG.value] = bool(options[Options.DEBUG]) + + # Check whether they are any unknown options. + for key in options: + if key not in Options.__members__.values(): + warnings.warn(f"Unknown option: {key}.", RuntimeWarning, 3) + + +def _set_default_constants(**kwargs): + """ + Set the default constants. + """ + constants = dict(kwargs) + constants.setdefault( + Constants.DECREASE_RADIUS_FACTOR.value, + DEFAULT_CONSTANTS[Constants.DECREASE_RADIUS_FACTOR], + ) + constants[Constants.DECREASE_RADIUS_FACTOR.value] = float( + constants[Constants.DECREASE_RADIUS_FACTOR] + ) + if ( + constants[Constants.DECREASE_RADIUS_FACTOR] <= 0.0 + or constants[Constants.DECREASE_RADIUS_FACTOR] >= 1.0 + ): + raise ValueError( + "The constant decrease_radius_factor must be in the interval " + "(0, 1)." + ) + constants.setdefault( + Constants.INCREASE_RADIUS_THRESHOLD.value, + DEFAULT_CONSTANTS[Constants.INCREASE_RADIUS_THRESHOLD], + ) + constants[Constants.INCREASE_RADIUS_THRESHOLD.value] = float( + constants[Constants.INCREASE_RADIUS_THRESHOLD] + ) + if constants[Constants.INCREASE_RADIUS_THRESHOLD] <= 1.0: + raise ValueError( + "The constant increase_radius_threshold must be greater than 1." + ) + if ( + Constants.INCREASE_RADIUS_FACTOR in constants + and constants[Constants.INCREASE_RADIUS_FACTOR] <= 1.0 + ): + raise ValueError( + "The constant increase_radius_factor must be greater than 1." + ) + if ( + Constants.DECREASE_RADIUS_THRESHOLD in constants + and constants[Constants.DECREASE_RADIUS_THRESHOLD] <= 1.0 + ): + raise ValueError( + "The constant decrease_radius_threshold must be greater than 1." + ) + if ( + Constants.INCREASE_RADIUS_FACTOR in constants + and Constants.DECREASE_RADIUS_THRESHOLD in constants + ): + if ( + constants[Constants.DECREASE_RADIUS_THRESHOLD] + >= constants[Constants.INCREASE_RADIUS_FACTOR] + ): + raise ValueError( + "The constant decrease_radius_threshold must be " + "less than increase_radius_factor." + ) + elif Constants.INCREASE_RADIUS_FACTOR in constants: + constants[Constants.DECREASE_RADIUS_THRESHOLD.value] = np.min( + [ + DEFAULT_CONSTANTS[Constants.DECREASE_RADIUS_THRESHOLD], + 0.5 * (1.0 + constants[Constants.INCREASE_RADIUS_FACTOR]), + ] + ) + elif Constants.DECREASE_RADIUS_THRESHOLD in constants: + constants[Constants.INCREASE_RADIUS_FACTOR.value] = np.max( + [ + DEFAULT_CONSTANTS[Constants.INCREASE_RADIUS_FACTOR], + 2.0 * constants[Constants.DECREASE_RADIUS_THRESHOLD], + ] + ) + else: + constants[Constants.INCREASE_RADIUS_FACTOR.value] = DEFAULT_CONSTANTS[ + Constants.INCREASE_RADIUS_FACTOR + ] + constants[Constants.DECREASE_RADIUS_THRESHOLD.value] = ( + DEFAULT_CONSTANTS[Constants.DECREASE_RADIUS_THRESHOLD]) + constants.setdefault( + Constants.DECREASE_RESOLUTION_FACTOR.value, + DEFAULT_CONSTANTS[Constants.DECREASE_RESOLUTION_FACTOR], + ) + constants[Constants.DECREASE_RESOLUTION_FACTOR.value] = float( + constants[Constants.DECREASE_RESOLUTION_FACTOR] + ) + if ( + constants[Constants.DECREASE_RESOLUTION_FACTOR] <= 0.0 + or constants[Constants.DECREASE_RESOLUTION_FACTOR] >= 1.0 + ): + raise ValueError( + "The constant decrease_resolution_factor must be in the interval " + "(0, 1)." + ) + if ( + Constants.LARGE_RESOLUTION_THRESHOLD in constants + and constants[Constants.LARGE_RESOLUTION_THRESHOLD] <= 1.0 + ): + raise ValueError( + "The constant large_resolution_threshold must be greater than 1." + ) + if ( + Constants.MODERATE_RESOLUTION_THRESHOLD in constants + and constants[Constants.MODERATE_RESOLUTION_THRESHOLD] <= 1.0 + ): + raise ValueError( + "The constant moderate_resolution_threshold must be greater than " + "1." + ) + if ( + Constants.LARGE_RESOLUTION_THRESHOLD in constants + and Constants.MODERATE_RESOLUTION_THRESHOLD in constants + ): + if ( + constants[Constants.MODERATE_RESOLUTION_THRESHOLD] + > constants[Constants.LARGE_RESOLUTION_THRESHOLD] + ): + raise ValueError( + "The constant moderate_resolution_threshold " + "must be at most large_resolution_threshold." + ) + elif Constants.LARGE_RESOLUTION_THRESHOLD in constants: + constants[Constants.MODERATE_RESOLUTION_THRESHOLD.value] = np.min( + [ + DEFAULT_CONSTANTS[Constants.MODERATE_RESOLUTION_THRESHOLD], + constants[Constants.LARGE_RESOLUTION_THRESHOLD], + ] + ) + elif Constants.MODERATE_RESOLUTION_THRESHOLD in constants: + constants[Constants.LARGE_RESOLUTION_THRESHOLD.value] = np.max( + [ + DEFAULT_CONSTANTS[Constants.LARGE_RESOLUTION_THRESHOLD], + constants[Constants.MODERATE_RESOLUTION_THRESHOLD], + ] + ) + else: + constants[Constants.LARGE_RESOLUTION_THRESHOLD.value] = ( + DEFAULT_CONSTANTS[Constants.LARGE_RESOLUTION_THRESHOLD] + ) + constants[Constants.MODERATE_RESOLUTION_THRESHOLD.value] = ( + DEFAULT_CONSTANTS[Constants.MODERATE_RESOLUTION_THRESHOLD] + ) + if Constants.LOW_RATIO in constants and ( + constants[Constants.LOW_RATIO] <= 0.0 + or constants[Constants.LOW_RATIO] >= 1.0 + ): + raise ValueError( + "The constant low_ratio must be in the interval (0, 1)." + ) + if Constants.HIGH_RATIO in constants and ( + constants[Constants.HIGH_RATIO] <= 0.0 + or constants[Constants.HIGH_RATIO] >= 1.0 + ): + raise ValueError( + "The constant high_ratio must be in the interval (0, 1)." + ) + if Constants.LOW_RATIO in constants and Constants.HIGH_RATIO in constants: + if constants[Constants.LOW_RATIO] > constants[Constants.HIGH_RATIO]: + raise ValueError( + "The constant low_ratio must be at most high_ratio." + ) + elif Constants.LOW_RATIO in constants: + constants[Constants.HIGH_RATIO.value] = np.max( + [ + DEFAULT_CONSTANTS[Constants.HIGH_RATIO], + constants[Constants.LOW_RATIO], + ] + ) + elif Constants.HIGH_RATIO in constants: + constants[Constants.LOW_RATIO.value] = np.min( + [ + DEFAULT_CONSTANTS[Constants.LOW_RATIO], + constants[Constants.HIGH_RATIO], + ] + ) + else: + constants[Constants.LOW_RATIO.value] = DEFAULT_CONSTANTS[ + Constants.LOW_RATIO + ] + constants[Constants.HIGH_RATIO.value] = DEFAULT_CONSTANTS[ + Constants.HIGH_RATIO + ] + constants.setdefault( + Constants.VERY_LOW_RATIO.value, + DEFAULT_CONSTANTS[Constants.VERY_LOW_RATIO], + ) + constants[Constants.VERY_LOW_RATIO.value] = float( + constants[Constants.VERY_LOW_RATIO] + ) + if ( + constants[Constants.VERY_LOW_RATIO] <= 0.0 + or constants[Constants.VERY_LOW_RATIO] >= 1.0 + ): + raise ValueError( + "The constant very_low_ratio must be in the interval (0, 1)." + ) + if ( + Constants.PENALTY_INCREASE_THRESHOLD in constants + and constants[Constants.PENALTY_INCREASE_THRESHOLD] < 1.0 + ): + raise ValueError( + "The constant penalty_increase_threshold must be " + "greater than or equal to 1." + ) + if ( + Constants.PENALTY_INCREASE_FACTOR in constants + and constants[Constants.PENALTY_INCREASE_FACTOR] <= 1.0 + ): + raise ValueError( + "The constant penalty_increase_factor must be greater than 1." + ) + if ( + Constants.PENALTY_INCREASE_THRESHOLD in constants + and Constants.PENALTY_INCREASE_FACTOR in constants + ): + if ( + constants[Constants.PENALTY_INCREASE_FACTOR] + < constants[Constants.PENALTY_INCREASE_THRESHOLD] + ): + raise ValueError( + "The constant penalty_increase_factor must be " + "greater than or equal to " + "penalty_increase_threshold." + ) + elif Constants.PENALTY_INCREASE_THRESHOLD in constants: + constants[Constants.PENALTY_INCREASE_FACTOR.value] = np.max( + [ + DEFAULT_CONSTANTS[Constants.PENALTY_INCREASE_FACTOR], + constants[Constants.PENALTY_INCREASE_THRESHOLD], + ] + ) + elif Constants.PENALTY_INCREASE_FACTOR in constants: + constants[Constants.PENALTY_INCREASE_THRESHOLD.value] = np.min( + [ + DEFAULT_CONSTANTS[Constants.PENALTY_INCREASE_THRESHOLD], + constants[Constants.PENALTY_INCREASE_FACTOR], + ] + ) + else: + constants[Constants.PENALTY_INCREASE_THRESHOLD.value] = ( + DEFAULT_CONSTANTS[Constants.PENALTY_INCREASE_THRESHOLD] + ) + constants[Constants.PENALTY_INCREASE_FACTOR.value] = DEFAULT_CONSTANTS[ + Constants.PENALTY_INCREASE_FACTOR + ] + constants.setdefault( + Constants.SHORT_STEP_THRESHOLD.value, + DEFAULT_CONSTANTS[Constants.SHORT_STEP_THRESHOLD], + ) + constants[Constants.SHORT_STEP_THRESHOLD.value] = float( + constants[Constants.SHORT_STEP_THRESHOLD] + ) + if ( + constants[Constants.SHORT_STEP_THRESHOLD] <= 0.0 + or constants[Constants.SHORT_STEP_THRESHOLD] >= 1.0 + ): + raise ValueError( + "The constant short_step_threshold must be in the interval (0, 1)." + ) + constants.setdefault( + Constants.LOW_RADIUS_FACTOR.value, + DEFAULT_CONSTANTS[Constants.LOW_RADIUS_FACTOR], + ) + constants[Constants.LOW_RADIUS_FACTOR.value] = float( + constants[Constants.LOW_RADIUS_FACTOR] + ) + if ( + constants[Constants.LOW_RADIUS_FACTOR] <= 0.0 + or constants[Constants.LOW_RADIUS_FACTOR] >= 1.0 + ): + raise ValueError( + "The constant low_radius_factor must be in the interval (0, 1)." + ) + constants.setdefault( + Constants.BYRD_OMOJOKUN_FACTOR.value, + DEFAULT_CONSTANTS[Constants.BYRD_OMOJOKUN_FACTOR], + ) + constants[Constants.BYRD_OMOJOKUN_FACTOR.value] = float( + constants[Constants.BYRD_OMOJOKUN_FACTOR] + ) + if ( + constants[Constants.BYRD_OMOJOKUN_FACTOR] <= 0.0 + or constants[Constants.BYRD_OMOJOKUN_FACTOR] >= 1.0 + ): + raise ValueError( + "The constant byrd_omojokun_factor must be in the interval (0, 1)." + ) + constants.setdefault( + Constants.THRESHOLD_RATIO_CONSTRAINTS.value, + DEFAULT_CONSTANTS[Constants.THRESHOLD_RATIO_CONSTRAINTS], + ) + constants[Constants.THRESHOLD_RATIO_CONSTRAINTS.value] = float( + constants[Constants.THRESHOLD_RATIO_CONSTRAINTS] + ) + if constants[Constants.THRESHOLD_RATIO_CONSTRAINTS] <= 1.0: + raise ValueError( + "The constant threshold_ratio_constraints must be greater than 1." + ) + constants.setdefault( + Constants.LARGE_SHIFT_FACTOR.value, + DEFAULT_CONSTANTS[Constants.LARGE_SHIFT_FACTOR], + ) + constants[Constants.LARGE_SHIFT_FACTOR.value] = float( + constants[Constants.LARGE_SHIFT_FACTOR] + ) + if constants[Constants.LARGE_SHIFT_FACTOR] < 0.0: + raise ValueError("The constant large_shift_factor must be " + "nonnegative.") + constants.setdefault( + Constants.LARGE_GRADIENT_FACTOR.value, + DEFAULT_CONSTANTS[Constants.LARGE_GRADIENT_FACTOR], + ) + constants[Constants.LARGE_GRADIENT_FACTOR.value] = float( + constants[Constants.LARGE_GRADIENT_FACTOR] + ) + if constants[Constants.LARGE_GRADIENT_FACTOR] <= 1.0: + raise ValueError( + "The constant large_gradient_factor must be greater than 1." + ) + constants.setdefault( + Constants.RESOLUTION_FACTOR.value, + DEFAULT_CONSTANTS[Constants.RESOLUTION_FACTOR], + ) + constants[Constants.RESOLUTION_FACTOR.value] = float( + constants[Constants.RESOLUTION_FACTOR] + ) + if constants[Constants.RESOLUTION_FACTOR] <= 1.0: + raise ValueError( + "The constant resolution_factor must be greater than 1." + ) + constants.setdefault( + Constants.IMPROVE_TCG.value, + DEFAULT_CONSTANTS[Constants.IMPROVE_TCG], + ) + constants[Constants.IMPROVE_TCG.value] = bool( + constants[Constants.IMPROVE_TCG] + ) + + # Check whether they are any unknown options. + for key in kwargs: + if key not in Constants.__members__.values(): + warnings.warn(f"Unknown constant: {key}.", RuntimeWarning, 3) + return constants + + +def _eval(pb, framework, step, options): + """ + Evaluate the objective and constraint functions. + """ + if pb.n_eval >= options[Options.MAX_EVAL]: + raise MaxEvalError + x_eval = framework.x_best + step + fun_val, cub_val, ceq_val = pb(x_eval, framework.penalty) + r_val = pb.maxcv(x_eval, cub_val, ceq_val) + if ( + fun_val <= options[Options.TARGET] + and r_val <= options[Options.FEASIBILITY_TOL] + ): + raise TargetSuccess + if pb.is_feasibility and r_val <= options[Options.FEASIBILITY_TOL]: + raise FeasibleSuccess + return fun_val, cub_val, ceq_val + + +def _build_result(pb, penalty, success, status, n_iter, options): + """ + Build the result of the optimization process. + """ + # Build the result. + x, fun, maxcv = pb.best_eval(penalty) + success = success and np.isfinite(fun) and np.isfinite(maxcv) + if status not in [ExitStatus.TARGET_SUCCESS, ExitStatus.FEASIBLE_SUCCESS]: + success = success and maxcv <= options[Options.FEASIBILITY_TOL] + result = OptimizeResult() + result.message = { + ExitStatus.RADIUS_SUCCESS: "The lower bound for the trust-region " + "radius has been reached", + ExitStatus.TARGET_SUCCESS: "The target objective function value has " + "been reached", + ExitStatus.FIXED_SUCCESS: "All variables are fixed by the bound " + "constraints", + ExitStatus.CALLBACK_SUCCESS: "The callback requested to stop the " + "optimization procedure", + ExitStatus.FEASIBLE_SUCCESS: "The feasibility problem received has " + "been solved successfully", + ExitStatus.MAX_EVAL_WARNING: "The maximum number of function " + "evaluations has been exceeded", + ExitStatus.MAX_ITER_WARNING: "The maximum number of iterations has " + "been exceeded", + ExitStatus.INFEASIBLE_ERROR: "The bound constraints are infeasible", + ExitStatus.LINALG_ERROR: "A linear algebra error occurred", + }.get(status, "Unknown exit status") + result.success = success + result.status = status.value + result.x = pb.build_x(x) + result.fun = fun + result.maxcv = maxcv + result.nfev = pb.n_eval + result.nit = n_iter + if options[Options.STORE_HISTORY]: + result.fun_history = pb.fun_history + result.maxcv_history = pb.maxcv_history + + # Print the result if requested. + if options[Options.VERBOSE]: + _print_step( + result.message, + pb, + result.x, + result.fun, + result.maxcv, + result.nfev, + result.nit, + ) + return result + + +def _print_step(message, pb, x, fun_val, r_val, n_eval, n_iter): + """ + Print information about the current state of the optimization process. + """ + print() + print(f"{message}.") + print(f"Number of function evaluations: {n_eval}.") + print(f"Number of iterations: {n_iter}.") + if not pb.is_feasibility: + print(f"Least value of {pb.fun_name}: {fun_val}.") + print(f"Maximum constraint violation: {r_val}.") + with np.printoptions(**PRINT_OPTIONS): + print(f"Corresponding point: {x}.") diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/models.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/models.py new file mode 100644 index 0000000000000000000000000000000000000000..44da70bf03a77e63af9ee45974050d008eed0147 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/models.py @@ -0,0 +1,1531 @@ +import warnings + +import numpy as np +from scipy.linalg import eigh + +from .settings import Options +from .utils import MaxEvalError, TargetSuccess, FeasibleSuccess + + +EPS = np.finfo(float).eps + + +class Interpolation: + """ + Interpolation set. + + This class stores a base point around which the models are expanded and the + interpolation points. The coordinates of the interpolation points are + relative to the base point. + """ + + def __init__(self, pb, options): + """ + Initialize the interpolation set. + + Parameters + ---------- + pb : `cobyqa.problem.Problem` + Problem to be solved. + options : dict + Options of the solver. + """ + # Reduce the initial trust-region radius if necessary. + self._debug = options[Options.DEBUG] + max_radius = 0.5 * np.min(pb.bounds.xu - pb.bounds.xl) + if options[Options.RHOBEG] > max_radius: + options[Options.RHOBEG.value] = max_radius + options[Options.RHOEND.value] = np.min( + [ + options[Options.RHOEND], + max_radius, + ] + ) + + # Set the initial point around which the models are expanded. + self._x_base = np.copy(pb.x0) + very_close_xl_idx = ( + self.x_base <= pb.bounds.xl + 0.5 * options[Options.RHOBEG] + ) + self.x_base[very_close_xl_idx] = pb.bounds.xl[very_close_xl_idx] + close_xl_idx = ( + pb.bounds.xl + 0.5 * options[Options.RHOBEG] < self.x_base + ) & (self.x_base <= pb.bounds.xl + options[Options.RHOBEG]) + self.x_base[close_xl_idx] = np.minimum( + pb.bounds.xl[close_xl_idx] + options[Options.RHOBEG], + pb.bounds.xu[close_xl_idx], + ) + very_close_xu_idx = ( + self.x_base >= pb.bounds.xu - 0.5 * options[Options.RHOBEG] + ) + self.x_base[very_close_xu_idx] = pb.bounds.xu[very_close_xu_idx] + close_xu_idx = ( + self.x_base < pb.bounds.xu - 0.5 * options[Options.RHOBEG] + ) & (pb.bounds.xu - options[Options.RHOBEG] <= self.x_base) + self.x_base[close_xu_idx] = np.maximum( + pb.bounds.xu[close_xu_idx] - options[Options.RHOBEG], + pb.bounds.xl[close_xu_idx], + ) + + # Set the initial interpolation set. + self._xpt = np.zeros((pb.n, options[Options.NPT])) + for k in range(1, options[Options.NPT]): + if k <= pb.n: + if very_close_xu_idx[k - 1]: + self.xpt[k - 1, k] = -options[Options.RHOBEG] + else: + self.xpt[k - 1, k] = options[Options.RHOBEG] + elif k <= 2 * pb.n: + if very_close_xl_idx[k - pb.n - 1]: + self.xpt[k - pb.n - 1, k] = 2.0 * options[Options.RHOBEG] + elif very_close_xu_idx[k - pb.n - 1]: + self.xpt[k - pb.n - 1, k] = -2.0 * options[Options.RHOBEG] + else: + self.xpt[k - pb.n - 1, k] = -options[Options.RHOBEG] + else: + spread = (k - pb.n - 1) // pb.n + k1 = k - (1 + spread) * pb.n - 1 + k2 = (k1 + spread) % pb.n + self.xpt[k1, k] = self.xpt[k1, k1 + 1] + self.xpt[k2, k] = self.xpt[k2, k2 + 1] + self._lhs_cache = None + + @property + def n(self): + """ + Number of variables. + + Returns + ------- + int + Number of variables. + """ + return self.xpt.shape[0] + + @property + def npt(self): + """ + Number of interpolation points. + + Returns + ------- + int + Number of interpolation points. + """ + return self.xpt.shape[1] + + @property + def xpt(self): + """ + Interpolation points. + + Returns + ------- + `numpy.ndarray`, shape (n, npt) + Interpolation points. + """ + return self._xpt + + @xpt.setter + def xpt(self, xpt): + """ + Set the interpolation points. + + Parameters + ---------- + xpt : `numpy.ndarray`, shape (n, npt) + New interpolation points. + """ + if self._debug: + assert xpt.shape == ( + self.n, + self.npt, + ), "The shape of `xpt` is not valid." + self._xpt = xpt + + @property + def x_base(self): + """ + Base point around which the models are expanded. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Base point around which the models are expanded. + """ + return self._x_base + + @x_base.setter + def x_base(self, x_base): + """ + Set the base point around which the models are expanded. + + Parameters + ---------- + x_base : `numpy.ndarray`, shape (n,) + New base point around which the models are expanded. + """ + if self._debug: + assert x_base.shape == ( + self.n, + ), "The shape of `x_base` is not valid." + self._x_base = x_base + + def point(self, k): + """ + Get the `k`-th interpolation point. + + The return point is relative to the origin. + + Parameters + ---------- + k : int + Index of the interpolation point. + + Returns + ------- + `numpy.ndarray`, shape (n,) + `k`-th interpolation point. + """ + if self._debug: + assert 0 <= k < self.npt, "The index `k` is not valid." + return self.x_base + self.xpt[:, k] + + +def build_system(interpolation): + """ + Build the left-hand side matrix of the interpolation system. The + matrix below stores W * diag(right_scaling), + where W is the theoretical matrix of the interpolation system. The + right scaling matrices is chosen to keep the elements in + the matrix well-balanced. + + Parameters + ---------- + interpolation : `cobyqa.models.Interpolation` + Interpolation set. + """ + + _cache = interpolation._lhs_cache + # Compute the scaled directions from the base point to the + # interpolation points. We scale the directions to avoid numerical + # difficulties. + if _cache is not None and np.array_equal( + interpolation.xpt, _cache["xpt"] + ): + return _cache["a"], _cache["right_scaling"], _cache["eigh"] + + scale = np.max(np.linalg.norm(interpolation.xpt, axis=0), initial=EPS) + xpt_scale = interpolation.xpt / scale + + n, npt = xpt_scale.shape + a = np.zeros((npt + n + 1, npt + n + 1)) + a[:npt, :npt] = 0.5 * (xpt_scale.T @ xpt_scale) ** 2.0 + a[:npt, npt] = 1.0 + a[:npt, npt + 1:] = xpt_scale.T + a[npt, :npt] = 1.0 + a[npt + 1:, :npt] = xpt_scale + + # Build the left and right scaling diagonal matrices. + right_scaling = np.empty(npt + n + 1) + right_scaling[:npt] = 1.0 / scale**2.0 + right_scaling[npt] = scale**2.0 + right_scaling[npt + 1:] = scale + + eig_values, eig_vectors = eigh(a, check_finite=False) + + new_cache = { + "xpt": np.copy(interpolation.xpt), + "a": np.copy(a), + "right_scaling": np.copy(right_scaling), + "eigh": (eig_values, eig_vectors), + } + interpolation._lhs_cache = new_cache + + return a, right_scaling, (eig_values, eig_vectors) + + +class Quadratic: + """ + Quadratic model. + + This class stores the Hessian matrix of the quadratic model using the + implicit/explicit representation designed by Powell for NEWUOA [1]_. + + References + ---------- + .. [1] M. J. D. Powell. The NEWUOA software for unconstrained optimization + without derivatives. In G. Di Pillo and M. Roma, editors, *Large-Scale + Nonlinear Optimization*, volume 83 of Nonconvex Optim. Appl., pages + 255--297. Springer, Boston, MA, USA, 2006. `doi:10.1007/0-387-30065-1_16 + `_. + """ + + def __init__(self, interpolation, values, debug): + """ + Initialize the quadratic model. + + Parameters + ---------- + interpolation : `cobyqa.models.Interpolation` + Interpolation set. + values : `numpy.ndarray`, shape (npt,) + Values of the interpolated function at the interpolation points. + debug : bool + Whether to make debugging tests during the execution. + + Raises + ------ + `numpy.linalg.LinAlgError` + If the interpolation system is ill-defined. + """ + self._debug = debug + if self._debug: + assert values.shape == ( + interpolation.npt, + ), "The shape of `values` is not valid." + if interpolation.npt < interpolation.n + 1: + raise ValueError( + f"The number of interpolation points must be at least " + f"{interpolation.n + 1}." + ) + self._const, self._grad, self._i_hess, _ = self._get_model( + interpolation, + values, + ) + self._e_hess = np.zeros((self.n, self.n)) + + def __call__(self, x, interpolation): + """ + Evaluate the quadratic model at a given point. + + Parameters + ---------- + x : `numpy.ndarray`, shape (n,) + Point at which the quadratic model is evaluated. + interpolation : `cobyqa.models.Interpolation` + Interpolation set. + + Returns + ------- + float + Value of the quadratic model at `x`. + """ + if self._debug: + assert x.shape == (self.n,), "The shape of `x` is not valid." + x_diff = x - interpolation.x_base + return ( + self._const + + self._grad @ x_diff + + 0.5 + * ( + self._i_hess @ (interpolation.xpt.T @ x_diff) ** 2.0 + + x_diff @ self._e_hess @ x_diff + ) + ) + + @property + def n(self): + """ + Number of variables. + + Returns + ------- + int + Number of variables. + """ + return self._grad.size + + @property + def npt(self): + """ + Number of interpolation points used to define the quadratic model. + + Returns + ------- + int + Number of interpolation points used to define the quadratic model. + """ + return self._i_hess.size + + def grad(self, x, interpolation): + """ + Evaluate the gradient of the quadratic model at a given point. + + Parameters + ---------- + x : `numpy.ndarray`, shape (n,) + Point at which the gradient of the quadratic model is evaluated. + interpolation : `cobyqa.models.Interpolation` + Interpolation set. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Gradient of the quadratic model at `x`. + """ + if self._debug: + assert x.shape == (self.n,), "The shape of `x` is not valid." + x_diff = x - interpolation.x_base + return self._grad + self.hess_prod(x_diff, interpolation) + + def hess(self, interpolation): + """ + Evaluate the Hessian matrix of the quadratic model. + + Parameters + ---------- + interpolation : `cobyqa.models.Interpolation` + Interpolation set. + + Returns + ------- + `numpy.ndarray`, shape (n, n) + Hessian matrix of the quadratic model. + """ + return self._e_hess + interpolation.xpt @ ( + self._i_hess[:, np.newaxis] * interpolation.xpt.T + ) + + def hess_prod(self, v, interpolation): + """ + Evaluate the right product of the Hessian matrix of the quadratic model + with a given vector. + + Parameters + ---------- + v : `numpy.ndarray`, shape (n,) + Vector with which the Hessian matrix of the quadratic model is + multiplied from the right. + interpolation : `cobyqa.models.Interpolation` + Interpolation set. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Right product of the Hessian matrix of the quadratic model with + `v`. + """ + if self._debug: + assert v.shape == (self.n,), "The shape of `v` is not valid." + return self._e_hess @ v + interpolation.xpt @ ( + self._i_hess * (interpolation.xpt.T @ v) + ) + + def curv(self, v, interpolation): + """ + Evaluate the curvature of the quadratic model along a given direction. + + Parameters + ---------- + v : `numpy.ndarray`, shape (n,) + Direction along which the curvature of the quadratic model is + evaluated. + interpolation : `cobyqa.models.Interpolation` + Interpolation set. + + Returns + ------- + float + Curvature of the quadratic model along `v`. + """ + if self._debug: + assert v.shape == (self.n,), "The shape of `v` is not valid." + return ( + v @ self._e_hess @ v + + self._i_hess @ (interpolation.xpt.T @ v) ** 2.0 + ) + + def update(self, interpolation, k_new, dir_old, values_diff): + """ + Update the quadratic model. + + This method applies the derivative-free symmetric Broyden update to the + quadratic model. The `knew`-th interpolation point must be updated + before calling this method. + + Parameters + ---------- + interpolation : `cobyqa.models.Interpolation` + Updated interpolation set. + k_new : int + Index of the updated interpolation point. + dir_old : `numpy.ndarray`, shape (n,) + Value of ``interpolation.xpt[:, k_new]`` before the update. + values_diff : `numpy.ndarray`, shape (npt,) + Differences between the values of the interpolated nonlinear + function and the previous quadratic model at the updated + interpolation points. + + Raises + ------ + `numpy.linalg.LinAlgError` + If the interpolation system is ill-defined. + """ + if self._debug: + assert 0 <= k_new < self.npt, "The index `k_new` is not valid." + assert dir_old.shape == ( + self.n, + ), "The shape of `dir_old` is not valid." + assert values_diff.shape == ( + self.npt, + ), "The shape of `values_diff` is not valid." + + # Forward the k_new-th element of the implicit Hessian matrix to the + # explicit Hessian matrix. This must be done because the implicit + # Hessian matrix is related to the interpolation points, and the + # k_new-th interpolation point is modified. + self._e_hess += self._i_hess[k_new] * np.outer(dir_old, dir_old) + self._i_hess[k_new] = 0.0 + + # Update the quadratic model. + const, grad, i_hess, ill_conditioned = self._get_model( + interpolation, + values_diff, + ) + self._const += const + self._grad += grad + self._i_hess += i_hess + return ill_conditioned + + def shift_x_base(self, interpolation, new_x_base): + """ + Shift the point around which the quadratic model is defined. + + Parameters + ---------- + interpolation : `cobyqa.models.Interpolation` + Previous interpolation set. + new_x_base : `numpy.ndarray`, shape (n,) + Point that will replace ``interpolation.x_base``. + """ + if self._debug: + assert new_x_base.shape == ( + self.n, + ), "The shape of `new_x_base` is not valid." + self._const = self(new_x_base, interpolation) + self._grad = self.grad(new_x_base, interpolation) + shift = new_x_base - interpolation.x_base + update = np.outer( + shift, + (interpolation.xpt - 0.5 * shift[:, np.newaxis]) @ self._i_hess, + ) + self._e_hess += update + update.T + + @staticmethod + def solve_systems(interpolation, rhs): + """ + Solve the interpolation systems. + + Parameters + ---------- + interpolation : `cobyqa.models.Interpolation` + Interpolation set. + rhs : `numpy.ndarray`, shape (npt + n + 1, m) + Right-hand side vectors of the ``m`` interpolation systems. + + Returns + ------- + `numpy.ndarray`, shape (npt + n + 1, m) + Solutions of the interpolation systems. + `numpy.ndarray`, shape (m, ) + Whether the interpolation systems are ill-conditioned. + + Raises + ------ + `numpy.linalg.LinAlgError` + If the interpolation systems are ill-defined. + """ + n, npt = interpolation.xpt.shape + assert ( + rhs.ndim == 2 and rhs.shape[0] == npt + n + 1 + ), "The shape of `rhs` is not valid." + + # Build the left-hand side matrix of the interpolation system. The + # matrix below stores diag(left_scaling) * W * diag(right_scaling), + # where W is the theoretical matrix of the interpolation system. The + # left and right scaling matrices are chosen to keep the elements in + # the matrix well-balanced. + a, right_scaling, eig = build_system(interpolation) + + # Build the solution. After a discussion with Mike Saunders and Alexis + # Montoison during their visit to the Hong Kong Polytechnic University + # in 2024, we decided to use the eigendecomposition of the symmetric + # matrix a. This is more stable than the previously employed LBL + # decomposition, and allows us to directly detect ill-conditioning of + # the system and to build the least-squares solution if necessary. + # Numerical experiments have shown that this strategy improves the + # performance of the solver. + rhs_scaled = rhs * right_scaling[:, np.newaxis] + if not (np.all(np.isfinite(a)) and np.all(np.isfinite(rhs_scaled))): + raise np.linalg.LinAlgError( + "The interpolation system is ill-defined." + ) + + # calculated in build_system + eig_values, eig_vectors = eig + + large_eig_values = np.abs(eig_values) > EPS + eig_vectors = eig_vectors[:, large_eig_values] + inv_eig_values = 1.0 / eig_values[large_eig_values] + ill_conditioned = ~np.all(large_eig_values, 0) + left_scaled_solutions = eig_vectors @ ( + (eig_vectors.T @ rhs_scaled) * inv_eig_values[:, np.newaxis] + ) + return ( + left_scaled_solutions * right_scaling[:, np.newaxis], + ill_conditioned, + ) + + @staticmethod + def _get_model(interpolation, values): + """ + Solve the interpolation system. + + Parameters + ---------- + interpolation : `cobyqa.models.Interpolation` + Interpolation set. + values : `numpy.ndarray`, shape (npt,) + Values of the interpolated function at the interpolation points. + + Returns + ------- + float + Constant term of the quadratic model. + `numpy.ndarray`, shape (n,) + Gradient of the quadratic model at ``interpolation.x_base``. + `numpy.ndarray`, shape (npt,) + Implicit Hessian matrix of the quadratic model. + + Raises + ------ + `numpy.linalg.LinAlgError` + If the interpolation system is ill-defined. + """ + assert values.shape == ( + interpolation.npt, + ), "The shape of `values` is not valid." + n, npt = interpolation.xpt.shape + x, ill_conditioned = Quadratic.solve_systems( + interpolation, + np.block( + [ + [ + values, + np.zeros(n + 1), + ] + ] + ).T, + ) + return x[npt, 0], x[npt + 1:, 0], x[:npt, 0], ill_conditioned + + +class Models: + """ + Models for a nonlinear optimization problem. + """ + + def __init__(self, pb, options, penalty): + """ + Initialize the models. + + Parameters + ---------- + pb : `cobyqa.problem.Problem` + Problem to be solved. + options : dict + Options of the solver. + penalty : float + Penalty parameter used to select the point in the filter to forward + to the callback function. + + Raises + ------ + `cobyqa.utils.MaxEvalError` + If the maximum number of evaluations is reached. + `cobyqa.utils.TargetSuccess` + If a nearly feasible point has been found with an objective + function value below the target. + `cobyqa.utils.FeasibleSuccess` + If a feasible point has been found for a feasibility problem. + `numpy.linalg.LinAlgError` + If the interpolation system is ill-defined. + """ + # Set the initial interpolation set. + self._debug = options[Options.DEBUG] + self._interpolation = Interpolation(pb, options) + + # Evaluate the nonlinear functions at the initial interpolation points. + x_eval = self.interpolation.point(0) + fun_init, cub_init, ceq_init = pb(x_eval, penalty) + self._fun_val = np.full(options[Options.NPT], np.nan) + self._cub_val = np.full((options[Options.NPT], cub_init.size), np.nan) + self._ceq_val = np.full((options[Options.NPT], ceq_init.size), np.nan) + for k in range(options[Options.NPT]): + if k >= options[Options.MAX_EVAL]: + raise MaxEvalError + if k == 0: + self.fun_val[k] = fun_init + self.cub_val[k, :] = cub_init + self.ceq_val[k, :] = ceq_init + else: + x_eval = self.interpolation.point(k) + self.fun_val[k], self.cub_val[k, :], self.ceq_val[k, :] = pb( + x_eval, + penalty, + ) + + # Stop the iterations if the problem is a feasibility problem and + # the current interpolation point is feasible. + if ( + pb.is_feasibility + and pb.maxcv( + self.interpolation.point(k), + self.cub_val[k, :], + self.ceq_val[k, :], + ) + <= options[Options.FEASIBILITY_TOL] + ): + raise FeasibleSuccess + + # Stop the iterations if the current interpolation point is nearly + # feasible and has an objective function value below the target. + if ( + self._fun_val[k] <= options[Options.TARGET] + and pb.maxcv( + self.interpolation.point(k), + self.cub_val[k, :], + self.ceq_val[k, :], + ) + <= options[Options.FEASIBILITY_TOL] + ): + raise TargetSuccess + + # Build the initial quadratic models. + self._fun = Quadratic( + self.interpolation, + self._fun_val, + options[Options.DEBUG], + ) + self._cub = np.empty(self.m_nonlinear_ub, dtype=Quadratic) + self._ceq = np.empty(self.m_nonlinear_eq, dtype=Quadratic) + for i in range(self.m_nonlinear_ub): + self._cub[i] = Quadratic( + self.interpolation, + self.cub_val[:, i], + options[Options.DEBUG], + ) + for i in range(self.m_nonlinear_eq): + self._ceq[i] = Quadratic( + self.interpolation, + self.ceq_val[:, i], + options[Options.DEBUG], + ) + if self._debug: + self._check_interpolation_conditions() + + @property + def n(self): + """ + Dimension of the problem. + + Returns + ------- + int + Dimension of the problem. + """ + return self.interpolation.n + + @property + def npt(self): + """ + Number of interpolation points. + + Returns + ------- + int + Number of interpolation points. + """ + return self.interpolation.npt + + @property + def m_nonlinear_ub(self): + """ + Number of nonlinear inequality constraints. + + Returns + ------- + int + Number of nonlinear inequality constraints. + """ + return self.cub_val.shape[1] + + @property + def m_nonlinear_eq(self): + """ + Number of nonlinear equality constraints. + + Returns + ------- + int + Number of nonlinear equality constraints. + """ + return self.ceq_val.shape[1] + + @property + def interpolation(self): + """ + Interpolation set. + + Returns + ------- + `cobyqa.models.Interpolation` + Interpolation set. + """ + return self._interpolation + + @property + def fun_val(self): + """ + Values of the objective function at the interpolation points. + + Returns + ------- + `numpy.ndarray`, shape (npt,) + Values of the objective function at the interpolation points. + """ + return self._fun_val + + @property + def cub_val(self): + """ + Values of the nonlinear inequality constraint functions at the + interpolation points. + + Returns + ------- + `numpy.ndarray`, shape (npt, m_nonlinear_ub) + Values of the nonlinear inequality constraint functions at the + interpolation points. + """ + return self._cub_val + + @property + def ceq_val(self): + """ + Values of the nonlinear equality constraint functions at the + interpolation points. + + Returns + ------- + `numpy.ndarray`, shape (npt, m_nonlinear_eq) + Values of the nonlinear equality constraint functions at the + interpolation points. + """ + return self._ceq_val + + def fun(self, x): + """ + Evaluate the quadratic model of the objective function at a given + point. + + Parameters + ---------- + x : `numpy.ndarray`, shape (n,) + Point at which to evaluate the quadratic model of the objective + function. + + Returns + ------- + float + Value of the quadratic model of the objective function at `x`. + """ + if self._debug: + assert x.shape == (self.n,), "The shape of `x` is not valid." + return self._fun(x, self.interpolation) + + def fun_grad(self, x): + """ + Evaluate the gradient of the quadratic model of the objective function + at a given point. + + Parameters + ---------- + x : `numpy.ndarray`, shape (n,) + Point at which to evaluate the gradient of the quadratic model of + the objective function. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Gradient of the quadratic model of the objective function at `x`. + """ + if self._debug: + assert x.shape == (self.n,), "The shape of `x` is not valid." + return self._fun.grad(x, self.interpolation) + + def fun_hess(self): + """ + Evaluate the Hessian matrix of the quadratic model of the objective + function. + + Returns + ------- + `numpy.ndarray`, shape (n, n) + Hessian matrix of the quadratic model of the objective function. + """ + return self._fun.hess(self.interpolation) + + def fun_hess_prod(self, v): + """ + Evaluate the right product of the Hessian matrix of the quadratic model + of the objective function with a given vector. + + Parameters + ---------- + v : `numpy.ndarray`, shape (n,) + Vector with which the Hessian matrix of the quadratic model of the + objective function is multiplied from the right. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Right product of the Hessian matrix of the quadratic model of the + objective function with `v`. + """ + if self._debug: + assert v.shape == (self.n,), "The shape of `v` is not valid." + return self._fun.hess_prod(v, self.interpolation) + + def fun_curv(self, v): + """ + Evaluate the curvature of the quadratic model of the objective function + along a given direction. + + Parameters + ---------- + v : `numpy.ndarray`, shape (n,) + Direction along which the curvature of the quadratic model of the + objective function is evaluated. + + Returns + ------- + float + Curvature of the quadratic model of the objective function along + `v`. + """ + if self._debug: + assert v.shape == (self.n,), "The shape of `v` is not valid." + return self._fun.curv(v, self.interpolation) + + def fun_alt_grad(self, x): + """ + Evaluate the gradient of the alternative quadratic model of the + objective function at a given point. + + Parameters + ---------- + x : `numpy.ndarray`, shape (n,) + Point at which to evaluate the gradient of the alternative + quadratic model of the objective function. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Gradient of the alternative quadratic model of the objective + function at `x`. + + Raises + ------ + `numpy.linalg.LinAlgError` + If the interpolation system is ill-defined. + """ + if self._debug: + assert x.shape == (self.n,), "The shape of `x` is not valid." + model = Quadratic(self.interpolation, self.fun_val, self._debug) + return model.grad(x, self.interpolation) + + def cub(self, x, mask=None): + """ + Evaluate the quadratic models of the nonlinear inequality functions at + a given point. + + Parameters + ---------- + x : `numpy.ndarray`, shape (n,) + Point at which to evaluate the quadratic models of the nonlinear + inequality functions. + mask : `numpy.ndarray`, shape (m_nonlinear_ub,), optional + Mask of the quadratic models to consider. + + Returns + ------- + `numpy.ndarray` + Values of the quadratic model of the nonlinear inequality + functions. + """ + if self._debug: + assert x.shape == (self.n,), "The shape of `x` is not valid." + assert mask is None or mask.shape == ( + self.m_nonlinear_ub, + ), "The shape of `mask` is not valid." + return np.array( + [model(x, self.interpolation) for model in self._get_cub(mask)] + ) + + def cub_grad(self, x, mask=None): + """ + Evaluate the gradients of the quadratic models of the nonlinear + inequality functions at a given point. + + Parameters + ---------- + x : `numpy.ndarray`, shape (n,) + Point at which to evaluate the gradients of the quadratic models of + the nonlinear inequality functions. + mask : `numpy.ndarray`, shape (m_nonlinear_eq,), optional + Mask of the quadratic models to consider. + + Returns + ------- + `numpy.ndarray` + Gradients of the quadratic model of the nonlinear inequality + functions. + """ + if self._debug: + assert x.shape == (self.n,), "The shape of `x` is not valid." + assert mask is None or mask.shape == ( + self.m_nonlinear_ub, + ), "The shape of `mask` is not valid." + return np.reshape( + [model.grad(x, self.interpolation) + for model in self._get_cub(mask)], + (-1, self.n), + ) + + def cub_hess(self, mask=None): + """ + Evaluate the Hessian matrices of the quadratic models of the nonlinear + inequality functions. + + Parameters + ---------- + mask : `numpy.ndarray`, shape (m_nonlinear_ub,), optional + Mask of the quadratic models to consider. + + Returns + ------- + `numpy.ndarray` + Hessian matrices of the quadratic models of the nonlinear + inequality functions. + """ + if self._debug: + assert mask is None or mask.shape == ( + self.m_nonlinear_ub, + ), "The shape of `mask` is not valid." + return np.reshape( + [model.hess(self.interpolation) for model in self._get_cub(mask)], + (-1, self.n, self.n), + ) + + def cub_hess_prod(self, v, mask=None): + """ + Evaluate the right product of the Hessian matrices of the quadratic + models of the nonlinear inequality functions with a given vector. + + Parameters + ---------- + v : `numpy.ndarray`, shape (n,) + Vector with which the Hessian matrices of the quadratic models of + the nonlinear inequality functions are multiplied from the right. + mask : `numpy.ndarray`, shape (m_nonlinear_ub,), optional + Mask of the quadratic models to consider. + + Returns + ------- + `numpy.ndarray` + Right products of the Hessian matrices of the quadratic models of + the nonlinear inequality functions with `v`. + """ + if self._debug: + assert v.shape == (self.n,), "The shape of `v` is not valid." + assert mask is None or mask.shape == ( + self.m_nonlinear_ub, + ), "The shape of `mask` is not valid." + return np.reshape( + [ + model.hess_prod(v, self.interpolation) + for model in self._get_cub(mask) + ], + (-1, self.n), + ) + + def cub_curv(self, v, mask=None): + """ + Evaluate the curvature of the quadratic models of the nonlinear + inequality functions along a given direction. + + Parameters + ---------- + v : `numpy.ndarray`, shape (n,) + Direction along which the curvature of the quadratic models of the + nonlinear inequality functions is evaluated. + mask : `numpy.ndarray`, shape (m_nonlinear_ub,), optional + Mask of the quadratic models to consider. + + Returns + ------- + `numpy.ndarray` + Curvature of the quadratic models of the nonlinear inequality + functions along `v`. + """ + if self._debug: + assert v.shape == (self.n,), "The shape of `v` is not valid." + assert mask is None or mask.shape == ( + self.m_nonlinear_ub, + ), "The shape of `mask` is not valid." + return np.array( + [model.curv(v, self.interpolation) + for model in self._get_cub(mask)] + ) + + def ceq(self, x, mask=None): + """ + Evaluate the quadratic models of the nonlinear equality functions at a + given point. + + Parameters + ---------- + x : `numpy.ndarray`, shape (n,) + Point at which to evaluate the quadratic models of the nonlinear + equality functions. + mask : `numpy.ndarray`, shape (m_nonlinear_eq,), optional + Mask of the quadratic models to consider. + + Returns + ------- + `numpy.ndarray` + Values of the quadratic model of the nonlinear equality functions. + """ + if self._debug: + assert x.shape == (self.n,), "The shape of `x` is not valid." + assert mask is None or mask.shape == ( + self.m_nonlinear_eq, + ), "The shape of `mask` is not valid." + return np.array( + [model(x, self.interpolation) for model in self._get_ceq(mask)] + ) + + def ceq_grad(self, x, mask=None): + """ + Evaluate the gradients of the quadratic models of the nonlinear + equality functions at a given point. + + Parameters + ---------- + x : `numpy.ndarray`, shape (n,) + Point at which to evaluate the gradients of the quadratic models of + the nonlinear equality functions. + mask : `numpy.ndarray`, shape (m_nonlinear_eq,), optional + Mask of the quadratic models to consider. + + Returns + ------- + `numpy.ndarray` + Gradients of the quadratic model of the nonlinear equality + functions. + """ + if self._debug: + assert x.shape == (self.n,), "The shape of `x` is not valid." + assert mask is None or mask.shape == ( + self.m_nonlinear_eq, + ), "The shape of `mask` is not valid." + return np.reshape( + [model.grad(x, self.interpolation) + for model in self._get_ceq(mask)], + (-1, self.n), + ) + + def ceq_hess(self, mask=None): + """ + Evaluate the Hessian matrices of the quadratic models of the nonlinear + equality functions. + + Parameters + ---------- + mask : `numpy.ndarray`, shape (m_nonlinear_eq,), optional + Mask of the quadratic models to consider. + + Returns + ------- + `numpy.ndarray` + Hessian matrices of the quadratic models of the nonlinear equality + functions. + """ + if self._debug: + assert mask is None or mask.shape == ( + self.m_nonlinear_eq, + ), "The shape of `mask` is not valid." + return np.reshape( + [model.hess(self.interpolation) for model in self._get_ceq(mask)], + (-1, self.n, self.n), + ) + + def ceq_hess_prod(self, v, mask=None): + """ + Evaluate the right product of the Hessian matrices of the quadratic + models of the nonlinear equality functions with a given vector. + + Parameters + ---------- + v : `numpy.ndarray`, shape (n,) + Vector with which the Hessian matrices of the quadratic models of + the nonlinear equality functions are multiplied from the right. + mask : `numpy.ndarray`, shape (m_nonlinear_eq,), optional + Mask of the quadratic models to consider. + + Returns + ------- + `numpy.ndarray` + Right products of the Hessian matrices of the quadratic models of + the nonlinear equality functions with `v`. + """ + if self._debug: + assert v.shape == (self.n,), "The shape of `v` is not valid." + assert mask is None or mask.shape == ( + self.m_nonlinear_eq, + ), "The shape of `mask` is not valid." + return np.reshape( + [ + model.hess_prod(v, self.interpolation) + for model in self._get_ceq(mask) + ], + (-1, self.n), + ) + + def ceq_curv(self, v, mask=None): + """ + Evaluate the curvature of the quadratic models of the nonlinear + equality functions along a given direction. + + Parameters + ---------- + v : `numpy.ndarray`, shape (n,) + Direction along which the curvature of the quadratic models of the + nonlinear equality functions is evaluated. + mask : `numpy.ndarray`, shape (m_nonlinear_eq,), optional + Mask of the quadratic models to consider. + + Returns + ------- + `numpy.ndarray` + Curvature of the quadratic models of the nonlinear equality + functions along `v`. + """ + if self._debug: + assert v.shape == (self.n,), "The shape of `v` is not valid." + assert mask is None or mask.shape == ( + self.m_nonlinear_eq, + ), "The shape of `mask` is not valid." + return np.array( + [model.curv(v, self.interpolation) + for model in self._get_ceq(mask)] + ) + + def reset_models(self): + """ + Set the quadratic models of the objective function, nonlinear + inequality constraints, and nonlinear equality constraints to the + alternative quadratic models. + + Raises + ------ + `numpy.linalg.LinAlgError` + If the interpolation system is ill-defined. + """ + self._fun = Quadratic(self.interpolation, self.fun_val, self._debug) + for i in range(self.m_nonlinear_ub): + self._cub[i] = Quadratic( + self.interpolation, + self.cub_val[:, i], + self._debug, + ) + for i in range(self.m_nonlinear_eq): + self._ceq[i] = Quadratic( + self.interpolation, + self.ceq_val[:, i], + self._debug, + ) + if self._debug: + self._check_interpolation_conditions() + + def update_interpolation(self, k_new, x_new, fun_val, cub_val, ceq_val): + """ + Update the interpolation set. + + This method updates the interpolation set by replacing the `knew`-th + interpolation point with `xnew`. It also updates the function values + and the quadratic models. + + Parameters + ---------- + k_new : int + Index of the updated interpolation point. + x_new : `numpy.ndarray`, shape (n,) + New interpolation point. Its value is interpreted as relative to + the origin, not the base point. + fun_val : float + Value of the objective function at `x_new`. + Objective function value at `x_new`. + cub_val : `numpy.ndarray`, shape (m_nonlinear_ub,) + Values of the nonlinear inequality constraints at `x_new`. + ceq_val : `numpy.ndarray`, shape (m_nonlinear_eq,) + Values of the nonlinear equality constraints at `x_new`. + + Raises + ------ + `numpy.linalg.LinAlgError` + If the interpolation system is ill-defined. + """ + if self._debug: + assert 0 <= k_new < self.npt, "The index `k_new` is not valid." + assert x_new.shape == (self.n,), \ + "The shape of `x_new` is not valid." + assert isinstance(fun_val, float), \ + "The function value is not valid." + assert cub_val.shape == ( + self.m_nonlinear_ub, + ), "The shape of `cub_val` is not valid." + assert ceq_val.shape == ( + self.m_nonlinear_eq, + ), "The shape of `ceq_val` is not valid." + + # Compute the updates in the interpolation conditions. + fun_diff = np.zeros(self.npt) + cub_diff = np.zeros(self.cub_val.shape) + ceq_diff = np.zeros(self.ceq_val.shape) + fun_diff[k_new] = fun_val - self.fun(x_new) + cub_diff[k_new, :] = cub_val - self.cub(x_new) + ceq_diff[k_new, :] = ceq_val - self.ceq(x_new) + + # Update the function values. + self.fun_val[k_new] = fun_val + self.cub_val[k_new, :] = cub_val + self.ceq_val[k_new, :] = ceq_val + + # Update the interpolation set. + dir_old = np.copy(self.interpolation.xpt[:, k_new]) + self.interpolation.xpt[:, k_new] = x_new - self.interpolation.x_base + + # Update the quadratic models. + ill_conditioned = self._fun.update( + self.interpolation, + k_new, + dir_old, + fun_diff, + ) + for i in range(self.m_nonlinear_ub): + ill_conditioned = ill_conditioned or self._cub[i].update( + self.interpolation, + k_new, + dir_old, + cub_diff[:, i], + ) + for i in range(self.m_nonlinear_eq): + ill_conditioned = ill_conditioned or self._ceq[i].update( + self.interpolation, + k_new, + dir_old, + ceq_diff[:, i], + ) + if self._debug: + self._check_interpolation_conditions() + return ill_conditioned + + def determinants(self, x_new, k_new=None): + """ + Compute the normalized determinants of the new interpolation systems. + + Parameters + ---------- + x_new : `numpy.ndarray`, shape (n,) + New interpolation point. Its value is interpreted as relative to + the origin, not the base point. + k_new : int, optional + Index of the updated interpolation point. If `k_new` is not + specified, all the possible determinants are computed. + + Returns + ------- + {float, `numpy.ndarray`, shape (npt,)} + Determinant(s) of the new interpolation system. + + Raises + ------ + `numpy.linalg.LinAlgError` + If the interpolation system is ill-defined. + + Notes + ----- + The determinants are normalized by the determinant of the current + interpolation system. For stability reasons, the calculations are done + using the formula (2.12) in [1]_. + + References + ---------- + .. [1] M. J. D. Powell. On updating the inverse of a KKT matrix. + Technical Report DAMTP 2004/NA01, Department of Applied Mathematics + and Theoretical Physics, University of Cambridge, Cambridge, UK, + 2004. + """ + if self._debug: + assert x_new.shape == (self.n,), \ + "The shape of `x_new` is not valid." + assert ( + k_new is None or 0 <= k_new < self.npt + ), "The index `k_new` is not valid." + + # Compute the values independent of k_new. + shift = x_new - self.interpolation.x_base + new_col = np.empty((self.npt + self.n + 1, 1)) + new_col[: self.npt, 0] = ( + 0.5 * (self.interpolation.xpt.T @ shift) ** 2.0) + new_col[self.npt, 0] = 1.0 + new_col[self.npt + 1:, 0] = shift + inv_new_col = Quadratic.solve_systems(self.interpolation, new_col)[0] + beta = 0.5 * (shift @ shift) ** 2.0 - new_col[:, 0] @ inv_new_col[:, 0] + + # Compute the values that depend on k. + if k_new is None: + coord_vec = np.eye(self.npt + self.n + 1, self.npt) + alpha = np.diag( + Quadratic.solve_systems( + self.interpolation, + coord_vec, + )[0] + ) + tau = inv_new_col[: self.npt, 0] + else: + coord_vec = np.eye(self.npt + self.n + 1, 1, -k_new) + alpha = Quadratic.solve_systems( + self.interpolation, + coord_vec, + )[ + 0 + ][k_new, 0] + tau = inv_new_col[k_new, 0] + return alpha * beta + tau**2.0 + + def shift_x_base(self, new_x_base, options): + """ + Shift the base point without changing the interpolation set. + + Parameters + ---------- + new_x_base : `numpy.ndarray`, shape (n,) + New base point. + options : dict + Options of the solver. + """ + if self._debug: + assert new_x_base.shape == ( + self.n, + ), "The shape of `new_x_base` is not valid." + + # Update the models. + self._fun.shift_x_base(self.interpolation, new_x_base) + for model in self._cub: + model.shift_x_base(self.interpolation, new_x_base) + for model in self._ceq: + model.shift_x_base(self.interpolation, new_x_base) + + # Update the base point and the interpolation points. + shift = new_x_base - self.interpolation.x_base + self.interpolation.x_base += shift + self.interpolation.xpt -= shift[:, np.newaxis] + if options[Options.DEBUG]: + self._check_interpolation_conditions() + + def _get_cub(self, mask=None): + """ + Get the quadratic models of the nonlinear inequality constraints. + + Parameters + ---------- + mask : `numpy.ndarray`, shape (m_nonlinear_ub,), optional + Mask of the quadratic models to return. + + Returns + ------- + `numpy.ndarray` + Quadratic models of the nonlinear inequality constraints. + """ + return self._cub if mask is None else self._cub[mask] + + def _get_ceq(self, mask=None): + """ + Get the quadratic models of the nonlinear equality constraints. + + Parameters + ---------- + mask : `numpy.ndarray`, shape (m_nonlinear_eq,), optional + Mask of the quadratic models to return. + + Returns + ------- + `numpy.ndarray` + Quadratic models of the nonlinear equality constraints. + """ + return self._ceq if mask is None else self._ceq[mask] + + def _check_interpolation_conditions(self): + """ + Check the interpolation conditions of all quadratic models. + """ + error_fun = 0.0 + error_cub = 0.0 + error_ceq = 0.0 + for k in range(self.npt): + error_fun = np.max( + [ + error_fun, + np.abs( + self.fun(self.interpolation.point(k)) - self.fun_val[k] + ), + ] + ) + error_cub = np.max( + np.abs( + self.cub(self.interpolation.point(k)) - self.cub_val[k, :] + ), + initial=error_cub, + ) + error_ceq = np.max( + np.abs( + self.ceq(self.interpolation.point(k)) - self.ceq_val[k, :] + ), + initial=error_ceq, + ) + tol = 10.0 * np.sqrt(EPS) * max(self.n, self.npt) + if error_fun > tol * np.max(np.abs(self.fun_val), initial=1.0): + warnings.warn( + "The interpolation conditions for the objective function are " + "not satisfied.", + RuntimeWarning, + 2, + ) + if error_cub > tol * np.max(np.abs(self.cub_val), initial=1.0): + warnings.warn( + "The interpolation conditions for the inequality constraint " + "function are not satisfied.", + RuntimeWarning, + 2, + ) + if error_ceq > tol * np.max(np.abs(self.ceq_val), initial=1.0): + warnings.warn( + "The interpolation conditions for the equality constraint " + "function are not satisfied.", + RuntimeWarning, + 2, + ) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/problem.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/problem.py new file mode 100644 index 0000000000000000000000000000000000000000..2dbebce3a48067e97da2b75bd2cdd609e01029b2 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/problem.py @@ -0,0 +1,1296 @@ +from contextlib import suppress +from inspect import signature +import copy + +import numpy as np +from scipy.optimize import ( + Bounds, + LinearConstraint, + NonlinearConstraint, + OptimizeResult, +) +from scipy.optimize._constraints import PreparedConstraint + + +from .settings import PRINT_OPTIONS, BARRIER +from .utils import CallbackSuccess, get_arrays_tol +from .utils import exact_1d_array + + +class ObjectiveFunction: + """ + Real-valued objective function. + """ + + def __init__(self, fun, verbose, debug, *args): + """ + Initialize the objective function. + + Parameters + ---------- + fun : {callable, None} + Function to evaluate, or None. + + ``fun(x, *args) -> float`` + + where ``x`` is an array with shape (n,) and `args` is a tuple. + verbose : bool + Whether to print the function evaluations. + debug : bool + Whether to make debugging tests during the execution. + *args : tuple + Additional arguments to be passed to the function. + """ + if debug: + assert fun is None or callable(fun) + assert isinstance(verbose, bool) + assert isinstance(debug, bool) + + self._fun = fun + self._verbose = verbose + self._args = args + self._n_eval = 0 + + def __call__(self, x): + """ + Evaluate the objective function. + + Parameters + ---------- + x : array_like, shape (n,) + Point at which the objective function is evaluated. + + Returns + ------- + float + Function value at `x`. + """ + x = np.array(x, dtype=float) + if self._fun is None: + f = 0.0 + else: + f = float(np.squeeze(self._fun(x, *self._args))) + self._n_eval += 1 + if self._verbose: + with np.printoptions(**PRINT_OPTIONS): + print(f"{self.name}({x}) = {f}") + return f + + @property + def n_eval(self): + """ + Number of function evaluations. + + Returns + ------- + int + Number of function evaluations. + """ + return self._n_eval + + @property + def name(self): + """ + Name of the objective function. + + Returns + ------- + str + Name of the objective function. + """ + name = "" + if self._fun is not None: + try: + name = self._fun.__name__ + except AttributeError: + name = "fun" + return name + + +class BoundConstraints: + """ + Bound constraints ``xl <= x <= xu``. + """ + + def __init__(self, bounds): + """ + Initialize the bound constraints. + + Parameters + ---------- + bounds : scipy.optimize.Bounds + Bound constraints. + """ + self._xl = np.array(bounds.lb, float) + self._xu = np.array(bounds.ub, float) + + # Remove the ill-defined bounds. + self.xl[np.isnan(self.xl)] = -np.inf + self.xu[np.isnan(self.xu)] = np.inf + + self.is_feasible = ( + np.all(self.xl <= self.xu) + and np.all(self.xl < np.inf) + and np.all(self.xu > -np.inf) + ) + self.m = np.count_nonzero(self.xl > -np.inf) + np.count_nonzero( + self.xu < np.inf + ) + self.pcs = PreparedConstraint(bounds, np.ones(bounds.lb.size)) + + @property + def xl(self): + """ + Lower bound. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Lower bound. + """ + return self._xl + + @property + def xu(self): + """ + Upper bound. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Upper bound. + """ + return self._xu + + def maxcv(self, x): + """ + Evaluate the maximum constraint violation. + + Parameters + ---------- + x : array_like, shape (n,) + Point at which the maximum constraint violation is evaluated. + + Returns + ------- + float + Maximum constraint violation at `x`. + """ + x = np.asarray(x, dtype=float) + return self.violation(x) + + def violation(self, x): + # shortcut for no bounds + if self.is_feasible: + return np.array([0]) + else: + return self.pcs.violation(x) + + def project(self, x): + """ + Project a point onto the feasible set. + + Parameters + ---------- + x : array_like, shape (n,) + Point to be projected. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Projection of `x` onto the feasible set. + """ + return np.clip(x, self.xl, self.xu) if self.is_feasible else x + + +class LinearConstraints: + """ + Linear constraints ``a_ub @ x <= b_ub`` and ``a_eq @ x == b_eq``. + """ + + def __init__(self, constraints, n, debug): + """ + Initialize the linear constraints. + + Parameters + ---------- + constraints : list of LinearConstraint + Linear constraints. + n : int + Number of variables. + debug : bool + Whether to make debugging tests during the execution. + """ + if debug: + assert isinstance(constraints, list) + for constraint in constraints: + assert isinstance(constraint, LinearConstraint) + assert isinstance(debug, bool) + + self._a_ub = np.empty((0, n)) + self._b_ub = np.empty(0) + self._a_eq = np.empty((0, n)) + self._b_eq = np.empty(0) + for constraint in constraints: + is_equality = np.abs( + constraint.ub - constraint.lb + ) <= get_arrays_tol(constraint.lb, constraint.ub) + if np.any(is_equality): + self._a_eq = np.vstack((self.a_eq, constraint.A[is_equality])) + self._b_eq = np.concatenate( + ( + self.b_eq, + 0.5 + * ( + constraint.lb[is_equality] + + constraint.ub[is_equality] + ), + ) + ) + if not np.all(is_equality): + self._a_ub = np.vstack( + ( + self.a_ub, + constraint.A[~is_equality], + -constraint.A[~is_equality], + ) + ) + self._b_ub = np.concatenate( + ( + self.b_ub, + constraint.ub[~is_equality], + -constraint.lb[~is_equality], + ) + ) + + # Remove the ill-defined constraints. + self.a_ub[np.isnan(self.a_ub)] = 0.0 + self.a_eq[np.isnan(self.a_eq)] = 0.0 + undef_ub = np.isnan(self.b_ub) | np.isinf(self.b_ub) + undef_eq = np.isnan(self.b_eq) + self._a_ub = self.a_ub[~undef_ub, :] + self._b_ub = self.b_ub[~undef_ub] + self._a_eq = self.a_eq[~undef_eq, :] + self._b_eq = self.b_eq[~undef_eq] + self.pcs = [ + PreparedConstraint(c, np.ones(n)) for c in constraints if c.A.size + ] + + @property + def a_ub(self): + """ + Left-hand side matrix of the linear inequality constraints. + + Returns + ------- + `numpy.ndarray`, shape (m, n) + Left-hand side matrix of the linear inequality constraints. + """ + return self._a_ub + + @property + def b_ub(self): + """ + Right-hand side vector of the linear inequality constraints. + + Returns + ------- + `numpy.ndarray`, shape (m, n) + Right-hand side vector of the linear inequality constraints. + """ + return self._b_ub + + @property + def a_eq(self): + """ + Left-hand side matrix of the linear equality constraints. + + Returns + ------- + `numpy.ndarray`, shape (m, n) + Left-hand side matrix of the linear equality constraints. + """ + return self._a_eq + + @property + def b_eq(self): + """ + Right-hand side vector of the linear equality constraints. + + Returns + ------- + `numpy.ndarray`, shape (m, n) + Right-hand side vector of the linear equality constraints. + """ + return self._b_eq + + @property + def m_ub(self): + """ + Number of linear inequality constraints. + + Returns + ------- + int + Number of linear inequality constraints. + """ + return self.b_ub.size + + @property + def m_eq(self): + """ + Number of linear equality constraints. + + Returns + ------- + int + Number of linear equality constraints. + """ + return self.b_eq.size + + def maxcv(self, x): + """ + Evaluate the maximum constraint violation. + + Parameters + ---------- + x : array_like, shape (n,) + Point at which the maximum constraint violation is evaluated. + + Returns + ------- + float + Maximum constraint violation at `x`. + """ + return np.max(self.violation(x), initial=0.0) + + def violation(self, x): + if len(self.pcs): + return np.concatenate([pc.violation(x) for pc in self.pcs]) + return np.array([]) + + +class NonlinearConstraints: + """ + Nonlinear constraints ``c_ub(x) <= 0`` and ``c_eq(x) == b_eq``. + """ + + def __init__(self, constraints, verbose, debug): + """ + Initialize the nonlinear constraints. + + Parameters + ---------- + constraints : list + Nonlinear constraints. + verbose : bool + Whether to print the function evaluations. + debug : bool + Whether to make debugging tests during the execution. + """ + if debug: + assert isinstance(constraints, list) + for constraint in constraints: + assert isinstance(constraint, NonlinearConstraint) + assert isinstance(verbose, bool) + assert isinstance(debug, bool) + + self._constraints = constraints + self.pcs = [] + self._verbose = verbose + + # map of indexes for equality and inequality constraints + self._map_ub = None + self._map_eq = None + self._m_ub = self._m_eq = None + + def __call__(self, x): + """ + Calculates the residual (slack) for the constraints. + + Parameters + ---------- + x : array_like, shape (n,) + Point at which the constraints are evaluated. + + Returns + ------- + `numpy.ndarray`, shape (m_nonlinear_ub,) + Nonlinear inequality constraint slack values. + `numpy.ndarray`, shape (m_nonlinear_eq,) + Nonlinear equality constraint slack values. + """ + if not len(self._constraints): + self._m_eq = self._m_ub = 0 + return np.array([]), np.array([]) + + x = np.array(x, dtype=float) + # first time around the constraints haven't been prepared + if not len(self.pcs): + self._map_ub = [] + self._map_eq = [] + self._m_eq = 0 + self._m_ub = 0 + + for constraint in self._constraints: + if not callable(constraint.jac): + # having a callable constraint function prevents + # constraint.fun from being evaluated when preparing + # constraint + c = copy.copy(constraint) + c.jac = lambda x0: x0 + c.hess = lambda x0, v: 0.0 + pc = PreparedConstraint(c, x) + else: + pc = PreparedConstraint(constraint, x) + # we're going to be using the same x value again immediately + # after this initialisation + pc.fun.f_updated = True + + self.pcs.append(pc) + idx = np.arange(pc.fun.m) + + # figure out equality and inequality maps + lb, ub = pc.bounds[0], pc.bounds[1] + arr_tol = get_arrays_tol(lb, ub) + is_equality = np.abs(ub - lb) <= arr_tol + self._map_eq.append(idx[is_equality]) + self._map_ub.append(idx[~is_equality]) + + # these values will be corrected to their proper values later + self._m_eq += np.count_nonzero(is_equality) + self._m_ub += np.count_nonzero(~is_equality) + + c_ub = [] + c_eq = [] + for i, pc in enumerate(self.pcs): + val = pc.fun.fun(x) + if self._verbose: + with np.printoptions(**PRINT_OPTIONS): + with suppress(AttributeError): + fun_name = self._constraints[i].fun.__name__ + print(f"{fun_name}({x}) = {val}") + + # separate violations into c_eq and c_ub + eq_idx = self._map_eq[i] + ub_idx = self._map_ub[i] + + ub_val = val[ub_idx] + if len(ub_idx): + xl = pc.bounds[0][ub_idx] + xu = pc.bounds[1][ub_idx] + + # calculate slack within lower bound + finite_xl = xl > -np.inf + _v = xl[finite_xl] - ub_val[finite_xl] + c_ub.append(_v) + + # calculate slack within lower bound + finite_xu = xu < np.inf + _v = ub_val[finite_xu] - xu[finite_xu] + c_ub.append(_v) + + # equality constraints taken from midpoint between lb and ub + eq_val = val[eq_idx] + if len(eq_idx): + midpoint = 0.5 * (pc.bounds[1][eq_idx] + pc.bounds[0][eq_idx]) + eq_val -= midpoint + c_eq.append(eq_val) + + if self._m_eq: + c_eq = np.concatenate(c_eq) + else: + c_eq = np.array([]) + + if self._m_ub: + c_ub = np.concatenate(c_ub) + else: + c_ub = np.array([]) + + self._m_ub = c_ub.size + self._m_eq = c_eq.size + + return c_ub, c_eq + + @property + def m_ub(self): + """ + Number of nonlinear inequality constraints. + + Returns + ------- + int + Number of nonlinear inequality constraints. + + Raises + ------ + ValueError + If the number of nonlinear inequality constraints is unknown. + """ + if self._m_ub is None: + raise ValueError( + "The number of nonlinear inequality constraints is unknown." + ) + else: + return self._m_ub + + @property + def m_eq(self): + """ + Number of nonlinear equality constraints. + + Returns + ------- + int + Number of nonlinear equality constraints. + + Raises + ------ + ValueError + If the number of nonlinear equality constraints is unknown. + """ + if self._m_eq is None: + raise ValueError( + "The number of nonlinear equality constraints is unknown." + ) + else: + return self._m_eq + + @property + def n_eval(self): + """ + Number of function evaluations. + + Returns + ------- + int + Number of function evaluations. + """ + if len(self.pcs): + return self.pcs[0].fun.nfev + else: + return 0 + + def maxcv(self, x, cub_val=None, ceq_val=None): + """ + Evaluate the maximum constraint violation. + + Parameters + ---------- + x : array_like, shape (n,) + Point at which the maximum constraint violation is evaluated. + cub_val : array_like, shape (m_nonlinear_ub,), optional + Values of the nonlinear inequality constraints. If not provided, + the nonlinear inequality constraints are evaluated at `x`. + ceq_val : array_like, shape (m_nonlinear_eq,), optional + Values of the nonlinear equality constraints. If not provided, + the nonlinear equality constraints are evaluated at `x`. + + Returns + ------- + float + Maximum constraint violation at `x`. + """ + return np.max( + self.violation(x, cub_val=cub_val, ceq_val=ceq_val), initial=0.0 + ) + + def violation(self, x, cub_val=None, ceq_val=None): + return np.concatenate([pc.violation(x) for pc in self.pcs]) + + +class Problem: + """ + Optimization problem. + """ + + def __init__( + self, + obj, + x0, + bounds, + linear, + nonlinear, + callback, + feasibility_tol, + scale, + store_history, + history_size, + filter_size, + debug, + ): + """ + Initialize the nonlinear problem. + + The problem is preprocessed to remove all the variables that are fixed + by the bound constraints. + + Parameters + ---------- + obj : ObjectiveFunction + Objective function. + x0 : array_like, shape (n,) + Initial guess. + bounds : BoundConstraints + Bound constraints. + linear : LinearConstraints + Linear constraints. + nonlinear : NonlinearConstraints + Nonlinear constraints. + callback : {callable, None} + Callback function. + feasibility_tol : float + Tolerance on the constraint violation. + scale : bool + Whether to scale the problem according to the bounds. + store_history : bool + Whether to store the function evaluations. + history_size : int + Maximum number of function evaluations to store. + filter_size : int + Maximum number of points in the filter. + debug : bool + Whether to make debugging tests during the execution. + """ + if debug: + assert isinstance(obj, ObjectiveFunction) + assert isinstance(bounds, BoundConstraints) + assert isinstance(linear, LinearConstraints) + assert isinstance(nonlinear, NonlinearConstraints) + assert isinstance(feasibility_tol, float) + assert isinstance(scale, bool) + assert isinstance(store_history, bool) + assert isinstance(history_size, int) + if store_history: + assert history_size > 0 + assert isinstance(filter_size, int) + assert filter_size > 0 + assert isinstance(debug, bool) + + self._obj = obj + self._linear = linear + self._nonlinear = nonlinear + if callback is not None: + if not callable(callback): + raise TypeError("The callback must be a callable function.") + self._callback = callback + + # Check the consistency of the problem. + x0 = exact_1d_array(x0, "The initial guess must be a vector.") + n = x0.size + if bounds.xl.size != n: + raise ValueError(f"The bounds must have {n} elements.") + if linear.a_ub.shape[1] != n: + raise ValueError( + f"The left-hand side matrices of the linear constraints must " + f"have {n} columns." + ) + + # Check which variables are fixed. + tol = get_arrays_tol(bounds.xl, bounds.xu) + self._fixed_idx = (bounds.xl <= bounds.xu) & ( + np.abs(bounds.xl - bounds.xu) < tol + ) + self._fixed_val = 0.5 * ( + bounds.xl[self._fixed_idx] + bounds.xu[self._fixed_idx] + ) + self._fixed_val = np.clip( + self._fixed_val, + bounds.xl[self._fixed_idx], + bounds.xu[self._fixed_idx], + ) + + # Set the bound constraints. + self._orig_bounds = bounds + self._bounds = BoundConstraints( + Bounds(bounds.xl[~self._fixed_idx], bounds.xu[~self._fixed_idx]) + ) + + # Set the initial guess. + self._x0 = self._bounds.project(x0[~self._fixed_idx]) + + # Set the linear constraints. + b_eq = linear.b_eq - linear.a_eq[:, self._fixed_idx] @ self._fixed_val + self._linear = LinearConstraints( + [ + LinearConstraint( + linear.a_ub[:, ~self._fixed_idx], + -np.inf, + linear.b_ub + - linear.a_ub[:, self._fixed_idx] @ self._fixed_val, + ), + LinearConstraint(linear.a_eq[:, ~self._fixed_idx], b_eq, b_eq), + ], + self.n, + debug, + ) + + # Scale the problem if necessary. + scale = ( + scale + and self._bounds.is_feasible + and np.all(np.isfinite(self._bounds.xl)) + and np.all(np.isfinite(self._bounds.xu)) + ) + if scale: + self._scaling_factor = 0.5 * (self._bounds.xu - self._bounds.xl) + self._scaling_shift = 0.5 * (self._bounds.xu + self._bounds.xl) + self._bounds = BoundConstraints( + Bounds(-np.ones(self.n), np.ones(self.n)) + ) + b_eq = self._linear.b_eq - self._linear.a_eq @ self._scaling_shift + self._linear = LinearConstraints( + [ + LinearConstraint( + self._linear.a_ub @ np.diag(self._scaling_factor), + -np.inf, + self._linear.b_ub + - self._linear.a_ub @ self._scaling_shift, + ), + LinearConstraint( + self._linear.a_eq @ np.diag(self._scaling_factor), + b_eq, + b_eq, + ), + ], + self.n, + debug, + ) + self._x0 = (self._x0 - self._scaling_shift) / self._scaling_factor + else: + self._scaling_factor = np.ones(self.n) + self._scaling_shift = np.zeros(self.n) + + # Set the initial filter. + self._feasibility_tol = feasibility_tol + self._filter_size = filter_size + self._fun_filter = [] + self._maxcv_filter = [] + self._x_filter = [] + + # Set the initial history. + self._store_history = store_history + self._history_size = history_size + self._fun_history = [] + self._maxcv_history = [] + self._x_history = [] + + def __call__(self, x, penalty=0.0): + """ + Evaluate the objective and nonlinear constraint functions. + + Parameters + ---------- + x : array_like, shape (n,) + Point at which the functions are evaluated. + penalty : float, optional + Penalty parameter used to select the point in the filter to forward + to the callback function. + + Returns + ------- + float + Objective function value. + `numpy.ndarray`, shape (m_nonlinear_ub,) + Nonlinear inequality constraint function values. + `numpy.ndarray`, shape (m_nonlinear_eq,) + Nonlinear equality constraint function values. + + Raises + ------ + `cobyqa.utils.CallbackSuccess` + If the callback function raises a ``StopIteration``. + """ + # Evaluate the objective and nonlinear constraint functions. + x = np.asarray(x, dtype=float) + x_full = self.build_x(x) + fun_val = self._obj(x_full) + cub_val, ceq_val = self._nonlinear(x_full) + maxcv_val = self.maxcv(x, cub_val, ceq_val) + if self._store_history: + self._fun_history.append(fun_val) + self._maxcv_history.append(maxcv_val) + self._x_history.append(x) + if len(self._fun_history) > self._history_size: + self._fun_history.pop(0) + self._maxcv_history.pop(0) + self._x_history.pop(0) + + # Add the point to the filter if it is not dominated by any point. + if np.isnan(fun_val) and np.isnan(maxcv_val): + include_point = len(self._fun_filter) == 0 + elif np.isnan(fun_val): + include_point = all( + np.isnan(fun_filter) + and maxcv_val < maxcv_filter + or np.isnan(maxcv_filter) + for fun_filter, maxcv_filter in zip( + self._fun_filter, + self._maxcv_filter, + ) + ) + elif np.isnan(maxcv_val): + include_point = all( + np.isnan(maxcv_filter) + and fun_val < fun_filter + or np.isnan(fun_filter) + for fun_filter, maxcv_filter in zip( + self._fun_filter, + self._maxcv_filter, + ) + ) + else: + include_point = all( + fun_val < fun_filter or maxcv_val < maxcv_filter + for fun_filter, maxcv_filter in zip( + self._fun_filter, + self._maxcv_filter, + ) + ) + if include_point: + self._fun_filter.append(fun_val) + self._maxcv_filter.append(maxcv_val) + self._x_filter.append(x) + + # Remove the points in the filter that are dominated by the new + # point. We must iterate in reverse order to avoid problems when + # removing elements from the list. + for k in range(len(self._fun_filter) - 2, -1, -1): + if np.isnan(fun_val): + remove_point = np.isnan(self._fun_filter[k]) + elif np.isnan(maxcv_val): + remove_point = np.isnan(self._maxcv_filter[k]) + else: + remove_point = ( + np.isnan(self._fun_filter[k]) + or np.isnan(self._maxcv_filter[k]) + or fun_val <= self._fun_filter[k] + and maxcv_val <= self._maxcv_filter[k] + ) + if remove_point: + self._fun_filter.pop(k) + self._maxcv_filter.pop(k) + self._x_filter.pop(k) + + # Keep only the most recent points in the filter. + if len(self._fun_filter) > self._filter_size: + self._fun_filter.pop(0) + self._maxcv_filter.pop(0) + self._x_filter.pop(0) + + # Evaluate the callback function after updating the filter to ensure + # that the current point can be returned by the method. + if self._callback is not None: + sig = signature(self._callback) + try: + x_best, fun_best, _ = self.best_eval(penalty) + x_best = self.build_x(x_best) + if set(sig.parameters) == {"intermediate_result"}: + intermediate_result = OptimizeResult( + x=x_best, + fun=fun_best, + # maxcv=maxcv_best, + ) + self._callback(intermediate_result=intermediate_result) + else: + self._callback(x_best) + except StopIteration as exc: + raise CallbackSuccess from exc + + # Apply the extreme barriers and return. + if np.isnan(fun_val): + fun_val = BARRIER + cub_val[np.isnan(cub_val)] = BARRIER + ceq_val[np.isnan(ceq_val)] = BARRIER + fun_val = max(min(fun_val, BARRIER), -BARRIER) + cub_val = np.maximum(np.minimum(cub_val, BARRIER), -BARRIER) + ceq_val = np.maximum(np.minimum(ceq_val, BARRIER), -BARRIER) + return fun_val, cub_val, ceq_val + + @property + def n(self): + """ + Number of variables. + + Returns + ------- + int + Number of variables. + """ + return self.x0.size + + @property + def n_orig(self): + """ + Number of variables in the original problem (with fixed variables). + + Returns + ------- + int + Number of variables in the original problem (with fixed variables). + """ + return self._fixed_idx.size + + @property + def x0(self): + """ + Initial guess. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Initial guess. + """ + return self._x0 + + @property + def n_eval(self): + """ + Number of function evaluations. + + Returns + ------- + int + Number of function evaluations. + """ + return self._obj.n_eval + + @property + def fun_name(self): + """ + Name of the objective function. + + Returns + ------- + str + Name of the objective function. + """ + return self._obj.name + + @property + def bounds(self): + """ + Bound constraints. + + Returns + ------- + BoundConstraints + Bound constraints. + """ + return self._bounds + + @property + def linear(self): + """ + Linear constraints. + + Returns + ------- + LinearConstraints + Linear constraints. + """ + return self._linear + + @property + def m_bounds(self): + """ + Number of bound constraints. + + Returns + ------- + int + Number of bound constraints. + """ + return self.bounds.m + + @property + def m_linear_ub(self): + """ + Number of linear inequality constraints. + + Returns + ------- + int + Number of linear inequality constraints. + """ + return self.linear.m_ub + + @property + def m_linear_eq(self): + """ + Number of linear equality constraints. + + Returns + ------- + int + Number of linear equality constraints. + """ + return self.linear.m_eq + + @property + def m_nonlinear_ub(self): + """ + Number of nonlinear inequality constraints. + + Returns + ------- + int + Number of nonlinear inequality constraints. + + Raises + ------ + ValueError + If the number of nonlinear inequality constraints is not known. + """ + return self._nonlinear.m_ub + + @property + def m_nonlinear_eq(self): + """ + Number of nonlinear equality constraints. + + Returns + ------- + int + Number of nonlinear equality constraints. + + Raises + ------ + ValueError + If the number of nonlinear equality constraints is not known. + """ + return self._nonlinear.m_eq + + @property + def fun_history(self): + """ + History of objective function evaluations. + + Returns + ------- + `numpy.ndarray`, shape (n_eval,) + History of objective function evaluations. + """ + return np.array(self._fun_history, dtype=float) + + @property + def maxcv_history(self): + """ + History of maximum constraint violations. + + Returns + ------- + `numpy.ndarray`, shape (n_eval,) + History of maximum constraint violations. + """ + return np.array(self._maxcv_history, dtype=float) + + @property + def type(self): + """ + Type of the problem. + + The problem can be either 'unconstrained', 'bound-constrained', + 'linearly constrained', or 'nonlinearly constrained'. + + Returns + ------- + str + Type of the problem. + """ + try: + if self.m_nonlinear_ub > 0 or self.m_nonlinear_eq > 0: + return "nonlinearly constrained" + elif self.m_linear_ub > 0 or self.m_linear_eq > 0: + return "linearly constrained" + elif self.m_bounds > 0: + return "bound-constrained" + else: + return "unconstrained" + except ValueError: + # The number of nonlinear constraints is not known. It may be zero + # if the user provided a nonlinear inequality and/or equality + # constraint function that returns an empty array. However, as this + # is not known before the first call to the function, we assume + # that the problem is nonlinearly constrained. + return "nonlinearly constrained" + + @property + def is_feasibility(self): + """ + Whether the problem is a feasibility problem. + + Returns + ------- + bool + Whether the problem is a feasibility problem. + """ + return self.fun_name == "" + + def build_x(self, x): + """ + Build the full vector of variables from the reduced vector. + + Parameters + ---------- + x : array_like, shape (n,) + Reduced vector of variables. + + Returns + ------- + `numpy.ndarray`, shape (n_orig,) + Full vector of variables. + """ + x_full = np.empty(self.n_orig) + x_full[self._fixed_idx] = self._fixed_val + x_full[~self._fixed_idx] = (x * self._scaling_factor + + self._scaling_shift) + return self._orig_bounds.project(x_full) + + def maxcv(self, x, cub_val=None, ceq_val=None): + """ + Evaluate the maximum constraint violation. + + Parameters + ---------- + x : array_like, shape (n,) + Point at which the maximum constraint violation is evaluated. + cub_val : array_like, shape (m_nonlinear_ub,), optional + Values of the nonlinear inequality constraints. If not provided, + the nonlinear inequality constraints are evaluated at `x`. + ceq_val : array_like, shape (m_nonlinear_eq,), optional + Values of the nonlinear equality constraints. If not provided, + the nonlinear equality constraints are evaluated at `x`. + + Returns + ------- + float + Maximum constraint violation at `x`. + """ + violation = self.violation(x, cub_val=cub_val, ceq_val=ceq_val) + if np.count_nonzero(violation): + return np.max(violation, initial=0.0) + else: + return 0.0 + + def violation(self, x, cub_val=None, ceq_val=None): + violation = [] + if not self.bounds.is_feasible: + b = self.bounds.violation(x) + violation.append(b) + + if len(self.linear.pcs): + lc = self.linear.violation(x) + violation.append(lc) + if len(self._nonlinear.pcs): + nlc = self._nonlinear.violation(x, cub_val, ceq_val) + violation.append(nlc) + + if len(violation): + return np.concatenate(violation) + + def best_eval(self, penalty): + """ + Return the best point in the filter and the corresponding objective and + nonlinear constraint function evaluations. + + Parameters + ---------- + penalty : float + Penalty parameter + + Returns + ------- + `numpy.ndarray`, shape (n,) + Best point. + float + Corresponding objective function value. + float + Corresponding maximum constraint violation. + """ + # If the filter is empty, i.e., if no function evaluation has been + # performed, we evaluate the objective and nonlinear constraint + # functions at the initial guess. + if len(self._fun_filter) == 0: + self(self.x0) + + # Find the best point in the filter. + fun_filter = np.array(self._fun_filter) + maxcv_filter = np.array(self._maxcv_filter) + x_filter = np.array(self._x_filter) + finite_idx = np.isfinite(maxcv_filter) + if np.any(finite_idx): + # At least one point has a finite maximum constraint violation. + feasible_idx = maxcv_filter <= self._feasibility_tol + if np.any(feasible_idx) and not np.all( + np.isnan(fun_filter[feasible_idx]) + ): + # At least one point is feasible and has a well-defined + # objective function value. We select the point with the least + # objective function value. If there is a tie, we select the + # point with the least maximum constraint violation. If there + # is still a tie, we select the most recent point. + fun_min_idx = feasible_idx & ( + fun_filter <= np.nanmin(fun_filter[feasible_idx]) + ) + if np.count_nonzero(fun_min_idx) > 1: + fun_min_idx &= maxcv_filter <= np.min( + maxcv_filter[fun_min_idx] + ) + i = np.flatnonzero(fun_min_idx)[-1] + elif np.any(feasible_idx): + # At least one point is feasible but no feasible point has a + # well-defined objective function value. We select the most + # recent feasible point. + i = np.flatnonzero(feasible_idx)[-1] + else: + # No point is feasible. We first compute the merit function + # value for each point. + merit_filter = np.full_like(fun_filter, np.nan) + merit_filter[finite_idx] = ( + fun_filter[finite_idx] + penalty * maxcv_filter[finite_idx] + ) + if np.all(np.isnan(merit_filter)): + # No point has a well-defined merit function value. In + # other words, among the points with a well-defined maximum + # constraint violation, none has a well-defined objective + # function value. We select the point with the least + # maximum constraint violation. If there is a tie, we + # select the most recent point. + min_maxcv_idx = maxcv_filter <= np.nanmin(maxcv_filter) + i = np.flatnonzero(min_maxcv_idx)[-1] + else: + # At least one point has a well-defined merit function + # value. We select the point with the least merit function + # value. If there is a tie, we select the point with the + # least maximum constraint violation. If there is still a + # tie, we select the point with the least objective + # function value. If there is still a tie, we select the + # most recent point. + merit_min_idx = merit_filter <= np.nanmin(merit_filter) + if np.count_nonzero(merit_min_idx) > 1: + merit_min_idx &= maxcv_filter <= np.min( + maxcv_filter[merit_min_idx] + ) + + if np.count_nonzero(merit_min_idx) > 1: + merit_min_idx &= fun_filter <= np.min( + fun_filter[merit_min_idx] + ) + i = np.flatnonzero(merit_min_idx)[-1] + elif not np.all(np.isnan(fun_filter)): + # No maximum constraint violation is well-defined but at least one + # point has a well-defined objective function value. We select the + # point with the least objective function value. If there is a tie, + # we select the most recent point. + fun_min_idx = fun_filter <= np.nanmin(fun_filter) + i = np.flatnonzero(fun_min_idx)[-1] + else: + # No point has a well-defined maximum constraint violation or + # objective function value. We select the most recent point. + i = len(fun_filter) - 1 + return ( + self.bounds.project(x_filter[i, :]), + fun_filter[i], + maxcv_filter[i], + ) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/settings.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/settings.py new file mode 100644 index 0000000000000000000000000000000000000000..6394822826e094a803a485556a298e342bf260ac --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/settings.py @@ -0,0 +1,132 @@ +import sys +from enum import Enum + +import numpy as np + + +# Exit status. +class ExitStatus(Enum): + """ + Exit statuses. + """ + + RADIUS_SUCCESS = 0 + TARGET_SUCCESS = 1 + FIXED_SUCCESS = 2 + CALLBACK_SUCCESS = 3 + FEASIBLE_SUCCESS = 4 + MAX_EVAL_WARNING = 5 + MAX_ITER_WARNING = 6 + INFEASIBLE_ERROR = -1 + LINALG_ERROR = -2 + + +class Options(str, Enum): + """ + Options. + """ + + DEBUG = "debug" + FEASIBILITY_TOL = "feasibility_tol" + FILTER_SIZE = "filter_size" + HISTORY_SIZE = "history_size" + MAX_EVAL = "maxfev" + MAX_ITER = "maxiter" + NPT = "nb_points" + RHOBEG = "radius_init" + RHOEND = "radius_final" + SCALE = "scale" + STORE_HISTORY = "store_history" + TARGET = "target" + VERBOSE = "disp" + + +class Constants(str, Enum): + """ + Constants. + """ + + DECREASE_RADIUS_FACTOR = "decrease_radius_factor" + INCREASE_RADIUS_FACTOR = "increase_radius_factor" + INCREASE_RADIUS_THRESHOLD = "increase_radius_threshold" + DECREASE_RADIUS_THRESHOLD = "decrease_radius_threshold" + DECREASE_RESOLUTION_FACTOR = "decrease_resolution_factor" + LARGE_RESOLUTION_THRESHOLD = "large_resolution_threshold" + MODERATE_RESOLUTION_THRESHOLD = "moderate_resolution_threshold" + LOW_RATIO = "low_ratio" + HIGH_RATIO = "high_ratio" + VERY_LOW_RATIO = "very_low_ratio" + PENALTY_INCREASE_THRESHOLD = "penalty_increase_threshold" + PENALTY_INCREASE_FACTOR = "penalty_increase_factor" + SHORT_STEP_THRESHOLD = "short_step_threshold" + LOW_RADIUS_FACTOR = "low_radius_factor" + BYRD_OMOJOKUN_FACTOR = "byrd_omojokun_factor" + THRESHOLD_RATIO_CONSTRAINTS = "threshold_ratio_constraints" + LARGE_SHIFT_FACTOR = "large_shift_factor" + LARGE_GRADIENT_FACTOR = "large_gradient_factor" + RESOLUTION_FACTOR = "resolution_factor" + IMPROVE_TCG = "improve_tcg" + + +# Default options. +DEFAULT_OPTIONS = { + Options.DEBUG.value: False, + Options.FEASIBILITY_TOL.value: np.sqrt(np.finfo(float).eps), + Options.FILTER_SIZE.value: sys.maxsize, + Options.HISTORY_SIZE.value: sys.maxsize, + Options.MAX_EVAL.value: lambda n: 500 * n, + Options.MAX_ITER.value: lambda n: 1000 * n, + Options.NPT.value: lambda n: 2 * n + 1, + Options.RHOBEG.value: 1.0, + Options.RHOEND.value: 1e-6, + Options.SCALE.value: False, + Options.STORE_HISTORY.value: False, + Options.TARGET.value: -np.inf, + Options.VERBOSE.value: False, +} + +# Default constants. +DEFAULT_CONSTANTS = { + Constants.DECREASE_RADIUS_FACTOR.value: 0.5, + Constants.INCREASE_RADIUS_FACTOR.value: np.sqrt(2.0), + Constants.INCREASE_RADIUS_THRESHOLD.value: 2.0, + Constants.DECREASE_RADIUS_THRESHOLD.value: 1.4, + Constants.DECREASE_RESOLUTION_FACTOR.value: 0.1, + Constants.LARGE_RESOLUTION_THRESHOLD.value: 250.0, + Constants.MODERATE_RESOLUTION_THRESHOLD.value: 16.0, + Constants.LOW_RATIO.value: 0.1, + Constants.HIGH_RATIO.value: 0.7, + Constants.VERY_LOW_RATIO.value: 0.01, + Constants.PENALTY_INCREASE_THRESHOLD.value: 1.5, + Constants.PENALTY_INCREASE_FACTOR.value: 2.0, + Constants.SHORT_STEP_THRESHOLD.value: 0.5, + Constants.LOW_RADIUS_FACTOR.value: 0.1, + Constants.BYRD_OMOJOKUN_FACTOR.value: 0.8, + Constants.THRESHOLD_RATIO_CONSTRAINTS.value: 2.0, + Constants.LARGE_SHIFT_FACTOR.value: 10.0, + Constants.LARGE_GRADIENT_FACTOR.value: 10.0, + Constants.RESOLUTION_FACTOR.value: 2.0, + Constants.IMPROVE_TCG.value: True, +} + +# Printing options. +PRINT_OPTIONS = { + "threshold": 6, + "edgeitems": 2, + "linewidth": sys.maxsize, + "formatter": { + "float_kind": lambda x: np.format_float_scientific( + x, + precision=3, + unique=False, + pad_left=2, + ) + }, +} + +# Constants. +BARRIER = 2.0 ** min( + 100, + np.finfo(float).maxexp // 2, + -np.finfo(float).minexp // 2, +) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..01a1ad3c6f4cb5c0c9b99d1ce35fea92e7618ff5 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/__init__.py @@ -0,0 +1,14 @@ +from .geometry import cauchy_geometry, spider_geometry +from .optim import ( + tangential_byrd_omojokun, + constrained_tangential_byrd_omojokun, + normal_byrd_omojokun, +) + +__all__ = [ + "cauchy_geometry", + "spider_geometry", + "tangential_byrd_omojokun", + "constrained_tangential_byrd_omojokun", + "normal_byrd_omojokun", +] diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62e130989f9db7e4f4b3cdd968b214d2ed93dd68 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/__pycache__/geometry.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/__pycache__/geometry.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9a4523e2eacd627e4fcfabf6dd558262947cf4a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/__pycache__/geometry.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/__pycache__/optim.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/__pycache__/optim.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4eff28a5adc07668dc97696493be6c634437cf98 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/__pycache__/optim.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/geometry.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/geometry.py new file mode 100644 index 0000000000000000000000000000000000000000..7b67fd7c813ee493b18720d1daf71324d72330b6 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/geometry.py @@ -0,0 +1,387 @@ +import inspect + +import numpy as np + +from ..utils import get_arrays_tol + + +TINY = np.finfo(float).tiny + + +def cauchy_geometry(const, grad, curv, xl, xu, delta, debug): + r""" + Maximize approximately the absolute value of a quadratic function subject + to bound constraints in a trust region. + + This function solves approximately + + .. math:: + + \max_{s \in \mathbb{R}^n} \quad \bigg\lvert c + g^{\mathsf{T}} s + + \frac{1}{2} s^{\mathsf{T}} H s \bigg\rvert \quad \text{s.t.} \quad + \left\{ \begin{array}{l} + l \le s \le u,\\ + \lVert s \rVert \le \Delta, + \end{array} \right. + + by maximizing the objective function along the constrained Cauchy + direction. + + Parameters + ---------- + const : float + Constant :math:`c` as shown above. + grad : `numpy.ndarray`, shape (n,) + Gradient :math:`g` as shown above. + curv : callable + Curvature of :math:`H` along any vector. + + ``curv(s) -> float`` + + returns :math:`s^{\mathsf{T}} H s`. + xl : `numpy.ndarray`, shape (n,) + Lower bounds :math:`l` as shown above. + xu : `numpy.ndarray`, shape (n,) + Upper bounds :math:`u` as shown above. + delta : float + Trust-region radius :math:`\Delta` as shown above. + debug : bool + Whether to make debugging tests during the execution. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Approximate solution :math:`s`. + + Notes + ----- + This function is described as the first alternative in Section 6.5 of [1]_. + It is assumed that the origin is feasible with respect to the bound + constraints and that `delta` is finite and positive. + + References + ---------- + .. [1] T. M. Ragonneau. *Model-Based Derivative-Free Optimization Methods + and Software*. PhD thesis, Department of Applied Mathematics, The Hong + Kong Polytechnic University, Hong Kong, China, 2022. URL: + https://theses.lib.polyu.edu.hk/handle/200/12294. + """ + if debug: + assert isinstance(const, float) + assert isinstance(grad, np.ndarray) and grad.ndim == 1 + assert inspect.signature(curv).bind(grad) + assert isinstance(xl, np.ndarray) and xl.shape == grad.shape + assert isinstance(xu, np.ndarray) and xu.shape == grad.shape + assert isinstance(delta, float) + assert isinstance(debug, bool) + tol = get_arrays_tol(xl, xu) + assert np.all(xl <= tol) + assert np.all(xu >= -tol) + assert np.isfinite(delta) and delta > 0.0 + xl = np.minimum(xl, 0.0) + xu = np.maximum(xu, 0.0) + + # To maximize the absolute value of a quadratic function, we maximize the + # function itself or its negative, and we choose the solution that provides + # the largest function value. + step1, q_val1 = _cauchy_geom(const, grad, curv, xl, xu, delta, debug) + step2, q_val2 = _cauchy_geom( + -const, + -grad, + lambda x: -curv(x), + xl, + xu, + delta, + debug, + ) + step = step1 if abs(q_val1) >= abs(q_val2) else step2 + + if debug: + assert np.all(xl <= step) + assert np.all(step <= xu) + assert np.linalg.norm(step) < 1.1 * delta + return step + + +def spider_geometry(const, grad, curv, xpt, xl, xu, delta, debug): + r""" + Maximize approximately the absolute value of a quadratic function subject + to bound constraints in a trust region. + + This function solves approximately + + .. math:: + + \max_{s \in \mathbb{R}^n} \quad \bigg\lvert c + g^{\mathsf{T}} s + + \frac{1}{2} s^{\mathsf{T}} H s \bigg\rvert \quad \text{s.t.} \quad + \left\{ \begin{array}{l} + l \le s \le u,\\ + \lVert s \rVert \le \Delta, + \end{array} \right. + + by maximizing the objective function along given straight lines. + + Parameters + ---------- + const : float + Constant :math:`c` as shown above. + grad : `numpy.ndarray`, shape (n,) + Gradient :math:`g` as shown above. + curv : callable + Curvature of :math:`H` along any vector. + + ``curv(s) -> float`` + + returns :math:`s^{\mathsf{T}} H s`. + xpt : `numpy.ndarray`, shape (n, npt) + Points defining the straight lines. The straight lines considered are + the ones passing through the origin and the points in `xpt`. + xl : `numpy.ndarray`, shape (n,) + Lower bounds :math:`l` as shown above. + xu : `numpy.ndarray`, shape (n,) + Upper bounds :math:`u` as shown above. + delta : float + Trust-region radius :math:`\Delta` as shown above. + debug : bool + Whether to make debugging tests during the execution. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Approximate solution :math:`s`. + + Notes + ----- + This function is described as the second alternative in Section 6.5 of + [1]_. It is assumed that the origin is feasible with respect to the bound + constraints and that `delta` is finite and positive. + + References + ---------- + .. [1] T. M. Ragonneau. *Model-Based Derivative-Free Optimization Methods + and Software*. PhD thesis, Department of Applied Mathematics, The Hong + Kong Polytechnic University, Hong Kong, China, 2022. URL: + https://theses.lib.polyu.edu.hk/handle/200/12294. + """ + if debug: + assert isinstance(const, float) + assert isinstance(grad, np.ndarray) and grad.ndim == 1 + assert inspect.signature(curv).bind(grad) + assert ( + isinstance(xpt, np.ndarray) + and xpt.ndim == 2 + and xpt.shape[0] == grad.size + ) + assert isinstance(xl, np.ndarray) and xl.shape == grad.shape + assert isinstance(xu, np.ndarray) and xu.shape == grad.shape + assert isinstance(delta, float) + assert isinstance(debug, bool) + tol = get_arrays_tol(xl, xu) + assert np.all(xl <= tol) + assert np.all(xu >= -tol) + assert np.isfinite(delta) and delta > 0.0 + xl = np.minimum(xl, 0.0) + xu = np.maximum(xu, 0.0) + + # Iterate through the straight lines. + step = np.zeros_like(grad) + q_val = const + s_norm = np.linalg.norm(xpt, axis=0) + + # Set alpha_xl to the step size for the lower-bound constraint and + # alpha_xu to the step size for the upper-bound constraint. + + # xl.shape = (N,) + # xpt.shape = (N, M) + # i_xl_pos.shape = (M, N) + i_xl_pos = (xl > -np.inf) & (xpt.T > -TINY * xl) + i_xl_neg = (xl > -np.inf) & (xpt.T < TINY * xl) + i_xu_pos = (xu < np.inf) & (xpt.T > TINY * xu) + i_xu_neg = (xu < np.inf) & (xpt.T < -TINY * xu) + + # (M, N) + alpha_xl_pos = np.atleast_2d( + np.broadcast_to(xl, i_xl_pos.shape)[i_xl_pos] / xpt.T[i_xl_pos] + ) + # (M,) + alpha_xl_pos = np.max(alpha_xl_pos, axis=1, initial=-np.inf) + # make sure it's (M,) + alpha_xl_pos = np.broadcast_to(np.atleast_1d(alpha_xl_pos), xpt.shape[1]) + + alpha_xl_neg = np.atleast_2d( + np.broadcast_to(xl, i_xl_neg.shape)[i_xl_neg] / xpt.T[i_xl_neg] + ) + alpha_xl_neg = np.max(alpha_xl_neg, axis=1, initial=np.inf) + alpha_xl_neg = np.broadcast_to(np.atleast_1d(alpha_xl_neg), xpt.shape[1]) + + alpha_xu_neg = np.atleast_2d( + np.broadcast_to(xu, i_xu_neg.shape)[i_xu_neg] / xpt.T[i_xu_neg] + ) + alpha_xu_neg = np.max(alpha_xu_neg, axis=1, initial=-np.inf) + alpha_xu_neg = np.broadcast_to(np.atleast_1d(alpha_xu_neg), xpt.shape[1]) + + alpha_xu_pos = np.atleast_2d( + np.broadcast_to(xu, i_xu_pos.shape)[i_xu_pos] / xpt.T[i_xu_pos] + ) + alpha_xu_pos = np.max(alpha_xu_pos, axis=1, initial=np.inf) + alpha_xu_pos = np.broadcast_to(np.atleast_1d(alpha_xu_pos), xpt.shape[1]) + + for k in range(xpt.shape[1]): + # Set alpha_tr to the step size for the trust-region constraint. + if s_norm[k] > TINY * delta: + alpha_tr = max(delta / s_norm[k], 0.0) + else: + # The current straight line is basically zero. + continue + + alpha_bd_pos = max(min(alpha_xu_pos[k], alpha_xl_neg[k]), 0.0) + alpha_bd_neg = min(max(alpha_xl_pos[k], alpha_xu_neg[k]), 0.0) + + # Set alpha_quad_pos and alpha_quad_neg to the step size to the extrema + # of the quadratic function along the positive and negative directions. + grad_step = grad @ xpt[:, k] + curv_step = curv(xpt[:, k]) + if ( + grad_step >= 0.0 + and curv_step < -TINY * grad_step + or grad_step <= 0.0 + and curv_step > -TINY * grad_step + ): + alpha_quad_pos = max(-grad_step / curv_step, 0.0) + else: + alpha_quad_pos = np.inf + if ( + grad_step >= 0.0 + and curv_step > TINY * grad_step + or grad_step <= 0.0 + and curv_step < TINY * grad_step + ): + alpha_quad_neg = min(-grad_step / curv_step, 0.0) + else: + alpha_quad_neg = -np.inf + + # Select the step that provides the largest value of the objective + # function if it improves the current best. The best positive step is + # either the one that reaches the constraints or the one that reaches + # the extremum of the objective function along the current direction + # (only possible if the resulting step is feasible). We test both, and + # we perform similar calculations along the negative step. + # N.B.: we select the largest possible step among all the ones that + # maximize the objective function. This is to avoid returning the zero + # step in some extreme cases. + alpha_pos = min(alpha_tr, alpha_bd_pos) + alpha_neg = max(-alpha_tr, alpha_bd_neg) + q_val_pos = ( + const + alpha_pos * grad_step + 0.5 * alpha_pos**2.0 * curv_step + ) + q_val_neg = ( + const + alpha_neg * grad_step + 0.5 * alpha_neg**2.0 * curv_step + ) + if alpha_quad_pos < alpha_pos: + q_val_quad_pos = ( + const + + alpha_quad_pos * grad_step + + 0.5 * alpha_quad_pos**2.0 * curv_step + ) + if abs(q_val_quad_pos) > abs(q_val_pos): + alpha_pos = alpha_quad_pos + q_val_pos = q_val_quad_pos + if alpha_quad_neg > alpha_neg: + q_val_quad_neg = ( + const + + alpha_quad_neg * grad_step + + 0.5 * alpha_quad_neg**2.0 * curv_step + ) + if abs(q_val_quad_neg) > abs(q_val_neg): + alpha_neg = alpha_quad_neg + q_val_neg = q_val_quad_neg + if abs(q_val_pos) >= abs(q_val_neg) and abs(q_val_pos) > abs(q_val): + step = np.clip(alpha_pos * xpt[:, k], xl, xu) + q_val = q_val_pos + elif abs(q_val_neg) > abs(q_val_pos) and abs(q_val_neg) > abs(q_val): + step = np.clip(alpha_neg * xpt[:, k], xl, xu) + q_val = q_val_neg + + if debug: + assert np.all(xl <= step) + assert np.all(step <= xu) + assert np.linalg.norm(step) < 1.1 * delta + return step + + +def _cauchy_geom(const, grad, curv, xl, xu, delta, debug): + """ + Same as `bound_constrained_cauchy_step` without the absolute value. + """ + # Calculate the initial active set. + fixed_xl = (xl < 0.0) & (grad > 0.0) + fixed_xu = (xu > 0.0) & (grad < 0.0) + + # Calculate the Cauchy step. + cauchy_step = np.zeros_like(grad) + cauchy_step[fixed_xl] = xl[fixed_xl] + cauchy_step[fixed_xu] = xu[fixed_xu] + if np.linalg.norm(cauchy_step) > delta: + working = fixed_xl | fixed_xu + while True: + # Calculate the Cauchy step for the directions in the working set. + g_norm = np.linalg.norm(grad[working]) + delta_reduced = np.sqrt( + delta**2.0 - cauchy_step[~working] @ cauchy_step[~working] + ) + if g_norm > TINY * abs(delta_reduced): + mu = max(delta_reduced / g_norm, 0.0) + else: + break + cauchy_step[working] = mu * grad[working] + + # Update the working set. + fixed_xl = working & (cauchy_step < xl) + fixed_xu = working & (cauchy_step > xu) + if not np.any(fixed_xl) and not np.any(fixed_xu): + # Stop the calculations as the Cauchy step is now feasible. + break + cauchy_step[fixed_xl] = xl[fixed_xl] + cauchy_step[fixed_xu] = xu[fixed_xu] + working = working & ~(fixed_xl | fixed_xu) + + # Calculate the step that maximizes the quadratic along the Cauchy step. + grad_step = grad @ cauchy_step + if grad_step >= 0.0: + # Set alpha_tr to the step size for the trust-region constraint. + s_norm = np.linalg.norm(cauchy_step) + if s_norm > TINY * delta: + alpha_tr = max(delta / s_norm, 0.0) + else: + # The Cauchy step is basically zero. + alpha_tr = 0.0 + + # Set alpha_quad to the step size for the maximization problem. + curv_step = curv(cauchy_step) + if curv_step < -TINY * grad_step: + alpha_quad = max(-grad_step / curv_step, 0.0) + else: + alpha_quad = np.inf + + # Set alpha_bd to the step size for the bound constraints. + i_xl = (xl > -np.inf) & (cauchy_step < TINY * xl) + i_xu = (xu < np.inf) & (cauchy_step > TINY * xu) + alpha_xl = np.min(xl[i_xl] / cauchy_step[i_xl], initial=np.inf) + alpha_xu = np.min(xu[i_xu] / cauchy_step[i_xu], initial=np.inf) + alpha_bd = min(alpha_xl, alpha_xu) + + # Calculate the solution and the corresponding function value. + alpha = min(alpha_tr, alpha_quad, alpha_bd) + step = np.clip(alpha * cauchy_step, xl, xu) + q_val = const + alpha * grad_step + 0.5 * alpha**2.0 * curv_step + else: + # This case is never reached in exact arithmetic. It prevents this + # function to return a step that decreases the objective function. + step = np.zeros_like(grad) + q_val = const + + if debug: + assert np.all(xl <= step) + assert np.all(step <= xu) + assert np.linalg.norm(step) < 1.1 * delta + return step, q_val diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/optim.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/optim.py new file mode 100644 index 0000000000000000000000000000000000000000..c4a960396fb2e992cf76bac0baf171b5af9b7717 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/subsolvers/optim.py @@ -0,0 +1,1203 @@ +import inspect + +import numpy as np +from scipy.linalg import qr + +from ..utils import get_arrays_tol + + +TINY = np.finfo(float).tiny +EPS = np.finfo(float).eps + + +def tangential_byrd_omojokun(grad, hess_prod, xl, xu, delta, debug, **kwargs): + r""" + Minimize approximately a quadratic function subject to bound constraints in + a trust region. + + This function solves approximately + + .. math:: + + \min_{s \in \mathbb{R}^n} \quad g^{\mathsf{T}} s + \frac{1}{2} + s^{\mathsf{T}} H s \quad \text{s.t.} \quad + \left\{ \begin{array}{l} + l \le s \le u\\ + \lVert s \rVert \le \Delta, + \end{array} \right. + + using an active-set variation of the truncated conjugate gradient method. + + Parameters + ---------- + grad : `numpy.ndarray`, shape (n,) + Gradient :math:`g` as shown above. + hess_prod : callable + Product of the Hessian matrix :math:`H` with any vector. + + ``hess_prod(s) -> `numpy.ndarray`, shape (n,)`` + + returns the product :math:`H s`. + xl : `numpy.ndarray`, shape (n,) + Lower bounds :math:`l` as shown above. + xu : `numpy.ndarray`, shape (n,) + Upper bounds :math:`u` as shown above. + delta : float + Trust-region radius :math:`\Delta` as shown above. + debug : bool + Whether to make debugging tests during the execution. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Approximate solution :math:`s`. + + Other Parameters + ---------------- + improve_tcg : bool, optional + If True, a solution generated by the truncated conjugate gradient + method that is on the boundary of the trust region is improved by + moving around the trust-region boundary on the two-dimensional space + spanned by the solution and the gradient of the quadratic function at + the solution (default is True). + + Notes + ----- + This function implements Algorithm 6.2 of [1]_. It is assumed that the + origin is feasible with respect to the bound constraints and that `delta` + is finite and positive. + + References + ---------- + .. [1] T. M. Ragonneau. *Model-Based Derivative-Free Optimization Methods + and Software*. PhD thesis, Department of Applied Mathematics, The Hong + Kong Polytechnic University, Hong Kong, China, 2022. URL: + https://theses.lib.polyu.edu.hk/handle/200/12294. + """ + if debug: + assert isinstance(grad, np.ndarray) and grad.ndim == 1 + assert inspect.signature(hess_prod).bind(grad) + assert isinstance(xl, np.ndarray) and xl.shape == grad.shape + assert isinstance(xu, np.ndarray) and xu.shape == grad.shape + assert isinstance(delta, float) + assert isinstance(debug, bool) + tol = get_arrays_tol(xl, xu) + assert np.all(xl <= tol) + assert np.all(xu >= -tol) + assert np.isfinite(delta) and delta > 0.0 + xl = np.minimum(xl, 0.0) + xu = np.maximum(xu, 0.0) + + # Copy the arrays that may be modified by the code below. + n = grad.size + grad = np.copy(grad) + grad_orig = np.copy(grad) + + # Calculate the initial active set. + free_bd = ((xl < 0.0) | (grad < 0.0)) & ((xu > 0.0) | (grad > 0.0)) + + # Set the initial iterate and the initial search direction. + step = np.zeros_like(grad) + sd = np.zeros_like(step) + sd[free_bd] = -grad[free_bd] + + k = 0 + reduct = 0.0 + boundary_reached = False + while k < np.count_nonzero(free_bd): + # Stop the computations if sd is not a descent direction. + grad_sd = grad @ sd + if grad_sd >= -10.0 * EPS * n * max(1.0, np.linalg.norm(grad)): + break + + # Set alpha_tr to the step size for the trust-region constraint. + try: + alpha_tr = _alpha_tr(step, sd, delta) + except ZeroDivisionError: + break + + # Stop the computations if a step along sd is expected to give a + # relatively small reduction in the objective function. + if -alpha_tr * grad_sd <= 1e-8 * reduct: + break + + # Set alpha_quad to the step size for the minimization problem. + hess_sd = hess_prod(sd) + curv_sd = sd @ hess_sd + if curv_sd > TINY * abs(grad_sd): + alpha_quad = max(-grad_sd / curv_sd, 0.0) + else: + alpha_quad = np.inf + + # Stop the computations if the reduction in the objective function + # provided by an unconstrained step is small. + alpha = min(alpha_tr, alpha_quad) + if -alpha * (grad_sd + 0.5 * alpha * curv_sd) <= 1e-8 * reduct: + break + + # Set alpha_bd to the step size for the bound constraints. + i_xl = (xl > -np.inf) & (sd < -TINY * np.abs(xl - step)) + i_xu = (xu < np.inf) & (sd > TINY * np.abs(xu - step)) + all_alpha_xl = np.full_like(step, np.inf) + all_alpha_xu = np.full_like(step, np.inf) + all_alpha_xl[i_xl] = np.maximum( + (xl[i_xl] - step[i_xl]) / sd[i_xl], + 0.0, + ) + all_alpha_xu[i_xu] = np.maximum( + (xu[i_xu] - step[i_xu]) / sd[i_xu], + 0.0, + ) + alpha_xl = np.min(all_alpha_xl) + alpha_xu = np.min(all_alpha_xu) + alpha_bd = min(alpha_xl, alpha_xu) + + # Update the iterate. + alpha = min(alpha, alpha_bd) + if alpha > 0.0: + step[free_bd] = np.clip( + step[free_bd] + alpha * sd[free_bd], + xl[free_bd], + xu[free_bd], + ) + grad += alpha * hess_sd + reduct -= alpha * (grad_sd + 0.5 * alpha * curv_sd) + + if alpha < min(alpha_tr, alpha_bd): + # The current iteration is a conjugate gradient iteration. Update + # the search direction so that it is conjugate (with respect to H) + # to all the previous search directions. + beta = (grad[free_bd] @ hess_sd[free_bd]) / curv_sd + sd[free_bd] = beta * sd[free_bd] - grad[free_bd] + sd[~free_bd] = 0.0 + k += 1 + elif alpha < alpha_tr: + # The iterate is restricted by a bound constraint. Add this bound + # constraint to the active set, and restart the calculations. + if alpha_xl <= alpha: + i_new = np.argmin(all_alpha_xl) + step[i_new] = xl[i_new] + else: + i_new = np.argmin(all_alpha_xu) + step[i_new] = xu[i_new] + free_bd[i_new] = False + sd[free_bd] = -grad[free_bd] + sd[~free_bd] = 0.0 + k = 0 + else: + # The current iterate is on the trust-region boundary. Add all the + # active bounds to the working set to prepare for the improvement + # of the solution, and stop the iterations. + if alpha_xl <= alpha: + i_new = _argmin(all_alpha_xl) + step[i_new] = xl[i_new] + free_bd[i_new] = False + if alpha_xu <= alpha: + i_new = _argmin(all_alpha_xu) + step[i_new] = xu[i_new] + free_bd[i_new] = False + boundary_reached = True + break + + # Attempt to improve the solution on the trust-region boundary. + if kwargs.get("improve_tcg", True) and boundary_reached: + step_base = np.copy(step) + step_comparator = grad_orig @ step_base + 0.5 * step_base @ hess_prod( + step_base + ) + + while np.count_nonzero(free_bd) > 0: + # Check whether a substantial reduction in the objective function + # is possible, and set the search direction. + step_sq = step[free_bd] @ step[free_bd] + grad_sq = grad[free_bd] @ grad[free_bd] + grad_step = grad[free_bd] @ step[free_bd] + grad_sd = -np.sqrt(max(step_sq * grad_sq - grad_step**2.0, 0.0)) + sd[free_bd] = grad_step * step[free_bd] - step_sq * grad[free_bd] + sd[~free_bd] = 0.0 + if grad_sd >= -1e-8 * reduct or np.any( + grad_sd >= -TINY * np.abs(sd[free_bd]) + ): + break + sd[free_bd] /= -grad_sd + + # Calculate an upper bound for the tangent of half the angle theta + # of this alternative iteration. The step will be updated as: + # step = cos(theta) * step + sin(theta) * sd. + temp_xl = np.zeros(n) + temp_xu = np.zeros(n) + temp_xl[free_bd] = ( + step[free_bd] ** 2.0 + sd[free_bd] ** 2.0 - xl[free_bd] ** 2.0 + ) + temp_xu[free_bd] = ( + step[free_bd] ** 2.0 + sd[free_bd] ** 2.0 - xu[free_bd] ** 2.0 + ) + temp_xl[temp_xl > 0.0] = ( + np.sqrt(temp_xl[temp_xl > 0.0]) - sd[temp_xl > 0.0] + ) + temp_xu[temp_xu > 0.0] = ( + np.sqrt(temp_xu[temp_xu > 0.0]) + sd[temp_xu > 0.0] + ) + dist_xl = np.maximum(step - xl, 0.0) + dist_xu = np.maximum(xu - step, 0.0) + i_xl = temp_xl > TINY * dist_xl + i_xu = temp_xu > TINY * dist_xu + all_t_xl = np.ones(n) + all_t_xu = np.ones(n) + all_t_xl[i_xl] = np.minimum( + all_t_xl[i_xl], + dist_xl[i_xl] / temp_xl[i_xl], + ) + all_t_xu[i_xu] = np.minimum( + all_t_xu[i_xu], + dist_xu[i_xu] / temp_xu[i_xu], + ) + t_xl = np.min(all_t_xl) + t_xu = np.min(all_t_xu) + t_bd = min(t_xl, t_xu) + + # Calculate some curvature information. + hess_step = hess_prod(step) + hess_sd = hess_prod(sd) + curv_step = step @ hess_step + curv_sd = sd @ hess_sd + curv_step_sd = step @ hess_sd + + # For a range of equally spaced values of tan(0.5 * theta), + # calculate the reduction in the objective function that would be + # obtained by accepting the corresponding angle. + n_samples = 20 + n_samples = int((n_samples - 3) * t_bd + 3) + t_samples = np.linspace(t_bd / n_samples, t_bd, n_samples) + sin_values = 2.0 * t_samples / (1.0 + t_samples**2.0) + all_reduct = sin_values * ( + grad_step * t_samples + - grad_sd + - t_samples * curv_step + + sin_values + * (t_samples * curv_step_sd - 0.5 * (curv_sd - curv_step)) + ) + if np.all(all_reduct <= 0.0): + # No reduction in the objective function is obtained. + break + + # Accept the angle that provides the largest reduction in the + # objective function, and update the iterate. + i_max = np.argmax(all_reduct) + cos_value = (1.0 - t_samples[i_max] ** 2.0) / ( + 1.0 + t_samples[i_max] ** 2.0 + ) + step[free_bd] = ( + cos_value * step[free_bd] + sin_values[i_max] * sd[free_bd] + ) + grad += (cos_value - 1.0) * hess_step + sin_values[i_max] * hess_sd + reduct += all_reduct[i_max] + + # If the above angle is restricted by bound constraints, add them + # to the working set, and restart the alternative iteration. + # Otherwise, the calculations are terminated. + if t_bd < 1.0 and i_max == n_samples - 1: + if t_xl <= t_bd: + i_new = _argmin(all_t_xl) + step[i_new] = xl[i_new] + free_bd[i_new] = False + if t_xu <= t_bd: + i_new = _argmin(all_t_xu) + step[i_new] = xu[i_new] + free_bd[i_new] = False + else: + break + + # Ensure that the alternative iteration improves the objective + # function. + if grad_orig @ step + 0.5 * step @ hess_prod(step) > step_comparator: + step = step_base + + if debug: + assert np.all(xl <= step) + assert np.all(step <= xu) + assert np.linalg.norm(step) < 1.1 * delta + return step + + +def constrained_tangential_byrd_omojokun( + grad, + hess_prod, + xl, + xu, + aub, + bub, + aeq, + delta, + debug, + **kwargs, +): + r""" + Minimize approximately a quadratic function subject to bound and linear + constraints in a trust region. + + This function solves approximately + + .. math:: + + \min_{s \in \mathbb{R}^n} \quad g^{\mathsf{T}} s + \frac{1}{2} + s^{\mathsf{T}} H s \quad \text{s.t.} \quad + \left\{ \begin{array}{l} + l \le s \le u,\\ + A_{\scriptscriptstyle I} s \le b_{\scriptscriptstyle I},\\ + A_{\scriptscriptstyle E} s = 0,\\ + \lVert s \rVert \le \Delta, + \end{array} \right. + + using an active-set variation of the truncated conjugate gradient method. + + Parameters + ---------- + grad : `numpy.ndarray`, shape (n,) + Gradient :math:`g` as shown above. + hess_prod : callable + Product of the Hessian matrix :math:`H` with any vector. + + ``hess_prod(s) -> `numpy.ndarray`, shape (n,)`` + + returns the product :math:`H s`. + xl : `numpy.ndarray`, shape (n,) + Lower bounds :math:`l` as shown above. + xu : `numpy.ndarray`, shape (n,) + Upper bounds :math:`u` as shown above. + aub : `numpy.ndarray`, shape (m_linear_ub, n) + Coefficient matrix :math:`A_{\scriptscriptstyle I}` as shown above. + bub : `numpy.ndarray`, shape (m_linear_ub,) + Right-hand side :math:`b_{\scriptscriptstyle I}` as shown above. + aeq : `numpy.ndarray`, shape (m_linear_eq, n) + Coefficient matrix :math:`A_{\scriptscriptstyle E}` as shown above. + delta : float + Trust-region radius :math:`\Delta` as shown above. + debug : bool + Whether to make debugging tests during the execution. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Approximate solution :math:`s`. + + Other Parameters + ---------------- + improve_tcg : bool, optional + If True, a solution generated by the truncated conjugate gradient + method that is on the boundary of the trust region is improved by + moving around the trust-region boundary on the two-dimensional space + spanned by the solution and the gradient of the quadratic function at + the solution (default is True). + + Notes + ----- + This function implements Algorithm 6.3 of [1]_. It is assumed that the + origin is feasible with respect to the bound and linear constraints, and + that `delta` is finite and positive. + + References + ---------- + .. [1] T. M. Ragonneau. *Model-Based Derivative-Free Optimization Methods + and Software*. PhD thesis, Department of Applied Mathematics, The Hong + Kong Polytechnic University, Hong Kong, China, 2022. URL: + https://theses.lib.polyu.edu.hk/handle/200/12294. + """ + if debug: + assert isinstance(grad, np.ndarray) and grad.ndim == 1 + assert inspect.signature(hess_prod).bind(grad) + assert isinstance(xl, np.ndarray) and xl.shape == grad.shape + assert isinstance(xu, np.ndarray) and xu.shape == grad.shape + assert ( + isinstance(aub, np.ndarray) + and aub.ndim == 2 + and aub.shape[1] == grad.size + ) + assert ( + isinstance(bub, np.ndarray) + and bub.ndim == 1 + and bub.size == aub.shape[0] + ) + assert ( + isinstance(aeq, np.ndarray) + and aeq.ndim == 2 + and aeq.shape[1] == grad.size + ) + assert isinstance(delta, float) + assert isinstance(debug, bool) + tol = get_arrays_tol(xl, xu) + assert np.all(xl <= tol) + assert np.all(xu >= -tol) + assert np.all(bub >= -tol) + assert np.isfinite(delta) and delta > 0.0 + xl = np.minimum(xl, 0.0) + xu = np.maximum(xu, 0.0) + bub = np.maximum(bub, 0.0) + + # Copy the arrays that may be modified by the code below. + n = grad.size + grad = np.copy(grad) + grad_orig = np.copy(grad) + + # Calculate the initial active set. + free_xl = (xl < 0.0) | (grad < 0.0) + free_xu = (xu > 0.0) | (grad > 0.0) + free_ub = (bub > 0.0) | (aub @ grad > 0.0) + n_act, q = qr_tangential_byrd_omojokun(aub, aeq, free_xl, free_xu, free_ub) + + # Set the initial iterate and the initial search direction. + step = np.zeros_like(grad) + sd = -q[:, n_act:] @ (q[:, n_act:].T @ grad) + resid = np.copy(bub) + + k = 0 + reduct = 0.0 + boundary_reached = False + while k < n - n_act: + # Stop the computations if sd is not a descent direction. + grad_sd = grad @ sd + if grad_sd >= -10.0 * EPS * n * max(1.0, np.linalg.norm(grad)): + break + + # Set alpha_tr to the step size for the trust-region constraint. + try: + alpha_tr = _alpha_tr(step, sd, delta) + except ZeroDivisionError: + break + + # Stop the computations if a step along sd is expected to give a + # relatively small reduction in the objective function. + if -alpha_tr * grad_sd <= 1e-8 * reduct: + break + + # Set alpha_quad to the step size for the minimization problem. + hess_sd = hess_prod(sd) + curv_sd = sd @ hess_sd + if curv_sd > TINY * abs(grad_sd): + alpha_quad = max(-grad_sd / curv_sd, 0.0) + else: + alpha_quad = np.inf + + # Stop the computations if the reduction in the objective function + # provided by an unconstrained step is small. + alpha = min(alpha_tr, alpha_quad) + if -alpha * (grad_sd + 0.5 * alpha * curv_sd) <= 1e-8 * reduct: + break + + # Set alpha_bd to the step size for the bound constraints. + i_xl = free_xl & (xl > -np.inf) & (sd < -TINY * np.abs(xl - step)) + i_xu = free_xu & (xu < np.inf) & (sd > TINY * np.abs(xu - step)) + all_alpha_xl = np.full_like(step, np.inf) + all_alpha_xu = np.full_like(step, np.inf) + all_alpha_xl[i_xl] = np.maximum( + (xl[i_xl] - step[i_xl]) / sd[i_xl], + 0.0, + ) + all_alpha_xu[i_xu] = np.maximum( + (xu[i_xu] - step[i_xu]) / sd[i_xu], + 0.0, + ) + alpha_xl = np.min(all_alpha_xl) + alpha_xu = np.min(all_alpha_xu) + alpha_bd = min(alpha_xl, alpha_xu) + + # Set alpha_ub to the step size for the linear constraints. + aub_sd = aub @ sd + i_ub = free_ub & (aub_sd > TINY * np.abs(resid)) + all_alpha_ub = np.full_like(bub, np.inf) + all_alpha_ub[i_ub] = resid[i_ub] / aub_sd[i_ub] + alpha_ub = np.min(all_alpha_ub, initial=np.inf) + + # Update the iterate. + alpha = min(alpha, alpha_bd, alpha_ub) + if alpha > 0.0: + step = np.clip(step + alpha * sd, xl, xu) + grad += alpha * hess_sd + resid = np.maximum(0.0, resid - alpha * aub_sd) + reduct -= alpha * (grad_sd + 0.5 * alpha * curv_sd) + + if alpha < min(alpha_tr, alpha_bd, alpha_ub): + # The current iteration is a conjugate gradient iteration. Update + # the search direction so that it is conjugate (with respect to H) + # to all the previous search directions. + grad_proj = q[:, n_act:] @ (q[:, n_act:].T @ grad) + beta = (grad_proj @ hess_sd) / curv_sd + sd = beta * sd - grad_proj + k += 1 + elif alpha < alpha_tr: + # The iterate is restricted by a bound/linear constraint. Add this + # constraint to the active set, and restart the calculations. + if alpha_xl <= alpha: + i_new = np.argmin(all_alpha_xl) + step[i_new] = xl[i_new] + free_xl[i_new] = False + elif alpha_xu <= alpha: + i_new = np.argmin(all_alpha_xu) + step[i_new] = xu[i_new] + free_xu[i_new] = False + else: + i_new = np.argmin(all_alpha_ub) + free_ub[i_new] = False + n_act, q = qr_tangential_byrd_omojokun( + aub, + aeq, + free_xl, + free_xu, + free_ub, + ) + sd = -q[:, n_act:] @ (q[:, n_act:].T @ grad) + k = 0 + else: + # The current iterate is on the trust-region boundary. Add all the + # active bound/linear constraints to the working set to prepare for + # the improvement of the solution, and stop the iterations. + if alpha_xl <= alpha: + i_new = _argmin(all_alpha_xl) + step[i_new] = xl[i_new] + free_xl[i_new] = False + if alpha_xu <= alpha: + i_new = _argmin(all_alpha_xu) + step[i_new] = xu[i_new] + free_xu[i_new] = False + if alpha_ub <= alpha: + i_new = _argmin(all_alpha_ub) + free_ub[i_new] = False + n_act, q = qr_tangential_byrd_omojokun( + aub, + aeq, + free_xl, + free_xu, + free_ub, + ) + boundary_reached = True + break + + # Attempt to improve the solution on the trust-region boundary. + if kwargs.get("improve_tcg", True) and boundary_reached and n_act < n: + step_base = np.copy(step) + while n_act < n: + # Check whether a substantial reduction in the objective function + # is possible, and set the search direction. + step_proj = q[:, n_act:] @ (q[:, n_act:].T @ step) + grad_proj = q[:, n_act:] @ (q[:, n_act:].T @ grad) + step_sq = step_proj @ step_proj + grad_sq = grad_proj @ grad_proj + grad_step = grad_proj @ step_proj + grad_sd = -np.sqrt(max(step_sq * grad_sq - grad_step**2.0, 0.0)) + sd = q[:, n_act:] @ ( + q[:, n_act:].T @ (grad_step * step - step_sq * grad) + ) + if grad_sd >= -1e-8 * reduct or np.any( + grad_sd >= -TINY * np.abs(sd) + ): + break + sd /= -grad_sd + + # Calculate an upper bound for the tangent of half the angle theta + # of this alternative iteration for the bound constraints. The step + # will be updated as: + # step += (cos(theta) - 1) * step_proj + sin(theta) * sd. + temp_xl = np.zeros(n) + temp_xu = np.zeros(n) + dist_xl = np.maximum(step - xl, 0.0) + dist_xu = np.maximum(xu - step, 0.0) + temp_xl[free_xl] = sd[free_xl] ** 2.0 - dist_xl[free_xl] * ( + dist_xl[free_xl] - 2.0 * step_proj[free_xl] + ) + temp_xu[free_xu] = sd[free_xu] ** 2.0 - dist_xu[free_xu] * ( + dist_xu[free_xu] + 2.0 * step_proj[free_xu] + ) + temp_xl[temp_xl > 0.0] = ( + np.sqrt(temp_xl[temp_xl > 0.0]) - sd[temp_xl > 0.0] + ) + temp_xu[temp_xu > 0.0] = ( + np.sqrt(temp_xu[temp_xu > 0.0]) + sd[temp_xu > 0.0] + ) + i_xl = temp_xl > TINY * dist_xl + i_xu = temp_xu > TINY * dist_xu + all_t_xl = np.ones(n) + all_t_xu = np.ones(n) + all_t_xl[i_xl] = np.minimum( + all_t_xl[i_xl], + dist_xl[i_xl] / temp_xl[i_xl], + ) + all_t_xu[i_xu] = np.minimum( + all_t_xu[i_xu], + dist_xu[i_xu] / temp_xu[i_xu], + ) + t_xl = np.min(all_t_xl) + t_xu = np.min(all_t_xu) + t_bd = min(t_xl, t_xu) + + # Calculate an upper bound for the tangent of half the angle theta + # of this alternative iteration for the linear constraints. + temp_ub = np.zeros_like(resid) + aub_step = aub @ step_proj + aub_sd = aub @ sd + temp_ub[free_ub] = aub_sd[free_ub] ** 2.0 - resid[free_ub] * ( + resid[free_ub] + 2.0 * aub_step[free_ub] + ) + temp_ub[temp_ub > 0.0] = ( + np.sqrt(temp_ub[temp_ub > 0.0]) + aub_sd[temp_ub > 0.0] + ) + i_ub = temp_ub > TINY * resid + all_t_ub = np.ones_like(resid) + all_t_ub[i_ub] = np.minimum( + all_t_ub[i_ub], + resid[i_ub] / temp_ub[i_ub], + ) + t_ub = np.min(all_t_ub, initial=1.0) + t_min = min(t_bd, t_ub) + + # Calculate some curvature information. + hess_step = hess_prod(step_proj) + hess_sd = hess_prod(sd) + curv_step = step_proj @ hess_step + curv_sd = sd @ hess_sd + curv_step_sd = step_proj @ hess_sd + + # For a range of equally spaced values of tan(0.5 * theta), + # calculate the reduction in the objective function that would be + # obtained by accepting the corresponding angle. + n_samples = 20 + n_samples = int((n_samples - 3) * t_min + 3) + t_samples = np.linspace(t_min / n_samples, t_min, n_samples) + sin_values = 2.0 * t_samples / (1.0 + t_samples**2.0) + all_reduct = sin_values * ( + grad_step * t_samples + - grad_sd + - sin_values + * ( + 0.5 * t_samples**2.0 * curv_step + - 2.0 * t_samples * curv_step_sd + + 0.5 * curv_sd + ) + ) + if np.all(all_reduct <= 0.0): + # No reduction in the objective function is obtained. + break + + # Accept the angle that provides the largest reduction in the + # objective function, and update the iterate. + i_max = np.argmax(all_reduct) + cos_value = (1.0 - t_samples[i_max] ** 2.0) / ( + 1.0 + t_samples[i_max] ** 2.0 + ) + step = np.clip( + step + (cos_value - 1.0) * step_proj + sin_values[i_max] * sd, + xl, + xu, + ) + grad += (cos_value - 1.0) * hess_step + sin_values[i_max] * hess_sd + resid = np.maximum( + 0.0, + resid + - (cos_value - 1.0) * aub_step + - sin_values[i_max] * aub_sd, + ) + reduct += all_reduct[i_max] + + # If the above angle is restricted by bound constraints, add them + # to the working set, and restart the alternative iteration. + # Otherwise, the calculations are terminated. + if t_min < 1.0 and i_max == n_samples - 1: + if t_xl <= t_min: + i_new = _argmin(all_t_xl) + step[i_new] = xl[i_new] + free_xl[i_new] = False + if t_xu <= t_min: + i_new = _argmin(all_t_xu) + step[i_new] = xu[i_new] + free_xl[i_new] = False + if t_ub <= t_min: + i_new = _argmin(all_t_ub) + free_ub[i_new] = False + n_act, q = qr_tangential_byrd_omojokun( + aub, + aeq, + free_xl, + free_xu, + free_ub, + ) + else: + break + + # Ensure that the alternative iteration improves the objective + # function. + if grad_orig @ step + 0.5 * step @ hess_prod( + step + ) > grad_orig @ step_base + 0.5 * step_base @ hess_prod(step_base): + step = step_base + + if debug: + tol = get_arrays_tol(xl, xu) + assert np.all(xl <= step) + assert np.all(step <= xu) + assert np.all(aub @ step <= bub + tol) + assert np.all(np.abs(aeq @ step) <= tol) + assert np.linalg.norm(step) < 1.1 * delta + return step + + +def normal_byrd_omojokun(aub, bub, aeq, beq, xl, xu, delta, debug, **kwargs): + r""" + Minimize approximately a linear constraint violation subject to bound + constraints in a trust region. + + This function solves approximately + + .. math:: + + \min_{s \in \mathbb{R}^n} \quad \frac{1}{2} \big( \lVert \max \{ + A_{\scriptscriptstyle I} s - b_{\scriptscriptstyle I}, 0 \} \rVert^2 + + \lVert A_{\scriptscriptstyle E} s - b_{\scriptscriptstyle E} \rVert^2 + \big) \quad \text{s.t.} + \quad + \left\{ \begin{array}{l} + l \le s \le u,\\ + \lVert s \rVert \le \Delta, + \end{array} \right. + + using a variation of the truncated conjugate gradient method. + + Parameters + ---------- + aub : `numpy.ndarray`, shape (m_linear_ub, n) + Matrix :math:`A_{\scriptscriptstyle I}` as shown above. + bub : `numpy.ndarray`, shape (m_linear_ub,) + Vector :math:`b_{\scriptscriptstyle I}` as shown above. + aeq : `numpy.ndarray`, shape (m_linear_eq, n) + Matrix :math:`A_{\scriptscriptstyle E}` as shown above. + beq : `numpy.ndarray`, shape (m_linear_eq,) + Vector :math:`b_{\scriptscriptstyle E}` as shown above. + xl : `numpy.ndarray`, shape (n,) + Lower bounds :math:`l` as shown above. + xu : `numpy.ndarray`, shape (n,) + Upper bounds :math:`u` as shown above. + delta : float + Trust-region radius :math:`\Delta` as shown above. + debug : bool + Whether to make debugging tests during the execution. + + Returns + ------- + `numpy.ndarray`, shape (n,) + Approximate solution :math:`s`. + + Other Parameters + ---------------- + improve_tcg : bool, optional + If True, a solution generated by the truncated conjugate gradient + method that is on the boundary of the trust region is improved by + moving around the trust-region boundary on the two-dimensional space + spanned by the solution and the gradient of the quadratic function at + the solution (default is True). + + Notes + ----- + This function implements Algorithm 6.4 of [1]_. It is assumed that the + origin is feasible with respect to the bound constraints and that `delta` + is finite and positive. + + References + ---------- + .. [1] T. M. Ragonneau. *Model-Based Derivative-Free Optimization Methods + and Software*. PhD thesis, Department of Applied Mathematics, The Hong + Kong Polytechnic University, Hong Kong, China, 2022. URL: + https://theses.lib.polyu.edu.hk/handle/200/12294. + """ + if debug: + assert isinstance(aub, np.ndarray) and aub.ndim == 2 + assert ( + isinstance(bub, np.ndarray) + and bub.ndim == 1 + and bub.size == aub.shape[0] + ) + assert ( + isinstance(aeq, np.ndarray) + and aeq.ndim == 2 + and aeq.shape[1] == aub.shape[1] + ) + assert ( + isinstance(beq, np.ndarray) + and beq.ndim == 1 + and beq.size == aeq.shape[0] + ) + assert isinstance(xl, np.ndarray) and xl.shape == (aub.shape[1],) + assert isinstance(xu, np.ndarray) and xu.shape == (aub.shape[1],) + assert isinstance(delta, float) + assert isinstance(debug, bool) + tol = get_arrays_tol(xl, xu) + assert np.all(xl <= tol) + assert np.all(xu >= -tol) + assert np.isfinite(delta) and delta > 0.0 + xl = np.minimum(xl, 0.0) + xu = np.maximum(xu, 0.0) + + # Calculate the initial active set. + m_linear_ub, n = aub.shape + grad = np.r_[aeq.T @ -beq, np.maximum(0.0, -bub)] + free_xl = (xl < 0.0) | (grad[:n] < 0.0) + free_xu = (xu > 0.0) | (grad[:n] > 0.0) + free_slack = bub < 0.0 + free_ub = (bub > 0.0) | (aub @ grad[:n] - grad[n:] > 0.0) + n_act, q = qr_normal_byrd_omojokun( + aub, + free_xl, + free_xu, + free_slack, + free_ub, + ) + + # Calculate an upper bound on the norm of the slack variables. It is not + # used in the original algorithm, but it may prevent undesired behaviors + # engendered by computer rounding errors. + delta_slack = np.sqrt(beq @ beq + grad[n:] @ grad[n:]) + + # Set the initial iterate and the initial search direction. + step = np.zeros(n) + sd = -q[:, n_act:] @ (q[:, n_act:].T @ grad) + resid = bub + grad[n:] + + k = 0 + reduct = 0.0 + boundary_reached = False + while k < n + m_linear_ub - n_act: + # Stop the computations if sd is not a descent direction. + grad_sd = grad @ sd + if grad_sd >= -10.0 * EPS * n * max(1.0, np.linalg.norm(grad)): + break + + # Set alpha_tr to the step size for the trust-region constraint. + try: + alpha_tr = _alpha_tr(step, sd[:n], delta) + except ZeroDivisionError: + alpha_tr = np.inf + + # Prevent undesired behaviors engendered by computer rounding errors by + # considering the trust-region constraint on the slack variables. + try: + alpha_tr = min(alpha_tr, _alpha_tr(grad[n:], sd[n:], delta_slack)) + except ZeroDivisionError: + pass + + # Stop the computations if a step along sd is expected to give a + # relatively small reduction in the objective function. + if -alpha_tr * grad_sd <= 1e-8 * reduct: + break + + # Set alpha_quad to the step size for the minimization problem. + hess_sd = np.r_[aeq.T @ (aeq @ sd[:n]), sd[n:]] + curv_sd = sd @ hess_sd + if curv_sd > TINY * abs(grad_sd): + alpha_quad = max(-grad_sd / curv_sd, 0.0) + else: + alpha_quad = np.inf + + # Stop the computations if the reduction in the objective function + # provided by an unconstrained step is small. + alpha = min(alpha_tr, alpha_quad) + if -alpha * (grad_sd + 0.5 * alpha * curv_sd) <= 1e-8 * reduct: + break + + # Set alpha_bd to the step size for the bound constraints. + i_xl = free_xl & (xl > -np.inf) & (sd[:n] < -TINY * np.abs(xl - step)) + i_xu = free_xu & (xu < np.inf) & (sd[:n] > TINY * np.abs(xu - step)) + i_slack = free_slack & (sd[n:] < -TINY * np.abs(grad[n:])) + all_alpha_xl = np.full_like(step, np.inf) + all_alpha_xu = np.full_like(step, np.inf) + all_alpha_slack = np.full_like(bub, np.inf) + all_alpha_xl[i_xl] = np.maximum( + (xl[i_xl] - step[i_xl]) / sd[:n][i_xl], + 0.0, + ) + all_alpha_xu[i_xu] = np.maximum( + (xu[i_xu] - step[i_xu]) / sd[:n][i_xu], + 0.0, + ) + all_alpha_slack[i_slack] = np.maximum( + -grad[n:][i_slack] / sd[n:][i_slack], + 0.0, + ) + alpha_xl = np.min(all_alpha_xl) + alpha_xu = np.min(all_alpha_xu) + alpha_slack = np.min(all_alpha_slack, initial=np.inf) + alpha_bd = min(alpha_xl, alpha_xu, alpha_slack) + + # Set alpha_ub to the step size for the linear constraints. + aub_sd = aub @ sd[:n] - sd[n:] + i_ub = free_ub & (aub_sd > TINY * np.abs(resid)) + all_alpha_ub = np.full_like(bub, np.inf) + all_alpha_ub[i_ub] = resid[i_ub] / aub_sd[i_ub] + alpha_ub = np.min(all_alpha_ub, initial=np.inf) + + # Update the iterate. + alpha = min(alpha, alpha_bd, alpha_ub) + if alpha > 0.0: + step = np.clip(step + alpha * sd[:n], xl, xu) + grad += alpha * hess_sd + resid = np.maximum(0.0, resid - alpha * aub_sd) + reduct -= alpha * (grad_sd + 0.5 * alpha * curv_sd) + + if alpha < min(alpha_tr, alpha_bd, alpha_ub): + # The current iteration is a conjugate gradient iteration. Update + # the search direction so that it is conjugate (with respect to H) + # to all the previous search directions. + grad_proj = q[:, n_act:] @ (q[:, n_act:].T @ grad) + beta = (grad_proj @ hess_sd) / curv_sd + sd = beta * sd - grad_proj + k += 1 + elif alpha < alpha_tr: + # The iterate is restricted by a bound/linear constraint. Add this + # constraint to the active set, and restart the calculations. + if alpha_xl <= alpha: + i_new = np.argmin(all_alpha_xl) + step[i_new] = xl[i_new] + free_xl[i_new] = False + elif alpha_xu <= alpha: + i_new = np.argmin(all_alpha_xu) + step[i_new] = xu[i_new] + free_xu[i_new] = False + elif alpha_slack <= alpha: + i_new = np.argmin(all_alpha_slack) + free_slack[i_new] = False + else: + i_new = np.argmin(all_alpha_ub) + free_ub[i_new] = False + n_act, q = qr_normal_byrd_omojokun( + aub, free_xl, free_xu, free_slack, free_ub + ) + sd = -q[:, n_act:] @ (q[:, n_act:].T @ grad) + k = 0 + else: + # The current iterate is on the trust-region boundary. Add all the + # active bound constraints to the working set to prepare for the + # improvement of the solution, and stop the iterations. + if alpha_xl <= alpha: + i_new = _argmin(all_alpha_xl) + step[i_new] = xl[i_new] + free_xl[i_new] = False + if alpha_xu <= alpha: + i_new = _argmin(all_alpha_xu) + step[i_new] = xu[i_new] + free_xu[i_new] = False + boundary_reached = True + break + + # Attempt to improve the solution on the trust-region boundary. + if kwargs.get("improve_tcg", True) and boundary_reached: + step_base = np.copy(step) + free_bd = free_xl & free_xu + grad = aub.T @ np.maximum(aub @ step - bub, 0.0) + aeq.T @ ( + aeq @ step - beq + ) + sd = np.zeros(n) + while np.count_nonzero(free_bd) > 0: + # Check whether a substantial reduction in the objective function + # is possible, and set the search direction. + step_sq = step[free_bd] @ step[free_bd] + grad_sq = grad[free_bd] @ grad[free_bd] + grad_step = grad[free_bd] @ step[free_bd] + grad_sd = -np.sqrt(max(step_sq * grad_sq - grad_step**2.0, 0.0)) + sd[free_bd] = grad_step * step[free_bd] - step_sq * grad[free_bd] + sd[~free_bd] = 0.0 + if grad_sd >= -1e-8 * reduct or np.any( + grad_sd >= -TINY * np.abs(sd[free_bd]) + ): + break + sd[free_bd] /= -grad_sd + + # Calculate an upper bound for the tangent of half the angle theta + # of this alternative iteration. The step will be updated as: + # step = cos(theta) * step + sin(theta) * sd. + temp_xl = np.zeros(n) + temp_xu = np.zeros(n) + temp_xl[free_bd] = ( + step[free_bd] ** 2.0 + sd[free_bd] ** 2.0 - xl[free_bd] ** 2.0 + ) + temp_xu[free_bd] = ( + step[free_bd] ** 2.0 + sd[free_bd] ** 2.0 - xu[free_bd] ** 2.0 + ) + temp_xl[temp_xl > 0.0] = ( + np.sqrt(temp_xl[temp_xl > 0.0]) - sd[temp_xl > 0.0] + ) + temp_xu[temp_xu > 0.0] = ( + np.sqrt(temp_xu[temp_xu > 0.0]) + sd[temp_xu > 0.0] + ) + dist_xl = np.maximum(step - xl, 0.0) + dist_xu = np.maximum(xu - step, 0.0) + i_xl = temp_xl > TINY * dist_xl + i_xu = temp_xu > TINY * dist_xu + all_t_xl = np.ones(n) + all_t_xu = np.ones(n) + all_t_xl[i_xl] = np.minimum( + all_t_xl[i_xl], + dist_xl[i_xl] / temp_xl[i_xl], + ) + all_t_xu[i_xu] = np.minimum( + all_t_xu[i_xu], + dist_xu[i_xu] / temp_xu[i_xu], + ) + t_xl = np.min(all_t_xl) + t_xu = np.min(all_t_xu) + t_bd = min(t_xl, t_xu) + + # For a range of equally spaced values of tan(0.5 * theta), + # calculate the reduction in the objective function that would be + # obtained by accepting the corresponding angle. + n_samples = 20 + n_samples = int((n_samples - 3) * t_bd + 3) + t_samples = np.linspace(t_bd / n_samples, t_bd, n_samples) + resid_ub = np.maximum(aub @ step - bub, 0.0) + resid_eq = aeq @ step - beq + step_proj = np.copy(step) + step_proj[~free_bd] = 0.0 + all_reduct = np.empty(n_samples) + for i in range(n_samples): + sin_value = 2.0 * t_samples[i] / (1.0 + t_samples[i] ** 2.0) + step_alt = np.clip( + step + sin_value * (sd - t_samples[i] * step_proj), + xl, + xu, + ) + resid_ub_alt = np.maximum(aub @ step_alt - bub, 0.0) + resid_eq_alt = aeq @ step_alt - beq + all_reduct[i] = 0.5 * ( + resid_ub @ resid_ub + + resid_eq @ resid_eq + - resid_ub_alt @ resid_ub_alt + - resid_eq_alt @ resid_eq_alt + ) + if np.all(all_reduct <= 0.0): + # No reduction in the objective function is obtained. + break + + # Accept the angle that provides the largest reduction in the + # objective function, and update the iterate. + i_max = np.argmax(all_reduct) + cos_value = (1.0 - t_samples[i_max] ** 2.0) / ( + 1.0 + t_samples[i_max] ** 2.0 + ) + sin_value = (2.0 * t_samples[i_max] + / (1.0 + t_samples[i_max] ** 2.0)) + step[free_bd] = cos_value * step[free_bd] + sin_value * sd[free_bd] + grad = aub.T @ np.maximum(aub @ step - bub, 0.0) + aeq.T @ ( + aeq @ step - beq + ) + reduct += all_reduct[i_max] + + # If the above angle is restricted by bound constraints, add them + # to the working set, and restart the alternative iteration. + # Otherwise, the calculations are terminated. + if t_bd < 1.0 and i_max == n_samples - 1: + if t_xl <= t_bd: + i_new = _argmin(all_t_xl) + step[i_new] = xl[i_new] + free_bd[i_new] = False + if t_xu <= t_bd: + i_new = _argmin(all_t_xu) + step[i_new] = xu[i_new] + free_bd[i_new] = False + else: + break + + # Ensure that the alternative iteration improves the objective + # function. + resid_ub = np.maximum(aub @ step - bub, 0.0) + resid_ub_base = np.maximum(aub @ step_base - bub, 0.0) + resid_eq = aeq @ step - beq + resid_eq_base = aeq @ step_base - beq + if ( + resid_ub @ resid_ub + resid_eq @ resid_eq + > resid_ub_base @ resid_ub_base + resid_eq_base @ resid_eq_base + ): + step = step_base + + if debug: + assert np.all(xl <= step) + assert np.all(step <= xu) + assert np.linalg.norm(step) < 1.1 * delta + return step + + +def qr_tangential_byrd_omojokun(aub, aeq, free_xl, free_xu, free_ub): + n = free_xl.size + identity = np.eye(n) + q, r, _ = qr( + np.block( + [ + [aeq], + [aub[~free_ub, :]], + [-identity[~free_xl, :]], + [identity[~free_xu, :]], + ] + ).T, + pivoting=True, + ) + n_act = np.count_nonzero( + np.abs(np.diag(r)) + >= 10.0 + * EPS + * n + * np.linalg.norm(r[: np.min(r.shape), : np.min(r.shape)], axis=0) + ) + return n_act, q + + +def qr_normal_byrd_omojokun(aub, free_xl, free_xu, free_slack, free_ub): + m_linear_ub, n = aub.shape + identity_n = np.eye(n) + identity_m = np.eye(m_linear_ub) + q, r, _ = qr( + np.block( + [ + [ + aub[~free_ub, :], + -identity_m[~free_ub, :], + ], + [ + np.zeros((m_linear_ub - np.count_nonzero(free_slack), n)), + -identity_m[~free_slack, :], + ], + [ + -identity_n[~free_xl, :], + np.zeros((n - np.count_nonzero(free_xl), m_linear_ub)), + ], + [ + identity_n[~free_xu, :], + np.zeros((n - np.count_nonzero(free_xu), m_linear_ub)), + ], + ] + ).T, + pivoting=True, + ) + n_act = np.count_nonzero( + np.abs(np.diag(r)) + >= 10.0 + * EPS + * (n + m_linear_ub) + * np.linalg.norm(r[: np.min(r.shape), : np.min(r.shape)], axis=0) + ) + return n_act, q + + +def _alpha_tr(step, sd, delta): + step_sd = step @ sd + sd_sq = sd @ sd + dist_tr_sq = delta**2.0 - step @ step + temp = np.sqrt(max(step_sd**2.0 + sd_sq * dist_tr_sq, 0.0)) + if step_sd <= 0.0 and sd_sq > TINY * abs(temp - step_sd): + alpha_tr = max((temp - step_sd) / sd_sq, 0.0) + elif abs(temp + step_sd) > TINY * dist_tr_sq: + alpha_tr = max(dist_tr_sq / (temp + step_sd), 0.0) + else: + raise ZeroDivisionError + return alpha_tr + + +def _argmax(x): + return np.flatnonzero(x >= np.max(x)) + + +def _argmin(x): + return np.flatnonzero(x <= np.min(x)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..fe6b4841ddff3a04bda5cbff744e30681b6963b9 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/__init__.py @@ -0,0 +1,18 @@ +from .exceptions import ( + MaxEvalError, + TargetSuccess, + CallbackSuccess, + FeasibleSuccess, +) +from .math import get_arrays_tol, exact_1d_array +from .versions import show_versions + +__all__ = [ + "MaxEvalError", + "TargetSuccess", + "CallbackSuccess", + "FeasibleSuccess", + "get_arrays_tol", + "exact_1d_array", + "show_versions", +] diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1ea44e3897c10e82152625cce7ce1cbf918616bc Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/__pycache__/exceptions.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/__pycache__/exceptions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d30f066cdddec3d77c4d784c465ed008a87f1f67 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/__pycache__/exceptions.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/__pycache__/math.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/__pycache__/math.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f90cddcad58a3e60bfb5dfed84f968cf6190e562 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/__pycache__/math.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/__pycache__/versions.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/__pycache__/versions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fd24d2e38835c95f27b849446091297548039fb2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/__pycache__/versions.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/exceptions.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/exceptions.py new file mode 100644 index 0000000000000000000000000000000000000000..c85094894f378a8e3934ad109ea6166e33e4366b --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/exceptions.py @@ -0,0 +1,22 @@ +class MaxEvalError(Exception): + """ + Exception raised when the maximum number of evaluations is reached. + """ + + +class TargetSuccess(Exception): + """ + Exception raised when the target value is reached. + """ + + +class CallbackSuccess(StopIteration): + """ + Exception raised when the callback function raises a ``StopIteration``. + """ + + +class FeasibleSuccess(Exception): + """ + Exception raised when a feasible point of a feasible problem is found. + """ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/math.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/math.py new file mode 100644 index 0000000000000000000000000000000000000000..1b16ae98a0df38752815f5a69d56da20f856f9f9 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/math.py @@ -0,0 +1,77 @@ +import numpy as np + + +EPS = np.finfo(float).eps + + +def get_arrays_tol(*arrays): + """ + Get a relative tolerance for a set of arrays. + + Parameters + ---------- + *arrays: tuple + Set of `numpy.ndarray` to get the tolerance for. + + Returns + ------- + float + Relative tolerance for the set of arrays. + + Raises + ------ + ValueError + If no array is provided. + """ + if len(arrays) == 0: + raise ValueError("At least one array must be provided.") + size = max(array.size for array in arrays) + weight = max( + np.max(np.abs(array[np.isfinite(array)]), initial=1.0) + for array in arrays + ) + return 10.0 * EPS * max(size, 1.0) * weight + + +def exact_1d_array(x, message): + """ + Preprocess a 1-dimensional array. + + Parameters + ---------- + x : array_like + Array to be preprocessed. + message : str + Error message if `x` cannot be interpreter as a 1-dimensional array. + + Returns + ------- + `numpy.ndarray` + Preprocessed array. + """ + x = np.atleast_1d(np.squeeze(x)).astype(float) + if x.ndim != 1: + raise ValueError(message) + return x + + +def exact_2d_array(x, message): + """ + Preprocess a 2-dimensional array. + + Parameters + ---------- + x : array_like + Array to be preprocessed. + message : str + Error message if `x` cannot be interpreter as a 2-dimensional array. + + Returns + ------- + `numpy.ndarray` + Preprocessed array. + """ + x = np.atleast_2d(x).astype(float) + if x.ndim != 2: + raise ValueError(message) + return x diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/versions.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/versions.py new file mode 100644 index 0000000000000000000000000000000000000000..94a0f8f5cef626354f40901cbe06a84287291c1c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/cobyqa/utils/versions.py @@ -0,0 +1,67 @@ +import os +import platform +import sys +from importlib.metadata import PackageNotFoundError, version + + +def _get_sys_info(): + """ + Get useful system information. + + Returns + ------- + dict + Useful system information. + """ + return { + "python": sys.version.replace(os.linesep, " "), + "executable": sys.executable, + "machine": platform.platform(), + } + + +def _get_deps_info(): + """ + Get the versions of the dependencies. + + Returns + ------- + dict + Versions of the dependencies. + """ + deps = ["cobyqa", "numpy", "scipy", "setuptools", "pip"] + deps_info = {} + for module in deps: + try: + deps_info[module] = version(module) + except PackageNotFoundError: + deps_info[module] = None + return deps_info + + +def show_versions(): + """ + Display useful system and dependencies information. + + When reporting issues, please include this information. + """ + print("System settings") + print("---------------") + sys_info = _get_sys_info() + print( + "\n".join( + f"{k:>{max(map(len, sys_info.keys())) + 1}}: {v}" + for k, v in sys_info.items() + ) + ) + + print() + print("Python dependencies") + print("-------------------") + deps_info = _get_deps_info() + print( + "\n".join( + f"{k:>{max(map(len, deps_info.keys())) + 1}}: {v}" + for k, v in deps_info.items() + ) + ) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..577e1d266162d70023cdee4cc0bfe72ce0796712 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/__init__.py @@ -0,0 +1,212 @@ +# Bounds may appear unused in this file but we need to import it to make it available to the user +from scipy.optimize import NonlinearConstraint, LinearConstraint, Bounds +from .common._nonlinear_constraints import process_nl_constraints +from .common._linear_constraints import ( + combine_multiple_linear_constraints, + separate_LC_into_eq_and_ineq, +) +from .common._bounds import process_bounds +from enum import Enum +from .common._project import _project +from .common.linalg import get_arrays_tol +from .cobyla.cobyla import cobyla +import numpy as np +from collections.abc import Iterable + + +class ConstraintType(Enum): + LINEAR_OBJECT = 5 + NONLINEAR_OBJECT = 10 + LINEAR_DICT = 15 + NONLINEAR_DICT = 20 + + +def get_constraint_type(constraint): + if isinstance(constraint, dict) and ("A" in constraint) and ("lb" in constraint) and ("ub" in constraint): + return ConstraintType.LINEAR_DICT + elif isinstance(constraint, dict) and ("fun" in constraint) and ("lb" in constraint) and ("ub" in constraint): + return ConstraintType.NONLINEAR_DICT + elif hasattr(constraint, "A") and hasattr(constraint, "lb") and hasattr(constraint, "ub"): + return ConstraintType.LINEAR_OBJECT + elif hasattr(constraint, "fun") and hasattr(constraint, "lb") and hasattr(constraint, "ub"): + return ConstraintType.NONLINEAR_OBJECT + else: + raise ValueError(f"Constraint type {type(constraint)} not recognized") + + +def process_constraints(constraints): + # First throw it back if it's an empty tuple + if not constraints: + return None, None + # Next figure out if it's a list of constraints or a single constraint + # If it's a single constraint, make it a list, and then the remaining logic + # doesn't have to change + if not isinstance(constraints, Iterable): + constraints = [constraints] + + # Separate out the linear and nonlinear constraints + linear_constraints = [] + nonlinear_constraints = [] + for constraint in constraints: + constraint_type = get_constraint_type(constraint) + if constraint_type is ConstraintType.LINEAR_OBJECT: + linear_constraints.append(constraint) + elif constraint_type is ConstraintType.NONLINEAR_OBJECT: + nonlinear_constraints.append(constraint) + elif constraint_type == ConstraintType.LINEAR_DICT: + linear_constraints.append(LinearConstraint(constraint["A"], constraint["lb"], constraint["ub"])) + elif constraint_type == ConstraintType.NONLINEAR_DICT: + nonlinear_constraints.append(NonlinearConstraint(constraint["fun"], constraint["lb"], constraint["ub"])) + else: + raise ValueError("Constraint type not recognized") + + if len(nonlinear_constraints) > 0: + nonlinear_constraint_function = process_nl_constraints(nonlinear_constraints) + else: + nonlinear_constraint_function = None + + # Determine if we have multiple linear constraints, just 1, or none, and process accordingly + if len(linear_constraints) > 1: + linear_constraint = combine_multiple_linear_constraints(linear_constraints) + elif len(linear_constraints) == 1: + linear_constraint = linear_constraints[0] + else: + linear_constraint = None + + return linear_constraint, nonlinear_constraint_function + + +def minimize(fun, x0, args=(), method=None, bounds=None, constraints=(), callback=None, options=None): + + linear_constraint, nonlinear_constraint_function = process_constraints(constraints) + + options = {'quiet': True} if options is None else options + quiet = options.get("quiet", True) + + if method is None: + if nonlinear_constraint_function is not None: + if not quiet: print("Nonlinear constraints detected, applying COBYLA") + method = "cobyla" + elif linear_constraint is not None: + if not quiet: print("Linear constraints detected without nonlinear constraints, applying LINCOA") + method = "lincoa" + elif bounds is not None: + if not quiet: print("Bounds without linear or nonlinear constraints detected, applying BOBYQA") + method = "bobyqa" + else: + if not quiet: print("No bounds or constraints detected, applying NEWUOA") + method = "newuoa" + else: + # Raise some errors if methods were called with inappropriate options + method = method.lower() + if method not in ('newuoa', 'uobyqa', 'bobyqa', 'cobyla', 'lincoa'): + raise ValueError(f"Method must be one of NEWUOA, UOBYQA, BOBYQA, COBYLA, or LINCOA, not '{method}'") + if method != "cobyla" and nonlinear_constraint_function is not None: + raise ValueError("Nonlinear constraints were provided for an algorithm that cannot handle them") + if method not in ("cobyla", "lincoa") and linear_constraint is not None: + raise ValueError("Linear constraints were provided for an algorithm that cannot handle them") + if method not in ("cobyla", "bobyqa", "lincoa") and bounds is not None: + raise ValueError("Bounds were provided for an algorithm that cannot handle them") + + # Try to get the length of x0. If we can't that likely means it's a scalar, and + # in that case we turn it into an array and wrap the original function so that it + # can accept an array and return a scalar. + try: + lenx0 = len(x0) + except TypeError: + x0 = np.array([x0]) + original_scalar_fun = fun + def scalar_fun(x): + return original_scalar_fun(x[0], *args) + fun = scalar_fun + lenx0 = 1 + + lb, ub = process_bounds(bounds, lenx0) + + # Check which variables are fixed and eliminate them from the problem. + # Save the indices and values so that we can call the original function with + # an array of the appropriate size, and so that we can add the fixed values to the + # result when COBYLA returns. + tol = get_arrays_tol(lb, ub) + _fixed_idx = ( + (lb <= ub) + & (np.abs(lb - ub) < tol) + ) + if any(_fixed_idx): + _fixed_values = 0.5 * ( + lb[_fixed_idx] + ub[_fixed_idx] + ) + _fixed_values = np.clip( + _fixed_values, + lb[_fixed_idx], + ub[_fixed_idx], + ) + x0 = x0[~_fixed_idx] + lb = lb[~_fixed_idx] + ub = ub[~_fixed_idx] + original_fun = fun + def fixed_fun(x): + newx = np.zeros(lenx0) + newx[_fixed_idx] = _fixed_values + newx[~_fixed_idx] = x + return original_fun(newx, *args) + fun = fixed_fun + + + # Project x0 onto the feasible set + if nonlinear_constraint_function is None: + result = _project(x0, lb, ub, {"linear": linear_constraint, "nonlinear": None}) + x0 = result.x + + if linear_constraint is not None: + A_eq, b_eq, A_ineq, b_ineq = separate_LC_into_eq_and_ineq(linear_constraint) + else: + A_eq, b_eq, A_ineq, b_ineq = None, None, None, None + + if nonlinear_constraint_function is not None: + # If there is a nonlinear constraint function, we will call COBYLA, which needs the number of nonlinear + # constraints (m_nlcon). In order to get this number we need to evaluate the constraint function at x0. + # The constraint value at x0 (nlconstr0) is not discarded but passed down to the Fortran backend, as its + # evaluation is assumed to be expensive. We also evaluate the objective function at x0 and pass the result + # (f0) down to the Fortran backend, which expects nlconstr0 and f0 to be provided in sync. + def calcfc(x): + f = fun(x, *args) + nlconstr = nonlinear_constraint_function(x) + return f, nlconstr + else: + def calcfc(x): + f = fun(x, *args) + constr = np.zeros(0) + return f, constr + + f0, nlconstr0 = calcfc(x0) + + if 'quiet' in options: + del options['quiet'] + + if 'maxfev' in options: + options['maxfun'] = options['maxfev'] + del options['maxfev'] + + result = cobyla( + calcfc, + len(nlconstr0), + x0, + A_ineq, + b_ineq, + A_eq, + b_eq, + lb, + ub, + f0=f0, + nlconstr0=nlconstr0, + callback=callback, + **options + ) + + if any(_fixed_idx): + newx = np.zeros(lenx0) + newx[_fixed_idx] = _fixed_values + newx[~_fixed_idx] = result.x + result.x = newx + return result diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..886d2cff5ca562e57e9380177b05cb4a14a55d9f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..150789be00ed736f56aabdc3c4733e6c21ed563b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/cobyla.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/cobyla.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7782ca6ffc28f554f9bf6f29d7eaf455c70dbf5a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/cobyla.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/cobylb.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/cobylb.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e79640896cdff6483672e237286d8bb63593b461 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/cobylb.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/geometry.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/geometry.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f00369ab8e9b3a0b22d2d22418c27c6bb6c4cb51 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/geometry.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/initialize.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/initialize.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..76996550024696de253e5cc2351776c85c0f4dac Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/initialize.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/trustregion.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/trustregion.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0e7b534091709c1cc0ea6393285952ec50ef36ae Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/trustregion.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/update.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/update.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a38a6a6da7418a9aaa2fcedf08d84f99159dbf07 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/__pycache__/update.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/cobyla.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/cobyla.py new file mode 100644 index 0000000000000000000000000000000000000000..11772a249e71ea23663b4d78479cd3792e1e7c43 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/cobyla.py @@ -0,0 +1,559 @@ +''' +This module provides Powell's COBYLA algorithm. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. + +N.B.: + +1. The modern-Fortran reference implementation in PRIMA contains bug fixes and improvements over the +original Fortran 77 implementation by Powell. Consequently, the PRIMA implementation behaves differently +from the original Fortran 77 implementation by Powell. Therefore, it is important to point out that +you are using PRIMA rather than the original solvers if you want your results to be reproducible. + +2. Compared to Powell's Fortran 77 implementation, the modern-Fortran implementation and hence any +faithful translation like this one generally produce better solutions with fewer function evaluations, +making them preferable for applications with expensive function evaluations. However, if function +evaluations are not the dominant cost in your application, the Fortran 77 solvers are likely to be +faster, as they are more efficient in terms of memory usage and flops thanks to the careful and +ingenious (but unmaintained and unmaintainable) implementation by Powell. + +See the PRIMA documentation (www.libprima.net) for more information. +''' + +from ..common.evaluate import evaluate, moderatex, moderatef, moderatec +from ..common.consts import (EPS, RHOBEG_DEFAULT, RHOEND_DEFAULT, CTOL_DEFAULT, + CWEIGHT_DEFAULT, FTARGET_DEFAULT, IPRINT_DEFAULT, + MAXFUN_DIM_DEFAULT, DEBUGGING, BOUNDMAX, + ETA1_DEFAULT, ETA2_DEFAULT, GAMMA1_DEFAULT, + GAMMA2_DEFAULT) +from ..common.preproc import preproc +from ..common.present import present +from ..common.linalg import matprod +from .cobylb import cobylb +import numpy as np +from dataclasses import dataclass +from copy import copy + + +@dataclass +class COBYLAResult: + x: np.ndarray + f: float + constr: np.ndarray + cstrv: float + nf: int + xhist: np.ndarray | None + fhist: np.ndarray | None + chist: np.ndarray | None + conhist: np.ndarray | None + info: int + + +def cobyla(calcfc, m_nlcon, x, Aineq=None, bineq=None, Aeq=None, beq=None, + xl=None, xu=None, f0=None, nlconstr0=None, rhobeg=None, rhoend=None, + ftarget=FTARGET_DEFAULT, ctol=CTOL_DEFAULT, cweight=CWEIGHT_DEFAULT, + maxfun=None, iprint=IPRINT_DEFAULT, eta1=None, eta2=None, + gamma1=GAMMA1_DEFAULT, gamma2=GAMMA2_DEFAULT, maxhist=None, maxfilt=2000, + callback=None): + """ + Among all the arguments, only CALCFC, M_NLCON, and X are obligatory. The others are + OPTIONAL and you can neglect them unless you are familiar with the algorithm. Any + unspecified optional input will take the default value detailed below. For + instance, we may invoke the solver as follows. + + # First define CALCFC, M_NLCON, and X, and then do the following. + result = cobyla(calcfc, m_nlcon, x) + + or + + # First define CALCFC, M_NLCON, X, Aineq, and Bineq, and then do the following. + result = cobyla(calcfc, m_nlcon, x, Aineq=Aineq, bineq=bineq, rhobeg=1.0e0, + rhoend=1.0e-6) + + #################################################################################### + # IMPORTANT NOTICE: The user must set M_NLCON correctly to the number of nonlinear + # constraints, namely the size of NLCONSTR introduced below. Set it to 0 if there + # is no nonlinear constraint. + #################################################################################### + + See examples/cobyla/cobyla_example.py for a concrete example. + + A detailed introduction to the arguments is as follows. + + #################################################################################### + # INPUTS + #################################################################################### + + CALCFC + Input, function. + f, nlconstr = CALCFC(X) should evaluate the objective function and nonlinear + constraints at the given vector X; it should return a tuple consisting of the + objective function value and the nonlinear constraint value. It must be provided + by the user, and its definition must conform to the following interface: + #-------------------------------------------------------------------------# + def calcfc(x): + f = 0.0 + nlconstr = np.zeros(m_nlcon) + return f, nlconstr + #-------------------------------------------------------------------------# + + M_NLCON + Input, scalar. + M_NLCON must be set to the number of nonlinear constraints, namely the size of + NLCONSTR(X). + N.B.: + 1. Why don't we define M_NLCON as optional and default it to 0 when it is absent? + This is because we need to allocate memory for CONSTR_LOC using M_NLCON. To + ensure that the size of CONSTR_LOC is correct, we require the user to specify + M_NLCON explicitly. + + X + Input, vector. + As an input, X should be an N-dimensional vector that contains the starting + point, N being the dimension of the problem. + + Aineq, Bineq + Input, matrix of size [Mineq, N] and vector of size Mineq unless they are both + empty, default: None and None. + Aineq and Bineq represent the linear inequality constraints: Aineq*X <= Bineq. + + Aeq, Beq + Input, matrix of size [Meq, N] and vector of size Meq unless they are both + empty, default: None and None. + Aeq and Beq represent the linear equality constraints: Aeq*X = Beq. + + XL, XU + Input, vectors of size N unless they are both None, default: None and None. + XL is the lower bound for X. If XL is None, X has no + lower bound. Any entry of XL that is NaN or below -BOUNDMAX will be taken as + -BOUNDMAX, which effectively means there is no lower bound for the corresponding + entry of X. The value of BOUNDMAX is 0.25*HUGE(X), which is about 8.6E37 for + single precision and 4.5E307 for double precision. XU is similar. + + F0 + Input, scalar. + F0, if present, should be set to the objective function value of the starting X. + + NLCONSTR0 + Input, vector. + NLCONSTR0, if present, should be set to the nonlinear constraint value at the + starting X; in addition, SIZE(NLCONSTR0) must be M_NLCON, or the solver will + abort. + + RHOBEG, RHOEND + Inputs, scalars, default: RHOBEG = 1, RHOEND = 10^-6. RHOBEG and RHOEND must be + set to the initial and final values of a trust-region radius, both being positive + and RHOEND <= RHOBEG. Typically RHOBEG should be about one tenth of the greatest + expected change to a variable, and RHOEND should indicate the accuracy that is + required in the final values of the variables. + + FTARGET + Input, scalar, default: -Inf. + FTARGET is the target function value. The algorithm will terminate when a + feasible point with a function value <= FTARGET is found. + + CTOL + Input, scalar, default: sqrt(machine epsilon). + CTOL is the tolerance of constraint violation. X is considered feasible if + CSTRV(X) <= CTOL. + N.B.: + 1. CTOL is absolute, not relative. + 2. CTOL is used only when selecting the returned X. It does not affect the + iterations of the algorithm. + + CWEIGHT + Input, scalar, default: CWEIGHT_DFT defined in common/consts.py. + CWEIGHT is the weight that the constraint violation takes in the selection of the + returned X. + + MAXFUN + Input, integer scalar, default: MAXFUN_DIM_DFT*N with MAXFUN_DIM_DFT defined in + common/consts.py. MAXFUN is the maximal number of calls of CALCFC. + + IPRINT + Input, integer scalar, default: 0. + The value of IPRINT should be set to 0, 1, -1, 2, -2, 3, or -3, which controls + how much information will be printed during the computation: + 0: there will be no printing; + 1: a message will be printed to the screen at the return, showing the best vector + of variables found and its objective function value; + 2: in addition to 1, each new value of RHO is printed to the screen, with the + best vector of variables so far and its objective function value; each new + value of CPEN is also printed; + 3: in addition to 2, each function evaluation with its variables will be printed + to the screen; -1, -2, -3: the same information as 1, 2, 3 will be printed, + not to the screen but to a file named COBYLA_output.txt; the file will be + created if it does not exist; the new output will be appended to the end of + this file if it already exists. + Note that IPRINT = +/-3 can be costly in terms of time and/or space. + + ETA1, ETA2, GAMMA1, GAMMA2 + Input, scalars, default: ETA1 = 0.1, ETA2 = 0.7, GAMMA1 = 0.5, and GAMMA2 = 2. + ETA1, ETA2, GAMMA1, and GAMMA2 are parameters in the updating scheme of the + trust-region radius detailed in the subroutine TRRAD in trustregion.py. Roughly + speaking, the trust-region radius is contracted by a factor of GAMMA1 when the + reduction ratio is below ETA1, and enlarged by a factor of GAMMA2 when the + reduction ratio is above ETA2. It is required that 0 < ETA1 <= ETA2 < 1 and + 0 < GAMMA1 < 1 < GAMMA2. Normally, ETA1 <= 0.25. It is NOT advised to set + ETA1 >= 0.5. + + MAXFILT + Input, scalar. + MAXFILT is a nonnegative integer indicating the maximal length of the filter used + for selecting the returned solution; default: MAXFILT_DFT (a value lower than + MIN_MAXFILT is not recommended); + see common/consts.py for the definitions of MAXFILT_DFT and MIN_MAXFILT. + + CALLBACK + Input, function to report progress and optionally request termination. + + + #################################################################################### + # OUTPUTS + #################################################################################### + + The output is a single data structure, COBYLAResult, with the following fields: + + X + Output, vector. + As an output, X will be set to an approximate minimizer. + + F + Output, scalar. + F will be set to the objective function value of X at exit. + + CONSTR + Output, vector. + CONSTR will be set to the constraint value of X at exit. + + CSTRV + Output, scalar. + CSTRV will be set to the constraint violation of X at exit, i.e., + max([0, XL - X, X - XU, Aineq*X - Bineq, ABS(Aeq*X -Beq), NLCONSTR(X)]). + + NF + Output, scalar. + NF will be set to the number of calls of CALCFC at exit. + + XHIST, FHIST, CHIST, CONHIST, MAXHIST + XHIST: Output, rank 2 array; + FHIST: Output, rank 1 array; + CHIST: Output, rank 1 array; + CONHIST: Output, rank 2 array; + MAXHIST: Input, scalar, default: MAXFUN + XHIST, if present, will output the history of iterates; FHIST, if present, will + output the history function values; CHIST, if present, will output the history of + constraint violations; CONHIST, if present, will output the history of constraint + values; MAXHIST should be a nonnegative integer, and XHIST/FHIST/CHIST/CONHIST + will output only the history of the last MAXHIST iterations. + Therefore, MAXHIST= 0 means XHIST/FHIST/CONHIST/CHIST will output + nothing, while setting MAXHIST = MAXFUN requests XHIST/FHIST/CHIST/CONHIST to + output all the history. If XHIST is present, its size at exit will be + (N, min(NF, MAXHIST)); if FHIST is present, its size at exit will be + min(NF, MAXHIST); if CHIST is present, its size at exit will be min(NF, MAXHIST); + if CONHIST is present, its size at exit will be (M, min(NF, MAXHIST)). + + IMPORTANT NOTICE: + Setting MAXHIST to a large value can be costly in terms of memory for large + problems. + MAXHIST will be reset to a smaller value if the memory needed exceeds MAXHISTMEM + defined in common/consts.py + Use *HIST with caution!!! (N.B.: the algorithm is NOT designed for large + problems). + + INFO + Output, scalar. + INFO is the exit flag. It will be set to one of the following values defined in + common/infos.py: + SMALL_TR_RADIUS: the lower bound for the trust region radius is reached; + FTARGET_ACHIEVED: the target function value is reached; + MAXFUN_REACHED: the objective function has been evaluated MAXFUN times; + MAXTR_REACHED: the trust region iteration has been performed MAXTR times (MAXTR = 2*MAXFUN); + NAN_INF_X: NaN or Inf occurs in X; + DAMAGING_ROUNDING: rounding errors are becoming damaging. + #--------------------------------------------------------------------------# + The following case(s) should NEVER occur unless there is a bug. + NAN_INF_F: the objective function returns NaN or +Inf; + NAN_INF_MODEL: NaN or Inf occurs in the model; + TRSUBP_FAILED: a trust region step failed to reduce the model + #--------------------------------------------------------------------------# + """ + + # Local variables + solver = "COBYLA" + srname = "COBYLA" + + # Sizes + mineq = len(bineq) if present(bineq) else 0 + meq = len(beq) if present(beq) else 0 + mxl = sum(xl > -BOUNDMAX) if present(xl) else 0 + mxu = sum(xu < BOUNDMAX) if present(xu) else 0 + mmm = mxu + mxl + 2*meq + mineq + m_nlcon + num_vars = len(x) + + # Preconditions + if DEBUGGING: + assert m_nlcon >= 0, f'{srname} M_NLCON >= 0' + assert num_vars >= 1, f'{srname} N >= 1' + + assert present(Aineq) == present(bineq), \ + f'{srname} Aineq and Bineq are both present or both absent' + if (present(Aineq)): + assert Aineq.shape == (mineq, num_vars), f'{srname} SIZE(Aineq) == [Mineq, N]' + + assert present(Aeq) == present(beq), \ + f'{srname} Aeq and Beq are both present or both absent' + if (present(Aeq)): + assert Aeq.shape == (meq, num_vars), f'{srname} SIZE(Aeq) == [Meq, N]' + + if (present(xl)): + assert len(xl) == num_vars, f'{srname} SIZE(XL) == N' + if (present(xu)): + assert len(xu) == num_vars, f'{srname} SIZE(XU) == N' + + + # N.B.: If NLCONSTR0 is present, then F0 must be present, and we assume that + # F(X0) = F0 even if F0 is NaN; if NLCONSTR0 is absent, then F0 must be either + # absent or NaN, both of which will be interpreted as F(X0) is not provided. + if present(nlconstr0): + assert present(f0), f'{srname} If NLCONSTR0 is present, then F0 is present' + if present(f0): + assert np.isnan(f0) or present(nlconstr0), \ + f'{srname} If F0 is present and not NaN, then NLCONSTR0 is present' + + + + # Exit if the size of NLCONSTR0 is inconsistent with M_NLCON. + if present(nlconstr0): + assert np.size(nlconstr0) == m_nlcon + + # Read the inputs. + + if xl is not None: + xl = copy(xl) + xl[np.isnan(xl)] = -BOUNDMAX + xl[xl < -BOUNDMAX] = -BOUNDMAX + + if xu is not None: + xu = copy(xu) + xu[np.isnan(xu)] = BOUNDMAX + xu[xu > BOUNDMAX] = BOUNDMAX + + # Wrap the linear and bound constraints into a single constraint: AMAT@X <= BVEC. + amat, bvec = get_lincon(Aeq, Aineq, beq, bineq, xl, xu) + + # Create constraint vector + constr = np.zeros(mmm) + + # Set [F_LOC, CONSTR_LOC] to [F(X0), CONSTR(X0)] after evaluating the latter if + # needed. In this way, COBYLB only needs one interface. + # N.B.: Due to the preconditions above, there are two possibilities for F0 and + # NLCONSTR0. + # If NLCONSTR0 is present, then F0 must be present, and we assume that F(X0) = F0 + # even if F0 is NaN. + # If NLCONSTR0 is absent, then F0 must be either absent or NaN, both of which will + # be interpreted as F(X0) is not provided and we have to evaluate F(X0) and + # NLCONSTR(X0) now. + if (present(f0) and present(nlconstr0) and all(np.isfinite(x))): + f = moderatef(f0) + if amat is not None: + constr[:mmm - m_nlcon] = moderatec(matprod(amat, x) - bvec) + constr[mmm - m_nlcon:] = moderatec(nlconstr0) + else: + x = moderatex(x) + f, constr = evaluate(calcfc, x, m_nlcon, amat, bvec) + constr[:mmm - m_nlcon] = moderatec(constr[:mmm - m_nlcon]) + # N.B.: Do NOT call FMSG, SAVEHIST, or SAVEFILT for the function/constraint evaluation at X0. + # They will be called during the initialization, which will read the function/constraint at X0. + cstrv = max(np.append(0, constr)) + + + # If RHOBEG is present, use it; otherwise, RHOBEG takes the default value for + # RHOBEG, taking the value of RHOEND into account. Note that RHOEND is considered + # only if it is present and it is VALID (i.e., finite and positive). The other + # inputs are read similarly. + if present(rhobeg): + rhobeg = rhobeg + elif present(rhoend) and np.isfinite(rhoend) and rhoend > 0: + rhobeg = max(10 * rhoend, RHOBEG_DEFAULT) + else: + rhobeg = RHOBEG_DEFAULT + + if present(rhoend): + rhoend = rhoend + elif rhobeg > 0: + rhoend = max(EPS, min(RHOEND_DEFAULT/RHOBEG_DEFAULT * rhobeg, RHOEND_DEFAULT)) + else: + rhoend = RHOEND_DEFAULT + + maxfun = maxfun if present(maxfun) else MAXFUN_DIM_DEFAULT * num_vars + + if present(eta1): + eta1 = eta1 + elif present(eta2) and 0 < eta2 < 1: + eta1 = max(EPS, eta2 / 7) + else: + eta1 = ETA1_DEFAULT + + if present(eta2): + eta2 = eta2 + elif 0 < eta1 < 1: + eta2 = (eta1 + 2) / 3 + else: + eta2 = ETA2_DEFAULT + + maxhist = ( + maxhist + if present(maxhist) + else max(maxfun, num_vars + 2, MAXFUN_DIM_DEFAULT * num_vars) + ) + + # Preprocess the inputs in case some of them are invalid. It does nothing if all + # inputs are valid. + ( + iprint, + maxfun, + maxhist, + ftarget, + rhobeg, + rhoend, + npt, # Unused in COBYLA + maxfilt, + ctol, + cweight, + eta1, + eta2, + gamma1, + gamma2, + _x0, # Unused in COBYLA + ) = preproc( + solver, + num_vars, + iprint, + maxfun, + maxhist, + ftarget, + rhobeg, + rhoend, + num_constraints=mmm, + maxfilt=maxfilt, + ctol=ctol, + cweight=cweight, + eta1=eta1, + eta2=eta2, + gamma1=gamma1, + gamma2=gamma2, + is_constrained=(mmm > 0), + ) + + # Further revise MAXHIST according to MAXHISTMEM, and allocate memory for the history. + # In MATLAB/Python/Julia/R implementation, we should simply set MAXHIST = MAXFUN and initialize + # CHIST = NaN(1, MAXFUN), CONHIST = NaN(M, MAXFUN), FHIST = NaN(1, MAXFUN), XHIST = NaN(N, MAXFUN) + # if they are requested; replace MAXFUN with 0 for the history that is not requested. + # prehist(maxhist, num_vars, present(xhist), xhist_loc, present(fhist), fhist_loc, & + # & present(chist), chist_loc, m, present(conhist), conhist_loc) + + # call cobylb, which performs the real calculations + x, f, constr, cstrv, nf, xhist, fhist, chist, conhist, info = cobylb( + calcfc, + iprint, + maxfilt, + maxfun, + amat, + bvec, + ctol, + cweight, + eta1, + eta2, + ftarget, + gamma1, + gamma2, + rhobeg, + rhoend, + constr, + f, + x, + maxhist, + callback + ) + + return COBYLAResult(x, f, constr, cstrv, nf, xhist, fhist, chist, conhist, info) + + +def get_lincon(Aeq=None, Aineq=None, beq=None, bineq=None, xl=None, xu=None): + """ + This subroutine wraps the linear and bound constraints into a single constraint: + AMAT*X <= BVEC. + + N.B.: + + LINCOA normalizes the linear constraints so that each constraint has a gradient + of norm 1. However, COBYLA does not do this. + """ + + # Sizes + if Aeq is not None: + num_vars = Aeq.shape[1] + elif Aineq is not None: + num_vars = Aineq.shape[1] + elif xl is not None: + num_vars = len(xl) + elif xu is not None: + num_vars = len(xu) + else: + return None, None + + # Preconditions + if DEBUGGING: + assert Aineq is None or Aineq.shape == (len(bineq), num_vars) + assert Aeq is None or Aeq.shape == (len(beq), num_vars) + assert (xl is None or xu is None) or len(xl) == len(xu) == num_vars + + #====================# + # Calculation starts # + #====================# + + # Define the indices of the nontrivial bound constraints. + ixl = np.where(xl > -BOUNDMAX)[0] if xl is not None else None + ixu = np.where(xu < BOUNDMAX)[0] if xu is not None else None + + # Wrap the linear constraints. + # The bound constraint XL <= X <= XU is handled as two constraints: + # -X <= -XL, X <= XU. + # The equality constraint Aeq*X = Beq is handled as two constraints: + # -Aeq*X <= -Beq, Aeq*X <= Beq. + # N.B.: + # 1. The treatment of the equality constraints is naive. One may choose to + # eliminate them instead. + idmat = np.eye(num_vars) + amat = np.vstack([ + -idmat[ixl, :] if ixl is not None else np.empty((0, num_vars)), + idmat[ixu, :] if ixu is not None else np.empty((0, num_vars)), + -Aeq if Aeq is not None else np.empty((0, num_vars)), + Aeq if Aeq is not None else np.empty((0, num_vars)), + Aineq if Aineq is not None else np.empty((0, num_vars)) + ]) + bvec = np.hstack([ + -xl[ixl] if ixl is not None else np.empty(0), + xu[ixu] if ixu is not None else np.empty(0), + -beq if beq is not None else np.empty(0), + beq if beq is not None else np.empty(0), + bineq if bineq is not None else np.empty(0) + ]) + + amat = amat if amat.shape[0] > 0 else None + bvec = bvec if bvec.shape[0] > 0 else None + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert (amat is None and bvec is None) or amat.shape == (len(bvec), num_vars) + + return amat, bvec diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/cobylb.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/cobylb.py new file mode 100644 index 0000000000000000000000000000000000000000..91012c3b3b2bca1c8827db3c4e2b7245735d23c2 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/cobylb.py @@ -0,0 +1,714 @@ +''' +This module performs the major calculations of COBYLA. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +import numpy as np +from ..common.checkbreak import checkbreak_con +from ..common.consts import REALMAX, EPS, DEBUGGING, MIN_MAXFILT +from ..common.infos import INFO_DEFAULT, MAXTR_REACHED, DAMAGING_ROUNDING, \ + SMALL_TR_RADIUS, CALLBACK_TERMINATE +from ..common.evaluate import evaluate +from ..common.history import savehist +from ..common.linalg import isinv, matprod, inprod, norm, primasum, primapow2 +from ..common.message import fmsg, retmsg, rhomsg +from ..common.ratio import redrat +from ..common.redrho import redrho +from ..common.selectx import savefilt, selectx +from .update import updatepole, findpole, updatexfc +from .geometry import setdrop_tr, geostep +from .trustregion import trstlp, trrad +from .initialize import initxfc, initfilt + + +def cobylb(calcfc, iprint, maxfilt, maxfun, amat, bvec, ctol, cweight, eta1, eta2, + ftarget, gamma1, gamma2, rhobeg, rhoend, constr, f, x, maxhist, callback): + ''' + This subroutine performs the actual computations of COBYLA. + ''' + + # Outputs + xhist = [] + fhist = [] + chist = [] + conhist = [] + + # Local variables + solver = 'COBYLA' + A = np.zeros((np.size(x), np.size(constr))) # A contains the approximate gradient for the constraints + distsq = np.zeros(np.size(x) + 1) + # CPENMIN is the minimum of the penalty parameter CPEN for the L-infinity + # constraint violation in the merit function. Note that CPENMIN = 0 in Powell's + # implementation, which allows CPEN to be 0. Here, we take CPENMIN > 0 so that CPEN + # is always positive. This avoids the situation where PREREM becomes 0 when + # PREREF = 0 = CPEN. It brings two advantages as follows. + # 1. If the trust-region subproblem solver works correctly and the trust-region + # center is not optimal for the subproblem, then PREREM > 0 is guaranteed. This + # is because, in theory, PREREC >= 0 and MAX(PREREC, PREREF) > 0, and the + # definition of CPEN in GETCPEN ensures that PREREM > 0. + # 2. There is no need to revise ACTREM and PREREM when CPEN = 0 and F = FVAL(N+1) + # as in lines 312--314 of Powell's cobylb.f code. Powell's code revises ACTREM + # to CVAL(N + 1) - CSTRV and PREREM to PREREC in this case, which is crucial for + # feasibility problems. + cpenmin = EPS + + # Sizes + m_lcon = np.size(bvec) if bvec is not None else 0 + num_constraints = np.size(constr) + m_nlcon = num_constraints - m_lcon + num_vars = np.size(x) + + # Preconditions + if DEBUGGING: + assert abs(iprint) <= 3 + assert num_constraints >= m_lcon and m_lcon >= 0 + assert num_vars >= 1 + assert maxfun >= num_vars + 2 + assert rhobeg >= rhoend and rhoend > 0 + assert all(np.isfinite(x)) + assert 0 <= eta1 <= eta2 < 1 + assert 0 < gamma1 < 1 < gamma2 + assert 0 <= ctol + assert 0 <= cweight + assert 0 <= maxhist <= maxfun + assert amat is None or np.shape(amat) == (m_lcon, num_vars) + assert min(MIN_MAXFILT, maxfun) <= maxfilt <= maxfun + + #====================# + # Calculation starts # + #====================# + + # Initialize SIM, FVAL, CONMAT, and CVAL, together with the history. + # After the initialization, SIM[:, NUM_VARS] holds the vertex of the initial + # simplex with the smallest function value (regardless of the constraint + # violation), and SIM[:, :NUM_VARS] holds the displacements from the other vertices + # to SIM[:, NUM_VARS]. FVAL, CONMAT, and CVAL hold the function values, constraint + # values, and constraint violations on the vertices in the order corresponding to + # SIM. + evaluated, conmat, cval, sim, simi, fval, nf, subinfo = initxfc(calcfc, iprint, + maxfun, constr, amat, bvec, ctol, f, ftarget, rhobeg, x, + xhist, fhist, chist, conhist, maxhist) + + # Initialize the filter, including xfilt, ffilt, confilt, cfilt, and nfilt. + # N.B.: The filter is used only when selecting which iterate to return. It does not + # interfere with the iterations. COBYLA is NOT a filter method but a trust-region + # method based on an L-infinity merit function. Powell's implementation does not + # use a filter to select the iterate, possibly returning a suboptimal iterate. + cfilt = np.zeros(np.minimum(np.maximum(maxfilt, 1), maxfun)) + confilt = np.zeros((np.size(constr), np.size(cfilt))) + ffilt = np.zeros(np.size(cfilt)) + xfilt = np.zeros((np.size(x), np.size(cfilt))) + nfilt = initfilt(conmat, ctol, cweight, cval, fval, sim, evaluated, cfilt, confilt, + ffilt, xfilt) + + # Check whether to return due to abnormal cases that may occur during the initialization. + if subinfo != INFO_DEFAULT: + info = subinfo + # Return the best calculated values of the variables + # N.B: Selectx and findpole choose X by different standards, one cannot replace the other + kopt = selectx(ffilt[:nfilt], cfilt[:nfilt], cweight, ctol) + x = xfilt[:, kopt] + f = ffilt[kopt] + constr = confilt[:, kopt] + cstrv = cfilt[kopt] + # print a return message according to IPRINT. + retmsg(solver, info, iprint, nf, f, x, cstrv, constr) + # Postconditions + if DEBUGGING: + assert nf <= maxfun + assert np.size(x) == num_vars and not any(np.isnan(x)) + assert not (np.isnan(f) or np.isposinf(f)) + # assert np.size(xhist, 0) == n and np.size(xhist, 1) == maxxhist + # assert not any(np.isnan(xhist(:, 1:min(nf, maxxhist)))) + # The last calculated X can be Inf (finite + finite can be Inf numerically). + # assert np.size(fhist) == maxfhist + # assert not any(np.isnan(fhist(1:min(nf, maxfhist))) or np.isposinf(fhist(1:min(nf, maxfhist)))) + # assert np.size(conhist, 0) == m and np.size(conhist, 1) == maxconhist + # assert not any(np.isnan(conhist(:, 1:min(nf, maxconhist))) or np.isneginf(conhist(:, 1:min(nf, maxconhist)))) + # assert np.size(chist) == maxchist + # assert not any(chist(1:min(nf, maxchist)) < 0 or np.isnan(chist(1:min(nf, maxchist))) or np.isposinf(chist(1:min(nf, maxchist)))) + # nhist = minval([nf, maxfhist, maxchist]) + # assert not any(isbetter(fhist(1:nhist), chist(1:nhist), f, cstrv, ctol)) + return x, f, constr, cstrv, nf, xhist, fhist, chist, conhist, info + + + # Set some more initial values. + # We must initialize shortd, ratio, and jdrop_tr because these get defined on + # branches that are not guaranteed to be executed, but their values are used later. + # Our initialization of CPEN differs from Powell's in two ways. First, we use the + # ratio defined in (13) of Powell's COBYLA paper to initialize CPEN. Second, we + # impose CPEN >= CPENMIN > 0. Powell's code simply initializes CPEN to 0. + rho = rhobeg + delta = rhobeg + cpen = np.maximum(cpenmin, np.minimum(1.0E3, fcratio(conmat, fval))) # Powell's code: CPEN = ZERO + shortd = False + ratio = -1 + jdrop_tr = 0 + + # If DELTA <= GAMMA3*RHO after an update, we set DELTA to RHO. GAMMA3 must be less + # than GAMMA2. The reason is as follows. Imagine a very successful step with + # DNORM = the un-updated DELTA = RHO. The TRRAD will update DELTA to GAMMA2*RHO. + # If GAMMA3 >= GAMMA2, then DELTA will be reset to RHO, which is not reasonable as + # D is very successful. See paragraph two of Sec 5.2.5 in T. M. Ragonneau's thesis: + # "Model-Based Derivative-Free Optimization Methods and Software." According to + # test on 20230613, for COBYLA, this Powellful updating scheme of DELTA works + # slightly better than setting directly DELTA = max(NEW_DELTA, RHO). + gamma3 = np.maximum(1, np.minimum(0.75 * gamma2, 1.5)) + + # MAXTR is the maximal number of trust region iterations. Each trust-region + # iteration takes 1 or 2 function evaluations unless the trust-region step is short + # or the trust-region subproblem solver fails but the geometry step is not invoked. + # Thus the following MAXTR is unlikely to be reached. + maxtr = 10 * maxfun + info = MAXTR_REACHED + + # Begin the iterative procedure + # After solving a trust-region subproblem, we use three boolean variables to + # control the workflow. + # SHORTD - Is the trust-region trial step too short to invoke # a function + # evaluation? + # IMPROVE_GEO - Will we improve the model after the trust-region iteration? If yes, + # a geometry step will be taken, corresponding to the "Branch (Delta)" + # in the COBYLA paper. + # REDUCE_RHO - Will we reduce rho after the trust-region iteration? + # COBYLA never sets IMPROVE_GEO and REDUCE_RHO to True simultaneously. + for tr in range(maxtr): + # Increase the penalty parameter CPEN, if needed, so that + # PREREM = PREREF + CPEN * PREREC > 0. + # This is the first (out of two) update of CPEN, where CPEN increases or + # remains the same. + # N.B.: CPEN and the merit function PHI = FVAL + CPEN*CVAL are used in three + # places only. + # 1. In FINDPOLE/UPDATEPOLE, deciding the optimal vertex of the current simplex. + # 2. After the trust-region trial step, calculating the reduction ratio. + # 3. In GEOSTEP, deciding the direction of the geometry step. + # They do not appear explicitly in the trust-region subproblem, though the + # trust-region center (i.e. the current optimal vertex) is defined by them. + cpen = getcpen(amat, bvec, conmat, cpen, cval, delta, fval, rho, sim, simi) + + # Switch the best vertex of the current simplex to SIM[:, NUM_VARS]. + conmat, cval, fval, sim, simi, subinfo = updatepole(cpen, conmat, cval, fval, + sim, simi) + # Check whether to exit due to damaging rounding in UPDATEPOLE. + if subinfo == DAMAGING_ROUNDING: + info = subinfo + break # Better action to take? Geometry step, or simply continue? + + # Does the interpolation set have adequate geometry? It affects improve_geo and + # reduce_rho. + adequate_geo = all(primasum(primapow2(sim[:, :num_vars]), axis=0) <= 4 * primapow2(delta)) + + # Calculate the linear approximations to the objective and constraint functions. + # N.B.: TRSTLP accesses A mostly by columns, so it is more reasonable to save A + # instead of A^T. + # Zaikun 2023108: According to a test on 2023108, calculating G and + # A(:, M_LCON+1:M) by solving the linear systems SIM^T*G = FVAL(1:N)-FVAL(N+1) + # and SIM^T*A = CONMAT(:, 1:N)-CONMAT(:, N+1) does not seem to improve or worsen + # the performance of COBYLA in terms of the number of function evaluations. The + # system was solved by SOLVE in LINALG_MOD based on a QR factorization of SIM + # (not necessarily a good algorithm). No preconditioning or scaling was used. + g = matprod((fval[:num_vars] - fval[num_vars]), simi) + A[:, :m_lcon] = amat.T if amat is not None else amat + A[:, m_lcon:] = matprod((conmat[m_lcon:, :num_vars] - + np.tile(conmat[m_lcon:, num_vars], (num_vars, 1)).T), simi).T + + # Calculate the trust-region trial step d. Note that d does NOT depend on cpen. + d = trstlp(A, -conmat[:, num_vars], delta, g) + dnorm = min(delta, norm(d)) + + # Is the trust-region trial step short? N.B.: we compare DNORM with RHO, not + # DELTA. Powell's code especially defines SHORTD by SHORTD = (DNORM < 0.5 * + # RHO). In our tests 1/10 seems to work better than 1/2 or 1/4, especially for + # linearly constrained problems. Note that LINCOA has a slightly more + # sophisticated way of defining SHORTD, taking into account whether D causes a + # change to the active set. Should we try the same here? + shortd = (dnorm <= 0.1 * rho) + + # Predict the change to F (PREREF) and to the constraint violation (PREREC) due + # to D. We have the following in precise arithmetic. They may fail to hold due + # to rounding errors. + # 1. B[:NUM_CONSTRAINTS] = -CONMAT[:, NUM_VARS] and hence + # np.max(np.append(B[:NUM_CONSTRAINTS] - D@A[:, :NUM_CONSTRAINTS], 0)) is the + # L-infinity violation of the linearized constraints corresponding to D. When + # D=0, the violation is np.max(np.append(B[:NUM_CONSTRAINTS], 0)) = + # CVAL[NUM_VARS]. PREREC is the reduction of this violation achieved by D, + # which is nonnegative in theory; PREREC = 0 iff B[:NUM_CONSTRAINTS] <= 0, i.e. + # the trust-region center satisfies the linearized constraints. + # 2. PREREF may be negative or 0, but it is positive when PREREC = 0 and shortd + # is False + # 3. Due to 2, in theory, max(PREREC, PREREF) > 0 if shortd is False. + preref = -inprod(d, g) # Can be negative + prerec = cval[num_vars] - np.max(np.append(0, conmat[:, num_vars] + matprod(d, A))) + + # Evaluate PREREM, which is the predicted reduction in the merit function. + # In theory, PREREM >= 0 and it is 0 iff CPEN = 0 = PREREF. This may not be true + # numerically. + prerem = preref + cpen * prerec + trfail = not (prerem > 1.0E-6 * min(cpen, 1) * rho) + + if shortd or trfail: + # Reduce DELTA if D is short or if D fails to render PREREM > 0. The latter + # can only happen due to rounding errors. This seems quite important for + # performance + delta *= 0.1 + if delta <= gamma3 * rho: + delta = rho # set delta to rho when it is close to or below + else: + # Calculate the next value of the objective and constraint functions. + # If X is close to one of the points in the interpolation set, then we do + # not evaluate the objective and constraints at X, assuming them to have + # the values at the closest point. + # N.B.: If this happens, do NOT include X into the filter, as F and CONSTR + # are inaccurate. + x = sim[:, num_vars] + d + distsq[num_vars] = primasum(primapow2(x - sim[:, num_vars])) + distsq[:num_vars] = primasum(primapow2(x.reshape(num_vars, 1) - + (sim[:, num_vars].reshape(num_vars, 1) + sim[:, :num_vars])), axis=0) + j = np.argmin(distsq) + if distsq[j] <= primapow2(1e-4 * rhoend): + f = fval[j] + constr = conmat[:, j] + cstrv = cval[j] + else: + # Evaluate the objective and constraints at X, taking care of possible + # inf/nan values. + f, constr = evaluate(calcfc, x, m_nlcon, amat, bvec) + cstrv = np.max(np.append(0, constr)) + nf += 1 + # Save X, F, CONSTR, CSTRV into the history. + savehist(maxhist, x, xhist, f, fhist, cstrv, chist, constr, conhist) + # Save X, F, CONSTR, CSTRV into the filter. + nfilt, cfilt, ffilt, xfilt, confilt = savefilt(cstrv, ctol, cweight, f, + x, nfilt, cfilt, ffilt, + xfilt, constr, confilt) + + # Print a message about the function/constraint evaluation according to + # iprint + fmsg(solver, 'Trust region', iprint, nf, delta, f, x, cstrv, constr) + + # Evaluate ACTREM, which is the actual reduction in the merit function + actrem = (fval[num_vars] + cpen * cval[num_vars]) - (f + cpen * cstrv) + + # Calculate the reduction ratio by redrat, which hands inf/nan carefully + ratio = redrat(actrem, prerem, eta1) + + # Update DELTA. After this, DELTA < DNORM may hold. + # N.B.: + # 1. Powell's code uses RHO as the trust-region radius and updates it as + # follows. + # Reduce RHO to GAMMA1*RHO if ADEQUATE_GEO is TRUE and either SHORTD is + # TRUE or RATIO < ETA1, and then revise RHO to RHOEND if its new value is + # not more than GAMMA3*RHOEND; RHO remains unchanged in all other cases; + # in particular, RHO is never increased. + # 2. Our implementation uses DELTA as the trust-region radius, while using + # RHO as a lower bound for DELTA. DELTA is updated in a way that is + # typical for trust-region methods, and it is revised to RHO if its new + # value is not more than GAMMA3*RHO. RHO reflects the current resolution + # of the algorithm; its update is essentially the same as the update of + # RHO in Powell's code (see the definition of REDUCE_RHO below). Our + # implementation aligns with UOBYQA/NEWUOA/BOBYQA/LINCOA and improves the + # performance of COBYLA. + # 3. The same as Powell's code, we do not reduce RHO unless ADEQUATE_GEO is + # TRUE. This is also how Powell updated RHO in + # UOBYQA/NEWUOA/BOBYQA/LINCOA. What about we also use ADEQUATE_GEO == + # TRUE as a prerequisite for reducing DELTA? The argument would be that + # the bad (small) value of RATIO may be because of a bad geometry (and + # hence a bad model) rather than an improperly large DELTA, and it might + # be good to try improving the geometry first without reducing DELTA. + # However, according to a test on 20230206, it does not improve the + # performance if we skip the update of DELTA when ADEQUATE_GEO is FALSE + # and RATIO < 0.1. Therefore, we choose to update DELTA without checking + # ADEQUATE_GEO. + + delta = trrad(delta, dnorm, eta1, eta2, gamma1, gamma2, ratio) + if delta <= gamma3*rho: + delta = rho # Set delta to rho when it is close to or below. + + # Is the newly generated X better than the current best point? + ximproved = actrem > 0 # If ACTREM is NaN, then XIMPROVED should and will be False + + # Set JDROP_TR to the index of the vertex to be replaced with X. JDROP_TR = 0 means there + # is no good point to replace, and X will not be included into the simplex; in this case, + # the geometry of the simplex likely needs improvement, which will be handled below. + jdrop_tr = setdrop_tr(ximproved, d, delta, rho, sim, simi) + + # Update SIM, SIMI, FVAL, CONMAT, and CVAL so that SIM[:, JDROP_TR] is replaced with D. + # UPDATEXFC does nothing if JDROP_TR is None, as the algorithm decides to discard X. + sim, simi, fval, conmat, cval, subinfo = updatexfc(jdrop_tr, constr, cpen, cstrv, d, f, conmat, cval, fval, sim, simi) + # Check whether to break due to damaging rounding in UPDATEXFC + if subinfo == DAMAGING_ROUNDING: + info = subinfo + break # Better action to take? Geometry step, or a RESCUE as in BOBYQA? + + # Check whether to break due to maxfun, ftarget, etc. + subinfo = checkbreak_con(maxfun, nf, cstrv, ctol, f, ftarget, x) + if subinfo != INFO_DEFAULT: + info = subinfo + break + # End of if SHORTD or TRFAIL. The normal trust-region calculation ends. + + # Before the next trust-region iteration, we possibly improve the geometry of the simplex or + # reduce RHO according to IMPROVE_GEO and REDUCE_RHO. Now we decide these indicators. + # N.B.: We must ensure that the algorithm does not set IMPROVE_GEO = True at infinitely many + # consecutive iterations without moving SIM[:, NUM_VARS] or reducing RHO. Otherwise, the algorithm + # will get stuck in repetitive invocations of GEOSTEP. This is ensured by the following facts: + # 1. If an iteration sets IMPROVE_GEO to True, it must also reduce DELTA or set DELTA to RHO. + # 2. If SIM[:, NUM_VARS] and RHO remain unchanged, then ADEQUATE_GEO will become True after at + # most NUM_VARS invocations of GEOSTEP. + + # BAD_TRSTEP: Is the last trust-region step bad? + bad_trstep = shortd or trfail or ratio <= 0 or jdrop_tr is None + # IMPROVE_GEO: Should we take a geometry step to improve the geometry of the interpolation set? + improve_geo = bad_trstep and not adequate_geo + # REDUCE_RHO: Should we enhance the resolution by reducing rho? + reduce_rho = bad_trstep and adequate_geo and max(delta, dnorm) <= rho + + # COBYLA never sets IMPROVE_GEO and REDUCE_RHO to True simultaneously. + # assert not (IMPROVE_GEO and REDUCE_RHO), 'IMPROVE_GEO or REDUCE_RHO are not both TRUE, COBYLA' + + # If SHORTD or TRFAIL is True, then either IMPROVE_GEO or REDUCE_RHO is True unless ADEQUATE_GEO + # is True and max(DELTA, DNORM) > RHO. + # assert not (shortd or trfail) or (improve_geo or reduce_rho or (adequate_geo and max(delta, dnorm) > rho)), \ + # 'If SHORTD or TRFAIL is TRUE, then either IMPROVE_GEO or REDUCE_RHO is TRUE unless ADEQUATE_GEO is TRUE and MAX(DELTA, DNORM) > RHO' + + # Comments on BAD_TRSTEP: + # 1. Powell's definition of BAD_TRSTEP is as follows. The one used above seems to work better, + # especially for linearly constrained problems due to the factor TENTH (= ETA1). + # !bad_trstep = (shortd .or. actrem <= 0 .or. actrem < TENTH * prerem .or. jdrop_tr == 0) + # Besides, Powell did not check PREREM > 0 in BAD_TRSTEP, which is reasonable to do but has + # little impact upon the performance. + # 2. NEWUOA/BOBYQA/LINCOA would define BAD_TRSTEP, IMPROVE_GEO, and REDUCE_RHO as follows. Two + # different thresholds are used in BAD_TRSTEP. It outperforms Powell's version. + # !bad_trstep = (shortd .or. trfail .or. ratio <= eta1 .or. jdrop_tr == 0) + # !improve_geo = bad_trstep .and. .not. adequate_geo + # !bad_trstep = (shortd .or. trfail .or. ratio <= 0 .or. jdrop_tr == 0) + # !reduce_rho = bad_trstep .and. adequate_geo .and. max(delta, dnorm) <= rho + # 3. Theoretically, JDROP_TR > 0 when ACTREM > 0 (guaranteed by RATIO > 0). However, in Powell's + # implementation, JDROP_TR may be 0 even RATIO > 0 due to NaN. The modernized code has rectified + # this in the function SETDROP_TR. After this rectification, we can indeed simplify the + # definition of BAD_TRSTEP by removing the condition JDROP_TR == 0. We retain it for robustness. + + # Comments on REDUCE_RHO: + # When SHORTD is TRUE, UOBYQA/NEWUOA/BOBYQA/LINCOA all set REDUCE_RHO to TRUE if the recent + # models are sufficiently accurate according to certain criteria. See the paragraph around (37) + # in the UOBYQA paper and the discussions about Box 14 in the NEWUOA paper. This strategy is + # crucial for the performance of the solvers. However, as of 20221111, we have not managed to + # make it work in COBYLA. As in NEWUOA, we recorded the errors of the recent models, and set + # REDUCE_RHO to true if they are small (e.g., ALL(ABS(MODERR_REC) <= 0.1 * MAXVAL(ABS(A))*RHO) or + # ALL(ABS(MODERR_REC) <= RHO**2)) when SHORTD is TRUE. It made little impact on the performance. + + + # Since COBYLA never sets IMPROVE_GEO and REDUCE_RHO to TRUE simultaneously, the following + # two blocks are exchangeable: IF (IMPROVE_GEO) ... END IF and IF (REDUCE_RHO) ... END IF. + + # Improve the geometry of the simplex by removing a point and adding a new one. + # If the current interpolation set has acceptable geometry, then we skip the geometry step. + # The code has a small difference from Powell's original code here: If the current geometry + # is acceptable, then we will continue with a new trust-region iteration; however, at the + # beginning of the iteration, CPEN may be updated, which may alter the pole point SIM(:, N+1) + # by UPDATEPOLE; the quality of the interpolation point depends on SIM(:, N + 1), meaning + # that the same interpolation set may have good or bad geometry with respect to different + # "poles"; if the geometry turns out bad with the new pole, the original COBYLA code will + # take a geometry step, but our code here will NOT do it but continue to take a trust-region + # step. The argument is this: even if the geometry step is not skipped in the first place, the + # geometry may turn out bad again after the pole is altered due to an update to CPEN; should + # we take another geometry step in that case? If no, why should we do it here? Indeed, this + # distinction makes no practical difference for CUTEst problems with at most 100 variables + # and 5000 constraints, while the algorithm framework is simplified. + if improve_geo and not all(primasum(primapow2(sim[:, :num_vars]), axis=0) <= 4 * primapow2(delta)): + # Before the geometry step, updatepole has been called either implicitly by UPDATEXFC or + # explicitly after CPEN is updated, so that SIM[:, :NUM_VARS] is the optimal vertex. + + # Decide a vertex to drop from the simplex. It will be replaced with SIM[:, NUM_VARS] + D to + # improve the geometry of the simplex. + # N.B.: + # 1. COBYLA never sets JDROP_GEO = num_vars. + # 2. The following JDROP_GEO comes from UOBYQA/NEWUOA/BOBYQA/LINCOA. + # 3. In Powell's original algorithm, the geometry of the simplex is considered acceptable + # iff the distance between any vertex and the pole is at most 2.1*DELTA, and the distance + # between any vertex and the opposite face of the simplex is at least 0.25*DELTA, as + # specified in (14) of the COBYLA paper. Correspondingly, JDROP_GEO is set to the index of + # the vertex with the largest distance to the pole provided that the distance is larger than + # 2.1*DELTA, or the vertex with the smallest distance to the opposite face of the simplex, + # in which case the distance must be less than 0.25*DELTA, as the current simplex does not + # have acceptable geometry (see (15)--(16) of the COBYLA paper). Once JDROP_GEO is set, the + # algorithm replaces SIM(:, JDROP_GEO) with D specified in (17) of the COBYLA paper, which + # is orthogonal to the face opposite to SIM(:, JDROP_GEO) and has a length of 0.5*DELTA, + # intending to improve the geometry of the simplex as per (14). + # 4. Powell's geometry-improving procedure outlined above has an intrinsic flaw: it may lead + # to infinite cycling, as was observed in a test on 20240320. In this test, the geometry- + # improving point introduced in the previous iteration was replaced with the trust-region + # trial point in the current iteration, which was then replaced with the same geometry- + # improving point in the next iteration, and so on. In this process, the simplex alternated + # between two configurations, neither of which had acceptable geometry. Thus RHO was never + # reduced, leading to infinite cycling. (N.B.: Our implementation uses DELTA as the trust + # region radius, with RHO being its lower bound. When the infinite cycling occurred in this + # test, DELTA = RHO and it could not be reduced due to the requirement that DELTA >= RHO.) + jdrop_geo = np.argmax(primasum(primapow2(sim[:, :num_vars]), axis=0), axis=0) + + # Calculate the geometry step D. + delbar = delta/2 + d = geostep(jdrop_geo, amat, bvec, conmat, cpen, cval, delbar, fval, simi) + + # Calculate the next value of the objective and constraint functions. + # If X is close to one of the points in the interpolation set, then we do not evaluate the + # objective and constraints at X, assuming them to have the values at the closest point. + # N.B.: + # 1. If this happens, do NOT include X into the filter, as F and CONSTR are inaccurate. + # 2. In precise arithmetic, the geometry improving step ensures that the distance between X + # and any interpolation point is at least DELBAR, yet X may be close to them due to + # rounding. In an experiment with single precision on 20240317, X = SIM(:, N+1) occurred. + x = sim[:, num_vars] + d + distsq[num_vars] = primasum(primapow2(x - sim[:, num_vars])) + distsq[:num_vars] = primasum(primapow2(x.reshape(num_vars, 1) - + (sim[:, num_vars].reshape(num_vars, 1) + sim[:, :num_vars])), axis=0) + j = np.argmin(distsq) + if distsq[j] <= primapow2(1e-4 * rhoend): + f = fval[j] + constr = conmat[:, j] + cstrv = cval[j] + else: + # Evaluate the objective and constraints at X, taking care of possible + # inf/nan values. + f, constr = evaluate(calcfc, x, m_nlcon, amat, bvec) + cstrv = np.max(np.append(0, constr)) + nf += 1 + # Save X, F, CONSTR, CSTRV into the history. + savehist(maxhist, x, xhist, f, fhist, cstrv, chist, constr, conhist) + # Save X, F, CONSTR, CSTRV into the filter. + nfilt, cfilt, ffilt, xfilt, confilt = savefilt(cstrv, ctol, cweight, f, + x, nfilt, cfilt, ffilt, + xfilt, constr, confilt) + + # Print a message about the function/constraint evaluation according to iprint + fmsg(solver, 'Geometry', iprint, nf, delta, f, x, cstrv, constr) + # Update SIM, SIMI, FVAL, CONMAT, and CVAL so that SIM(:, JDROP_GEO) is replaced with D. + sim, simi, fval, conmat, cval, subinfo = updatexfc(jdrop_geo, constr, cpen, cstrv, d, f, conmat, cval, fval, sim, simi) + # Check whether to break due to damaging rounding in UPDATEXFC + if subinfo == DAMAGING_ROUNDING: + info = subinfo + break # Better action to take? Geometry step, or simply continue? + + # Check whether to break due to maxfun, ftarget, etc. + subinfo = checkbreak_con(maxfun, nf, cstrv, ctol, f, ftarget, x) + if subinfo != INFO_DEFAULT: + info = subinfo + break + # end of if improve_geo. The procedure of improving the geometry ends. + + # The calculations with the current RHO are complete. Enhance the resolution of the algorithm + # by reducing RHO; update DELTA and CPEN at the same time. + if reduce_rho: + if rho <= rhoend: + info = SMALL_TR_RADIUS + break + delta = max(0.5 * rho, redrho(rho, rhoend)) + rho = redrho(rho, rhoend) + # THe second (out of two) updates of CPEN, where CPEN decreases or remains the same. + # Powell's code: cpen = min(cpen, fcratio(fval, conmat)), which may set CPEN to 0. + cpen = np.maximum(cpenmin, np.minimum(cpen, fcratio(conmat, fval))) + # Print a message about the reduction of rho according to iprint + rhomsg(solver, iprint, nf, fval[num_vars], rho, sim[:, num_vars], cval[num_vars], conmat[:, num_vars], cpen) + conmat, cval, fval, sim, simi, subinfo = updatepole(cpen, conmat, cval, fval, sim, simi) + # Check whether to break due to damaging rounding detected in updatepole + if subinfo == DAMAGING_ROUNDING: + info = subinfo + break # Better action to take? Geometry step, or simply continue? + # End of if reduce_rho. The procedure of reducing RHO ends. + # Report the current best value, and check if user asks for early termination. + if callback: + terminate = callback(sim[:, num_vars], fval[num_vars], nf, tr, cval[num_vars], conmat[:, num_vars]) + if terminate: + info = CALLBACK_TERMINATE + break + # End of for loop. The iterative procedure ends + + # Return from the calculation, after trying the last trust-region step if it has not been tried yet. + # Ensure that D has not been updated after SHORTD == TRUE occurred, or the code below is incorrect. + x = sim[:, num_vars] + d + if (info == SMALL_TR_RADIUS and + shortd and + norm(x - sim[:, num_vars]) > 1.0E-3 * rhoend and + nf < maxfun): + # Zaikun 20230615: UPDATEXFC or UPDATEPOLE is not called since the last trust-region step. Hence + # SIM[:, NUM_VARS] remains unchanged. Otherwise SIM[:, NUM_VARS] + D would not make sense. + f, constr = evaluate(calcfc, x, m_nlcon, amat, bvec) + cstrv = np.max(np.append(0, constr)) + nf += 1 + savehist(maxhist, x, xhist, f, fhist, cstrv, chist, constr, conhist) + nfilt, cfilt, ffilt, xfilt, confilt = savefilt(cstrv, ctol, cweight, f, x, nfilt, cfilt, ffilt, xfilt, constr, confilt) + # Zaikun 20230512: DELTA has been updated. RHO is only indicative here. TO BE IMPROVED. + fmsg(solver, 'Trust region', iprint, nf, rho, f, x, cstrv, constr) + + # Return the best calculated values of the variables + # N.B.: SELECTX and FINDPOLE choose X by different standards, one cannot replace the other. + kopt = selectx(ffilt[:nfilt], cfilt[:nfilt], max(cpen, cweight), ctol) + x = xfilt[:, kopt] + f = ffilt[kopt] + constr = confilt[:, kopt] + cstrv = cfilt[kopt] + + # Print a return message according to IPRINT. + retmsg(solver, info, iprint, nf, f, x, cstrv, constr) + return x, f, constr, cstrv, nf, xhist, fhist, chist, conhist, info + + + +def getcpen(amat, bvec, conmat, cpen, cval, delta, fval, rho, sim, simi): + ''' + This function gets the penalty parameter CPEN so that PREREM = PREREF + CPEN * PREREC > 0. + See the discussions around equation (9) of the COBYLA paper. + ''' + + # Even after nearly all of the pycutest problems were showing nearly bit for bit + # identical results between Python and the Fortran bindings, HS102 was still off by + # more than machine epsilon. It turned out to be due to the fact that getcpen was + # modifying fval, among other. It just goes to show that even when you're nearly + # perfect, you can still have non trivial bugs. + conmat = conmat.copy() + cval = cval.copy() + fval = fval.copy() + sim = sim.copy() + simi = simi.copy() + + # Intermediate variables + A = np.zeros((np.size(sim, 0), np.size(conmat, 0))) + itol = 1 + + # Sizes + m_lcon = np.size(bvec) if bvec is not None else 0 + num_constraints = np.size(conmat, 0) + num_vars = np.size(sim, 0) + + # Preconditions + if DEBUGGING: + assert num_constraints >= 0 + assert num_vars >= 1 + assert cpen > 0 + assert np.size(conmat, 0) == num_constraints and np.size(conmat, 1) == num_vars + 1 + assert not (np.isnan(conmat) | np.isneginf(conmat)).any() + assert np.size(cval) == num_vars + 1 and \ + not any(cval < 0 | np.isnan(cval) | np.isposinf(cval)) + assert np.size(fval) == num_vars + 1 and not any(np.isnan(fval) | np.isposinf(fval)) + assert np.size(sim, 0) == num_vars and np.size(sim, 1) == num_vars + 1 + assert np.isfinite(sim).all() + assert all(np.max(abs(sim[:, :num_vars]), axis=0) > 0) + assert np.size(simi, 0) == num_vars and np.size(simi, 1) == num_vars + assert np.isfinite(simi).all() + assert isinv(sim[:, :num_vars], simi, itol) + assert delta >= rho and rho > 0 + + #====================# + # Calculation starts # + #====================# + + # Initialize INFO which is needed in the postconditions + info = INFO_DEFAULT + + # Increase CPEN if necessary to ensure PREREM > 0. Branch back for the next loop + # if this change alters the optimal vertex of the current simplex. + # Note the following: + # 1. In each loop, CPEN is changed only if PREREC > 0 > PREREF, in which case + # PREREM is guaranteed positive after the update. Note that PREREC >= 0 and + # max(PREREC, PREREF) > 0 in theory. If this holds numerically as well then CPEN + # is not changed only if PREREC = 0 or PREREF >= 0, in which case PREREM is + # currently positive, explaining why CPEN needs no update. + # 2. Even without an upper bound for the loop counter, the loop can occur at most + # NUM_VARS+1 times. This is because the update of CPEN does not decrease CPEN, + # and hence it can make vertex J (J <= NUM_VARS) become the new optimal vertex + # only if CVAL[J] is less than CVAL[NUM_VARS], which can happen at most NUM_VARS + # times. See the paragraph below (9) in the COBYLA paper. After the "correct" + # optimal vertex is found, one more loop is needed to calculate CPEN, and hence + # the loop can occur at most NUM_VARS+1 times. + for iter in range(num_vars + 1): + # Switch the best vertex of the current simplex to SIM[:, NUM_VARS] + conmat, cval, fval, sim, simi, info = updatepole(cpen, conmat, cval, fval, sim, + simi) + # Check whether to exit due to damaging rounding in UPDATEPOLE + if info == DAMAGING_ROUNDING: + break + + # Calculate the linear approximations to the objective and constraint functions. + g = matprod(fval[:num_vars] - fval[num_vars], simi) + A[:, :m_lcon] = amat.T if amat is not None else amat + A[:, m_lcon:] = matprod((conmat[m_lcon:, :num_vars] - + np.tile(conmat[m_lcon:, num_vars], (num_vars, 1)).T), simi).T + + # Calculate the trust-region trial step D. Note that D does NOT depend on CPEN. + d = trstlp(A, -conmat[:, num_vars], delta, g) + + # Predict the change to F (PREREF) and to the constraint violation (PREREC) due + # to D. + preref = -inprod(d, g) # Can be negative + prerec = cval[num_vars] - np.max(np.append(0, conmat[:, num_vars] + matprod(d, A))) + + # PREREC <= 0 or PREREF >=0 or either is NaN + if not (prerec > 0 and preref < 0): + break + + # Powell's code defines BARMU = -PREREF / PREREC, and CPEN is increased to + # 2*BARMU if and only if it is currently less than 1.5*BARMU, a very + # "Powellful" scheme. In our implementation, however, we set CPEN directly to + # the maximum between its current value and 2*BARMU while handling possible + # overflow. The simplifies the scheme without worsening the performance of + # COBYLA. + cpen = max(cpen, min(-2 * preref / prerec, REALMAX)) + + if findpole(cpen, cval, fval) == num_vars: + break + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert cpen >= cpen and cpen > 0 + assert preref + cpen * prerec > 0 or info == DAMAGING_ROUNDING or \ + not (prerec >= 0 and np.maximum(prerec, preref) > 0) or not np.isfinite(preref) + + return cpen + + +def fcratio(conmat, fval): + ''' + This function calculates the ratio between the "typical change" of F and that of CONSTR. + See equations (12)-(13) in Section 3 of the COBYLA paper for the definition of the ratio. + ''' + + # Preconditions + if DEBUGGING: + assert np.size(fval) >= 1 + assert np.size(conmat, 1) == np.size(fval) + + #====================# + # Calculation starts # + #====================# + + cmin = np.min(-conmat, axis=1) + cmax = np.max(-conmat, axis=1) + fmin = min(fval) + fmax = max(fval) + if any(cmin < 0.5 * cmax) and fmin < fmax: + denom = np.min(np.maximum(cmax, 0) - cmin, where=cmin < 0.5 * cmax, initial=np.inf) + # Powell mentioned the following alternative in section 4 of his COBYLA paper. According to a test + # on 20230610, it does not make much difference to the performance. + # denom = np.max(max(*cmax, 0) - cmin, mask=(cmin < 0.5 * cmax)) + r = (fmax - fmin) / denom + else: + r = 0 + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert r >= 0 + + return r diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/geometry.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/geometry.py new file mode 100644 index 0000000000000000000000000000000000000000..c03e5626696f5a40939792b6448972d304b31d71 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/geometry.py @@ -0,0 +1,226 @@ +''' +This module contains subroutines concerning the geometry-improving of the interpolation set. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +from ..common.consts import DEBUGGING +from ..common.linalg import isinv, matprod, inprod, norm, primasum, primapow2 +import numpy as np + + +def setdrop_tr(ximproved, d, delta, rho, sim, simi): + ''' + This function finds (the index) of a current interpolation point to be replaced with + the trust-region trial point. See (19)-(22) of the COBYLA paper. + N.B.: + 1. If XIMPROVED == True, then JDROP > 0 so that D is included into XPT. Otherwise, + it is a bug. + 2. COBYLA never sets JDROP = NUM_VARS + TODO: Check whether it improves the performance if JDROP = NUM_VARS is allowed when + XIMPROVED is True. Note that UPDATEXFC should be revised accordingly. + ''' + + # Local variables + itol = 0.1 + + # Sizes + num_vars = np.size(sim, 0) + + # Preconditions + if DEBUGGING: + assert num_vars >= 1 + assert np.size(d) == num_vars and all(np.isfinite(d)) + assert delta >= rho and rho > 0 + assert np.size(sim, 0) == num_vars and np.size(sim, 1) == num_vars + 1 + assert np.isfinite(sim).all() + assert all(np.max(abs(sim[:, :num_vars]), axis=0) > 0) + assert np.size(simi, 0) == num_vars and np.size(simi, 1) == num_vars + assert np.isfinite(simi).all() + assert isinv(sim[:, :num_vars], simi, itol) + + #====================# + # Calculation starts # + #====================# + + # -------------------------------------------------------------------------------------------------- # + # The following code is Powell's scheme for defining JDROP. + # -------------------------------------------------------------------------------------------------- # + # ! JDROP = 0 by default. It cannot be removed, as JDROP may not be set below in some cases (e.g., + # ! when XIMPROVED == FALSE, MAXVAL(ABS(SIMID)) <= 1, and MAXVAL(VETA) <= EDGMAX). + # jdrop = 0 + # + # ! SIMID(J) is the value of the J-th Lagrange function at D. It is the counterpart of VLAG in UOBYQA + # ! and DEN in NEWUOA/BOBYQA/LINCOA, but it excludes the value of the (N+1)-th Lagrange function. + # simid = matprod(simi, d) + # if (any(abs(simid) > 1) .or. (ximproved .and. any(.not. is_nan(simid)))) then + # jdrop = int(maxloc(abs(simid), mask=(.not. is_nan(simid)), dim=1), kind(jdrop)) + # !!MATLAB: [~, jdrop] = max(simid, [], 'omitnan'); + # end if + # + # ! VETA(J) is the distance from the J-th vertex of the simplex to the best vertex, taking the trial + # ! point SIM(:, N+1) + D into account. + # if (ximproved) then + # veta = sqrt(sum((sim(:, 1:n) - spread(d, dim=2, ncopies=n))**2, dim=1)) + # !!MATLAB: veta = sqrt(sum((sim(:, 1:n) - d).^2)); % d should be a column! Implicit expansion + # else + # veta = sqrt(sum(sim(:, 1:n)**2, dim=1)) + # end if + # + # ! VSIG(J) (J=1, .., N) is the Euclidean distance from vertex J to the opposite face of the simplex. + # vsig = ONE / sqrt(sum(simi**2, dim=2)) + # sigbar = abs(simid) * vsig + # + # ! The following JDROP will overwrite the previous one if its premise holds. + # mask = (veta > factor_delta * delta .and. (sigbar >= factor_alpha * delta .or. sigbar >= vsig)) + # if (any(mask)) then + # jdrop = int(maxloc(veta, mask=mask, dim=1), kind(jdrop)) + # !!MATLAB: etamax = max(veta(mask)); jdrop = find(mask & ~(veta < etamax), 1, 'first'); + # end if + # + # ! Powell's code does not include the following instructions. With Powell's code, if SIMID consists + # ! of only NaN, then JDROP can be 0 even when XIMPROVED == TRUE (i.e., D reduces the merit function). + # ! With the following code, JDROP cannot be 0 when XIMPROVED == TRUE, unless VETA is all NaN, which + # ! should not happen if X0 does not contain NaN, the trust-region/geometry steps never contain NaN, + # ! and we exit once encountering an iterate containing Inf (due to overflow). + # if (ximproved .and. jdrop <= 0) then ! Write JDROP <= 0 instead of JDROP == 0 for robustness. + # jdrop = int(maxloc(veta, mask=(.not. is_nan(veta)), dim=1), kind(jdrop)) + # !!MATLAB: [~, jdrop] = max(veta, [], 'omitnan'); + # end if + # -------------------------------------------------------------------------------------------------- # + # Powell's scheme ends here. + # -------------------------------------------------------------------------------------------------- # + + # The following definition of JDROP is inspired by SETDROP_TR in UOBYQA/NEWUOA/BOBYQA/LINCOA. + # It is simpler and works better than Powell's scheme. Note that we allow JDROP to be NUM_VARS+1 if + # XIMPROVED is True, whereas Powell's code does not. + # See also (4.1) of Scheinberg-Toint-2010: Self-Correcting Geometry in Model-Based Algorithms for + # Derivative-Free Unconstrained Optimization, which refers to the strategy here as the "combined + # distance/poisedness criteria". + + # DISTSQ[j] is the square of the distance from the jth vertex of the simplex to get "best" point so + # far, taking the trial point SIM[:, NUM_VARS] + D into account. + distsq = np.zeros(np.size(sim, 1)) + if ximproved: + distsq[:num_vars] = primasum(primapow2(sim[:, :num_vars] - np.tile(d, (num_vars, 1)).T), axis=0) + distsq[num_vars] = primasum(d*d) + else: + distsq[:num_vars] = primasum(primapow2(sim[:, :num_vars]), axis=0) + distsq[num_vars] = 0 + + weight = np.maximum(1, distsq / primapow2(np.maximum(rho, delta/10))) # Similar to Powell's NEWUOA code. + + # Other possible definitions of weight. They work almost the same as the one above. + # weight = distsq # Similar to Powell's LINCOA code, but WRONG. See comments in LINCOA/geometry.f90. + # weight = max(1, max(25 * distsq / delta**2)) # Similar to Powell's BOBYQA code, works well. + # weight = max(1, max(10 * distsq / delta**2)) + # weight = max(1, max(1e2 * distsq / delta**2)) + # weight = max(1, max(distsq / rho**2)) ! Similar to Powell's UOBYQA + + # If 0 <= j < NUM_VARS, SIMID[j] is the value of the jth Lagrange function at D; the value of the + # (NUM_VARS+1)th Lagrange function is 1 - sum(SIMID). [SIMID, 1 - sum(SIMID)] is the counterpart of + # VLAG in UOBYQA and DEN in NEWUOA/BOBYQA/LINCOA. + simid = matprod(simi, d) + score = weight * abs(np.array([*simid, 1 - primasum(simid)])) + + # If XIMPROVED = False (D does not render a better X), set SCORE[NUM_VARS] = -1 to avoid JDROP = NUM_VARS. + if not ximproved: + score[num_vars] = -1 + + # score[j] is NaN implies SIMID[j] is NaN, but we want abs(SIMID) to be big. So we + # exclude such j. + score[np.isnan(score)] = -1 + + jdrop = None + # The following if statement works a bit better than + # `if any(score > 1) or (any(score > 0) and ximproved)` from Powell's UOBYQA and + # NEWUOA code. + if any(score > 0): # Powell's BOBYQA and LINCOA code. + jdrop = np.argmax(score) + + if (ximproved and jdrop is None): + jdrop = np.argmax(distsq) + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert jdrop is None or (0 <= jdrop < num_vars + 1) + assert jdrop <= num_vars or ximproved + assert jdrop >= 0 or not ximproved + # JDROP >= 1 when XIMPROVED = TRUE unless NaN occurs in DISTSQ, which should not happen if the + # starting point does not contain NaN and the trust-region/geometry steps never contain NaN. + + return jdrop + + + + +def geostep(jdrop, amat, bvec, conmat, cpen, cval, delbar, fval, simi): + ''' + This function calculates a geometry step so that the geometry of the interpolation set is improved + when SIM[: JDROP_GEO] is replaced with SIM[:, NUM_VARS] + D. See (15)--(17) of the COBYLA paper. + ''' + + # Sizes + m_lcon = np.size(bvec, 0) if bvec is not None else 0 + num_constraints = np.size(conmat, 0) + num_vars = np.size(simi, 0) + + # Preconditions + if DEBUGGING: + assert num_constraints >= m_lcon >= 0 + assert num_vars >= 1 + assert delbar > 0 + assert cpen > 0 + assert np.size(simi, 0) == num_vars and np.size(simi, 1) == num_vars + assert np.isfinite(simi).all() + assert np.size(fval) == num_vars + 1 and not any(np.isnan(fval) | np.isposinf(fval)) + assert np.size(conmat, 0) == num_constraints and np.size(conmat, 1) == num_vars + 1 + assert not np.any(np.isnan(conmat) | np.isposinf(conmat)) + assert np.size(cval) == num_vars + 1 and not any(cval < 0 | np.isnan(cval) | np.isposinf(cval)) + assert 0 <= jdrop < num_vars + + #====================# + # Calculation starts # + #====================# + + # SIMI[JDROP, :] is a vector perpendicular to the face of the simplex to the opposite of vertex + # JDROP. Set D to the vector in this direction and with length DELBAR. + d = simi[jdrop, :] + d = delbar * (d / norm(d)) + + # The code below chooses the direction of D according to an approximation of the merit function. + # See (17) of the COBYLA paper and line 225 of Powell's cobylb.f. + + # Calculate the coefficients of the linear approximations to the objective and constraint functions. + # N.B.: CONMAT and SIMI have been updated after the last trust-region step, but G and A have not. + # So we cannot pass G and A from outside. + g = matprod(fval[:num_vars] - fval[num_vars], simi) + A = np.zeros((num_vars, num_constraints)) + A[:, :m_lcon] = amat.T if amat is not None else amat + A[:, m_lcon:] = matprod((conmat[m_lcon:, :num_vars] - + np.tile(conmat[m_lcon:, num_vars], (num_vars, 1)).T), simi).T + # CVPD and CVND are the predicted constraint violation of D and -D by the linear models. + cvpd = np.max(np.append(0, conmat[:, num_vars] + matprod(d, A))) + cvnd = np.max(np.append(0, conmat[:, num_vars] - matprod(d, A))) + if -inprod(d, g) + cpen * cvnd < inprod(d, g) + cpen * cvpd: + d *= -1 + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert np.size(d) == num_vars and all(np.isfinite(d)) + # In theory, ||S|| == DELBAR, which may be false due to rounding, but not too far. + # It is crucial to ensure that the geometry step is nonzero, which holds in theory. + assert 0.9 * delbar < np.linalg.norm(d) <= 1.1 * delbar + return d diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/initialize.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/initialize.py new file mode 100644 index 0000000000000000000000000000000000000000..c8c3da8e2c7b0ec09bb30b7bf67ec55238022a94 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/initialize.py @@ -0,0 +1,215 @@ +''' +This module contains subroutines for initialization. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +from ..common.checkbreak import checkbreak_con +from ..common.consts import DEBUGGING, REALMAX +from ..common.infos import INFO_DEFAULT +from ..common.evaluate import evaluate +from ..common.history import savehist +from ..common.linalg import inv +from ..common.message import fmsg +from ..common.selectx import savefilt + +import numpy as np + +def initxfc(calcfc, iprint, maxfun, constr0, amat, bvec, ctol, f0, ftarget, rhobeg, x0, + xhist, fhist, chist, conhist, maxhist): + ''' + This subroutine does the initialization concerning X, function values, and + constraints. + ''' + + # Local variables + solver = 'COBYLA' + srname = "INITIALIZE" + + # Sizes + num_constraints = np.size(constr0) + m_lcon = np.size(bvec) if bvec is not None else 0 + m_nlcon = num_constraints - m_lcon + num_vars = np.size(x0) + + # Preconditions + if DEBUGGING: + assert num_constraints >= 0, f'M >= 0 {srname}' + assert num_vars >= 1, f'N >= 1 {srname}' + assert abs(iprint) <= 3, f'IPRINT is 0, 1, -1, 2, -2, 3, or -3 {srname}' + # assert conmat.shape == (num_constraints , num_vars + 1), f'CONMAT.shape = [M, N+1] {srname}' + # assert cval.size == num_vars + 1, f'CVAL.size == N+1 {srname}' + # assert maxchist * (maxchist - maxhist) == 0, f'CHIST.shape == 0 or MAXHIST {srname}' + # assert conhist.shape[0] == num_constraints and maxconhist * (maxconhist - maxhist) == 0, 'CONHIST.shape[0] == num_constraints, SIZE(CONHIST, 2) == 0 or MAXHIST {srname)}' + # assert maxfhist * (maxfhist - maxhist) == 0, f'FHIST.shape == 0 or MAXHIST {srname}' + # assert xhist.shape[0] == num_vars and maxxhist * (maxxhist - maxhist) == 0, 'XHIST.shape[0] == N, SIZE(XHIST, 2) == 0 or MAXHIST {srname)}' + assert all(np.isfinite(x0)), f'X0 is finite {srname}' + assert rhobeg > 0, f'RHOBEG > 0 {srname}' + + #====================# + # Calculation starts # + #====================# + + # Initialize info to the default value. At return, a value different from this + # value will indicate an abnormal return + info = INFO_DEFAULT + + # Initialize the simplex. It will be revised during the initialization. + sim = np.eye(num_vars, num_vars+1) * rhobeg + sim[:, num_vars] = x0 + + # Initialize the matrix simi. In most cases simi is overwritten, but not always. + simi = np.eye(num_vars) / rhobeg + + # evaluated[j] = True iff the function/constraint of SIM[:, j] has been evaluated. + evaluated = np.zeros(num_vars+1, dtype=bool) + + # Initialize fval + fval = np.zeros(num_vars+1) + REALMAX + cval = np.zeros(num_vars+1) + REALMAX + conmat = np.zeros((num_constraints, num_vars+1)) + REALMAX + + + for k in range(num_vars + 1): + x = sim[:, num_vars].copy() + # We will evaluate F corresponding to SIM(:, J). + if k == 0: + j = num_vars + f = f0 + constr = constr0 + else: + j = k - 1 + x[j] += rhobeg + f, constr = evaluate(calcfc, x, m_nlcon, amat, bvec) + cstrv = np.max(np.append(0, constr)) + + # Print a message about the function/constraint evaluation according to IPRINT. + fmsg(solver, 'Initialization', iprint, k, rhobeg, f, x, cstrv, constr) + + # Save X, F, CONSTR, CSTRV into the history. + savehist(maxhist, x, xhist, f, fhist, cstrv, chist, constr, conhist) + + # Save F, CONSTR, and CSTRV to FVAL, CONMAT, and CVAL respectively. + evaluated[j] = True + fval[j] = f + conmat[:, j] = constr + cval[j] = cstrv + + # Check whether to exit. + subinfo = checkbreak_con(maxfun, k, cstrv, ctol, f, ftarget, x) + if subinfo != INFO_DEFAULT: + info = subinfo + break + + # Exchange the new vertex of the initial simplex with the optimal vertex if necessary. + # This is the ONLY part that is essentially non-parallel. + if j < num_vars and fval[j] < fval[num_vars]: + fval[j], fval[num_vars] = fval[num_vars], fval[j] + cval[j], cval[num_vars] = cval[num_vars], cval[j] + conmat[:, [j, num_vars]] = conmat[:, [num_vars, j]] + sim[:, num_vars] = x + sim[j, :j+1] = -rhobeg # SIM[:, :j+1] is lower triangular + + nf = np.count_nonzero(evaluated) + + if evaluated.all(): + # Initialize SIMI to the inverse of SIM[:, :num_vars] + simi = inv(sim[:, :num_vars]) + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert nf <= maxfun, f'NF <= MAXFUN {srname}' + assert evaluated.size == num_vars + 1, f'EVALUATED.size == Num_vars + 1 {srname}' + # assert chist.size == maxchist, f'CHIST.size == MAXCHIST {srname}' + # assert conhist.shape== (num_constraints, maxconhist), f'CONHIST.shape == [M, MAXCONHIST] {srname}' + assert conmat.shape == (num_constraints, num_vars + 1), f'CONMAT.shape = [M, N+1] {srname}' + assert not (np.isnan(conmat).any() or np.isneginf(conmat).any()), f'CONMAT does not contain NaN/-Inf {srname}' + assert cval.size == num_vars + 1 and not (any(cval < 0) or any(np.isnan(cval)) or any(np.isposinf(cval))), f'CVAL.shape == Num_vars+1 and CVAL does not contain negative values or NaN/+Inf {srname}' + # assert fhist.shape == maxfhist, f'FHIST.shape == MAXFHIST {srname}' + # assert maxfhist * (maxfhist - maxhist) == 0, f'FHIST.shape == 0 or MAXHIST {srname}' + assert fval.size == num_vars + 1 and not (any(np.isnan(fval)) or any(np.isposinf(fval))), f'FVAL.shape == Num_vars+1 and FVAL is not NaN/+Inf {srname}' + # assert xhist.shape == (num_vars, maxxhist), f'XHIST.shape == [N, MAXXHIST] {srname}' + assert sim.shape == (num_vars, num_vars + 1), f'SIM.shape == [N, N+1] {srname}' + assert np.isfinite(sim).all(), f'SIM is finite {srname}' + assert all(np.max(abs(sim[:, :num_vars]), axis=0) > 0), f'SIM(:, 1:N) has no zero column {srname}' + assert simi.shape == (num_vars, num_vars), f'SIMI.shape == [N, N] {srname}' + assert np.isfinite(simi).all(), f'SIMI is finite {srname}' + assert np.allclose(sim[:, :num_vars] @ simi, np.eye(num_vars), rtol=0.1, atol=0.1) or not all(evaluated), f'SIMI = SIM(:, 1:N)^{-1} {srname}' + + return evaluated, conmat, cval, sim, simi, fval, nf, info + + +def initfilt(conmat, ctol, cweight, cval, fval, sim, evaluated, cfilt, confilt, ffilt, xfilt): + ''' + This function initializes the filter (XFILT, etc) that will be used when selecting + x at the end of the solver. + N.B.: + 1. Why not initialize the filters using XHIST, etc? Because the history is empty if + the user chooses not to output it. + 2. We decouple INITXFC and INITFILT so that it is easier to parallelize the former + if needed. + ''' + + # Sizes + num_constraints = conmat.shape[0] + num_vars = sim.shape[0] + maxfilt = len(ffilt) + + # Preconditions + if DEBUGGING: + assert num_constraints >= 0 + assert num_vars >= 1 + assert maxfilt >= 1 + assert np.size(confilt, 0) == num_constraints and np.size(confilt, 1) == maxfilt + assert np.size(cfilt) == maxfilt + assert np.size(xfilt, 0) == num_vars and np.size(xfilt, 1) == maxfilt + assert np.size(ffilt) == maxfilt + assert np.size(conmat, 0) == num_constraints and np.size(conmat, 1) == num_vars + 1 + assert not (np.isnan(conmat) | np.isneginf(conmat)).any() + assert np.size(cval) == num_vars + 1 and not any(cval < 0 | np.isnan(cval) | np.isposinf(cval)) + assert np.size(fval) == num_vars + 1 and not any(np.isnan(fval) | np.isposinf(fval)) + assert np.size(sim, 0) == num_vars and np.size(sim, 1) == num_vars + 1 + assert np.isfinite(sim).all() + assert all(np.max(abs(sim[:, :num_vars]), axis=0) > 0) + assert np.size(evaluated) == num_vars + 1 + + #====================# + # Calculation starts # + #====================# + + + nfilt = 0 + for i in range(num_vars+1): + if evaluated[i]: + if i < num_vars: + x = sim[:, i] + sim[:, num_vars] + else: + x = sim[:, i] # i == num_vars, i.e. the last column + nfilt, cfilt, ffilt, xfilt, confilt = savefilt(cval[i], ctol, cweight, fval[i], x, nfilt, cfilt, ffilt, xfilt, conmat[:, i], confilt) + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert nfilt <= maxfilt + assert np.size(confilt, 0) == num_constraints and np.size(confilt, 1) == maxfilt + assert not (np.isnan(confilt[:, :nfilt]) | np.isneginf(confilt[:, :nfilt])).any() + assert np.size(cfilt) == maxfilt + assert not any(cfilt[:nfilt] < 0 | np.isnan(cfilt[:nfilt]) | np.isposinf(cfilt[:nfilt])) + assert np.size(xfilt, 0) == num_vars and np.size(xfilt, 1) == maxfilt + assert not (np.isnan(xfilt[:, :nfilt])).any() + # The last calculated X can be Inf (finite + finite can be Inf numerically). + assert np.size(ffilt) == maxfilt + assert not any(np.isnan(ffilt[:nfilt]) | np.isposinf(ffilt[:nfilt])) + + return nfilt diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/trustregion.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/trustregion.py new file mode 100644 index 0000000000000000000000000000000000000000..3e97d7c0b5066a94e96168bd2f42e72197f4b632 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/trustregion.py @@ -0,0 +1,492 @@ +''' +This module provides subroutines concerning the trust-region calculations of COBYLA. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +import numpy as np +import numpy.typing as npt +from ..common.consts import DEBUGGING, REALMIN, REALMAX, EPS +from ..common.powalg import qradd_Rdiag, qrexc_Rdiag +from ..common.linalg import isminor, matprod, inprod, lsqr, primasum + + +def trstlp(A, b, delta, g): + ''' + This function calculated an n-component vector d by the following two stages. In the first + stage, d is set to the shortest vector that minimizes the greatest violation of the constraints + A.T @ D <= B, K = 1, 2, 3, ..., M, + subject to the Euclidean length of d being at most delta. If its length is strictly less than + delta, then the second stage uses the resultant freedom in d to minimize the objective function + G.T @ D + subject to no increase in any greatest constraint violation. + + It is possible but rare that a degeneracy may prevent d from attaining the target length delta. + + cviol is the largest constraint violation of the current d: max(max(A.T@D - b), 0) + icon is the index of a most violated constraint if cviol is positive. + + nact is the number of constraints in the active set and iact[0], ..., iact[nact-1] are their indices, + while the remainder of the iact contains a permutation of the remaining constraint indicies. + N.B.: nact <= min(num_constraints, num_vars). Obviously nact <= num_constraints. In addition, the constraints + in iact[0, ..., nact-1] have linearly independent gradients (see the comments above the instruction + that delete a constraint from the active set to make room for the new active constraint with index iact[icon]); + it can also be seen from the update of nact: starting from 0, nact is incremented only if nact < n. + + Further, Z is an orthogonal matrix whose first nact columns can be regarded as the result of + Gram-Schmidt applied to the active constraint gradients. For j = 0, 1, ..., nact-1, the number + zdota[j] is the scalar product of the jth column of Z with the gradient of the jth active + constraint. d is the current vector of variables and here the residuals of the active constraints + should be zero. Further, the active constraints have nonnegative Lagrange multipliers that are + held at the beginning of vmultc. The remainder of this vector holds the residuals of the inactive + constraints at d, the ordering of the components of vmultc being in agreement with the permutation + of the indices of the constraints that is in iact. All these residuals are nonnegative, which is + achieved by the shift cviol that makes the least residual zero. + + N.B.: + 0. In Powell's implementation, the constraints are A.T @ D >= B. In other words, the A and B in + our implementation are the negative of those in Powell's implementation. + 1. The algorithm was NOT documented in the COBYLA paper. A note should be written to introduce it! + 2. As a major part of the algorithm (see trstlp_sub), the code maintains and updates the QR + factorization of A[iact[:nact]], i.e. the gradients of all the active (linear) constraints. The + matrix Z is indeed Q, and the vector zdota is the diagonal of R. The factorization is updated by + Givens rotations when an index is added in or removed from iact. + 3. There are probably better algorithms available for the trust-region linear programming problem. + ''' + + # Sizes + num_constraints = A.shape[1] + num_vars = A.shape[0] + + # Preconditions + if DEBUGGING: + assert num_vars >= 1 + assert num_constraints >= 0 + assert np.size(g) == num_vars + assert np.size(b) == num_constraints + assert delta > 0 + + + vmultc = np.zeros(num_constraints + 1) + iact = np.zeros(num_constraints + 1, dtype=int) + nact = 0 + d = np.zeros(num_vars) + z = np.zeros((num_vars, num_vars)) + + # ================== + # Calculation starts + # ================== + + # Form A_aug and B_aug. This allows the gradient of the objective function to be regarded as the + # gradient of a constraint in the second stage. + A_aug = np.hstack([A, g.reshape((num_vars, 1))]) + b_aug = np.hstack([b, 0]) + + + # Scale the problem if A contains large values. Otherwise floating point exceptions may occur. + # Note that the trust-region step is scale invariant. + for i in range(num_constraints+1): # Note that A_aug.shape[1] == num_constraints+1 + if (maxval:=max(abs(A_aug[:, i]))) > 1e12: + modscal = max(2*REALMIN, 1/maxval) + A_aug[:, i] *= modscal + b_aug[i] *= modscal + + # Stage 1: minimize the 1+infinity constraint violation of the linearized constraints. + iact[:num_constraints], nact, d, vmultc[:num_constraints], z = trstlp_sub(iact[:num_constraints], nact, 1, A_aug[:, :num_constraints], b_aug[:num_constraints], delta, d, vmultc[:num_constraints], z) + + # Stage 2: minimize the linearized objective without increasing the 1_infinity constraint violation. + iact, nact, d, vmultc, z = trstlp_sub(iact, nact, 2, A_aug, b_aug, delta, d, vmultc, z) + + # ================ + # Calculation ends + # ================ + + # Postconditions + if DEBUGGING: + assert all(np.isfinite(d)) + # Due to rounding, it may happen that ||D|| > DELTA, but ||D|| > 2*DELTA is highly improbable. + assert np.linalg.norm(d) <= 2 * delta + + return d + +def trstlp_sub(iact: npt.NDArray, nact: int, stage, A, b, delta, d, vmultc, z): + ''' + This subroutine does the real calculations for trstlp, both stage 1 and stage 2. + Major differences between stage 1 and stage 2: + 1. Initialization. Stage 2 inherits the values of some variables from stage 1, so they are + initialized in stage 1 but not in stage 2. + 2. cviol. cviol is updated after at iteration in stage 1, while it remains a constant in stage2. + 3. sdirn. See the definition of sdirn in the code for details. + 4. optnew. The two stages have different objectives, so optnew is updated differently. + 5. step. step <= cviol in stage 1. + ''' + zdasav = np.zeros(z.shape[1]) + vmultd = np.zeros(np.size(vmultc)) + zdota = np.zeros(np.size(z, 1)) + + # Sizes + mcon = np.size(A, 1) + num_vars = np.size(A, 0) + + # Preconditions + if DEBUGGING: + assert num_vars >= 1 + assert stage == 1 or stage == 2 + assert (mcon >= 0 and stage == 1) or (mcon >= 1 and stage == 2) + assert np.size(b) == mcon + assert np.size(iact) == mcon + assert np.size(vmultc) == mcon + assert np.size(d) == num_vars + assert np.size(z, 0) == num_vars and np.size(z, 1) == num_vars + assert delta > 0 + if stage == 2: + assert all(np.isfinite(d)) and np.linalg.norm(d) <= 2 * delta + assert nact >= 0 and nact <= np.minimum(mcon, num_vars) + assert all(vmultc[:mcon]) >= 0 + # N.B.: Stage 1 defines only VMULTC(1:M); VMULTC(M+1) is undefined! + + + # Initialize according to stage + if stage == 1: + iact = np.linspace(0, mcon-1, mcon, dtype=int) + nact = 0 + d = np.zeros(num_vars) + cviol = np.max(np.append(0, -b)) + vmultc = cviol + b + z = np.eye(num_vars) + if mcon == 0 or cviol <= 0: + # Check whether a quick return is possible. Make sure the in-outputs have been initialized. + return iact, nact, d, vmultc, z + + if all(np.isnan(b)): + return iact, nact, d, vmultc, z + else: + icon = np.nanargmax(-b) + num_constraints = mcon + sdirn = np.zeros(len(d)) + else: + if inprod(d, d) >= delta*delta: + # Check whether a quick return is possible. + return iact, nact, d, vmultc, z + + iact[mcon-1] = mcon-1 + vmultc[mcon-1] = 0 + num_constraints = mcon - 1 + icon = mcon - 1 + + # In Powell's code, stage 2 uses the zdota and cviol calculated by stage1. Here we recalculate + # them so that they need not be passed from stage 1 to 2, and hence the coupling is reduced. + cviol = np.max(np.append(0, matprod(d, A[:, :num_constraints]) - b[:num_constraints])) + zdota[:nact] = [inprod(z[:, k], A[:, iact[k]]) for k in range(nact)] + + # More initialization + optold = REALMAX + nactold = nact + nfail = 0 + + # Zaikun 20211011: vmultd is computed from scratch at each iteration, but vmultc is inherited + + # Powell's code can encounter infinite cycling, which did happen when testing the following CUTEst + # problems: DANWOODLS, GAUSS1LS, GAUSS2LS, GAUSS3LS, KOEBHELB, TAX13322, TAXR13322. Indeed, in all + # these cases, Inf/NaN appear in d due to extremely large values in A (up to 10^219). To resolve + # this, we set the maximal number of iterations to maxiter, and terminate if Inf/NaN occurs in d. + maxiter = np.minimum(10000, 100*max(num_constraints, num_vars)) + for iter in range(maxiter): + if DEBUGGING: + assert all(vmultc >= 0) + if stage == 1: + optnew = cviol + else: + optnew = inprod(d, A[:, mcon-1]) + + # End the current stage of the calculation if 3 consecutive iterations have either failed to + # reduce the best calculated value of the objective function or to increase the number of active + # constraints since the best value was calculated. This strategy prevents cycling, but there is + # a remote possibility that it will cause premature termination. + if optnew < optold or nact > nactold: + nactold = nact + nfail = 0 + else: + nfail += 1 + optold = np.minimum(optold, optnew) + if nfail == 3: + break + + # If icon exceeds nact, then we add the constraint with index iact[icon] to the active set. + if icon >= nact: # In Python this needs to be >= since Python is 0-indexed (in Fortran we have 1 > 0, in Python we need 0 >= 0) + zdasav[:nact] = zdota[:nact] + nactsav = nact + z, zdota, nact = qradd_Rdiag(A[:, iact[icon]], z, zdota, nact) # May update nact to nact+1 + # Indeed it suffices to pass zdota[:min(num_vars, nact+1)] to qradd as follows: + # qradd(A[:, iact[icon]], z, zdota[:min(num_vars, nact+1)], nact) + + if nact == nactsav + 1: + # N.B.: It is possible to index arrays using [nact, icon] when nact == icon. + # Zaikun 20211012: Why should vmultc[nact] = 0? + if nact != (icon + 1): # Need to add 1 to Python for 0 indexing + vmultc[[icon, nact-1]] = vmultc[nact-1], 0 + iact[[icon, nact-1]] = iact[[nact-1, icon]] + else: + vmultc[nact-1] = 0 + else: + # Zaikun 20211011: + # 1. VMULTD is calculated from scratch for the first time (out of 2) in one iteration. + # 2. Note that IACT has not been updated to replace IACT[NACT] with IACT[ICON]. Thus + # A[:, IACT[:NACT]] is the UNUPDATED version before QRADD (note Z[:, :NACT] remains the + # same before and after QRADD). Therefore if we supply ZDOTA to LSQR (as Rdiag) as + # Powell did, we should use the UNUPDATED version, namely ZDASAV. + # vmultd[:nact] = lsqr(A[:, iact[:nact]], A[:, iact[icon]], z[:, :nact], zdasav[:nact]) + vmultd[:nact] = lsqr(A[:, iact[:nact]], A[:, iact[icon]], z[:, :nact], zdasav[:nact]) + if not any(np.logical_and(vmultd[:nact] > 0, iact[:nact] <= num_constraints)): + # N.B.: This can be triggered by NACT == 0 (among other possibilities)! This is + # important, because NACT will be used as an index in the sequel. + break + # vmultd[NACT+1:mcon] is not used, but we have to initialize it in Fortran, or compilers + # complain about the where construct below (another solution: restrict where to 1:NACT). + vmultd[nact:mcon] = -1 # len(vmultd) == mcon + + # Revise the Lagrange multipliers. The revision is not applicable to vmultc[nact:num_constraints]. + fracmult = [vmultc[i]/vmultd[i] if vmultd[i] > 0 and iact[i] <= num_constraints else REALMAX for i in range(nact)] + # Only the places with vmultd > 0 and iact <= m is relevant below, if any. + frac = min(fracmult[:nact]) # fracmult[nact:mcon] may contain garbage + vmultc[:nact] = np.maximum(np.zeros(len(vmultc[:nact])), vmultc[:nact] - frac*vmultd[:nact]) + + # Reorder the active constraints so that the one to be replaced is at the end of the list. + # Exit if the new value of zdota[nact] is not acceptable. Powell's condition for the + # following If: not abs(zdota[nact]) > 0. Note that it is different from + # 'abs(zdota[nact]) <=0)' as zdota[nact] can be NaN. + # N.B.: We cannot arrive here with nact == 0, which should have triggered a break above + if np.isnan(zdota[nact - 1]) or abs(zdota[nact - 1]) <= EPS**2: + break + vmultc[[icon, nact - 1]] = 0, frac # vmultc[[icon, nact]] is valid as icon > nact + iact[[icon, nact - 1]] = iact[[nact - 1, icon]] + # end if nact == nactsav + 1 + + # In stage 2, ensure that the objective continues to be treated as the last active constraint. + # Zaikun 20211011, 20211111: Is it guaranteed for stage 2 that iact[nact-1] = mcon when + # iact[nact] != mcon??? If not, then how does the following procedure ensure that mcon is + # the last of iact[:nact]? + if stage == 2 and iact[nact - 1] != (mcon - 1): + if nact <= 1: + # We must exit, as nact-2 is used as an index below. Powell's code does not have this. + break + z, zdota[:nact] = qrexc_Rdiag(A[:, iact[:nact]], z, zdota[:nact], nact - 2) # We pass nact-2 in Python instead of nact-1 + # Indeed, it suffices to pass Z[:, :nact] to qrexc as follows: + # z[:, :nact], zdota[:nact] = qrexc(A[:, iact[:nact]], z[:, :nact], zdota[:nact], nact - 1) + iact[[nact-2, nact-1]] = iact[[nact-1, nact-2]] + vmultc[[nact-2, nact-1]] = vmultc[[nact-1, nact-2]] + # Zaikun 20211117: It turns out that the last few lines do not guarantee iact[nact] == num_vars in + # stage 2; the following test cannot be passed. IS THIS A BUG?! + # assert iact[nact] == mcon or stage == 1, 'iact[nact] must == mcon in stage 2' + + # Powell's code does not have the following. It avoids subsequent floating points exceptions. + if np.isnan(zdota[nact-1]) or abs(zdota[nact-1]) <= EPS**2: + break + + # Set sdirn to the direction of the next change to the current vector of variables + # Usually during stage 1 the vector sdirn gives a search direction that reduces all the + # active constraint violations by one simultaneously. + if stage == 1: + sdirn -= ((inprod(sdirn, A[:, iact[nact-1]]) + 1)/zdota[nact-1])*z[:, nact-1] + else: + sdirn = -1/zdota[nact-1]*z[:, nact-1] + else: # icon < nact + # Delete the constraint with the index iact[icon] from the active set, which is done by + # reordering iact[icon:nact] into [iact[icon+1:nact], iact[icon]] and then reduce nact to + # nact - 1. In theory, icon > 0. + # assert icon > 0, "icon > 0 is required" # For Python I think this is irrelevant + z, zdota[:nact] = qrexc_Rdiag(A[:, iact[:nact]], z, zdota[:nact], icon) # qrexc does nothing if icon == nact + # Indeed, it suffices to pass Z[:, :nact] to qrexc as follows: + # z[:, :nact], zdota[:nact] = qrexc(A[:, iact[:nact]], z[:, :nact], zdota[:nact], icon) + iact[icon:nact] = [*iact[icon+1:nact], iact[icon]] + vmultc[icon:nact] = [*vmultc[icon+1:nact], vmultc[icon]] + nact -= 1 + + # Powell's code does not have the following. It avoids subsequent exceptions. + # Zaikun 20221212: In theory, nact > 0 in stage 2, as the objective function should always + # be considered as an "active constraint" --- more precisely, iact[nact] = mcon. However, + # looking at the code, I cannot see why in stage 2 nact must be positive after the reduction + # above. It did happen in stage 1 that nact became 0 after the reduction --- this is + # extremely rare, and it was never observed until 20221212, after almost one year of + # random tests. Maybe nact is theoretically positive even in stage 1? + if stage == 2 and nact < 0: + break # If this case ever occurs, we have to break, as nact is used as an index below. + if nact > 0: + if np.isnan(zdota[nact-1]) or abs(zdota[nact-1]) <= EPS**2: + break + + # Set sdirn to the direction of the next change to the current vector of variables. + if stage == 1: + sdirn -= inprod(sdirn, z[:, nact]) * z[:, nact] + # sdirn is orthogonal to z[:, nact+1] + else: + sdirn = -1/zdota[nact-1] * z[:, nact-1] + # end if icon > nact + + # Calculate the step to the trust region boundary or take the step that reduces cviol to 0. + # ----------------------------------------------------------------------------------------- # + # The following calculation of step is adopted from NEWUOA/BOBYQA/LINCOA. It seems to improve + # the performance of COBYLA. We also found that removing the precaution about underflows is + # beneficial to the overall performance of COBYLA --- the underflows are harmless anyway. + dd = delta*delta - inprod(d, d) + ss = inprod(sdirn, sdirn) + sd = inprod(sdirn, d) + if dd <= 0 or ss <= EPS * delta*delta or np.isnan(sd): + break + # sqrtd: square root of a discriminant. The max avoids sqrtd < abs(sd) due to underflow + sqrtd = max(np.sqrt(ss*dd + sd*sd), abs(sd), np.sqrt(ss * dd)) + if sd > 0: + step = dd / (sqrtd + sd) + else: + step = (sqrtd - sd) / ss + # step < 0 should not happen. Step can be 0 or NaN when, e.g., sd or ss becomes inf + if step <= 0 or not np.isfinite(step): + break + + # Powell's approach and comments are as follows. + # -------------------------------------------------- # + # The two statements below that include the factor eps prevent + # some harmless underflows that occurred in a test calculation + # (Zaikun: here, eps is the machine epsilon; Powell's original + # code used 1.0e-6, and Powell's code was written in single + # precision). Further, we skip the step if it could be 0 within + # a reasonable tolerance for computer rounding errors. + + # !dd = delta*delta - sum(d**2, mask=(abs(d) >= EPS * delta)) + # !ss = inprod(sdirn, sdirn) + # !if (dd <= 0) then + # ! exit + # !end if + # !sd = inprod(sdirn, d) + # !if (abs(sd) >= EPS * sqrt(ss * dd)) then + # ! step = dd / (sqrt(ss * dd + sd*sd) + sd) + # !else + # ! step = dd / (sqrt(ss * dd) + sd) + # !end if + # -------------------------------------------------- # + + if stage == 1: + if isminor(cviol, step): + break + step = min(step, cviol) + + # Set dnew to the new variables if step is the steplength, and reduce cviol to the corresponding + # maximum residual if stage 1 is being done + dnew = d + step * sdirn + if stage == 1: + cviol = np.max(np.append(0, matprod(dnew, A[:, iact[:nact]]) - b[iact[:nact]])) + # N.B.: cviol will be used when calculating vmultd[nact+1:mcon]. + + # Zaikun 20211011: + # 1. vmultd is computed from scratch for the second (out of 2) time in one iteration. + # 2. vmultd[:nact] and vmultd[nact:mcon] are calculated separately with no coupling. + # 3. vmultd will be calculated from scratch again in the next iteration. + # Set vmultd to the vmultc vector that would occur if d became dnew. A device is included to + # force vmultd[k] = 0 if deviations from this value can be attributed to computer rounding + # errors. First calculate the new Lagrange multipliers. + vmultd[:nact] = -lsqr(A[:, iact[:nact]], dnew, z[:, :nact], zdota[:nact]) + if stage == 2: + vmultd[nact-1] = max(0, vmultd[nact-1]) # This seems never activated. + # Complete vmultd by finding the new constraint residuals. (Powell wrote "Complete vmultc ...") + cvshift = cviol - (matprod(dnew, A[:, iact]) - b[iact]) # Only cvshift[nact+1:mcon] is needed + cvsabs = matprod(abs(dnew), abs(A[:, iact])) + abs(b[iact]) + cviol + cvshift[isminor(cvshift, cvsabs)] = 0 + vmultd[nact:mcon] = cvshift[nact:mcon] + + # Calculate the fraction of the step from d to dnew that will be taken + fracmult = [vmultc[i]/(vmultc[i] - vmultd[i]) if vmultd[i] < 0 else REALMAX for i in range(len(vmultd))] + # Only the places with vmultd < 0 are relevant below, if any. + icon = np.argmin(np.append(1, fracmult)) - 1 + frac = min(np.append(1, fracmult)) + + # Update d, vmultc, and cviol + dold = d + d = (1 - frac)*d + frac * dnew + vmultc = np.maximum(0, (1 - frac)*vmultc + frac*vmultd) + # Break in the case of inf/nan in d or vmultc. + if not (np.isfinite(primasum(abs(d))) and np.isfinite(primasum(abs(vmultc)))): + d = dold # Should we restore also iact, nact, vmultc, and z? + break + + if stage == 1: + # cviol = (1 - frac) * cvold + frac * cviol # Powell's version + # In theory, cviol = np.max(np.append(d@A - b, 0)), yet the + # cviol updated as above can be quite different from this value if A has huge entries (e.g., > 1e20) + cviol = np.max(np.append(0, matprod(d, A) - b)) + + if icon < 0 or icon >= mcon: + # In Powell's code, the condition is icon == 0. Indeed, icon < 0 cannot hold unless + # fracmult contains only nan, which should not happen; icon >= mcon should never occur. + break + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert np.size(iact) == mcon + assert np.size(vmultc) == mcon + assert all(vmultc >= 0) + assert np.size(d) == num_vars + assert all(np.isfinite(d)) + assert np.linalg.norm(d) <= 2 * delta + assert np.size(z, 0) == num_vars and np.size(z, 1) == num_vars + assert nact >= 0 and nact <= np.minimum(mcon, num_vars) + + return iact, nact, d, vmultc, z + + +def trrad(delta_in, dnorm, eta1, eta2, gamma1, gamma2, ratio): + ''' + This function updates the trust region radius according to RATIO and DNORM. + ''' + + # Preconditions + if DEBUGGING: + assert delta_in >= dnorm > 0 + assert 0 <= eta1 <= eta2 < 1 + assert 0 < gamma1 < 1 < gamma2 + # By the definition of RATIO in ratio.f90, RATIO cannot be NaN unless the + # actual reduction is NaN, which should NOT happen due to the moderated extreme + # barrier. + assert not np.isnan(ratio) + + #====================# + # Calculation starts # + #====================# + + if ratio <= eta1: + delta = gamma1 * dnorm # Powell's UOBYQA/NEWUOA + # delta = gamma1 * delta_in # Powell's COBYLA/LINCOA + # delta = min(gamma1 * delta_in, dnorm) # Powell's BOBYQA + elif ratio <= eta2: + delta = max(gamma1 * delta_in, dnorm) # Powell's UOBYQA/NEWUOA/BOBYQA/LINCOA + else: + delta = max(gamma1 * delta_in, gamma2 * dnorm) # Powell's NEWUOA/BOBYQA + # delta = max(delta_in, gamma2 * dnorm) # Modified version. Works well for UOBYQA + # For noise-free CUTEst problems of <= 100 variables, Powell's version works slightly better + # than the modified one. + # delta = max(delta_in, 1.25*dnorm, dnorm + rho) # Powell's UOBYQA + # delta = min(max(gamma1 * delta_in, gamma2 * dnorm), gamma3 * delta_in) # Powell's LINCOA, gamma3 = np.sqrt(2) + + # For noisy problems, the following may work better. + # if ratio <= eta1: + # delta = gamma1 * dnorm + # elseif ratio <= eta2: # Ensure DELTA >= DELTA_IN + # delta = delta_in + # else: # Ensure DELTA > DELTA_IN with a constant factor + # delta = max(delta_in * (1 + gamma2) / 2, gamma2 * dnorm) + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert delta > 0 + return delta diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/update.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/update.py new file mode 100644 index 0000000000000000000000000000000000000000..66a3fa3623f9373b27346ebe052ddbf6f3ba68a4 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/cobyla/update.py @@ -0,0 +1,289 @@ +''' +This module contains subroutines concerning the update of the interpolation set. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +from ..common.consts import DEBUGGING +from ..common.infos import DAMAGING_ROUNDING, INFO_DEFAULT +from ..common.linalg import isinv, matprod, outprod, inprod, inv, primasum +import numpy as np + + +def updatexfc(jdrop, constr, cpen, cstrv, d, f, conmat, cval, fval, sim, simi): + ''' + This function revises the simplex by updating the elements of SIM, SIMI, FVAL, CONMAT, and CVAL + ''' + + # Local variables + itol = 1 + + # Sizes + num_constraints = np.size(constr) + num_vars = np.size(sim, 0) + + # Preconditions + if DEBUGGING: + assert num_constraints >= 0 + assert num_vars >= 1 + assert jdrop >= 0 and jdrop <= num_vars + 1 + assert not any(np.isnan(constr) | np.isneginf(constr)) + assert not (np.isnan(cstrv) | np.isposinf(cstrv)) + assert np.size(d) == num_vars and all(np.isfinite(d)) + assert not (np.isnan(f) | np.isposinf(f)) + assert np.size(conmat, 0) == num_constraints and np.size(conmat, 1) == num_vars + 1 + assert not (np.isnan(conmat) | np.isneginf(conmat)).any() + assert np.size(cval) == num_vars + 1 and not any(cval < 0 | np.isnan(cval) | np.isposinf(cval)) + assert np.size(fval) == num_vars + 1 and not any(np.isnan(fval) | np.isposinf(fval)) + assert np.size(sim, 0) == num_vars and np.size(sim, 1) == num_vars + 1 + assert np.isfinite(sim).all() + assert all(primasum(abs(sim[:, :num_vars]), axis=0) > 0) + assert np.size(simi, 0) == num_vars and np.size(simi, 1) == num_vars + assert np.isfinite(simi).all() + assert isinv(sim[:, :num_vars], simi, itol) + + #====================# + # Calculation starts # + #====================# + + + # Do nothing when JDROP is None. This can only happen after a trust-region step. + if jdrop is None: # JDROP is None is impossible if the input is correct. + return conmat, cval, fval, sim, simi, INFO_DEFAULT + + sim_old = sim + simi_old = simi + if jdrop < num_vars: + sim[:, jdrop] = d + simi_jdrop = simi[jdrop, :] / inprod(simi[jdrop, :], d) + simi -= outprod(matprod(simi, d), simi_jdrop) + simi[jdrop, :] = simi_jdrop + else: # jdrop == num_vars + sim[:, num_vars] += d + sim[:, :num_vars] -= np.tile(d, (num_vars, 1)).T + simid = matprod(simi, d) + sum_simi = primasum(simi, axis=0) + simi += outprod(simid, sum_simi / (1 - sum(simid))) + + # Check whether SIMI is a poor approximation to the inverse of SIM[:, :NUM_VARS] + # Calculate SIMI from scratch if the current one is damaged by rounding errors. + itol = 1 + erri = np.max(abs(matprod(simi, sim[:, :num_vars]) - np.eye(num_vars))) # np.max returns NaN if any input is NaN + if erri > 0.1 * itol or np.isnan(erri): + simi_test = inv(sim[:, :num_vars]) + erri_test = np.max(abs(matprod(simi_test, sim[:, :num_vars]) - np.eye(num_vars))) + if erri_test < erri or (np.isnan(erri) and not np.isnan(erri_test)): + simi = simi_test + erri = erri_test + + # If SIMI is satisfactory, then update FVAL, CONMAT, CVAL, and the pole position. Otherwise restore + # SIM and SIMI, and return with INFO = DAMAGING_ROUNDING. + if erri <= itol: + fval[jdrop] = f + conmat[:, jdrop] = constr + cval[jdrop] = cstrv + # Switch the best vertex to the pole position SIM[:, NUM_VARS] if it is not there already + conmat, cval, fval, sim, simi, info = updatepole(cpen, conmat, cval, fval, sim, simi) + else: + info = DAMAGING_ROUNDING + sim = sim_old + simi = simi_old + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert np.size(conmat, 0) == num_constraints and np.size(conmat, 1) == num_vars + 1 + assert not (np.isnan(conmat) | np.isneginf(conmat)).any() + assert np.size(cval) == num_vars + 1 and not any(cval < 0 | np.isnan(cval) | np.isposinf(cval)) + assert np.size(fval) == num_vars + 1 and not any(np.isnan(fval) | np.isposinf(fval)) + assert np.size(sim, 0) == num_vars and np.size(sim, 1) == num_vars + 1 + assert np.isfinite(sim).all() + assert all(primasum(abs(sim[:, :num_vars]), axis=0) > 0) + assert np.size(simi, 0) == num_vars and np.size(simi, 1) == num_vars + assert np.isfinite(simi).all() + assert isinv(sim[:, :num_vars], simi, itol) or info == DAMAGING_ROUNDING + + return sim, simi, fval, conmat, cval, info + +def findpole(cpen, cval, fval): + ''' + This subroutine identifies the best vertex of the current simplex with respect to the merit + function PHI = F + CPEN * CSTRV. + ''' + + # Size + num_vars = np.size(fval) - 1 + + # Preconditions + if DEBUGGING: + assert cpen > 0 + assert np.size(cval) == num_vars + 1 and not any(cval < 0 | np.isnan(cval) | np.isposinf(cval)) + assert np.size(fval) == num_vars + 1 and not any(np.isnan(fval) | np.isposinf(fval)) + + #====================# + # Calculation starts # + #====================# + + # Identify the optimal vertex of the current simplex + jopt = np.size(fval) - 1 + phi = fval + cpen * cval + phimin = min(phi) + # Essentially jopt = np.argmin(phi). However, we keep jopt = num_vars unless there + # is a strictly better choice. When there are multiple choices, we choose the jopt + # with the smallest value of cval. + if phimin < phi[jopt] or any((cval < cval[jopt]) & (phi <= phi[jopt])): + # While we could use argmin(phi), there may be two places where phi achieves + # phimin, and in that case we should choose the one with the smallest cval. + jopt = np.ma.array(cval, mask=(phi > phimin)).argmin() + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert jopt >= 0 and jopt < num_vars + 1 + assert jopt == num_vars or phi[jopt] < phi[num_vars] or (phi[jopt] <= phi[num_vars] and cval[jopt] < cval[num_vars]) + return jopt + + +def updatepole(cpen, conmat, cval, fval, sim, simi): + #--------------------------------------------------------------------------------------------------! + # This subroutine identifies the best vertex of the current simplex with respect to the merit + # function PHI = F + CPEN * CSTRV, and then switch this vertex to SIM[:, NUM_VARS], which Powell called + # the "pole position" in his comments. CONMAT, CVAL, FVAL, and SIMI are updated accordingly. + # + # N.B. 1: In precise arithmetic, the following two procedures produce the same results: + # 1) apply UPDATEPOLE to SIM twice, first with CPEN = CPEN1 and then with CPEN = CPEN2; + # 2) apply UPDATEPOLE to SIM with CPEN = CPEN2. + # In finite-precision arithmetic, however, they may produce different results unless CPEN1 = CPEN2. + # + # N.B. 2: When JOPT == N+1, the best vertex is already at the pole position, so there is nothing to + # switch. However, as in Powell's code, the code below will check whether SIMI is good enough to + # work as the inverse of SIM(:, 1:N) or not. If not, Powell's code would invoke an error return of + # COBYLB; our implementation, however, will try calculating SIMI from scratch; if the recalculated + # SIMI is still of poor quality, then UPDATEPOLE will return with INFO = DAMAGING_ROUNDING, + # informing COBYLB that SIMI is poor due to damaging rounding errors. + # + # N.B. 3: UPDATEPOLE should be called when and only when FINDPOLE can potentially returns a value + # other than N+1. The value of FINDPOLE is determined by CPEN, CVAL, and FVAL, the latter two being + # decided by SIM. Thus UPDATEPOLE should be called after CPEN or SIM changes. COBYLA updates CPEN at + # only two places: the beginning of each trust-region iteration, and when REDRHO is called; + # SIM is updated only by UPDATEXFC, which itself calls UPDATEPOLE internally. Therefore, we only + # need to call UPDATEPOLE after updating CPEN at the beginning of each trust-region iteration and + # after each invocation of REDRHO. + + # Local variables + itol = 1 + + # Sizes + num_constraints = conmat.shape[0] + num_vars = sim.shape[0] + + # Preconditions + if DEBUGGING: + assert num_constraints >= 0 + assert num_vars >= 1 + assert cpen > 0 + assert np.size(conmat, 0) == num_constraints and np.size(conmat, 1) == num_vars + 1 + assert not (np.isnan(conmat) | np.isneginf(conmat)).any() + assert np.size(cval) == num_vars + 1 and not any(cval < 0 | np.isnan(cval) | np.isposinf(cval)) + assert np.size(fval) == num_vars + 1 and not any(np.isnan(fval) | np.isposinf(fval)) + assert np.size(sim, 0) == num_vars and np.size(sim, 1) == num_vars + 1 + assert np.isfinite(sim).all() + assert all(primasum(abs(sim[:, :num_vars]), axis=0) > 0) + assert np.size(simi, 0) == num_vars and np.size(simi, 1) == num_vars + assert np.isfinite(simi).all() + assert isinv(sim[:, :num_vars], simi, itol) + + #====================# + # Calculation starts # + #====================# + + # INFO must be set, as it is an output. + info = INFO_DEFAULT + + # Identify the optimal vertex of the current simplex. + jopt = findpole(cpen, cval, fval) + + # Switch the best vertex to the pole position SIM[:, NUM_VARS] if it is not there already and update + # SIMI. Before the update, save a copy of SIM and SIMI. If the update is unsuccessful due to + # damaging rounding errors, we restore them and return with INFO = DAMAGING_ROUNDING. + sim_old = sim.copy() + simi_old = simi.copy() + if 0 <= jopt < num_vars: + # Unless there is a bug in FINDPOLE it is guaranteed that JOPT >= 0 + # When JOPT == NUM_VARS, there is nothing to switch; in addition SIMI[JOPT, :] will be illegal. + # fval[[jopt, -1]] = fval[[-1, jopt]] + # conmat[:, [jopt, -1]] = conmat[:, [-1, jopt]] # Exchange CONMAT[:, JOPT] AND CONMAT[:, -1] + # cval[[jopt, -1]] = cval[[-1, jopt]] + sim[:, num_vars] += sim[:, jopt] + sim_jopt = sim[:, jopt].copy() + sim[:, jopt] = 0 # np.zeros(num_constraints)? + sim[:, :num_vars] -= np.tile(sim_jopt, (num_vars, 1)).T + # The above update is equivalent to multiplying SIM[:, :NUM_VARS] from the right side by a matrix whose + # JOPT-th row is [-1, -1, ..., -1], while all the other rows are the same as those of the + # identity matrix. It is easy to check that the inverse of this matrix is itself. Therefore, + # SIMI should be updated by a multiplication with this matrix (i.e. its inverse) from the left + # side, as is done in the following line. The JOPT-th row of the updated SIMI is minus the sum + # of all rows of the original SIMI, whereas all the other rows remain unchanged. + # NDB 20250114: In testing the cutest problem 'SYNTHES2' between the Python implementation and + # the Fortran bindings, I saw a difference between the following for loop and the + # np.sum command. The differences were small, on the order of 1e-16, i.e. epsilon. + # According to numpy documentation, np.sum sometimes uses partial pairwise summation, + # depending on the memory layout of the array and the axis specified. + # for i in range(simi.shape[1]): + # simi[jopt, i] = -sum(simi[:, i]) + simi[jopt, :] = -primasum(simi, axis=0) + + # Check whether SIMI is a poor approximation to the inverse of SIM[:, :NUM_VARS] + # Calculate SIMI from scratch if the current one is damaged by rounding errors. + erri = np.max(abs(matprod(simi, sim[:, :num_vars]) - np.eye(num_vars))) # np.max returns NaN if any input is NaN + itol = 1 + if erri > 0.1 * itol or np.isnan(erri): + simi_test = inv(sim[:, :num_vars]) + erri_test = np.max(abs(matprod(simi_test, sim[:, :num_vars]) - np.eye(num_vars))) + if erri_test < erri or (np.isnan(erri) and not np.isnan(erri_test)): + simi = simi_test + erri = erri_test + + + # If SIMI is satisfactory, then update FVAL, CONMAT, and CVAL. Otherwise restore SIM and SIMI, and + # return with INFO = DAMAGING_ROUNDING. + if erri <= itol: + if 0 <= jopt < num_vars: + fval[[jopt, num_vars]] = fval[[num_vars, jopt]] + conmat[:, [jopt, num_vars]] = conmat[:, [num_vars, jopt]] + cval[[jopt, num_vars]] = cval[[num_vars, jopt]] + else: # erri > itol or erri is NaN + info = DAMAGING_ROUNDING + sim = sim_old + simi = simi_old + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert findpole(cpen, cval, fval) == num_vars or info == DAMAGING_ROUNDING + assert np.size(conmat, 0) == num_constraints and np.size(conmat, 1) == num_vars + 1 + assert not (np.isnan(conmat) | np.isneginf(conmat)).any() + assert np.size(cval) == num_vars + 1 and not any(cval < 0 | np.isnan(cval) | np.isposinf(cval)) + assert np.size(fval) == num_vars + 1 and not any(np.isnan(fval) | np.isposinf(fval)) + assert np.size(sim, 0) == num_vars and np.size(sim, 1) == num_vars + 1 + assert np.isfinite(sim).all() + assert all(primasum(abs(sim[:, :num_vars]), axis=0) > 0) + assert np.size(simi, 0) == num_vars and np.size(simi, 1) == num_vars + assert np.isfinite(simi).all() + # Do not check SIMI = SIM[:, :num_vars]^{-1}, as it may not be true due to damaging rounding. + assert isinv(sim[:, :num_vars], simi, itol) or info == DAMAGING_ROUNDING + + return conmat, cval, fval, sim, simi, info diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e4a20852eed58216d436d333df4ab6e0561b5e95 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/_bounds.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/_bounds.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5cfe618665761b930fdd4a3079c1ae180e46ba05 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/_bounds.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/_linear_constraints.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/_linear_constraints.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9f0a942fbabe609c4a3291262d0ff5351bf1f6a4 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/_linear_constraints.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/_nonlinear_constraints.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/_nonlinear_constraints.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4e05815ad2777d6b2d100a131957f30477cad380 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/_nonlinear_constraints.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/_project.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/_project.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3b76b1d75cb1ab95918293cf541271c64d72116a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/_project.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/checkbreak.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/checkbreak.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c75291b4f7080d1c83849ce602bb1e0d9dc46510 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/checkbreak.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/consts.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/consts.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..00e9216fe3255939a99217626cd66fc015b8b82d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/consts.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/evaluate.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/evaluate.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..df1a45b43428400abbc783c58cf97b4a2ba14ab0 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/evaluate.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/history.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/history.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cab7f9fa65de3a0686b55f27350ba6a271306d0a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/history.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/infos.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/infos.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1710b2feff90574e88f1055dc9b2579ca132cc6e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/infos.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/linalg.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/linalg.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c1cb804a807c169f63fe11db9e9eab41fe556513 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/linalg.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/message.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/message.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac5075574fffac139a24d94bd00b68545adddf21 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/message.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/powalg.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/powalg.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..adc9d16e89c129b263b29015d9e9f524ab2abe55 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/powalg.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/preproc.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/preproc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e28323fac99ff4c93cc54c8e84536fee000cdadb Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/preproc.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/present.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/present.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..539555bb9bbc07112868f5ea475c934d1d0b589a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/present.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/ratio.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/ratio.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..15ba27e80e30e15a687f05b35755332d14301679 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/ratio.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/redrho.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/redrho.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fe590395a892ce498d3da01c3ef8678276042fe6 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/redrho.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/selectx.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/selectx.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d25c60c9bfc7ac2989481268d46c9ec43bff7590 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/__pycache__/selectx.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/_bounds.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/_bounds.py new file mode 100644 index 0000000000000000000000000000000000000000..89afe9529f21235fc659d661df5f6037688bfdcf --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/_bounds.py @@ -0,0 +1,34 @@ +import numpy as np +from scipy.optimize import Bounds + +def process_bounds(bounds, lenx0): + ''' + `bounds` can either be an object with the properties lb and ub, or a list of tuples + indicating a lower bound and an upper bound for each variable. If the list contains + fewer entries than the length of x0, the remaining entries will generated as -/+ infinity. + Some examples of valid lists of tuple, assuming len(x0) == 3: + [(0, 1), (2, 3), (4, 5)] -> returns [0, 2, 4], [1, 3, 5] + [(0, 1), (None, 3)] -> returns [0, -inf, -inf], [1, 3, inf] + [(0, 1), (-np.inf, 3)] -> returns [0, -inf, -inf], [1, 3, inf] + ''' + + if bounds is None: + lb = np.array([-np.inf]*lenx0, dtype=np.float64) + ub = np.array([np.inf]*lenx0, dtype=np.float64) + return lb, ub + + if isinstance(bounds, Bounds): + lb = np.array(bounds.lb, dtype=np.float64) + ub = np.array(bounds.ub, dtype=np.float64) + lb = np.concatenate((lb, -np.inf*np.ones(lenx0 - len(lb)))) + ub = np.concatenate((ub, np.inf*np.ones(lenx0 - len(ub)))) + return lb, ub + + # If neither of the above conditions are true, we assume that bounds is a list of tuples + lb = np.array([bound[0] if bound[0] is not None else -np.inf for bound in bounds], dtype=np.float64) + ub = np.array([bound[1] if bound[1] is not None else np.inf for bound in bounds], dtype=np.float64) + # If there were fewer bounds than variables, pad the rest with -/+ infinity + lb = np.concatenate((lb, -np.inf*np.ones(lenx0 - len(lb)))) + ub = np.concatenate((ub, np.inf*np.ones(lenx0 - len(ub)))) + + return lb, ub diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/_linear_constraints.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/_linear_constraints.py new file mode 100644 index 0000000000000000000000000000000000000000..be508dced7edd7cda998d840bf195411a140b2ad --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/_linear_constraints.py @@ -0,0 +1,46 @@ +import numpy as np +from scipy.optimize import LinearConstraint + + +def combine_multiple_linear_constraints(constraints): + full_A = constraints[0].A + full_lb = constraints[0].lb + full_ub = constraints[0].ub + for constraint in constraints[1:]: + full_A = np.concatenate((full_A, constraint.A), axis=0) + full_lb = np.concatenate((full_lb, constraint.lb), axis=0) + full_ub = np.concatenate((full_ub, constraint.ub), axis=0) + return LinearConstraint(full_A, full_lb, full_ub) + + +def separate_LC_into_eq_and_ineq(linear_constraint): + # The Python interface receives linear constraints lb <= A*x <= ub, but the + # Fortran backend of PRIMA expects that the linear constraints are specified + # as A_eq*x = b_eq, A_ineq*x <= b_ineq. + # As such, we must: + # 1. for constraints with lb == ub, rewrite them as A_eq*x = lb; + # 2. for constraints with lb < ub, rewrite them as A_ineq*x <= b_ineq. + + # We suppose lb == ub if ub <= lb + 2*epsilon, assuming that the preprocessing + # ensures lb <= ub. + epsilon = np.finfo(np.float64).eps + + eq_indices = (linear_constraint.ub <= (linear_constraint.lb + 2*epsilon)) + A_eq = linear_constraint.A[eq_indices] + b_eq = (linear_constraint.lb[eq_indices] + linear_constraint.ub[eq_indices])/2.0 + + ineq_lb_indices = (linear_constraint.lb > -np.inf) + A_ineq_lb = -linear_constraint.A[~eq_indices & ineq_lb_indices] + b_ineq_lb = -linear_constraint.lb[~eq_indices & ineq_lb_indices] + ineq_ub_indices = (linear_constraint.ub < np.inf) + A_ineq_ub = linear_constraint.A[~eq_indices & ineq_ub_indices] + b_ineq_ub = linear_constraint.ub[~eq_indices & ineq_ub_indices] + A_ineq = np.concatenate((A_ineq_lb, A_ineq_ub)) + b_ineq = np.concatenate((b_ineq_lb, b_ineq_ub)) + + # Ensure dtype is float64, or set to None if empty + A_eq = np.array(A_eq, dtype=np.float64) if len(A_eq) > 0 else None + b_eq = np.array(b_eq, dtype=np.float64) if len(b_eq) > 0 else None + A_ineq = np.array(A_ineq, dtype=np.float64) if len(A_ineq) > 0 else None + b_ineq = np.array(b_ineq, dtype=np.float64) if len(b_ineq) > 0 else None + return A_eq, b_eq, A_ineq, b_ineq diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/_nonlinear_constraints.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/_nonlinear_constraints.py new file mode 100644 index 0000000000000000000000000000000000000000..bfee3b7f2cf2e591b5d956cf3a1ae75cc79f1a19 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/_nonlinear_constraints.py @@ -0,0 +1,54 @@ +import numpy as np + +def transform_constraint_function(nlc): + ''' + The Python interfaces receives the constraints as lb <= constraint(x) <= ub, + but the Fortran backend expects the nonlinear constraints to be constraint(x) <= 0. + Thus a conversion is needed. + + In addition to the conversion, we add a check to ensure that the provided lower/upper bounds + have a shape consistent with the output of the constraint function. + ''' + + def newconstraint(x): + values = np.atleast_1d(np.array(nlc.fun(x), dtype=np.float64)) + + # Upgrade the lower/upper bounds to vectors if necessary + lb = nlc.lb + try: + _ = len(lb) + except TypeError: + lb = np.array([nlc.lb]*len(values), dtype=np.float64) + + ub = nlc.ub + try: + _ = len(ub) + except TypeError: + ub = np.array([nlc.ub]*len(values), dtype=np.float64) + + + # Check the shapes and raise an exception if they do not match + if len(values) != len(lb): + raise ValueError("The number of elements in the constraint function's output does not match the number of elements in the lower bound.") + if len(values) != len(ub): + raise ValueError("The number of elements in the constraint function's output does not match the number of elements in the upper bound.") + + # Combine the upper and lower bounds to transform the function into the form + # expected by the Fortran backend. + return np.concatenate(([lb_ii - vi for lb_ii, vi in zip(lb, values) if lb_ii > -np.inf], + [vi - ub_ii for ub_ii, vi in zip(ub, values) if ub_ii < np.inf], + )) + return newconstraint + + +def process_nl_constraints(nlcs): + functions = [] + for nlc in nlcs: + fun_i = transform_constraint_function(nlc) + functions.append(fun_i) + def constraint_function(x): + values = np.empty(0, dtype=np.float64) + for fun in functions: + values = np.concatenate((values, fun(x))) + return values + return constraint_function diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/_project.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/_project.py new file mode 100644 index 0000000000000000000000000000000000000000..233a4e32e905d9a4d3b91f3918de766f51a085fc --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/_project.py @@ -0,0 +1,173 @@ +''' +This module provides the _project function that attempts to project the initial guess +onto the feasible set. + +Adapted from the corresponding function in the PDFO package (https://www.pdfo.net) by +Tom M. Ragonneau (https://ragonneau.github.io) and Zaikun Zhang (https://www.zhangzk.net). +''' + +import numpy as np +from ._linear_constraints import LinearConstraint +from scipy.optimize import OptimizeResult + +# All the accepted scalar types; np.generic correspond to all NumPy types. +scalar_types = (int, float, np.generic) +eps = np.finfo(np.float64).eps + +def _project(x0, lb, ub, constraints): + """Projection of the initial guess onto the feasible set. + + Parameters + ---------- + x0: ndarray, shape (n,) + The same as in prepdfo. + lb: ndarray, shape (n,) + The same as in prepdfo. + ub: ndarray, shape (n,) + The same as in prepdfo. + constraints: dict + The general constraints of the problem, defined as a dictionary with + fields: + linear: LinearConstraint + The linear constraints of the problem. + nonlinear: dict + The nonlinear constraints of the problem. When ``_project`` is called, the nonlinear constraints are + None. + + Returns + ------- + result: OptimizeResult + The result of the projection. + + Authors + ------- + Tom M. RAGONNEAU (ragonneau.github.io) + and Zaikun ZHANG (www.zhangzk.net) + + Dedicated to the late Professor M. J. D. Powell FRS (1936--2015). + """ + invoker = 'prima' + + # Validate x0. + if isinstance(x0, scalar_types): + x0_c = [x0] + elif hasattr(x0, '__len__'): + x0_c = x0 + else: + raise ValueError('{}: UNEXPECTED ERROR: x0 should be a vector.'.format(invoker)) + try: + x0_c = np.asarray(x0_c, dtype=np.float64) + except ValueError: + raise ValueError('{}: UNEXPECTED ERROR: x0 should contain only scalars.'.format(invoker)) + if len(x0_c.shape) != 1: + raise ValueError('{}: UNEXPECTED ERROR: x0 should be a vector.'.format(invoker)) + lenx0 = x0_c.size + + # Validate lb. + if isinstance(lb, scalar_types): + lb_c = [lb] + elif hasattr(lb, '__len__'): + lb_c = lb + else: + raise ValueError('{}: UNEXPECTED ERROR: lb should be a vector.'.format(invoker)) + try: + lb_c = np.asarray(lb_c, dtype=np.float64) + except ValueError: + raise ValueError('{}: UNEXPECTED ERROR: lb should contain only scalars.'.format(invoker)) + if len(lb_c.shape) != 1 or lb_c.size != lenx0: + raise ValueError('{}: UNEXPECTED ERROR: the size of lb is inconsistent with x0.'.format(invoker)) + + # Validate ub. + if isinstance(ub, scalar_types): + ub_c = [ub] + elif hasattr(ub, '__len__'): + ub_c = ub + else: + raise ValueError('{}: UNEXPECTED ERROR: ub should be a vector.'.format(invoker)) + try: + ub_c = np.asarray(ub_c, dtype=np.float64) + except ValueError: + raise ValueError('{}: UNEXPECTED ERROR: ub should contain only scalars.'.format(invoker)) + if len(ub_c.shape) != 1 or ub_c.size != lenx0: + raise ValueError('{}: UNEXPECTED ERROR: the size of ub is inconsistent with x0.'.format(invoker)) + + # Validate constraints. + if not isinstance(constraints, dict) or not ({'linear', 'nonlinear'} <= set(constraints.keys())) or \ + not (isinstance(constraints['linear'], LinearConstraint) or constraints['linear'] is None): + # the nonlinear constraints will not be taken into account in this function and are, therefore, not validated + raise ValueError('{}: UNEXPECTED ERROR: The constraints are ill-defined.'.format(invoker)) + + max_con = 1e20 # Decide whether an inequality constraint can be ignored + + # Project onto the feasible set. + if constraints['linear'] is None: + # Direct projection onto the bound constraints + x_proj = np.nanmin((np.nanmax((x0_c, lb_c), axis=0), ub_c), axis=0) + return OptimizeResult(x=x_proj) + elif all(np.less_equal(np.abs(constraints['linear'].ub - constraints['linear'].lb), eps)) and \ + np.max(lb_c) <= -max_con and np.min(ub_c) >= max_con: + # The linear constraints are all equality constraints. The projection can therefore be done by solving the + # least-squares problem: min ||A*x - (b - A*x_0)||. + a = constraints['linear'].A + b = (constraints['linear'].lb + constraints['linear'].ub) / 2 + xi, _, _, _ = np.linalg.lstsq(a, b - np.dot(a, x0_c), rcond=None) + + # The problem is not bounded. However, if the least-square solver returned values bigger in absolute value + # than max_con, they will be reduced to this bound. + x_proj = np.nanmin((np.nanmax((x0_c + xi, lb_c), axis=0), ub_c), axis=0) + + return OptimizeResult(x=x_proj) + + if constraints['linear'] is not None: + try: + # Project the initial guess onto the linear constraints via SciPy. + from scipy.optimize import minimize + from scipy.optimize import Bounds as ScipyBounds + from scipy.optimize import LinearConstraint as ScipyLinearConstraint + + linear = constraints['linear'] + + # To be more efficient, SciPy asks to separate the equality and the inequality constraints into two + # different LinearConstraint structures + pc_args_ineq, pc_args_eq = dict(), dict() + pc_args_ineq['A'], pc_args_eq['A'] = np.asarray([[]]), np.asarray([[]]) + pc_args_ineq['A'] = pc_args_ineq['A'].reshape(0, linear.A.shape[1]) + pc_args_eq['A'] = pc_args_eq['A'].reshape(0, linear.A.shape[1]) + pc_args_ineq['lb'], pc_args_eq['lb'] = np.asarray([]), np.asarray([]) + pc_args_ineq['ub'], pc_args_eq['ub'] = np.asarray([]), np.asarray([]) + + for i in range(linear.lb.size): + if linear.lb[i] != linear.ub[i]: + pc_args_ineq['A'] = np.concatenate((pc_args_ineq['A'], linear.A[i:i+1, :]), axis=0) + pc_args_ineq['lb'] = np.r_[pc_args_ineq['lb'], linear.lb[i]] + pc_args_ineq['ub'] = np.r_[pc_args_ineq['ub'], linear.ub[i]] + else: + pc_args_eq['A'] = np.concatenate((pc_args_eq['A'], linear.A[i:i+1, :]), axis=0) + pc_args_eq['lb'] = np.r_[pc_args_eq['lb'], linear.lb[i]] + pc_args_eq['ub'] = np.r_[pc_args_eq['ub'], linear.ub[i]] + + if pc_args_ineq['A'].size > 0 and pc_args_ineq['lb'].size > 0 and pc_args_eq['lb'].size > 0: + project_constraints = [ScipyLinearConstraint(**pc_args_ineq), ScipyLinearConstraint(**pc_args_eq)] + elif pc_args_ineq['A'].size > 0 and pc_args_ineq['lb'].size > 0: + project_constraints = ScipyLinearConstraint(**pc_args_ineq) + elif pc_args_eq['A'].size > 0: + project_constraints = ScipyLinearConstraint(**pc_args_eq) + else: + project_constraints = () + + # Perform the actual projection. + ax_ineq = np.dot(pc_args_ineq['A'], x0_c) + ax_eq = np.dot(pc_args_eq['A'], x0_c) + if np.greater(ax_ineq, pc_args_ineq['ub']).any() or np.greater(pc_args_ineq['lb'], ax_ineq).any() or \ + np.not_equal(ax_eq, pc_args_eq['lb']).any() or \ + np.greater(x0_c, ub_c).any() or np.greater(lb_c, x0_c).any(): + return minimize(lambda x: np.dot(x - x0_c, x - x0_c) / 2, x0_c, jac=lambda x: (x - x0_c), + bounds=ScipyBounds(lb_c, ub_c), constraints=project_constraints) + else: + # Do not perform any projection if the initial guess is feasible. + return OptimizeResult(x=x0_c) + + except ImportError: + return OptimizeResult(x=x0_c) + + return OptimizeResult(x=x0_c) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/checkbreak.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/checkbreak.py new file mode 100644 index 0000000000000000000000000000000000000000..95efd6c14b3dc6e572b3d83a7f47b419ac050c93 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/checkbreak.py @@ -0,0 +1,93 @@ +''' +This module checks whether to break out of the solver loop. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +from .infos import INFO_DEFAULT, NAN_INF_X, NAN_INF_F, FTARGET_ACHIEVED, MAXFUN_REACHED + +import numpy as np + +def checkbreak_unc(maxfun, nf, f, ftarget, x): + ''' + This module checks whether to break out of the solver loop in the unconstrained case. + ''' + + # Outputs + info = INFO_DEFAULT + + # Local variables + srname = "CHECKbreak_UNC" + + # Preconditions + assert INFO_DEFAULT not in [NAN_INF_X, NAN_INF_F, FTARGET_ACHIEVED, MAXFUN_REACHED], f'NAN_INF_X, NAN_INF_F, FTARGET_ACHIEVED, and MAXFUN_REACHED differ from INFO_DFT {srname}' + # X does not contain NaN if the initial X does not contain NaN and the subroutines generating + # trust-region/geometry steps work properly so that they never produce a step containing NaN/Inf. + assert not any(np.isnan(x)), f'X does not contain NaN {srname}' + # With the moderated extreme barrier, F cannot be NaN/+Inf. + assert not (any(np.isnan(f)) or any(np.isposinf(f))), f'F is not NaN/+Inf {srname}' + + #====================# + # Calculation starts # + #====================# + + # Although X should not contain NaN unless there is a bug, we include the following for security. + # X can be Inf, as finite + finite can be Inf numerically. + if any(np.isnan(x)) or any(np.isinf(x)): + info = NAN_INF_X + + # Although NAN_INF_F should not happen unless there is a bug, we include the following for security. + if any(np.isnan(f)) or any(np.isposinf(f)): + info = NAN_INF_F + + if f <= ftarget: + info = FTARGET_ACHIEVED + + if nf >= maxfun: + info = MAXFUN_REACHED + + return info + +def checkbreak_con(maxfun, nf, cstrv, ctol, f, ftarget, x): + ''' + This module checks whether to break out of the solver loop in the constrained case. + ''' + + # Outputs + info = INFO_DEFAULT + + # Local variables + srname = "CHECKbreak_CON" + + # Preconditions + assert INFO_DEFAULT not in [NAN_INF_X, NAN_INF_F, FTARGET_ACHIEVED, MAXFUN_REACHED], f'NAN_INF_X, NAN_INF_F, FTARGET_ACHIEVED, and MAXFUN_REACHED differ from INFO_DFT {srname}' + # X does not contain NaN if the initial X does not contain NaN and the subroutines generating + # trust-region/geometry steps work properly so that they never produce a step containing NaN/Inf. + assert not any(np.isnan(x)), f'X does not contain NaN {srname}' + # With the moderated extreme barrier, F or CSTRV cannot be NaN/+Inf. + assert not (np.isnan(f) or np.isposinf(f) or np.isnan(cstrv) or np.isposinf(cstrv)), f'F or CSTRV is not NaN/+Inf {srname}' + + #====================# + # Calculation starts # + #====================# + + # Although X should not contain NaN unless there is a bug, we include the following for security. + # X can be Inf, as finite + finite can be Inf numerically. + if any(np.isnan(x)) or any(np.isinf(x)): + info = NAN_INF_X + + # Although NAN_INF_F should not happen unless there is a bug, we include the following for security. + if np.isnan(f) or np.isposinf(f) or np.isnan(cstrv) or np.isposinf(cstrv): + info = NAN_INF_F + + if cstrv <= ctol and f <= ftarget: + info = FTARGET_ACHIEVED + + if nf >= maxfun: + info = MAXFUN_REACHED + + return info diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/consts.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/consts.py new file mode 100644 index 0000000000000000000000000000000000000000..1916bae39cf08a495af8008cd623eb45680914e8 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/consts.py @@ -0,0 +1,47 @@ +''' +This is a module defining some constants. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +import numpy as np +import os + +DEBUGGING = bool(os.getenv('PRIMA_DEBUGGING')) + +REALMIN = np.finfo(float).tiny +REALMAX = np.finfo(float).max +FUNCMAX = 10.0**30 +CONSTRMAX = FUNCMAX +EPS = np.finfo(float).eps + +# Any bound with an absolute value at least BOUNDMAX is considered as no bound. +BOUNDMAX = REALMAX/4 + +# Some default values +RHOBEG_DEFAULT = 1 +RHOEND_DEFAULT = 1e-6 +FTARGET_DEFAULT = -REALMAX +CTOL_DEFAULT = np.sqrt(EPS) +CWEIGHT_DEFAULT = 1e8 +ETA1_DEFAULT = 0.1 +ETA2_DEFAULT = 0.7 +GAMMA1_DEFAULT = 0.5 +GAMMA2_DEFAULT = 2 +IPRINT_DEFAULT = 0 +MAXFUN_DIM_DEFAULT = 500 + +PRIMA_MAX_HIST_MEM_MB = 300 # 1MB > 10^5*REAL64. 100 can be too small. + +# Maximal amount of memory (Byte) allowed for XHIST, FHIST, CONHIST, CHIST, and the filters. +MHM = PRIMA_MAX_HIST_MEM_MB * 10**6 +# Make sure that MAXHISTMEM does not exceed HUGE(0) to avoid overflow and memory errors. +MAXHISTMEM = min(MHM, np.iinfo(np.int32).max) + +# Maximal length of the filter used in constrained solvers. +MIN_MAXFILT = 200 # Should be positive; < 200 is not recommended. +MAXFILT_DEFAULT = 10 * MIN_MAXFILT diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/evaluate.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/evaluate.py new file mode 100644 index 0000000000000000000000000000000000000000..075e1d42fa30fcd0eaeb7b40a491f41623e27293 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/evaluate.py @@ -0,0 +1,99 @@ +''' +This is a module evaluating the objective/constraint function with Nan/Inf handling. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +import numpy as np +from .consts import FUNCMAX, CONSTRMAX, REALMAX, DEBUGGING +from .linalg import matprod, primasum + +# This is a module evaluating the objective/constraint function with Nan/Inf handling. + + +def moderatex(x): + ''' + This function moderates a decision variable. It replaces NaN by 0 and Inf/-Inf by + REALMAX/-REALMAX. + ''' + x[np.isnan(x)] = 0 + x = np.clip(x, -REALMAX, REALMAX) + return x + +def moderatef(f): + """ + This function moderates the function value of a MINIMIZATION problem. It replaces + NaN and any value above FUNCMAX by FUNCMAX. + """ + f = FUNCMAX if np.isnan(f) else f + f = np.clip(f, -REALMAX, FUNCMAX) + # We may moderate huge negative function values as follows, but we decide not to. + # f = np.clip(f, -FUNCMAX, FUNCMAX) + return f + + +def moderatec(c): + """ + This function moderates the constraint value, the constraint demanding this value + to be NONNEGATIVE. It replaces any value below -CONSTRMAX by -CONSTRMAX, and any + NaN or value above CONSTRMAX by CONSTRMAX. + """ + np.nan_to_num(c, copy=False, nan=CONSTRMAX) + c = np.clip(c, -CONSTRMAX, CONSTRMAX) + return c + + +def evaluate(calcfc, x, m_nlcon, amat, bvec): + """ + This function evaluates CALCFC at X, returning the objective function value and the + constraint value. Nan/Inf are handled by a moderated extreme barrier. + """ + + # Sizes + m_lcon = len(bvec) if bvec is not None else 0 + + # Preconditions + if DEBUGGING: + # X should not contain NaN if the initial X does not contain NaN and the + # subroutines generating # trust-region/geometry steps work properly so that + # they never produce a step containing NaN/Inf. + assert not any(np.isnan(x)) + + #====================# + # Calculation starts # + #====================# + + constr = np.zeros(m_lcon + m_nlcon) + if amat is not None: + constr[:m_lcon] = matprod(x, amat.T) - bvec + + if any(np.isnan(x)): + # Although this should not happen unless there is a bug, we include this case + # for robustness. + f = primasum(x) + constr = np.ones(m_nlcon) * f + else: + f, constr[m_lcon:] = calcfc(moderatex(x)) + + # Moderated extreme barrier: replace NaN/huge objective or constraint values + # with a large but finite value. This is naive, and better approaches surely + # exist. + f = moderatef(f) + constr[m_lcon:] = moderatec(constr[m_lcon:]) + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + # With X not containing NaN, and with the moderated extreme barrier, F cannot + # be NaN/+Inf, and CONSTR cannot be NaN/-Inf. + assert not (np.isnan(f) or np.isposinf(f)) + assert not any(np.isnan(constr) | np.isposinf(constr)) + + return f, constr diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/history.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/history.py new file mode 100644 index 0000000000000000000000000000000000000000..212db7305d890d0133afb312ed6c73b79f8bb0fa --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/history.py @@ -0,0 +1,38 @@ +''' +This module provides subroutines that handle the X/F/C histories of the solver, taking into +account that MAXHIST may be smaller than NF. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +def savehist(maxhist, x, xhist, f, fhist, cstrv, chist, constr, conhist): + ''' + Save the data values to the history lists. + + The implementation of this function is vastly different from the Fortran implementation. + This is mostly due to the ease of creating and appending to lists in Python + + However just like the Fortran version we should be concerned about both performance + and memory constraints. It will probably be better to initialize an array of NaN for + each of the histories and keep track of how many indices we have stored. Not needed for + the moment. + ''' + if len(xhist) < maxhist: + xhist.append(x) + fhist.append(f) + chist.append(cstrv) + conhist.append(constr) + else: + # This effectively accomplishes what rangehist does in the Fortran implementation + xhist.pop(0) + fhist.pop(0) + chist.pop(0) + conhist.pop(0) + xhist.append(x) + fhist.append(f) + chist.append(cstrv) + conhist.append(constr) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/infos.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/infos.py new file mode 100644 index 0000000000000000000000000000000000000000..27d0f1e144bdfabf1633ccfccaab2ac5dd93781f --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/infos.py @@ -0,0 +1,30 @@ +''' +This is a module defining exit flags. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +INFO_DEFAULT = 0 +SMALL_TR_RADIUS = 0 +FTARGET_ACHIEVED = 1 +TRSUBP_FAILED = 2 +MAXFUN_REACHED = 3 +MAXTR_REACHED = 20 +NAN_INF_X = -1 +NAN_INF_F = -2 +NAN_INF_MODEL = -3 +NO_SPACE_BETWEEN_BOUNDS = 6 +DAMAGING_ROUNDING = 7 +ZERO_LINEAR_CONSTRAINT = 8 +CALLBACK_TERMINATE = 30 + +# Stop-codes. +# The following codes are used by ERROR STOP as stop-codes, which should be default integers. +INVALID_INPUT = 100 +ASSERTION_FAILS = 101 +VALIDATION_FAILS = 102 +MEMORY_ALLOCATION_FAILS = 103 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/linalg.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/linalg.py new file mode 100644 index 0000000000000000000000000000000000000000..a5ee756aaf867ca76afe9cbb5f768c2097ecbadc --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/linalg.py @@ -0,0 +1,435 @@ +''' +This module provides some basic linear algebra procedures. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +import numpy as np +from .consts import DEBUGGING, EPS, REALMAX, REALMIN +from .present import present + + +# We use naive implementations of matrix multiplication and other routines for two +# reasons: +# 1. When Fortran is compiled in debug mode, and Python is using these routines, we +# can get bit for bit identical results as compared to Fortran. This is helpful +# for comparing the two implementations. It will be particularly helpful when porting +# the other implementations like LINCOA, etc. +# 2. On some problems this algorithm is very sensitive to errors in finite precision +# arithmetic. Switching to naive implementation will slow down the algorithm, but +# may be more stable. +USE_NAIVE_MATH = False + + +def inprod(x, y): + if not USE_NAIVE_MATH: + return np.dot(x, y) + result = 0 + for i in range(len(x)): + result += x[i] * y[i] + return result + + +def matprod12(x, y): + result = np.zeros(y.shape[1]) + for i in range(y.shape[1]): + result[i] = inprod(x, y[:, i]) + return result + + +def matprod21(x, y): + result = np.zeros(x.shape[0]) + for i in range(x.shape[1]): + result += x[:, i] * y[i] + return result + + +def matprod22(x, y): + result = np.zeros((x.shape[0], y.shape[1])) + for i in range(y.shape[1]): + for j in range(x.shape[1]): + result[:, j] += x[:, i] * y[i, j] + return result + + +def matprod(x, y): + if not USE_NAIVE_MATH: + return x@y + if len(x.shape) == 1 and len(y.shape) == 1: + return inprod(x, y) + elif len(x.shape) == 1 and len(y.shape) == 2: + return matprod12(x, y) + elif len(x.shape) == 2 and len(y.shape) == 1: + return matprod21(x, y) + elif len(x.shape) == 2 and len(y.shape) == 2: + return matprod22(x, y) + else: + raise ValueError(f'Invalid shapes for x and y: {x.shape} and {y.shape}') + + +def outprod(x, y): + if not USE_NAIVE_MATH: + return np.outer(x, y) + result = np.zeros((len(x), len(y))) + for i in range(len(x)): + result[:, i] = x * y[i] + return result + + +def lsqr(A, b, Q, Rdiag): + if not USE_NAIVE_MATH: + return np.linalg.lstsq(A, b, rcond=None)[0] + + m = A.shape[0] + n = A.shape[1] + + rank = min(m, n) + + x = np.zeros(n) + y = b.copy() + + for i in range(rank - 1, -1, -1): + yq = inprod(y, Q[:, i]) + yqa = inprod(np.abs(y), np.abs(Q[:, i])) + if isminor(yq, yqa): + x[i] = 0 + else: + x[i] = yq / Rdiag[i] + y = y - x[i] * A[:, i] + return x + + +def hypot(x1, x2): + if not USE_NAIVE_MATH: + return np.hypot(x1, x2) + if not np.isfinite(x1): + r = abs(x1) + elif not np.isfinite(x2): + r = abs(x2) + else: + y = abs(np.array([x1, x2])) + y = np.array([min(y), max(y)]) + if y[0] > np.sqrt(REALMIN) and y[1] < np.sqrt(REALMAX/2.1): + r = np.sqrt(sum(y*y)) + elif y[1] > 0: + r = y[1] * np.sqrt((y[0]/y[1])*(y[0]/y[1]) + 1) + else: + r = 0 + return r + + +def norm(x): + if not USE_NAIVE_MATH: + return np.linalg.norm(x) + # NOTE: Avoid np.pow! And exponentiation in general! + # It appears that in Fortran, x*x and x**2 are the same, but in Python they are not! + # Try it with x = 5 - 1e-15 + result = np.sqrt(sum([xi*xi for xi in x])) + return result + + +def istril(A, tol=0): + return primasum(abs(A) - np.tril(abs(A))) <= tol + +def istriu(A, tol=0): + return primasum(abs(A) - np.triu(abs(A))) <= tol + + +def inv(A): + if not USE_NAIVE_MATH: + return np.linalg.inv(A) + A = A.copy() + n = A.shape[0] + if istril(A): + # This case is invoked in COBYLA. + R = A.T + B = np.zeros((n, n)) + for i in range(n): + B[i, i] = 1 / R[i, i] + B[:i, i] = -matprod(B[:i, :i], R[:i, i]) / R[i, i] + return B.T + elif istriu(A): + B = np.zeros((n, n)) + for i in range(n): + B[i, i] = 1 / A[i, i] + B[:i, i] = -matprod(B[:i, :i], A[:i, i]) / A[i, i] + else: + # This is NOT the best algorithm for the inverse, but since the QR subroutine is available ... + Q, R, P = qr(A) + R = R.T + B = np.zeros((n, n)) + for i in range(n - 1, -1, -1): + B[:, i] = (Q[:, i] - matprod(B[:, i + 1:n], R[i + 1:n, i])) / R[i, i] + InvP = np.zeros(n, dtype=int) + InvP[P] = np.linspace(0, n-1, n) + B = B[:, InvP].T + return B + + +def qr(A): + m = A.shape[0] + n = A.shape[1] + + Q = np.eye(m) + T = A.T + P = np.linspace(0, n-1, n, dtype=int) + + for j in range(n): + k = np.argmax(primasum(primapow2(T[j:n+1, j:m+1]), axis=1), axis=0) + if k > 0 and k <= n - j - 1: + k += j + P[j], P[k] = P[k], P[j] + T[[j, k], :] = T[[k, j], :] + for i in range(m-1, j, -1): + G = planerot(T[j, [j, i]]).T + T[j, [j, i]] = np.append(hypot(T[j, j], T[j, i]), 0) + T[j + 1:n + 1, [j, i]] = matprod(T[j + 1:n + 1, [j, i]], G) + Q[:, [j, i]] = matprod(Q[:, [j, i]], G) + + R = T.T + + return Q, R, P + + +def primasum(x, axis=None): + ''' + According to its documentation, np.sum will sometimes do partial pairwise summation. + For our purposes, when comparing, we want don't want to do anything fancy, and we + just want to add things up one at a time. + ''' + if not USE_NAIVE_MATH: + return np.sum(x, axis=axis) + if axis is None: + if x.ndim == 2: + # Sum columns first, then sum the result + return sum(primasum(x, axis=0)) + else: + return sum(x) + elif axis == 0: + result = np.zeros(x.shape[1]) + for i in range(x.shape[1]): + result[i] = sum(x[:, i]) + return result + elif axis == 1: + result = np.zeros(x.shape[0]) + for i in range(x.shape[0]): + result[i] = sum(x[i, :]) + return result + + +def primapow2(x): + ''' + Believe it or now, x**2 is not always the same as x*x in Python. In Fortran they + appear to be identical. Here's a quick one-line to find an example on your system + (well, two liner after importing numpy): + list(filter(lambda x: x[1], [(x:=np.random.random(), x**2 - x*x != 0) for _ in range(10000)])) + ''' + return x*x + + +def planerot(x): + ''' + As in MATLAB, planerot(x) returns a 2x2 Givens matrix G for x in R2 so that Y=G@x has Y[1] = 0. + Roughly speaking, G = np.array([[x[0]/R, x[1]/R], [-x[1]/R, x[0]/R]]), where R = np.linalg.norm(x). + 0. We need to take care of the possibilities of R=0, Inf, NaN, and over/underflow. + 1. The G defined above is continuous with respect to X except at 0. Following this definition, + G = np.array([[np.sign(x[0]), 0], [0, np.sign(x[0])]]) if x[1] == 0, + G = np.array([[0, np.sign(x[1])], [np.sign(x[1]), 0]]) if x[0] == 0 + Yet some implementations ignore the signs, leading to discontinuity and numerical instability. + 2. Difference from MATLAB: if x contains NaN of consists of only Inf, MATLAB returns a NaN matrix, + but we return an identity matrix or a matrix of +/-np.sqrt(2). We intend to keep G always orthogonal. + ''' + + # Preconditions + if DEBUGGING: + assert len(x) == 2, "x must be a 2-vector" + + # ================== + # Calculation starts + # ================== + + # Define C = X(1) / R and S = X(2) / R with R = HYPOT(X(1), X(2)). Handle Inf/NaN, over/underflow. + if (any(np.isnan(x))): + # In this case, MATLAB sets G to NaN(2, 2). We refrain from doing so to keep G orthogonal. + c = 1 + s = 0 + elif (all(np.isinf(x))): + # In this case, MATLAB sets G to NaN(2, 2). We refrain from doing so to keep G orthogonal. + c = 1 / np.sqrt(2) * np.sign(x[0]) + s = 1 / np.sqrt(2) * np.sign(x[1]) + elif (abs(x[0]) <= 0 and abs(x[1]) <= 0): # X(1) == 0 == X(2). + c = 1 + s = 0 + elif (abs(x[1]) <= EPS * abs(x[0])): + # N.B.: + # 0. With <= instead of <, this case covers X(1) == 0 == X(2), which is treated above separately + # to avoid the confusing SIGN(., 0) (see 1). + # 1. SIGN(A, 0) = ABS(A) in Fortran but sign(0) = 0 in MATLAB, Python, Julia, and R# + # 2. Taking SIGN(X(1)) into account ensures the continuity of G with respect to X except at 0. + c = np.sign(x[0]) + s = 0 + elif (abs(x[0]) <= EPS * abs(x[1])): + # N.B.: SIGN(A, X) = ABS(A) * sign of X /= A * sign of X # Therefore, it is WRONG to define G + # as SIGN(RESHAPE([ZERO, -ONE, ONE, ZERO], [2, 2]), X(2)). This mistake was committed on + # 20211206 and took a whole day to debug! NEVER use SIGN on arrays unless you are really sure. + c = 0 + s = np.sign(x[1]) + else: + # Here is the normal case. It implements the Givens rotation in a stable & continuous way as in: + # Bindel, D., Demmel, J., Kahan, W., and Marques, O. (2002). On computing Givens rotations + # reliably and efficiently. ACM Transactions on Mathematical Software (TOMS), 28(2), 206-238. + # N.B.: 1. Modern compilers compute SQRT(REALMIN) and SQRT(REALMAX/2.1) at compilation time. + # 2. The direct calculation without involving T and U seems to work better; use it if possible. + if (all(np.logical_and(np.sqrt(REALMIN) < np.abs(x), np.abs(x) < np.sqrt(REALMAX / 2.1)))): + # Do NOT use HYPOTENUSE here; the best implementation for one may be suboptimal for the other + r = norm(x) + c = x[0] / r + s = x[1] / r + elif (abs(x[0]) > abs(x[1])): + t = x[1] / x[0] + u = max(1, abs(t), np.sqrt(1 + t*t)) # MAXVAL: precaution against rounding error. + u *= np.sign(x[0]) ##MATLAB: u = sign(x(1))*sqrt(1 + t**2) + c = 1 / u + s = t / u + else: + t = x[0] / x[1] + u = max([1, abs(t), np.sqrt(1 + t*t)]) # MAXVAL: precaution against rounding error. + u *= np.sign(x[1]) ##MATLAB: u = sign(x(2))*sqrt(1 + t**2) + c = t / u + s = 1 / u + + G = np.array([[c, s], [-s, c]]) # MATLAB: G = [c, s; -s, c] + + #====================# + # Calculation ends # + #====================# + + # Postconditions + if DEBUGGING: + assert G.shape == (2,2) + assert np.all(np.isfinite(G)) + assert abs(G[0, 0] - G[1, 1]) + abs(G[0, 1] + G[1, 0]) <= 0 + tol = np.maximum(1.0E-10, np.minimum(1.0E-1, 1.0E6 * EPS)) + assert isorth(G, tol) + if all(np.logical_and(np.isfinite(x), np.abs(x) < np.sqrt(REALMAX / 2.1))): + r = np.linalg.norm(x) + assert max(abs(G@x - [r, 0])) <= max(tol, tol * r), 'G @ X = [||X||, 0]' + + return G + + +def isminor(x, ref): + ''' + This function tests whether x is minor compared to ref. It is used by Powell, e.g., in COBYLA. + In precise arithmetic, isminor(x, ref) is true if and only if x == 0; in floating point + arithmetic, isminor(x, ref) is true if x is 0 or its nonzero value can be attributed to + computer rounding errors according to ref. + Larger sensitivity means the function is more strict/precise, the value 0.1 being due to Powell. + + For example: + isminor(1e-20, 1e300) -> True, because in floating point arithmetic 1e-20 cannot be added to + 1e300 without being rounded to 1e300. + isminor(1e300, 1e-20) -> False, because in floating point arithmetic adding 1e300 to 1e-20 + dominates the latter number. + isminor(3, 4) -> False, because 3 can be added to 4 without being rounded off + ''' + + sensitivity = 0.1 + refa = abs(ref) + sensitivity * abs(x) + refb = abs(ref) + 2 * sensitivity * abs(x) + return np.logical_or(abs(ref) >= refa, refa >= refb) + + +def isinv(A, B, tol=None): + ''' + This procedure tests whether A = B^{-1} up to the tolerance TOL. + ''' + + # Sizes + n = np.size(A, 0) + + # Preconditions + if DEBUGGING: + assert np.size(A, 0) == np.size(A, 1) + assert np.size(B, 0) == np.size(B, 1) + assert np.size(A, 0) == np.size(B, 0) + if present(tol): + assert tol >= 0 + + #====================# + # Calculation starts # + #====================# + + tol = tol if present(tol) else np.minimum(1e-3, 1e2 * EPS * np.maximum(np.size(A, 0), np.size(A, 1))) + tol = np.max([tol, tol * np.max(abs(A)), tol * np.max(abs(B))]) + is_inv = ((abs(matprod(A, B)) - np.eye(n)) <= tol).all() or ((abs(matprod(B, A) - np.eye(n))) <= tol).all() + + #===================# + # Calculation ends # + #===================# + return is_inv + + +def isorth(A, tol=None): + ''' + This function tests whether the matrix A has orthonormal columns up to the tolerance TOL. + ''' + + # Preconditions + if DEBUGGING: + if present(tol): + assert tol >= 0 + + #====================# + # Calculation starts # + #====================# + + num_vars = np.size(A, 1) + + if num_vars > np.size(A, 0): + is_orth = False + elif (np.isnan(primasum(abs(A)))): + is_orth = False + else: + if present(tol): + is_orth = (abs(matprod(A.T, A) - np.eye(num_vars)) <= np.maximum(tol, tol * np.max(abs(A)))).all() + else: + is_orth = (abs(matprod(A.T, A) - np.eye(num_vars)) <= 0).all() + + #====================# + # Calculation ends # + #====================# + return is_orth + + +def get_arrays_tol(*arrays): + """ + Get a relative tolerance for a set of arrays. Borrowed from COBYQA + + Parameters + ---------- + *arrays: tuple + Set of `numpy.ndarray` to get the tolerance for. + + Returns + ------- + float + Relative tolerance for the set of arrays. + + Raises + ------ + ValueError + If no array is provided. + """ + if len(arrays) == 0: + raise ValueError("At least one array must be provided.") + size = max(array.size for array in arrays) + weight = max( + np.max(np.abs(array[np.isfinite(array)]), initial=1.0) + for array in arrays + ) + return 10.0 * EPS * max(size, 1.0) * weight diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/message.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/message.py new file mode 100644 index 0000000000000000000000000000000000000000..899d5fa63daa2b55bc6a1050f27786b569c0e92c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/message.py @@ -0,0 +1,290 @@ +''' +This module provides some functions that print messages to terminal/files. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. + +N.B.: +1. In case parallelism is desirable (especially during initialization), the functions may +have to be modified or disabled due to the IO operations. +2. IPRINT indicates the level of verbosity, which increases with the absolute value of IPRINT. +IPRINT = +/-3 can be expensive due to high IO operations. +''' + +from .consts import DEBUGGING +from .infos import FTARGET_ACHIEVED, MAXFUN_REACHED, MAXTR_REACHED, \ + SMALL_TR_RADIUS, TRSUBP_FAILED, NAN_INF_F, NAN_INF_X, NAN_INF_MODEL, DAMAGING_ROUNDING, \ + NO_SPACE_BETWEEN_BOUNDS, ZERO_LINEAR_CONSTRAINT, CALLBACK_TERMINATE +from .present import present +import numpy as np + +spaces = ' ' + + +def get_info_string(solver, info): + if info == FTARGET_ACHIEVED: + reason = 'the target function value is achieved.' + elif info == MAXFUN_REACHED: + reason = 'the objective function has been evaluated MAXFUN times.' + elif info == MAXTR_REACHED: + reason = 'the maximal number of trust region iterations has been reached.' + elif info == SMALL_TR_RADIUS: + reason = 'the trust region radius reaches its lower bound.' + elif info == TRSUBP_FAILED: + reason = 'a trust region step has failed to reduce the quadratic model.' + elif info == NAN_INF_X: + reason = 'NaN or Inf occurs in x.' + elif info == NAN_INF_F: + reason = 'the objective function returns NaN/+Inf.' + elif info == NAN_INF_MODEL: + reason = 'NaN or Inf occurs in the models.' + elif info == DAMAGING_ROUNDING: + reason = 'rounding errors are becoming damaging.' + elif info == NO_SPACE_BETWEEN_BOUNDS: + reason = 'there is no space between the lower and upper bounds of variable.' + elif info == ZERO_LINEAR_CONSTRAINT: + reason = 'one of the linear constraints has a zero gradient' + elif info == CALLBACK_TERMINATE: + reason = 'the callback function requested termination' + else: + reason = 'UNKNOWN EXIT FLAG' + ret_message = f'Return from {solver} because {reason.strip()}' + return ret_message + + +def retmsg(solver, info, iprint, nf, f, x, cstrv=None, constr=None): + ''' + This function prints messages at return. + ''' + # Local variables + valid_exit_codes = [FTARGET_ACHIEVED, MAXFUN_REACHED, MAXTR_REACHED, + SMALL_TR_RADIUS, TRSUBP_FAILED, NAN_INF_F, NAN_INF_X, NAN_INF_MODEL, DAMAGING_ROUNDING, + NO_SPACE_BETWEEN_BOUNDS, ZERO_LINEAR_CONSTRAINT, CALLBACK_TERMINATE] + + # Preconditions + if DEBUGGING: + assert info in valid_exit_codes + + #====================# + # Calculation starts # + #====================# + + if abs(iprint) < 1: # No printing (iprint == 0) + return + elif iprint > 0: # Print the message to the standard out. + fname = '' + else: # Print the message to a file named FNAME. + fname = f'{solver}_output.txt' + + # Decide whether the problem is truly constrained. + if present(constr): + is_constrained = (np.size(constr) > 0) + else: + is_constrained = present(cstrv) + + # Decide the constraint violation. + if present(cstrv): + cstrv_loc = cstrv + elif present(constr): + cstrv_loc = np.max(np.append(0, -constr)) # N.B.: We assume that the constraint is CONSTR >= 0. + else: + cstrv_loc = 0 + + # Decide the return message. + ret_message = get_info_string(solver, info) + + if np.size(x) <= 2: + x_message = f'\nThe corresponding X is: {x}' # Printed in one line + else: + x_message = f'\nThe corresponding X is:\n{x}' + + if is_constrained: + nf_message = (f'\nNumber of function values = {nf}{spaces}' + f'Least value of F = {f}{spaces}Constraint violation = {cstrv_loc}') + else: + nf_message = f'\nNumber of function values = {nf}{spaces}Least value of F = {f}' + + if is_constrained and present(constr): + if np.size(constr) <= 2: + constr_message = f'\nThe constraint value is: {constr}' # Printed in one line + else: + constr_message = f'\nThe constraint value is:\n{constr}' + else: + constr_message = '' + + # Print the message. + if abs(iprint) >= 2: + message = f'\n{ret_message}{nf_message}{x_message}{constr_message}\n' + else: + message = f'{ret_message}{nf_message}{x_message}{constr_message}\n' + if len(fname) > 0: + with open(fname, 'a') as f: f.write(message) + else: + print(message) + + +def rhomsg(solver, iprint, nf, delta, f, rho, x, cstrv=None, constr=None, cpen=None): + ''' + This function prints messages when RHO is updated. + ''' + + #====================# + # Calculation starts # + #====================# + + if abs(iprint) < 2: # No printing + return + elif iprint > 0: # Print the message to the standard out. + fname = '' + else: # Print the message to a file named FNAME. + fname = f'{solver.strip()}_output.txt' + + # Decide whether the problem is truly constrained. + if present(constr): + is_constrained = (np.size(constr) > 0) + else: + is_constrained = present(cstrv) + + # Decide the constraint violation. + if present(cstrv): + cstrv_loc = cstrv + elif present(constr): + cstrv_loc = np.max(np.append(0, -constr)) # N.B.: We assume that the constraint is CONSTR >= 0. + else: + cstrv_loc = 0 + + if present(cpen): + rho_message = (f'\nNew RHO = {rho}{spaces}Delta = {delta}{spaces}' + f'CPEN = {cpen}') + else: + rho_message = f'\nNew RHO = {rho}{spaces}Delta = {delta}' + + if np.size(x) <= 2: + x_message = f'\nThe corresponding X is: {x}' # Printed in one line + else: + x_message = f'\nThe corresponding X is:\n{x}' + + if is_constrained: + nf_message = (f'\nNumber of function values = {nf}{spaces}' + f'Least value of F = {f}{spaces}Constraint violation = {cstrv_loc}') + else: + nf_message = f'\nNumber of function values = {nf}{spaces}Least value of F = {f}' + + if is_constrained and present(constr): + if np.size(constr) <= 2: + constr_message = f'\nThe constraint value is: {constr}' # Printed in one line + else: + constr_message = f'\nThe constraint value is:\n{constr}' + else: + constr_message = '' + + # Print the message. + if abs(iprint) >= 3: + message = f'\n{rho_message}{nf_message}{x_message}{constr_message}' + else: + message = f'{rho_message}{nf_message}{x_message}{constr_message}' + if len(fname) > 0: + with open(fname, 'a') as f: f.write(message) + else: + print(message) + + #====================# + # Calculation ends # + #====================# + + +def cpenmsg(solver, iprint, cpen): + ''' + This function prints a message when CPEN is updated. + ''' + + #====================# + # Calculation starts # + #====================# + + if abs(iprint) < 2: # No printing + return + elif iprint > 0: # Print the message to the standard out. + fname = '' + else: # Print the message to a file named FNAME. + fname = f'{solver.strip()}_output.txt' + + # Print the message. + if abs(iprint) >= 3: + message = f'\nSet CPEN to {cpen}' + else: + message = f'\n\nSet CPEN to {cpen}' + if len(fname) > 0: + with open(fname, 'a') as f: f.write(message) + else: + print(message) + + #====================# + # Calculation ends # + #====================# + + +def fmsg(solver, state, iprint, nf, delta, f, x, cstrv=None, constr=None): + ''' + This subroutine prints messages for each evaluation of the objective function. + ''' + + #====================# + # Calculation starts # + #====================# + + if abs(iprint) < 2: # No printing + return + elif iprint > 0: # Print the message to the standard out. + fname = '' + else: # Print the message to a file named FNAME. + fname = f'{solver.strip()}_output.txt' + + # Decide whether the problem is truly constrained. + if present(constr): + is_constrained = (np.size(constr) > 0) + else: + is_constrained = present(cstrv) + + # Decide the constraint violation. + if present(cstrv): + cstrv_loc = cstrv + elif present(constr): + cstrv_loc = np.max(np.append(0, -constr)) # N.B.: We assume that the constraint is CONSTR >= 0. + else: + cstrv_loc = 0 + + delta_message = f'\n{state} step with radius = {delta}' + + if is_constrained: + nf_message = (f'\nNumber of function values = {nf}{spaces}' + f'Least value of F = {f}{spaces}Constraint violation = {cstrv_loc}') + else: + nf_message = f'\nNumber of function values = {nf}{spaces}Least value of F = {f}' + + if np.size(x) <= 2: + x_message = f'\nThe corresponding X is: {x}' # Printed in one line + else: + x_message = f'\nThe corresponding X is:\n{x}' + + if is_constrained and present(constr): + if np.size(constr) <= 2: + constr_message = f'\nThe constraint value is: {constr}' # Printed in one line + else: + constr_message = f'\nThe constraint value is:\n{constr}' + else: + constr_message = '' + + # Print the message. + message = f'{delta_message}{nf_message}{x_message}{constr_message}' + if len(fname) > 0: + with open(fname, 'a') as f: f.write(message) + else: + print(message) + + #====================# + # Calculation ends # + #====================# diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/powalg.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/powalg.py new file mode 100644 index 0000000000000000000000000000000000000000..1a8268b2631ba830f8bd36129dd10a3fb9133dc1 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/powalg.py @@ -0,0 +1,131 @@ +''' +This module provides some Powell-style linear algebra procedures. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +import numpy as np +from .linalg import isminor, planerot, matprod, inprod, hypot +from .consts import DEBUGGING, EPS + + +def qradd_Rdiag(c, Q, Rdiag, n): + ''' + This function updates the QR factorization of an MxN matrix A of full column rank, attempting to + add a new column C to this matrix as the LAST column while maintaining the full-rankness. + Case 1. If C is not in range(A) (theoretically, it implies N < M), then the new matrix is np.hstack([A, C]) + Case 2. If C is in range(A), then the new matrix is np.hstack([A[:, :n-1], C]) + N.B.: + 0. Instead of R, this subroutine updates Rdiag, which is np.diag(R), with a size at most M and at + least min(m, n+1). The number is min(m, n+1) rather than min(m, n) as n may be augmented by 1 in + the function. + 1. With the two cases specified as above, this function does not need A as an input. + 2. The function changes only Q[:, nsave:m] (nsave is the original value of n) and + R[:, n-1] (n takes the updated value) + 3. Indeed, when C is in range(A), Powell wrote in comments that "set iOUT to the index of the + constraint (here, column of A --- Zaikun) to be deleted, but branch if no suitable index can be + found". The idea is to replace a column of A by C so that the new matrix still has full rank + (such a column must exist unless C = 0). But his code essentially sets iout=n always. Maybe he + found this worked well enough in practice. Meanwhile, Powell's code includes a snippet that can + never be reached, which was probably intended to deal with the case that IOUT != n + ''' + m = Q.shape[1] + nsave = n # Needed for debugging (only) + + # As in Powell's COBYLA, CQ is set to 0 at the positions with CQ being negligible as per ISMINOR. + # This may not be the best choice if the subroutine is used in other contexts, e.g. LINCOA. + cq = matprod(c, Q) + cqa = matprod(abs(c), abs(Q)) + # The line below basically makes an element of cq 0 if adding it to the corresponding element of + # cqa does not change the latter. + cq = np.array([0 if isminor(cqi, cqai) else cqi for cqi, cqai in zip(cq, cqa)]) + + # Update Q so that the columns of Q[:, n+1:m] are orthogonal to C. This is done by applying a 2D + # Givens rotation to Q[:, [k, k+1]] from the right to zero C' @ Q[:, k+1] out for K=n+1, ... m-1. + # Nothing will be done if n >= m-1 + for k in range(m-2, n-1, -1): + if abs(cq[k+1]) > 0: + # Powell wrote cq[k+1] != 0 instead of abs. The two differ if cq[k+1] is NaN. + # If we apply the rotation below when cq[k+1] = 0, then cq[k] will get updated to |cq[k]|. + G = planerot(cq[k:k+2]) + Q[:, [k, k+1]] = matprod(Q[:, [k, k+1]], G.T) + cq[k] = hypot(*cq[k:k+2]) + + # Augment n by 1 if C is not in range(A) + if n < m: + # Powell's condition for the following if: cq[n+1] != 0 + if abs(cq[n]) > EPS**2 and not isminor(cq[n], cqa[n]): + n += 1 + + # Update Rdiag so that Rdiag[n] = cq[n] = np.dot(c, q[:, n]). Note that N may be been augmented. + if n - 1 >= 0 and n - 1 < m: # n >= m should not happen unless the input is wrong + Rdiag[n - 1] = cq[n - 1] + + if DEBUGGING: + assert nsave <= n <= min(nsave + 1, m) + assert n <= len(Rdiag) <= m + assert Q.shape == (m, m) + + return Q, Rdiag, n + + +def qrexc_Rdiag(A, Q, Rdiag, i): # Used in COBYLA + ''' + This function updates the QR factorization for an MxN matrix A=Q@R so that the updated Q and + R form a QR factorization of [A_0, ..., A_{I-1}, A_{I+1}, ..., A_{N-1}, A_I] which is the matrix + obtained by rearranging columns [I, I+1, ... N-1] of A to [I+1, ..., N-1, I]. Here A is ASSUMED TO + BE OF FULL COLUMN RANK, Q is a matrix whose columns are orthogonal, and R, which is not present, + is an upper triangular matrix whose diagonal entries are nonzero. Q and R need not be square. + N.B.: + 0. Instead of R, this function updates Rdiag, which is np.diag(R), the size being n. + 1. With L = Q.shape[1] = R.shape[0], we have M >= L >= N. Most often L = M or N. + 2. This function changes only Q[:, i:] and Rdiag[i:] + 3. (NDB 20230919) In Python, i is either icon or nact - 2, whereas in FORTRAN it is either icon or nact - 1. + ''' + + # Sizes + m, n = A.shape + + # Preconditions + assert n >= 1 and n <= m + assert i >= 0 and i < n + assert len(Rdiag) == n + assert Q.shape[0] == m and Q.shape[1] >= n and Q.shape[1] <= m + # tol = max(1.0E-8, min(1.0E-1, 1.0E8 * EPS * m + 1)) + # assert isorth(Q, tol) # Costly! + + + if i < 0 or i >= n: + return Q, Rdiag + + # Let R be the upper triangular matrix in the QR factorization, namely R = Q.T@A. + # For each k, find the Givens rotation G with G@(R[k:k+2, :]) = [hypt, 0], and update Q[:, k:k+2] + # to Q[:, k:k+2]@(G.T). Then R = Q.T@A is an upper triangular matrix as long as A[:, [k, k+1]] is + # updated to A[:, [k+1, k]]. Indeed, this new upper triangular matrix can be obtained by first + # updating R[[k, k+1], :] to G@(R[[k, k+1], :]) and then exchanging its columns K and K+1; at the same + # time, entries k and k+1 of R's diagonal Rdiag become [hypt, -(Rdiag[k+1]/hypt)*RDiag[k]]. + # After this is done for each k = 0, ..., n-2, we obtain the QR factorization of the matrix that + # rearranges columns [i, i+1, ... n-1] of A as [i+1, ..., n-1, i]. + # Powell's code, however, is slightly different: before everything, he first exchanged columns k and + # k+1 of Q (as well as rows k and k+1 of R). This makes sure that the entries of the update Rdiag + # are all positive if it is the case for the original Rdiag. + for k in range(i, n-1): + G = planerot([Rdiag[k+1], inprod(Q[:, k], A[:, k+1])]) + Q[:, [k, k+1]] = matprod(Q[:, [k+1, k]], (G.T)) + # Powell's code updates Rdiag in the following way: + # hypt = np.sqrt(Rdiag[k+1]**2 + np.dot(Q[:, k], A[:, k+1])**2) + # Rdiag[[k, k+1]] = [hypt, (Rdiag[k+1]/hypt)*Rdiag[k]] + # Note that Rdiag[n-1] inherits all rounding in Rdiag[i:n-1] and Q[:, i:n-1] and hence contains + # significant errors. Thus we may modify Powell's code to set only Rdiag[k] = hypt here and then + # calculate Rdiag[n] by an inner product after the loop. Nevertheless, we simple calculate RDiag + # from scratch below. + + # Calculate Rdiag(i:n) from scratch + Rdiag[i:n-1] = [inprod(Q[:, k], A[:, k+1]) for k in range(i, n-1)] + Rdiag[n-1] = inprod(Q[:, n-1], A[:, i]) + + return Q, Rdiag diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/preproc.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/preproc.py new file mode 100644 index 0000000000000000000000000000000000000000..465b0b2de289b61be4c560dec89482887002aa24 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/preproc.py @@ -0,0 +1,277 @@ +''' +This is a module that preprocesses the inputs. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +from .consts import DEBUGGING, EPS, IPRINT_DEFAULT, FTARGET_DEFAULT, \ + MIN_MAXFILT, MAXFILT_DEFAULT, MAXHISTMEM, ETA1_DEFAULT, ETA2_DEFAULT, \ + GAMMA1_DEFAULT, GAMMA2_DEFAULT, RHOBEG_DEFAULT, RHOEND_DEFAULT, \ + CTOL_DEFAULT, CWEIGHT_DEFAULT +from .present import present +from warnings import warn +import numpy as np + + +def preproc(solver, num_vars, iprint, maxfun, maxhist, ftarget, rhobeg, rhoend, + num_constraints=None, npt=None, maxfilt=None, ctol=None, cweight=None, + eta1=None, eta2=None, gamma1=None, gamma2=None, is_constrained=None, has_rhobeg=None, + honour_x0=None, xl=None, xu=None, x0=None): + ''' + This subroutine preprocesses the inputs. It does nothing to the inputs that are valid. + ''' + # Preconditions + if DEBUGGING: + assert num_vars >= 1 + if present(num_constraints): + assert num_constraints >= 0 + assert num_constraints == 0 or solver.lower() == 'cobyla' + if solver.lower() == 'cobyla' and present(num_constraints) and present(is_constrained): + assert num_constraints == 0 or is_constrained + if solver.lower() == 'bobyqa': + assert present(xl) and present(xu) + assert all(xu - xl >= 2 * EPS) + if present(honour_x0): + assert solver.lower() == 'bobyqa' and present(has_rhobeg) and present(xl) and present(xu) and present(x0) + + #====================# + # Calculation starts # + #====================# + + # Read num_constraints, if necessary + num_constraints = num_constraints if (present(num_constraints) and solver.lower() == 'cobyla') else 0 + + # Decide whether the problem is truly constrained + is_constrained = is_constrained if (present(is_constrained)) else num_constraints > 0 + + # Validate IPRINT + if np.abs(iprint) > 3: + iprint = IPRINT_DEFAULT + warn(f'{solver}: Invalid IPRINT; it should be 0, 1, -1, 2, -2, 3, or -3; it is set to {iprint}') + + # Validate MAXFUN + if solver.lower() == 'uobyqa': + min_maxfun = (num_vars + 1) * (num_vars + 2) / 2 + 1 + min_maxfun_str = '(N+1)(N+2)/2 + 1' + elif solver.lower() == 'cobyla': + min_maxfun = num_vars + 2 + min_maxfun_str = 'num_vars + 2' + else: # CASE ('NEWUOA', 'BOBYQA', 'LINCOA') + min_maxfun = num_vars + 3 + min_maxfun_str = 'num_vars + 3' + if maxfun < min_maxfun: + maxfun = min_maxfun + warn(f'{solver}: Invalid MAXFUN; it should be at least {min_maxfun_str}; it is set to {maxfun}') + + # Validate MAXHIST + if maxhist < 0: + maxhist = maxfun + warn(f'{solver}: Invalid MAXHIST; it should be a nonnegative integer; it is set to {maxhist}') + maxhist = min(maxhist, maxfun) # MAXHIST > MAXFUN is never needed. + + # Validate FTARGET + if np.isnan(ftarget): + ftarget = FTARGET_DEFAULT + warn(f'{solver}: Invalid FTARGET; it should be a real number; it is set to {ftarget}') + + # Validate NPT + if (solver.lower() == 'newuoa' or solver.lower() == 'bobyqa' or solver.lower() == 'lincoa') and present(npt): + if (npt < num_vars + 2 or npt > min(maxfun - 1, ((num_vars + 2) * (num_vars + 1)) / 2)): + npt = int(min(maxfun - 1, 2 * num_vars + 1)) + warn(f'{solver}: Invalid NPT; it should be an integer in the interval [N+2, (N+1)(N+2)/2] and less than MAXFUN; it is set to {npt}') + + # Validate MAXFILT + if present(maxfilt) and (solver.lower() == 'lincoa' or solver.lower() == 'cobyla'): + maxfilt_in = maxfilt + if maxfilt < 1: + maxfilt = MAXFILT_DEFAULT # The inputted MAXFILT is obviously wrong. + else: + maxfilt = max(MIN_MAXFILT, maxfilt) # The inputted MAXFILT is too small. + # Further revise MAXFILT according to MAXHISTMEM. + if solver.lower() == 'lincoa': + unit_memo = (num_vars + 2) * np.dtype(float).itemsize + elif solver.lower() == 'cobyla': + unit_memo = (num_constraints + num_vars + 2) * np.dtype(float).itemsize + else: + unit_memo = 1 + # We cannot simply set MAXFILT = MIN(MAXFILT, MAXHISTMEM/...), as they may not have + # the same kind, and compilers may complain. We may convert them, but overflow may occur. + if maxfilt > MAXHISTMEM / unit_memo: + maxfilt = int(MAXHISTMEM / unit_memo) # Integer division. + maxfilt = min(maxfun, max(MIN_MAXFILT, maxfilt)) + if is_constrained: + if maxfilt_in < 1: + warn(f'{solver}: Invalid MAXFILT; it should be a positive integer; it is set to {maxfilt}') + elif maxfilt_in < min(maxfun, MIN_MAXFILT): + warn(f'{solver}: MAXFILT is too small; it is set to {maxfilt}') + elif maxfilt < min(maxfilt_in, maxfun): + warn(f'{solver}: MAXFILT is set to {maxfilt} due to memory limit') + + # Validate ETA1 and ETA2 + eta1_local = eta1 if present(eta1) else ETA1_DEFAULT + eta2_local = eta2 if present(eta2) else ETA2_DEFAULT + + # When the difference between ETA1 and ETA2 is tiny, we force them to equal. + # See the explanation around RHOBEG and RHOEND for the reason. + if present(eta1) and present(eta2): + if np.abs(eta1 - eta2) < 1.0E2 * EPS * max(np.abs(eta1), 1): + eta2 = eta1 + + if present(eta1): + if np.isnan(eta1): + # In this case, we take the value hard coded in Powell's original code + # without any warning. It is useful when interfacing with MATLAB/Python. + eta1 = ETA1_DEFAULT + elif eta1 < 0 or eta1 >= 1: + # Take ETA2 into account if it has a valid value. + if present(eta2) and eta2_local > 0 and eta2_local <= 1: + eta1 = max(EPS, eta2 / 7.0) + else: + eta1 = ETA1_DEFAULT + warn(f'{solver}: Invalid ETA1; it should be in the interval [0, 1) and not more than ETA2; it is set to {eta1}') + + if present(eta2): + if np.isnan(eta2): + # In this case, we take the value hard coded in Powell's original code + # without any warning. It is useful when interfacing with MATLAB/Python. + eta2 = ETA2_DEFAULT + elif present(eta1) and (eta2 < eta1_local or eta2 > 1): + eta2 = (eta1 + 2) / 3.0 + warn(f'{solver}: Invalid ETA2; it should be in the interval [0, 1) and not less than ETA1; it is set to {eta2}') + + # Validate GAMMA1 and GAMMA2 + if present(gamma1): + if np.isnan(gamma1): + # In this case, we take the value hard coded in Powell's original code + # without any warning. It is useful when interfacing with MATLAB/Python. + gamma1 = GAMMA1_DEFAULT + elif gamma1 <= 0 or gamma1 >= 1: + gamma1 = GAMMA1_DEFAULT + warn(f'{solver}: Invalid GAMMA1; it should in the interval (0, 1); it is set to {gamma1}') + + if present(gamma2): + if np.isnan(gamma2): + # In this case, we take the value hard coded in Powell's original code + # without any warning. It is useful when interfacing with MATLAB/Python. + gamma2 = GAMMA2_DEFAULT + elif gamma2 < 1 or np.isinf(gamma2): + gamma2 = GAMMA2_DEFAULT + warn(f'{solver}: Invalid GAMMA2; it should be a real number not less than 1; it is set to {gamma2}') + + # Validate RHOBEG and RHOEND + + if np.abs(rhobeg - rhoend) < 1.0e2 * EPS * np.maximum(np.abs(rhobeg), 1): + # When the data is passed from the interfaces (e.g., MEX) to the Fortran code, RHOBEG, and RHOEND + # may change a bit. It was observed in a MATLAB test that MEX passed 1 to Fortran as + # 0.99999999999999978. Therefore, if we set RHOEND = RHOBEG in the interfaces, then it may happen + # that RHOEND > RHOBEG, which is considered as an invalid input. To avoid this situation, we + # force RHOBEG and RHOEND to equal when the difference is tiny. + rhoend = rhobeg + + # Revise the default values for RHOBEG/RHOEND according to the solver. + if solver.lower() == 'bobyqa': + rhobeg_default = np.maximum(EPS, np.min(RHOBEG_DEFAULT, np.min(xu - xl) / 4.0)) + rhoend_default = np.maximum(EPS, np.min(0.1 * rhobeg_default, RHOEND_DEFAULT)) + else: + rhobeg_default = RHOBEG_DEFAULT + rhoend_default = RHOEND_DEFAULT + + if solver.lower() == 'bobyqa': + # Do NOT merge the IF below into the ELIF above! Otherwise, XU and XL may be accessed even if + # the solver is not BOBYQA, because the logical evaluation is not short-circuit. + if rhobeg > np.min(xu - xl) / 2: + # Do NOT make this revision if RHOBEG not positive or not finite, because otherwise RHOBEG + # will get a huge value when XU or XL contains huge values that indicate unbounded variables. + rhobeg = np.min(xu - xl) / 4.0 # Here, we do not take RHOBEG_DEFAULT. + warn(f'{solver}: Invalid RHOBEG; {solver} requires 0 < RHOBEG <= np.min(XU-XL)/2; it is set to np.min(XU-XL)/4') + if rhobeg <= 0 or np.isnan(rhobeg) or np.isinf(rhobeg): + # Take RHOEND into account if it has a valid value. We do not do this if the solver is BOBYQA, + # which requires that RHOBEG <= (XU-XL)/2. + if np.isfinite(rhoend) and rhoend > 0 and solver.lower() != 'bobyqa': + rhobeg = max(10 * rhoend, rhobeg_default) + else: + rhobeg = rhobeg_default + warn(f'{solver}: Invalid RHOBEG; it should be a positive number; it is set to {rhobeg}') + + if rhoend <= 0 or rhobeg < rhoend or np.isnan(rhoend) or np.isinf(rhoend): + rhoend = max(EPS, min(0.1 * rhobeg, rhoend_default)) + warn(f'{solver}: Invalid RHOEND; it should be a positive number and RHOEND <= RHOBEG; it is set to {rhoend}') + + # For BOBYQA, revise X0 or RHOBEG so that the distance between X0 and the inactive bounds is at + # least RHOBEG. If HONOUR_X0 == TRUE, revise RHOBEG if needed; otherwise, revise HONOUR_X0 if needed. + if present(honour_x0): + if honour_x0: + rhobeg_old = rhobeg; + lbx = np.isfinite(xl) & (x0 - xl <= EPS * np.maximum(1, np.abs(xl))) # X0 essentially equals XL + ubx = np.isfinite(xu) & (x0 - xu >= -EPS * np.maximum(1, np.abs(xu))) # X0 essentially equals XU + x0[lbx] = xl[lbx] + x0[ubx] = xu[ubx] + rhobeg = max(EPS, np.min([rhobeg, x0[~lbx] - xl[~lbx], xu[~ubx] - x0[~ubx]])) + if rhobeg_old - rhobeg > EPS * max(1, rhobeg_old): + rhoend = max(EPS, min(0.1 * rhobeg, rhoend)) # We do not revise RHOEND unless RHOBEG is truly revised. + if has_rhobeg: + warn(f'{solver}: RHOBEG is revised to {rhobeg} and RHOEND to at most 0.1*RHOBEG so that the distance between X0 and the inactive bounds is at least RHOBEG') + else: + rhoend = np.minimum(rhoend, rhobeg) # This may update RHOEND slightly. + else: + x0_old = x0 # Recorded to see whether X0 is really revised. + # N.B.: The following revision is valid only if XL <= X0 <= XU and RHOBEG <= MINVAL(XU-XL)/2, + # which should hold at this point due to the revision of RHOBEG and moderation of X0. + # The cases below are mutually exclusive in precise arithmetic as MINVAL(XU-XL) >= 2*RHOBEG. + lbx = x0 <= xl + 0.5 * rhobeg + lbx_plus = (x0 > xl + 0.5 * rhobeg) & (x0 < xl + rhobeg) + ubx = x0 >= xu - 0.5 * rhobeg + ubx_minus = (x0 < xu - 0.5 * rhobeg) & (x0 > xu - rhobeg) + x0[lbx] = xl[lbx] + x0[lbx_plus] = xl[lbx_plus] + rhobeg + x0[ubx] = xu[ubx] + x0[ubx_minus] = xu[ubx_minus] - rhobeg + + if (any(np.abs(x0_old - x0) > 0)): + warn(f'{solver}: X0 is revised so that the distance between X0 and the inactive bounds is at least RHOBEG set HONOUR_X0 to .TRUE. if you prefer to keep X0 unchanged') + + # Validate CTOL (it can be 0) + if (present(ctol)): + if (np.isnan(ctol) or ctol < 0): + ctol = CTOL_DEFAULT + if (is_constrained): + warn(f'{solver}: Invalid CTOL; it should be a nonnegative number; it is set to {ctol}') + + # Validate CWEIGHT (it can be +Inf) + if (present(cweight)): + if (np.isnan(cweight) or cweight < 0): + cweight = CWEIGHT_DEFAULT + if (is_constrained): + warn(f'{solver}: Invalid CWEIGHT; it should be a nonnegative number; it is set to {cweight}') + + #====================# + # Calculation ends # + #====================# + + # Postconditions + if DEBUGGING: + assert abs(iprint) <= 3 + assert maxhist >= 0 and maxhist <= maxfun + if present(npt): + assert maxfun >= npt + 1 + assert npt >= 3 + if present(maxfilt): + assert maxfilt >= np.minimum(MIN_MAXFILT, maxfun) and maxfilt <= maxfun + if present(eta1) and present(eta2): + assert eta1 >= 0 and eta1 <= eta2 and eta2 < 1 + if present(gamma1) and present(gamma2): + assert gamma1 > 0 and gamma1 < 1 and gamma2 > 1 + assert rhobeg >= rhoend and rhoend > 0 + if solver.lower() == 'bobyqa': + assert all(rhobeg <= (xu - xl) / 2) + assert all(np.isfinite(x0)) + assert all(x0 >= xl and (x0 <= xl or x0 >= xl + rhobeg)) + assert all(x0 <= xu and (x0 >= xu or x0 <= xu - rhobeg)) + if present(ctol): + assert ctol >= 0 + + return iprint, maxfun, maxhist, ftarget, rhobeg, rhoend, npt, maxfilt, ctol, cweight, eta1, eta2, gamma1, gamma2, x0 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/present.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/present.py new file mode 100644 index 0000000000000000000000000000000000000000..15f8b47b6721994399ebafff419087afe582b2b8 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/present.py @@ -0,0 +1,5 @@ +def present(x): + ''' + This is a Python equivalent of the Fortran 'present' function for optional arguments. + ''' + return x is not None \ No newline at end of file diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/ratio.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/ratio.py new file mode 100644 index 0000000000000000000000000000000000000000..c1c3a28ef4a49eeb47438c4a6ad3fb10e83dbc92 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/ratio.py @@ -0,0 +1,54 @@ +''' +This module calculates the reduction ratio for trust-region methods. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +from .consts import DEBUGGING, REALMAX +import numpy as np + +def redrat(ared, pred, rshrink): + ''' + This function evaluates the reduction ratio of a trust-region step, handling inf/nan properly. + ''' + + # Preconditions + if DEBUGGING: + assert rshrink >= 0 + + #====================# + # Calculation starts # + #====================# + + if np.isnan(ared): + # This should not happen in unconstrained problems due to the moderated extreme barrier. + ratio = -REALMAX + elif np.isnan(pred) or pred <= 0: + # The trust-region subproblem solver fails in this rare case. Instead of terminating as Powell's + # original code does, we set ratio as follows so that the solver may continue to progress. + if ared > 0: + # The trial point will be accepted, but the trust-region radius will be shrunk if rshrink>0 + ratio = rshrink/2 + else: + # Set the ration to a large negative number to signify a bad trust-region step, so that the + # solver will check whether to take a geometry step or reduce rho. + ratio = -REALMAX + elif np.isposinf(pred) and np.isposinf(ared): + ratio = 1 # ared/pred = NaN if calculated directly + elif np.isposinf(pred) and np.isneginf(ared): + ratio = -REALMAX # ared/pred = NaN if calculated directly + else: + ratio = ared/pred + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert not np.isnan(ratio) + return ratio diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/redrho.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/redrho.py new file mode 100644 index 0000000000000000000000000000000000000000..4b4c09b8400e694ed6f7016273aecfd384bf38a0 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/redrho.py @@ -0,0 +1,47 @@ +''' +This module provides a function that calculates RHO when it needs to be reduced. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +from .consts import DEBUGGING +import numpy as np + +def redrho(rho_in, rhoend): + ''' + This function calculates RHO when it needs to be reduced. + The scheme is shared by UOBYQA, NEWUOA, BOBYQA, LINCOA. For COBYLA, Powell's code reduces RHO by + 'RHO *= 0.5; if RHO <= 1.5 * RHOEND: RHO = RHOEND' as specified in (11) of the COBYLA + paper. However, this scheme seems to work better, especially after we introduce DELTA. + ''' + + # Preconditions + if DEBUGGING: + assert rho_in > rhoend > 0 + + #====================# + # Calculation starts # + #====================# + + rho_ratio = rho_in / rhoend + + if rho_ratio > 250: + rho = 0.1 * rho_in + elif rho_ratio <= 16: + rho = rhoend + else: + rho = np.sqrt(rho_ratio) * rhoend # rho = np.sqrt(rho * rhoend) + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert rho_in > rho >= rhoend + + return rho diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/selectx.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/selectx.py new file mode 100644 index 0000000000000000000000000000000000000000..63d76ad709dac1c0a4d246ba24566f6c8e655124 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/pyprima/common/selectx.py @@ -0,0 +1,296 @@ +''' +This module provides subroutines that ensure the returned X is optimal among all the calculated +points in the sense that no other point achieves both lower function value and lower constraint +violation at the same time. This module is needed only in the constrained case. + +Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA. + +Dedicated to late Professor M. J. D. Powell FRS (1936--2015). + +Python translation by Nickolai Belakovski. +''' + +import numpy as np +import numpy.typing as npt +from .consts import DEBUGGING, EPS, CONSTRMAX, REALMAX, FUNCMAX +from .present import present + +def isbetter(f1: float, c1: float, f2: float, c2: float, ctol: float) -> bool: + ''' + This function compares whether FC1 = (F1, C1) is (strictly) better than FC2 = (F2, C2), which + basically means that (F1 < F2 and C1 <= C2) or (F1 <= F2 and C1 < C2). + It takes care of the cases where some of these values are NaN or Inf, even though some cases + should never happen due to the moderated extreme barrier. + At return, BETTER = TRUE if and only if (F1, C1) is better than (F2, C2). + Here, C means constraint violation, which is a nonnegative number. + ''' + + # Preconditions + if DEBUGGING: + assert not any(np.isnan([f1, c1]) | np.isposinf([f2, c2])) + assert not any(np.isnan([f2, c2]) | np.isposinf([f2, c2])) + assert c1 >= 0 and c2 >= 0 + assert ctol >= 0 + + #====================# + # Calculation starts # + #====================# + + is_better = False + # Even though NaN/+Inf should not occur in FC1 or FC2 due to the moderated extreme barrier, for + # security and robustness, the code below does not make this assumption. + is_better = is_better or (any(np.isnan([f1, c1]) | np.isposinf([f1, c1])) and not any(np.isnan([f2, c2]) | np.isposinf([f2, c2]))) + + is_better = is_better or (f1 < f2 and c1 <= c2) + is_better = is_better or (f1 <= f2 and c1 < c2) + + # If C1 <= CTOL and C2 is significantly larger/worse than CTOL, i.e., C2 > MAX(CTOL,CREF), + # then FC1 is better than FC2 as long as F1 < REALMAX. Normally CREF >= CTOL so MAX(CTOL, CREF) + # is indeed CREF. However, this may not be true if CTOL > 1E-1*CONSTRMAX. + cref = 10 * max(EPS, min(ctol, 1.0E-2 * CONSTRMAX)) # The MIN avoids overflow. + is_better = is_better or (f1 < REALMAX and c1 <= ctol and (c2 > max(ctol, cref) or np.isnan(c2))) + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert not (is_better and f1 >= f2 and c1 >= c2) + assert is_better or not (f1 <= f2 and c1 < c2) + assert is_better or not (f1 < f2 and c1 <= c2) + + return is_better + + +def savefilt(cstrv, ctol, cweight, f, x, nfilt, cfilt, ffilt, xfilt, constr=None, confilt=None): + ''' + This subroutine saves X, F, and CSTRV in XFILT, FFILT, and CFILT (and CONSTR in CONFILT + if they are present), unless a vector in XFILT[:, :NFILT] is better than X. + If X is better than some vectors in XFILT[:, :NFILT] then these vectors will be + removed. If X is not better than any of XFILT[:, :NFILT], but NFILT == MAXFILT, + then we remove a column from XFILT according to the merit function + PHI = FFILT + CWEIGHT * max(CFILT - CTOL, 0) + N.B.: + 1. Only XFILT[:, :NFILT] and FFILT[:, :NFILT] etc contains valid information, + while XFILT[:, NFILT+1:MAXFILT] and FFILT[:, NFILT+1:MAXFILT] etc are not + initialized yet. + 2. We decide whether and X is better than another by the ISBETTER function + ''' + + # Sizes + if present(constr): + num_constraints = len(constr) + else: + num_constraints = 0 + num_vars = len(x) + maxfilt = len(ffilt) + + # Preconditions + if DEBUGGING: + # Check the size of X. + assert num_vars >= 1 + # Check CWEIGHT and CTOL + assert cweight >= 0 + assert ctol >= 0 + # Check NFILT + assert nfilt >= 0 and nfilt <= maxfilt + # Check the sizes of XFILT, FFILT, CFILT. + assert maxfilt >= 1 + assert np.size(xfilt, 0) == num_vars and np.size(xfilt, 1) == maxfilt + assert np.size(cfilt) == maxfilt + # Check the values of XFILT, FFILT, CFILT. + assert not (np.isnan(xfilt[:, :nfilt])).any() + assert not any(np.isnan(ffilt[:nfilt]) | np.isposinf(ffilt[:nfilt])) + assert not any(cfilt[:nfilt] < 0 | np.isnan(cfilt[:nfilt]) | np.isposinf(cfilt[:nfilt])) + # Check the values of X, F, CSTRV. + # X does not contain NaN if X0 does not and the trust-region/geometry steps are proper. + assert not any(np.isnan(x)) + # F cannot be NaN/+Inf due to the moderated extreme barrier. + assert not (np.isnan(f) | np.isposinf(f)) + # CSTRV cannot be NaN/+Inf due to the moderated extreme barrier. + assert not (cstrv < 0 | np.isnan(cstrv) | np.isposinf(cstrv)) + # Check CONSTR and CONFILT. + assert present(constr) == present(confilt) + if present(constr): + # CONSTR cannot contain NaN/-Inf due to the moderated extreme barrier. + assert not any(np.isnan(constr) | np.isneginf(constr)) + assert np.size(confilt, 0) == num_constraints and np.size(confilt, 1) == maxfilt + assert not (np.isnan(confilt[:, :nfilt]) | np.isneginf(confilt[:, :nfilt])).any() + + #====================# + # Calculation starts # + #====================# + + # Return immediately if any column of XFILT is better than X. + if any((isbetter(ffilt_i, cfilt_i, f, cstrv, ctol) for ffilt_i, cfilt_i in zip(ffilt[:nfilt], cfilt[:nfilt]))) or \ + any(np.logical_and(ffilt[:nfilt] <= f, cfilt[:nfilt] <= cstrv)): + return nfilt, cfilt, ffilt, xfilt, confilt + + # Decide which columns of XFILT to keep. + keep = np.logical_not([isbetter(f, cstrv, ffilt_i, cfilt_i, ctol) for ffilt_i, cfilt_i in zip(ffilt[:nfilt], cfilt[:nfilt])]) + + # If NFILT == MAXFILT and X is not better than any column of XFILT, then we remove the worst column + # of XFILT according to the merit function PHI = FFILT + CWEIGHT * MAX(CFILT - CTOL, ZERO). + if sum(keep) == maxfilt: # In this case, NFILT = SIZE(KEEP) = COUNT(KEEP) = MAXFILT > 0. + cfilt_shifted = np.maximum(cfilt - ctol, 0) + if cweight <= 0: + phi = ffilt + elif np.isposinf(cweight): + phi = cfilt_shifted + # We should not use CFILT here; if MAX(CFILT_SHIFTED) is attained at multiple indices, then + # we will check FFILT to exhaust the remaining degree of freedom. + else: + phi = np.maximum(ffilt, -REALMAX) + phi = np.nan_to_num(phi, nan=-REALMAX) # Replace NaN with -REALMAX and +/- inf with large numbers + phi += cweight * cfilt_shifted + # We select X to maximize PHI. In case there are multiple maximizers, we take the one with the + # largest CSTRV_SHIFTED; if there are more than one choices, we take the one with the largest F; + # if there are several candidates, we take the one with the largest CSTRV; if the last comparison + # still leads to more than one possibilities, then they are equally bad and we choose the first. + # N.B.: + # 1. This process is the opposite of selecting KOPT in SELECTX. + # 2. In finite-precision arithmetic, PHI_1 == PHI_2 and CSTRV_SHIFTED_1 == CSTRV_SHIFTED_2 do + # not ensure that F_1 == F_2! + phimax = max(phi) + cref = max(cfilt_shifted[phi >= phimax]) + fref = max(ffilt[cfilt_shifted >= cref]) + kworst = np.ma.array(cfilt, mask=(ffilt > fref)).argmax() + if kworst < 0 or kworst >= len(keep): # For security. Should not happen. + kworst = 0 + keep[kworst] = False + + # Keep the good xfilt values and remove all the ones that are strictly worse than the new x. + nfilt = sum(keep) + index_to_keep = np.where(keep)[0] + xfilt[:, :nfilt] = xfilt[:, index_to_keep] + ffilt[:nfilt] = ffilt[index_to_keep] + cfilt[:nfilt] = cfilt[index_to_keep] + if confilt is not None and constr is not None: + confilt[:, :nfilt] = confilt[:, index_to_keep] + + # Once we have removed all the vectors that are strictly worse than x, + # we add x to the filter. + xfilt[:, nfilt] = x + ffilt[nfilt] = f + cfilt[nfilt] = cstrv + if confilt is not None and constr is not None: + confilt[:, nfilt] = constr + nfilt += 1 # In Python we need to increment the index afterwards + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + # Check NFILT and the sizes of XFILT, FFILT, CFILT. + assert nfilt >= 1 and nfilt <= maxfilt + assert np.size(xfilt, 0) == num_vars and np.size(xfilt, 1) == maxfilt + assert np.size(ffilt) == maxfilt + assert np.size(cfilt) == maxfilt + # Check the values of XFILT, FFILT, CFILT. + assert not (np.isnan(xfilt[:, :nfilt])).any() + assert not any(np.isnan(ffilt[:nfilt]) | np.isposinf(ffilt[:nfilt])) + assert not any(cfilt[:nfilt] < 0 | np.isnan(cfilt[:nfilt]) | np.isposinf(cfilt[:nfilt])) + # Check that no point in the filter is better than X, and X is better than no point. + assert not any([isbetter(ffilt_i, cfilt_i, f, cstrv, ctol) for ffilt_i, cfilt_i in zip(ffilt[:nfilt], cfilt[:nfilt])]) + assert not any([isbetter(f, cstrv, ffilt_i, cfilt_i, ctol) for ffilt_i, cfilt_i in zip(ffilt[:nfilt], cfilt[:nfilt])]) + # Check CONFILT. + if present(confilt): + assert np.size(confilt, 0) == num_constraints and np.size(confilt, 1) == maxfilt + assert not (np.isnan(confilt[:, :nfilt]) | np.isneginf(confilt[:, :nfilt])).any() + + + return nfilt, cfilt, ffilt, xfilt, confilt + + +def selectx(fhist: npt.NDArray, chist: npt.NDArray, cweight: float, ctol: float): + ''' + This subroutine selects X according to FHIST and CHIST, which represents (a part of) history + of F and CSTRV. Normally, FHIST and CHIST are not the full history but only a filter, e.g. ffilt + and CFILT generated by SAVEFILT. However, we name them as FHIST and CHIST because the [F, CSTRV] + in a filter should not dominate each other, but this subroutine does NOT assume such a property. + N.B.: CTOL is the tolerance of the constraint violation (CSTRV). A point is considered feasible if + its constraint violation is at most CTOL. Not that CTOL is absolute, not relative. + ''' + + # Sizes + nhist = len(fhist) + + # Preconditions + if DEBUGGING: + assert nhist >= 1 + assert np.size(chist) == nhist + assert not any(np.isnan(fhist) | np.isposinf(fhist)) + assert not any(chist < 0 | np.isnan(chist) | np.isposinf(chist)) + assert cweight >= 0 + assert ctol >= 0 + + #====================# + # Calculation starts # + #====================# + + # We select X among the points with F < FREF and CSTRV < CREF. + # Do NOT use F <= FREF, because F == FREF (FUNCMAX or REALMAX) may mean F == INF in practice! + if any(np.logical_and(fhist < FUNCMAX, chist < CONSTRMAX)): + fref = FUNCMAX + cref = CONSTRMAX + elif any(np.logical_and(fhist < REALMAX, chist < CONSTRMAX)): + fref = REALMAX + cref = CONSTRMAX + elif any(np.logical_and(fhist < FUNCMAX, chist < REALMAX)): + fref = FUNCMAX + cref = REALMAX + else: + fref = REALMAX + cref = REALMAX + + if not any(np.logical_and(fhist < fref, chist < cref)): + kopt = nhist - 1 + else: + # Shift the constraint violations by ctol, so that cstrv <= ctol is regarded as no violation. + chist_shifted = np.maximum(chist - ctol, 0) + # cmin is the minimal shift constraint violation attained in the history. + cmin = np.min(chist_shifted[fhist < fref]) + # We consider only the points whose shifted constraint violations are at most the cref below. + # N.B.: Without taking np.maximum(EPS, .), cref would be 0 if cmin = 0. In that case, asking for + # cstrv_shift < cref would be WRONG! + cref = np.maximum(EPS, 2*cmin) + # We use the following phi as our merit function to select X. + if cweight <= 0: + phi = fhist + elif np.isposinf(cweight): + phi = chist_shifted + # We should not use chist here; if np.minimum(chist_shifted) is attained at multiple indices, then + # we will check fhist to exhaust the remaining degree of freedom. + else: + phi = np.maximum(fhist, -REALMAX) + cweight * chist_shifted + # np.maximum(fhist, -REALMAX) makes sure that phi will not contain NaN (unless there is a bug). + + # We select X to minimize phi subject to f < fref and cstrv_shift <= cref (see the comments + # above for the reason of taking "<" and "<=" in these two constraints). In case there are + # multiple minimizers, we take the one with the least cstrv_shift; if there is more than one + # choice, we take the one with the least f; if there are several candidates, we take the one + # with the least cstrv; if the last comparison still leads to more than one possibility, then + # they are equally good and we choose the first. + # N.B.: + # 1. This process is the opposite of selecting kworst in savefilt + # 2. In finite-precision arithmetic, phi_2 == phi_2 and cstrv_shift_1 == cstrv_shifted_2 do + # not ensure thatn f_1 == f_2! + phimin = np.min(phi[np.logical_and(fhist < fref, chist_shifted <= cref)]) + cref = np.min(chist_shifted[np.logical_and(fhist < fref, phi <= phimin)]) + fref = np.min(fhist[chist_shifted <= cref]) + # Can't use argmin here because using it with a mask throws off the index + kopt = np.ma.array(chist, mask=(fhist > fref)).argmin() + + #==================# + # Calculation ends # + #==================# + + # Postconditions + if DEBUGGING: + assert kopt >= 0 and kopt < nhist + assert not any([isbetter(fhisti, chisti, fhist[kopt], chist[kopt], ctol) for fhisti, chisti in zip(fhist[:nhist], chist[:nhist])]) + + return kopt diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..529065f9f28f1d68ffd7fa487772fc3c3050bd8c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test__gcutils.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test__gcutils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..66ecc49d4812e491cac3839128b3d4c8698dc2c0 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test__gcutils.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test__pep440.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test__pep440.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aa4653c204d1eb04168521772d015433ffbec72f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test__pep440.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test__testutils.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test__testutils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..874864ea311661a037c767e95bca99c19b3bd926 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test__testutils.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test__util.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test__util.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7ffc5528441fa8b92343e1faa573d21fa0c6709 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test__util.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_array_api.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_array_api.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c2e59f42bec5368cb78bbd31e7a2d65a6ad923d6 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_array_api.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_bunch.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_bunch.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c9f03e1d5a71d320f6e41140ba1ae05cb1914552 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_bunch.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_ccallback.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_ccallback.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..018bd40af2044f6571eebad42c45cb71578be128 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_ccallback.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_config.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_config.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da32d213c70f432c71be9d916c8f1e9bb8607520 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_config.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_deprecation.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_deprecation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..76cd0944f61feced5e8841271190ceaa1c72ca90 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_deprecation.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_doccer.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_doccer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..39e20e0c5cb472788b1f730d27fd8c5c67b66fac Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_doccer.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_import_cycles.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_import_cycles.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5fc7381629498d5e97bcc668003ef9379648b826 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_import_cycles.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_public_api.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_public_api.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..66ada78c2d47605d77af0ce5fabfecf48b25a761 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_public_api.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_scipy_version.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_scipy_version.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a544d368c4d18f092cf52a62e1ea73c57c2c41bf Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_scipy_version.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_tmpdirs.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_tmpdirs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fc9dc0c1616ff685e6e5fa0c21996462ed8fda07 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_tmpdirs.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_warnings.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_warnings.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aea8ced3be018c9230af040d872512d975a2b5d4 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/__pycache__/test_warnings.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test__gcutils.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test__gcutils.py new file mode 100644 index 0000000000000000000000000000000000000000..0e397af4fb7e9bc69f31d1e39aa80716469d5470 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test__gcutils.py @@ -0,0 +1,110 @@ +""" Test for assert_deallocated context manager and gc utilities +""" +import gc +from threading import Lock + +from scipy._lib._gcutils import (set_gc_state, gc_state, assert_deallocated, + ReferenceError, IS_PYPY) + +from numpy.testing import assert_equal + +import pytest + + +@pytest.fixture +def gc_lock(): + return Lock() + + +def test_set_gc_state(gc_lock): + with gc_lock: + gc_status = gc.isenabled() + try: + for state in (True, False): + gc.enable() + set_gc_state(state) + assert_equal(gc.isenabled(), state) + gc.disable() + set_gc_state(state) + assert_equal(gc.isenabled(), state) + finally: + if gc_status: + gc.enable() + + +def test_gc_state(gc_lock): + # Test gc_state context manager + with gc_lock: + gc_status = gc.isenabled() + try: + for pre_state in (True, False): + set_gc_state(pre_state) + for with_state in (True, False): + # Check the gc state is with_state in with block + with gc_state(with_state): + assert_equal(gc.isenabled(), with_state) + # And returns to previous state outside block + assert_equal(gc.isenabled(), pre_state) + # Even if the gc state is set explicitly within the block + with gc_state(with_state): + assert_equal(gc.isenabled(), with_state) + set_gc_state(not with_state) + assert_equal(gc.isenabled(), pre_state) + finally: + if gc_status: + gc.enable() + + +@pytest.mark.skipif(IS_PYPY, reason="Test not meaningful on PyPy") +def test_assert_deallocated(gc_lock): + # Ordinary use + class C: + def __init__(self, arg0, arg1, name='myname'): + self.name = name + with gc_lock: + for gc_current in (True, False): + with gc_state(gc_current): + # We are deleting from with-block context, so that's OK + with assert_deallocated(C, 0, 2, 'another name') as c: + assert_equal(c.name, 'another name') + del c + # Or not using the thing in with-block context, also OK + with assert_deallocated(C, 0, 2, name='third name'): + pass + assert_equal(gc.isenabled(), gc_current) + + +@pytest.mark.skipif(IS_PYPY, reason="Test not meaningful on PyPy") +def test_assert_deallocated_nodel(): + class C: + pass + with pytest.raises(ReferenceError): + # Need to delete after using if in with-block context + # Note: assert_deallocated(C) needs to be assigned for the test + # to function correctly. It is assigned to _, but _ itself is + # not referenced in the body of the with, it is only there for + # the refcount. + with assert_deallocated(C) as _: + pass + + +@pytest.mark.skipif(IS_PYPY, reason="Test not meaningful on PyPy") +def test_assert_deallocated_circular(): + class C: + def __init__(self): + self._circular = self + with pytest.raises(ReferenceError): + # Circular reference, no automatic garbage collection + with assert_deallocated(C) as c: + del c + + +@pytest.mark.skipif(IS_PYPY, reason="Test not meaningful on PyPy") +def test_assert_deallocated_circular2(): + class C: + def __init__(self): + self._circular = self + with pytest.raises(ReferenceError): + # Still circular reference, no automatic garbage collection + with assert_deallocated(C): + pass diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test__pep440.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test__pep440.py new file mode 100644 index 0000000000000000000000000000000000000000..7f5b71c8f1e13b42de2e8e612a005dec409fc025 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test__pep440.py @@ -0,0 +1,67 @@ +from pytest import raises as assert_raises +from scipy._lib._pep440 import Version, parse + + +def test_main_versions(): + assert Version('1.8.0') == Version('1.8.0') + for ver in ['1.9.0', '2.0.0', '1.8.1']: + assert Version('1.8.0') < Version(ver) + + for ver in ['1.7.0', '1.7.1', '0.9.9']: + assert Version('1.8.0') > Version(ver) + + +def test_version_1_point_10(): + # regression test for gh-2998. + assert Version('1.9.0') < Version('1.10.0') + assert Version('1.11.0') < Version('1.11.1') + assert Version('1.11.0') == Version('1.11.0') + assert Version('1.99.11') < Version('1.99.12') + + +def test_alpha_beta_rc(): + assert Version('1.8.0rc1') == Version('1.8.0rc1') + for ver in ['1.8.0', '1.8.0rc2']: + assert Version('1.8.0rc1') < Version(ver) + + for ver in ['1.8.0a2', '1.8.0b3', '1.7.2rc4']: + assert Version('1.8.0rc1') > Version(ver) + + assert Version('1.8.0b1') > Version('1.8.0a2') + + +def test_dev_version(): + assert Version('1.9.0.dev+Unknown') < Version('1.9.0') + for ver in ['1.9.0', '1.9.0a1', '1.9.0b2', '1.9.0b2.dev+ffffffff', '1.9.0.dev1']: + assert Version('1.9.0.dev+f16acvda') < Version(ver) + + assert Version('1.9.0.dev+f16acvda') == Version('1.9.0.dev+f16acvda') + + +def test_dev_a_b_rc_mixed(): + assert Version('1.9.0a2.dev+f16acvda') == Version('1.9.0a2.dev+f16acvda') + assert Version('1.9.0a2.dev+6acvda54') < Version('1.9.0a2') + + +def test_dev0_version(): + assert Version('1.9.0.dev0+Unknown') < Version('1.9.0') + for ver in ['1.9.0', '1.9.0a1', '1.9.0b2', '1.9.0b2.dev0+ffffffff']: + assert Version('1.9.0.dev0+f16acvda') < Version(ver) + + assert Version('1.9.0.dev0+f16acvda') == Version('1.9.0.dev0+f16acvda') + + +def test_dev0_a_b_rc_mixed(): + assert Version('1.9.0a2.dev0+f16acvda') == Version('1.9.0a2.dev0+f16acvda') + assert Version('1.9.0a2.dev0+6acvda54') < Version('1.9.0a2') + + +def test_raises(): + for ver in ['1,9.0', '1.7.x']: + assert_raises(ValueError, Version, ver) + +def test_legacy_version(): + # Non-PEP-440 version identifiers always compare less. For NumPy this only + # occurs on dev builds prior to 1.10.0 which are unsupported anyway. + assert parse('invalid') < Version('0.0.0') + assert parse('1.9.0-f16acvda') < Version('1.0.0') diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test__testutils.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test__testutils.py new file mode 100644 index 0000000000000000000000000000000000000000..88db113d6d5a35c96ecc0a6a36ab42d74be49153 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test__testutils.py @@ -0,0 +1,32 @@ +import sys +from scipy._lib._testutils import _parse_size, _get_mem_available +import pytest + + +def test__parse_size(): + expected = { + '12': 12e6, + '12 b': 12, + '12k': 12e3, + ' 12 M ': 12e6, + ' 12 G ': 12e9, + ' 12Tb ': 12e12, + '12 Mib ': 12 * 1024.0**2, + '12Tib': 12 * 1024.0**4, + } + + for inp, outp in sorted(expected.items()): + if outp is None: + with pytest.raises(ValueError): + _parse_size(inp) + else: + assert _parse_size(inp) == outp + + +def test__mem_available(): + # May return None on non-Linux platforms + available = _get_mem_available() + if sys.platform.startswith('linux'): + assert available >= 0 + else: + assert available is None or available >= 0 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test__util.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test__util.py new file mode 100644 index 0000000000000000000000000000000000000000..f78e36613f2a49a6e685a7775e117f80fe50affa --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test__util.py @@ -0,0 +1,638 @@ +from multiprocessing import Pool +from multiprocessing.pool import Pool as PWL +import re +import math +import functools +from fractions import Fraction + +import numpy as np +from numpy.testing import assert_equal, assert_ +import pytest +from pytest import raises as assert_raises +from scipy.conftest import skip_xp_invalid_arg + +from scipy._lib._array_api import xp_assert_equal +from scipy._lib._util import (_aligned_zeros, check_random_state, MapWrapper, + getfullargspec_no_self, FullArgSpec, + rng_integers, _validate_int, _rename_parameter, + _contains_nan, _rng_html_rewrite, _workers_wrapper) +import scipy._lib.array_api_extra as xpx +from scipy._lib.array_api_extra.testing import lazy_xp_function +from scipy import cluster, interpolate, linalg, optimize, sparse, spatial, stats + + +lazy_xp_function(_contains_nan) + + +@pytest.mark.slow +def test__aligned_zeros(): + niter = 10 + + def check(shape, dtype, order, align): + err_msg = repr((shape, dtype, order, align)) + x = _aligned_zeros(shape, dtype, order, align=align) + if align is None: + align = np.dtype(dtype).alignment + assert_equal(x.__array_interface__['data'][0] % align, 0) + if hasattr(shape, '__len__'): + assert_equal(x.shape, shape, err_msg) + else: + assert_equal(x.shape, (shape,), err_msg) + assert_equal(x.dtype, dtype) + if order == "C": + assert_(x.flags.c_contiguous, err_msg) + elif order == "F": + if x.size > 0: + # Size-0 arrays get invalid flags on NumPy 1.5 + assert_(x.flags.f_contiguous, err_msg) + elif order is None: + assert_(x.flags.c_contiguous, err_msg) + else: + raise ValueError() + + # try various alignments + for align in [1, 2, 3, 4, 8, 16, 32, 64, None]: + for n in [0, 1, 3, 11]: + for order in ["C", "F", None]: + for dtype in [np.uint8, np.float64]: + for shape in [n, (1, 2, 3, n)]: + for j in range(niter): + check(shape, dtype, order, align) + + +def test_check_random_state(): + # If seed is None, return the RandomState singleton used by np.random. + # If seed is an int, return a new RandomState instance seeded with seed. + # If seed is already a RandomState instance, return it. + # Otherwise raise ValueError. + rsi = check_random_state(1) + assert_equal(type(rsi), np.random.RandomState) + rsi = check_random_state(rsi) + assert_equal(type(rsi), np.random.RandomState) + rsi = check_random_state(None) + assert_equal(type(rsi), np.random.RandomState) + assert_raises(ValueError, check_random_state, 'a') + rg = np.random.Generator(np.random.PCG64()) + rsi = check_random_state(rg) + assert_equal(type(rsi), np.random.Generator) + + +def test_getfullargspec_no_self(): + p = MapWrapper(1) + argspec = getfullargspec_no_self(p.__init__) + assert_equal(argspec, FullArgSpec(['pool'], None, None, (1,), [], + None, {})) + argspec = getfullargspec_no_self(p.__call__) + assert_equal(argspec, FullArgSpec(['func', 'iterable'], None, None, None, + [], None, {})) + + class _rv_generic: + def _rvs(self, a, b=2, c=3, *args, size=None, **kwargs): + return None + + rv_obj = _rv_generic() + argspec = getfullargspec_no_self(rv_obj._rvs) + assert_equal(argspec, FullArgSpec(['a', 'b', 'c'], 'args', 'kwargs', + (2, 3), ['size'], {'size': None}, {})) + + +def test_mapwrapper_serial(): + in_arg = np.arange(10.) + out_arg = np.sin(in_arg) + + p = MapWrapper(1) + assert_(p._mapfunc is map) + assert_(p.pool is None) + assert_(p._own_pool is False) + out = list(p(np.sin, in_arg)) + assert_equal(out, out_arg) + + with assert_raises(RuntimeError): + p = MapWrapper(0) + + +def test_pool(): + with Pool(2) as p: + p.map(math.sin, [1, 2, 3, 4]) + + +def test_mapwrapper_parallel(): + in_arg = np.arange(10.) + out_arg = np.sin(in_arg) + + with MapWrapper(2) as p: + out = p(np.sin, in_arg) + assert_equal(list(out), out_arg) + + assert_(p._own_pool is True) + assert_(isinstance(p.pool, PWL)) + assert_(p._mapfunc is not None) + + # the context manager should've closed the internal pool + # check that it has by asking it to calculate again. + with assert_raises(Exception) as excinfo: + p(np.sin, in_arg) + + assert_(excinfo.type is ValueError) + + # can also set a PoolWrapper up with a map-like callable instance + with Pool(2) as p: + q = MapWrapper(p.map) + + assert_(q._own_pool is False) + q.close() + + # closing the PoolWrapper shouldn't close the internal pool + # because it didn't create it + out = p.map(np.sin, in_arg) + assert_equal(list(out), out_arg) + + +@_workers_wrapper +def user_of_workers(x, b=1, workers=None): + assert workers is not None + assert isinstance(workers, MapWrapper) + return np.array(list(workers(np.sin, x * b))) + + +def test__workers_wrapper(): + arr = np.linspace(0, np.pi) + req = np.sin(arr * 2.0) + + with Pool(2) as p: + v = user_of_workers(arr, workers=p.map, b=2) + assert_equal(v, req) + + v = user_of_workers(arr, workers=None, b=2) + assert_equal(v, req) + + v = user_of_workers(arr, workers=2, b=2) + assert_equal(v, req) + + # assess if decorator works with partial functions + part_f = functools.partial(user_of_workers, b=2) + assert_equal(part_f(arr), req) + + with Pool(2) as p: + part_f = functools.partial(user_of_workers, b=2, workers=p.map) + assert_equal(part_f(arr), req) + + +def test_rng_integers(): + rng = np.random.RandomState() + + # test that numbers are inclusive of high point + arr = rng_integers(rng, low=2, high=5, size=100, endpoint=True) + assert np.max(arr) == 5 + assert np.min(arr) == 2 + assert arr.shape == (100, ) + + # test that numbers are inclusive of high point + arr = rng_integers(rng, low=5, size=100, endpoint=True) + assert np.max(arr) == 5 + assert np.min(arr) == 0 + assert arr.shape == (100, ) + + # test that numbers are exclusive of high point + arr = rng_integers(rng, low=2, high=5, size=100, endpoint=False) + assert np.max(arr) == 4 + assert np.min(arr) == 2 + assert arr.shape == (100, ) + + # test that numbers are exclusive of high point + arr = rng_integers(rng, low=5, size=100, endpoint=False) + assert np.max(arr) == 4 + assert np.min(arr) == 0 + assert arr.shape == (100, ) + + # now try with np.random.Generator + try: + rng = np.random.default_rng() + except AttributeError: + return + + # test that numbers are inclusive of high point + arr = rng_integers(rng, low=2, high=5, size=100, endpoint=True) + assert np.max(arr) == 5 + assert np.min(arr) == 2 + assert arr.shape == (100, ) + + # test that numbers are inclusive of high point + arr = rng_integers(rng, low=5, size=100, endpoint=True) + assert np.max(arr) == 5 + assert np.min(arr) == 0 + assert arr.shape == (100, ) + + # test that numbers are exclusive of high point + arr = rng_integers(rng, low=2, high=5, size=100, endpoint=False) + assert np.max(arr) == 4 + assert np.min(arr) == 2 + assert arr.shape == (100, ) + + # test that numbers are exclusive of high point + arr = rng_integers(rng, low=5, size=100, endpoint=False) + assert np.max(arr) == 4 + assert np.min(arr) == 0 + assert arr.shape == (100, ) + + +class TestValidateInt: + + @pytest.mark.parametrize('n', [4, np.uint8(4), np.int16(4), np.array(4)]) + def test_validate_int(self, n): + n = _validate_int(n, 'n') + assert n == 4 + + @pytest.mark.parametrize('n', [4.0, np.array([4]), Fraction(4, 1)]) + def test_validate_int_bad(self, n): + with pytest.raises(TypeError, match='n must be an integer'): + _validate_int(n, 'n') + + def test_validate_int_below_min(self): + with pytest.raises(ValueError, match='n must be an integer not ' + 'less than 0'): + _validate_int(-1, 'n', 0) + + +class TestRenameParameter: + # check that wrapper `_rename_parameter` for backward-compatible + # keyword renaming works correctly + + # Example method/function that still accepts keyword `old` + @_rename_parameter("old", "new") + def old_keyword_still_accepted(self, new): + return new + + # Example method/function for which keyword `old` is deprecated + @_rename_parameter("old", "new", dep_version="1.9.0") + def old_keyword_deprecated(self, new): + return new + + def test_old_keyword_still_accepted(self): + # positional argument and both keyword work identically + res1 = self.old_keyword_still_accepted(10) + res2 = self.old_keyword_still_accepted(new=10) + res3 = self.old_keyword_still_accepted(old=10) + assert res1 == res2 == res3 == 10 + + # unexpected keyword raises an error + message = re.escape("old_keyword_still_accepted() got an unexpected") + with pytest.raises(TypeError, match=message): + self.old_keyword_still_accepted(unexpected=10) + + # multiple values for the same parameter raises an error + message = re.escape("old_keyword_still_accepted() got multiple") + with pytest.raises(TypeError, match=message): + self.old_keyword_still_accepted(10, new=10) + with pytest.raises(TypeError, match=message): + self.old_keyword_still_accepted(10, old=10) + with pytest.raises(TypeError, match=message): + self.old_keyword_still_accepted(new=10, old=10) + + @pytest.fixture + def kwarg_lock(self): + from threading import Lock + return Lock() + + def test_old_keyword_deprecated(self, kwarg_lock): + # positional argument and both keyword work identically, + # but use of old keyword results in DeprecationWarning + dep_msg = "Use of keyword argument `old` is deprecated" + res1 = self.old_keyword_deprecated(10) + res2 = self.old_keyword_deprecated(new=10) + # pytest warning filter is not thread-safe, enforce serialization + with kwarg_lock: + with pytest.warns(DeprecationWarning, match=dep_msg): + res3 = self.old_keyword_deprecated(old=10) + assert res1 == res2 == res3 == 10 + + # unexpected keyword raises an error + message = re.escape("old_keyword_deprecated() got an unexpected") + with pytest.raises(TypeError, match=message): + self.old_keyword_deprecated(unexpected=10) + + # multiple values for the same parameter raises an error and, + # if old keyword is used, results in DeprecationWarning + message = re.escape("old_keyword_deprecated() got multiple") + with pytest.raises(TypeError, match=message): + self.old_keyword_deprecated(10, new=10) + with kwarg_lock: + with pytest.raises(TypeError, match=message), \ + pytest.warns(DeprecationWarning, match=dep_msg): + # breakpoint() + self.old_keyword_deprecated(10, old=10) + with kwarg_lock: + with pytest.raises(TypeError, match=message), \ + pytest.warns(DeprecationWarning, match=dep_msg): + self.old_keyword_deprecated(new=10, old=10) + + +class TestContainsNaN: + def test_policy(self): + data = np.array([1, 2, 3, np.nan]) + + assert _contains_nan(data) # default policy is "propagate" + assert _contains_nan(data, nan_policy="propagate") + assert _contains_nan(data, nan_policy="omit") + assert not _contains_nan(data[:3]) + assert not _contains_nan(data[:3], nan_policy="propagate") + assert not _contains_nan(data[:3], nan_policy="omit") + + with pytest.raises(ValueError, match="The input contains nan values"): + _contains_nan(data, nan_policy="raise") + assert not _contains_nan(data[:3], nan_policy="raise") + + with pytest.raises(ValueError, match="nan_policy must be one of"): + _contains_nan(data, nan_policy="nan") + + def test_contains_nan(self): + # Special case: empty array + assert not _contains_nan(np.array([], dtype=float)) + + # Integer arrays cannot contain NaN + assert not _contains_nan(np.array([1, 2, 3])) + assert not _contains_nan(np.array([[1, 2], [3, 4]])) + + assert not _contains_nan(np.array([1., 2., 3.])) + assert not _contains_nan(np.array([1., 2.j, 3.])) + assert _contains_nan(np.array([1., 2.j, np.nan])) + assert _contains_nan(np.array([1., 2., np.nan])) + assert _contains_nan(np.array([np.nan, 2., np.nan])) + assert not _contains_nan(np.array([[1., 2.], [3., 4.]])) + assert _contains_nan(np.array([[1., 2.], [3., np.nan]])) + + @skip_xp_invalid_arg + def test_contains_nan_with_strings(self): + data1 = np.array([1, 2, "3", np.nan]) # converted to string "nan" + assert not _contains_nan(data1) + + data2 = np.array([1, 2, "3", np.nan], dtype='object') + assert _contains_nan(data2) + + data3 = np.array([["1", 2], [3, np.nan]]) # converted to string "nan" + assert not _contains_nan(data3) + + data4 = np.array([["1", 2], [3, np.nan]], dtype='object') + assert _contains_nan(data4) + + @pytest.mark.skip_xp_backends(eager_only=True, + reason="lazy backends tested separately") + @pytest.mark.parametrize("nan_policy", ['propagate', 'omit', 'raise']) + def test_array_api(self, xp, nan_policy): + rng = np.random.default_rng(932347235892482) + x0 = rng.random(size=(2, 3, 4)) + x = xp.asarray(x0) + assert not _contains_nan(x, nan_policy) + + x = xpx.at(x)[1, 2, 1].set(xp.nan) + + if nan_policy == 'raise': + with pytest.raises(ValueError, match="The input contains nan values"): + _contains_nan(x, nan_policy) + elif nan_policy == 'omit': + assert _contains_nan(x, nan_policy, xp_omit_okay=True) + elif nan_policy == 'propagate': + assert _contains_nan(x, nan_policy) + + @pytest.mark.skip_xp_backends("numpy", reason="lazy backends only") + @pytest.mark.skip_xp_backends("cupy", reason="lazy backends only") + @pytest.mark.skip_xp_backends("array_api_strict", reason="lazy backends only") + @pytest.mark.skip_xp_backends("torch", reason="lazy backends only") + def test_array_api_lazy(self, xp): + rng = np.random.default_rng(932347235892482) + x0 = rng.random(size=(2, 3, 4)) + x = xp.asarray(x0) + + xp_assert_equal(_contains_nan(x), xp.asarray(False)) + xp_assert_equal(_contains_nan(x, "propagate"), xp.asarray(False)) + xp_assert_equal(_contains_nan(x, "omit", xp_omit_okay=True), xp.asarray(False)) + # Lazy arrays don't support "omit" and "raise" policies + match = "not supported for lazy arrays" + with pytest.raises(TypeError, match=match): + _contains_nan(x, "omit") + with pytest.raises(TypeError, match=match): + _contains_nan(x, "raise") + + x = xpx.at(x)[1, 2, 1].set(np.nan) + + xp_assert_equal(_contains_nan(x), xp.asarray(True)) + xp_assert_equal(_contains_nan(x, "propagate"), xp.asarray(True)) + xp_assert_equal(_contains_nan(x, "omit", xp_omit_okay=True), xp.asarray(True)) + with pytest.raises(TypeError, match=match): + _contains_nan(x, "omit") + with pytest.raises(TypeError, match=match): + _contains_nan(x, "raise") + + +def test__rng_html_rewrite(): + def mock_str(): + lines = [ + 'np.random.default_rng(8989843)', + 'np.random.default_rng(seed)', + 'np.random.default_rng(0x9a71b21474694f919882289dc1559ca)', + ' bob ', + ] + return lines + + res = _rng_html_rewrite(mock_str)() + ref = [ + 'np.random.default_rng()', + 'np.random.default_rng(seed)', + 'np.random.default_rng()', + ' bob ', + ] + + assert res == ref + + +class TestTransitionToRNG: + def kmeans(self, **kwargs): + rng = np.random.default_rng(3458934594269824562) + return cluster.vq.kmeans2(rng.random(size=(20, 3)), 3, **kwargs) + + def kmeans2(self, **kwargs): + rng = np.random.default_rng(3458934594269824562) + return cluster.vq.kmeans2(rng.random(size=(20, 3)), 3, **kwargs) + + def barycentric(self, **kwargs): + rng = np.random.default_rng(3458934594269824562) + x1, x2, y1 = rng.random((3, 10)) + f = interpolate.BarycentricInterpolator(x1, y1, **kwargs) + return f(x2) + + def clarkson_woodruff_transform(self, **kwargs): + rng = np.random.default_rng(3458934594269824562) + return linalg.clarkson_woodruff_transform(rng.random((10, 10)), 3, **kwargs) + + def basinhopping(self, **kwargs): + rng = np.random.default_rng(3458934594269824562) + return optimize.basinhopping(optimize.rosen, rng.random(3), **kwargs).x + + def opt(self, fun, **kwargs): + rng = np.random.default_rng(3458934594269824562) + bounds = optimize.Bounds(-rng.random(3) * 10, rng.random(3) * 10) + return fun(optimize.rosen, bounds, **kwargs).x + + def differential_evolution(self, **kwargs): + return self.opt(optimize.differential_evolution, **kwargs) + + def dual_annealing(self, **kwargs): + return self.opt(optimize.dual_annealing, **kwargs) + + def check_grad(self, **kwargs): + rng = np.random.default_rng(3458934594269824562) + x = rng.random(3) + return optimize.check_grad(optimize.rosen, optimize.rosen_der, x, + direction='random', **kwargs) + + def random_array(self, **kwargs): + return sparse.random_array((10, 10), density=1.0, **kwargs).toarray() + + def random(self, **kwargs): + return sparse.random(10, 10, density=1.0, **kwargs).toarray() + + def rand(self, **kwargs): + return sparse.rand(10, 10, density=1.0, **kwargs).toarray() + + def svds(self, **kwargs): + rng = np.random.default_rng(3458934594269824562) + A = rng.random((10, 10)) + return sparse.linalg.svds(A, **kwargs) + + def random_rotation(self, **kwargs): + return spatial.transform.Rotation.random(3, **kwargs).as_matrix() + + def goodness_of_fit(self, **kwargs): + rng = np.random.default_rng(3458934594269824562) + data = rng.random(100) + return stats.goodness_of_fit(stats.laplace, data, **kwargs).pvalue + + def permutation_test(self, **kwargs): + rng = np.random.default_rng(3458934594269824562) + data = tuple(rng.random((2, 100))) + def statistic(x, y, axis): return np.mean(x, axis=axis) - np.mean(y, axis=axis) + return stats.permutation_test(data, statistic, **kwargs).pvalue + + def bootstrap(self, **kwargs): + rng = np.random.default_rng(3458934594269824562) + data = (rng.random(100),) + return stats.bootstrap(data, np.mean, **kwargs).confidence_interval + + def dunnett(self, **kwargs): + rng = np.random.default_rng(3458934594269824562) + x, y, control = rng.random((3, 100)) + return stats.dunnett(x, y, control=control, **kwargs).pvalue + + def sobol_indices(self, **kwargs): + def f_ishigami(x): return (np.sin(x[0]) + 7 * np.sin(x[1]) ** 2 + + 0.1 * (x[2] ** 4) * np.sin(x[0])) + dists = [stats.uniform(loc=-np.pi, scale=2 * np.pi), + stats.uniform(loc=-np.pi, scale=2 * np.pi), + stats.uniform(loc=-np.pi, scale=2 * np.pi)] + res = stats.sobol_indices(func=f_ishigami, n=1024, dists=dists, **kwargs) + return res.first_order + + def qmc_engine(self, engine, **kwargs): + qrng = engine(d=1, **kwargs) + return qrng.random(4) + + def halton(self, **kwargs): + return self.qmc_engine(stats.qmc.Halton, **kwargs) + + def sobol(self, **kwargs): + return self.qmc_engine(stats.qmc.Sobol, **kwargs) + + def latin_hypercube(self, **kwargs): + return self.qmc_engine(stats.qmc.LatinHypercube, **kwargs) + + def poisson_disk(self, **kwargs): + return self.qmc_engine(stats.qmc.PoissonDisk, **kwargs) + + def multivariate_normal_qmc(self, **kwargs): + X = stats.qmc.MultivariateNormalQMC([0], **kwargs) + return X.random(4) + + def multinomial_qmc(self, **kwargs): + X = stats.qmc.MultinomialQMC([0.5, 0.5], 4, **kwargs) + return X.random(4) + + def permutation_method(self, **kwargs): + rng = np.random.default_rng(3458934594269824562) + data = tuple(rng.random((2, 100))) + method = stats.PermutationMethod(**kwargs) + return stats.pearsonr(*data, method=method).pvalue + + def bootstrap_method(self, **kwargs): + rng = np.random.default_rng(3458934594269824562) + data = tuple(rng.random((2, 100))) + res = stats.pearsonr(*data) + method = stats.BootstrapMethod(**kwargs) + return res.confidence_interval(method=method) + + @pytest.mark.fail_slow(10) + @pytest.mark.slow + @pytest.mark.parametrize("method, arg_name", [ + (kmeans, "seed"), + (kmeans2, "seed"), + (barycentric, "random_state"), + (clarkson_woodruff_transform, "seed"), + (basinhopping, "seed"), + (differential_evolution, "seed"), + (dual_annealing, "seed"), + (check_grad, "seed"), + (random_array, 'random_state'), + (random, 'random_state'), + (rand, 'random_state'), + (random_rotation, "random_state"), + (goodness_of_fit, "random_state"), + (permutation_test, "random_state"), + (bootstrap, "random_state"), + (permutation_method, "random_state"), + (bootstrap_method, "random_state"), + (dunnett, "random_state"), + (sobol_indices, "random_state"), + (halton, "seed"), + (sobol, "seed"), + (latin_hypercube, "seed"), + (poisson_disk, "seed"), + (multivariate_normal_qmc, "seed"), + (multinomial_qmc, "seed"), + ]) + def test_rng_deterministic(self, method, arg_name): + np.random.seed(None) + seed = 2949672964 + + rng = np.random.default_rng(seed) + message = "got multiple values for argument now known as `rng`" + with pytest.raises(TypeError, match=message): + method(self, **{'rng': rng, arg_name: seed}) + + rng = np.random.default_rng(seed) + res1 = method(self, rng=rng) + res2 = method(self, rng=seed) + assert_equal(res2, res1) + + if method.__name__ in {"dunnett", "sobol_indices"}: + # the two kwargs have essentially the same behavior for these functions + res3 = method(self, **{arg_name: seed}) + assert_equal(res3, res1) + return + + rng = np.random.RandomState(seed) + res1 = method(self, **{arg_name: rng}) + res2 = method(self, **{arg_name: seed}) + + if method.__name__ in {"halton", "sobol", "latin_hypercube", "poisson_disk", + "multivariate_normal_qmc", "multinomial_qmc"}: + # For these, passing `random_state=RandomState(seed)` is not the same as + # passing integer `seed`. + res1b = method(self, **{arg_name: np.random.RandomState(seed)}) + assert_equal(res1b, res1) + res2b = method(self, **{arg_name: seed}) + assert_equal(res2b, res2) + return + + np.random.seed(seed) + res3 = method(self, **{arg_name: None}) + assert_equal(res2, res1) + assert_equal(res3, res1) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_array_api.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_array_api.py new file mode 100644 index 0000000000000000000000000000000000000000..cb7735debae5a18640aca3c6c6c330e7f1802e81 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_array_api.py @@ -0,0 +1,400 @@ +import re + +import numpy as np +import pytest + +from importlib import import_module + +from scipy._lib._array_api import ( + SCIPY_ARRAY_API, array_namespace, _asarray, xp_copy, xp_assert_equal, is_numpy, + np_compat, xp_default_dtype, xp_result_type, is_torch, + xp_capabilities_table, _xp_copy_to_numpy +) +from scipy._lib._array_api_docs_tables import is_named_function_like_object +from scipy._lib import array_api_extra as xpx +from scipy._lib._array_api_no_0d import xp_assert_equal as xp_assert_equal_no_0d +from scipy._lib.array_api_extra.testing import lazy_xp_function + +# Run all tests in this module in the Array API CI, +# including those without the `xp` fixture +pytestmark = pytest.mark.array_api_backends + +lazy_xp_function(_asarray) +lazy_xp_function(xp_copy) + + +@pytest.mark.skipif(not SCIPY_ARRAY_API, + reason="Array API test; set environment variable SCIPY_ARRAY_API=1 to run it") +class TestArrayAPI: + + def test_array_namespace(self): + x, y = np.array([0, 1, 2]), np.array([0, 1, 2]) + xp = array_namespace(x, y) + assert 'array_api_compat.numpy' in xp.__name__ + + def test_asarray(self, xp): + x, y = _asarray([0, 1, 2], xp=xp), _asarray(np.arange(3), xp=xp) + ref = xp.asarray([0, 1, 2]) + xp_assert_equal(x, ref) + xp_assert_equal(y, ref) + + @pytest.mark.filterwarnings("ignore: the matrix subclass") + def test_raises(self): + msg = "of type `numpy.ma.MaskedArray` are not supported" + with pytest.raises(TypeError, match=msg): + array_namespace(np.ma.array(1), np.array(1)) + + msg = "of type `numpy.matrix` are not supported" + with pytest.raises(TypeError, match=msg): + array_namespace(np.array(1), np.matrix(1)) + + msg = "only boolean and numerical dtypes are supported" + with pytest.raises(TypeError, match=msg): + array_namespace([object()]) + with pytest.raises(TypeError, match=msg): + array_namespace('abc') + + @pytest.mark.skip_xp_backends(np_only=True, reason="Array-likes") + def test_array_likes(self, xp): + """Test that if all parameters of array_namespace are Array-likes, + the output is array_api_compat.numpy + """ + assert array_namespace([0, 1, 2]) is xp + assert array_namespace((0, 1, 2)) is xp + assert array_namespace(1, 2, 3) is xp + assert array_namespace(1) is xp + assert array_namespace(np.int64(1)) is xp + assert array_namespace([0, 1, 2], 3) is xp + assert array_namespace() is xp + assert array_namespace(None) is xp + assert array_namespace(1, None) is xp + assert array_namespace(None, 1) is xp + + # This only works when xp is numpy! + assert array_namespace(np.asarray([1, 2]), [3, 4]) is xp + assert array_namespace(np.int64(1), [3, 4]) is xp + + def test_array_and_array_likes_mix(self, xp): + """Test that if there is at least one Array API object among + the parameters of array_namespace, and all other parameters + are scalars, the output is its namespace. + + If there are non-scalar Array-Likes, raise as in array-api-compat. + """ + x = xp.asarray(1) + assert array_namespace(x) is xp + assert array_namespace(x, 1) is xp + assert array_namespace(1, x) is xp + assert array_namespace(None, x) is xp + + if is_numpy(xp): + assert array_namespace(x, [1, 2]) is xp + else: + with pytest.raises(TypeError, match="Multiple namespaces"): + array_namespace(x, [1, 2]) + with pytest.raises(TypeError, match="Multiple namespaces"): + array_namespace(x, np.int64(1)) + with pytest.raises(TypeError, match="Multiple namespaces"): + # Subclass of float; matches array_api_compat behavior + array_namespace(x, np.float64(1)) + with pytest.raises(TypeError, match="Multiple namespaces"): + # Subclass of complex; matches array_api_compat behavior + array_namespace(x, np.complex128(1)) + + def test_array_api_extra_hook(self): + """Test that the `array_namespace` function used by + array-api-extra has been overridden by scipy + """ + msg = "only boolean and numerical dtypes are supported" + with pytest.raises(TypeError, match=msg): + xpx.atleast_nd("abc", ndim=0) + + def test_jax_zero_gradient_array(self): + """Test array_namespace special case for JAX zero-gradient arrays, which are + numpy arrays but must be treated as JAX arrays. + See matching code and tests in array_api_compat. + """ + jax = pytest.importorskip("jax") + xp = pytest.importorskip("jax.numpy") + # Create numpy array with dtype=jax.float0 + jax_zero = jax.vmap(jax.grad(xp.float32, allow_int=True))(xp.arange(4)) + assert array_namespace(jax_zero) is xp + + def test_void_but_not_jax_zero_gradient_array(self): + """A void dtype that is not a jax.float0 must not be caught in the + special case for JAX zero-gradient arrays. + """ + void = np.empty(0, dtype=np.dtype([])) + with pytest.raises(TypeError, match="only boolean and numerical dtypes"): + array_namespace(void) + with pytest.raises(TypeError, match="only boolean and numerical dtypes"): + array_namespace([void, void]) + + def test_copy(self, xp): + for _xp in [xp, None]: + x = xp.asarray([1, 2, 3]) + y = xp_copy(x, xp=_xp) + # with numpy we'd want to use np.shared_memory, but that's not specified + # in the array-api + assert id(x) != id(y) + try: + y[0] = 10 + except (TypeError, ValueError): + pass + else: + assert x[0] != y[0] + + @pytest.mark.parametrize( + "dtype", + ["float32", "float64", "complex64", "complex128", "int32", "int64"], + ) + @pytest.mark.parametrize( + "data", [[], 1, [1, 2, 3], [[1, 2], [2, 3]]], + ) + def test_copy_to_numpy(self, xp, data, dtype): + xp_dtype = getattr(xp, dtype) + np_dtype = getattr(np, dtype) + x = xp.asarray(data, dtype=xp_dtype) + y = _xp_copy_to_numpy(x) + assert isinstance(y, np.ndarray) + assert y.dtype == np_dtype + assert x.shape == y.shape + np.testing.assert_equal(y, np.asarray(data, dtype=np_dtype)) + if is_numpy(xp): + # Ensure y is a copy when xp is numpy. + assert id(x) != id(y) + + + @pytest.mark.parametrize('dtype', ['int32', 'int64', 'float32', 'float64']) + @pytest.mark.parametrize('shape', [(), (3,)]) + def test_strict_checks(self, xp, dtype, shape): + # Check that `_strict_check` behaves as expected + dtype = getattr(xp, dtype) + x = xp.broadcast_to(xp.asarray(1, dtype=dtype), shape) + x = x if shape else x[()] + y = np_compat.asarray(1)[()] + + kwarg_names = ["check_namespace", "check_dtype", "check_shape", "check_0d"] + options = dict(zip(kwarg_names, [True, False, False, False])) + if is_numpy(xp): + xp_assert_equal(x, y, **options) + else: + with pytest.raises( + AssertionError, + match="Namespace of desired array does not match", + ): + xp_assert_equal(x, y, **options) + with pytest.raises( + AssertionError, + match="Namespace of actual and desired arrays do not match", + ): + xp_assert_equal(y, x, **options) + + options = dict(zip(kwarg_names, [False, True, False, False])) + if y.dtype.name in str(x.dtype): + xp_assert_equal(x, y, **options) + else: + with pytest.raises(AssertionError, match="dtypes do not match."): + xp_assert_equal(x, y, **options) + + options = dict(zip(kwarg_names, [False, False, True, False])) + if x.shape == y.shape: + xp_assert_equal(x, y, **options) + else: + with pytest.raises(AssertionError, match="Shapes do not match."): + xp_assert_equal(x, xp.asarray(y), **options) + + options = dict(zip(kwarg_names, [False, False, False, True])) + if is_numpy(xp) and x.shape == y.shape: + xp_assert_equal(x, y, **options) + elif is_numpy(xp): + with pytest.raises(AssertionError, match="Array-ness does not match."): + xp_assert_equal(x, y, **options) + + @pytest.mark.skip_xp_backends(np_only=True, reason="Scalars only exist in NumPy") + def test_check_scalar(self, xp): + # identity always passes + xp_assert_equal(xp.float64(0), xp.float64(0)) + xp_assert_equal(xp.asarray(0.), xp.asarray(0.)) + xp_assert_equal(xp.float64(0), xp.float64(0), check_0d=False) + xp_assert_equal(xp.asarray(0.), xp.asarray(0.), check_0d=False) + + # Check default convention: 0d-arrays are distinguished from scalars + message = "Array-ness does not match:.*" + with pytest.raises(AssertionError, match=message): + xp_assert_equal(xp.asarray(0.), xp.float64(0)) + with pytest.raises(AssertionError, match=message): + xp_assert_equal(xp.float64(0), xp.asarray(0.)) + with pytest.raises(AssertionError, match=message): + xp_assert_equal(xp.asarray(42), xp.int64(42)) + with pytest.raises(AssertionError, match=message): + xp_assert_equal(xp.int64(42), xp.asarray(42)) + + # with `check_0d=False`, scalars-vs-0d passes (if values match) + xp_assert_equal(xp.asarray(0.), xp.float64(0), check_0d=False) + xp_assert_equal(xp.float64(0), xp.asarray(0.), check_0d=False) + # also with regular python objects + xp_assert_equal(xp.asarray(0.), 0., check_0d=False) + xp_assert_equal(0., xp.asarray(0.), check_0d=False) + xp_assert_equal(xp.asarray(42), 42, check_0d=False) + xp_assert_equal(42, xp.asarray(42), check_0d=False) + + # as an alternative to `check_0d=False`, explicitly expect scalar + xp_assert_equal(xp.float64(0), xp.asarray(0.)[()]) + + @pytest.mark.skip_xp_backends(np_only=True, reason="Scalars only exist in NumPy") + def test_check_scalar_no_0d(self, xp): + # identity passes, if first argument is not 0d (or check_0d=True) + xp_assert_equal_no_0d(xp.float64(0), xp.float64(0)) + xp_assert_equal_no_0d(xp.float64(0), xp.float64(0), check_0d=True) + xp_assert_equal_no_0d(xp.asarray(0.), xp.asarray(0.), check_0d=True) + + # by default, 0d values are forbidden as the first argument + message = "Result is a NumPy 0d-array.*" + with pytest.raises(AssertionError, match=message): + xp_assert_equal_no_0d(xp.asarray(0.), xp.asarray(0.)) + with pytest.raises(AssertionError, match=message): + xp_assert_equal_no_0d(xp.asarray(0.), xp.float64(0)) + with pytest.raises(AssertionError, match=message): + xp_assert_equal_no_0d(xp.asarray(42), xp.int64(42)) + + # Check default convention: 0d-arrays are NOT distinguished from scalars + xp_assert_equal_no_0d(xp.float64(0), xp.asarray(0.)) + xp_assert_equal_no_0d(xp.int64(42), xp.asarray(42)) + + # opt in to 0d-check remains possible + message = "Array-ness does not match:.*" + with pytest.raises(AssertionError, match=message): + xp_assert_equal_no_0d(xp.asarray(0.), xp.float64(0), check_0d=True) + with pytest.raises(AssertionError, match=message): + xp_assert_equal_no_0d(xp.float64(0), xp.asarray(0.), check_0d=True) + with pytest.raises(AssertionError, match=message): + xp_assert_equal_no_0d(xp.asarray(42), xp.int64(0), check_0d=True) + with pytest.raises(AssertionError, match=message): + xp_assert_equal_no_0d(xp.int64(0), xp.asarray(42), check_0d=True) + + # scalars-vs-0d passes (if values match) also with regular python objects + xp_assert_equal_no_0d(0., xp.asarray(0.)) + xp_assert_equal_no_0d(42, xp.asarray(42)) + + def test_default_dtype(self, xp): + assert xp_default_dtype(xp) == xp.asarray(1.).dtype + + +scalars = [1, 1., 1. + 1j] +lists = [[1], [1.], [1. + 1j]] +types = ('int8 int16 int32 int64 ' + 'uint8 uint16 uint32 uint64 ' + 'float32 float64 complex64 complex128').split() +arrays = [np.asarray([1], dtype=getattr(np, t)) for t in types] + + +def convert_type(x, xp): + # Convert NumPy array to xp-array + # Convert string to indicated dtype from xp + # Return Python scalars unchanged + if isinstance(x, np.ndarray): + return xp.asarray(x) + elif isinstance(x, str): + return getattr(xp, x) + return x + + +def is_inexact(x, xp): + # Determine whether `x` is of inexact (real of complex floating) dtype + x = xp.asarray(x) if np.isscalar(x) or isinstance(x, list) else x + dtype = getattr(x, 'dtype', x) + return xp.isdtype(dtype, ('real floating', 'complex floating')) + + +@pytest.mark.parametrize('x', scalars + lists + types + arrays) +@pytest.mark.parametrize('y', scalars + lists + types + arrays) +def test_xp_result_type_no_force(x, y, xp): + # When force_floating==False (default), behavior of `xp_result_type` + # should match that of `xp.result_type` on the same arguments after + # converting lists to arrays of type `xp`. + x = convert_type(x, xp) + y = convert_type(y, xp) + x_ref = xp.asarray(x) if isinstance(x, list) else x + y_ref = xp.asarray(y) if isinstance(y, list) else y + + try: + dtype_ref = xp.result_type(x_ref, y_ref) + expected_error = None + except Exception as e: + expected_error = (type(e), str(e)) + + if expected_error is not None: + with pytest.raises(expected_error[0], match=re.escape(expected_error[1])): + xp_result_type(x, y, xp=xp) + return + + dtype_res = xp_result_type(x, y, xp=xp) + assert dtype_res == dtype_ref + + +@pytest.mark.parametrize('x', scalars + lists + types + arrays) +@pytest.mark.parametrize('y', scalars + lists + types + arrays) +def test_xp_result_type_force_floating(x, y, xp): + # When `force_floating==True`, behavior of `xp_result_type` + # should match that of `xp.result_type` with `1.0` appended to the set of + # arguments (after converting lists to arrays of type `xp`). + # If this raises a `TypeError`, which is the case when the result + # type is not defined by the standard, the result type should be + # the result type of any inexact (real or complex floating) arguments + # and the default floating point type. + if (is_torch(xp) and not(isinstance(x, str) or isinstance(y, str)) + and np.isscalar(x) and np.isscalar(y)): + pytest.skip("See 3/27/2024 comment at data-apis/array-api-compat#277") + + x = convert_type(x, xp) + y = convert_type(y, xp) + x_ref = xp.asarray(x) if isinstance(x, list) else x + y_ref = xp.asarray(y) if isinstance(y, list) else y + + expected_error = None + try: + dtype_ref = xp.result_type(x_ref, y_ref, 1.0) + except TypeError: + args = [] + if is_inexact(x_ref, xp): + args.append(x_ref) + if is_inexact(y_ref, xp): + args.append(y_ref) + dtype_ref = xp.result_type(*args, xp.asarray(1.0)) + except Exception as e: + expected_error = (type(e), str(e)) + + if expected_error is not None: + with pytest.raises(expected_error[0], match=expected_error[1]): + xp_result_type(x, y, xp=xp) + return + + dtype_res = xp_result_type(x, y, force_floating=True, xp=xp) + assert dtype_res == dtype_ref + +# Test that the xp_capabilities decorator has been applied to all +# functions and function-likes in the public API. Modules will be +# added to the list of tested_modules below as decorator coverage +# is added on a module by module basis. It remains for future work +# to offer similar functionality to xp_capabilities for classes in +# the public API. + +tested_modules = ["scipy.stats"] + + +def collect_public_functions(): + functions = [] + for module_name in tested_modules: + module = import_module(module_name) + for name in module.__all__: + obj = getattr(module, name) + if not is_named_function_like_object(obj): + continue + functions.append(pytest.param(obj, id=f"{module_name}.{name}")) + return functions + + +@pytest.mark.parametrize("func", collect_public_functions()) +def test_xp_capabilities_coverage(func): + assert func in xp_capabilities_table diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_bunch.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_bunch.py new file mode 100644 index 0000000000000000000000000000000000000000..96008627e3afef540913071c95ea543c718a326c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_bunch.py @@ -0,0 +1,169 @@ +import pytest +import pickle +from numpy.testing import assert_equal +from scipy._lib._bunch import _make_tuple_bunch + + +# `Result` is defined at the top level of the module so it can be +# used to test pickling. +Result = _make_tuple_bunch('Result', ['x', 'y', 'z'], ['w', 'beta']) + + +class TestMakeTupleBunch: + + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + # Tests with Result + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + def setup_method(self): + # Set up an instance of Result. + self.result = Result(x=1, y=2, z=3, w=99, beta=0.5) + + def test_attribute_access(self): + assert_equal(self.result.x, 1) + assert_equal(self.result.y, 2) + assert_equal(self.result.z, 3) + assert_equal(self.result.w, 99) + assert_equal(self.result.beta, 0.5) + + def test_indexing(self): + assert_equal(self.result[0], 1) + assert_equal(self.result[1], 2) + assert_equal(self.result[2], 3) + assert_equal(self.result[-1], 3) + with pytest.raises(IndexError, match='index out of range'): + self.result[3] + + def test_unpacking(self): + x0, y0, z0 = self.result + assert_equal((x0, y0, z0), (1, 2, 3)) + assert_equal(self.result, (1, 2, 3)) + + def test_slice(self): + assert_equal(self.result[1:], (2, 3)) + assert_equal(self.result[::2], (1, 3)) + assert_equal(self.result[::-1], (3, 2, 1)) + + def test_len(self): + assert_equal(len(self.result), 3) + + def test_repr(self): + s = repr(self.result) + assert_equal(s, 'Result(x=1, y=2, z=3, w=99, beta=0.5)') + + def test_hash(self): + assert_equal(hash(self.result), hash((1, 2, 3))) + + def test_pickle(self): + s = pickle.dumps(self.result) + obj = pickle.loads(s) + assert isinstance(obj, Result) + assert_equal(obj.x, self.result.x) + assert_equal(obj.y, self.result.y) + assert_equal(obj.z, self.result.z) + assert_equal(obj.w, self.result.w) + assert_equal(obj.beta, self.result.beta) + + def test_read_only_existing(self): + with pytest.raises(AttributeError, match="can't set attribute"): + self.result.x = -1 + + def test_read_only_new(self): + self.result.plate_of_shrimp = "lattice of coincidence" + assert self.result.plate_of_shrimp == "lattice of coincidence" + + def test_constructor_missing_parameter(self): + with pytest.raises(TypeError, match='missing'): + # `w` is missing. + Result(x=1, y=2, z=3, beta=0.75) + + def test_constructor_incorrect_parameter(self): + with pytest.raises(TypeError, match='unexpected'): + # `foo` is not an existing field. + Result(x=1, y=2, z=3, w=123, beta=0.75, foo=999) + + def test_module(self): + m = 'scipy._lib.tests.test_bunch' + assert_equal(Result.__module__, m) + assert_equal(self.result.__module__, m) + + def test_extra_fields_per_instance(self): + # This test exists to ensure that instances of the same class + # store their own values for the extra fields. That is, the values + # are stored per instance and not in the class. + result1 = Result(x=1, y=2, z=3, w=-1, beta=0.0) + result2 = Result(x=4, y=5, z=6, w=99, beta=1.0) + assert_equal(result1.w, -1) + assert_equal(result1.beta, 0.0) + # The rest of these checks aren't essential, but let's check + # them anyway. + assert_equal(result1[:], (1, 2, 3)) + assert_equal(result2.w, 99) + assert_equal(result2.beta, 1.0) + assert_equal(result2[:], (4, 5, 6)) + + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + # Other tests + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + def test_extra_field_names_is_optional(self): + Square = _make_tuple_bunch('Square', ['width', 'height']) + sq = Square(width=1, height=2) + assert_equal(sq.width, 1) + assert_equal(sq.height, 2) + s = repr(sq) + assert_equal(s, 'Square(width=1, height=2)') + + def test_tuple_like(self): + Tup = _make_tuple_bunch('Tup', ['a', 'b']) + tu = Tup(a=1, b=2) + assert isinstance(tu, tuple) + assert isinstance(tu + (1,), tuple) + + def test_explicit_module(self): + m = 'some.module.name' + Foo = _make_tuple_bunch('Foo', ['x'], ['a', 'b'], module=m) + foo = Foo(x=1, a=355, b=113) + assert_equal(Foo.__module__, m) + assert_equal(foo.__module__, m) + + def test_passes_polars_checks(self): + # gh-22450 + Square = _make_tuple_bunch('Square', ['width', 'height']) + assert hasattr(Square, '_replace') + assert hasattr(Square, '_field_defaults') + + + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + # Argument validation + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @pytest.mark.parametrize('args', [('123', ['a'], ['b']), + ('Foo', ['-3'], ['x']), + ('Foo', ['a'], ['+-*/'])]) + def test_identifiers_not_allowed(self, args): + with pytest.raises(ValueError, match='identifiers'): + _make_tuple_bunch(*args) + + @pytest.mark.parametrize('args', [('Foo', ['a', 'b', 'a'], ['x']), + ('Foo', ['a', 'b'], ['b', 'x'])]) + def test_repeated_field_names(self, args): + with pytest.raises(ValueError, match='Duplicate'): + _make_tuple_bunch(*args) + + @pytest.mark.parametrize('args', [('Foo', ['_a'], ['x']), + ('Foo', ['a'], ['_x'])]) + def test_leading_underscore_not_allowed(self, args): + with pytest.raises(ValueError, match='underscore'): + _make_tuple_bunch(*args) + + @pytest.mark.parametrize('args', [('Foo', ['def'], ['x']), + ('Foo', ['a'], ['or']), + ('and', ['a'], ['x'])]) + def test_keyword_not_allowed_in_fields(self, args): + with pytest.raises(ValueError, match='keyword'): + _make_tuple_bunch(*args) + + def test_at_least_one_field_name_required(self): + with pytest.raises(ValueError, match='at least one name'): + _make_tuple_bunch('Qwerty', [], ['a', 'b']) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_ccallback.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_ccallback.py new file mode 100644 index 0000000000000000000000000000000000000000..e8a2c97c6f67732f55eea6ed5cad297f5068a714 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_ccallback.py @@ -0,0 +1,196 @@ +from numpy.testing import assert_equal, assert_ +from pytest import raises as assert_raises + +import time +import pytest +import ctypes +import threading +from scipy._lib import _ccallback_c as _test_ccallback_cython +from scipy._lib import _test_ccallback +from scipy._lib._ccallback import LowLevelCallable + + +ERROR_VALUE = 2.0 + + +def callback_python(a, user_data=None): + if a == ERROR_VALUE: + raise ValueError("bad value") + + if user_data is None: + return a + 1 + else: + return a + user_data + +def _get_cffi_func(base, signature): + cffi = pytest.importorskip("cffi") + + # Get function address + voidp = ctypes.cast(base, ctypes.c_void_p) + address = voidp.value + + # Create corresponding cffi handle + ffi = cffi.FFI() + func = ffi.cast(signature, address) + return func + + +def _get_ctypes_data(): + value = ctypes.c_double(2.0) + return ctypes.cast(ctypes.pointer(value), ctypes.c_voidp) + + +def _get_cffi_data(): + cffi = pytest.importorskip("cffi") + ffi = cffi.FFI() + return ffi.new('double *', 2.0) + + +CALLERS = { + 'simple': _test_ccallback.test_call_simple, + 'nodata': _test_ccallback.test_call_nodata, + 'nonlocal': _test_ccallback.test_call_nonlocal, + 'cython': _test_ccallback_cython.test_call_cython, +} + +# These functions have signatures known to the callers +FUNCS = { + 'python': lambda: callback_python, + 'capsule': lambda: _test_ccallback.test_get_plus1_capsule(), + 'cython': lambda: LowLevelCallable.from_cython(_test_ccallback_cython, + "plus1_cython"), + 'ctypes': lambda: _test_ccallback_cython.plus1_ctypes, + 'cffi': lambda: _get_cffi_func(_test_ccallback_cython.plus1_ctypes, + 'double (*)(double, int *, void *)'), + 'capsule_b': lambda: _test_ccallback.test_get_plus1b_capsule(), + 'cython_b': lambda: LowLevelCallable.from_cython(_test_ccallback_cython, + "plus1b_cython"), + 'ctypes_b': lambda: _test_ccallback_cython.plus1b_ctypes, + 'cffi_b': lambda: _get_cffi_func(_test_ccallback_cython.plus1b_ctypes, + 'double (*)(double, double, int *, void *)'), +} + +# These functions have signatures the callers don't know +BAD_FUNCS = { + 'capsule_bc': lambda: _test_ccallback.test_get_plus1bc_capsule(), + 'cython_bc': lambda: LowLevelCallable.from_cython(_test_ccallback_cython, + "plus1bc_cython"), + 'ctypes_bc': lambda: _test_ccallback_cython.plus1bc_ctypes, + 'cffi_bc': lambda: _get_cffi_func( + _test_ccallback_cython.plus1bc_ctypes, + 'double (*)(double, double, double, int *, void *)' + ), +} + +USER_DATAS = { + 'ctypes': _get_ctypes_data, + 'cffi': _get_cffi_data, + 'capsule': _test_ccallback.test_get_data_capsule, +} + + +def test_callbacks(): + def check(caller, func, user_data): + caller = CALLERS[caller] + func = FUNCS[func]() + user_data = USER_DATAS[user_data]() + + if func is callback_python: + def func2(x): + return func(x, 2.0) + else: + func2 = LowLevelCallable(func, user_data) + func = LowLevelCallable(func) + + # Test basic call + assert_equal(caller(func, 1.0), 2.0) + + # Test 'bad' value resulting to an error + assert_raises(ValueError, caller, func, ERROR_VALUE) + + # Test passing in user_data + assert_equal(caller(func2, 1.0), 3.0) + + for caller in sorted(CALLERS.keys()): + for func in sorted(FUNCS.keys()): + for user_data in sorted(USER_DATAS.keys()): + check(caller, func, user_data) + + +def test_bad_callbacks(): + def check(caller, func, user_data): + caller = CALLERS[caller] + user_data = USER_DATAS[user_data]() + func = BAD_FUNCS[func]() + + if func is callback_python: + def func2(x): + return func(x, 2.0) + else: + func2 = LowLevelCallable(func, user_data) + func = LowLevelCallable(func) + + # Test that basic call fails + assert_raises(ValueError, caller, LowLevelCallable(func), 1.0) + + # Test that passing in user_data also fails + assert_raises(ValueError, caller, func2, 1.0) + + # Test error message + llfunc = LowLevelCallable(func) + try: + caller(llfunc, 1.0) + except ValueError as err: + msg = str(err) + assert_(llfunc.signature in msg, msg) + assert_('double (double, double, int *, void *)' in msg, msg) + + for caller in sorted(CALLERS.keys()): + for func in sorted(BAD_FUNCS.keys()): + for user_data in sorted(USER_DATAS.keys()): + check(caller, func, user_data) + + +def test_signature_override(): + caller = _test_ccallback.test_call_simple + func = _test_ccallback.test_get_plus1_capsule() + + llcallable = LowLevelCallable(func, signature="bad signature") + assert_equal(llcallable.signature, "bad signature") + assert_raises(ValueError, caller, llcallable, 3) + + llcallable = LowLevelCallable(func, signature="double (double, int *, void *)") + assert_equal(llcallable.signature, "double (double, int *, void *)") + assert_equal(caller(llcallable, 3), 4) + + +def test_threadsafety(): + def callback(a, caller): + if a <= 0: + return 1 + else: + res = caller(lambda x: callback(x, caller), a - 1) + return 2*res + + def check(caller): + caller = CALLERS[caller] + + results = [] + + count = 10 + + def run(): + time.sleep(0.01) + r = caller(lambda x: callback(x, caller), count) + results.append(r) + + threads = [threading.Thread(target=run) for j in range(20)] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + + assert_equal(results, [2.0**count]*len(threads)) + + for caller in CALLERS.keys(): + check(caller) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_config.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_config.py new file mode 100644 index 0000000000000000000000000000000000000000..b43d3f9f0da39a86b78cb2210cb21d670e5cf978 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_config.py @@ -0,0 +1,44 @@ +""" +Check the SciPy config is valid. +""" +import scipy +import pytest +from unittest.mock import patch + +pytestmark = pytest.mark.skipif( + not hasattr(scipy.__config__, "_built_with_meson"), + reason="Requires Meson builds", +) + + +class TestSciPyConfigs: + REQUIRED_CONFIG_KEYS = [ + "Compilers", + "Machine Information", + "Python Information", + ] + + @patch("scipy.__config__._check_pyyaml") + def test_pyyaml_not_found(self, mock_yaml_importer): + mock_yaml_importer.side_effect = ModuleNotFoundError() + with pytest.warns(UserWarning): + scipy.show_config() + + def test_dict_mode(self): + config = scipy.show_config(mode="dicts") + + assert isinstance(config, dict) + assert all([key in config for key in self.REQUIRED_CONFIG_KEYS]), ( + "Required key missing," + " see index of `False` with `REQUIRED_CONFIG_KEYS`" + ) + + def test_invalid_mode(self): + with pytest.raises(AttributeError): + scipy.show_config(mode="foo") + + def test_warn_to_add_tests(self): + assert len(scipy.__config__.DisplayModes) == 2, ( + "New mode detected," + " please add UT if applicable and increment this count" + ) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_deprecation.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_deprecation.py new file mode 100644 index 0000000000000000000000000000000000000000..36d4b671117ba54fa612e7de504382c238dc18ff --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_deprecation.py @@ -0,0 +1,10 @@ +import pytest + +@pytest.mark.thread_unsafe(reason="deprecate_cython_api is not thread-safe") +def test_cython_api_deprecation(): + match = ("`scipy._lib._test_deprecation_def.foo_deprecated` " + "is deprecated, use `foo` instead!\n" + "Deprecated in Scipy 42.0.0") + with pytest.warns(DeprecationWarning, match=match): + from .. import _test_deprecation_call + assert _test_deprecation_call.call() == (1, 1) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_doccer.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_doccer.py new file mode 100644 index 0000000000000000000000000000000000000000..d351b12da33e0f873e71b6ab6c11fa3aff5e9430 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_doccer.py @@ -0,0 +1,144 @@ +''' Some tests for the documenting decorator and support functions ''' + +import sys +import warnings +import pytest +from numpy.testing import assert_equal + +from scipy._lib import doccer + +# python -OO strips docstrings +DOCSTRINGS_STRIPPED = sys.flags.optimize > 1 + +docstring = \ +"""Docstring + %(strtest1)s + %(strtest2)s + %(strtest3)s +""" +param_doc1 = \ +"""Another test + with some indent""" + +param_doc2 = \ +"""Another test, one line""" + +param_doc3 = \ +""" Another test + with some indent""" + +doc_dict = {'strtest1':param_doc1, + 'strtest2':param_doc2, + 'strtest3':param_doc3} + +filled_docstring = \ +"""Docstring + Another test + with some indent + Another test, one line + Another test + with some indent +""" + + +def test_unindent(): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", category=DeprecationWarning) + assert_equal(doccer.unindent_string(param_doc1), param_doc1) + assert_equal(doccer.unindent_string(param_doc2), param_doc2) + assert_equal(doccer.unindent_string(param_doc3), param_doc1) + + +def test_unindent_dict(): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", category=DeprecationWarning) + d2 = doccer.unindent_dict(doc_dict) + assert_equal(d2['strtest1'], doc_dict['strtest1']) + assert_equal(d2['strtest2'], doc_dict['strtest2']) + assert_equal(d2['strtest3'], doc_dict['strtest1']) + + +def test_docformat(): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", category=DeprecationWarning) + udd = doccer.unindent_dict(doc_dict) + formatted = doccer.docformat(docstring, udd) + assert_equal(formatted, filled_docstring) + single_doc = 'Single line doc %(strtest1)s' + formatted = doccer.docformat(single_doc, doc_dict) + # Note - initial indent of format string does not + # affect subsequent indent of inserted parameter + assert_equal(formatted, """Single line doc Another test + with some indent""") + + +@pytest.mark.skipif(DOCSTRINGS_STRIPPED, reason="docstrings stripped") +def test_decorator(): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", category=DeprecationWarning) + # with unindentation of parameters + decorator = doccer.filldoc(doc_dict, True) + + @decorator + def func(): + """ Docstring + %(strtest3)s + """ + + def expected(): + """ Docstring + Another test + with some indent + """ + assert_equal(func.__doc__, expected.__doc__) + + # without unindentation of parameters + + # The docstring should be unindented for Python 3.13+ + # because of https://github.com/python/cpython/issues/81283 + decorator = doccer.filldoc(doc_dict, False if \ + sys.version_info < (3, 13) else True) + + @decorator + def func(): + """ Docstring + %(strtest3)s + """ + def expected(): + """ Docstring + Another test + with some indent + """ + assert_equal(func.__doc__, expected.__doc__) + + +@pytest.mark.skipif(DOCSTRINGS_STRIPPED, reason="docstrings stripped") +def test_inherit_docstring_from(): + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", category=DeprecationWarning) + + class Foo: + def func(self): + '''Do something useful.''' + return + + def func2(self): + '''Something else.''' + + class Bar(Foo): + @doccer.inherit_docstring_from(Foo) + def func(self): + '''%(super)sABC''' + return + + @doccer.inherit_docstring_from(Foo) + def func2(self): + # No docstring. + return + + assert_equal(Bar.func.__doc__, Foo.func.__doc__ + 'ABC') + assert_equal(Bar.func2.__doc__, Foo.func2.__doc__) + bar = Bar() + assert_equal(bar.func.__doc__, Foo.func.__doc__ + 'ABC') + assert_equal(bar.func2.__doc__, Foo.func2.__doc__) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_import_cycles.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_import_cycles.py new file mode 100644 index 0000000000000000000000000000000000000000..d1d7c2bfca4976019b77bfbbfbc0cc4ca96a6962 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_import_cycles.py @@ -0,0 +1,26 @@ +import multiprocessing +import subprocess +import sys + +import pytest + +from .test_public_api import PUBLIC_MODULES + +# Regression tests for gh-6793. +# Check that all modules are importable in a new Python process. +# This is not necessarily true if there are import cycles present. + + +def _check_single_module(module): + pid = subprocess.Popen([sys.executable, '-X', 'faulthandler', '-c', + f'import {module}']) + assert pid.wait() == 0, f'Failed to import {module}' + + +@pytest.mark.fail_slow(40) +@pytest.mark.slow +def test_public_modules_importable_2(): + # Ensure we use max 6 processes, to limit peak resource usage (memory, file handles) + # on resource-constrained systems (e.g., RISC-V - see gh-24163). + with multiprocessing.Pool(processes=6) as pool: + pool.map(_check_single_module, PUBLIC_MODULES) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_public_api.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_public_api.py new file mode 100644 index 0000000000000000000000000000000000000000..dfafb4f223364fd566a83bf3425e8077f96dafad --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_public_api.py @@ -0,0 +1,433 @@ +""" +This test script is adopted from: + https://github.com/numpy/numpy/blob/main/numpy/tests/test_public_api.py +""" + +import pkgutil +import types +import importlib +import warnings +from importlib import import_module + +import pytest + +import scipy + +from scipy._lib._public_api import PUBLIC_MODULES +from scipy.conftest import xp_available_backends + + +def test_dir_testing(): + """Assert that output of dir has only one "testing/tester" + attribute without duplicate""" + assert len(dir(scipy)) == len(set(dir(scipy))) + + +# The PRIVATE_BUT_PRESENT_MODULES list contains modules that lacked underscores +# in their name and hence looked public, but weren't meant to be. All these +# namespace were deprecated in the 1.8.0 release - see "clear split between +# public and private API" in the 1.8.0 release notes. +# These private modules support will be removed in SciPy v2.0.0, as the +# deprecation messages emitted by each of these modules say. +PRIVATE_BUT_PRESENT_MODULES = [ + 'scipy.constants.codata', + 'scipy.constants.constants', + 'scipy.fftpack.basic', + 'scipy.fftpack.convolve', + 'scipy.fftpack.helper', + 'scipy.fftpack.pseudo_diffs', + 'scipy.fftpack.realtransforms', + 'scipy.integrate.dop', + 'scipy.integrate.odepack', + 'scipy.integrate.quadpack', + 'scipy.integrate.vode', + 'scipy.interpolate.dfitpack', + 'scipy.interpolate.fitpack', + 'scipy.interpolate.fitpack2', + 'scipy.interpolate.interpnd', + 'scipy.interpolate.interpolate', + 'scipy.interpolate.ndgriddata', + 'scipy.interpolate.polyint', + 'scipy.interpolate.rbf', + 'scipy.io.arff.arffread', + 'scipy.io.harwell_boeing', + 'scipy.io.idl', + 'scipy.io.matlab.byteordercodes', + 'scipy.io.matlab.mio', + 'scipy.io.matlab.mio4', + 'scipy.io.matlab.mio5', + 'scipy.io.matlab.mio5_params', + 'scipy.io.matlab.mio5_utils', + 'scipy.io.matlab.mio_utils', + 'scipy.io.matlab.miobase', + 'scipy.io.matlab.streams', + 'scipy.io.mmio', + 'scipy.io.netcdf', + 'scipy.linalg.basic', + 'scipy.linalg.decomp', + 'scipy.linalg.decomp_cholesky', + 'scipy.linalg.decomp_lu', + 'scipy.linalg.decomp_qr', + 'scipy.linalg.decomp_schur', + 'scipy.linalg.decomp_svd', + 'scipy.linalg.matfuncs', + 'scipy.linalg.misc', + 'scipy.linalg.special_matrices', + 'scipy.misc', + 'scipy.misc.common', + 'scipy.misc.doccer', + 'scipy.ndimage.filters', + 'scipy.ndimage.fourier', + 'scipy.ndimage.interpolation', + 'scipy.ndimage.measurements', + 'scipy.ndimage.morphology', + 'scipy.odr.models', + 'scipy.odr.odrpack', + 'scipy.optimize.cobyla', + 'scipy.optimize.cython_optimize', + 'scipy.optimize.lbfgsb', + 'scipy.optimize.linesearch', + 'scipy.optimize.minpack', + 'scipy.optimize.minpack2', + 'scipy.optimize.moduleTNC', + 'scipy.optimize.nonlin', + 'scipy.optimize.optimize', + 'scipy.optimize.slsqp', + 'scipy.optimize.tnc', + 'scipy.optimize.zeros', + 'scipy.signal.bsplines', + 'scipy.signal.filter_design', + 'scipy.signal.fir_filter_design', + 'scipy.signal.lti_conversion', + 'scipy.signal.ltisys', + 'scipy.signal.signaltools', + 'scipy.signal.spectral', + 'scipy.signal.spline', + 'scipy.signal.waveforms', + 'scipy.signal.wavelets', + 'scipy.signal.windows.windows', + 'scipy.sparse.base', + 'scipy.sparse.bsr', + 'scipy.sparse.compressed', + 'scipy.sparse.construct', + 'scipy.sparse.coo', + 'scipy.sparse.csc', + 'scipy.sparse.csr', + 'scipy.sparse.data', + 'scipy.sparse.dia', + 'scipy.sparse.dok', + 'scipy.sparse.extract', + 'scipy.sparse.lil', + 'scipy.sparse.linalg.dsolve', + 'scipy.sparse.linalg.eigen', + 'scipy.sparse.linalg.interface', + 'scipy.sparse.linalg.isolve', + 'scipy.sparse.linalg.matfuncs', + 'scipy.sparse.sparsetools', + 'scipy.sparse.spfuncs', + 'scipy.sparse.sputils', + 'scipy.spatial.ckdtree', + 'scipy.spatial.kdtree', + 'scipy.spatial.qhull', + 'scipy.spatial.transform.rotation', + 'scipy.special.add_newdocs', + 'scipy.special.basic', + 'scipy.special.cython_special', + 'scipy.special.orthogonal', + 'scipy.special.sf_error', + 'scipy.special.specfun', + 'scipy.special.spfun_stats', + 'scipy.stats.biasedurn', + 'scipy.stats.kde', + 'scipy.stats.morestats', + 'scipy.stats.mstats_basic', + 'scipy.stats.mstats_extras', + 'scipy.stats.mvn', + 'scipy.stats.stats', +] + + +def is_unexpected(name): + """Check if this needs to be considered.""" + if '._' in name or '.tests' in name or '.setup' in name: + return False + + if name in PUBLIC_MODULES: + return False + + if name in PRIVATE_BUT_PRESENT_MODULES: + return False + + return True + + +SKIP_LIST = [ + 'scipy.conftest', + 'scipy.version', + 'scipy.special.libsf_error_state', + 'scipy.integrate.lsoda' +] + + +# XXX: this test does more than it says on the tin - in using `pkgutil.walk_packages`, +# it will raise if it encounters any exceptions which are not handled by `ignore_errors` +# while attempting to import each discovered package. +# For now, `ignore_errors` only ignores what is necessary, but this could be expanded - +# for example, to all errors from private modules or git subpackages - if desired. +@pytest.mark.thread_unsafe( + reason=("crashes in pkgutil.walk_packages, see " + "https://github.com/data-apis/array-api-compat/issues/343")) +def test_all_modules_are_expected(): + """ + Test that we don't add anything that looks like a new public module by + accident. Check is based on filenames. + """ + + def ignore_errors(name): + # if versions of other array libraries are installed which are incompatible + # with the installed NumPy version, there can be errors on importing + # `array_api_compat`. This should only raise if SciPy is configured with + # that library as an available backend. + backends = {'cupy', 'torch', 'dask.array'} + for backend in backends: + path = f'array_api_compat.{backend}' + if path in name and backend not in xp_available_backends: + return + raise + + modnames = [] + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", "scipy.misc", DeprecationWarning) + for _, modname, _ in pkgutil.walk_packages(path=scipy.__path__, + prefix=scipy.__name__ + '.', + onerror=ignore_errors): + if is_unexpected(modname) and modname not in SKIP_LIST: + # We have a name that is new. If that's on purpose, add it to + # PUBLIC_MODULES. We don't expect to have to add anything to + # PRIVATE_BUT_PRESENT_MODULES. Use an underscore in the name! + modnames.append(modname) + + if modnames: + raise AssertionError(f'Found unexpected modules: {modnames}') + + +# Stuff that clearly shouldn't be in the API and is detected by the next test +# below +SKIP_LIST_2 = [ + 'scipy.char', + 'scipy.rec', + 'scipy.emath', + 'scipy.math', + 'scipy.random', + 'scipy.ctypeslib', + 'scipy.ma', + 'scipy.integrate.lsoda' +] + + +def test_all_modules_are_expected_2(): + """ + Method checking all objects. The pkgutil-based method in + `test_all_modules_are_expected` does not catch imports into a namespace, + only filenames. + """ + + def find_unexpected_members(mod_name): + members = [] + module = importlib.import_module(mod_name) + if hasattr(module, '__all__'): + objnames = module.__all__ + else: + objnames = dir(module) + + for objname in objnames: + if not objname.startswith('_'): + fullobjname = mod_name + '.' + objname + if isinstance(getattr(module, objname), types.ModuleType): + if is_unexpected(fullobjname) and fullobjname not in SKIP_LIST_2: + members.append(fullobjname) + + return members + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", "scipy.misc", DeprecationWarning) + unexpected_members = find_unexpected_members("scipy") + + for modname in PUBLIC_MODULES: + unexpected_members.extend(find_unexpected_members(modname)) + + if unexpected_members: + raise AssertionError("Found unexpected object(s) that look like " + f"modules: {unexpected_members}") + + +def test_api_importable(): + """ + Check that all submodules listed higher up in this file can be imported + Note that if a PRIVATE_BUT_PRESENT_MODULES entry goes missing, it may + simply need to be removed from the list (deprecation may or may not be + needed - apply common sense). + """ + def check_importable(module_name): + try: + importlib.import_module(module_name) + except (ImportError, AttributeError): + return False + + return True + + module_names = [] + for module_name in PUBLIC_MODULES: + if not check_importable(module_name): + module_names.append(module_name) + + if module_names: + raise AssertionError("Modules in the public API that cannot be " + f"imported: {module_names}") + + with warnings.catch_warnings(record=True): + warnings.simplefilter('always', category=DeprecationWarning) + warnings.simplefilter('always', category=ImportWarning) + for module_name in PRIVATE_BUT_PRESENT_MODULES: + if not check_importable(module_name): + module_names.append(module_name) + + if module_names: + raise AssertionError("Modules that are not really public but looked " + "public and can not be imported: " + f"{module_names}") + + +@pytest.mark.parametrize(("module_name", "correct_module"), + [('scipy.constants.codata', None), + ('scipy.constants.constants', None), + ('scipy.fftpack.basic', None), + ('scipy.fftpack.helper', None), + ('scipy.fftpack.pseudo_diffs', None), + ('scipy.fftpack.realtransforms', None), + ('scipy.integrate.dop', None), + ('scipy.integrate.odepack', None), + ('scipy.integrate.quadpack', None), + ('scipy.integrate.vode', None), + ('scipy.interpolate.dfitpack', None), + ('scipy.interpolate.fitpack', None), + ('scipy.interpolate.fitpack2', None), + ('scipy.interpolate.interpnd', None), + ('scipy.interpolate.interpolate', None), + ('scipy.interpolate.ndgriddata', None), + ('scipy.interpolate.polyint', None), + ('scipy.interpolate.rbf', None), + ('scipy.io.harwell_boeing', None), + ('scipy.io.idl', None), + ('scipy.io.mmio', None), + ('scipy.io.netcdf', None), + ('scipy.io.arff.arffread', 'arff'), + ('scipy.io.matlab.byteordercodes', 'matlab'), + ('scipy.io.matlab.mio_utils', 'matlab'), + ('scipy.io.matlab.mio', 'matlab'), + ('scipy.io.matlab.mio4', 'matlab'), + ('scipy.io.matlab.mio5_params', 'matlab'), + ('scipy.io.matlab.mio5_utils', 'matlab'), + ('scipy.io.matlab.mio5', 'matlab'), + ('scipy.io.matlab.miobase', 'matlab'), + ('scipy.io.matlab.streams', 'matlab'), + ('scipy.linalg.basic', None), + ('scipy.linalg.decomp', None), + ('scipy.linalg.decomp_cholesky', None), + ('scipy.linalg.decomp_lu', None), + ('scipy.linalg.decomp_qr', None), + ('scipy.linalg.decomp_schur', None), + ('scipy.linalg.decomp_svd', None), + ('scipy.linalg.matfuncs', None), + ('scipy.linalg.misc', None), + ('scipy.linalg.special_matrices', None), + ('scipy.ndimage.filters', None), + ('scipy.ndimage.fourier', None), + ('scipy.ndimage.interpolation', None), + ('scipy.ndimage.measurements', None), + ('scipy.ndimage.morphology', None), + ('scipy.optimize.cobyla', None), + ('scipy.optimize.lbfgsb', None), + ('scipy.optimize.linesearch', None), + ('scipy.optimize.minpack', None), + ('scipy.optimize.minpack2', None), + ('scipy.optimize.moduleTNC', None), + ('scipy.optimize.nonlin', None), + ('scipy.optimize.optimize', None), + ('scipy.optimize.slsqp', None), + ('scipy.optimize.tnc', None), + ('scipy.optimize.zeros', None), + ('scipy.signal.bsplines', None), + ('scipy.signal.filter_design', None), + ('scipy.signal.fir_filter_design', None), + ('scipy.signal.lti_conversion', None), + ('scipy.signal.ltisys', None), + ('scipy.signal.signaltools', None), + ('scipy.signal.spectral', None), + ('scipy.signal.spline', None), + ('scipy.signal.waveforms', None), + ('scipy.signal.wavelets', None), + ('scipy.signal.windows.windows', 'windows'), + ('scipy.sparse.base', None), + ('scipy.sparse.bsr', None), + ('scipy.sparse.compressed', None), + ('scipy.sparse.construct', None), + ('scipy.sparse.coo', None), + ('scipy.sparse.csc', None), + ('scipy.sparse.csr', None), + ('scipy.sparse.data', None), + ('scipy.sparse.dia', None), + ('scipy.sparse.dok', None), + ('scipy.sparse.extract', None), + ('scipy.sparse.lil', None), + ('scipy.sparse.linalg.dsolve', 'linalg'), + ('scipy.sparse.linalg.eigen', 'linalg'), + ('scipy.sparse.linalg.interface', 'linalg'), + ('scipy.sparse.linalg.isolve', 'linalg'), + ('scipy.sparse.linalg.matfuncs', 'linalg'), + ('scipy.sparse.sparsetools', None), + ('scipy.sparse.spfuncs', None), + ('scipy.sparse.sputils', None), + ('scipy.spatial.ckdtree', None), + ('scipy.spatial.kdtree', None), + ('scipy.spatial.qhull', None), + ('scipy.spatial.transform.rotation', 'transform'), + ('scipy.special.add_newdocs', None), + ('scipy.special.basic', None), + ('scipy.special.orthogonal', None), + ('scipy.special.sf_error', None), + ('scipy.special.specfun', None), + ('scipy.special.spfun_stats', None), + ('scipy.stats.biasedurn', None), + ('scipy.stats.kde', None), + ('scipy.stats.morestats', None), + ('scipy.stats.mstats_basic', 'mstats'), + ('scipy.stats.mstats_extras', 'mstats'), + ('scipy.stats.mvn', None), + ('scipy.stats.stats', None)]) +def test_private_but_present_deprecation(module_name, correct_module): + # gh-18279, gh-17572, gh-17771 noted that deprecation warnings + # for imports from private modules + # were misleading. Check that this is resolved. + module = import_module(module_name) + if correct_module is None: + import_name = f'scipy.{module_name.split(".")[1]}' + else: + import_name = f'scipy.{module_name.split(".")[1]}.{correct_module}' + + correct_import = import_module(import_name) + + # Attributes that were formerly in `module_name` can still be imported from + # `module_name`, albeit with a deprecation warning. + for attr_name in module.__all__: + # ensure attribute is present where the warning is pointing + assert getattr(correct_import, attr_name, None) is not None + message = f"Please import `{attr_name}` from the `{import_name}`..." + with pytest.deprecated_call(match=message): + getattr(module, attr_name) + + # Attributes that were not in `module_name` get an error notifying the user + # that the attribute is not in `module_name` and that `module_name` is deprecated. + message = f"`{module_name}` is deprecated..." + with pytest.raises(AttributeError, match=message): + getattr(module, "ekki") diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_scipy_version.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_scipy_version.py new file mode 100644 index 0000000000000000000000000000000000000000..68e1a43c3fb329b6a4274ba76b53a215738da6ad --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_scipy_version.py @@ -0,0 +1,28 @@ +import re + +import scipy +import scipy.version + + +def test_valid_scipy_version(): + # Verify that the SciPy version is a valid one (no .post suffix or other + # nonsense). See NumPy issue gh-6431 for an issue caused by an invalid + # version. + version_pattern = r"^[0-9]+\.[0-9]+\.[0-9]+(|a[0-9]|b[0-9]|rc[0-9])" + dev_suffix = r"((.dev0)|(\.dev0+\+git[0-9]{8}.[0-9a-f]{7}))" + if scipy.version.release: + res = re.match(version_pattern, scipy.__version__) + else: + res = re.match(version_pattern + dev_suffix, scipy.__version__) + + assert res is not None + assert scipy.__version__ + + +def test_version_submodule_members(): + """`scipy.version` may not be quite public, but we install it. + + So check that we don't silently change its contents. + """ + for attr in ('version', 'full_version', 'short_version', 'git_revision', 'release'): + assert hasattr(scipy.version, attr) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_tmpdirs.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_tmpdirs.py new file mode 100644 index 0000000000000000000000000000000000000000..3ee90319aa4c7b6d73c64f0f16eadc1ab070c7ec --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_tmpdirs.py @@ -0,0 +1,48 @@ +""" Test tmpdirs module """ +from os import getcwd +from os.path import realpath, abspath, dirname, isfile, join as pjoin, exists + +from scipy._lib._tmpdirs import tempdir, in_tempdir, in_dir + +from numpy.testing import assert_, assert_equal + +import pytest + + +MY_PATH = abspath(__file__) +MY_DIR = dirname(MY_PATH) + + +@pytest.mark.thread_unsafe(reason="tempdir is not thread-safe") +def test_tempdir(): + with tempdir() as tmpdir: + fname = pjoin(tmpdir, 'example_file.txt') + with open(fname, "w") as fobj: + fobj.write('a string\\n') + assert_(not exists(tmpdir)) + + +@pytest.mark.thread_unsafe(reason="in_tempdir is not thread-safe") +def test_in_tempdir(): + my_cwd = getcwd() + with in_tempdir() as tmpdir: + with open('test.txt', "w") as f: + f.write('some text') + assert_(isfile('test.txt')) + assert_(isfile(pjoin(tmpdir, 'test.txt'))) + assert_(not exists(tmpdir)) + assert_equal(getcwd(), my_cwd) + + +@pytest.mark.thread_unsafe(reason="in_dir is not thread-safe") +def test_given_directory(): + # Test InGivenDirectory + cwd = getcwd() + with in_dir() as tmpdir: + assert_equal(tmpdir, abspath(cwd)) + assert_equal(tmpdir, abspath(getcwd())) + with in_dir(MY_DIR) as tmpdir: + assert_equal(tmpdir, MY_DIR) + assert_equal(realpath(MY_DIR), realpath(abspath(getcwd()))) + # We were deleting the given directory! Check not so now. + assert_(isfile(MY_PATH)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_warnings.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_warnings.py new file mode 100644 index 0000000000000000000000000000000000000000..2dd96428fe4106da2e90b65718ad78752d28cd0c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/_lib/tests/test_warnings.py @@ -0,0 +1,137 @@ +""" +Tests which scan for certain occurrences in the code, they may not find +all of these occurrences but should catch almost all. This file was adapted +from NumPy. +""" + + +import os +from pathlib import Path +import ast +import tokenize + +import scipy + +import pytest + + +class ParseCall(ast.NodeVisitor): + def __init__(self): + self.ls = [] + + def visit_Attribute(self, node): + ast.NodeVisitor.generic_visit(self, node) + self.ls.append(node.attr) + + def visit_Name(self, node): + self.ls.append(node.id) + + +class FindFuncs(ast.NodeVisitor): + def __init__(self, filename): + super().__init__() + self.__filename = filename + self.bad_filters = [] + self.bad_stacklevels = [] + + def visit_Call(self, node): + p = ParseCall() + p.visit(node.func) + ast.NodeVisitor.generic_visit(self, node) + + if p.ls[-1] == 'simplefilter' or p.ls[-1] == 'filterwarnings': + # get first argument of the `args` node of the filter call + match node.args[0]: + case ast.Constant() as c: + argtext = c.value + case ast.JoinedStr() as js: + # if we get an f-string, discard the templated pieces, which + # are likely the type or specific message; we're interested + # in the action, which is less likely to use a template + argtext = "".join( + x.value for x in js.values if isinstance(x, ast.Constant) + ) + case _: + raise ValueError("unknown ast node type") + # check if filter is set to ignore outside of test code + if argtext == "ignore" and "tests" not in self.__filename.parts: + self.bad_filters.append( + f"{self.__filename}:{node.lineno}") + + if p.ls[-1] == 'warn' and ( + len(p.ls) == 1 or p.ls[-2] == 'warnings'): + + if self.__filename == "_lib/tests/test_warnings.py": + # This file + return + + # See if stacklevel exists: + if len(node.args) == 3: + return + args = {kw.arg for kw in node.keywords} + if "stacklevel" not in args: + self.bad_stacklevels.append( + f"{self.__filename}:{node.lineno}") + + +@pytest.fixture(scope="session") +def warning_calls(): + # combined "ignore" and stacklevel error + base = Path(scipy.__file__).parent + + bad_filters = [] + bad_stacklevels = [] + + for path in base.rglob("*.py"): + # use tokenize to auto-detect encoding on systems where no + # default encoding is defined (e.g., LANG='C') + with tokenize.open(str(path)) as file: + tree = ast.parse(file.read(), filename=str(path)) + finder = FindFuncs(path.relative_to(base)) + finder.visit(tree) + bad_filters.extend(finder.bad_filters) + bad_stacklevels.extend(finder.bad_stacklevels) + + return bad_filters, bad_stacklevels + + +@pytest.mark.fail_slow(40) +@pytest.mark.slow +def test_warning_calls_filters(warning_calls): + bad_filters, bad_stacklevels = warning_calls + + # We try not to add filters in the code base, because those filters aren't + # thread-safe. We aim to only filter in tests with + # warnings.catch_warnings. However, in some cases it may prove + # necessary to filter out warnings, because we can't (easily) fix the root + # cause for them and we don't want users to see some warnings when they use + # SciPy correctly. So we list exceptions here. Add new entries only if + # there's a good reason. + allowed_filters = ( + os.path.join('datasets', '_fetchers.py'), + os.path.join('datasets', '__init__.py'), + os.path.join('optimize', '_optimize.py'), + os.path.join('optimize', '_constraints.py'), + os.path.join('optimize', '_nnls.py'), + os.path.join('signal', '_ltisys.py'), + os.path.join('sparse', '__init__.py'), # np.matrix pending-deprecation + os.path.join('special', '_basic.py'), # gh-21801 + os.path.join('stats', '_discrete_distns.py'), # gh-14901 + os.path.join('stats', '_continuous_distns.py'), + os.path.join('stats', '_binned_statistic.py'), # gh-19345 + os.path.join('stats', '_stats_py.py'), # gh-20743 + os.path.join('stats', '_variation.py'), # gh-22827 + os.path.join('stats', 'tests', 'test_axis_nan_policy.py'), # gh-20694 + os.path.join('_lib', '_util.py'), # gh-19341 + os.path.join('sparse', 'linalg', '_dsolve', 'linsolve.py'), # gh-17924 + "conftest.py", + ) + bad_filters = [item for item in bad_filters if item.split(':')[0] not in + allowed_filters] + + if bad_filters: + raise AssertionError( + "Warning ignore filters should not be used outside of tests.\n" + "Found in:\n {}".format( + "\n ".join(bad_filters))) + diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3ace59bf2043e22d4b3889179f6d6627ab2a9d42 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/__pycache__/vq.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/__pycache__/vq.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..56af2c3324d277198ff224208aa9a8651751045d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/__pycache__/vq.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07f81c64982618e15c80facddc9b683e0787772e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__pycache__/hierarchy_test_data.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__pycache__/hierarchy_test_data.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ffa8fbecc310d5162d5ea13e75cc1d6a3802ccb6 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__pycache__/hierarchy_test_data.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__pycache__/test_disjoint_set.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__pycache__/test_disjoint_set.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eb8a1086e73b0642c3a3e68a6504032f7238695d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__pycache__/test_disjoint_set.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__pycache__/test_hierarchy.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__pycache__/test_hierarchy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86f85ea4b6c122f27c8bf4e2b3089f0e66fc478b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__pycache__/test_hierarchy.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__pycache__/test_vq.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__pycache__/test_vq.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7ed62e1ff82e1cba287ad1390ebd02af82e6d53b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/__pycache__/test_vq.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/hierarchy_test_data.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/hierarchy_test_data.py new file mode 100644 index 0000000000000000000000000000000000000000..7d874ca5eb7141a44559307d1c28dd412171396f --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/hierarchy_test_data.py @@ -0,0 +1,145 @@ +from numpy import array + + +Q_X = array([[5.26563660e-01, 3.14160190e-01, 8.00656370e-02], + [7.50205180e-01, 4.60299830e-01, 8.98696460e-01], + [6.65461230e-01, 6.94011420e-01, 9.10465700e-01], + [9.64047590e-01, 1.43082200e-03, 7.39874220e-01], + [1.08159060e-01, 5.53028790e-01, 6.63804780e-02], + [9.31359130e-01, 8.25424910e-01, 9.52315440e-01], + [6.78086960e-01, 3.41903970e-01, 5.61481950e-01], + [9.82730940e-01, 7.04605210e-01, 8.70978630e-02], + [6.14691610e-01, 4.69989230e-02, 6.02406450e-01], + [5.80161260e-01, 9.17354970e-01, 5.88163850e-01], + [1.38246310e+00, 1.96358160e+00, 1.94437880e+00], + [2.10675860e+00, 1.67148730e+00, 1.34854480e+00], + [1.39880070e+00, 1.66142050e+00, 1.32224550e+00], + [1.71410460e+00, 1.49176380e+00, 1.45432170e+00], + [1.54102340e+00, 1.84374950e+00, 1.64658950e+00], + [2.08512480e+00, 1.84524350e+00, 2.17340850e+00], + [1.30748740e+00, 1.53801650e+00, 2.16007740e+00], + [1.41447700e+00, 1.99329070e+00, 1.99107420e+00], + [1.61943490e+00, 1.47703280e+00, 1.89788160e+00], + [1.59880600e+00, 1.54988980e+00, 1.57563350e+00], + [3.37247380e+00, 2.69635310e+00, 3.39981700e+00], + [3.13705120e+00, 3.36528090e+00, 3.06089070e+00], + [3.29413250e+00, 3.19619500e+00, 2.90700170e+00], + [2.65510510e+00, 3.06785900e+00, 2.97198540e+00], + [3.30941040e+00, 2.59283970e+00, 2.57714110e+00], + [2.59557220e+00, 3.33477370e+00, 3.08793190e+00], + [2.58206180e+00, 3.41615670e+00, 3.26441990e+00], + [2.71127000e+00, 2.77032450e+00, 2.63466500e+00], + [2.79617850e+00, 3.25473720e+00, 3.41801560e+00], + [2.64741750e+00, 2.54538040e+00, 3.25354110e+00]]) + +ytdist = array([662., 877., 255., 412., 996., 295., 468., 268., 400., 754., + 564., 138., 219., 869., 669.]) + +linkage_ytdist_single = array([[2., 5., 138., 2.], + [3., 4., 219., 2.], + [0., 7., 255., 3.], + [1., 8., 268., 4.], + [6., 9., 295., 6.]]) + +linkage_ytdist_complete = array([[2., 5., 138., 2.], + [3., 4., 219., 2.], + [1., 6., 400., 3.], + [0., 7., 412., 3.], + [8., 9., 996., 6.]]) + +linkage_ytdist_average = array([[2., 5., 138., 2.], + [3., 4., 219., 2.], + [0., 7., 333.5, 3.], + [1., 6., 347.5, 3.], + [8., 9., 680.77777778, 6.]]) + +linkage_ytdist_weighted = array([[2., 5., 138., 2.], + [3., 4., 219., 2.], + [0., 7., 333.5, 3.], + [1., 6., 347.5, 3.], + [8., 9., 670.125, 6.]]) + +# the optimal leaf ordering of linkage_ytdist_single +linkage_ytdist_single_olo = array([[5., 2., 138., 2.], + [4., 3., 219., 2.], + [7., 0., 255., 3.], + [1., 8., 268., 4.], + [6., 9., 295., 6.]]) + +X = array([[1.43054825, -7.5693489], + [6.95887839, 6.82293382], + [2.87137846, -9.68248579], + [7.87974764, -6.05485803], + [8.24018364, -6.09495602], + [7.39020262, 8.54004355]]) + +linkage_X_centroid = array([[3., 4., 0.36265956, 2.], + [1., 5., 1.77045373, 2.], + [0., 2., 2.55760419, 2.], + [6., 8., 6.43614494, 4.], + [7., 9., 15.17363237, 6.]]) + +linkage_X_median = array([[3., 4., 0.36265956, 2.], + [1., 5., 1.77045373, 2.], + [0., 2., 2.55760419, 2.], + [6., 8., 6.43614494, 4.], + [7., 9., 15.17363237, 6.]]) + +linkage_X_ward = array([[3., 4., 0.36265956, 2.], + [1., 5., 1.77045373, 2.], + [0., 2., 2.55760419, 2.], + [6., 8., 9.10208346, 4.], + [7., 9., 24.7784379, 6.]]) + +# the optimal leaf ordering of linkage_X_ward +linkage_X_ward_olo = array([[4., 3., 0.36265956, 2.], + [5., 1., 1.77045373, 2.], + [2., 0., 2.55760419, 2.], + [6., 8., 9.10208346, 4.], + [7., 9., 24.7784379, 6.]]) + +inconsistent_ytdist = { + 1: array([[138., 0., 1., 0.], + [219., 0., 1., 0.], + [255., 0., 1., 0.], + [268., 0., 1., 0.], + [295., 0., 1., 0.]]), + 2: array([[138., 0., 1., 0.], + [219., 0., 1., 0.], + [237., 25.45584412, 2., 0.70710678], + [261.5, 9.19238816, 2., 0.70710678], + [233.66666667, 83.9424406, 3., 0.7306594]]), + 3: array([[138., 0., 1., 0.], + [219., 0., 1., 0.], + [237., 25.45584412, 2., 0.70710678], + [247.33333333, 25.38372182, 3., 0.81417007], + [239., 69.36377537, 4., 0.80733783]]), + 4: array([[138., 0., 1., 0.], + [219., 0., 1., 0.], + [237., 25.45584412, 2., 0.70710678], + [247.33333333, 25.38372182, 3., 0.81417007], + [235., 60.73302232, 5., 0.98793042]])} + +fcluster_inconsistent = { + 0.8: array([6, 2, 2, 4, 6, 2, 3, 7, 3, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1]), + 1.0: array([6, 2, 2, 4, 6, 2, 3, 7, 3, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1]), + 2.0: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1])} + +fcluster_distance = { + 0.6: array([4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 3, + 1, 1, 1, 2, 1, 1, 1, 1, 1]), + 1.0: array([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1]), + 2.0: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1])} + +fcluster_maxclust = { + 8.0: array([5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 7, 7, 7, 7, 7, 8, 7, 7, 7, 7, 4, + 1, 1, 1, 3, 1, 1, 1, 1, 2]), + 4.0: array([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1]), + 1.0: array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1])} diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/test_disjoint_set.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/test_disjoint_set.py new file mode 100644 index 0000000000000000000000000000000000000000..a73512d35eef168f625a1942a87d248e73a71aa2 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/test_disjoint_set.py @@ -0,0 +1,202 @@ +import pytest +from pytest import raises as assert_raises +import numpy as np +from scipy.cluster.hierarchy import DisjointSet +import string + + +def generate_random_token(): + k = len(string.ascii_letters) + tokens = list(np.arange(k, dtype=int)) + tokens += list(np.arange(k, dtype=float)) + tokens += list(string.ascii_letters) + tokens += [None for i in range(k)] + tokens = np.array(tokens, dtype=object) + rng = np.random.RandomState(seed=0) + + while 1: + size = rng.randint(1, 3) + element = rng.choice(tokens, size) + if size == 1: + yield element[0] + else: + yield tuple(element) + + +def get_elements(n): + # dict is deterministic without difficulty of comparing numpy ints + elements = {} + for element in generate_random_token(): + if element not in elements: + elements[element] = len(elements) + if len(elements) >= n: + break + return list(elements.keys()) + + +def test_init(): + n = 10 + elements = get_elements(n) + dis = DisjointSet(elements) + assert dis.n_subsets == n + assert list(dis) == elements + + +def test_len(): + n = 10 + elements = get_elements(n) + dis = DisjointSet(elements) + assert len(dis) == n + + dis.add("dummy") + assert len(dis) == n + 1 + + +@pytest.mark.parametrize("n", [10, 100]) +def test_contains(n): + elements = get_elements(n) + dis = DisjointSet(elements) + for x in elements: + assert x in dis + + assert "dummy" not in dis + + +@pytest.mark.parametrize("n", [10, 100]) +def test_add(n): + elements = get_elements(n) + dis1 = DisjointSet(elements) + + dis2 = DisjointSet() + for i, x in enumerate(elements): + dis2.add(x) + assert len(dis2) == i + 1 + + # test idempotency by adding element again + dis2.add(x) + assert len(dis2) == i + 1 + + assert list(dis1) == list(dis2) + + +def test_element_not_present(): + elements = get_elements(n=10) + dis = DisjointSet(elements) + + with assert_raises(KeyError): + dis["dummy"] + + with assert_raises(KeyError): + dis.merge(elements[0], "dummy") + + with assert_raises(KeyError): + dis.connected(elements[0], "dummy") + + +@pytest.mark.parametrize("direction", ["forwards", "backwards"]) +@pytest.mark.parametrize("n", [10, 100]) +def test_linear_union_sequence(n, direction): + elements = get_elements(n) + dis = DisjointSet(elements) + assert elements == list(dis) + + indices = list(range(n - 1)) + if direction == "backwards": + indices = indices[::-1] + + for it, i in enumerate(indices): + assert not dis.connected(elements[i], elements[i + 1]) + assert dis.merge(elements[i], elements[i + 1]) + assert dis.connected(elements[i], elements[i + 1]) + assert dis.n_subsets == n - 1 - it + + roots = [dis[i] for i in elements] + if direction == "forwards": + assert all(elements[0] == r for r in roots) + else: + assert all(elements[-2] == r for r in roots) + assert not dis.merge(elements[0], elements[-1]) + + +@pytest.mark.parametrize("n", [10, 100]) +def test_self_unions(n): + elements = get_elements(n) + dis = DisjointSet(elements) + + for x in elements: + assert dis.connected(x, x) + assert not dis.merge(x, x) + assert dis.connected(x, x) + assert dis.n_subsets == len(elements) + + assert elements == list(dis) + roots = [dis[x] for x in elements] + assert elements == roots + + +@pytest.mark.parametrize("order", ["ab", "ba"]) +@pytest.mark.parametrize("n", [10, 100]) +def test_equal_size_ordering(n, order): + elements = get_elements(n) + dis = DisjointSet(elements) + + rng = np.random.RandomState(seed=0) + indices = np.arange(n) + rng.shuffle(indices) + + for i in range(0, len(indices), 2): + a, b = elements[indices[i]], elements[indices[i + 1]] + if order == "ab": + assert dis.merge(a, b) + else: + assert dis.merge(b, a) + + expected = elements[min(indices[i], indices[i + 1])] + assert dis[a] == expected + assert dis[b] == expected + + +@pytest.mark.parametrize("kmax", [5, 10]) +def test_binary_tree(kmax): + n = 2**kmax + elements = get_elements(n) + dis = DisjointSet(elements) + rng = np.random.RandomState(seed=0) + + for k in 2**np.arange(kmax): + for i in range(0, n, 2 * k): + r1, r2 = rng.randint(0, k, size=2) + a, b = elements[i + r1], elements[i + k + r2] + assert not dis.connected(a, b) + assert dis.merge(a, b) + assert dis.connected(a, b) + + assert elements == list(dis) + roots = [dis[i] for i in elements] + expected_indices = np.arange(n) - np.arange(n) % (2 * k) + expected = [elements[i] for i in expected_indices] + assert roots == expected + + +@pytest.mark.parametrize("n", [10, 100]) +def test_subsets(n): + elements = get_elements(n) + dis = DisjointSet(elements) + + rng = np.random.RandomState(seed=0) + for i, j in rng.randint(0, n, (n, 2)): + x = elements[i] + y = elements[j] + + expected = {element for element in dis if {dis[element]} == {dis[x]}} + assert dis.subset_size(x) == len(dis.subset(x)) + assert expected == dis.subset(x) + + expected = {dis[element]: set() for element in dis} + for element in dis: + expected[dis[element]].add(element) + expected = list(expected.values()) + assert expected == dis.subsets() + + dis.merge(x, y) + assert dis.subset(x) == dis.subset(y) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/test_hierarchy.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/test_hierarchy.py new file mode 100644 index 0000000000000000000000000000000000000000..e634bb0d9ee2c889236df3e1e4ecb7b6009c449b --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/test_hierarchy.py @@ -0,0 +1,1237 @@ +# +# Author: Damian Eads +# Date: April 17, 2008 +# +# Copyright (C) 2008 Damian Eads +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# +# 3. The name of the author may not be used to endorse or promote +# products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import numpy as np +from numpy.testing import assert_allclose, assert_equal, assert_array_equal, assert_ +import pytest +from pytest import raises as assert_raises + +from scipy.cluster.hierarchy import ( + ClusterWarning, linkage, from_mlab_linkage, to_mlab_linkage, + num_obs_linkage, inconsistent, cophenet, fclusterdata, fcluster, + is_isomorphic, single, ward, leaders, + correspond, is_monotonic, maxdists, maxinconsts, maxRstat, + is_valid_linkage, is_valid_im, to_tree, leaves_list, dendrogram, + set_link_color_palette, cut_tree, optimal_leaf_ordering, + _order_cluster_tree, _hierarchy, _EUCLIDEAN_METHODS, _LINKAGE_METHODS) +from scipy.cluster._hierarchy import Heap +from scipy.spatial.distance import pdist +from scipy._lib._array_api import (eager_warns, make_xp_test_case, + xp_assert_close, xp_assert_equal) +import scipy._lib.array_api_extra as xpx + +from threading import Lock + +from . import hierarchy_test_data + +class eager: + # Bypass xpx.testing.lazy_xp_function when calling + # these functions from this namespace + is_valid_im = is_valid_im + is_valid_linkage = is_valid_linkage + + +# Matplotlib is not a scipy dependency but is optionally used in dendrogram, so +# check if it's available +try: + import matplotlib + # and set the backend to be Agg (no gui) + matplotlib.use('Agg') + # before importing pyplot + import matplotlib.pyplot as plt + have_matplotlib = True +except Exception: + have_matplotlib = False + +skip_xp_backends = pytest.mark.skip_xp_backends + + +@make_xp_test_case(linkage) +class TestLinkage: + + @skip_xp_backends("jax.numpy", reason="Can't raise inside jax.pure_callback") + def test_linkage_non_finite_elements_in_distance_matrix(self, xp): + # Tests linkage(Y) where Y contains a non-finite element (e.g. NaN or Inf). + # Exception expected. + y = xp.asarray([xp.nan] + [0.0]*5) + assert_raises(ValueError, linkage, y) + + def test_linkage_empty_distance_matrix(self, xp): + # Tests linkage(Y) where Y is a 0x4 linkage matrix. Exception expected. + y = xp.zeros((0,)) + assert_raises(ValueError, linkage, y) + + def test_linkage_tdist(self, xp): + for method in ['single', 'complete', 'average', 'weighted']: + self.check_linkage_tdist(method, xp) + + def check_linkage_tdist(self, method, xp): + # Tests linkage(Y, method) on the tdist data set. + Z = linkage(xp.asarray(hierarchy_test_data.ytdist), method) + expectedZ = getattr(hierarchy_test_data, 'linkage_ytdist_' + method) + xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-10) + + def test_linkage_X(self, xp): + for method in ['centroid', 'median', 'ward']: + self.check_linkage_q(method, xp) + + def check_linkage_q(self, method, xp): + # Tests linkage(Y, method) on the Q data set. + Z = linkage(xp.asarray(hierarchy_test_data.X), method) + expectedZ = getattr(hierarchy_test_data, 'linkage_X_' + method) + xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-06) + + X = xp.asarray(hierarchy_test_data.X) + y = pdist(X, metric="euclidean") + Z = linkage(y, method) + xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-06) + + def test_compare_with_trivial(self, xp): + rng = np.random.RandomState(0) + n = 20 + X = rng.rand(n, 2) + d = pdist(X) + + for method, code in _LINKAGE_METHODS.items(): + Z_trivial = _hierarchy.linkage(d, n, code) + Z = linkage(xp.asarray(d), method) + xp_assert_close(Z, xp.asarray(Z_trivial), rtol=1e-14, atol=1e-15) + + def test_optimal_leaf_ordering(self, xp): + Z = linkage(xp.asarray(hierarchy_test_data.ytdist), optimal_ordering=True) + expectedZ = getattr(hierarchy_test_data, 'linkage_ytdist_single_olo') + xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-10) + + @pytest.mark.parametrize("method,expect", [ + ('single', [[0, 1, 1.41421356, 2], + [2, 3, 1.41421356, 3]]), + ('complete', [[0, 1, 1.41421356, 2], + [2, 3, 2.82842712, 3]]), + ('average', [[0, 1, 1.41421356, 2], + [2, 3, 2.12132034, 3]]), + ('weighted', [[0, 1, 1.41421356, 2], + [2, 3, 2.12132034, 3]]), + ('centroid', [[0, 1, 1.41421356, 2], + [2, 3, 2.12132034, 3]]), + ('median', [[0, 1, 1.41421356, 2], + [2, 3, 2.12132034, 3]]), + ('ward', [[0, 1, 1.41421356, 2], + [2, 3, 2.44948974, 3]]), + ]) + def test_linkage_ties(self, method, expect, xp): + X = xp.asarray([[-1, -1], [0, 0], [1, 1]]) + Z = linkage(X, method=method) + expect = xp.asarray(expect, dtype=xp.float64) + xp_assert_close(Z, expect, atol=1e-06) + + def test_unsupported_uncondensed_distance_matrix_linkage_warning(self, xp): + X = xp.asarray([[0, 1], [1, 0]]) + with eager_warns(ClusterWarning, xp=xp): + linkage(X) + + @pytest.mark.parametrize("method", _EUCLIDEAN_METHODS) + def test_euclidean_linkage_value_error(self, method, xp): + X = xp.asarray([[1, 1], [1, 1]]) + with pytest.raises(ValueError): + linkage(X, method=method, metric='cityblock') + + def test_2x2_linkage(self, xp): + Z1 = linkage(xp.asarray([1]), method='single', metric='euclidean') + Z2 = linkage(xp.asarray([[0, 1], [0, 0]]), method='single', metric='euclidean') + xp_assert_close(Z1, Z2, rtol=1e-15) + + @skip_xp_backends("jax.numpy", reason="Can't raise inside jax.pure_callback") + def test_centroid_neg_distance(self, xp): + # gh-21011 + values = xp.asarray([0, 0, -1]) + with pytest.raises(ValueError): + # This is just checking that this doesn't crash + linkage(values, method='centroid') + + +@make_xp_test_case(inconsistent) +class TestInconsistent: + + def test_inconsistent_tdist(self, xp): + for depth in hierarchy_test_data.inconsistent_ytdist: + self.check_inconsistent_tdist(depth, xp) + + def check_inconsistent_tdist(self, depth, xp): + Z = xp.asarray(hierarchy_test_data.linkage_ytdist_single) + xp_assert_close(inconsistent(Z, depth), + xp.asarray(hierarchy_test_data.inconsistent_ytdist[depth])) + + +@make_xp_test_case(cophenet) +class TestCopheneticDistance: + + def test_linkage_cophenet_tdist_Z(self, xp): + # Tests cophenet(Z) on tdist data set. + expectedM = xp.asarray([268, 295, 255, 255, 295, 295, 268, 268, 295, 295, + 295, 138, 219, 295, 295]) + Z = xp.asarray(hierarchy_test_data.linkage_ytdist_single) + M = cophenet(Z) + xp_assert_close(M, xp.asarray(expectedM, dtype=xp.float64), atol=1e-10) + + def test_linkage_cophenet_tdist_Z_Y(self, xp): + # Tests cophenet(Z, Y) on tdist data set. + Z = xp.asarray(hierarchy_test_data.linkage_ytdist_single) + (c, M) = cophenet(Z, xp.asarray(hierarchy_test_data.ytdist)) + expectedM = xp.asarray([268, 295, 255, 255, 295, 295, 268, 268, 295, 295, + 295, 138, 219, 295, 295], dtype=xp.float64) + expectedc = xp.asarray(0.639931296433393415057366837573, dtype=xp.float64)[()] + xp_assert_close(c, expectedc, atol=1e-10) + xp_assert_close(M, expectedM, atol=1e-10) + + @skip_xp_backends("jax.numpy", reason="Can't raise inside jax.pure_callback") + def test_gh_22183(self, xp): + # check for lack of segfault + # (out of bounds memory access) + # and correct interception of + # invalid linkage matrix + arr=[[0.0, 1.0, 1.0, 2.0], + [2.0, 12.0, 1.0, 3.0], + [3.0, 4.0, 1.0, 2.0], + [5.0, 14.0, 1.0, 3.0], + [6.0, 7.0, 1.0, 2.0], + [8.0, 16.0, 1.0, 3.0], + [9.0, 10.0, 1.0, 2.0], + [11.0, 18.0, 1.0, 3.0], + [13.0, 15.0, 2.0, 6.0], + [17.0, 20.0, 2.0, 32.0], + [19.0, 21.0, 2.0, 12.0]] + with pytest.raises(ValueError, match="excessive observations"): + cophenet(xp.asarray(arr)) + + +@make_xp_test_case(from_mlab_linkage, to_mlab_linkage) +class TestMLabLinkageConversion: + + def test_mlab_linkage_conversion_empty(self, xp): + # Tests from/to_mlab_linkage on empty linkage array. + X = xp.asarray([], dtype=xp.float64) + xp_assert_equal(from_mlab_linkage(X), X) + xp_assert_equal(to_mlab_linkage(X), X) + + def test_mlab_linkage_conversion_single_row(self, xp): + # Tests from/to_mlab_linkage on linkage array with single row. + Z = xp.asarray([[0., 1., 3., 2.]]) + Zm = xp.asarray([[1, 2, 3]]) + xp_assert_close(from_mlab_linkage(Zm), xp.asarray(Z, dtype=xp.float64), + rtol=1e-15) + xp_assert_close(to_mlab_linkage(Z), xp.asarray(Zm, dtype=xp.float64), + rtol=1e-15) + + def test_mlab_linkage_conversion_multiple_rows(self, xp): + # Tests from/to_mlab_linkage on linkage array with multiple rows. + Zm = xp.asarray([[3, 6, 138], [4, 5, 219], + [1, 8, 255], [2, 9, 268], [7, 10, 295]]) + Z = xp.asarray([[2., 5., 138., 2.], + [3., 4., 219., 2.], + [0., 7., 255., 3.], + [1., 8., 268., 4.], + [6., 9., 295., 6.]], + dtype=xp.float64) + xp_assert_close(from_mlab_linkage(Zm), Z, rtol=1e-15) + xp_assert_close(to_mlab_linkage(Z), xp.asarray(Zm, dtype=xp.float64), + rtol=1e-15) + + +@make_xp_test_case(fclusterdata) +class TestFclusterData: + + @make_xp_test_case(is_isomorphic) + @pytest.mark.parametrize("criterion,t", + [("inconsistent", t) for t in hierarchy_test_data.fcluster_inconsistent] + + [("distance", t) for t in hierarchy_test_data.fcluster_distance] + + [("maxclust", t) for t in hierarchy_test_data.fcluster_maxclust] + ) + def test_fclusterdata(self, t, criterion, xp): + # Tests fclusterdata(X, criterion=criterion, t=t) on a random 3-cluster data set + expectedT = xp.asarray(getattr(hierarchy_test_data, 'fcluster_' + criterion)[t]) + X = xp.asarray(hierarchy_test_data.Q_X) + T = fclusterdata(X, criterion=criterion, t=t) + assert is_isomorphic(T, expectedT) + + +@make_xp_test_case(fcluster) +class TestFcluster: + + @make_xp_test_case(single, is_isomorphic) + @pytest.mark.parametrize("criterion,t", + [("inconsistent", t) for t in hierarchy_test_data.fcluster_inconsistent] + + [("distance", t) for t in hierarchy_test_data.fcluster_distance] + + [("maxclust", t) for t in hierarchy_test_data.fcluster_maxclust] + ) + def test_fcluster(self, t, criterion, xp): + # Tests fcluster(Z, criterion=criterion, t=t) on a random 3-cluster data set. + expectedT = xp.asarray(getattr(hierarchy_test_data, 'fcluster_' + criterion)[t]) + Z = single(xp.asarray(hierarchy_test_data.Q_X)) + T = fcluster(Z, criterion=criterion, t=t) + assert_(is_isomorphic(T, expectedT)) + + @make_xp_test_case(single, is_isomorphic, maxdists) + @pytest.mark.parametrize("t", hierarchy_test_data.fcluster_distance) + def test_fcluster_monocrit(self, t, xp): + expectedT = xp.asarray(hierarchy_test_data.fcluster_distance[t]) + Z = single(xp.asarray(hierarchy_test_data.Q_X)) + T = fcluster(Z, t, criterion='monocrit', monocrit=maxdists(Z)) + assert_(is_isomorphic(T, expectedT)) + + @make_xp_test_case(single, is_isomorphic, maxdists) + @pytest.mark.parametrize("t", hierarchy_test_data.fcluster_maxclust) + def test_fcluster_maxclust_monocrit(self, t, xp): + expectedT = xp.asarray(hierarchy_test_data.fcluster_maxclust[t]) + Z = single(xp.asarray(hierarchy_test_data.Q_X)) + T = fcluster(Z, t, criterion='maxclust_monocrit', monocrit=maxdists(Z)) + assert_(is_isomorphic(T, expectedT)) + + @make_xp_test_case(single) + def test_fcluster_maxclust_gh_12651(self, xp): + y = xp.asarray([[1], [4], [5]]) + Z = single(y) + assert_array_equal(fcluster(Z, t=1, criterion="maxclust"), + xp.asarray([1, 1, 1])) + assert_array_equal(fcluster(Z, t=2, criterion="maxclust"), + xp.asarray([2, 1, 1])) + assert_array_equal(fcluster(Z, t=3, criterion="maxclust"), + xp.asarray([1, 2, 3])) + assert_array_equal(fcluster(Z, t=5, criterion="maxclust"), + xp.asarray([1, 2, 3])) + + +@make_xp_test_case(leaders) +class TestLeaders: + + def test_leaders_single(self, xp): + # Tests leaders using a flat clustering generated by single linkage. + X = hierarchy_test_data.Q_X + Y = pdist(X) + Z = linkage(Y) + T = fcluster(Z, criterion='maxclust', t=3) + Z = xp.asarray(Z) + T = xp.asarray(T, dtype=xp.int32) + L = leaders(Z, T) + expect = xp.asarray([53, 55, 56, 2, 3, 1], dtype=xp.int32) + xp_assert_close(xp.concat(L), expect, rtol=1e-15) + + +@make_xp_test_case(is_isomorphic) +class TestIsIsomorphic: + + def test_array_like(self): + assert is_isomorphic([1, 1, 1], [2, 2, 2]) + assert is_isomorphic([], []) + + def test_is_isomorphic_1(self, xp): + # Tests is_isomorphic on test case #1 (one flat cluster, different labellings) + a = xp.asarray([1, 1, 1]) + b = xp.asarray([2, 2, 2]) + assert is_isomorphic(a, b) + assert is_isomorphic(b, a) + + def test_is_isomorphic_2(self, xp): + # Tests is_isomorphic on test case #2 (two flat clusters, different labelings) + a = xp.asarray([1, 7, 1]) + b = xp.asarray([2, 3, 2]) + assert is_isomorphic(a, b) + assert is_isomorphic(b, a) + + def test_is_isomorphic_3(self, xp): + # Tests is_isomorphic on test case #3 (no flat clusters) + a = xp.asarray([]) + b = xp.asarray([]) + assert is_isomorphic(a, b) + + def test_is_isomorphic_4A(self, xp): + # Tests is_isomorphic on test case #4A + # (3 flat clusters, different labelings, isomorphic) + a = xp.asarray([1, 2, 3]) + b = xp.asarray([1, 3, 2]) + assert is_isomorphic(a, b) + assert is_isomorphic(b, a) + + def test_is_isomorphic_4B(self, xp): + # Tests is_isomorphic on test case #4B + # (3 flat clusters, different labelings, nonisomorphic) + a = xp.asarray([1, 2, 3, 3]) + b = xp.asarray([1, 3, 2, 3]) + assert not is_isomorphic(a, b) + assert not is_isomorphic(b, a) + + def test_is_isomorphic_4C(self, xp): + # Tests is_isomorphic on test case #4C + # (3 flat clusters, different labelings, isomorphic) + a = xp.asarray([7, 2, 3]) + b = xp.asarray([6, 3, 2]) + assert is_isomorphic(a, b) + assert is_isomorphic(b, a) + + @pytest.mark.parametrize("nclusters", [2, 3, 5]) + def test_is_isomorphic_5(self, nclusters, xp): + # Tests is_isomorphic on test case #5 (1000 observations, 2/3/5 random + # clusters, random permutation of the labeling). + self.is_isomorphic_randperm(1000, nclusters, xp=xp) + + @pytest.mark.parametrize("nclusters", [2, 3, 5]) + def test_is_isomorphic_6(self, nclusters, xp): + # Tests is_isomorphic on test case #5A (1000 observations, 2/3/5 random + # clusters, random permutation of the labeling, slightly + # nonisomorphic.) + self.is_isomorphic_randperm(1000, nclusters, True, 5, xp=xp) + + def test_is_isomorphic_7(self, xp): + # Regression test for gh-6271 + a = xp.asarray([1, 2, 3]) + b = xp.asarray([1, 1, 1]) + assert not is_isomorphic(a, b) + + def is_isomorphic_randperm(self, nobs, nclusters, noniso=False, nerrors=0, *, xp): + rng = np.random.default_rng() + for _ in range(3): + a = rng.integers(0, nclusters, size=nobs) + p = rng.permutation(nclusters) + b = p.take(a.astype(np.intp)) + if noniso: + q = rng.permutation(nobs) + b[q[0:nerrors]] += 1 + b[q[0:nerrors]] %= nclusters + a = xp.asarray(a) + b = xp.asarray(b) + assert is_isomorphic(a, b) == (not noniso) + assert is_isomorphic(b, a) == (not noniso) + + +@make_xp_test_case(is_valid_linkage) +class TestIsValidLinkage: + + @pytest.mark.parametrize("nrow, ncol, valid", [(2, 5, False), (2, 3, False), + (1, 4, True), (2, 4, True)]) + def test_is_valid_linkage_various_size(self, nrow, ncol, valid, xp): + # Tests is_valid_linkage(Z) with linkage matrices of various sizes + Z = xp.asarray([[0, 1, 3.0, 2, 5], + [3, 2, 4.0, 3, 3]], dtype=xp.float64) + Z = Z[:nrow, :ncol] + xp_assert_equal(is_valid_linkage(Z), valid, check_namespace=False) + if not valid: + assert_raises(ValueError, is_valid_linkage, Z, throw=True) + + def test_is_valid_linkage_int_type(self, xp): + # Tests is_valid_linkage(Z) with integer type. + Z = xp.asarray([[0, 1, 3.0, 2], + [3, 2, 4.0, 3]], dtype=xp.int64) + xp_assert_equal(is_valid_linkage(Z), False, check_namespace=False) + assert_raises(TypeError, is_valid_linkage, Z, throw=True) + + def test_is_valid_linkage_empty(self, xp): + # Tests is_valid_linkage(Z) with empty linkage. + Z = xp.zeros((0, 4), dtype=xp.float64) + xp_assert_equal(is_valid_linkage(Z), False, check_namespace=False) + assert_raises(ValueError, is_valid_linkage, Z, throw=True) + + def test_is_valid_linkage_4_and_up(self, xp): + # Tests is_valid_linkage(Z) on linkage on observation sets between + # sizes 4 and 15 (step size 3). + for i in range(4, 15, 3): + y = np.random.rand(i*(i-1)//2) + Z = xp.asarray(linkage(y)) + y = xp.asarray(y) + xp_assert_equal(is_valid_linkage(Z), True, check_namespace=False) + + def test_is_valid_linkage_4_and_up_neg_index_left(self, xp): + # Tests is_valid_linkage(Z) on linkage on observation sets between + # sizes 4 and 15 (step size 3) with negative indices (left). + for i in range(4, 15, 3): + y = np.random.rand(i*(i-1)//2) + Z = xp.asarray(linkage(y)) + y = xp.asarray(y) + Z = xpx.at(Z)[i//2, 0].set(-2) + xp_assert_equal(is_valid_linkage(Z), False, check_namespace=False) + with pytest.raises(ValueError): + eager.is_valid_linkage(Z, throw=True) + + def test_is_valid_linkage_4_and_up_neg_index_right(self, xp): + # Tests is_valid_linkage(Z) on linkage on observation sets between + # sizes 4 and 15 (step size 3) with negative indices (right). + for i in range(4, 15, 3): + y = np.random.rand(i*(i-1)//2) + Z = xp.asarray(linkage(y)) + y = xp.asarray(y) + Z = xpx.at(Z)[i//2, 1].set(-2) + xp_assert_equal(is_valid_linkage(Z), False, check_namespace=False) + with pytest.raises(ValueError): + eager.is_valid_linkage(Z, throw=True) + + def test_is_valid_linkage_4_and_up_neg_dist(self, xp): + # Tests is_valid_linkage(Z) on linkage on observation sets between + # sizes 4 and 15 (step size 3) with negative distances. + for i in range(4, 15, 3): + y = np.random.rand(i*(i-1)//2) + Z = xp.asarray(linkage(y)) + y = xp.asarray(y) + Z = xpx.at(Z)[i//2, 2].set(-0.5) + xp_assert_equal(is_valid_linkage(Z), False, check_namespace=False) + with pytest.raises(ValueError): + eager.is_valid_linkage(Z, throw=True) + + def test_is_valid_linkage_4_and_up_neg_counts(self, xp): + # Tests is_valid_linkage(Z) on linkage on observation sets between + # sizes 4 and 15 (step size 3) with negative counts. + for i in range(4, 15, 3): + y = np.random.rand(i*(i-1)//2) + Z = xp.asarray(linkage(y)) + y = xp.asarray(y) + Z = xpx.at(Z)[i//2, 3].set(-2) + xp_assert_equal(is_valid_linkage(Z), False, check_namespace=False) + with pytest.raises(ValueError): + eager.is_valid_linkage(Z, throw=True) + + +@make_xp_test_case(is_valid_im) +class TestIsValidInconsistent: + + def test_is_valid_im_int_type(self, xp): + # Tests is_valid_im(R) with integer type. + R = xp.asarray([[0, 1, 3.0, 2], + [3, 2, 4.0, 3]], dtype=xp.int64) + xp_assert_equal(is_valid_im(R), False, check_namespace=False) + assert_raises(TypeError, is_valid_im, R, throw=True) + + @pytest.mark.parametrize("nrow, ncol, valid", [(2, 5, False), (2, 3, False), + (1, 4, True), (2, 4, True)]) + def test_is_valid_im_various_size(self, nrow, ncol, valid, xp): + # Tests is_valid_im(R) with linkage matrices of various sizes + R = xp.asarray([[0, 1, 3.0, 2, 5], + [3, 2, 4.0, 3, 3]], dtype=xp.float64) + R = R[:nrow, :ncol] + xp_assert_equal(is_valid_im(R), valid, check_namespace=False) + if not valid: + assert_raises(ValueError, is_valid_im, R, throw=True) + + def test_is_valid_im_empty(self, xp): + # Tests is_valid_im(R) with empty inconsistency matrix. + R = xp.zeros((0, 4), dtype=xp.float64) + xp_assert_equal(is_valid_im(R), False, check_namespace=False) + assert_raises(ValueError, is_valid_im, R, throw=True) + + def test_is_valid_im_4_and_up(self, xp): + # Tests is_valid_im(R) on im on observation sets between sizes 4 and 15 + # (step size 3). + for i in range(4, 15, 3): + y = np.random.rand(i*(i-1)//2) + Z = linkage(y) + R = inconsistent(Z) + R = xp.asarray(R) + xp_assert_equal(is_valid_im(R), True, check_namespace=False) + + def test_is_valid_im_4_and_up_neg_index_left(self, xp): + # Tests is_valid_im(R) on im on observation sets between sizes 4 and 15 + # (step size 3) with negative link height means. + for i in range(4, 15, 3): + y = np.random.rand(i*(i-1)//2) + Z = linkage(y) + R = inconsistent(Z) + R = xpx.at(R)[i//2 , 0].set(-2.0) + R = xp.asarray(R) + xp_assert_equal(is_valid_im(R), False, check_namespace=False) + with pytest.raises(ValueError): + eager.is_valid_im(R, throw=True) + + def test_is_valid_im_4_and_up_neg_index_right(self, xp): + # Tests is_valid_im(R) on im on observation sets between sizes 4 and 15 + # (step size 3) with negative link height standard deviations. + for i in range(4, 15, 3): + y = np.random.rand(i*(i-1)//2) + Z = linkage(y) + R = inconsistent(Z) + R = xpx.at(R)[i//2 , 1].set(-2.0) + R = xp.asarray(R) + xp_assert_equal(is_valid_im(R), False, check_namespace=False) + with pytest.raises(ValueError): + eager.is_valid_im(R, throw=True) + + def test_is_valid_im_4_and_up_neg_dist(self, xp): + # Tests is_valid_im(R) on im on observation sets between sizes 4 and 15 + # (step size 3) with negative link counts. + for i in range(4, 15, 3): + y = np.random.rand(i*(i-1)//2) + Z = linkage(y) + R = inconsistent(Z) + R = xpx.at(R)[i//2, 2].set(-0.5) + R = xp.asarray(R) + xp_assert_equal(is_valid_im(R), False, check_namespace=False) + with pytest.raises(ValueError): + eager.is_valid_im(R, throw=True) + + +class TestNumObsLinkage: + + def test_num_obs_linkage_empty(self, xp): + # Tests num_obs_linkage(Z) with empty linkage. + Z = xp.zeros((0, 4), dtype=xp.float64) + assert_raises(ValueError, num_obs_linkage, Z) + + def test_num_obs_linkage_1x4(self, xp): + # Tests num_obs_linkage(Z) on linkage over 2 observations. + Z = xp.asarray([[0, 1, 3.0, 2]], dtype=xp.float64) + assert num_obs_linkage(Z) == 2 + + def test_num_obs_linkage_2x4(self, xp): + # Tests num_obs_linkage(Z) on linkage over 3 observations. + Z = xp.asarray([[0, 1, 3.0, 2], + [3, 2, 4.0, 3]], dtype=xp.float64) + assert num_obs_linkage(Z) == 3 + + def test_num_obs_linkage_4_and_up(self, xp): + # Tests num_obs_linkage(Z) on linkage on observation sets between sizes + # 4 and 15 (step size 3). + for i in range(4, 15, 3): + y = np.random.rand(i*(i-1)//2) + Z = xp.asarray(linkage(y)) + assert num_obs_linkage(Z) == i + + def test_num_obs_linkage_multi_matrix(self, xp): + # Tests num_obs_linkage with observation matrices of multiple sizes. + for n in range(2, 10): + X = np.random.rand(n, 4) + Y = pdist(X) + Z = xp.asarray(linkage(Y)) + assert num_obs_linkage(Z) == n + + +@make_xp_test_case(leaves_list, to_tree) +class TestLeavesList: + + def test_leaves_list_1x4(self, xp): + # Tests leaves_list(Z) on a 1x4 linkage. + Z = xp.asarray([[0, 1, 3.0, 2]], dtype=xp.float64) + to_tree(Z) + assert_allclose(leaves_list(Z), [0, 1], rtol=1e-15) + + def test_leaves_list_2x4(self, xp): + # Tests leaves_list(Z) on a 2x4 linkage. + Z = xp.asarray([[0, 1, 3.0, 2], + [3, 2, 4.0, 3]], dtype=xp.float64) + to_tree(Z) + assert_allclose(leaves_list(Z), [0, 1, 2], rtol=1e-15) + + @pytest.mark.parametrize("method", + ['single', 'complete', 'average', 'weighted', 'centroid', 'median', 'ward']) + def test_leaves_list_Q(self, method, xp): + # Tests leaves_list(Z) on the Q data set + X = hierarchy_test_data.Q_X + Z = xp.asarray(linkage(X, method)) + node = to_tree(Z) + assert_allclose(node.pre_order(), leaves_list(Z), rtol=1e-15) + + def test_Q_subtree_pre_order(self, xp): + # Tests that pre_order() works when called on sub-trees. + X = hierarchy_test_data.Q_X + Z = xp.asarray(linkage(X, 'single')) + node = to_tree(Z) + assert_allclose(node.pre_order(), + (node.get_left().pre_order() + node.get_right().pre_order()), + rtol=1e-15) + + +@make_xp_test_case(correspond) +class TestCorrespond: + + def test_correspond_empty(self, xp): + # Tests correspond(Z, y) with empty linkage and condensed distance matrix. + y = xp.zeros((0,), dtype=xp.float64) + Z = xp.zeros((0,4), dtype=xp.float64) + assert_raises(ValueError, correspond, Z, y) + + def test_correspond_2_and_up(self, xp): + # Tests correspond(Z, y) on linkage and CDMs over observation sets of + # different sizes. + for i in range(2, 4): + y = np.random.rand(i*(i-1)//2) + Z = xp.asarray(linkage(y)) + y = xp.asarray(y) + assert_(correspond(Z, y)) + for i in range(4, 15, 3): + y = np.random.rand(i*(i-1)//2) + Z = xp.asarray(linkage(y)) + y = xp.asarray(y) + assert_(correspond(Z, y)) + + def test_correspond_4_and_up(self, xp): + # Tests correspond(Z, y) on linkage and CDMs over observation sets of + # different sizes. Correspondence should be false. + for (i, j) in (list(zip(list(range(2, 4)), list(range(3, 5)))) + + list(zip(list(range(3, 5)), list(range(2, 4))))): + y = np.random.rand(i*(i-1)//2) + y2 = np.random.rand(j*(j-1)//2) + Z = xp.asarray(linkage(y)) + Z2 = xp.asarray(linkage(y2)) + y = xp.asarray(y) + y2 = xp.asarray(y2) + assert not correspond(Z, y2) + assert not correspond(Z2, y) + + def test_correspond_4_and_up_2(self, xp): + # Tests correspond(Z, y) on linkage and CDMs over observation sets of + # different sizes. Correspondence should be false. + for (i, j) in (list(zip(list(range(2, 7)), list(range(16, 21)))) + + list(zip(list(range(2, 7)), list(range(16, 21))))): + y = np.random.rand(i*(i-1)//2) + y2 = np.random.rand(j*(j-1)//2) + Z = xp.asarray(linkage(y)) + Z2 = xp.asarray(linkage(y2)) + y = xp.asarray(y) + y2 = xp.asarray(y2) + assert not correspond(Z, y2) + assert not correspond(Z2, y) + + +@make_xp_test_case(is_monotonic) +class TestIsMonotonic: + + def test_is_monotonic_empty(self, xp): + # Tests is_monotonic(Z) on an empty linkage. + Z = xp.zeros((0, 4), dtype=xp.float64) + assert_raises(ValueError, is_monotonic, Z) + + def test_is_monotonic_1x4(self, xp): + # Tests is_monotonic(Z) on 1x4 linkage. Expecting True. + Z = xp.asarray([[0, 1, 0.3, 2]], dtype=xp.float64) + assert is_monotonic(Z) + + def test_is_monotonic_2x4_T(self, xp): + # Tests is_monotonic(Z) on 2x4 linkage. Expecting True. + Z = xp.asarray([[0, 1, 0.3, 2], + [2, 3, 0.4, 3]], dtype=xp.float64) + assert is_monotonic(Z) + + def test_is_monotonic_2x4_F(self, xp): + # Tests is_monotonic(Z) on 2x4 linkage. Expecting False. + Z = xp.asarray([[0, 1, 0.4, 2], + [2, 3, 0.3, 3]], dtype=xp.float64) + assert not is_monotonic(Z) + + def test_is_monotonic_3x4_T(self, xp): + # Tests is_monotonic(Z) on 3x4 linkage. Expecting True. + Z = xp.asarray([[0, 1, 0.3, 2], + [2, 3, 0.4, 2], + [4, 5, 0.6, 4]], dtype=xp.float64) + assert is_monotonic(Z) + + def test_is_monotonic_3x4_F1(self, xp): + # Tests is_monotonic(Z) on 3x4 linkage (case 1). Expecting False. + Z = xp.asarray([[0, 1, 0.3, 2], + [2, 3, 0.2, 2], + [4, 5, 0.6, 4]], dtype=xp.float64) + assert not is_monotonic(Z) + + def test_is_monotonic_3x4_F2(self, xp): + # Tests is_monotonic(Z) on 3x4 linkage (case 2). Expecting False. + Z = xp.asarray([[0, 1, 0.8, 2], + [2, 3, 0.4, 2], + [4, 5, 0.6, 4]], dtype=xp.float64) + assert not is_monotonic(Z) + + def test_is_monotonic_3x4_F3(self, xp): + # Tests is_monotonic(Z) on 3x4 linkage (case 3). Expecting False + Z = xp.asarray([[0, 1, 0.3, 2], + [2, 3, 0.4, 2], + [4, 5, 0.2, 4]], dtype=xp.float64) + assert not is_monotonic(Z) + + def test_is_monotonic_tdist_linkage1(self, xp): + # Tests is_monotonic(Z) on clustering generated by single linkage on + # tdist data set. Expecting True. + Z = xp.asarray(linkage(hierarchy_test_data.ytdist, 'single')) + assert is_monotonic(Z) + + def test_is_monotonic_tdist_linkage2(self, xp): + # Tests is_monotonic(Z) on clustering generated by single linkage on + # tdist data set. Perturbing. Expecting False. + Z = xp.asarray(linkage(hierarchy_test_data.ytdist, 'single')) + Z = xpx.at(Z)[2, 2].set(0.0) + assert not is_monotonic(Z) + + def test_is_monotonic_Q_linkage(self, xp): + # Tests is_monotonic(Z) on clustering generated by single linkage on + # Q data set. Expecting True. + X = hierarchy_test_data.Q_X + Z = xp.asarray(linkage(X, 'single')) + assert is_monotonic(Z) + + +@make_xp_test_case(maxdists) +class TestMaxDists: + + def test_maxdists_empty_linkage(self, xp): + # Tests maxdists(Z) on empty linkage. Expecting exception. + Z = xp.zeros((0, 4), dtype=xp.float64) + assert_raises(ValueError, maxdists, Z) + + def test_maxdists_one_cluster_linkage(self, xp): + # Tests maxdists(Z) on linkage with one cluster. + Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64) + MD = maxdists(Z) + expectedMD = calculate_maximum_distances(Z, xp) + xp_assert_close(MD, expectedMD, atol=1e-15) + + @pytest.mark.parametrize( + "method", ['single', 'complete', 'ward', 'centroid', 'median']) + def test_maxdists_Q_linkage(self, method, xp): + # Tests maxdists(Z) on the Q data set + X = hierarchy_test_data.Q_X + Z = xp.asarray(linkage(X, method)) + MD = maxdists(Z) + expectedMD = calculate_maximum_distances(Z, xp) + xp_assert_close(MD, expectedMD, atol=1e-15) + + +@make_xp_test_case(maxinconsts) +class TestMaxInconsts: + + def test_maxinconsts_empty_linkage(self, xp): + # Tests maxinconsts(Z, R) on empty linkage. Expecting exception. + Z = xp.zeros((0, 4), dtype=xp.float64) + R = xp.zeros((0, 4), dtype=xp.float64) + assert_raises(ValueError, maxinconsts, Z, R) + + def test_maxinconsts_difrow_linkage(self, xp): + # Tests maxinconsts(Z, R) on linkage and inconsistency matrices with + # different numbers of clusters. Expecting exception. + Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64) + R = np.random.rand(2, 4) + R = xp.asarray(R) + assert_raises(ValueError, maxinconsts, Z, R) + + def test_maxinconsts_one_cluster_linkage(self, xp): + # Tests maxinconsts(Z, R) on linkage with one cluster. + Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64) + R = xp.asarray([[0, 0, 0, 0.3]], dtype=xp.float64) + MD = maxinconsts(Z, R) + expectedMD = calculate_maximum_inconsistencies(Z, R, xp=xp) + xp_assert_close(MD, expectedMD, atol=1e-15) + + @pytest.mark.parametrize( + "method", ['single', 'complete', 'ward', 'centroid', 'median']) + def test_maxinconsts_Q_linkage(self, method, xp): + # Tests maxinconsts(Z, R) on the Q data set + X = hierarchy_test_data.Q_X + Z = linkage(X, method) + R = xp.asarray(inconsistent(Z)) + Z = xp.asarray(Z) + MD = maxinconsts(Z, R) + expectedMD = calculate_maximum_inconsistencies(Z, R, xp=xp) + xp_assert_close(MD, expectedMD, atol=1e-15) + + +@make_xp_test_case(maxRstat) +class TestMaxRStat: + + def test_maxRstat_invalid_index(self, xp): + # Tests maxRstat(Z, R, i). Expecting exception. + Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64) + R = xp.asarray([[0, 0, 0, 0.3]], dtype=xp.float64) + with pytest.raises(TypeError): + maxRstat(Z, R, 3.3) + with pytest.raises(ValueError): + maxRstat(Z, R, -1) + with pytest.raises(ValueError): + maxRstat(Z, R, 4) + + @pytest.mark.parametrize("i", range(4)) + def test_maxRstat_empty_linkage(self, i, xp): + # Tests maxRstat(Z, R, i) on empty linkage. Expecting exception. + Z = xp.zeros((0, 4), dtype=xp.float64) + R = xp.zeros((0, 4), dtype=xp.float64) + assert_raises(ValueError, maxRstat, Z, R, i) + + @pytest.mark.parametrize("i", range(4)) + def test_maxRstat_difrow_linkage(self, i, xp): + # Tests maxRstat(Z, R, i) on linkage and inconsistency matrices with + # different numbers of clusters. Expecting exception. + Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64) + R = np.random.rand(2, 4) + R = xp.asarray(R) + assert_raises(ValueError, maxRstat, Z, R, i) + + def test_maxRstat_one_cluster_linkage(self, xp): + # Tests maxRstat(Z, R, i) on linkage with one cluster. + Z = xp.asarray([[0, 1, 0.3, 4]], dtype=xp.float64) + R = xp.asarray([[0, 0, 0, 0.3]], dtype=xp.float64) + MD = maxRstat(Z, R, 1) + expectedMD = calculate_maximum_inconsistencies(Z, R, 1, xp) + xp_assert_close(MD, expectedMD, atol=1e-15) + + @pytest.mark.parametrize( + "method", ['single', 'complete', 'ward', 'centroid', 'median']) + def test_maxRstat_Q_linkage(self, method, xp): + # Tests maxRstat(Z, R, 1) on the Q data set + X = hierarchy_test_data.Q_X + Z = linkage(X, method) + R = xp.asarray(inconsistent(Z)) + Z = xp.asarray(Z) + MD = maxRstat(Z, R, 1) + expectedMD = calculate_maximum_inconsistencies(Z, R, 1, xp) + xp_assert_close(MD, expectedMD, atol=1e-15) + + +@make_xp_test_case(dendrogram) +class TestDendrogram: + + def test_dendrogram_single_linkage_tdist(self, xp): + # Tests dendrogram calculation on single linkage of the tdist data set. + Z = xp.asarray(linkage(hierarchy_test_data.ytdist, 'single')) + R = dendrogram(Z, no_plot=True) + leaves = R["leaves"] + assert_equal(leaves, [2, 5, 1, 0, 3, 4]) + + def test_valid_orientation(self, xp): + Z = xp.asarray(linkage(hierarchy_test_data.ytdist, 'single')) + assert_raises(ValueError, dendrogram, Z, orientation="foo") + + def test_labels_as_array_or_list(self, xp): + # test for gh-12418 + Z = xp.asarray(linkage(hierarchy_test_data.ytdist, 'single')) + labels = [1, 3, 2, 6, 4, 5] + result1 = dendrogram(Z, labels=xp.asarray(labels), no_plot=True) + result2 = dendrogram(Z, labels=labels, no_plot=True) + assert result1 == result2 + + @pytest.mark.skipif(not have_matplotlib, reason="no matplotlib") + def test_valid_label_size(self, xp): + link = xp.asarray([ + [0, 1, 1.0, 4], + [2, 3, 1.0, 5], + [4, 5, 2.0, 6], + ]) + plt.figure() + with pytest.raises(ValueError) as exc_info: + dendrogram(link, labels=list(range(100))) + assert "Dimensions of Z and labels must be consistent."\ + in str(exc_info.value) + + with pytest.raises( + ValueError, + match="Dimensions of Z and labels must be consistent."): + dendrogram(link, labels=[]) + + plt.close() + + @skip_xp_backends('torch', + reason='MPL 3.9.2 & torch DeprecationWarning from __array_wrap__' + ' and NumPy 2.0' + ) + @skip_xp_backends('dask.array', + reason='dask.array has bad interaction with matplotlib' + ) + @pytest.mark.skipif(not have_matplotlib, reason="no matplotlib") + @pytest.mark.parametrize("orientation", ['top', 'bottom', 'left', 'right']) + def test_dendrogram_plot(self, orientation, xp): + # Tests dendrogram plotting. + Z = xp.asarray(linkage(hierarchy_test_data.ytdist, 'single')) + expected = {'color_list': ['C1', 'C0', 'C0', 'C0', 'C0'], + 'dcoord': [[0.0, 138.0, 138.0, 0.0], + [0.0, 219.0, 219.0, 0.0], + [0.0, 255.0, 255.0, 219.0], + [0.0, 268.0, 268.0, 255.0], + [138.0, 295.0, 295.0, 268.0]], + 'icoord': [[5.0, 5.0, 15.0, 15.0], + [45.0, 45.0, 55.0, 55.0], + [35.0, 35.0, 50.0, 50.0], + [25.0, 25.0, 42.5, 42.5], + [10.0, 10.0, 33.75, 33.75]], + 'ivl': ['2', '5', '1', '0', '3', '4'], + 'leaves': [2, 5, 1, 0, 3, 4], + 'leaves_color_list': ['C1', 'C1', 'C0', 'C0', 'C0', 'C0'], + } + + fig = plt.figure() + ax = fig.add_subplot(221) + + # test that dendrogram accepts ax keyword + R1 = dendrogram(Z, ax=ax, orientation=orientation) + R1['dcoord'] = np.asarray(R1['dcoord']) + assert_equal(R1, expected) + + # test that dendrogram accepts and handle the leaf_font_size and + # leaf_rotation keywords + dendrogram(Z, ax=ax, orientation=orientation, + leaf_font_size=20, leaf_rotation=90) + testlabel = ( + ax.get_xticklabels()[0] + if orientation in ['top', 'bottom'] + else ax.get_yticklabels()[0] + ) + assert_equal(testlabel.get_rotation(), 90) + assert_equal(testlabel.get_size(), 20) + dendrogram(Z, ax=ax, orientation=orientation, + leaf_rotation=90) + testlabel = ( + ax.get_xticklabels()[0] + if orientation in ['top', 'bottom'] + else ax.get_yticklabels()[0] + ) + assert_equal(testlabel.get_rotation(), 90) + dendrogram(Z, ax=ax, orientation=orientation, + leaf_font_size=20) + testlabel = ( + ax.get_xticklabels()[0] + if orientation in ['top', 'bottom'] + else ax.get_yticklabels()[0] + ) + assert_equal(testlabel.get_size(), 20) + plt.close() + + # test plotting to gca (will import pylab) + R2 = dendrogram(Z, orientation=orientation) + plt.close() + R2['dcoord'] = np.asarray(R2['dcoord']) + assert_equal(R2, expected) + + @skip_xp_backends('torch', + reason='MPL 3.9.2 & torch DeprecationWarning from __array_wrap__' + ' and NumPy 2.0' + ) + @skip_xp_backends('dask.array', + reason='dask.array has bad interaction with matplotlib' + ) + @pytest.mark.skipif(not have_matplotlib, reason="no matplotlib") + def test_dendrogram_truncate_mode(self, xp): + Z = xp.asarray(linkage(hierarchy_test_data.ytdist, 'single')) + + R = dendrogram(Z, 2, 'lastp', show_contracted=True) + plt.close() + R['dcoord'] = np.asarray(R['dcoord']) + assert_equal(R, {'color_list': ['C0'], + 'dcoord': [[0.0, 295.0, 295.0, 0.0]], + 'icoord': [[5.0, 5.0, 15.0, 15.0]], + 'ivl': ['(2)', '(4)'], + 'leaves': [6, 9], + 'leaves_color_list': ['C0', 'C0'], + }) + + R = dendrogram(Z, 2, 'mtica', show_contracted=True) + plt.close() + R['dcoord'] = np.asarray(R['dcoord']) + assert_equal(R, {'color_list': ['C1', 'C0', 'C0', 'C0'], + 'dcoord': [[0.0, 138.0, 138.0, 0.0], + [0.0, 255.0, 255.0, 0.0], + [0.0, 268.0, 268.0, 255.0], + [138.0, 295.0, 295.0, 268.0]], + 'icoord': [[5.0, 5.0, 15.0, 15.0], + [35.0, 35.0, 45.0, 45.0], + [25.0, 25.0, 40.0, 40.0], + [10.0, 10.0, 32.5, 32.5]], + 'ivl': ['2', '5', '1', '0', '(2)'], + 'leaves': [2, 5, 1, 0, 7], + 'leaves_color_list': ['C1', 'C1', 'C0', 'C0', 'C0'], + }) + + @pytest.fixture + def dendrogram_lock(self): + return Lock() + + def test_dendrogram_colors(self, xp, dendrogram_lock): + # Tests dendrogram plots with alternate colors + Z = xp.asarray(linkage(hierarchy_test_data.ytdist, 'single')) + + with dendrogram_lock: + # Global color palette might be changed concurrently + set_link_color_palette(['c', 'm', 'y', 'k']) + R = dendrogram(Z, no_plot=True, + above_threshold_color='g', color_threshold=250) + set_link_color_palette(['g', 'r', 'c', 'm', 'y', 'k']) + + color_list = R['color_list'] + assert_equal(color_list, ['c', 'm', 'g', 'g', 'g']) + + # reset color palette (global list) + set_link_color_palette(None) + + def test_dendrogram_leaf_colors_zero_dist(self, xp): + # tests that the colors of leafs are correct for tree + # with two identical points + X = np.asarray([[1, 0, 0], + [0, 0, 1], + [0, 2, 0], + [0, 0, 1], + [0, 1, 0], + [0, 1, 0]]) + Z = xp.asarray(linkage(X, "single")) + d = dendrogram(Z, no_plot=True) + exp_colors = ['C0', 'C1', 'C1', 'C0', 'C2', 'C2'] + colors = d["leaves_color_list"] + assert_equal(colors, exp_colors) + + def test_dendrogram_leaf_colors(self, xp): + # tests that the colors are correct for a tree + # with two near points ((0, 0, 1.1) and (0, 0, 1)) + X = np.asarray([[1, 0, 0], + [0, 0, 1.1], + [0, 2, 0], + [0, 0, 1], + [0, 1, 0], + [0, 1, 0]]) + Z = xp.asarray(linkage(X, "single")) + d = dendrogram(Z, no_plot=True) + exp_colors = ['C0', 'C1', 'C1', 'C0', 'C2', 'C2'] + colors = d["leaves_color_list"] + assert_equal(colors, exp_colors) + + +def calculate_maximum_distances(Z, xp): + # Used for testing correctness of maxdists. + n = Z.shape[0] + 1 + B = xp.zeros((n-1,), dtype=Z.dtype) + for i in range(0, n - 1): + q = xp.zeros((3,)) + left = Z[i, 0] + right = Z[i, 1] + if left >= n: + b_left = B[xp.asarray(left, dtype=xp.int64) - n] + q = xpx.at(q, 0).set(b_left) + if right >= n: + b_right = B[xp.asarray(right, dtype=xp.int64) - n] + q = xpx.at(q, 1).set(b_right) + q = xpx.at(q, 2).set(Z[i, 2]) + B = xpx.at(B, i).set(xp.max(q)) + return B + + +def calculate_maximum_inconsistencies(Z, R, k=3, xp=np): + # Used for testing correctness of maxinconsts. + n = Z.shape[0] + 1 + dtype = xp.result_type(Z, R) + B = xp.zeros((n-1,), dtype=dtype) + for i in range(0, n - 1): + q = xp.zeros((3,)) + left = Z[i, 0] + right = Z[i, 1] + if left >= n: + b_left = B[xp.asarray(left, dtype=xp.int64) - n] + q = xpx.at(q, 0).set(b_left) + if right >= n: + b_right = B[xp.asarray(right, dtype=xp.int64) - n] + q = xpx.at(q, 1).set(b_right) + q = xpx.at(q, 2).set(R[i, k]) + B = xpx.at(B, i).set(xp.max(q)) + return B + + +@make_xp_test_case(to_tree) +def test_node_compare(xp): + np.random.seed(23) + nobs = 50 + X = np.random.randn(nobs, 4) + Z = xp.asarray(ward(X)) + tree = to_tree(Z) + assert_(tree > tree.get_left()) + assert_(tree.get_right() > tree.get_left()) + assert_(tree.get_right() == tree.get_right()) + assert_(tree.get_right() != tree.get_left()) + + +@make_xp_test_case(cut_tree) +def test_cut_tree(xp): + np.random.seed(23) + nobs = 50 + X = np.random.randn(nobs, 4) + Z = xp.asarray(ward(X)) + cutree = cut_tree(Z) + + # cutree.dtype varies between int32 and int64 over platforms + xp_assert_close(cutree[:, 0], xp.arange(nobs), rtol=1e-15, check_dtype=False) + xp_assert_close(cutree[:, -1], xp.zeros(nobs), rtol=1e-15, check_dtype=False) + assert_equal(np.asarray(cutree).max(0), np.arange(nobs - 1, -1, -1)) + + xp_assert_close(cutree[:, [-5]], cut_tree(Z, n_clusters=5), rtol=1e-15) + xp_assert_close(cutree[:, [-5, -10]], cut_tree(Z, n_clusters=[5, 10]), rtol=1e-15) + xp_assert_close(cutree[:, [-10, -5]], cut_tree(Z, n_clusters=[10, 5]), rtol=1e-15) + + nodes = _order_cluster_tree(Z) + heights = xp.asarray([node.dist for node in nodes]) + + xp_assert_close(cutree[:, np.searchsorted(heights, [5])], + cut_tree(Z, height=5), rtol=1e-15) + xp_assert_close(cutree[:, np.searchsorted(heights, [5, 10])], + cut_tree(Z, height=[5, 10]), rtol=1e-15) + xp_assert_close(cutree[:, np.searchsorted(heights, [10, 5])], + cut_tree(Z, height=[10, 5]), rtol=1e-15) + + +@make_xp_test_case(optimal_leaf_ordering) +def test_optimal_leaf_ordering(xp): + # test with the distance vector y + Z = optimal_leaf_ordering(xp.asarray(linkage(hierarchy_test_data.ytdist)), + xp.asarray(hierarchy_test_data.ytdist)) + expectedZ = hierarchy_test_data.linkage_ytdist_single_olo + xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-10) + + # test with the observation matrix X + Z = optimal_leaf_ordering(xp.asarray(linkage(hierarchy_test_data.X, 'ward')), + xp.asarray(hierarchy_test_data.X)) + expectedZ = hierarchy_test_data.linkage_X_ward_olo + xp_assert_close(Z, xp.asarray(expectedZ), atol=1e-06) + + +@skip_xp_backends(np_only=True, reason='`Heap` only supports NumPy backend') +def test_Heap(xp): + values = xp.asarray([2, -1, 0, -1.5, 3]) + heap = Heap(values) + + pair = heap.get_min() + assert_equal(pair['key'], 3) + assert_equal(pair['value'], -1.5) + + heap.remove_min() + pair = heap.get_min() + assert_equal(pair['key'], 1) + assert_equal(pair['value'], -1) + + heap.change_value(1, 2.5) + pair = heap.get_min() + assert_equal(pair['key'], 2) + assert_equal(pair['value'], 0) + + heap.remove_min() + heap.remove_min() + + heap.change_value(1, 10) + pair = heap.get_min() + assert_equal(pair['key'], 4) + assert_equal(pair['value'], 3) + + heap.remove_min() + pair = heap.get_min() + assert_equal(pair['key'], 1) + assert_equal(pair['value'], 10) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/test_vq.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/test_vq.py new file mode 100644 index 0000000000000000000000000000000000000000..cd285d96ed0badb8aa42d7c68ae04998b717c4a3 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/cluster/tests/test_vq.py @@ -0,0 +1,437 @@ +import math +import sys +import warnings +from copy import deepcopy +from threading import Lock + +import numpy as np +from numpy.testing import assert_array_equal +import pytest +from pytest import raises as assert_raises + +from scipy.cluster.vq import (kmeans, kmeans2, py_vq, vq, whiten, + ClusterError, _krandinit) +from scipy.cluster import _vq +from scipy.sparse._sputils import matrix + +from scipy._lib import array_api_extra as xpx +from scipy._lib._array_api import ( + SCIPY_ARRAY_API, eager_warns, is_lazy_array, make_xp_test_case, + xp_copy, xp_assert_close, xp_assert_equal +) + +xfail_xp_backends = pytest.mark.xfail_xp_backends +skip_xp_backends = pytest.mark.skip_xp_backends + +TESTDATA_2D = np.array([ + -2.2, 1.17, -1.63, 1.69, -2.04, 4.38, -3.09, 0.95, -1.7, 4.79, -1.68, 0.68, + -2.26, 3.34, -2.29, 2.55, -1.72, -0.72, -1.99, 2.34, -2.75, 3.43, -2.45, + 2.41, -4.26, 3.65, -1.57, 1.87, -1.96, 4.03, -3.01, 3.86, -2.53, 1.28, + -4.0, 3.95, -1.62, 1.25, -3.42, 3.17, -1.17, 0.12, -3.03, -0.27, -2.07, + -0.55, -1.17, 1.34, -2.82, 3.08, -2.44, 0.24, -1.71, 2.48, -5.23, 4.29, + -2.08, 3.69, -1.89, 3.62, -2.09, 0.26, -0.92, 1.07, -2.25, 0.88, -2.25, + 2.02, -4.31, 3.86, -2.03, 3.42, -2.76, 0.3, -2.48, -0.29, -3.42, 3.21, + -2.3, 1.73, -2.84, 0.69, -1.81, 2.48, -5.24, 4.52, -2.8, 1.31, -1.67, + -2.34, -1.18, 2.17, -2.17, 2.82, -1.85, 2.25, -2.45, 1.86, -6.79, 3.94, + -2.33, 1.89, -1.55, 2.08, -1.36, 0.93, -2.51, 2.74, -2.39, 3.92, -3.33, + 2.99, -2.06, -0.9, -2.83, 3.35, -2.59, 3.05, -2.36, 1.85, -1.69, 1.8, + -1.39, 0.66, -2.06, 0.38, -1.47, 0.44, -4.68, 3.77, -5.58, 3.44, -2.29, + 2.24, -1.04, -0.38, -1.85, 4.23, -2.88, 0.73, -2.59, 1.39, -1.34, 1.75, + -1.95, 1.3, -2.45, 3.09, -1.99, 3.41, -5.55, 5.21, -1.73, 2.52, -2.17, + 0.85, -2.06, 0.49, -2.54, 2.07, -2.03, 1.3, -3.23, 3.09, -1.55, 1.44, + -0.81, 1.1, -2.99, 2.92, -1.59, 2.18, -2.45, -0.73, -3.12, -1.3, -2.83, + 0.2, -2.77, 3.24, -1.98, 1.6, -4.59, 3.39, -4.85, 3.75, -2.25, 1.71, -3.28, + 3.38, -1.74, 0.88, -2.41, 1.92, -2.24, 1.19, -2.48, 1.06, -1.68, -0.62, + -1.3, 0.39, -1.78, 2.35, -3.54, 2.44, -1.32, 0.66, -2.38, 2.76, -2.35, + 3.95, -1.86, 4.32, -2.01, -1.23, -1.79, 2.76, -2.13, -0.13, -5.25, 3.84, + -2.24, 1.59, -4.85, 2.96, -2.41, 0.01, -0.43, 0.13, -3.92, 2.91, -1.75, + -0.53, -1.69, 1.69, -1.09, 0.15, -2.11, 2.17, -1.53, 1.22, -2.1, -0.86, + -2.56, 2.28, -3.02, 3.33, -1.12, 3.86, -2.18, -1.19, -3.03, 0.79, -0.83, + 0.97, -3.19, 1.45, -1.34, 1.28, -2.52, 4.22, -4.53, 3.22, -1.97, 1.75, + -2.36, 3.19, -0.83, 1.53, -1.59, 1.86, -2.17, 2.3, -1.63, 2.71, -2.03, + 3.75, -2.57, -0.6, -1.47, 1.33, -1.95, 0.7, -1.65, 1.27, -1.42, 1.09, -3.0, + 3.87, -2.51, 3.06, -2.6, 0.74, -1.08, -0.03, -2.44, 1.31, -2.65, 2.99, + -1.84, 1.65, -4.76, 3.75, -2.07, 3.98, -2.4, 2.67, -2.21, 1.49, -1.21, + 1.22, -5.29, 2.38, -2.85, 2.28, -5.6, 3.78, -2.7, 0.8, -1.81, 3.5, -3.75, + 4.17, -1.29, 2.99, -5.92, 3.43, -1.83, 1.23, -1.24, -1.04, -2.56, 2.37, + -3.26, 0.39, -4.63, 2.51, -4.52, 3.04, -1.7, 0.36, -1.41, 0.04, -2.1, 1.0, + -1.87, 3.78, -4.32, 3.59, -2.24, 1.38, -1.99, -0.22, -1.87, 1.95, -0.84, + 2.17, -5.38, 3.56, -1.27, 2.9, -1.79, 3.31, -5.47, 3.85, -1.44, 3.69, + -2.02, 0.37, -1.29, 0.33, -2.34, 2.56, -1.74, -1.27, -1.97, 1.22, -2.51, + -0.16, -1.64, -0.96, -2.99, 1.4, -1.53, 3.31, -2.24, 0.45, -2.46, 1.71, + -2.88, 1.56, -1.63, 1.46, -1.41, 0.68, -1.96, 2.76, -1.61, + 2.11]).reshape((200, 2)) + + +# Global data +X = np.array([[3.0, 3], [4, 3], [4, 2], + [9, 2], [5, 1], [6, 2], [9, 4], + [5, 2], [5, 4], [7, 4], [6, 5]]) + +CODET1 = np.array([[3.0000, 3.0000], + [6.2000, 4.0000], + [5.8000, 1.8000]]) + +CODET2 = np.array([[11.0/3, 8.0/3], + [6.7500, 4.2500], + [6.2500, 1.7500]]) + +LABEL1 = np.array([0, 1, 2, 2, 2, 2, 1, 2, 1, 1, 1]) + + +@make_xp_test_case(whiten) +class TestWhiten: + + def test_whiten(self, xp): + desired = xp.asarray([[5.08738849, 2.97091878], + [3.19909255, 0.69660580], + [4.51041982, 0.02640918], + [4.38567074, 0.95120889], + [2.32191480, 1.63195503]]) + + obs = xp.asarray([[0.98744510, 0.82766775], + [0.62093317, 0.19406729], + [0.87545741, 0.00735733], + [0.85124403, 0.26499712], + [0.45067590, 0.45464607]]) + xp_assert_close(whiten(obs), desired, rtol=1e-5) + + def test_whiten_zero_std(self, xp): + desired = xp.asarray([[0., 1.0, 2.86666544], + [0., 1.0, 1.32460034], + [0., 1.0, 3.74382172]]) + + obs = xp.asarray([[0., 1., 0.74109533], + [0., 1., 0.34243798], + [0., 1., 0.96785929]]) + + with eager_warns(RuntimeWarning, match="Some columns have standard...", xp=xp): + actual = whiten(obs) + xp_assert_close(actual, desired, rtol=1e-5) + + @pytest.mark.filterwarnings("ignore:invalid value encountered:RuntimeWarning:dask") + @pytest.mark.parametrize("bad_value", [math.nan, math.inf, -math.inf]) + def test_whiten_not_finite(self, bad_value, xp): + obs = xp.asarray([[0.98744510, bad_value], + [0.62093317, 0.19406729], + [0.87545741, 0.00735733], + [0.85124403, 0.26499712], + [0.45067590, 0.45464607]]) + + if is_lazy_array(obs): + desired = xp.asarray([[5.08738849, math.nan], + [3.19909255, math.nan], + [4.51041982, math.nan], + [4.38567074, math.nan], + [2.32191480, math.nan]]) + xp_assert_close(whiten(obs), desired, rtol=1e-5) + else: + assert_raises(ValueError, whiten, obs) + + @pytest.mark.skipif(SCIPY_ARRAY_API, + reason='`np.matrix` unsupported in array API mode') + def test_whiten_not_finite_matrix(self): + for bad_value in np.nan, np.inf, -np.inf: + obs = matrix([[0.98744510, bad_value], + [0.62093317, 0.19406729], + [0.87545741, 0.00735733], + [0.85124403, 0.26499712], + [0.45067590, 0.45464607]]) + assert_raises(ValueError, whiten, obs) + + +@make_xp_test_case(vq) +class TestVq: + + def test_py_vq(self, xp): + initc = np.concatenate([[X[0]], [X[1]], [X[2]]]) + # label1.dtype varies between int32 and int64 over platforms + label1 = py_vq(xp.asarray(X), xp.asarray(initc))[0] + xp_assert_equal(label1, xp.asarray(LABEL1, dtype=xp.int64), + check_dtype=False) + + @pytest.mark.skipif(SCIPY_ARRAY_API, + reason='`np.matrix` unsupported in array API mode') + def test_py_vq_matrix(self): + initc = np.concatenate([[X[0]], [X[1]], [X[2]]]) + # label1.dtype varies between int32 and int64 over platforms + label1 = py_vq(matrix(X), matrix(initc))[0] + assert_array_equal(label1, LABEL1) + + def test_vq(self, xp): + initc = np.concatenate([[X[0]], [X[1]], [X[2]]]) + label1, _ = _vq.vq(X, initc) + assert_array_equal(label1, LABEL1) + _, _ = vq(xp.asarray(X), xp.asarray(initc)) + + @pytest.mark.skipif(SCIPY_ARRAY_API, + reason='`np.matrix` unsupported in array API mode') + def test_vq_matrix(self): + initc = np.concatenate([[X[0]], [X[1]], [X[2]]]) + label1, _ = _vq.vq(matrix(X), matrix(initc)) + assert_array_equal(label1, LABEL1) + _, _ = vq(matrix(X), matrix(initc)) + + def test_vq_1d(self, xp): + # Test special rank 1 vq algo, python implementation. + data = X[:, 0] + initc = data[:3] + a, b = _vq.vq(data, initc) + data = xp.asarray(data) + initc = xp.asarray(initc) + ta, tb = py_vq(data[:, np.newaxis], initc[:, np.newaxis]) + # ta.dtype varies between int32 and int64 over platforms + xp_assert_equal(ta, xp.asarray(a, dtype=xp.int64), check_dtype=False) + xp_assert_equal(tb, xp.asarray(b)) + + def test__vq_sametype(self): + a = np.asarray([1.0, 2.0]) + b = a.astype(np.float32) + assert_raises(TypeError, _vq.vq, a, b) + + def test__vq_invalid_type(self): + a = np.asarray([1, 2], dtype=int) + assert_raises(TypeError, _vq.vq, a, a) + + def test_vq_large_nfeat(self, xp): + X = np.random.rand(20, 20) + code_book = np.random.rand(3, 20) + + codes0, dis0 = _vq.vq(X, code_book) + codes1, dis1 = py_vq( + xp.asarray(X), xp.asarray(code_book) + ) + xp_assert_close(dis1, xp.asarray(dis0), rtol=1e-5) + # codes1.dtype varies between int32 and int64 over platforms + xp_assert_equal(codes1, xp.asarray(codes0, dtype=xp.int64), check_dtype=False) + + X = X.astype(np.float32) + code_book = code_book.astype(np.float32) + + codes0, dis0 = _vq.vq(X, code_book) + codes1, dis1 = py_vq( + xp.asarray(X), xp.asarray(code_book) + ) + xp_assert_close(dis1, xp.asarray(dis0, dtype=xp.float64), rtol=1e-5) + # codes1.dtype varies between int32 and int64 over platforms + xp_assert_equal(codes1, xp.asarray(codes0, dtype=xp.int64), check_dtype=False) + + def test_vq_large_features(self, xp): + X = np.random.rand(10, 5) * 1000000 + code_book = np.random.rand(2, 5) * 1000000 + + codes0, dis0 = _vq.vq(X, code_book) + codes1, dis1 = py_vq( + xp.asarray(X), xp.asarray(code_book) + ) + xp_assert_close(dis1, xp.asarray(dis0), rtol=1e-5) + # codes1.dtype varies between int32 and int64 over platforms + xp_assert_equal(codes1, xp.asarray(codes0, dtype=xp.int64), check_dtype=False) + + +# Whole class skipped on GPU for now; +# once pdist/cdist are hooked up for CuPy, more tests will work +@make_xp_test_case(kmeans, kmeans2) +class TestKMeans: + + def test_large_features(self, xp): + # Generate a data set with large values, and run kmeans on it to + # (regression for 1077). + d = 300 + n = 100 + + m1 = np.random.randn(d) + m2 = np.random.randn(d) + x = 10000 * np.random.randn(n, d) - 20000 * m1 + y = 10000 * np.random.randn(n, d) + 20000 * m2 + + data = np.empty((x.shape[0] + y.shape[0], d), np.float64) + data[:x.shape[0]] = x + data[x.shape[0]:] = y + + # use `seed` to ensure backwards compatibility after SPEC7 + kmeans(xp.asarray(data), 2, seed=1) + + def test_kmeans_simple(self, xp): + rng = np.random.default_rng(54321) + initc = np.concatenate([[X[0]], [X[1]], [X[2]]]) + code1 = kmeans(xp.asarray(X), xp.asarray(initc), iter=1, rng=rng)[0] + xp_assert_close(code1, xp.asarray(CODET2)) + + @pytest.mark.skipif(SCIPY_ARRAY_API, + reason='`np.matrix` unsupported in array API mode') + def test_kmeans_simple_matrix(self): + rng = np.random.default_rng(54321) + initc = np.concatenate([[X[0]], [X[1]], [X[2]]]) + code1 = kmeans(matrix(X), matrix(initc), iter=1, rng=rng)[0] + xp_assert_close(code1, CODET2) + + def test_kmeans_lost_cluster(self, xp): + # This will cause kmeans to have a cluster with no points. + data = xp.asarray(TESTDATA_2D) + initk = xp.asarray([[-1.8127404, -0.67128041], + [2.04621601, 0.07401111], + [-2.31149087, -0.05160469]]) + + kmeans(data, initk) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + ("One of the clusters is empty. Re-run kmeans with a different " + "initialization"), + UserWarning, + ) + kmeans2(data, initk, missing='warn') + + assert_raises(ClusterError, kmeans2, data, initk, missing='raise') + + def test_kmeans2_simple(self, xp): + rng = np.random.default_rng(12345678) + initc = xp.asarray(np.concatenate([[X[0]], [X[1]], [X[2]]])) + arrays = [xp.asarray] if SCIPY_ARRAY_API else [np.asarray, matrix] + for tp in arrays: + code1 = kmeans2(tp(X), tp(initc), iter=1, rng=rng)[0] + code2 = kmeans2(tp(X), tp(initc), iter=2, rng=rng)[0] + + xp_assert_close(code1, xp.asarray(CODET1)) + xp_assert_close(code2, xp.asarray(CODET2)) + + @pytest.mark.skipif(SCIPY_ARRAY_API, + reason='`np.matrix` unsupported in array API mode') + def test_kmeans2_simple_matrix(self): + rng = np.random.default_rng(12345678) + initc = np.concatenate([[X[0]], [X[1]], [X[2]]]) + code1 = kmeans2(matrix(X), matrix(initc), iter=1, rng=rng)[0] + code2 = kmeans2(matrix(X), matrix(initc), iter=2, rng=rng)[0] + + xp_assert_close(code1, CODET1) + xp_assert_close(code2, CODET2) + + def test_kmeans2_rank1(self, xp): + data = xp.asarray(TESTDATA_2D) + data1 = data[:, 0] + + initc = data1[:3] + code = xp_copy(initc, xp=xp) + + # use `seed` to ensure backwards compatibility after SPEC7 + kmeans2(data1, code, iter=1, seed=1)[0] + kmeans2(data1, code, iter=2)[0] + + def test_kmeans2_rank1_2(self, xp): + data = xp.asarray(TESTDATA_2D) + data1 = data[:, 0] + kmeans2(data1, 2, iter=1) + + def test_kmeans2_high_dim(self, xp): + # test kmeans2 when the number of dimensions exceeds the number + # of input points + data = xp.asarray(TESTDATA_2D) + data = xp.reshape(data, (20, 20))[:10, :] + kmeans2(data, 2) + + def test_kmeans2_init(self, xp): + rng = np.random.default_rng(12345678) + data = xp.asarray(TESTDATA_2D) + k = 3 + + kmeans2(data, k, minit='points', rng=rng) + kmeans2(data[:, 1], k, minit='points', rng=rng) # special case (1-D) + + kmeans2(data, k, minit='++', rng=rng) + kmeans2(data[:, 1], k, minit='++', rng=rng) # special case (1-D) + + # minit='random' can give warnings, filter those + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", "One of the clusters is empty. Re-run.") + kmeans2(data, k, minit='random', rng=rng) + kmeans2(data[:, 1], k, minit='random', rng=rng) # special case (1-D) + + @pytest.fixture + def krand_lock(self): + return Lock() + + @xfail_xp_backends('dask.array', reason="Wrong answer") + @pytest.mark.skipif(sys.platform == 'win32', + reason='Fails with MemoryError in Wine.') + def test_krandinit(self, xp, krand_lock): + data = xp.asarray(TESTDATA_2D) + datas = [xp.reshape(data, (200, 2)), + xp.reshape(data, (20, 20))[:10, :]] + k = int(1e6) + with krand_lock: + for data in datas: + rng = np.random.default_rng(1234) + init = _krandinit(data, k, rng, xp) + orig_cov = xpx.cov(data.T, xp=xp) + init_cov = xpx.cov(init.T, xp=xp) + xp_assert_close(orig_cov, init_cov, atol=1.1e-2) + + def test_kmeans2_empty(self, xp): + # Regression test for gh-1032. + assert_raises(ValueError, kmeans2, xp.asarray([]), 2) + + def test_kmeans_0k(self, xp): + # Regression test for gh-1073: fail when k arg is 0. + assert_raises(ValueError, kmeans, xp.asarray(X), 0) + assert_raises(ValueError, kmeans2, xp.asarray(X), 0) + assert_raises(ValueError, kmeans2, xp.asarray(X), xp.asarray([])) + + def test_kmeans_large_thres(self, xp): + # Regression test for gh-1774 + x = xp.asarray([1, 2, 3, 4, 10], dtype=xp.float64) + res = kmeans(x, 1, thresh=1e16) + xp_assert_close(res[0], xp.asarray([4.], dtype=xp.float64)) + xp_assert_close(res[1], xp.asarray(2.3999999999999999, dtype=xp.float64)[()]) + + def test_kmeans2_kpp_low_dim(self, xp): + # Regression test for gh-11462 + rng = np.random.default_rng(2358792345678234568) + prev_res = xp.asarray([[-1.95266667, 0.898], + [-3.153375, 3.3945]], dtype=xp.float64) + res, _ = kmeans2(xp.asarray(TESTDATA_2D), 2, minit='++', rng=rng) + xp_assert_close(res, prev_res) + + def test_kmeans2_kpp_high_dim(self, xp): + # Regression test for gh-11462 + rng = np.random.default_rng(23587923456834568) + n_dim = 100 + size = 10 + centers = np.vstack([5 * np.ones(n_dim), + -5 * np.ones(n_dim)]) + + data = np.vstack([ + rng.multivariate_normal(centers[0], np.eye(n_dim), size=size), + rng.multivariate_normal(centers[1], np.eye(n_dim), size=size) + ]) + + data = xp.asarray(data) + res, _ = kmeans2(data, 2, minit='++', rng=rng) + xp_assert_equal(xp.sign(res), xp.sign(xp.asarray(centers))) + + def test_kmeans_diff_convergence(self, xp): + # Regression test for gh-8727 + obs = xp.asarray([-3, -1, 0, 1, 1, 8], dtype=xp.float64) + res = kmeans(obs, xp.asarray([-3., 0.99])) + xp_assert_close(res[0], xp.asarray([-0.4, 8.], dtype=xp.float64)) + xp_assert_close(res[1], xp.asarray(1.0666666666666667, dtype=xp.float64)[()]) + + def test_kmeans_and_kmeans2_random_seed(self, xp): + + seed_list = [ + 1234, np.random.RandomState(1234), np.random.default_rng(1234) + ] + + for seed in seed_list: + seed1 = deepcopy(seed) + seed2 = deepcopy(seed) + data = xp.asarray(TESTDATA_2D) + # test for kmeans + res1, _ = kmeans(data, 2, seed=seed1) + res2, _ = kmeans(data, 2, seed=seed2) + xp_assert_close(res1, res2) # should be same results + # test for kmeans2 + for minit in ["random", "points", "++"]: + res1, _ = kmeans2(data, 2, minit=minit, seed=seed1) + res2, _ = kmeans2(data, 2, minit=minit, seed=seed2) + xp_assert_close(res1, res2) # should be same results diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..541a317324c44bbe283aaba678117c5907106691 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_backend.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_backend.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ebe52a61c4c4672baf01135f032bc44756e999b5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_backend.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_basic.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_basic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e8584c8e1db7e03039a94b9d01ef857fb503de4a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_basic.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_basic_backend.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_basic_backend.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b3ec63bc6469a72d955c5b014dcec76a7e81b821 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_basic_backend.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_debug_backends.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_debug_backends.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1d9c50dccdd334615d3e1742a9b54154ae1b2547 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_debug_backends.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_fftlog.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_fftlog.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a16e2c1b0b0fff22a554fe00dc2ea2b20e2d56fd Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_fftlog.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_fftlog_backend.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_fftlog_backend.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7db445fefc0eb770e1107822532f0dc4281fa7b7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_fftlog_backend.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_helper.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_helper.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dac297c0fbc273cdc3544e1a0dc86495c00859d0 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_helper.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_realtransforms.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_realtransforms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd77e4f6db39e6edd0502a6b3b445178087bc859 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_realtransforms.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_realtransforms_backend.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_realtransforms_backend.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b8cad9f048dac6403d83fce0e6470f9903bd42bc Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/__pycache__/_realtransforms_backend.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/LICENSE.md b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/LICENSE.md new file mode 100644 index 0000000000000000000000000000000000000000..1b5163d8435976c24988afbd39ded304947178cb --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/LICENSE.md @@ -0,0 +1,25 @@ +Copyright (C) 2010-2019 Max-Planck-Society +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +* Neither the name of the copyright holder nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..0671484c9a0780df353b9b783813b6fa7492d38d --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/__init__.py @@ -0,0 +1,9 @@ +""" FFT backend using pypocketfft """ + +from .basic import * +from .realtransforms import * +from .helper import * + +from scipy._lib._testutils import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..25cbac1ff9efa799a16635cc88af7351336c68e7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/__pycache__/basic.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/__pycache__/basic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c838ca3537bf1238f6cbfd27bbcecb2ac96132d3 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/__pycache__/basic.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/__pycache__/helper.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/__pycache__/helper.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..216ae5a054bdcebaa48d41bb4a7c5e36802f2910 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/__pycache__/helper.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/__pycache__/realtransforms.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/__pycache__/realtransforms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e5d5000cd51d305eac6db94abb6d4881c6d901d1 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/__pycache__/realtransforms.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/basic.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/basic.py new file mode 100644 index 0000000000000000000000000000000000000000..bd2d0d33958021c431171b72f72c37363ac98e03 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/basic.py @@ -0,0 +1,251 @@ +""" +Discrete Fourier Transforms - basic.py +""" +import numpy as np +import functools +from . import pypocketfft as pfft +from .helper import (_asfarray, _init_nd_shape_and_axes, _datacopied, + _fix_shape, _fix_shape_1d, _normalization, + _workers) + +def c2c(forward, x, n=None, axis=-1, norm=None, overwrite_x=False, + workers=None, *, plan=None): + """ Return discrete Fourier transform of real or complex sequence. """ + if plan is not None: + raise NotImplementedError('Passing a precomputed plan is not yet ' + 'supported by scipy.fft functions') + tmp = _asfarray(x) + overwrite_x = overwrite_x or _datacopied(tmp, x) + norm = _normalization(norm, forward) + workers = _workers(workers) + + if n is not None: + tmp, copied = _fix_shape_1d(tmp, n, axis) + overwrite_x = overwrite_x or copied + elif tmp.shape[axis] < 1: + message = f"invalid number of data points ({tmp.shape[axis]}) specified" + raise ValueError(message) + + out = (tmp if overwrite_x and tmp.dtype.kind == 'c' else None) + + return pfft.c2c(tmp, (axis,), forward, norm, out, workers) + + +fft = functools.partial(c2c, True) +fft.__name__ = 'fft' +ifft = functools.partial(c2c, False) +ifft.__name__ = 'ifft' + + +def r2c(forward, x, n=None, axis=-1, norm=None, overwrite_x=False, + workers=None, *, plan=None): + """ + Discrete Fourier transform of a real sequence. + """ + if plan is not None: + raise NotImplementedError('Passing a precomputed plan is not yet ' + 'supported by scipy.fft functions') + tmp = _asfarray(x) + norm = _normalization(norm, forward) + workers = _workers(workers) + + if not np.isrealobj(tmp): + raise TypeError("x must be a real sequence") + + if n is not None: + tmp, _ = _fix_shape_1d(tmp, n, axis) + elif tmp.shape[axis] < 1: + raise ValueError(f"invalid number of data points ({tmp.shape[axis]}) specified") + + # Note: overwrite_x is not utilised + return pfft.r2c(tmp, (axis,), forward, norm, None, workers) + + +rfft = functools.partial(r2c, True) +rfft.__name__ = 'rfft' +ihfft = functools.partial(r2c, False) +ihfft.__name__ = 'ihfft' + + +def c2r(forward, x, n=None, axis=-1, norm=None, overwrite_x=False, + workers=None, *, plan=None): + """ + Return inverse discrete Fourier transform of real sequence x. + """ + if plan is not None: + raise NotImplementedError('Passing a precomputed plan is not yet ' + 'supported by scipy.fft functions') + tmp = _asfarray(x) + norm = _normalization(norm, forward) + workers = _workers(workers) + + # TODO: Optimize for hermitian and real? + if np.isrealobj(tmp): + tmp = tmp + 0.j + + # Last axis utilizes hermitian symmetry + if n is None: + n = (tmp.shape[axis] - 1) * 2 + if n < 1: + raise ValueError(f"Invalid number of data points ({n}) specified") + else: + tmp, _ = _fix_shape_1d(tmp, (n//2) + 1, axis) + + # Note: overwrite_x is not utilized + return pfft.c2r(tmp, (axis,), n, forward, norm, None, workers) + + +hfft = functools.partial(c2r, True) +hfft.__name__ = 'hfft' +irfft = functools.partial(c2r, False) +irfft.__name__ = 'irfft' + + +def hfft2(x, s=None, axes=(-2,-1), norm=None, overwrite_x=False, workers=None, + *, plan=None): + """ + 2-D discrete Fourier transform of a Hermitian sequence + """ + if plan is not None: + raise NotImplementedError('Passing a precomputed plan is not yet ' + 'supported by scipy.fft functions') + return hfftn(x, s, axes, norm, overwrite_x, workers) + + +def ihfft2(x, s=None, axes=(-2,-1), norm=None, overwrite_x=False, workers=None, + *, plan=None): + """ + 2-D discrete inverse Fourier transform of a Hermitian sequence + """ + if plan is not None: + raise NotImplementedError('Passing a precomputed plan is not yet ' + 'supported by scipy.fft functions') + return ihfftn(x, s, axes, norm, overwrite_x, workers) + + +def c2cn(forward, x, s=None, axes=None, norm=None, overwrite_x=False, + workers=None, *, plan=None): + """ + Return multidimensional discrete Fourier transform. + """ + if plan is not None: + raise NotImplementedError('Passing a precomputed plan is not yet ' + 'supported by scipy.fft functions') + tmp = _asfarray(x) + + shape, axes = _init_nd_shape_and_axes(tmp, s, axes) + overwrite_x = overwrite_x or _datacopied(tmp, x) + workers = _workers(workers) + + if len(axes) == 0: + return x + + tmp, copied = _fix_shape(tmp, shape, axes) + overwrite_x = overwrite_x or copied + + norm = _normalization(norm, forward) + out = (tmp if overwrite_x and tmp.dtype.kind == 'c' else None) + + return pfft.c2c(tmp, axes, forward, norm, out, workers) + + +fftn = functools.partial(c2cn, True) +fftn.__name__ = 'fftn' +ifftn = functools.partial(c2cn, False) +ifftn.__name__ = 'ifftn' + +def r2cn(forward, x, s=None, axes=None, norm=None, overwrite_x=False, + workers=None, *, plan=None): + """Return multidimensional discrete Fourier transform of real input""" + if plan is not None: + raise NotImplementedError('Passing a precomputed plan is not yet ' + 'supported by scipy.fft functions') + tmp = _asfarray(x) + + if not np.isrealobj(tmp): + raise TypeError("x must be a real sequence") + + shape, axes = _init_nd_shape_and_axes(tmp, s, axes) + tmp, _ = _fix_shape(tmp, shape, axes) + norm = _normalization(norm, forward) + workers = _workers(workers) + + if len(axes) == 0: + raise ValueError("at least 1 axis must be transformed") + + # Note: overwrite_x is not utilized + return pfft.r2c(tmp, axes, forward, norm, None, workers) + + +rfftn = functools.partial(r2cn, True) +rfftn.__name__ = 'rfftn' +ihfftn = functools.partial(r2cn, False) +ihfftn.__name__ = 'ihfftn' + + +def c2rn(forward, x, s=None, axes=None, norm=None, overwrite_x=False, + workers=None, *, plan=None): + """Multidimensional inverse discrete fourier transform with real output""" + if plan is not None: + raise NotImplementedError('Passing a precomputed plan is not yet ' + 'supported by scipy.fft functions') + tmp = _asfarray(x) + + # TODO: Optimize for hermitian and real? + if np.isrealobj(tmp): + tmp = tmp + 0.j + + noshape = s is None + shape, axes = _init_nd_shape_and_axes(tmp, s, axes) + + if len(axes) == 0: + raise ValueError("at least 1 axis must be transformed") + + shape = list(shape) + if noshape: + shape[-1] = (x.shape[axes[-1]] - 1) * 2 + + norm = _normalization(norm, forward) + workers = _workers(workers) + + # Last axis utilizes hermitian symmetry + lastsize = shape[-1] + shape[-1] = (shape[-1] // 2) + 1 + + tmp, _ = tuple(_fix_shape(tmp, shape, axes)) + + # Note: overwrite_x is not utilized + return pfft.c2r(tmp, axes, lastsize, forward, norm, None, workers) + + +hfftn = functools.partial(c2rn, True) +hfftn.__name__ = 'hfftn' +irfftn = functools.partial(c2rn, False) +irfftn.__name__ = 'irfftn' + + +def r2r_fftpack(forward, x, n=None, axis=-1, norm=None, overwrite_x=False): + """FFT of a real sequence, returning fftpack half complex format""" + tmp = _asfarray(x) + overwrite_x = overwrite_x or _datacopied(tmp, x) + norm = _normalization(norm, forward) + workers = _workers(None) + + if tmp.dtype.kind == 'c': + raise TypeError('x must be a real sequence') + + if n is not None: + tmp, copied = _fix_shape_1d(tmp, n, axis) + overwrite_x = overwrite_x or copied + elif tmp.shape[axis] < 1: + raise ValueError(f"invalid number of data points ({tmp.shape[axis]}) specified") + + out = (tmp if overwrite_x else None) + + return pfft.r2r_fftpack(tmp, (axis,), forward, forward, norm, out, workers) + + +rfft_fftpack = functools.partial(r2r_fftpack, True) +rfft_fftpack.__name__ = 'rfft_fftpack' +irfft_fftpack = functools.partial(r2r_fftpack, False) +irfft_fftpack.__name__ = 'irfft_fftpack' diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/helper.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/helper.py new file mode 100644 index 0000000000000000000000000000000000000000..81e4827a88bf8162ca6fe830f1df1ad1bcfd30d6 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/helper.py @@ -0,0 +1,252 @@ +from numbers import Number +import operator +import os +import threading +import contextlib + +import numpy as np + +from scipy._lib._util import copy_if_needed +from scipy._lib._array_api import xp_capabilities + +# good_size is exposed (and used) from this import +from .pypocketfft import good_size, prev_good_size + + +__all__ = ['good_size', 'prev_good_size', 'set_workers', 'get_workers'] + +_config = threading.local() +_cpu_count = os.cpu_count() + + +def _iterable_of_int(x, name=None): + """Convert ``x`` to an iterable sequence of int + + Parameters + ---------- + x : value, or sequence of values, convertible to int + name : str, optional + Name of the argument being converted, only used in the error message + + Returns + ------- + y : ``List[int]`` + """ + if isinstance(x, Number): + x = (x,) + + try: + x = [operator.index(a) for a in x] + except TypeError as e: + name = name or "value" + raise ValueError(f"{name} must be a scalar or iterable of integers") from e + + return x + + +def _init_nd_shape_and_axes(x, shape, axes): + """ + Handle shape and axes arguments for N-D transforms. + + Returns the shape and axes in a standard form, taking into account negative + values and checking for various potential errors. + + Parameters + ---------- + x : ndarray + The input array. + shape : int or array_like of ints or None + The shape of the result. If both `shape` and `axes` (see below) are + None, `shape` is ``x.shape``; if `shape` is None but `axes` is + not None, then `shape` is ``numpy.take(x.shape, axes, axis=0)``. + If `shape` is -1, the size of the corresponding dimension of `x` is + used. + axes : int or array_like of ints or None + Axes along which the calculation is computed. + The default is over all axes. + Negative indices are automatically converted to their positive + counterparts. + + Returns + ------- + shape : tuple + The shape of the result as a tuple of integers. + axes : list + Axes along which the calculation is computed, as a list of integers. + """ + noshape = shape is None + noaxes = axes is None + + if not noaxes: + axes = _iterable_of_int(axes, 'axes') + axes = [a + x.ndim if a < 0 else a for a in axes] + + if any(a >= x.ndim or a < 0 for a in axes): + raise ValueError("axes exceeds dimensionality of input") + if len(set(axes)) != len(axes): + raise ValueError("all axes must be unique") + + if not noshape: + shape = _iterable_of_int(shape, 'shape') + + if axes and len(axes) != len(shape): + raise ValueError("when given, axes and shape arguments" + " have to be of the same length") + if noaxes: + if len(shape) > x.ndim: + raise ValueError("shape requires more axes than are present") + axes = range(x.ndim - len(shape), x.ndim) + + shape = [x.shape[a] if s == -1 else s for s, a in zip(shape, axes)] + elif noaxes: + shape = list(x.shape) + axes = range(x.ndim) + else: + shape = [x.shape[a] for a in axes] + + if any(s < 1 for s in shape): + raise ValueError( + f"invalid number of data points ({shape}) specified") + + return tuple(shape), list(axes) + + +def _asfarray(x): + """ + Convert to array with floating or complex dtype. + + float16 values are also promoted to float32. + """ + if not hasattr(x, "dtype"): + x = np.asarray(x) + + if x.dtype == np.float16: + return np.asarray(x, np.float32) + elif x.dtype.kind not in 'fc': + return np.asarray(x, np.float64) + + # Require native byte order + dtype = x.dtype.newbyteorder('=') + # Always align input + copy = True if not x.flags['ALIGNED'] else copy_if_needed + return np.array(x, dtype=dtype, copy=copy) + +def _datacopied(arr, original): + """ + Strict check for `arr` not sharing any data with `original`, + under the assumption that arr = asarray(original) + """ + if arr is original: + return False + if not isinstance(original, np.ndarray) and hasattr(original, '__array__'): + return False + return arr.base is None + + +def _fix_shape(x, shape, axes): + """Internal auxiliary function for _raw_fft, _raw_fftnd.""" + must_copy = False + + # Build an nd slice with the dimensions to be read from x + index = [slice(None)]*x.ndim + for n, ax in zip(shape, axes): + if x.shape[ax] >= n: + index[ax] = slice(0, n) + else: + index[ax] = slice(0, x.shape[ax]) + must_copy = True + + index = tuple(index) + + if not must_copy: + return x[index], False + + s = list(x.shape) + for n, axis in zip(shape, axes): + s[axis] = n + + z = np.zeros(s, x.dtype) + z[index] = x[index] + return z, True + + +def _fix_shape_1d(x, n, axis): + if n < 1: + raise ValueError( + f"invalid number of data points ({n}) specified") + + return _fix_shape(x, (n,), (axis,)) + + +_NORM_MAP = {None: 0, 'backward': 0, 'ortho': 1, 'forward': 2} + + +def _normalization(norm, forward): + """Returns the pypocketfft normalization mode from the norm argument""" + try: + inorm = _NORM_MAP[norm] + return inorm if forward else (2 - inorm) + except KeyError: + raise ValueError( + f'Invalid norm value {norm!r}, should ' + 'be "backward", "ortho" or "forward"') from None + + +def _workers(workers): + if workers is None: + return getattr(_config, 'default_workers', 1) + + if workers < 0: + if workers >= -_cpu_count: + workers += 1 + _cpu_count + else: + raise ValueError(f"workers value out of range; got {workers}, must not be" + f" less than {-_cpu_count}") + elif workers == 0: + raise ValueError("workers must not be zero") + + return workers + + +@xp_capabilities(out_of_scope=True) +@contextlib.contextmanager +def set_workers(workers): + """Context manager for the default number of workers used in `scipy.fft` + + Parameters + ---------- + workers : int + The default number of workers to use + + Examples + -------- + >>> import numpy as np + >>> from scipy import fft, signal + >>> rng = np.random.default_rng() + >>> x = rng.standard_normal((128, 64)) + >>> with fft.set_workers(4): + ... y = signal.fftconvolve(x, x) + + """ + old_workers = get_workers() + _config.default_workers = _workers(operator.index(workers)) + try: + yield + finally: + _config.default_workers = old_workers + + +@xp_capabilities(out_of_scope=True) +def get_workers(): + """Returns the default number of workers within the current context + + Examples + -------- + >>> from scipy import fft + >>> fft.get_workers() + 1 + >>> with fft.set_workers(4): + ... fft.get_workers() + 4 + """ + return getattr(_config, 'default_workers', 1) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/realtransforms.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/realtransforms.py new file mode 100644 index 0000000000000000000000000000000000000000..5a0c616742305444d51258e650344c060129dfab --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/realtransforms.py @@ -0,0 +1,109 @@ +import numpy as np +from . import pypocketfft as pfft +from .helper import (_asfarray, _init_nd_shape_and_axes, _datacopied, + _fix_shape, _fix_shape_1d, _normalization, _workers) +import functools + + +def _r2r(forward, transform, x, type=2, n=None, axis=-1, norm=None, + overwrite_x=False, workers=None, orthogonalize=None): + """Forward or backward 1-D DCT/DST + + Parameters + ---------- + forward : bool + Transform direction (determines type and normalisation) + transform : {pypocketfft.dct, pypocketfft.dst} + The transform to perform + """ + tmp = _asfarray(x) + overwrite_x = overwrite_x or _datacopied(tmp, x) + norm = _normalization(norm, forward) + workers = _workers(workers) + + if not forward: + if type == 2: + type = 3 + elif type == 3: + type = 2 + + if n is not None: + tmp, copied = _fix_shape_1d(tmp, n, axis) + overwrite_x = overwrite_x or copied + elif tmp.shape[axis] < 1: + raise ValueError(f"invalid number of data points ({tmp.shape[axis]}) specified") + + out = (tmp if overwrite_x else None) + + # For complex input, transform real and imaginary components separably + if np.iscomplexobj(x): + out = np.empty_like(tmp) if out is None else out + transform(tmp.real, type, (axis,), norm, out.real, workers) + transform(tmp.imag, type, (axis,), norm, out.imag, workers) + return out + + return transform(tmp, type, (axis,), norm, out, workers, orthogonalize) + + +dct = functools.partial(_r2r, True, pfft.dct) +dct.__name__ = 'dct' +idct = functools.partial(_r2r, False, pfft.dct) +idct.__name__ = 'idct' + +dst = functools.partial(_r2r, True, pfft.dst) +dst.__name__ = 'dst' +idst = functools.partial(_r2r, False, pfft.dst) +idst.__name__ = 'idst' + + +def _r2rn(forward, transform, x, type=2, s=None, axes=None, norm=None, + overwrite_x=False, workers=None, orthogonalize=None): + """Forward or backward nd DCT/DST + + Parameters + ---------- + forward : bool + Transform direction (determines type and normalisation) + transform : {pypocketfft.dct, pypocketfft.dst} + The transform to perform + """ + tmp = _asfarray(x) + + shape, axes = _init_nd_shape_and_axes(tmp, s, axes) + overwrite_x = overwrite_x or _datacopied(tmp, x) + + if len(axes) == 0: + return x + + tmp, copied = _fix_shape(tmp, shape, axes) + overwrite_x = overwrite_x or copied + + if not forward: + if type == 2: + type = 3 + elif type == 3: + type = 2 + + norm = _normalization(norm, forward) + workers = _workers(workers) + out = (tmp if overwrite_x else None) + + # For complex input, transform real and imaginary components separably + if np.iscomplexobj(x): + out = np.empty_like(tmp) if out is None else out + transform(tmp.real, type, axes, norm, out.real, workers) + transform(tmp.imag, type, axes, norm, out.imag, workers) + return out + + return transform(tmp, type, axes, norm, out, workers, orthogonalize) + + +dctn = functools.partial(_r2rn, True, pfft.dct) +dctn.__name__ = 'dctn' +idctn = functools.partial(_r2rn, False, pfft.dct) +idctn.__name__ = 'idctn' + +dstn = functools.partial(_r2rn, True, pfft.dst) +dstn.__name__ = 'dstn' +idstn = functools.partial(_r2rn, False, pfft.dst) +idstn.__name__ = 'idstn' diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..33e62f1a26cf09a9495c50af5af944160f6052eb Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/__pycache__/test_basic.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/__pycache__/test_basic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b91f44938639814d9ce9ca3bb901319fc23a7039 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/__pycache__/test_basic.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/__pycache__/test_real_transforms.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/__pycache__/test_real_transforms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4f2d1f01bec99db7da14c92d2454a89c8d2e06ae Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/__pycache__/test_real_transforms.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/test_basic.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/test_basic.py new file mode 100644 index 0000000000000000000000000000000000000000..4ed1abe818ce1769f480dadebc80e588babaff87 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/test_basic.py @@ -0,0 +1,1011 @@ +# Created by Pearu Peterson, September 2002 + +from numpy.testing import (assert_, assert_equal, assert_array_almost_equal, + assert_array_almost_equal_nulp, assert_array_less, + assert_allclose) +import pytest +from pytest import raises as assert_raises +from scipy.fft._pocketfft import (ifft, fft, fftn, ifftn, + rfft, irfft, rfftn, irfftn, + hfft, ihfft, hfftn, ihfftn) + +from numpy import (arange, array, asarray, zeros, dot, exp, pi, + swapaxes, cdouble) +import numpy as np +import numpy.fft +from numpy.random import rand + +# "large" composite numbers supported by FFT._PYPOCKETFFT +LARGE_COMPOSITE_SIZES = [ + 2**13, + 2**5 * 3**5, + 2**3 * 3**3 * 5**2, +] +SMALL_COMPOSITE_SIZES = [ + 2, + 2*3*5, + 2*2*3*3, +] +# prime +LARGE_PRIME_SIZES = [ + 2011 +] +SMALL_PRIME_SIZES = [ + 29 +] + + +def _assert_close_in_norm(x, y, rtol, size, rdt): + # helper function for testing + err_msg = f"size: {size} rdt: {rdt}" + assert_array_less(np.linalg.norm(x - y), rtol*np.linalg.norm(x), err_msg) + + +def random(size): + return rand(*size) + +def swap_byteorder(arr): + """Returns the same array with swapped byteorder""" + dtype = arr.dtype.newbyteorder('S') + return arr.astype(dtype) + +def direct_dft(x): + x = asarray(x) + n = len(x) + y = zeros(n, dtype=cdouble) + w = -arange(n)*(2j*pi/n) + for i in range(n): + y[i] = dot(exp(i*w), x) + return y + + +def direct_idft(x): + x = asarray(x) + n = len(x) + y = zeros(n, dtype=cdouble) + w = arange(n)*(2j*pi/n) + for i in range(n): + y[i] = dot(exp(i*w), x)/n + return y + + +def direct_dftn(x): + x = asarray(x) + for axis in range(x.ndim): + x = fft(x, axis=axis) + return x + + +def direct_idftn(x): + x = asarray(x) + for axis in range(x.ndim): + x = ifft(x, axis=axis) + return x + + +def direct_rdft(x): + x = asarray(x) + n = len(x) + w = -arange(n)*(2j*pi/n) + y = zeros(n//2+1, dtype=cdouble) + for i in range(n//2+1): + y[i] = dot(exp(i*w), x) + return y + + +def direct_irdft(x, n): + x = asarray(x) + x1 = zeros(n, dtype=cdouble) + for i in range(n//2+1): + x1[i] = x[i] + if i > 0 and 2*i < n: + x1[n-i] = np.conj(x[i]) + return direct_idft(x1).real + + +def direct_rdftn(x): + return fftn(rfft(x), axes=range(x.ndim - 1)) + + +class _TestFFTBase: + def setup_method(self): + self.cdt = None + self.rdt = None + np.random.seed(1234) + + def test_definition(self): + x = np.array([1,2,3,4+1j,1,2,3,4+2j], dtype=self.cdt) + y = fft(x) + assert_equal(y.dtype, self.cdt) + y1 = direct_dft(x) + assert_array_almost_equal(y,y1) + x = np.array([1,2,3,4+0j,5], dtype=self.cdt) + assert_array_almost_equal(fft(x),direct_dft(x)) + + def test_n_argument_real(self): + x1 = np.array([1,2,3,4], dtype=self.rdt) + x2 = np.array([1,2,3,4], dtype=self.rdt) + y = fft([x1,x2],n=4) + assert_equal(y.dtype, self.cdt) + assert_equal(y.shape,(2,4)) + assert_array_almost_equal(y[0],direct_dft(x1)) + assert_array_almost_equal(y[1],direct_dft(x2)) + + def _test_n_argument_complex(self): + x1 = np.array([1,2,3,4+1j], dtype=self.cdt) + x2 = np.array([1,2,3,4+1j], dtype=self.cdt) + y = fft([x1,x2],n=4) + assert_equal(y.dtype, self.cdt) + assert_equal(y.shape,(2,4)) + assert_array_almost_equal(y[0],direct_dft(x1)) + assert_array_almost_equal(y[1],direct_dft(x2)) + + def test_djbfft(self): + for i in range(2,14): + n = 2**i + x = np.arange(n) + y = fft(x.astype(complex)) + y2 = numpy.fft.fft(x) + assert_array_almost_equal(y,y2) + y = fft(x) + assert_array_almost_equal(y,y2) + + def test_invalid_sizes(self): + assert_raises(ValueError, fft, []) + assert_raises(ValueError, fft, [[1,1],[2,2]], -5) + + +class TestLongDoubleFFT(_TestFFTBase): + def setup_method(self): + self.cdt = np.clongdouble + self.rdt = np.longdouble + + +class TestDoubleFFT(_TestFFTBase): + def setup_method(self): + self.cdt = np.cdouble + self.rdt = np.float64 + + +class TestSingleFFT(_TestFFTBase): + def setup_method(self): + self.cdt = np.complex64 + self.rdt = np.float32 + + +class TestFloat16FFT: + + def test_1_argument_real(self): + x1 = np.array([1, 2, 3, 4], dtype=np.float16) + y = fft(x1, n=4) + assert_equal(y.dtype, np.complex64) + assert_equal(y.shape, (4, )) + assert_array_almost_equal(y, direct_dft(x1.astype(np.float32))) + + def test_n_argument_real(self): + x1 = np.array([1, 2, 3, 4], dtype=np.float16) + x2 = np.array([1, 2, 3, 4], dtype=np.float16) + y = fft([x1, x2], n=4) + assert_equal(y.dtype, np.complex64) + assert_equal(y.shape, (2, 4)) + assert_array_almost_equal(y[0], direct_dft(x1.astype(np.float32))) + assert_array_almost_equal(y[1], direct_dft(x2.astype(np.float32))) + + +class _TestIFFTBase: + def setup_method(self): + np.random.seed(1234) + + def test_definition(self): + x = np.array([1,2,3,4+1j,1,2,3,4+2j], self.cdt) + y = ifft(x) + y1 = direct_idft(x) + assert_equal(y.dtype, self.cdt) + assert_array_almost_equal(y,y1) + + x = np.array([1,2,3,4+0j,5], self.cdt) + assert_array_almost_equal(ifft(x),direct_idft(x)) + + def test_definition_real(self): + x = np.array([1,2,3,4,1,2,3,4], self.rdt) + y = ifft(x) + assert_equal(y.dtype, self.cdt) + y1 = direct_idft(x) + assert_array_almost_equal(y,y1) + + x = np.array([1,2,3,4,5], dtype=self.rdt) + assert_equal(y.dtype, self.cdt) + assert_array_almost_equal(ifft(x),direct_idft(x)) + + def test_djbfft(self): + for i in range(2,14): + n = 2**i + x = np.arange(n) + y = ifft(x.astype(self.cdt)) + y2 = numpy.fft.ifft(x.astype(self.cdt)) + assert_allclose(y,y2, rtol=self.rtol, atol=self.atol) + y = ifft(x) + assert_allclose(y,y2, rtol=self.rtol, atol=self.atol) + + def test_random_complex(self): + for size in [1,51,111,100,200,64,128,256,1024]: + x = random([size]).astype(self.cdt) + x = random([size]).astype(self.cdt) + 1j*x + y1 = ifft(fft(x)) + y2 = fft(ifft(x)) + assert_equal(y1.dtype, self.cdt) + assert_equal(y2.dtype, self.cdt) + assert_array_almost_equal(y1, x) + assert_array_almost_equal(y2, x) + + def test_random_real(self): + for size in [1,51,111,100,200,64,128,256,1024]: + x = random([size]).astype(self.rdt) + y1 = ifft(fft(x)) + y2 = fft(ifft(x)) + assert_equal(y1.dtype, self.cdt) + assert_equal(y2.dtype, self.cdt) + assert_array_almost_equal(y1, x) + assert_array_almost_equal(y2, x) + + def test_size_accuracy(self): + # Sanity check for the accuracy for prime and non-prime sized inputs + for size in LARGE_COMPOSITE_SIZES + LARGE_PRIME_SIZES: + np.random.seed(1234) + x = np.random.rand(size).astype(self.rdt) + y = ifft(fft(x)) + _assert_close_in_norm(x, y, self.rtol, size, self.rdt) + y = fft(ifft(x)) + _assert_close_in_norm(x, y, self.rtol, size, self.rdt) + + x = (x + 1j*np.random.rand(size)).astype(self.cdt) + y = ifft(fft(x)) + _assert_close_in_norm(x, y, self.rtol, size, self.rdt) + y = fft(ifft(x)) + _assert_close_in_norm(x, y, self.rtol, size, self.rdt) + + def test_invalid_sizes(self): + assert_raises(ValueError, ifft, []) + assert_raises(ValueError, ifft, [[1,1],[2,2]], -5) + + +@pytest.mark.skipif(np.longdouble is np.float64, + reason="Long double is aliased to double") +class TestLongDoubleIFFT(_TestIFFTBase): + def setup_method(self): + self.cdt = np.clongdouble + self.rdt = np.longdouble + self.rtol = 1e-10 + self.atol = 1e-10 + + +class TestDoubleIFFT(_TestIFFTBase): + def setup_method(self): + self.cdt = np.complex128 + self.rdt = np.float64 + self.rtol = 1e-10 + self.atol = 1e-10 + + +class TestSingleIFFT(_TestIFFTBase): + def setup_method(self): + self.cdt = np.complex64 + self.rdt = np.float32 + self.rtol = 1e-5 + self.atol = 1e-4 + + +class _TestRFFTBase: + def setup_method(self): + np.random.seed(1234) + + def test_definition(self): + for t in [[1, 2, 3, 4, 1, 2, 3, 4], [1, 2, 3, 4, 1, 2, 3, 4, 5]]: + x = np.array(t, dtype=self.rdt) + y = rfft(x) + y1 = direct_rdft(x) + assert_array_almost_equal(y,y1) + assert_equal(y.dtype, self.cdt) + + def test_djbfft(self): + for i in range(2,14): + n = 2**i + x = np.arange(n) + y1 = np.fft.rfft(x) + y = rfft(x) + assert_array_almost_equal(y,y1) + + def test_invalid_sizes(self): + assert_raises(ValueError, rfft, []) + assert_raises(ValueError, rfft, [[1,1],[2,2]], -5) + + def test_complex_input(self): + x = np.zeros(10, dtype=self.cdt) + with assert_raises(TypeError, match="x must be a real sequence"): + rfft(x) + + # See gh-5790 + class MockSeries: + def __init__(self, data): + self.data = np.asarray(data) + + def __getattr__(self, item): + try: + return getattr(self.data, item) + except AttributeError as e: + raise AttributeError("'MockSeries' object " + f"has no attribute '{item}'") from e + + def test_non_ndarray_with_dtype(self): + x = np.array([1., 2., 3., 4., 5.]) + xs = _TestRFFTBase.MockSeries(x) + + expected = [1, 2, 3, 4, 5] + rfft(xs) + + # Data should not have been overwritten + assert_equal(x, expected) + assert_equal(xs.data, expected) + +@pytest.mark.skipif(np.longdouble is np.float64, + reason="Long double is aliased to double") +class TestRFFTLongDouble(_TestRFFTBase): + def setup_method(self): + self.cdt = np.clongdouble + self.rdt = np.longdouble + + +class TestRFFTDouble(_TestRFFTBase): + def setup_method(self): + self.cdt = np.complex128 + self.rdt = np.float64 + + +class TestRFFTSingle(_TestRFFTBase): + def setup_method(self): + self.cdt = np.complex64 + self.rdt = np.float32 + + +class _TestIRFFTBase: + def setup_method(self): + np.random.seed(1234) + + def test_definition(self): + x1 = [1,2+3j,4+1j,1+2j,3+4j] + x1_1 = [1,2+3j,4+1j,2+3j,4,2-3j,4-1j,2-3j] + x1 = x1_1[:5] + x2_1 = [1,2+3j,4+1j,2+3j,4+5j,4-5j,2-3j,4-1j,2-3j] + x2 = x2_1[:5] + + def _test(x, xr): + y = irfft(np.array(x, dtype=self.cdt), n=len(xr)) + y1 = direct_irdft(x, len(xr)) + assert_equal(y.dtype, self.rdt) + assert_array_almost_equal(y,y1, decimal=self.ndec) + assert_array_almost_equal(y,ifft(xr), decimal=self.ndec) + + _test(x1, x1_1) + _test(x2, x2_1) + + def test_djbfft(self): + for i in range(2,14): + n = 2**i + x = np.arange(-1, n, 2) + 1j * np.arange(0, n+1, 2) + x[0] = 0 + if n % 2 == 0: + x[-1] = np.real(x[-1]) + y1 = np.fft.irfft(x) + y = irfft(x) + assert_array_almost_equal(y,y1) + + def test_random_real(self): + for size in [1,51,111,100,200,64,128,256,1024]: + x = random([size]).astype(self.rdt) + y1 = irfft(rfft(x), n=size) + y2 = rfft(irfft(x, n=(size*2-1))) + assert_equal(y1.dtype, self.rdt) + assert_equal(y2.dtype, self.cdt) + assert_array_almost_equal(y1, x, decimal=self.ndec, err_msg=f"size={size}") + assert_array_almost_equal(y2, x, decimal=self.ndec, err_msg=f"size={size}") + + def test_size_accuracy(self): + # Sanity check for the accuracy for prime and non-prime sized inputs + if self.rdt == np.float32: + rtol = 1e-5 + elif self.rdt == np.float64: + rtol = 1e-10 + + for size in LARGE_COMPOSITE_SIZES + LARGE_PRIME_SIZES: + np.random.seed(1234) + x = np.random.rand(size).astype(self.rdt) + y = irfft(rfft(x), len(x)) + _assert_close_in_norm(x, y, rtol, size, self.rdt) + y = rfft(irfft(x, 2 * len(x) - 1)) + _assert_close_in_norm(x, y, rtol, size, self.rdt) + + def test_invalid_sizes(self): + assert_raises(ValueError, irfft, []) + assert_raises(ValueError, irfft, [[1,1],[2,2]], -5) + + +# self.ndec is bogus; we should have a assert_array_approx_equal for number of +# significant digits + +@pytest.mark.skipif(np.longdouble is np.float64, + reason="Long double is aliased to double") +class TestIRFFTLongDouble(_TestIRFFTBase): + def setup_method(self): + self.cdt = np.complex128 + self.rdt = np.float64 + self.ndec = 14 + + +class TestIRFFTDouble(_TestIRFFTBase): + def setup_method(self): + self.cdt = np.complex128 + self.rdt = np.float64 + self.ndec = 14 + + +class TestIRFFTSingle(_TestIRFFTBase): + def setup_method(self): + self.cdt = np.complex64 + self.rdt = np.float32 + self.ndec = 5 + + +class TestFftnSingle: + def setup_method(self): + np.random.seed(1234) + + def test_definition(self): + x = [[1, 2, 3], + [4, 5, 6], + [7, 8, 9]] + y = fftn(np.array(x, np.float32)) + assert_(y.dtype == np.complex64, + msg="double precision output with single precision") + + y_r = np.array(fftn(x), np.complex64) + assert_array_almost_equal_nulp(y, y_r) + + @pytest.mark.parametrize('size', SMALL_COMPOSITE_SIZES + SMALL_PRIME_SIZES) + def test_size_accuracy_small(self, size): + rng = np.random.default_rng(1234) + x = rng.random((size, size)) + 1j * rng.random((size, size)) + y1 = fftn(x.real.astype(np.float32)) + y2 = fftn(x.real.astype(np.float64)).astype(np.complex64) + + assert_equal(y1.dtype, np.complex64) + assert_array_almost_equal_nulp(y1, y2, 2000) + + @pytest.mark.parametrize('size', LARGE_COMPOSITE_SIZES + LARGE_PRIME_SIZES) + def test_size_accuracy_large(self, size): + rng = np.random.default_rng(1234) + x = rng.random((size, 3)) + 1j * rng.random((size, 3)) + y1 = fftn(x.real.astype(np.float32)) + y2 = fftn(x.real.astype(np.float64)).astype(np.complex64) + + assert_equal(y1.dtype, np.complex64) + assert_array_almost_equal_nulp(y1, y2, 2000) + + def test_definition_float16(self): + x = [[1, 2, 3], + [4, 5, 6], + [7, 8, 9]] + y = fftn(np.array(x, np.float16)) + assert_equal(y.dtype, np.complex64) + y_r = np.array(fftn(x), np.complex64) + assert_array_almost_equal_nulp(y, y_r) + + @pytest.mark.parametrize('size', SMALL_COMPOSITE_SIZES + SMALL_PRIME_SIZES) + def test_float16_input_small(self, size): + rng = np.random.default_rng(1234) + x = rng.random((size, size)) + 1j*rng.random((size, size)) + y1 = fftn(x.real.astype(np.float16)) + y2 = fftn(x.real.astype(np.float64)).astype(np.complex64) + + assert_equal(y1.dtype, np.complex64) + assert_array_almost_equal_nulp(y1, y2, 5e5) + + @pytest.mark.parametrize('size', LARGE_COMPOSITE_SIZES + LARGE_PRIME_SIZES) + def test_float16_input_large(self, size): + rng = np.random.default_rng(1234) + x = rng.random((size, 3)) + 1j*rng.random((size, 3)) + y1 = fftn(x.real.astype(np.float16)) + y2 = fftn(x.real.astype(np.float64)).astype(np.complex64) + + assert_equal(y1.dtype, np.complex64) + assert_array_almost_equal_nulp(y1, y2, 2e6) + + +class TestFftn: + def setup_method(self): + np.random.seed(1234) + + def test_definition(self): + x = [[1, 2, 3], + [4, 5, 6], + [7, 8, 9]] + y = fftn(x) + assert_array_almost_equal(y, direct_dftn(x)) + + x = random((20, 26)) + assert_array_almost_equal(fftn(x), direct_dftn(x)) + + x = random((5, 4, 3, 20)) + assert_array_almost_equal(fftn(x), direct_dftn(x)) + + def test_axes_argument(self): + # plane == ji_plane, x== kji_space + plane1 = [[1, 2, 3], + [4, 5, 6], + [7, 8, 9]] + plane2 = [[10, 11, 12], + [13, 14, 15], + [16, 17, 18]] + plane3 = [[19, 20, 21], + [22, 23, 24], + [25, 26, 27]] + ki_plane1 = [[1, 2, 3], + [10, 11, 12], + [19, 20, 21]] + ki_plane2 = [[4, 5, 6], + [13, 14, 15], + [22, 23, 24]] + ki_plane3 = [[7, 8, 9], + [16, 17, 18], + [25, 26, 27]] + jk_plane1 = [[1, 10, 19], + [4, 13, 22], + [7, 16, 25]] + jk_plane2 = [[2, 11, 20], + [5, 14, 23], + [8, 17, 26]] + jk_plane3 = [[3, 12, 21], + [6, 15, 24], + [9, 18, 27]] + kj_plane1 = [[1, 4, 7], + [10, 13, 16], [19, 22, 25]] + kj_plane2 = [[2, 5, 8], + [11, 14, 17], [20, 23, 26]] + kj_plane3 = [[3, 6, 9], + [12, 15, 18], [21, 24, 27]] + ij_plane1 = [[1, 4, 7], + [2, 5, 8], + [3, 6, 9]] + ij_plane2 = [[10, 13, 16], + [11, 14, 17], + [12, 15, 18]] + ij_plane3 = [[19, 22, 25], + [20, 23, 26], + [21, 24, 27]] + ik_plane1 = [[1, 10, 19], + [2, 11, 20], + [3, 12, 21]] + ik_plane2 = [[4, 13, 22], + [5, 14, 23], + [6, 15, 24]] + ik_plane3 = [[7, 16, 25], + [8, 17, 26], + [9, 18, 27]] + ijk_space = [jk_plane1, jk_plane2, jk_plane3] + ikj_space = [kj_plane1, kj_plane2, kj_plane3] + jik_space = [ik_plane1, ik_plane2, ik_plane3] + jki_space = [ki_plane1, ki_plane2, ki_plane3] + kij_space = [ij_plane1, ij_plane2, ij_plane3] + x = array([plane1, plane2, plane3]) + + assert_array_almost_equal(fftn(x), + fftn(x, axes=(-3, -2, -1))) # kji_space + assert_array_almost_equal(fftn(x), fftn(x, axes=(0, 1, 2))) + assert_array_almost_equal(fftn(x, axes=(0, 2)), fftn(x, axes=(0, -1))) + y = fftn(x, axes=(2, 1, 0)) # ijk_space + assert_array_almost_equal(swapaxes(y, -1, -3), fftn(ijk_space)) + y = fftn(x, axes=(2, 0, 1)) # ikj_space + assert_array_almost_equal(swapaxes(swapaxes(y, -1, -3), -1, -2), + fftn(ikj_space)) + y = fftn(x, axes=(1, 2, 0)) # jik_space + assert_array_almost_equal(swapaxes(swapaxes(y, -1, -3), -3, -2), + fftn(jik_space)) + y = fftn(x, axes=(1, 0, 2)) # jki_space + assert_array_almost_equal(swapaxes(y, -2, -3), fftn(jki_space)) + y = fftn(x, axes=(0, 2, 1)) # kij_space + assert_array_almost_equal(swapaxes(y, -2, -1), fftn(kij_space)) + + y = fftn(x, axes=(-2, -1)) # ji_plane + assert_array_almost_equal(fftn(plane1), y[0]) + assert_array_almost_equal(fftn(plane2), y[1]) + assert_array_almost_equal(fftn(plane3), y[2]) + + y = fftn(x, axes=(1, 2)) # ji_plane + assert_array_almost_equal(fftn(plane1), y[0]) + assert_array_almost_equal(fftn(plane2), y[1]) + assert_array_almost_equal(fftn(plane3), y[2]) + + y = fftn(x, axes=(-3, -2)) # kj_plane + assert_array_almost_equal(fftn(x[:, :, 0]), y[:, :, 0]) + assert_array_almost_equal(fftn(x[:, :, 1]), y[:, :, 1]) + assert_array_almost_equal(fftn(x[:, :, 2]), y[:, :, 2]) + + y = fftn(x, axes=(-3, -1)) # ki_plane + assert_array_almost_equal(fftn(x[:, 0, :]), y[:, 0, :]) + assert_array_almost_equal(fftn(x[:, 1, :]), y[:, 1, :]) + assert_array_almost_equal(fftn(x[:, 2, :]), y[:, 2, :]) + + y = fftn(x, axes=(-1, -2)) # ij_plane + assert_array_almost_equal(fftn(ij_plane1), swapaxes(y[0], -2, -1)) + assert_array_almost_equal(fftn(ij_plane2), swapaxes(y[1], -2, -1)) + assert_array_almost_equal(fftn(ij_plane3), swapaxes(y[2], -2, -1)) + + y = fftn(x, axes=(-1, -3)) # ik_plane + assert_array_almost_equal(fftn(ik_plane1), + swapaxes(y[:, 0, :], -1, -2)) + assert_array_almost_equal(fftn(ik_plane2), + swapaxes(y[:, 1, :], -1, -2)) + assert_array_almost_equal(fftn(ik_plane3), + swapaxes(y[:, 2, :], -1, -2)) + + y = fftn(x, axes=(-2, -3)) # jk_plane + assert_array_almost_equal(fftn(jk_plane1), + swapaxes(y[:, :, 0], -1, -2)) + assert_array_almost_equal(fftn(jk_plane2), + swapaxes(y[:, :, 1], -1, -2)) + assert_array_almost_equal(fftn(jk_plane3), + swapaxes(y[:, :, 2], -1, -2)) + + y = fftn(x, axes=(-1,)) # i_line + for i in range(3): + for j in range(3): + assert_array_almost_equal(fft(x[i, j, :]), y[i, j, :]) + y = fftn(x, axes=(-2,)) # j_line + for i in range(3): + for j in range(3): + assert_array_almost_equal(fft(x[i, :, j]), y[i, :, j]) + y = fftn(x, axes=(0,)) # k_line + for i in range(3): + for j in range(3): + assert_array_almost_equal(fft(x[:, i, j]), y[:, i, j]) + + y = fftn(x, axes=()) # point + assert_array_almost_equal(y, x) + + def test_shape_argument(self): + small_x = [[1, 2, 3], + [4, 5, 6]] + large_x1 = [[1, 2, 3, 0], + [4, 5, 6, 0], + [0, 0, 0, 0], + [0, 0, 0, 0]] + + y = fftn(small_x, s=(4, 4)) + assert_array_almost_equal(y, fftn(large_x1)) + + y = fftn(small_x, s=(3, 4)) + assert_array_almost_equal(y, fftn(large_x1[:-1])) + + def test_shape_axes_argument(self): + small_x = [[1, 2, 3], + [4, 5, 6], + [7, 8, 9]] + large_x1 = array([[1, 2, 3, 0], + [4, 5, 6, 0], + [7, 8, 9, 0], + [0, 0, 0, 0]]) + y = fftn(small_x, s=(4, 4), axes=(-2, -1)) + assert_array_almost_equal(y, fftn(large_x1)) + y = fftn(small_x, s=(4, 4), axes=(-1, -2)) + + assert_array_almost_equal(y, swapaxes( + fftn(swapaxes(large_x1, -1, -2)), -1, -2)) + + def test_shape_axes_argument2(self): + # Change shape of the last axis + x = numpy.random.random((10, 5, 3, 7)) + y = fftn(x, axes=(-1,), s=(8,)) + assert_array_almost_equal(y, fft(x, axis=-1, n=8)) + + # Change shape of an arbitrary axis which is not the last one + x = numpy.random.random((10, 5, 3, 7)) + y = fftn(x, axes=(-2,), s=(8,)) + assert_array_almost_equal(y, fft(x, axis=-2, n=8)) + + # Change shape of axes: cf #244, where shape and axes were mixed up + x = numpy.random.random((4, 4, 2)) + y = fftn(x, axes=(-3, -2), s=(8, 8)) + assert_array_almost_equal(y, + numpy.fft.fftn(x, axes=(-3, -2), s=(8, 8))) + + def test_shape_argument_more(self): + x = zeros((4, 4, 2)) + with assert_raises(ValueError, + match="shape requires more axes than are present"): + fftn(x, s=(8, 8, 2, 1)) + + def test_invalid_sizes(self): + with assert_raises(ValueError, + match="invalid number of data points" + r" \(\[1, 0\]\) specified"): + fftn([[]]) + + with assert_raises(ValueError, + match="invalid number of data points" + r" \(\[4, -3\]\) specified"): + fftn([[1, 1], [2, 2]], (4, -3)) + + def test_no_axes(self): + x = numpy.random.random((2,2,2)) + assert_allclose(fftn(x, axes=[]), x, atol=1e-7) + + def test_regression_244(self): + """FFT returns wrong result with axes parameter.""" + # fftn (and hence fft2) used to break when both axes and shape were used + x = numpy.ones((4, 4, 2)) + y = fftn(x, s=(8, 8), axes=(-3, -2)) + y_r = numpy.fft.fftn(x, s=(8, 8), axes=(-3, -2)) + assert_allclose(y, y_r) + + +class TestIfftn: + dtype = None + cdtype = None + + def setup_method(self): + np.random.seed(1234) + + @pytest.mark.parametrize('dtype,cdtype,maxnlp', + [(np.float64, np.complex128, 2000), + (np.float32, np.complex64, 3500)]) + def test_definition(self, dtype, cdtype, maxnlp): + rng = np.random.default_rng(1234) + x = np.array([[1, 2, 3], + [4, 5, 6], + [7, 8, 9]], dtype=dtype) + y = ifftn(x) + assert_equal(y.dtype, cdtype) + assert_array_almost_equal_nulp(y, direct_idftn(x), maxnlp) + + x = rng.random((20, 26)) + assert_array_almost_equal_nulp(ifftn(x), direct_idftn(x), maxnlp) + + x = rng.random((5, 4, 3, 20)) + assert_array_almost_equal_nulp(ifftn(x), direct_idftn(x), maxnlp) + + @pytest.mark.parametrize('maxnlp', [2000, 3500]) + @pytest.mark.parametrize('size', [1, 2, 51, 32, 64, 92]) + def test_random_complex(self, maxnlp, size): + rng = np.random.default_rng(1234) + x = rng.random([size, size]) + 1j * rng.random([size, size]) + assert_array_almost_equal_nulp(ifftn(fftn(x)), x, maxnlp) + assert_array_almost_equal_nulp(fftn(ifftn(x)), x, maxnlp) + + def test_invalid_sizes(self): + with assert_raises(ValueError, + match="invalid number of data points" + r" \(\[1, 0\]\) specified"): + ifftn([[]]) + + with assert_raises(ValueError, + match="invalid number of data points" + r" \(\[4, -3\]\) specified"): + ifftn([[1, 1], [2, 2]], (4, -3)) + + def test_no_axes(self): + x = numpy.random.random((2,2,2)) + assert_allclose(ifftn(x, axes=[]), x, atol=1e-7) + +class TestRfftn: + dtype = None + cdtype = None + + def setup_method(self): + np.random.seed(1234) + + @pytest.mark.parametrize('dtype,cdtype,maxnlp', + [(np.float64, np.complex128, 2000), + (np.float32, np.complex64, 3500)]) + def test_definition(self, dtype, cdtype, maxnlp): + rng = np.random.default_rng(1234) + x = np.array([[1, 2, 3], + [4, 5, 6], + [7, 8, 9]], dtype=dtype) + y = rfftn(x) + assert_equal(y.dtype, cdtype) + assert_array_almost_equal_nulp(y, direct_rdftn(x), maxnlp) + + x = rng.random((20, 26)) + assert_array_almost_equal_nulp(rfftn(x), direct_rdftn(x), maxnlp) + + x = rng.random((5, 4, 3, 20)) + assert_array_almost_equal_nulp(rfftn(x), direct_rdftn(x), maxnlp) + + @pytest.mark.parametrize('size', [1, 2, 51, 32, 64, 92]) + def test_random(self, size): + rng = np.random.default_rng(1234) + x = rng.random([size, size]) + assert_allclose(irfftn(rfftn(x), x.shape), x, atol=1e-10) + + @pytest.mark.parametrize('func', [rfftn, irfftn]) + def test_invalid_sizes(self, func): + with assert_raises(ValueError, + match="invalid number of data points" + r" \(\[1, 0\]\) specified"): + func([[]]) + + with assert_raises(ValueError, + match="invalid number of data points" + r" \(\[4, -3\]\) specified"): + func([[1, 1], [2, 2]], (4, -3)) + + @pytest.mark.parametrize('func', [rfftn, irfftn]) + def test_no_axes(self, func): + with assert_raises(ValueError, + match="at least 1 axis must be transformed"): + func([], axes=[]) + + def test_complex_input(self): + with assert_raises(TypeError, match="x must be a real sequence"): + rfftn(np.zeros(10, dtype=np.complex64)) + + +class FakeArray: + def __init__(self, data): + self._data = data + self.__array_interface__ = data.__array_interface__ + + +class FakeArray2: + def __init__(self, data): + self._data = data + + def __array__(self, dtype=None, copy=None): + return self._data + +# TODO: Is this test actually valuable? The behavior it's testing shouldn't be +# relied upon by users except for overwrite_x = False +class TestOverwrite: + """Check input overwrite behavior of the FFT functions.""" + + real_dtypes = [np.float32, np.float64, np.longdouble] + dtypes = real_dtypes + [np.complex64, np.complex128, np.clongdouble] + fftsizes = [8, 16, 32] + + def _check(self, x, routine, fftsize, axis, overwrite_x, should_overwrite): + x2 = x.copy() + for fake in [lambda x: x, FakeArray, FakeArray2]: + routine(fake(x2), fftsize, axis, overwrite_x=overwrite_x) + + sig = (f"{routine.__name__}({x.dtype}{x.shape!r}, {fftsize!r}, " + f"axis={axis!r}, overwrite_x={overwrite_x!r})") + if not should_overwrite: + assert_equal(x2, x, err_msg=f"spurious overwrite in {sig}") + + def _check_1d(self, routine, dtype, shape, axis, overwritable_dtypes, + fftsize, overwrite_x): + np.random.seed(1234) + if np.issubdtype(dtype, np.complexfloating): + data = np.random.randn(*shape) + 1j*np.random.randn(*shape) + else: + data = np.random.randn(*shape) + data = data.astype(dtype) + + should_overwrite = (overwrite_x + and dtype in overwritable_dtypes + and fftsize <= shape[axis]) + self._check(data, routine, fftsize, axis, + overwrite_x=overwrite_x, + should_overwrite=should_overwrite) + + @pytest.mark.parametrize('dtype', dtypes) + @pytest.mark.parametrize('fftsize', fftsizes) + @pytest.mark.parametrize('overwrite_x', [True, False]) + @pytest.mark.parametrize('shape,axes', [((16,), -1), + ((16, 2), 0), + ((2, 16), 1)]) + def test_fft_ifft(self, dtype, fftsize, overwrite_x, shape, axes): + overwritable = (np.clongdouble, np.complex128, np.complex64) + self._check_1d(fft, dtype, shape, axes, overwritable, + fftsize, overwrite_x) + self._check_1d(ifft, dtype, shape, axes, overwritable, + fftsize, overwrite_x) + + @pytest.mark.parametrize('dtype', real_dtypes) + @pytest.mark.parametrize('fftsize', fftsizes) + @pytest.mark.parametrize('overwrite_x', [True, False]) + @pytest.mark.parametrize('shape,axes', [((16,), -1), + ((16, 2), 0), + ((2, 16), 1)]) + def test_rfft_irfft(self, dtype, fftsize, overwrite_x, shape, axes): + overwritable = self.real_dtypes + self._check_1d(irfft, dtype, shape, axes, overwritable, + fftsize, overwrite_x) + self._check_1d(rfft, dtype, shape, axes, overwritable, + fftsize, overwrite_x) + + def _check_nd_one(self, routine, dtype, shape, axes, overwritable_dtypes, + overwrite_x): + np.random.seed(1234) + if np.issubdtype(dtype, np.complexfloating): + data = np.random.randn(*shape) + 1j*np.random.randn(*shape) + else: + data = np.random.randn(*shape) + data = data.astype(dtype) + + def fftshape_iter(shp): + if len(shp) <= 0: + yield () + else: + for j in (shp[0]//2, shp[0], shp[0]*2): + for rest in fftshape_iter(shp[1:]): + yield (j,) + rest + + def part_shape(shape, axes): + if axes is None: + return shape + else: + return tuple(np.take(shape, axes)) + + def should_overwrite(data, shape, axes): + s = part_shape(data.shape, axes) + return (overwrite_x and + np.prod(shape) <= np.prod(s) + and dtype in overwritable_dtypes) + + for fftshape in fftshape_iter(part_shape(shape, axes)): + self._check(data, routine, fftshape, axes, + overwrite_x=overwrite_x, + should_overwrite=should_overwrite(data, fftshape, axes)) + if data.ndim > 1: + # check fortran order + self._check(data.T, routine, fftshape, axes, + overwrite_x=overwrite_x, + should_overwrite=should_overwrite( + data.T, fftshape, axes)) + + @pytest.mark.parametrize('dtype', dtypes) + @pytest.mark.parametrize('overwrite_x', [True, False]) + @pytest.mark.parametrize('shape,axes', [((16,), None), + ((16,), (0,)), + ((16, 2), (0,)), + ((2, 16), (1,)), + ((8, 16), None), + ((8, 16), (0, 1)), + ((8, 16, 2), (0, 1)), + ((8, 16, 2), (1, 2)), + ((8, 16, 2), (0,)), + ((8, 16, 2), (1,)), + ((8, 16, 2), (2,)), + ((8, 16, 2), None), + ((8, 16, 2), (0, 1, 2))]) + def test_fftn_ifftn(self, dtype, overwrite_x, shape, axes): + overwritable = (np.clongdouble, np.complex128, np.complex64) + self._check_nd_one(fftn, dtype, shape, axes, overwritable, + overwrite_x) + self._check_nd_one(ifftn, dtype, shape, axes, overwritable, + overwrite_x) + + +@pytest.mark.parametrize('func', [fft, ifft, fftn, ifftn, + rfft, irfft, rfftn, irfftn]) +def test_invalid_norm(func): + x = np.arange(10, dtype=float) + with assert_raises(ValueError, + match='Invalid norm value \'o\', should be' + ' "backward", "ortho" or "forward"'): + func(x, norm='o') + + +@pytest.mark.parametrize('func', [fft, ifft, fftn, ifftn, + irfft, irfftn, hfft, hfftn]) +def test_swapped_byte_order_complex(func): + rng = np.random.RandomState(1234) + x = rng.rand(10) + 1j * rng.rand(10) + assert_allclose(func(swap_byteorder(x)), func(x)) + + +@pytest.mark.parametrize('func', [ihfft, ihfftn, rfft, rfftn]) +def test_swapped_byte_order_real(func): + rng = np.random.RandomState(1234) + x = rng.rand(10) + assert_allclose(func(swap_byteorder(x)), func(x)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/test_real_transforms.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/test_real_transforms.py new file mode 100644 index 0000000000000000000000000000000000000000..16477375397e05ccbf7b87f84d66b1d450dcb3bd --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/_pocketfft/tests/test_real_transforms.py @@ -0,0 +1,506 @@ +from os.path import join, dirname +from collections.abc import Callable +from threading import Lock + +import numpy as np +from numpy.testing import ( + assert_array_almost_equal, assert_equal, assert_allclose) +import pytest +from pytest import raises as assert_raises + +from scipy.fft._pocketfft.realtransforms import ( + dct, idct, dst, idst, dctn, idctn, dstn, idstn) + +fftpack_test_dir = join(dirname(__file__), '..', '..', '..', 'fftpack', 'tests') + +MDATA_COUNT = 8 +FFTWDATA_COUNT = 14 + + +def is_longdouble_binary_compatible(): + try: + one = np.frombuffer( + b'\x00\x00\x00\x00\x00\x00\x00\x80\xff\x3f\x00\x00\x00\x00\x00\x00', + dtype=' decimal +dec_map: DecMapType = { + # DCT + (dct, np.float64, 1): 13, + (dct, np.float32, 1): 6, + + (dct, np.float64, 2): 14, + (dct, np.float32, 2): 5, + + (dct, np.float64, 3): 14, + (dct, np.float32, 3): 5, + + (dct, np.float64, 4): 13, + (dct, np.float32, 4): 6, + + # IDCT + (idct, np.float64, 1): 14, + (idct, np.float32, 1): 6, + + (idct, np.float64, 2): 14, + (idct, np.float32, 2): 5, + + (idct, np.float64, 3): 14, + (idct, np.float32, 3): 5, + + (idct, np.float64, 4): 14, + (idct, np.float32, 4): 6, + + # DST + (dst, np.float64, 1): 13, + (dst, np.float32, 1): 6, + + (dst, np.float64, 2): 14, + (dst, np.float32, 2): 6, + + (dst, np.float64, 3): 14, + (dst, np.float32, 3): 7, + + (dst, np.float64, 4): 13, + (dst, np.float32, 4): 5, + + # IDST + (idst, np.float64, 1): 14, + (idst, np.float32, 1): 6, + + (idst, np.float64, 2): 14, + (idst, np.float32, 2): 6, + + (idst, np.float64, 3): 14, + (idst, np.float32, 3): 6, + + (idst, np.float64, 4): 14, + (idst, np.float32, 4): 6, +} + +for k,v in dec_map.copy().items(): + if k[1] == np.float64: + dec_map[(k[0], np.longdouble, k[2])] = v + elif k[1] == np.float32: + dec_map[(k[0], int, k[2])] = v + + +@pytest.mark.parametrize('rdt', [np.longdouble, np.float64, np.float32, int]) +@pytest.mark.parametrize('type', [1, 2, 3, 4]) +class TestDCT: + def test_definition(self, rdt, type, fftwdata_size, + reference_data, ref_lock): + with ref_lock: + x, yr, dt = fftw_dct_ref(type, fftwdata_size, rdt, reference_data) + y = dct(x, type=type) + assert_equal(y.dtype, dt) + dec = dec_map[(dct, rdt, type)] + assert_allclose(y, yr, rtol=0., atol=np.max(yr)*10**(-dec)) + + @pytest.mark.parametrize('size', [7, 8, 9, 16, 32, 64]) + def test_axis(self, rdt, type, size): + nt = 2 + dec = dec_map[(dct, rdt, type)] + x = np.random.randn(nt, size) + y = dct(x, type=type) + for j in range(nt): + assert_array_almost_equal(y[j], dct(x[j], type=type), + decimal=dec) + + x = x.T + y = dct(x, axis=0, type=type) + for j in range(nt): + assert_array_almost_equal(y[:,j], dct(x[:,j], type=type), + decimal=dec) + + +@pytest.mark.parametrize('rdt', [np.longdouble, np.float64, np.float32, int]) +def test_dct1_definition_ortho(rdt, mdata_x): + # Test orthornomal mode. + dec = dec_map[(dct, rdt, 1)] + x = np.array(mdata_x, dtype=rdt) + dt = np.result_type(np.float32, rdt) + y = dct(x, norm='ortho', type=1) + y2 = naive_dct1(x, norm='ortho') + assert_equal(y.dtype, dt) + assert_allclose(y, y2, rtol=0., atol=np.max(y2)*10**(-dec)) + + +@pytest.mark.parametrize('rdt', [np.longdouble, np.float64, np.float32, int]) +def test_dct2_definition_matlab(mdata_xy, rdt): + # Test correspondence with matlab (orthornomal mode). + dt = np.result_type(np.float32, rdt) + x = np.array(mdata_xy[0], dtype=dt) + + yr = mdata_xy[1] + y = dct(x, norm="ortho", type=2) + dec = dec_map[(dct, rdt, 2)] + assert_equal(y.dtype, dt) + assert_array_almost_equal(y, yr, decimal=dec) + + +@pytest.mark.parametrize('rdt', [np.longdouble, np.float64, np.float32, int]) +def test_dct3_definition_ortho(mdata_x, rdt): + # Test orthornomal mode. + x = np.array(mdata_x, dtype=rdt) + dt = np.result_type(np.float32, rdt) + y = dct(x, norm='ortho', type=2) + xi = dct(y, norm="ortho", type=3) + dec = dec_map[(dct, rdt, 3)] + assert_equal(xi.dtype, dt) + assert_array_almost_equal(xi, x, decimal=dec) + + +@pytest.mark.parametrize('rdt', [np.longdouble, np.float64, np.float32, int]) +def test_dct4_definition_ortho(mdata_x, rdt): + # Test orthornomal mode. + x = np.array(mdata_x, dtype=rdt) + dt = np.result_type(np.float32, rdt) + y = dct(x, norm='ortho', type=4) + y2 = naive_dct4(x, norm='ortho') + dec = dec_map[(dct, rdt, 4)] + assert_equal(y.dtype, dt) + assert_allclose(y, y2, rtol=0., atol=np.max(y2)*10**(-dec)) + + +@pytest.mark.parametrize('rdt', [np.longdouble, np.float64, np.float32, int]) +@pytest.mark.parametrize('type', [1, 2, 3, 4]) +def test_idct_definition(fftwdata_size, rdt, type, reference_data, ref_lock): + with ref_lock: + xr, yr, dt = fftw_dct_ref(type, fftwdata_size, rdt, reference_data) + x = idct(yr, type=type) + dec = dec_map[(idct, rdt, type)] + assert_equal(x.dtype, dt) + assert_allclose(x, xr, rtol=0., atol=np.max(xr)*10**(-dec)) + + +@pytest.mark.parametrize('rdt', [np.longdouble, np.float64, np.float32, int]) +@pytest.mark.parametrize('type', [1, 2, 3, 4]) +def test_definition(fftwdata_size, rdt, type, reference_data, ref_lock): + with ref_lock: + xr, yr, dt = fftw_dst_ref(type, fftwdata_size, rdt, reference_data) + y = dst(xr, type=type) + dec = dec_map[(dst, rdt, type)] + assert_equal(y.dtype, dt) + assert_allclose(y, yr, rtol=0., atol=np.max(yr)*10**(-dec)) + + +@pytest.mark.parametrize('rdt', [np.longdouble, np.float64, np.float32, int]) +def test_dst1_definition_ortho(rdt, mdata_x): + # Test orthornomal mode. + dec = dec_map[(dst, rdt, 1)] + x = np.array(mdata_x, dtype=rdt) + dt = np.result_type(np.float32, rdt) + y = dst(x, norm='ortho', type=1) + y2 = naive_dst1(x, norm='ortho') + assert_equal(y.dtype, dt) + assert_allclose(y, y2, rtol=0., atol=np.max(y2)*10**(-dec)) + + +@pytest.mark.parametrize('rdt', [np.longdouble, np.float64, np.float32, int]) +def test_dst4_definition_ortho(rdt, mdata_x): + # Test orthornomal mode. + dec = dec_map[(dst, rdt, 4)] + x = np.array(mdata_x, dtype=rdt) + dt = np.result_type(np.float32, rdt) + y = dst(x, norm='ortho', type=4) + y2 = naive_dst4(x, norm='ortho') + assert_equal(y.dtype, dt) + assert_array_almost_equal(y, y2, decimal=dec) + + +@pytest.mark.parametrize('rdt', [np.longdouble, np.float64, np.float32, int]) +@pytest.mark.parametrize('type', [1, 2, 3, 4]) +def test_idst_definition(fftwdata_size, rdt, type, reference_data, ref_lock): + with ref_lock: + xr, yr, dt = fftw_dst_ref(type, fftwdata_size, rdt, reference_data) + x = idst(yr, type=type) + dec = dec_map[(idst, rdt, type)] + assert_equal(x.dtype, dt) + assert_allclose(x, xr, rtol=0., atol=np.max(xr)*10**(-dec)) + + +@pytest.mark.parametrize('routine', [dct, dst, idct, idst]) +@pytest.mark.parametrize('dtype', [np.float32, np.float64, np.longdouble]) +@pytest.mark.parametrize('shape, axis', [ + ((16,), -1), ((16, 2), 0), ((2, 16), 1) +]) +@pytest.mark.parametrize('type', [1, 2, 3, 4]) +@pytest.mark.parametrize('overwrite_x', [True, False]) +@pytest.mark.parametrize('norm', [None, 'ortho']) +def test_overwrite(routine, dtype, shape, axis, type, norm, overwrite_x): + # Check input overwrite behavior + np.random.seed(1234) + if np.issubdtype(dtype, np.complexfloating): + x = np.random.randn(*shape) + 1j*np.random.randn(*shape) + else: + x = np.random.randn(*shape) + x = x.astype(dtype) + x2 = x.copy() + routine(x2, type, None, axis, norm, overwrite_x=overwrite_x) + + sig = (f"{routine.__name__}({x.dtype}{x.shape!r}, {None!r}, axis={axis!r}, " + f"overwrite_x={overwrite_x!r})") + if not overwrite_x: + assert_equal(x2, x, err_msg=f"spurious overwrite in {sig}") + + +class Test_DCTN_IDCTN: + dec = 14 + dct_type = [1, 2, 3, 4] + norms = [None, 'backward', 'ortho', 'forward'] + rstate = np.random.RandomState(1234) + shape = (32, 16) + data = rstate.randn(*shape) + + @pytest.mark.parametrize('fforward,finverse', [(dctn, idctn), + (dstn, idstn)]) + @pytest.mark.parametrize('axes', [None, + 1, (1,), [1], + 0, (0,), [0], + (0, 1), [0, 1], + (-2, -1), [-2, -1]]) + @pytest.mark.parametrize('dct_type', dct_type) + @pytest.mark.parametrize('norm', ['ortho']) + def test_axes_round_trip(self, fforward, finverse, axes, dct_type, norm): + tmp = fforward(self.data, type=dct_type, axes=axes, norm=norm) + tmp = finverse(tmp, type=dct_type, axes=axes, norm=norm) + assert_array_almost_equal(self.data, tmp, decimal=12) + + @pytest.mark.parametrize('funcn,func', [(dctn, dct), (dstn, dst)]) + @pytest.mark.parametrize('dct_type', dct_type) + @pytest.mark.parametrize('norm', norms) + def test_dctn_vs_2d_reference(self, funcn, func, dct_type, norm): + y1 = funcn(self.data, type=dct_type, axes=None, norm=norm) + y2 = ref_2d(func, self.data, type=dct_type, norm=norm) + assert_array_almost_equal(y1, y2, decimal=11) + + @pytest.mark.parametrize('funcn,func', [(idctn, idct), (idstn, idst)]) + @pytest.mark.parametrize('dct_type', dct_type) + @pytest.mark.parametrize('norm', norms) + def test_idctn_vs_2d_reference(self, funcn, func, dct_type, norm): + fdata = dctn(self.data, type=dct_type, norm=norm) + y1 = funcn(fdata, type=dct_type, norm=norm) + y2 = ref_2d(func, fdata, type=dct_type, norm=norm) + assert_array_almost_equal(y1, y2, decimal=11) + + @pytest.mark.parametrize('fforward,finverse', [(dctn, idctn), + (dstn, idstn)]) + def test_axes_and_shape(self, fforward, finverse): + with assert_raises(ValueError, + match="when given, axes and shape arguments" + " have to be of the same length"): + fforward(self.data, s=self.data.shape[0], axes=(0, 1)) + + with assert_raises(ValueError, + match="when given, axes and shape arguments" + " have to be of the same length"): + fforward(self.data, s=self.data.shape, axes=0) + + @pytest.mark.parametrize('fforward', [dctn, dstn]) + def test_shape(self, fforward): + tmp = fforward(self.data, s=(128, 128), axes=None) + assert_equal(tmp.shape, (128, 128)) + + @pytest.mark.parametrize('fforward,finverse', [(dctn, idctn), + (dstn, idstn)]) + @pytest.mark.parametrize('axes', [1, (1,), [1], + 0, (0,), [0]]) + def test_shape_is_none_with_axes(self, fforward, finverse, axes): + tmp = fforward(self.data, s=None, axes=axes, norm='ortho') + tmp = finverse(tmp, s=None, axes=axes, norm='ortho') + assert_array_almost_equal(self.data, tmp, decimal=self.dec) + + +@pytest.mark.parametrize('func', [dct, dctn, idct, idctn, + dst, dstn, idst, idstn]) +def test_swapped_byte_order(func): + rng = np.random.RandomState(1234) + x = rng.rand(10) + swapped_dt = x.dtype.newbyteorder('S') + assert_allclose(func(x.astype(swapped_dt)), func(x)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a72d28a7b8fbde49e8e1b8b1f2ea1d4bbaa39fd7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/mock_backend.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/mock_backend.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7f259feb6c85b3c49bffd75b6c9a997ab1bde481 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/mock_backend.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_backend.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_backend.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0e9c03bfdbc806da5dea8b0bc12fe097198dccbd Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_backend.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_basic.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_basic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9063c5d5f5b710f93dddbb0cdc262367b2a4a7de Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_basic.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_fftlog.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_fftlog.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1f61b5b90a3f71cd7bbb96107d890e1c84016fea Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_fftlog.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_helper.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_helper.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..325de4b5613163c3f5f5acdbc70237183e044fe5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_helper.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_multithreading.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_multithreading.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b22f2adff8e3bde8dacae17583fe4bfb21e702a3 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_multithreading.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_real_transforms.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_real_transforms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d152daede10716b588d58fa98e3313a8047d13c2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/__pycache__/test_real_transforms.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/mock_backend.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/mock_backend.py new file mode 100644 index 0000000000000000000000000000000000000000..48a7d2b3b50501b84f7c18e366ad2e66782b4ab6 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/mock_backend.py @@ -0,0 +1,96 @@ +import numpy as np +import scipy.fft +import threading + +class _MockFunction: + def __init__(self, return_value = None): + self.number_calls = threading.local() + self.return_value = return_value + self.last_args = threading.local() + + def __call__(self, *args, **kwargs): + if not hasattr(self.number_calls, 'c'): + self.number_calls.c = 0 + + self.number_calls.c += 1 + self.last_args.l = (args, kwargs) + return self.return_value + + +fft = _MockFunction(np.random.random(10)) +fft2 = _MockFunction(np.random.random(10)) +fftn = _MockFunction(np.random.random(10)) + +ifft = _MockFunction(np.random.random(10)) +ifft2 = _MockFunction(np.random.random(10)) +ifftn = _MockFunction(np.random.random(10)) + +rfft = _MockFunction(np.random.random(10)) +rfft2 = _MockFunction(np.random.random(10)) +rfftn = _MockFunction(np.random.random(10)) + +irfft = _MockFunction(np.random.random(10)) +irfft2 = _MockFunction(np.random.random(10)) +irfftn = _MockFunction(np.random.random(10)) + +hfft = _MockFunction(np.random.random(10)) +hfft2 = _MockFunction(np.random.random(10)) +hfftn = _MockFunction(np.random.random(10)) + +ihfft = _MockFunction(np.random.random(10)) +ihfft2 = _MockFunction(np.random.random(10)) +ihfftn = _MockFunction(np.random.random(10)) + +dct = _MockFunction(np.random.random(10)) +idct = _MockFunction(np.random.random(10)) +dctn = _MockFunction(np.random.random(10)) +idctn = _MockFunction(np.random.random(10)) + +dst = _MockFunction(np.random.random(10)) +idst = _MockFunction(np.random.random(10)) +dstn = _MockFunction(np.random.random(10)) +idstn = _MockFunction(np.random.random(10)) + +fht = _MockFunction(np.random.random(10)) +ifht = _MockFunction(np.random.random(10)) + + +__ua_domain__ = "numpy.scipy.fft" + + +_implements = { + scipy.fft.fft: fft, + scipy.fft.fft2: fft2, + scipy.fft.fftn: fftn, + scipy.fft.ifft: ifft, + scipy.fft.ifft2: ifft2, + scipy.fft.ifftn: ifftn, + scipy.fft.rfft: rfft, + scipy.fft.rfft2: rfft2, + scipy.fft.rfftn: rfftn, + scipy.fft.irfft: irfft, + scipy.fft.irfft2: irfft2, + scipy.fft.irfftn: irfftn, + scipy.fft.hfft: hfft, + scipy.fft.hfft2: hfft2, + scipy.fft.hfftn: hfftn, + scipy.fft.ihfft: ihfft, + scipy.fft.ihfft2: ihfft2, + scipy.fft.ihfftn: ihfftn, + scipy.fft.dct: dct, + scipy.fft.idct: idct, + scipy.fft.dctn: dctn, + scipy.fft.idctn: idctn, + scipy.fft.dst: dst, + scipy.fft.idst: idst, + scipy.fft.dstn: dstn, + scipy.fft.idstn: idstn, + scipy.fft.fht: fht, + scipy.fft.ifht: ifht +} + + +def __ua_function__(method, args, kwargs): + fn = _implements.get(method) + return (fn(*args, **kwargs) if fn is not None + else NotImplemented) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_backend.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_backend.py new file mode 100644 index 0000000000000000000000000000000000000000..933e9c0302d46faf33b3dc015d58996e3e46c058 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_backend.py @@ -0,0 +1,98 @@ +from functools import partial + +import numpy as np +import scipy.fft +from scipy.fft import _fftlog, _pocketfft, set_backend +from scipy.fft.tests import mock_backend + +from numpy.testing import assert_allclose, assert_equal +import pytest + +fnames = ('fft', 'fft2', 'fftn', + 'ifft', 'ifft2', 'ifftn', + 'rfft', 'rfft2', 'rfftn', + 'irfft', 'irfft2', 'irfftn', + 'dct', 'idct', 'dctn', 'idctn', + 'dst', 'idst', 'dstn', 'idstn', + 'fht', 'ifht') + +np_funcs = (np.fft.fft, np.fft.fft2, np.fft.fftn, + np.fft.ifft, np.fft.ifft2, np.fft.ifftn, + np.fft.rfft, np.fft.rfft2, np.fft.rfftn, + np.fft.irfft, np.fft.irfft2, np.fft.irfftn, + np.fft.hfft, _pocketfft.hfft2, _pocketfft.hfftn, # np has no hfftn + np.fft.ihfft, _pocketfft.ihfft2, _pocketfft.ihfftn, + _pocketfft.dct, _pocketfft.idct, _pocketfft.dctn, _pocketfft.idctn, + _pocketfft.dst, _pocketfft.idst, _pocketfft.dstn, _pocketfft.idstn, + # must provide required kwargs for fht, ifht + partial(_fftlog.fht, dln=2, mu=0.5), + partial(_fftlog.ifht, dln=2, mu=0.5)) + +funcs = (scipy.fft.fft, scipy.fft.fft2, scipy.fft.fftn, + scipy.fft.ifft, scipy.fft.ifft2, scipy.fft.ifftn, + scipy.fft.rfft, scipy.fft.rfft2, scipy.fft.rfftn, + scipy.fft.irfft, scipy.fft.irfft2, scipy.fft.irfftn, + scipy.fft.hfft, scipy.fft.hfft2, scipy.fft.hfftn, + scipy.fft.ihfft, scipy.fft.ihfft2, scipy.fft.ihfftn, + scipy.fft.dct, scipy.fft.idct, scipy.fft.dctn, scipy.fft.idctn, + scipy.fft.dst, scipy.fft.idst, scipy.fft.dstn, scipy.fft.idstn, + # must provide required kwargs for fht, ifht + partial(scipy.fft.fht, dln=2, mu=0.5), + partial(scipy.fft.ifht, dln=2, mu=0.5)) + +mocks = (mock_backend.fft, mock_backend.fft2, mock_backend.fftn, + mock_backend.ifft, mock_backend.ifft2, mock_backend.ifftn, + mock_backend.rfft, mock_backend.rfft2, mock_backend.rfftn, + mock_backend.irfft, mock_backend.irfft2, mock_backend.irfftn, + mock_backend.hfft, mock_backend.hfft2, mock_backend.hfftn, + mock_backend.ihfft, mock_backend.ihfft2, mock_backend.ihfftn, + mock_backend.dct, mock_backend.idct, + mock_backend.dctn, mock_backend.idctn, + mock_backend.dst, mock_backend.idst, + mock_backend.dstn, mock_backend.idstn, + mock_backend.fht, mock_backend.ifht) + + +@pytest.mark.parametrize("func, np_func, mock", zip(funcs, np_funcs, mocks)) +def test_backend_call(func, np_func, mock): + x = np.arange(20).reshape((10,2)) + answer = np_func(x.astype(np.float64)) + assert_allclose(func(x), answer, atol=1e-10) + + with set_backend(mock_backend, only=True): + mock.number_calls.c = 0 + y = func(x) + assert_equal(y, mock.return_value) + assert_equal(mock.number_calls.c, 1) + + assert_allclose(func(x), answer, atol=1e-10) + + +plan_funcs = (scipy.fft.fft, scipy.fft.fft2, scipy.fft.fftn, + scipy.fft.ifft, scipy.fft.ifft2, scipy.fft.ifftn, + scipy.fft.rfft, scipy.fft.rfft2, scipy.fft.rfftn, + scipy.fft.irfft, scipy.fft.irfft2, scipy.fft.irfftn, + scipy.fft.hfft, scipy.fft.hfft2, scipy.fft.hfftn, + scipy.fft.ihfft, scipy.fft.ihfft2, scipy.fft.ihfftn) + +plan_mocks = (mock_backend.fft, mock_backend.fft2, mock_backend.fftn, + mock_backend.ifft, mock_backend.ifft2, mock_backend.ifftn, + mock_backend.rfft, mock_backend.rfft2, mock_backend.rfftn, + mock_backend.irfft, mock_backend.irfft2, mock_backend.irfftn, + mock_backend.hfft, mock_backend.hfft2, mock_backend.hfftn, + mock_backend.ihfft, mock_backend.ihfft2, mock_backend.ihfftn) + + +@pytest.mark.parametrize("func, mock", zip(plan_funcs, plan_mocks)) +def test_backend_plan(func, mock): + x = np.arange(20).reshape((10, 2)) + + with pytest.raises(NotImplementedError, match='precomputed plan'): + func(x, plan='foo') + + with set_backend(mock_backend, only=True): + mock.number_calls.c = 0 + y = func(x, plan='foo') + assert_equal(y, mock.return_value) + assert_equal(mock.number_calls.c, 1) + assert_equal(mock.last_args.l[1]['plan'], 'foo') diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_basic.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_basic.py new file mode 100644 index 0000000000000000000000000000000000000000..8d25baba624de6a639b815cc6bf15cddf5cdac69 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_basic.py @@ -0,0 +1,549 @@ +import queue +import threading +import multiprocessing +import numpy as np +import pytest +from numpy.random import random +from numpy.testing import assert_array_almost_equal, assert_allclose +from pytest import raises as assert_raises +import scipy.fft as fft +from scipy._lib._array_api import ( + is_numpy, xp_size, xp_assert_close, xp_assert_equal, make_xp_test_case, + make_xp_pytest_param +) + +lazy_xp_modules = [fft] +skip_xp_backends = pytest.mark.skip_xp_backends + + +# Expected input dtypes. Note that `scipy.fft` is more flexible for numpy, +# but for C2C transforms like `fft.fft`, the array API standard only mandates +# that complex dtypes should work, float32/float64 aren't guaranteed to. +def get_expected_input_dtype(func, xp): + # use __name__ so that `lazy_xp_function` doesn't break things + if func.__name__ in ["fft", "fftn", "fft2", "ifft", "ifftn", "ifft2", "hfft", + "hfftn", "hfft2", "irfft", "irfftn", "irfft2"]: + dtype = xp.complex128 + elif func.__name__ in ["rfft", "rfftn", "rfft2", "ihfft", "ihfftn", "ihfft2"]: + dtype = xp.float64 + else: + raise ValueError(f'Unknown FFT function: {func}') + + return dtype + + +def fft1(x): + L = len(x) + phase = -2j*np.pi*(np.arange(L)/float(L)) + phase = np.arange(L).reshape(-1, 1) * phase + return np.sum(x*np.exp(phase), axis=1) + + +class TestFFT: + @make_xp_test_case(fft.ifft, fft.fft, fft.rfft, fft.irfft) + def test_identity(self, xp): + maxlen = 512 + x = xp.asarray(random(maxlen) + 1j*random(maxlen)) + xr = xp.asarray(random(maxlen)) + # Check some powers of 2 and some primes + for i in [1, 2, 16, 128, 512, 53, 149, 281, 397]: + xp_assert_close(fft.ifft(fft.fft(x[0:i])), x[0:i]) + xp_assert_close(fft.irfft(fft.rfft(xr[0:i]), i), xr[0:i]) + + @skip_xp_backends(np_only=True, reason='significant overhead for some backends') + def test_identity_extensive(self, xp): + maxlen = 512 + x = xp.asarray(random(maxlen) + 1j*random(maxlen)) + xr = xp.asarray(random(maxlen)) + for i in range(1, maxlen): + xp_assert_close(fft.ifft(fft.fft(x[0:i])), x[0:i]) + xp_assert_close(fft.irfft(fft.rfft(xr[0:i]), i), xr[0:i]) + + @make_xp_test_case(fft.fft) + def test_fft(self, xp): + x = random(30) + 1j*random(30) + expect = xp.asarray(fft1(x)) + x = xp.asarray(x) + xp_assert_close(fft.fft(x), expect) + xp_assert_close(fft.fft(x, norm="backward"), expect) + xp_assert_close(fft.fft(x, norm="ortho"), + expect / xp.sqrt(xp.asarray(30, dtype=xp.float64)),) + xp_assert_close(fft.fft(x, norm="forward"), expect / 30) + + @skip_xp_backends(np_only=True, reason='some backends allow `n=0`') + def test_fft_n(self, xp): + x = xp.asarray([1, 2, 3], dtype=xp.complex128) + assert_raises(ValueError, fft.fft, x, 0) + + @make_xp_test_case(fft.fft, fft.ifft) + def test_ifft(self, xp): + x = xp.asarray(random(30) + 1j*random(30)) + xp_assert_close(fft.ifft(fft.fft(x)), x) + for norm in ["backward", "ortho", "forward"]: + xp_assert_close(fft.ifft(fft.fft(x, norm=norm), norm=norm), x) + + @make_xp_test_case(fft.fft, fft.fft2) + def test_fft2(self, xp): + x = xp.asarray(random((30, 20)) + 1j*random((30, 20))) + expect = fft.fft(fft.fft(x, axis=1), axis=0) + xp_assert_close(fft.fft2(x), expect) + xp_assert_close(fft.fft2(x, norm="backward"), expect) + xp_assert_close(fft.fft2(x, norm="ortho"), + expect / xp.sqrt(xp.asarray(30 * 20, dtype=xp.float64))) + xp_assert_close(fft.fft2(x, norm="forward"), expect / (30 * 20)) + + @make_xp_test_case(fft.ifft, fft.ifft2) + def test_ifft2(self, xp): + x = xp.asarray(random((30, 20)) + 1j*random((30, 20))) + expect = fft.ifft(fft.ifft(x, axis=1), axis=0) + xp_assert_close(fft.ifft2(x), expect) + xp_assert_close(fft.ifft2(x, norm="backward"), expect) + xp_assert_close(fft.ifft2(x, norm="ortho"), + expect * xp.sqrt(xp.asarray(30 * 20, dtype=xp.float64))) + xp_assert_close(fft.ifft2(x, norm="forward"), expect * (30 * 20)) + + @make_xp_test_case(fft.fft, fft.fftn) + def test_fftn(self, xp): + x = xp.asarray(random((30, 20, 10)) + 1j*random((30, 20, 10))) + expect = fft.fft(fft.fft(fft.fft(x, axis=2), axis=1), axis=0) + xp_assert_close(fft.fftn(x), expect) + xp_assert_close(fft.fftn(x, norm="backward"), expect) + xp_assert_close(fft.fftn(x, norm="ortho"), + expect / xp.sqrt(xp.asarray(30 * 20 * 10, dtype=xp.float64))) + xp_assert_close(fft.fftn(x, norm="forward"), expect / (30 * 20 * 10)) + + @make_xp_test_case(fft.ifft, fft.ifftn) + def test_ifftn(self, xp): + x = xp.asarray(random((30, 20, 10)) + 1j*random((30, 20, 10))) + expect = fft.ifft(fft.ifft(fft.ifft(x, axis=2), axis=1), axis=0) + xp_assert_close(fft.ifftn(x), expect, rtol=1e-7) + xp_assert_close(fft.ifftn(x, norm="backward"), expect, rtol=1e-7) + xp_assert_close( + fft.ifftn(x, norm="ortho"), + fft.ifftn(x) * xp.sqrt(xp.asarray(30 * 20 * 10, dtype=xp.float64)) + ) + xp_assert_close(fft.ifftn(x, norm="forward"), + expect * (30 * 20 * 10), + rtol=1e-7) + + @make_xp_test_case(fft.fft, fft.rfft) + def test_rfft(self, xp): + x = xp.asarray(random(29), dtype=xp.float64) + for n in [xp_size(x), 2*xp_size(x)]: + for norm in [None, "backward", "ortho", "forward"]: + xp_assert_close(fft.rfft(x, n=n, norm=norm), + fft.fft(xp.asarray(x, dtype=xp.complex128), + n=n, norm=norm)[:(n//2 + 1)]) + xp_assert_close( + fft.rfft(x, n=n, norm="ortho"), + fft.rfft(x, n=n) / xp.sqrt(xp.asarray(n, dtype=xp.float64)) + ) + + @make_xp_test_case(fft.irfft, fft.rfft) + def test_irfft(self, xp): + x = xp.asarray(random(30)) + xp_assert_close(fft.irfft(fft.rfft(x)), x) + for norm in ["backward", "ortho", "forward"]: + xp_assert_close(fft.irfft(fft.rfft(x, norm=norm), norm=norm), x) + + @make_xp_test_case(fft.rfft2) + def test_rfft2(self, xp): + x = xp.asarray(random((30, 20)), dtype=xp.float64) + expect = fft.fft2(xp.asarray(x, dtype=xp.complex128))[:, :11] + xp_assert_close(fft.rfft2(x), expect) + xp_assert_close(fft.rfft2(x, norm="backward"), expect) + xp_assert_close(fft.rfft2(x, norm="ortho"), + expect / xp.sqrt(xp.asarray(30 * 20, dtype=xp.float64))) + xp_assert_close(fft.rfft2(x, norm="forward"), expect / (30 * 20)) + + @make_xp_test_case(fft.rfft2, fft.irfft2) + def test_irfft2(self, xp): + x = xp.asarray(random((30, 20))) + xp_assert_close(fft.irfft2(fft.rfft2(x)), x) + for norm in ["backward", "ortho", "forward"]: + xp_assert_close(fft.irfft2(fft.rfft2(x, norm=norm), norm=norm), x) + + @make_xp_test_case(fft.fftn, fft.rfftn) + def test_rfftn(self, xp): + x = xp.asarray(random((30, 20, 10)), dtype=xp.float64) + expect = fft.fftn(xp.asarray(x, dtype=xp.complex128))[:, :, :6] + xp_assert_close(fft.rfftn(x), expect) + xp_assert_close(fft.rfftn(x, norm="backward"), expect) + xp_assert_close(fft.rfftn(x, norm="ortho"), + expect / xp.sqrt(xp.asarray(30 * 20 * 10, dtype=xp.float64))) + xp_assert_close(fft.rfftn(x, norm="forward"), expect / (30 * 20 * 10)) + + @make_xp_test_case(fft.irfftn, fft.rfftn) + def test_irfftn(self, xp): + x = xp.asarray(random((30, 20, 10))) + xp_assert_close(fft.irfftn(fft.rfftn(x)), x) + for norm in ["backward", "ortho", "forward"]: + xp_assert_close(fft.irfftn(fft.rfftn(x, norm=norm), norm=norm), x) + + @make_xp_test_case(fft.hfft, fft.fft) + def test_hfft(self, xp): + x = random(14) + 1j*random(14) + x_herm = np.concatenate((random(1), x, random(1))) + x = np.concatenate((x_herm, x[::-1].conj())) + x = xp.asarray(x) + x_herm = xp.asarray(x_herm) + expect = xp.real(fft.fft(x)) + xp_assert_close(fft.hfft(x_herm), expect) + xp_assert_close(fft.hfft(x_herm, norm="backward"), expect) + xp_assert_close(fft.hfft(x_herm, norm="ortho"), + expect / xp.sqrt(xp.asarray(30, dtype=xp.float64))) + xp_assert_close(fft.hfft(x_herm, norm="forward"), expect / 30) + + @make_xp_test_case(fft.hfft, fft.ihfft) + def test_ihfft(self, xp): + x = random(14) + 1j*random(14) + x_herm = np.concatenate((random(1), x, random(1))) + x = np.concatenate((x_herm, x[::-1].conj())) + x = xp.asarray(x) + x_herm = xp.asarray(x_herm) + xp_assert_close(fft.ihfft(fft.hfft(x_herm)), x_herm) + for norm in ["backward", "ortho", "forward"]: + xp_assert_close(fft.ihfft(fft.hfft(x_herm, norm=norm), norm=norm), x_herm) + + @make_xp_test_case(fft.hfft2, fft.ihfft2) + def test_hfft2(self, xp): + x = xp.asarray(random((30, 20))) + xp_assert_close(fft.hfft2(fft.ihfft2(x)), x) + for norm in ["backward", "ortho", "forward"]: + xp_assert_close(fft.hfft2(fft.ihfft2(x, norm=norm), norm=norm), x) + + @make_xp_test_case(fft.ifft2) + def test_ihfft2(self, xp): + x = xp.asarray(random((30, 20)), dtype=xp.float64) + expect = fft.ifft2(xp.asarray(x, dtype=xp.complex128))[:, :11] + xp_assert_close(fft.ihfft2(x), expect) + xp_assert_close(fft.ihfft2(x, norm="backward"), expect) + xp_assert_close( + fft.ihfft2(x, norm="ortho"), + expect * xp.sqrt(xp.asarray(30 * 20, dtype=xp.float64)) + ) + xp_assert_close(fft.ihfft2(x, norm="forward"), expect * (30 * 20)) + + @make_xp_test_case(fft.hfftn, fft.ihfftn) + def test_hfftn(self, xp): + x = xp.asarray(random((30, 20, 10))) + xp_assert_close(fft.hfftn(fft.ihfftn(x)), x) + for norm in ["backward", "ortho", "forward"]: + xp_assert_close(fft.hfftn(fft.ihfftn(x, norm=norm), norm=norm), x) + + @make_xp_test_case(fft.ifftn, fft.ihfftn) + def test_ihfftn(self, xp): + x = xp.asarray(random((30, 20, 10)), dtype=xp.float64) + expect = fft.ifftn(xp.asarray(x, dtype=xp.complex128))[:, :, :6] + xp_assert_close(expect, fft.ihfftn(x)) + xp_assert_close(expect, fft.ihfftn(x, norm="backward")) + xp_assert_close( + fft.ihfftn(x, norm="ortho"), + expect * xp.sqrt(xp.asarray(30 * 20 * 10, dtype=xp.float64)) + ) + xp_assert_close(fft.ihfftn(x, norm="forward"), expect * (30 * 20 * 10)) + + def _check_axes(self, op, xp): + dtype = get_expected_input_dtype(op, xp) + x = xp.asarray(random((30, 20, 10)), dtype=dtype) + axes = [(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)] + + for a in axes: + op_tr = op(xp.permute_dims(x, axes=a)) + tr_op = xp.permute_dims(op(x, axes=a), axes=a) + xp_assert_close(op_tr, tr_op) + + @pytest.mark.parametrize("op", [make_xp_pytest_param(fft.fftn), + make_xp_pytest_param(fft.ifftn), + make_xp_pytest_param(fft.rfftn), + make_xp_pytest_param(fft.irfftn)]) + def test_axes_standard(self, op, xp): + self._check_axes(op, xp) + + @pytest.mark.parametrize("op", [make_xp_pytest_param(fft.hfftn), + make_xp_pytest_param(fft.ihfftn)]) + def test_axes_non_standard(self, op, xp): + self._check_axes(op, xp) + + @pytest.mark.parametrize("op", [make_xp_pytest_param(fft.fftn), + make_xp_pytest_param(fft.ifftn), + make_xp_pytest_param(fft.rfftn), + make_xp_pytest_param(fft.irfftn)]) + def test_axes_subset_with_shape_standard(self, op, xp): + dtype = get_expected_input_dtype(op, xp) + x = xp.asarray(random((16, 8, 4)), dtype=dtype) + axes = [(0, 1, 2), (0, 2, 1), (1, 2, 0)] + + for a in axes: + # different shape on the first two axes + shape = tuple([2*x.shape[ax] if ax in a[:2] else x.shape[ax] + for ax in range(x.ndim)]) + # transform only the first two axes + op_tr = op(xp.permute_dims(x, axes=a), + s=shape[:2], axes=(0, 1)) + tr_op = xp.permute_dims(op(x, s=shape[:2], axes=a[:2]), + axes=a) + xp_assert_close(op_tr, tr_op) + + @pytest.mark.parametrize("op", [make_xp_pytest_param(fft.fft2), + make_xp_pytest_param(fft.ifft2), + make_xp_pytest_param(fft.rfft2), + make_xp_pytest_param(fft.irfft2), + make_xp_pytest_param(fft.hfft2), + make_xp_pytest_param(fft.ihfft2), + make_xp_pytest_param(fft.hfftn), + make_xp_pytest_param(fft.ihfftn)]) + def test_axes_subset_with_shape_non_standard(self, op, xp): + dtype = get_expected_input_dtype(op, xp) + x = xp.asarray(random((16, 8, 4)), dtype=dtype) + axes = [(0, 1, 2), (0, 2, 1), (1, 2, 0)] + + for a in axes: + # different shape on the first two axes + shape = tuple([2*x.shape[ax] if ax in a[:2] else x.shape[ax] + for ax in range(x.ndim)]) + # transform only the first two axes + op_tr = op(xp.permute_dims(x, axes=a), s=shape[:2], axes=(0, 1)) + tr_op = xp.permute_dims(op(x, s=shape[:2], axes=a[:2]), axes=a) + xp_assert_close(op_tr, tr_op) + + @make_xp_test_case(fft.rfft, fft.irfft, fft.ihfft, fft.hfft, fft.fft, fft.ifft) + def test_all_1d_norm_preserving(self, xp): + # verify that round-trip transforms are norm-preserving + x = xp.asarray(random(30), dtype=xp.float64) + + x_norm = xp.linalg.vector_norm(x) + n = xp_size(x) * 2 + func_pairs = [(fft.rfft, fft.irfft), + # hfft: order so the first function takes x.size samples + # (necessary for comparison to x_norm above) + (fft.ihfft, fft.hfft), + # functions that expect complex dtypes at the end + (fft.fft, fft.ifft), + ] + for forw, back in func_pairs: + if forw == fft.fft: + x = xp.asarray(x, dtype=xp.complex128) + x_norm = xp.linalg.vector_norm(x) + for n in [xp_size(x), 2*xp_size(x)]: + for norm in ['backward', 'ortho', 'forward']: + tmp = forw(x, n=n, norm=norm) + tmp = back(tmp, n=n, norm=norm) + xp_assert_close(xp.linalg.vector_norm(tmp), x_norm) + + @pytest.mark.parametrize("dtype", [np.float16, np.longdouble]) + def test_dtypes_nonstandard(self, dtype): + x = random(30).astype(dtype) + out_dtypes = {np.float16: np.complex64, np.longdouble: np.clongdouble} + x_complex = x.astype(out_dtypes[dtype]) + + res_fft = fft.ifft(fft.fft(x)) + res_rfft = fft.irfft(fft.rfft(x)) + res_hfft = fft.hfft(fft.ihfft(x), x.shape[0]) + # Check both numerical results and exact dtype matches + assert_array_almost_equal(res_fft, x_complex) + assert_array_almost_equal(res_rfft, x) + assert_array_almost_equal(res_hfft, x) + assert res_fft.dtype == x_complex.dtype + assert res_rfft.dtype == np.result_type(np.float32, x.dtype) + assert res_hfft.dtype == np.result_type(np.float32, x.dtype) + + @make_xp_test_case(fft.irfft, fft.rfft) + @pytest.mark.parametrize("dtype", ["float32", "float64"]) + def test_dtypes_real(self, dtype, xp): + x = xp.asarray(random(30), dtype=getattr(xp, dtype)) + + res_rfft = fft.irfft(fft.rfft(x)) + res_hfft = fft.hfft(fft.ihfft(x), x.shape[0]) + # Check both numerical results and exact dtype matches + xp_assert_close(res_rfft, x) + xp_assert_close(res_hfft, x) + + @make_xp_test_case(fft.fft, fft.ifft) + @pytest.mark.parametrize("dtype", ["complex64", "complex128"]) + def test_dtypes_complex(self, dtype, xp): + rng = np.random.default_rng(1234) + x = xp.asarray(rng.random(30), dtype=getattr(xp, dtype)) + + res_fft = fft.ifft(fft.fft(x)) + # Check both numerical results and exact dtype matches + xp_assert_close(res_fft, x) + + @pytest.mark.parametrize("op", [fft.fft, fft.ifft, + fft.fft2, fft.ifft2, + fft.fftn, fft.ifftn, + fft.rfft, fft.irfft, + fft.rfft2, fft.irfft2, + fft.rfftn, fft.irfftn, + fft.hfft, fft.ihfft, + fft.hfft2, fft.ihfft2, + fft.hfftn, fft.ihfftn,]) + def test_array_like(self, op): + x = [[[1.0, 1.0], [1.0, 1.0]], + [[1.0, 1.0], [1.0, 1.0]], + [[1.0, 1.0], [1.0, 1.0]]] + xp_assert_close(op(x), op(np.asarray(x))) + + +@pytest.mark.parametrize( + "dtype", + [np.float32, np.float64, np.longdouble, + np.complex64, np.complex128, np.clongdouble]) +@pytest.mark.parametrize("order", ["F", 'non-contiguous']) +@pytest.mark.parametrize( + "fft", + [fft.fft, fft.fft2, fft.fftn, fft.ifft, fft.ifft2, fft.ifftn]) +def test_fft_with_order(dtype, order, fft): + # Check that FFT/IFFT produces identical results for C, Fortran and + # non contiguous arrays + rng = np.random.RandomState(42) + X = rng.rand(8, 7, 13).astype(dtype, copy=False) + if order == 'F': + Y = np.asfortranarray(X) + else: + # Make a non contiguous array + Y = X[::-1] + X = np.ascontiguousarray(X[::-1]) + + if fft.__name__.endswith('fft'): + for axis in range(3): + X_res = fft(X, axis=axis) + Y_res = fft(Y, axis=axis) + assert_array_almost_equal(X_res, Y_res) + elif fft.__name__.endswith(('fft2', 'fftn')): + axes = [(0, 1), (1, 2), (0, 2)] + if fft.__name__.endswith('fftn'): + axes.extend([(0,), (1,), (2,), None]) + for ax in axes: + X_res = fft(X, axes=ax) + Y_res = fft(Y, axes=ax) + assert_array_almost_equal(X_res, Y_res) + else: + raise ValueError + + +@skip_xp_backends(cpu_only=True) +class TestFFTThreadSafe: + threads = 16 + input_shape = (800, 200) + + def _test_mtsame(self, func, *args, xp=None): + def worker(args, q): + q.put(func(*args)) + + q = queue.Queue() + expected = func(*args) + + # Spin off a bunch of threads to call the same function simultaneously + t = [threading.Thread(target=worker, args=(args, q)) + for i in range(self.threads)] + [x.start() for x in t] + + [x.join() for x in t] + + # Make sure all threads returned the correct value + for i in range(self.threads): + xp_assert_equal( + q.get(timeout=5), expected, + err_msg='Function returned wrong value in multithreaded context' + ) + + @make_xp_test_case(fft.fft) + def test_fft(self, xp): + a = xp.ones(self.input_shape, dtype=xp.complex128) + self._test_mtsame(fft.fft, a, xp=xp) + + @make_xp_test_case(fft.ifft) + def test_ifft(self, xp): + a = xp.full(self.input_shape, 1+0j) + self._test_mtsame(fft.ifft, a, xp=xp) + + @make_xp_test_case(fft.rfft) + def test_rfft(self, xp): + a = xp.ones(self.input_shape) + self._test_mtsame(fft.rfft, a, xp=xp) + + @make_xp_test_case(fft.irfft) + def test_irfft(self, xp): + a = xp.full(self.input_shape, 1+0j) + self._test_mtsame(fft.irfft, a, xp=xp) + + @make_xp_test_case(fft.hfft) + def test_hfft(self, xp): + a = xp.ones(self.input_shape, dtype=xp.complex64) + self._test_mtsame(fft.hfft, a, xp=xp) + + @make_xp_test_case(fft.ihfft) + def test_ihfft(self, xp): + a = xp.ones(self.input_shape) + self._test_mtsame(fft.ihfft, a, xp=xp) + + +@pytest.mark.parametrize("func", [fft.fft, fft.ifft, fft.rfft, fft.irfft]) +def test_multiprocess(func): + # Test that fft still works after fork (gh-10422) + + with multiprocessing.Pool(2) as p: + res = p.map(func, [np.ones(100) for _ in range(4)]) + + expect = func(np.ones(100)) + for x in res: + assert_allclose(x, expect) + + +@make_xp_test_case(fft.irfftn) +class TestIRFFTN: + + def test_not_last_axis_success(self, xp): + ar, ai = np.random.random((2, 16, 8, 32)) + a = ar + 1j*ai + a = xp.asarray(a) + + axes = (-2,) + + # Should not raise error + fft.irfftn(a, axes=axes) + + +@pytest.mark.parametrize("func", [make_xp_pytest_param(fft.fft), + make_xp_pytest_param(fft.ifft), + make_xp_pytest_param(fft.rfft), + make_xp_pytest_param(fft.irfft), + make_xp_pytest_param(fft.fftn), + make_xp_pytest_param(fft.ifftn), + make_xp_pytest_param(fft.rfftn), + make_xp_pytest_param(fft.irfftn), + make_xp_pytest_param(fft.hfft), + make_xp_pytest_param(fft.ihfft)]) +def test_non_standard_params(func, xp): + # use __name__ so that `lazy_xp_function` doesn't break things + if func.__name__ in ["rfft", "rfftn", "ihfft"]: + dtype = xp.float64 + else: + dtype = xp.complex128 + + x = xp.asarray([1, 2, 3], dtype=dtype) + # func(x) should not raise an exception + func(x) + + if is_numpy(xp): + func(x, workers=2) + else: + assert_raises(ValueError, func, x, workers=2) + + # `plan` param is not tested since SciPy does not use it currently + # but should be tested if it comes into use + + +@pytest.mark.parametrize("dtype", ['float32', 'float64']) +@pytest.mark.parametrize("func", [make_xp_pytest_param(fft.fft), + make_xp_pytest_param(fft.ifft), + make_xp_pytest_param(fft.irfft), + make_xp_pytest_param(fft.fftn), + make_xp_pytest_param(fft.ifftn), + make_xp_pytest_param(fft.irfftn), + make_xp_pytest_param(fft.hfft)]) +def test_real_input(func, dtype, xp): + x = xp.asarray([1, 2, 3], dtype=getattr(xp, dtype)) + # func(x) should not raise an exception + func(x) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_fftlog.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_fftlog.py new file mode 100644 index 0000000000000000000000000000000000000000..636d3fa8ffec108971385371213c4680b6a74035 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_fftlog.py @@ -0,0 +1,214 @@ +import warnings +import math + +import numpy as np +import pytest + +from scipy.fft._fftlog import fht, ifht, fhtoffset +from scipy.special import poch + +from scipy._lib._array_api import xp_assert_close, xp_assert_less + +skip_xp_backends = pytest.mark.skip_xp_backends + + +def test_fht_agrees_with_fftlog(xp): + # check that fht numerically agrees with the output from Fortran FFTLog, + # the results were generated with the provided `fftlogtest` program, + # after fixing how the k array is generated (divide range by n-1, not n) + + # test function, analytical Hankel transform is of the same form + def f(r, mu): + return r**(mu+1)*np.exp(-r**2/2) + + r = np.logspace(-4, 4, 16) + + dln = math.log(r[1]/r[0]) + mu = 0.3 + offset = 0.0 + bias = 0.0 + + a = xp.asarray(f(r, mu)) + + # test 1: compute as given + ours = fht(a, dln, mu, offset=offset, bias=bias) + theirs = [-0.1159922613593045E-02, +0.1625822618458832E-02, + -0.1949518286432330E-02, +0.3789220182554077E-02, + +0.5093959119952945E-03, +0.2785387803618774E-01, + +0.9944952700848897E-01, +0.4599202164586588E+00, + +0.3157462160881342E+00, -0.8201236844404755E-03, + -0.7834031308271878E-03, +0.3931444945110708E-03, + -0.2697710625194777E-03, +0.3568398050238820E-03, + -0.5554454827797206E-03, +0.8286331026468585E-03] + theirs = xp.asarray(theirs, dtype=xp.float64) + xp_assert_close(ours, theirs) + + # test 2: change to optimal offset + offset = fhtoffset(dln, mu, bias=bias) + ours = fht(a, dln, mu, offset=offset, bias=bias) + theirs = [+0.4353768523152057E-04, -0.9197045663594285E-05, + +0.3150140927838524E-03, +0.9149121960963704E-03, + +0.5808089753959363E-02, +0.2548065256377240E-01, + +0.1339477692089897E+00, +0.4821530509479356E+00, + +0.2659899781579785E+00, -0.1116475278448113E-01, + +0.1791441617592385E-02, -0.4181810476548056E-03, + +0.1314963536765343E-03, -0.5422057743066297E-04, + +0.3208681804170443E-04, -0.2696849476008234E-04] + theirs = xp.asarray(theirs, dtype=xp.float64) + xp_assert_close(ours, theirs) + + # test 3: positive bias + bias = 0.8 + offset = fhtoffset(dln, mu, bias=bias) + # offset is a np.float64, which array-api-strict disallows + # even if it's technically a subclass of float + offset = float(offset) + + ours = fht(a, dln, mu, offset=offset, bias=bias) + theirs = [-7.3436673558316850E+00, +0.1710271207817100E+00, + +0.1065374386206564E+00, -0.5121739602708132E-01, + +0.2636649319269470E-01, +0.1697209218849693E-01, + +0.1250215614723183E+00, +0.4739583261486729E+00, + +0.2841149874912028E+00, -0.8312764741645729E-02, + +0.1024233505508988E-02, -0.1644902767389120E-03, + +0.3305775476926270E-04, -0.7786993194882709E-05, + +0.1962258449520547E-05, -0.8977895734909250E-06] + theirs = xp.asarray(theirs, dtype=xp.float64) + xp_assert_close(ours, theirs) + + # test 4: negative bias + bias = -0.8 + offset = fhtoffset(dln, mu, bias=bias) + offset = float(offset) + + ours = fht(a, dln, mu, offset=offset, bias=bias) + theirs = [+0.8985777068568745E-05, +0.4074898209936099E-04, + +0.2123969254700955E-03, +0.1009558244834628E-02, + +0.5131386375222176E-02, +0.2461678673516286E-01, + +0.1235812845384476E+00, +0.4719570096404403E+00, + +0.2893487490631317E+00, -0.1686570611318716E-01, + +0.2231398155172505E-01, -0.1480742256379873E-01, + +0.1692387813500801E+00, +0.3097490354365797E+00, + +2.7593607182401860E+00, 10.5251075070045800E+00] + theirs = xp.asarray(theirs, dtype=xp.float64) + xp_assert_close(ours, theirs) + + +@pytest.mark.parametrize('optimal', [True, False]) +@pytest.mark.parametrize('offset', [0.0, 1.0, -1.0]) +@pytest.mark.parametrize('bias', [0, 0.1, -0.1]) +@pytest.mark.parametrize('n', [64, 63]) +def test_fht_identity(n, bias, offset, optimal, xp): + rng = np.random.RandomState(3491349965) + + a = xp.asarray(rng.standard_normal(n)) + dln = rng.uniform(-1, 1) + mu = rng.uniform(-2, 2) + + if optimal: + offset = fhtoffset(dln, mu, initial=offset, bias=bias) + # offset is a np.float64, which array-api-strict disallows + # even if it's technically a subclass of float + offset = float(offset) + + A = fht(a, dln, mu, offset=offset, bias=bias) + a_ = ifht(A, dln, mu, offset=offset, bias=bias) + + xp_assert_close(a_, a, rtol=1.5e-7) + + + + +def test_fht_special_cases(xp): + rng = np.random.RandomState(3491349965) + + a = xp.asarray(rng.standard_normal(64)) + dln = rng.uniform(-1, 1) + + # let x = (mu+1+q)/2, y = (mu+1-q)/2, M = {0, -1, -2, ...} + + # case 1: x in M, y in M => well-defined transform + mu, bias = -4.0, 1.0 + with warnings.catch_warnings(record=True) as record: + fht(a, dln, mu, bias=bias) + assert not record, 'fht warned about a well-defined transform' + + # case 2: x not in M, y in M => well-defined transform + mu, bias = -2.5, 0.5 + with warnings.catch_warnings(record=True) as record: + fht(a, dln, mu, bias=bias) + assert not record, 'fht warned about a well-defined transform' + + # with fht_lock: + # case 3: x in M, y not in M => singular transform + mu, bias = -3.5, 0.5 + with pytest.warns(Warning) as record: + fht(a, dln, mu, bias=bias) + assert record, 'fht did not warn about a singular transform' + + # with fht_lock: + # case 4: x not in M, y in M => singular inverse transform + mu, bias = -2.5, 0.5 + with pytest.warns(Warning) as record: + ifht(a, dln, mu, bias=bias) + assert record, 'ifht did not warn about a singular transform' + + +@pytest.mark.parametrize('n', [64, 63]) +def test_fht_exact(n, xp): + rng = np.random.RandomState(3491349965) + + # for a(r) a power law r^\gamma, the fast Hankel transform produces the + # exact continuous Hankel transform if biased with q = \gamma + + mu = rng.uniform(0, 3) + + # convergence of HT: -1-mu < gamma < 1/2 + gamma = rng.uniform(-1-mu, 1/2) + + r = np.logspace(-2, 2, n) + a = xp.asarray(r**gamma) + + dln = math.log(r[1]/r[0]) + + offset = fhtoffset(dln, mu, initial=0.0, bias=gamma) + # offset is a np.float64, which array-api-strict disallows + # even if it's technically a subclass of float + offset = float(offset) + + A = fht(a, dln, mu, offset=offset, bias=gamma) + + k = np.exp(offset)/r[::-1] + + # analytical result + At = xp.asarray((2/k)**gamma * poch((mu+1-gamma)/2, gamma)) + + xp_assert_close(A, At) + +@skip_xp_backends(np_only=True, + reason='array-likes only supported for NumPy backend') +@pytest.mark.parametrize("op", [fht, ifht]) +def test_array_like(xp, op): + x = [[[1.0, 1.0], [1.0, 1.0]], + [[1.0, 1.0], [1.0, 1.0]], + [[1.0, 1.0], [1.0, 1.0]]] + xp_assert_close(op(x, 1.0, 2.0), op(xp.asarray(x), 1.0, 2.0)) + +@pytest.mark.parametrize('n', [128, 129]) +def test_gh_21661(xp, n): + one = xp.asarray(1.0) + mu = 0.0 + r = np.logspace(-7, 1, n) + dln = math.log(r[1] / r[0]) + offset = fhtoffset(dln, initial=-6 * np.log(10), mu=mu) + r = xp.asarray(r, dtype=one.dtype) + k = math.exp(offset) / xp.flip(r, axis=-1) + + def f(x, mu): + return x**(mu + 1)*xp.exp(-x**2/2) + + a_r = f(r, mu) + fht_val = fht(a_r, dln, mu=mu, offset=offset) + a_k = f(k, mu) + rel_err = xp.max(xp.abs((fht_val - a_k) / a_k)) + xp_assert_less(rel_err, xp.asarray(7.28e+16)[()]) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_helper.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_helper.py new file mode 100644 index 0000000000000000000000000000000000000000..b0427966c256ab7b919f75f4ae773a4b18be818a --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_helper.py @@ -0,0 +1,555 @@ +"""Includes test functions for fftpack.helper module + +Copied from fftpack.helper by Pearu Peterson, October 2005 +Modified for Array API, 2023 + +""" +from scipy.fft._helper import next_fast_len, prev_fast_len, _init_nd_shape_and_axes +from numpy.testing import assert_equal +from pytest import raises as assert_raises +import pytest +import numpy as np +import sys +from scipy._lib._array_api import xp_assert_close, xp_device +from scipy import fft + +skip_xp_backends = pytest.mark.skip_xp_backends + +_5_smooth_numbers = [ + 2, 3, 4, 5, 6, 8, 9, 10, + 2 * 3 * 5, + 2**3 * 3**5, + 2**3 * 3**3 * 5**2, +] + + +def test_next_fast_len(): + for n in _5_smooth_numbers: + assert_equal(next_fast_len(n), n) + + +def _assert_n_smooth(x, n): + x_orig = x + if n < 2: + assert False + + while True: + q, r = divmod(x, 2) + if r != 0: + break + x = q + + for d in range(3, n+1, 2): + while True: + q, r = divmod(x, d) + if r != 0: + break + x = q + + assert x == 1, \ + f'x={x_orig} is not {n}-smooth, remainder={x}' + + +class TestNextFastLen: + + def test_next_fast_len(self): + np.random.seed(1234) + + def nums(): + yield from range(1, 1000) + yield 2**5 * 3**5 * 4**5 + 1 + + for n in nums(): + m = next_fast_len(n) + _assert_n_smooth(m, 11) + assert m == next_fast_len(n, False) + + m = next_fast_len(n, True) + _assert_n_smooth(m, 5) + + def test_np_integers(self): + ITYPES = [np.int16, np.int32, np.int64, np.uint16, np.uint32, np.uint64] + for ityp in ITYPES: + x = ityp(12345) + testN = next_fast_len(x) + assert_equal(testN, next_fast_len(int(x))) + + def testnext_fast_len_small(self): + hams = { + 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 8, 8: 8, 14: 15, 15: 15, + 16: 16, 17: 18, 1021: 1024, 1536: 1536, 51200000: 51200000 + } + for x, y in hams.items(): + assert_equal(next_fast_len(x, True), y) + + @pytest.mark.xfail(sys.maxsize < 2**32, + reason="Hamming Numbers too large for 32-bit", + raises=ValueError, strict=True) + def testnext_fast_len_big(self): + hams = { + 510183360: 510183360, 510183360 + 1: 512000000, + 511000000: 512000000, + 854296875: 854296875, 854296875 + 1: 859963392, + 196608000000: 196608000000, 196608000000 + 1: 196830000000, + 8789062500000: 8789062500000, 8789062500000 + 1: 8796093022208, + 206391214080000: 206391214080000, + 206391214080000 + 1: 206624260800000, + 470184984576000: 470184984576000, + 470184984576000 + 1: 470715894135000, + 7222041363087360: 7222041363087360, + 7222041363087360 + 1: 7230196133913600, + # power of 5 5**23 + 11920928955078125: 11920928955078125, + 11920928955078125 - 1: 11920928955078125, + # power of 3 3**34 + 16677181699666569: 16677181699666569, + 16677181699666569 - 1: 16677181699666569, + # power of 2 2**54 + 18014398509481984: 18014398509481984, + 18014398509481984 - 1: 18014398509481984, + # above this, int(ceil(n)) == int(ceil(n+1)) + 19200000000000000: 19200000000000000, + 19200000000000000 + 1: 19221679687500000, + 288230376151711744: 288230376151711744, + 288230376151711744 + 1: 288325195312500000, + 288325195312500000 - 1: 288325195312500000, + 288325195312500000: 288325195312500000, + 288325195312500000 + 1: 288555831593533440, + } + for x, y in hams.items(): + assert_equal(next_fast_len(x, True), y) + + def test_keyword_args(self, xp): + assert next_fast_len(11, real=True) == 12 + assert next_fast_len(target=7, real=False) == 7 + + +class TestPrevFastLen: + + def test_prev_fast_len(self): + np.random.seed(1234) + + def nums(): + yield from range(1, 1000) + yield 2**5 * 3**5 * 4**5 + 1 + + for n in nums(): + m = prev_fast_len(n) + _assert_n_smooth(m, 11) + assert m == prev_fast_len(n, False) + + m = prev_fast_len(n, True) + _assert_n_smooth(m, 5) + + def test_np_integers(self): + ITYPES = [np.int16, np.int32, np.int64, np.uint16, np.uint32, + np.uint64] + for ityp in ITYPES: + x = ityp(12345) + testN = prev_fast_len(x) + assert_equal(testN, prev_fast_len(int(x))) + + testN = prev_fast_len(x, real=True) + assert_equal(testN, prev_fast_len(int(x), real=True)) + + def testprev_fast_len_small(self): + hams = { + 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 6, 8: 8, 14: 12, 15: 15, + 16: 16, 17: 16, 1021: 1000, 1536: 1536, 51200000: 51200000 + } + for x, y in hams.items(): + assert_equal(prev_fast_len(x, True), y) + + hams = { + 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10, + 11: 11, 12: 12, 13: 12, 14: 14, 15: 15, 16: 16, 17: 16, 18: 18, + 19: 18, 20: 20, 21: 21, 22: 22, 120: 120, 121: 121, 122: 121, + 1021: 1008, 1536: 1536, 51200000: 51200000 + } + for x, y in hams.items(): + assert_equal(prev_fast_len(x, False), y) + + @pytest.mark.xfail(sys.maxsize < 2**32, + reason="Hamming Numbers too large for 32-bit", + raises=ValueError, strict=True) + def testprev_fast_len_big(self): + hams = { + # 2**6 * 3**13 * 5**1 + 510183360: 510183360, + 510183360 + 1: 510183360, + 510183360 - 1: 509607936, # 2**21 * 3**5 + # 2**6 * 5**6 * 7**1 * 73**1 + 511000000: 510183360, + 511000000 + 1: 510183360, + 511000000 - 1: 510183360, # 2**6 * 3**13 * 5**1 + # 3**7 * 5**8 + 854296875: 854296875, + 854296875 + 1: 854296875, + 854296875 - 1: 850305600, # 2**6 * 3**12 * 5**2 + # 2**22 * 3**1 * 5**6 + 196608000000: 196608000000, + 196608000000 + 1: 196608000000, + 196608000000 - 1: 195910410240, # 2**13 * 3**14 * 5**1 + # 2**5 * 3**2 * 5**15 + 8789062500000: 8789062500000, + 8789062500000 + 1: 8789062500000, + 8789062500000 - 1: 8748000000000, # 2**11 * 3**7 * 5**9 + # 2**24 * 3**9 * 5**4 + 206391214080000: 206391214080000, + 206391214080000 + 1: 206391214080000, + 206391214080000 - 1: 206158430208000, # 2**39 * 3**1 * 5**3 + # 2**18 * 3**15 * 5**3 + 470184984576000: 470184984576000, + 470184984576000 + 1: 470184984576000, + 470184984576000 - 1: 469654673817600, # 2**33 * 3**7 **5**2 + # 2**25 * 3**16 * 5**1 + 7222041363087360: 7222041363087360, + 7222041363087360 + 1: 7222041363087360, + 7222041363087360 - 1: 7213895789838336, # 2**40 * 3**8 + # power of 5 5**23 + 11920928955078125: 11920928955078125, + 11920928955078125 + 1: 11920928955078125, + 11920928955078125 - 1: 11901557422080000, # 2**14 * 3**19 * 5**4 + # power of 3 3**34 + 16677181699666569: 16677181699666569, + 16677181699666569 + 1: 16677181699666569, + 16677181699666569 - 1: 16607531250000000, # 2**7 * 3**12 * 5**12 + # power of 2 2**54 + 18014398509481984: 18014398509481984, + 18014398509481984 + 1: 18014398509481984, + 18014398509481984 - 1: 18000000000000000, # 2**16 * 3**2 * 5**15 + # 2**20 * 3**1 * 5**14 + 19200000000000000: 19200000000000000, + 19200000000000000 + 1: 19200000000000000, + 19200000000000000 - 1: 19131876000000000, # 2**11 * 3**14 * 5**9 + # 2**58 + 288230376151711744: 288230376151711744, + 288230376151711744 + 1: 288230376151711744, + 288230376151711744 - 1: 288000000000000000, # 2**20 * 3**2 * 5**15 + # 2**5 * 3**10 * 5**16 + 288325195312500000: 288325195312500000, + 288325195312500000 + 1: 288325195312500000, + 288325195312500000 - 1: 288230376151711744, # 2**58 + } + for x, y in hams.items(): + assert_equal(prev_fast_len(x, True), y) + + def test_keyword_args(self): + assert prev_fast_len(11, real=True) == 10 + assert prev_fast_len(target=7, real=False) == 7 + + +@skip_xp_backends(cpu_only=True) +class Test_init_nd_shape_and_axes: + + def test_py_0d_defaults(self, xp): + x = xp.asarray(4) + shape = None + axes = None + + shape_expected = () + axes_expected = [] + + shape_res, axes_res = _init_nd_shape_and_axes(x, shape, axes) + + assert shape_res == shape_expected + assert axes_res == axes_expected + + def test_xp_0d_defaults(self, xp): + x = xp.asarray(7.) + shape = None + axes = None + + shape_expected = () + axes_expected = [] + + shape_res, axes_res = _init_nd_shape_and_axes(x, shape, axes) + + assert shape_res == shape_expected + assert axes_res == axes_expected + + def test_py_1d_defaults(self, xp): + x = xp.asarray([1, 2, 3]) + shape = None + axes = None + + shape_expected = (3,) + axes_expected = [0] + + shape_res, axes_res = _init_nd_shape_and_axes(x, shape, axes) + + assert shape_res == shape_expected + assert axes_res == axes_expected + + def test_xp_1d_defaults(self, xp): + x = xp.arange(0, 1, .1) + shape = None + axes = None + + shape_expected = (10,) + axes_expected = [0] + + shape_res, axes_res = _init_nd_shape_and_axes(x, shape, axes) + + assert shape_res == shape_expected + assert axes_res == axes_expected + + def test_py_2d_defaults(self, xp): + x = xp.asarray([[1, 2, 3, 4], + [5, 6, 7, 8]]) + shape = None + axes = None + + shape_expected = (2, 4) + axes_expected = [0, 1] + + shape_res, axes_res = _init_nd_shape_and_axes(x, shape, axes) + + assert shape_res == shape_expected + assert axes_res == axes_expected + + def test_xp_2d_defaults(self, xp): + x = xp.arange(0, 1, .1) + x = xp.reshape(x, (5, 2)) + shape = None + axes = None + + shape_expected = (5, 2) + axes_expected = [0, 1] + + shape_res, axes_res = _init_nd_shape_and_axes(x, shape, axes) + + assert shape_res == shape_expected + assert axes_res == axes_expected + + def test_xp_5d_defaults(self, xp): + x = xp.zeros([6, 2, 5, 3, 4]) + shape = None + axes = None + + shape_expected = (6, 2, 5, 3, 4) + axes_expected = [0, 1, 2, 3, 4] + + shape_res, axes_res = _init_nd_shape_and_axes(x, shape, axes) + + assert shape_res == shape_expected + assert axes_res == axes_expected + + def test_xp_5d_set_shape(self, xp): + x = xp.zeros([6, 2, 5, 3, 4]) + shape = [10, -1, -1, 1, 4] + axes = None + + shape_expected = (10, 2, 5, 1, 4) + axes_expected = [0, 1, 2, 3, 4] + + shape_res, axes_res = _init_nd_shape_and_axes(x, shape, axes) + + assert shape_res == shape_expected + assert axes_res == axes_expected + + def test_xp_5d_set_axes(self, xp): + x = xp.zeros([6, 2, 5, 3, 4]) + shape = None + axes = [4, 1, 2] + + shape_expected = (4, 2, 5) + axes_expected = [4, 1, 2] + + shape_res, axes_res = _init_nd_shape_and_axes(x, shape, axes) + + assert shape_res == shape_expected + assert axes_res == axes_expected + + def test_xp_5d_set_shape_axes(self, xp): + x = xp.zeros([6, 2, 5, 3, 4]) + shape = [10, -1, 2] + axes = [1, 0, 3] + + shape_expected = (10, 6, 2) + axes_expected = [1, 0, 3] + + shape_res, axes_res = _init_nd_shape_and_axes(x, shape, axes) + + assert shape_res == shape_expected + assert axes_res == axes_expected + + def test_shape_axes_subset(self, xp): + x = xp.zeros((2, 3, 4, 5)) + shape, axes = _init_nd_shape_and_axes(x, shape=(5, 5, 5), axes=None) + + assert shape == (5, 5, 5) + assert axes == [1, 2, 3] + + def test_errors(self, xp): + x = xp.zeros(1) + with assert_raises(ValueError, match="axes must be a scalar or " + "iterable of integers"): + _init_nd_shape_and_axes(x, shape=None, axes=[[1, 2], [3, 4]]) + + with assert_raises(ValueError, match="axes must be a scalar or " + "iterable of integers"): + _init_nd_shape_and_axes(x, shape=None, axes=[1., 2., 3., 4.]) + + with assert_raises(ValueError, + match="axes exceeds dimensionality of input"): + _init_nd_shape_and_axes(x, shape=None, axes=[1]) + + with assert_raises(ValueError, + match="axes exceeds dimensionality of input"): + _init_nd_shape_and_axes(x, shape=None, axes=[-2]) + + with assert_raises(ValueError, + match="all axes must be unique"): + _init_nd_shape_and_axes(x, shape=None, axes=[0, 0]) + + with assert_raises(ValueError, match="shape must be a scalar or " + "iterable of integers"): + _init_nd_shape_and_axes(x, shape=[[1, 2], [3, 4]], axes=None) + + with assert_raises(ValueError, match="shape must be a scalar or " + "iterable of integers"): + _init_nd_shape_and_axes(x, shape=[1., 2., 3., 4.], axes=None) + + with assert_raises(ValueError, + match="when given, axes and shape arguments" + " have to be of the same length"): + _init_nd_shape_and_axes(xp.zeros([1, 1, 1, 1]), + shape=[1, 2, 3], axes=[1]) + + with assert_raises(ValueError, + match="invalid number of data points" + r" \(\[0\]\) specified"): + _init_nd_shape_and_axes(x, shape=[0], axes=None) + + with assert_raises(ValueError, + match="invalid number of data points" + r" \(\[-2\]\) specified"): + _init_nd_shape_and_axes(x, shape=-2, axes=None) + + +class TestFFTShift: + + def test_definition(self, xp): + x = xp.asarray([0., 1, 2, 3, 4, -4, -3, -2, -1]) + y = xp.asarray([-4., -3, -2, -1, 0, 1, 2, 3, 4]) + xp_assert_close(fft.fftshift(x), y) + xp_assert_close(fft.ifftshift(y), x) + x = xp.asarray([0., 1, 2, 3, 4, -5, -4, -3, -2, -1]) + y = xp.asarray([-5., -4, -3, -2, -1, 0, 1, 2, 3, 4]) + xp_assert_close(fft.fftshift(x), y) + xp_assert_close(fft.ifftshift(y), x) + + def test_inverse(self, xp): + for n in [1, 4, 9, 100, 211]: + x = xp.asarray(np.random.random((n,))) + xp_assert_close(fft.ifftshift(fft.fftshift(x)), x) + + def test_axes_keyword(self, xp): + freqs = xp.asarray([[0., 1, 2], [3, 4, -4], [-3, -2, -1]]) + shifted = xp.asarray([[-1., -3, -2], [2, 0, 1], [-4, 3, 4]]) + xp_assert_close(fft.fftshift(freqs, axes=(0, 1)), shifted) + xp_assert_close(fft.fftshift(freqs, axes=0), fft.fftshift(freqs, axes=(0,))) + xp_assert_close(fft.ifftshift(shifted, axes=(0, 1)), freqs) + xp_assert_close(fft.ifftshift(shifted, axes=0), + fft.ifftshift(shifted, axes=(0,))) + xp_assert_close(fft.fftshift(freqs), shifted) + xp_assert_close(fft.ifftshift(shifted), freqs) + + def test_uneven_dims(self, xp): + """ Test 2D input, which has uneven dimension sizes """ + freqs = xp.asarray([ + [0, 1], + [2, 3], + [4, 5] + ], dtype=xp.float64) + + # shift in dimension 0 + shift_dim0 = xp.asarray([ + [4, 5], + [0, 1], + [2, 3] + ], dtype=xp.float64) + xp_assert_close(fft.fftshift(freqs, axes=0), shift_dim0) + xp_assert_close(fft.ifftshift(shift_dim0, axes=0), freqs) + xp_assert_close(fft.fftshift(freqs, axes=(0,)), shift_dim0) + xp_assert_close(fft.ifftshift(shift_dim0, axes=[0]), freqs) + + # shift in dimension 1 + shift_dim1 = xp.asarray([ + [1, 0], + [3, 2], + [5, 4] + ], dtype=xp.float64) + xp_assert_close(fft.fftshift(freqs, axes=1), shift_dim1) + xp_assert_close(fft.ifftshift(shift_dim1, axes=1), freqs) + + # shift in both dimensions + shift_dim_both = xp.asarray([ + [5, 4], + [1, 0], + [3, 2] + ], dtype=xp.float64) + xp_assert_close(fft.fftshift(freqs, axes=(0, 1)), shift_dim_both) + xp_assert_close(fft.ifftshift(shift_dim_both, axes=(0, 1)), freqs) + xp_assert_close(fft.fftshift(freqs, axes=[0, 1]), shift_dim_both) + xp_assert_close(fft.ifftshift(shift_dim_both, axes=[0, 1]), freqs) + + # axes=None (default) shift in all dimensions + xp_assert_close(fft.fftshift(freqs, axes=None), shift_dim_both) + xp_assert_close(fft.ifftshift(shift_dim_both, axes=None), freqs) + xp_assert_close(fft.fftshift(freqs), shift_dim_both) + xp_assert_close(fft.ifftshift(shift_dim_both), freqs) + + +class TestFFTFreq: + def test_definition(self, xp): + x = xp.asarray([0, 1, 2, 3, 4, -4, -3, -2, -1], dtype=xp.float64) + x2 = xp.asarray([0, 1, 2, 3, 4, -5, -4, -3, -2, -1], dtype=xp.float64) + + # default dtype varies across backends + + y = 9 * fft.fftfreq(9, xp=xp) + xp_assert_close(y, x, check_dtype=False, check_namespace=True) + + y = 9 * xp.pi * fft.fftfreq(9, xp.pi, xp=xp) + xp_assert_close(y, x, check_dtype=False) + + y = 10 * fft.fftfreq(10, xp=xp) + xp_assert_close(y, x2, check_dtype=False) + + y = 10 * xp.pi * fft.fftfreq(10, xp.pi, xp=xp) + xp_assert_close(y, x2, check_dtype=False) + + def test_device(self, xp, devices): + for d in devices: + y = fft.fftfreq(9, xp=xp, device=d) + x = xp.empty(0, device=d) + assert xp_device(y) == xp_device(x) + + +class TestRFFTFreq: + + def test_definition(self, xp): + x = xp.asarray([0, 1, 2, 3, 4], dtype=xp.float64) + x2 = xp.asarray([0, 1, 2, 3, 4, 5], dtype=xp.float64) + + # default dtype varies across backends + + y = 9 * fft.rfftfreq(9, xp=xp) + xp_assert_close(y, x, check_dtype=False, check_namespace=True) + + y = 9 * xp.pi * fft.rfftfreq(9, xp.pi, xp=xp) + xp_assert_close(y, x, check_dtype=False) + + y = 10 * fft.rfftfreq(10, xp=xp) + xp_assert_close(y, x2, check_dtype=False) + + y = 10 * xp.pi * fft.rfftfreq(10, xp.pi, xp=xp) + xp_assert_close(y, x2, check_dtype=False) + + def test_device(self, xp, devices): + for d in devices: + y = fft.rfftfreq(9, xp=xp, device=d) + x = xp.empty(0, device=d) + assert xp_device(y) == xp_device(x) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_multithreading.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_multithreading.py new file mode 100644 index 0000000000000000000000000000000000000000..1a6b71b830211f8bcbe56e97ff71098be75021c8 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_multithreading.py @@ -0,0 +1,84 @@ +from scipy import fft +import numpy as np +import pytest +from numpy.testing import assert_allclose +import multiprocessing +import os + + +@pytest.fixture(scope='module') +def x(): + return np.random.randn(512, 128) # Must be large enough to qualify for mt + + +@pytest.mark.parametrize("func", [ + fft.fft, fft.ifft, fft.fft2, fft.ifft2, fft.fftn, fft.ifftn, + fft.rfft, fft.irfft, fft.rfft2, fft.irfft2, fft.rfftn, fft.irfftn, + fft.hfft, fft.ihfft, fft.hfft2, fft.ihfft2, fft.hfftn, fft.ihfftn, + fft.dct, fft.idct, fft.dctn, fft.idctn, + fft.dst, fft.idst, fft.dstn, fft.idstn, +]) +@pytest.mark.parametrize("workers", [2, -1]) +def test_threaded_same(x, func, workers): + expected = func(x, workers=1) + actual = func(x, workers=workers) + assert_allclose(actual, expected) + + +def _mt_fft(x): + return fft.fft(x, workers=2) + + +@pytest.mark.slow +def test_mixed_threads_processes(x): + # Test that the fft threadpool is safe to use before & after fork + + expect = fft.fft(x, workers=2) + + with multiprocessing.Pool(2) as p: + res = p.map(_mt_fft, [x for _ in range(4)]) + + for r in res: + assert_allclose(r, expect) + + fft.fft(x, workers=2) + + +def test_invalid_workers(x): + cpus = os.cpu_count() + + fft.ifft([1], workers=-cpus) + + with pytest.raises(ValueError, match='workers must not be zero'): + fft.fft(x, workers=0) + + with pytest.raises(ValueError, match='workers value out of range'): + fft.ifft(x, workers=-cpus-1) + + +def test_set_get_workers(): + cpus = os.cpu_count() + assert fft.get_workers() == 1 + with fft.set_workers(4): + assert fft.get_workers() == 4 + + with fft.set_workers(-1): + assert fft.get_workers() == cpus + + assert fft.get_workers() == 4 + + assert fft.get_workers() == 1 + + with fft.set_workers(-cpus): + assert fft.get_workers() == 1 + + +def test_set_workers_invalid(): + + with pytest.raises(ValueError, match='workers must not be zero'): + with fft.set_workers(0): + pass + + with pytest.raises(ValueError, match='workers value out of range'): + with fft.set_workers(-os.cpu_count()-1): + pass diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_real_transforms.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_real_transforms.py new file mode 100644 index 0000000000000000000000000000000000000000..3add13d58ae70a567f3f4bf7b73dda72a15a47ae --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fft/tests/test_real_transforms.py @@ -0,0 +1,249 @@ +import numpy as np +from numpy.testing import assert_allclose, assert_array_equal +import pytest +import math + +from scipy.fft import dct, idct, dctn, idctn, dst, idst, dstn, idstn +import scipy.fft as fft +from scipy import fftpack +from scipy._lib._array_api import (xp_copy, xp_assert_close, make_xp_test_case, + make_xp_pytest_param) +import scipy._lib.array_api_extra as xpx + +skip_xp_backends = pytest.mark.skip_xp_backends + +SQRT_2 = math.sqrt(2) + +# scipy.fft wraps the fftpack versions but with normalized inverse transforms. +# So, the forward transforms and definitions are already thoroughly tested in +# fftpack/test_real_transforms.py + + +@pytest.mark.parametrize("forward, backward", [make_xp_pytest_param(dct, idct), + make_xp_pytest_param(dst, idst)]) +@pytest.mark.parametrize("type", [1, 2, 3, 4]) +@pytest.mark.parametrize("n", [2, 3, 4, 5, 10, 16]) +@pytest.mark.parametrize("axis", [0, 1]) +@pytest.mark.parametrize("norm", [None, 'backward', 'ortho', 'forward']) +@pytest.mark.parametrize("orthogonalize", [False, True]) +def test_identity_1d(forward, backward, type, n, axis, norm, orthogonalize, xp): + # Test the identity f^-1(f(x)) == x + x = xp.asarray(np.random.rand(n, n)) + + y = forward(x, type, axis=axis, norm=norm, orthogonalize=orthogonalize) + z = backward(y, type, axis=axis, norm=norm, orthogonalize=orthogonalize) + xp_assert_close(z, x) + + pad = [(0, 0)] * 2 + pad[axis] = (0, 4) + + y2 = xp.asarray(np.pad(np.asarray(y), pad, mode='edge')) + z2 = backward(y2, type, n, axis, norm, orthogonalize=orthogonalize) + xp_assert_close(z2, x) + + +@skip_xp_backends(np_only=True, + reason='`overwrite_x` only supported for NumPy backend.') +@pytest.mark.parametrize("forward, backward", [(dct, idct), (dst, idst)]) +@pytest.mark.parametrize("type", [1, 2, 3, 4]) +@pytest.mark.parametrize("dtype", [np.float16, np.float32, np.float64, + np.complex64, np.complex128]) +@pytest.mark.parametrize("axis", [0, 1]) +@pytest.mark.parametrize("norm", [None, 'backward', 'ortho', 'forward']) +@pytest.mark.parametrize("overwrite_x", [True, False]) +def test_identity_1d_overwrite(forward, backward, type, dtype, axis, norm, + overwrite_x, xp): + # Test the identity f^-1(f(x)) == x + x = np.random.rand(7, 8).astype(dtype) + x_orig = x.copy() + + y = forward(x, type, axis=axis, norm=norm, overwrite_x=overwrite_x) + y_orig = y.copy() + z = backward(y, type, axis=axis, norm=norm, overwrite_x=overwrite_x) + if not overwrite_x: + assert_allclose(z, x, rtol=1e-6, atol=1e-6) + assert_array_equal(x, x_orig) + assert_array_equal(y, y_orig) + else: + assert_allclose(z, x_orig, rtol=1e-6, atol=1e-6) + + +@pytest.mark.parametrize("forward, backward", [make_xp_pytest_param(dctn, idctn), + make_xp_pytest_param(dstn, idstn)]) +@pytest.mark.parametrize("type", [1, 2, 3, 4]) +@pytest.mark.parametrize("shape, axes", + [ + ((4, 4), 0), + ((4, 4), 1), + ((4, 4), None), + ((4, 4), (0, 1)), + ((10, 12), None), + ((10, 12), (0, 1)), + ((4, 5, 6), None), + ((4, 5, 6), 1), + ((4, 5, 6), (0, 2)), + ]) +@pytest.mark.parametrize("norm", [None, 'backward', 'ortho', 'forward']) +@pytest.mark.parametrize("orthogonalize", [False, True]) +def test_identity_nd(forward, backward, type, shape, axes, norm, + orthogonalize, xp): + # Test the identity f^-1(f(x)) == x + + x = xp.asarray(np.random.random(shape)) + + if axes is not None: + shape = np.take(shape, axes) + + y = forward(x, type, axes=axes, norm=norm, orthogonalize=orthogonalize) + z = backward(y, type, axes=axes, norm=norm, orthogonalize=orthogonalize) + xp_assert_close(z, x) + + if axes is None: + pad = [(0, 4)] * x.ndim + elif isinstance(axes, int): + pad = [(0, 0)] * x.ndim + pad[axes] = (0, 4) + else: + pad = [(0, 0)] * x.ndim + + for a in axes: + pad[a] = (0, 4) + + # TODO write an array-agnostic pad + y2 = xp.asarray(np.pad(np.asarray(y), pad, mode='edge')) + z2 = backward(y2, type, shape, axes, norm, orthogonalize=orthogonalize) + xp_assert_close(z2, x) + + +@skip_xp_backends(np_only=True, + reason='`overwrite_x` only supported for NumPy backend.') +@pytest.mark.parametrize("forward, backward", [(dctn, idctn), (dstn, idstn)]) +@pytest.mark.parametrize("type", [1, 2, 3, 4]) +@pytest.mark.parametrize("shape, axes", + [ + ((4, 5), 0), + ((4, 5), 1), + ((4, 5), None), + ]) +@pytest.mark.parametrize("dtype", [np.float16, np.float32, np.float64, + np.complex64, np.complex128]) +@pytest.mark.parametrize("norm", [None, 'backward', 'ortho', 'forward']) +@pytest.mark.parametrize("overwrite_x", [False, True]) +def test_identity_nd_overwrite(forward, backward, type, shape, axes, dtype, + norm, overwrite_x, xp): + # Test the identity f^-1(f(x)) == x + + x = np.random.random(shape).astype(dtype) + x_orig = x.copy() + + if axes is not None: + shape = np.take(shape, axes) + + y = forward(x, type, axes=axes, norm=norm) + y_orig = y.copy() + z = backward(y, type, axes=axes, norm=norm) + if overwrite_x: + assert_allclose(z, x_orig, rtol=1e-6, atol=1e-6) + else: + assert_allclose(z, x, rtol=1e-6, atol=1e-6) + assert_array_equal(x, x_orig) + assert_array_equal(y, y_orig) + + +@pytest.mark.parametrize("func", [make_xp_pytest_param(dct), + make_xp_pytest_param(dst), + make_xp_pytest_param(dctn), + make_xp_pytest_param(dstn)]) +@pytest.mark.parametrize("type", [1, 2, 3, 4]) +@pytest.mark.parametrize("norm", [None, 'backward', 'ortho', 'forward']) +def test_fftpack_equivalience(func, type, norm, xp): + x = np.random.rand(8, 16) + fftpack_res = xp.asarray(getattr(fftpack, func.__name__)(x, type, norm=norm)) + x = xp.asarray(x) + fft_res = getattr(fft, func.__name__)(x, type, norm=norm) + + xp_assert_close(fft_res, fftpack_res) + + +@pytest.mark.parametrize("func", [make_xp_pytest_param(dct), + make_xp_pytest_param(dst), + make_xp_pytest_param(dctn), + make_xp_pytest_param(dstn)]) +@pytest.mark.parametrize("type", [1, 2, 3, 4]) +def test_orthogonalize_default(func, type, xp): + # Test orthogonalize is the default when norm="ortho", but not otherwise + x = xp.asarray(np.random.rand(100)) + + for norm, ortho in [ + ("forward", False), + ("backward", False), + ("ortho", True), + ]: + a = func(x, type=type, norm=norm, orthogonalize=ortho) + b = func(x, type=type, norm=norm) + xp_assert_close(a, b) + + +@pytest.mark.parametrize("norm", ["backward", "ortho", "forward"]) +@pytest.mark.parametrize("func, type", [make_xp_pytest_param(dct, 4), + make_xp_pytest_param(dst, 1), + make_xp_pytest_param(dst, 4)]) +def test_orthogonalize_noop(func, type, norm, xp): + # Transforms where orthogonalize is a no-op + x = xp.asarray(np.random.rand(100)) + y1 = func(x, type=type, norm=norm, orthogonalize=True) + y2 = func(x, type=type, norm=norm, orthogonalize=False) + xp_assert_close(y1, y2) + + +@make_xp_test_case(dct) +@pytest.mark.parametrize("norm", ["backward", "ortho", "forward"]) +def test_orthogonalize_dct1(norm, xp): + x = xp.asarray(np.random.rand(100)) + + x2 = xp_copy(x, xp=xp) + xpx.at(x2, 0).multiply(SQRT_2) + xpx.at(x2, -1).multiply(SQRT_2) + + y1 = dct(x, type=1, norm=norm, orthogonalize=True) + y2 = dct(x2, type=1, norm=norm, orthogonalize=False) + + xpx.at(y2, 0).divide(SQRT_2) + xpx.at(y2, -1).divide(SQRT_2) + xp_assert_close(y1, y2) + + + +@pytest.mark.parametrize("norm", ["backward", "ortho", "forward"]) +@pytest.mark.parametrize("func", [make_xp_pytest_param(dct), + make_xp_pytest_param(dst)]) +def test_orthogonalize_dcst2(func, norm, xp): + x = xp.asarray(np.random.rand(100)) + y1 = func(x, type=2, norm=norm, orthogonalize=True) + y2 = func(x, type=2, norm=norm, orthogonalize=False) + + xpx.at(y2, 0 if func.__name__ == "dct" else -1).divide(SQRT_2) + xp_assert_close(y1, y2) + + +@pytest.mark.parametrize("norm", ["backward", "ortho", "forward"]) +@pytest.mark.parametrize("func", [make_xp_pytest_param(dct), + make_xp_pytest_param(dst)]) +def test_orthogonalize_dcst3(func, norm, xp): + x = xp.asarray(np.random.rand(100)) + x2 = xp_copy(x, xp=xp) + xpx.at(x2, 0 if func.__name__ == "dct" else -1).multiply(SQRT_2) + + y1 = func(x, type=3, norm=norm, orthogonalize=True) + y2 = func(x2, type=3, norm=norm, orthogonalize=False) + xp_assert_close(y1, y2) + + +@skip_xp_backends(np_only=True, + reason='array-likes only supported for NumPy backend') +@pytest.mark.parametrize("func", [dct, idct, dctn, idctn, dst, idst, dstn, idstn]) +def test_array_like(xp, func): + x = [[[1.0, 1.0], [1.0, 1.0]], + [[1.0, 1.0], [1.0, 1.0]], + [[1.0, 1.0], [1.0, 1.0]]] + xp_assert_close(func(x), func(xp.asarray(x))) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ffade2775675b2a563513071e808493e2a28b93c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/_basic.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/_basic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..179a19cdb6ca516b75386450aada732f7a55ddec Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/_basic.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/_helper.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/_helper.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f6d41779679f15176c8f4975c0bfd547168c8f51 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/_helper.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/_pseudo_diffs.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/_pseudo_diffs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..48207c9f2a93ef0f5ea58a294607a18500f356e3 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/_pseudo_diffs.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/_realtransforms.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/_realtransforms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a7a56eb764a79c523985664487c37bd7595bffec Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/_realtransforms.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/basic.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/basic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..13fbf7c117d2251e312ff1a801009978c3653d29 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/basic.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/helper.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/helper.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8e1f4ca1b2c4582130a6910c580be2a799acf1c5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/helper.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/pseudo_diffs.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/pseudo_diffs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..41883599aef95879994e3fd72f7bd1e2b31e6ee2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/pseudo_diffs.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/realtransforms.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/realtransforms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bf4407b8802c8f00bec1b205f529fd50d2ab8a41 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/__pycache__/realtransforms.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..caa3abca4f8f756f85e3ab58a75e2cdeb51cff7c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/test_basic.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/test_basic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..377cdb3d3ccf3349f9044054e0c917163f577c95 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/test_basic.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/test_helper.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/test_helper.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c1082d671dc2d839fca94f72277acdcc1a12450c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/test_helper.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/test_import.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/test_import.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6fa96808a60460916c0cfc1c5c21fc438acbce6b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/test_import.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/test_pseudo_diffs.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/test_pseudo_diffs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e81290892bde65e402c7a66a4829e648f674b357 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/test_pseudo_diffs.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/test_real_transforms.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/test_real_transforms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..386d331495ee9d85d12bac5bbdfc7a8481ce0470 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/__pycache__/test_real_transforms.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/test_basic.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/test_basic.py new file mode 100644 index 0000000000000000000000000000000000000000..b7c3523b18b69f5363fa015869b2445cb4494c3a --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/test_basic.py @@ -0,0 +1,877 @@ +# Created by Pearu Peterson, September 2002 + +from numpy.testing import (assert_, assert_equal, assert_array_almost_equal, + assert_array_almost_equal_nulp, assert_array_less) +import pytest +from pytest import raises as assert_raises +from scipy.fftpack import ifft, fft, fftn, ifftn, rfft, irfft, fft2 + +from numpy import (arange, array, asarray, zeros, dot, exp, pi, + swapaxes, double, cdouble) +import numpy as np +import numpy.fft +from numpy.random import rand + +# "large" composite numbers supported by FFTPACK +LARGE_COMPOSITE_SIZES = [ + 2**13, + 2**5 * 3**5, + 2**3 * 3**3 * 5**2, +] +SMALL_COMPOSITE_SIZES = [ + 2, + 2*3*5, + 2*2*3*3, +] +# prime +LARGE_PRIME_SIZES = [ + 2011 +] +SMALL_PRIME_SIZES = [ + 29 +] + + +def _assert_close_in_norm(x, y, rtol, size, rdt): + # helper function for testing + err_msg = f"size: {size} rdt: {rdt}" + assert_array_less(np.linalg.norm(x - y), rtol*np.linalg.norm(x), err_msg) + + +def random(size): + return rand(*size) + + +def direct_dft(x): + x = asarray(x) + n = len(x) + y = zeros(n, dtype=cdouble) + w = -arange(n)*(2j*pi/n) + for i in range(n): + y[i] = dot(exp(i*w), x) + return y + + +def direct_idft(x): + x = asarray(x) + n = len(x) + y = zeros(n, dtype=cdouble) + w = arange(n)*(2j*pi/n) + for i in range(n): + y[i] = dot(exp(i*w), x)/n + return y + + +def direct_dftn(x): + x = asarray(x) + for axis in range(len(x.shape)): + x = fft(x, axis=axis) + return x + + +def direct_idftn(x): + x = asarray(x) + for axis in range(len(x.shape)): + x = ifft(x, axis=axis) + return x + + +def direct_rdft(x): + x = asarray(x) + n = len(x) + w = -arange(n)*(2j*pi/n) + r = zeros(n, dtype=double) + for i in range(n//2+1): + y = dot(exp(i*w), x) + if i: + r[2*i-1] = y.real + if 2*i < n: + r[2*i] = y.imag + else: + r[0] = y.real + return r + + +def direct_irdft(x): + x = asarray(x) + n = len(x) + x1 = zeros(n, dtype=cdouble) + for i in range(n//2+1): + if i: + if 2*i < n: + x1[i] = x[2*i-1] + 1j*x[2*i] + x1[n-i] = x[2*i-1] - 1j*x[2*i] + else: + x1[i] = x[2*i-1] + else: + x1[0] = x[0] + return direct_idft(x1).real + + +class _TestFFTBase: + def setup_method(self): + self.cdt = None + self.rdt = None + np.random.seed(1234) + + def test_definition(self): + x = np.array([1,2,3,4+1j,1,2,3,4+2j], dtype=self.cdt) + y = fft(x) + assert_equal(y.dtype, self.cdt) + y1 = direct_dft(x) + assert_array_almost_equal(y,y1) + x = np.array([1,2,3,4+0j,5], dtype=self.cdt) + assert_array_almost_equal(fft(x),direct_dft(x)) + + def test_n_argument_real(self): + x1 = np.array([1,2,3,4], dtype=self.rdt) + x2 = np.array([1,2,3,4], dtype=self.rdt) + y = fft([x1,x2],n=4) + assert_equal(y.dtype, self.cdt) + assert_equal(y.shape,(2,4)) + assert_array_almost_equal(y[0],direct_dft(x1)) + assert_array_almost_equal(y[1],direct_dft(x2)) + + def _test_n_argument_complex(self): + x1 = np.array([1,2,3,4+1j], dtype=self.cdt) + x2 = np.array([1,2,3,4+1j], dtype=self.cdt) + y = fft([x1,x2],n=4) + assert_equal(y.dtype, self.cdt) + assert_equal(y.shape,(2,4)) + assert_array_almost_equal(y[0],direct_dft(x1)) + assert_array_almost_equal(y[1],direct_dft(x2)) + + def test_invalid_sizes(self): + assert_raises(ValueError, fft, []) + assert_raises(ValueError, fft, [[1,1],[2,2]], -5) + + +class TestDoubleFFT(_TestFFTBase): + def setup_method(self): + self.cdt = np.complex128 + self.rdt = np.float64 + + +class TestSingleFFT(_TestFFTBase): + def setup_method(self): + self.cdt = np.complex64 + self.rdt = np.float32 + + reason = ("single-precision FFT implementation is partially disabled, " + "until accuracy issues with large prime powers are resolved") + + @pytest.mark.xfail(run=False, reason=reason) + def test_notice(self): + pass + + +class TestFloat16FFT: + + def test_1_argument_real(self): + x1 = np.array([1, 2, 3, 4], dtype=np.float16) + y = fft(x1, n=4) + assert_equal(y.dtype, np.complex64) + assert_equal(y.shape, (4, )) + assert_array_almost_equal(y, direct_dft(x1.astype(np.float32))) + + def test_n_argument_real(self): + x1 = np.array([1, 2, 3, 4], dtype=np.float16) + x2 = np.array([1, 2, 3, 4], dtype=np.float16) + y = fft([x1, x2], n=4) + assert_equal(y.dtype, np.complex64) + assert_equal(y.shape, (2, 4)) + assert_array_almost_equal(y[0], direct_dft(x1.astype(np.float32))) + assert_array_almost_equal(y[1], direct_dft(x2.astype(np.float32))) + + +class _TestIFFTBase: + def setup_method(self): + np.random.seed(1234) + + def test_definition(self): + x = np.array([1,2,3,4+1j,1,2,3,4+2j], self.cdt) + y = ifft(x) + y1 = direct_idft(x) + assert_equal(y.dtype, self.cdt) + assert_array_almost_equal(y,y1) + + x = np.array([1,2,3,4+0j,5], self.cdt) + assert_array_almost_equal(ifft(x),direct_idft(x)) + + def test_definition_real(self): + x = np.array([1,2,3,4,1,2,3,4], self.rdt) + y = ifft(x) + assert_equal(y.dtype, self.cdt) + y1 = direct_idft(x) + assert_array_almost_equal(y,y1) + + x = np.array([1,2,3,4,5], dtype=self.rdt) + assert_equal(y.dtype, self.cdt) + assert_array_almost_equal(ifft(x),direct_idft(x)) + + def test_random_complex(self): + for size in [1,51,111,100,200,64,128,256,1024]: + x = random([size]).astype(self.cdt) + x = random([size]).astype(self.cdt) + 1j*x + y1 = ifft(fft(x)) + y2 = fft(ifft(x)) + assert_equal(y1.dtype, self.cdt) + assert_equal(y2.dtype, self.cdt) + assert_array_almost_equal(y1, x) + assert_array_almost_equal(y2, x) + + def test_random_real(self): + for size in [1,51,111,100,200,64,128,256,1024]: + x = random([size]).astype(self.rdt) + y1 = ifft(fft(x)) + y2 = fft(ifft(x)) + assert_equal(y1.dtype, self.cdt) + assert_equal(y2.dtype, self.cdt) + assert_array_almost_equal(y1, x) + assert_array_almost_equal(y2, x) + + def test_size_accuracy(self): + # Sanity check for the accuracy for prime and non-prime sized inputs + if self.rdt == np.float32: + rtol = 1e-5 + elif self.rdt == np.float64: + rtol = 1e-10 + + for size in LARGE_COMPOSITE_SIZES + LARGE_PRIME_SIZES: + np.random.seed(1234) + x = np.random.rand(size).astype(self.rdt) + y = ifft(fft(x)) + _assert_close_in_norm(x, y, rtol, size, self.rdt) + y = fft(ifft(x)) + _assert_close_in_norm(x, y, rtol, size, self.rdt) + + x = (x + 1j*np.random.rand(size)).astype(self.cdt) + y = ifft(fft(x)) + _assert_close_in_norm(x, y, rtol, size, self.rdt) + y = fft(ifft(x)) + _assert_close_in_norm(x, y, rtol, size, self.rdt) + + def test_invalid_sizes(self): + assert_raises(ValueError, ifft, []) + assert_raises(ValueError, ifft, [[1,1],[2,2]], -5) + + +class TestDoubleIFFT(_TestIFFTBase): + def setup_method(self): + self.cdt = np.complex128 + self.rdt = np.float64 + + +class TestSingleIFFT(_TestIFFTBase): + def setup_method(self): + self.cdt = np.complex64 + self.rdt = np.float32 + + +class _TestRFFTBase: + def setup_method(self): + np.random.seed(1234) + + def test_definition(self): + for t in [[1, 2, 3, 4, 1, 2, 3, 4], [1, 2, 3, 4, 1, 2, 3, 4, 5]]: + x = np.array(t, dtype=self.rdt) + y = rfft(x) + y1 = direct_rdft(x) + assert_array_almost_equal(y,y1) + assert_equal(y.dtype, self.rdt) + + def test_invalid_sizes(self): + assert_raises(ValueError, rfft, []) + assert_raises(ValueError, rfft, [[1,1],[2,2]], -5) + + # See gh-5790 + class MockSeries: + def __init__(self, data): + self.data = np.asarray(data) + + def __getattr__(self, item): + try: + return getattr(self.data, item) + except AttributeError as e: + raise AttributeError("'MockSeries' object " + f"has no attribute '{item}'") from e + + def test_non_ndarray_with_dtype(self): + x = np.array([1., 2., 3., 4., 5.]) + xs = _TestRFFTBase.MockSeries(x) + + expected = [1, 2, 3, 4, 5] + rfft(xs) + + # Data should not have been overwritten + assert_equal(x, expected) + assert_equal(xs.data, expected) + + def test_complex_input(self): + assert_raises(TypeError, rfft, np.arange(4, dtype=np.complex64)) + + +class TestRFFTDouble(_TestRFFTBase): + def setup_method(self): + self.cdt = np.complex128 + self.rdt = np.float64 + + +class TestRFFTSingle(_TestRFFTBase): + def setup_method(self): + self.cdt = np.complex64 + self.rdt = np.float32 + + +class _TestIRFFTBase: + def setup_method(self): + np.random.seed(1234) + + def test_definition(self): + x1 = [1,2,3,4,1,2,3,4] + x1_1 = [1,2+3j,4+1j,2+3j,4,2-3j,4-1j,2-3j] + x2 = [1,2,3,4,1,2,3,4,5] + x2_1 = [1,2+3j,4+1j,2+3j,4+5j,4-5j,2-3j,4-1j,2-3j] + + def _test(x, xr): + y = irfft(np.array(x, dtype=self.rdt)) + y1 = direct_irdft(x) + assert_equal(y.dtype, self.rdt) + assert_array_almost_equal(y,y1, decimal=self.ndec) + assert_array_almost_equal(y,ifft(xr), decimal=self.ndec) + + _test(x1, x1_1) + _test(x2, x2_1) + + def test_random_real(self): + for size in [1,51,111,100,200,64,128,256,1024]: + x = random([size]).astype(self.rdt) + y1 = irfft(rfft(x)) + y2 = rfft(irfft(x)) + assert_equal(y1.dtype, self.rdt) + assert_equal(y2.dtype, self.rdt) + assert_array_almost_equal(y1, x, decimal=self.ndec, err_msg=f"size={size}") + assert_array_almost_equal(y2, x, decimal=self.ndec, err_msg=f"size={size}") + + def test_size_accuracy(self): + # Sanity check for the accuracy for prime and non-prime sized inputs + if self.rdt == np.float32: + rtol = 1e-5 + elif self.rdt == np.float64: + rtol = 1e-10 + + for size in LARGE_COMPOSITE_SIZES + LARGE_PRIME_SIZES: + np.random.seed(1234) + x = np.random.rand(size).astype(self.rdt) + y = irfft(rfft(x)) + _assert_close_in_norm(x, y, rtol, size, self.rdt) + y = rfft(irfft(x)) + _assert_close_in_norm(x, y, rtol, size, self.rdt) + + def test_invalid_sizes(self): + assert_raises(ValueError, irfft, []) + assert_raises(ValueError, irfft, [[1,1],[2,2]], -5) + + def test_complex_input(self): + assert_raises(TypeError, irfft, np.arange(4, dtype=np.complex64)) + + +# self.ndec is bogus; we should have a assert_array_approx_equal for number of +# significant digits + +class TestIRFFTDouble(_TestIRFFTBase): + def setup_method(self): + self.cdt = np.complex128 + self.rdt = np.float64 + self.ndec = 14 + + +class TestIRFFTSingle(_TestIRFFTBase): + def setup_method(self): + self.cdt = np.complex64 + self.rdt = np.float32 + self.ndec = 5 + + +class Testfft2: + def setup_method(self): + np.random.seed(1234) + + def test_regression_244(self): + """FFT returns wrong result with axes parameter.""" + # fftn (and hence fft2) used to break when both axes and shape were + # used + x = numpy.ones((4, 4, 2)) + y = fft2(x, shape=(8, 8), axes=(-3, -2)) + y_r = numpy.fft.fftn(x, s=(8, 8), axes=(-3, -2)) + assert_array_almost_equal(y, y_r) + + def test_invalid_sizes(self): + assert_raises(ValueError, fft2, [[]]) + assert_raises(ValueError, fft2, [[1, 1], [2, 2]], (4, -3)) + + +class TestFftnSingle: + def setup_method(self): + np.random.seed(1234) + + def test_definition(self): + x = [[1, 2, 3], + [4, 5, 6], + [7, 8, 9]] + y = fftn(np.array(x, np.float32)) + assert_(y.dtype == np.complex64, + msg="double precision output with single precision") + + y_r = np.array(fftn(x), np.complex64) + assert_array_almost_equal_nulp(y, y_r) + + @pytest.mark.parametrize('size', SMALL_COMPOSITE_SIZES + SMALL_PRIME_SIZES) + def test_size_accuracy_small(self, size): + rng = np.random.default_rng(1234) + x = rng.random((size, size)) + 1j*rng.random((size, size)) + y1 = fftn(x.real.astype(np.float32)) + y2 = fftn(x.real.astype(np.float64)).astype(np.complex64) + + assert_equal(y1.dtype, np.complex64) + assert_array_almost_equal_nulp(y1, y2, 2000) + + @pytest.mark.parametrize('size', LARGE_COMPOSITE_SIZES + LARGE_PRIME_SIZES) + def test_size_accuracy_large(self, size): + rand = np.random.default_rng(1234) + x = rand.random((size, 3)) + 1j*rand.random((size, 3)) + y1 = fftn(x.real.astype(np.float32)) + y2 = fftn(x.real.astype(np.float64)).astype(np.complex64) + + assert_equal(y1.dtype, np.complex64) + assert_array_almost_equal_nulp(y1, y2, 2000) + + def test_definition_float16(self): + x = [[1, 2, 3], + [4, 5, 6], + [7, 8, 9]] + y = fftn(np.array(x, np.float16)) + assert_equal(y.dtype, np.complex64) + y_r = np.array(fftn(x), np.complex64) + assert_array_almost_equal_nulp(y, y_r) + + @pytest.mark.parametrize('size', SMALL_COMPOSITE_SIZES + SMALL_PRIME_SIZES) + def test_float16_input_small(self, size): + rng = np.random.default_rng(1234) + x = rng.random((size, size)) + 1j * rng.random((size, size)) + y1 = fftn(x.real.astype(np.float16)) + y2 = fftn(x.real.astype(np.float64)).astype(np.complex64) + + assert_equal(y1.dtype, np.complex64) + assert_array_almost_equal_nulp(y1, y2, 5e5) + + @pytest.mark.parametrize('size', LARGE_COMPOSITE_SIZES + LARGE_PRIME_SIZES) + def test_float16_input_large(self, size): + rng = np.random.default_rng(1234) + x = rng.random((size, 3)) + 1j*rng.random((size, 3)) + y1 = fftn(x.real.astype(np.float16)) + y2 = fftn(x.real.astype(np.float64)).astype(np.complex64) + + assert_equal(y1.dtype, np.complex64) + assert_array_almost_equal_nulp(y1, y2, 2e6) + + +class TestFftn: + def setup_method(self): + np.random.seed(1234) + + def test_definition(self): + x = [[1, 2, 3], + [4, 5, 6], + [7, 8, 9]] + y = fftn(x) + assert_array_almost_equal(y, direct_dftn(x)) + + x = random((20, 26)) + assert_array_almost_equal(fftn(x), direct_dftn(x)) + + x = random((5, 4, 3, 20)) + assert_array_almost_equal(fftn(x), direct_dftn(x)) + + def test_axes_argument(self): + # plane == ji_plane, x== kji_space + plane1 = [[1, 2, 3], + [4, 5, 6], + [7, 8, 9]] + plane2 = [[10, 11, 12], + [13, 14, 15], + [16, 17, 18]] + plane3 = [[19, 20, 21], + [22, 23, 24], + [25, 26, 27]] + ki_plane1 = [[1, 2, 3], + [10, 11, 12], + [19, 20, 21]] + ki_plane2 = [[4, 5, 6], + [13, 14, 15], + [22, 23, 24]] + ki_plane3 = [[7, 8, 9], + [16, 17, 18], + [25, 26, 27]] + jk_plane1 = [[1, 10, 19], + [4, 13, 22], + [7, 16, 25]] + jk_plane2 = [[2, 11, 20], + [5, 14, 23], + [8, 17, 26]] + jk_plane3 = [[3, 12, 21], + [6, 15, 24], + [9, 18, 27]] + kj_plane1 = [[1, 4, 7], + [10, 13, 16], [19, 22, 25]] + kj_plane2 = [[2, 5, 8], + [11, 14, 17], [20, 23, 26]] + kj_plane3 = [[3, 6, 9], + [12, 15, 18], [21, 24, 27]] + ij_plane1 = [[1, 4, 7], + [2, 5, 8], + [3, 6, 9]] + ij_plane2 = [[10, 13, 16], + [11, 14, 17], + [12, 15, 18]] + ij_plane3 = [[19, 22, 25], + [20, 23, 26], + [21, 24, 27]] + ik_plane1 = [[1, 10, 19], + [2, 11, 20], + [3, 12, 21]] + ik_plane2 = [[4, 13, 22], + [5, 14, 23], + [6, 15, 24]] + ik_plane3 = [[7, 16, 25], + [8, 17, 26], + [9, 18, 27]] + ijk_space = [jk_plane1, jk_plane2, jk_plane3] + ikj_space = [kj_plane1, kj_plane2, kj_plane3] + jik_space = [ik_plane1, ik_plane2, ik_plane3] + jki_space = [ki_plane1, ki_plane2, ki_plane3] + kij_space = [ij_plane1, ij_plane2, ij_plane3] + x = array([plane1, plane2, plane3]) + + assert_array_almost_equal(fftn(x), + fftn(x, axes=(-3, -2, -1))) # kji_space + assert_array_almost_equal(fftn(x), fftn(x, axes=(0, 1, 2))) + assert_array_almost_equal(fftn(x, axes=(0, 2)), fftn(x, axes=(0, -1))) + y = fftn(x, axes=(2, 1, 0)) # ijk_space + assert_array_almost_equal(swapaxes(y, -1, -3), fftn(ijk_space)) + y = fftn(x, axes=(2, 0, 1)) # ikj_space + assert_array_almost_equal(swapaxes(swapaxes(y, -1, -3), -1, -2), + fftn(ikj_space)) + y = fftn(x, axes=(1, 2, 0)) # jik_space + assert_array_almost_equal(swapaxes(swapaxes(y, -1, -3), -3, -2), + fftn(jik_space)) + y = fftn(x, axes=(1, 0, 2)) # jki_space + assert_array_almost_equal(swapaxes(y, -2, -3), fftn(jki_space)) + y = fftn(x, axes=(0, 2, 1)) # kij_space + assert_array_almost_equal(swapaxes(y, -2, -1), fftn(kij_space)) + + y = fftn(x, axes=(-2, -1)) # ji_plane + assert_array_almost_equal(fftn(plane1), y[0]) + assert_array_almost_equal(fftn(plane2), y[1]) + assert_array_almost_equal(fftn(plane3), y[2]) + + y = fftn(x, axes=(1, 2)) # ji_plane + assert_array_almost_equal(fftn(plane1), y[0]) + assert_array_almost_equal(fftn(plane2), y[1]) + assert_array_almost_equal(fftn(plane3), y[2]) + + y = fftn(x, axes=(-3, -2)) # kj_plane + assert_array_almost_equal(fftn(x[:, :, 0]), y[:, :, 0]) + assert_array_almost_equal(fftn(x[:, :, 1]), y[:, :, 1]) + assert_array_almost_equal(fftn(x[:, :, 2]), y[:, :, 2]) + + y = fftn(x, axes=(-3, -1)) # ki_plane + assert_array_almost_equal(fftn(x[:, 0, :]), y[:, 0, :]) + assert_array_almost_equal(fftn(x[:, 1, :]), y[:, 1, :]) + assert_array_almost_equal(fftn(x[:, 2, :]), y[:, 2, :]) + + y = fftn(x, axes=(-1, -2)) # ij_plane + assert_array_almost_equal(fftn(ij_plane1), swapaxes(y[0], -2, -1)) + assert_array_almost_equal(fftn(ij_plane2), swapaxes(y[1], -2, -1)) + assert_array_almost_equal(fftn(ij_plane3), swapaxes(y[2], -2, -1)) + + y = fftn(x, axes=(-1, -3)) # ik_plane + assert_array_almost_equal(fftn(ik_plane1), + swapaxes(y[:, 0, :], -1, -2)) + assert_array_almost_equal(fftn(ik_plane2), + swapaxes(y[:, 1, :], -1, -2)) + assert_array_almost_equal(fftn(ik_plane3), + swapaxes(y[:, 2, :], -1, -2)) + + y = fftn(x, axes=(-2, -3)) # jk_plane + assert_array_almost_equal(fftn(jk_plane1), + swapaxes(y[:, :, 0], -1, -2)) + assert_array_almost_equal(fftn(jk_plane2), + swapaxes(y[:, :, 1], -1, -2)) + assert_array_almost_equal(fftn(jk_plane3), + swapaxes(y[:, :, 2], -1, -2)) + + y = fftn(x, axes=(-1,)) # i_line + for i in range(3): + for j in range(3): + assert_array_almost_equal(fft(x[i, j, :]), y[i, j, :]) + y = fftn(x, axes=(-2,)) # j_line + for i in range(3): + for j in range(3): + assert_array_almost_equal(fft(x[i, :, j]), y[i, :, j]) + y = fftn(x, axes=(0,)) # k_line + for i in range(3): + for j in range(3): + assert_array_almost_equal(fft(x[:, i, j]), y[:, i, j]) + + y = fftn(x, axes=()) # point + assert_array_almost_equal(y, x) + + def test_shape_argument(self): + small_x = [[1, 2, 3], + [4, 5, 6]] + large_x1 = [[1, 2, 3, 0], + [4, 5, 6, 0], + [0, 0, 0, 0], + [0, 0, 0, 0]] + + y = fftn(small_x, shape=(4, 4)) + assert_array_almost_equal(y, fftn(large_x1)) + + y = fftn(small_x, shape=(3, 4)) + assert_array_almost_equal(y, fftn(large_x1[:-1])) + + def test_shape_axes_argument(self): + small_x = [[1, 2, 3], + [4, 5, 6], + [7, 8, 9]] + large_x1 = array([[1, 2, 3, 0], + [4, 5, 6, 0], + [7, 8, 9, 0], + [0, 0, 0, 0]]) + y = fftn(small_x, shape=(4, 4), axes=(-2, -1)) + assert_array_almost_equal(y, fftn(large_x1)) + y = fftn(small_x, shape=(4, 4), axes=(-1, -2)) + + assert_array_almost_equal(y, swapaxes( + fftn(swapaxes(large_x1, -1, -2)), -1, -2)) + + def test_shape_axes_argument2(self): + # Change shape of the last axis + x = numpy.random.random((10, 5, 3, 7)) + y = fftn(x, axes=(-1,), shape=(8,)) + assert_array_almost_equal(y, fft(x, axis=-1, n=8)) + + # Change shape of an arbitrary axis which is not the last one + x = numpy.random.random((10, 5, 3, 7)) + y = fftn(x, axes=(-2,), shape=(8,)) + assert_array_almost_equal(y, fft(x, axis=-2, n=8)) + + # Change shape of axes: cf #244, where shape and axes were mixed up + x = numpy.random.random((4, 4, 2)) + y = fftn(x, axes=(-3, -2), shape=(8, 8)) + assert_array_almost_equal(y, + numpy.fft.fftn(x, axes=(-3, -2), s=(8, 8))) + + def test_shape_argument_more(self): + x = zeros((4, 4, 2)) + with assert_raises(ValueError, + match="when given, axes and shape arguments" + " have to be of the same length"): + fftn(x, shape=(8, 8, 2, 1)) + + def test_invalid_sizes(self): + with assert_raises(ValueError, + match="invalid number of data points" + r" \(\[1, 0\]\) specified"): + fftn([[]]) + + with assert_raises(ValueError, + match="invalid number of data points" + r" \(\[4, -3\]\) specified"): + fftn([[1, 1], [2, 2]], (4, -3)) + + +class TestIfftn: + dtype = None + cdtype = None + + def setup_method(self): + np.random.seed(1234) + + @pytest.mark.parametrize('dtype,cdtype,maxnlp', + [(np.float64, np.complex128, 2000), + (np.float32, np.complex64, 3500)]) + def test_definition(self, dtype, cdtype, maxnlp): + rng = np.random.default_rng(1234) + x = np.array([[1, 2, 3], + [4, 5, 6], + [7, 8, 9]], dtype=dtype) + y = ifftn(x) + assert_equal(y.dtype, cdtype) + assert_array_almost_equal_nulp(y, direct_idftn(x), maxnlp) + + x = rng.random((20, 26)) + assert_array_almost_equal_nulp(ifftn(x), direct_idftn(x), maxnlp) + + x = rng.random((5, 4, 3, 20)) + assert_array_almost_equal_nulp(ifftn(x), direct_idftn(x), maxnlp) + + @pytest.mark.parametrize('maxnlp', [2000, 3500]) + @pytest.mark.parametrize('size', [1, 2, 51, 32, 64, 92]) + def test_random_complex(self, maxnlp, size): + rng = np.random.default_rng(1234) + x = rng.random([size, size]) + 1j * rng.random([size, size]) + assert_array_almost_equal_nulp(ifftn(fftn(x)), x, maxnlp) + assert_array_almost_equal_nulp(fftn(ifftn(x)), x, maxnlp) + + def test_invalid_sizes(self): + with assert_raises(ValueError, + match="invalid number of data points" + r" \(\[1, 0\]\) specified"): + ifftn([[]]) + + with assert_raises(ValueError, + match="invalid number of data points" + r" \(\[4, -3\]\) specified"): + ifftn([[1, 1], [2, 2]], (4, -3)) + + +class FakeArray: + def __init__(self, data): + self._data = data + self.__array_interface__ = data.__array_interface__ + + +class FakeArray2: + def __init__(self, data): + self._data = data + + def __array__(self, dtype=None, copy=None): + return self._data + + +class TestOverwrite: + """Check input overwrite behavior of the FFT functions.""" + + real_dtypes = (np.float32, np.float64) + dtypes = real_dtypes + (np.complex64, np.complex128) + fftsizes = [8, 16, 32] + + def _check(self, x, routine, fftsize, axis, overwrite_x): + x2 = x.copy() + for fake in [lambda x: x, FakeArray, FakeArray2]: + routine(fake(x2), fftsize, axis, overwrite_x=overwrite_x) + + sig = (f"{routine.__name__}({x.dtype}{x.shape!r}, {fftsize!r}, " + f"axis={axis!r}, overwrite_x={overwrite_x!r})") + if not overwrite_x: + assert_equal(x2, x, err_msg=f"spurious overwrite in {sig}") + + def _check_1d(self, routine, dtype, shape, axis, overwritable_dtypes, + fftsize, overwrite_x): + np.random.seed(1234) + if np.issubdtype(dtype, np.complexfloating): + data = np.random.randn(*shape) + 1j*np.random.randn(*shape) + else: + data = np.random.randn(*shape) + data = data.astype(dtype) + + self._check(data, routine, fftsize, axis, + overwrite_x=overwrite_x) + + @pytest.mark.parametrize('dtype', dtypes) + @pytest.mark.parametrize('fftsize', fftsizes) + @pytest.mark.parametrize('overwrite_x', [True, False]) + @pytest.mark.parametrize('shape,axes', [((16,), -1), + ((16, 2), 0), + ((2, 16), 1)]) + def test_fft_ifft(self, dtype, fftsize, overwrite_x, shape, axes): + overwritable = (np.complex128, np.complex64) + self._check_1d(fft, dtype, shape, axes, overwritable, + fftsize, overwrite_x) + self._check_1d(ifft, dtype, shape, axes, overwritable, + fftsize, overwrite_x) + + @pytest.mark.parametrize('dtype', real_dtypes) + @pytest.mark.parametrize('fftsize', fftsizes) + @pytest.mark.parametrize('overwrite_x', [True, False]) + @pytest.mark.parametrize('shape,axes', [((16,), -1), + ((16, 2), 0), + ((2, 16), 1)]) + def test_rfft_irfft(self, dtype, fftsize, overwrite_x, shape, axes): + overwritable = self.real_dtypes + self._check_1d(irfft, dtype, shape, axes, overwritable, + fftsize, overwrite_x) + self._check_1d(rfft, dtype, shape, axes, overwritable, + fftsize, overwrite_x) + + def _check_nd_one(self, routine, dtype, shape, axes, overwritable_dtypes, + overwrite_x): + np.random.seed(1234) + if np.issubdtype(dtype, np.complexfloating): + data = np.random.randn(*shape) + 1j*np.random.randn(*shape) + else: + data = np.random.randn(*shape) + data = data.astype(dtype) + + def fftshape_iter(shp): + if len(shp) <= 0: + yield () + else: + for j in (shp[0]//2, shp[0], shp[0]*2): + for rest in fftshape_iter(shp[1:]): + yield (j,) + rest + + if axes is None: + part_shape = shape + else: + part_shape = tuple(np.take(shape, axes)) + + for fftshape in fftshape_iter(part_shape): + self._check(data, routine, fftshape, axes, + overwrite_x=overwrite_x) + if data.ndim > 1: + self._check(data.T, routine, fftshape, axes, + overwrite_x=overwrite_x) + + @pytest.mark.parametrize('dtype', dtypes) + @pytest.mark.parametrize('overwrite_x', [True, False]) + @pytest.mark.parametrize('shape,axes', [((16,), None), + ((16,), (0,)), + ((16, 2), (0,)), + ((2, 16), (1,)), + ((8, 16), None), + ((8, 16), (0, 1)), + ((8, 16, 2), (0, 1)), + ((8, 16, 2), (1, 2)), + ((8, 16, 2), (0,)), + ((8, 16, 2), (1,)), + ((8, 16, 2), (2,)), + ((8, 16, 2), None), + ((8, 16, 2), (0, 1, 2))]) + def test_fftn_ifftn(self, dtype, overwrite_x, shape, axes): + overwritable = (np.complex128, np.complex64) + self._check_nd_one(fftn, dtype, shape, axes, overwritable, + overwrite_x) + self._check_nd_one(ifftn, dtype, shape, axes, overwritable, + overwrite_x) + + +@pytest.mark.parametrize('func', [fftn, ifftn, fft2]) +def test_shape_axes_ndarray(func): + # Test fftn and ifftn work with NumPy arrays for shape and axes arguments + # Regression test for gh-13342 + a = np.random.rand(10, 10) + + expect = func(a, shape=(5, 5)) + actual = func(a, shape=np.array([5, 5])) + assert_equal(expect, actual) + + expect = func(a, axes=(-1,)) + actual = func(a, axes=np.array([-1,])) + assert_equal(expect, actual) + + expect = func(a, shape=(4, 7), axes=(1, 0)) + actual = func(a, shape=np.array([4, 7]), axes=np.array([1, 0])) + assert_equal(expect, actual) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/test_helper.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/test_helper.py new file mode 100644 index 0000000000000000000000000000000000000000..5e7be04f3c0291502b50b101db82d299aadc7772 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/test_helper.py @@ -0,0 +1,54 @@ +# Created by Pearu Peterson, September 2002 + +__usage__ = """ +Build fftpack: + python setup_fftpack.py build +Run tests if scipy is installed: + python -c 'import scipy;scipy.fftpack.test()' +Run tests if fftpack is not installed: + python tests/test_helper.py [] +""" + +from numpy.testing import assert_array_almost_equal +from scipy.fftpack import fftshift, ifftshift, fftfreq, rfftfreq + +from numpy import pi, random + +class TestFFTShift: + + def test_definition(self): + x = [0,1,2,3,4,-4,-3,-2,-1] + y = [-4,-3,-2,-1,0,1,2,3,4] + assert_array_almost_equal(fftshift(x),y) + assert_array_almost_equal(ifftshift(y),x) + x = [0,1,2,3,4,-5,-4,-3,-2,-1] + y = [-5,-4,-3,-2,-1,0,1,2,3,4] + assert_array_almost_equal(fftshift(x),y) + assert_array_almost_equal(ifftshift(y),x) + + def test_inverse(self): + for n in [1,4,9,100,211]: + x = random.random((n,)) + assert_array_almost_equal(ifftshift(fftshift(x)),x) + + +class TestFFTFreq: + + def test_definition(self): + x = [0,1,2,3,4,-4,-3,-2,-1] + assert_array_almost_equal(9*fftfreq(9),x) + assert_array_almost_equal(9*pi*fftfreq(9,pi),x) + x = [0,1,2,3,4,-5,-4,-3,-2,-1] + assert_array_almost_equal(10*fftfreq(10),x) + assert_array_almost_equal(10*pi*fftfreq(10,pi),x) + + +class TestRFFTFreq: + + def test_definition(self): + x = [0,1,1,2,2,3,3,4,4] + assert_array_almost_equal(9*rfftfreq(9),x) + assert_array_almost_equal(9*pi*rfftfreq(9,pi),x) + x = [0,1,1,2,2,3,3,4,4,5] + assert_array_almost_equal(10*rfftfreq(10),x) + assert_array_almost_equal(10*pi*rfftfreq(10,pi),x) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/test_import.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/test_import.py new file mode 100644 index 0000000000000000000000000000000000000000..e71aec9bd07cd4ef486b7e74b9589b6f1634d629 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/test_import.py @@ -0,0 +1,33 @@ +"""Test possibility of patching fftpack with pyfftw. + +No module source outside of scipy.fftpack should contain an import of +the form `from scipy.fftpack import ...`, so that a simple replacement +of scipy.fftpack by the corresponding fftw interface completely swaps +the two FFT implementations. + +Because this simply inspects source files, we only need to run the test +on one version of Python. +""" + + +from pathlib import Path +import re +import tokenize +import pytest +from numpy.testing import assert_ +import scipy + +class TestFFTPackImport: + @pytest.mark.slow + def test_fftpack_import(self): + base = Path(scipy.__file__).parent + regexp = r"\s*from.+\.fftpack import .*\n" + for path in base.rglob("*.py"): + if base / "fftpack" in path.parents: + continue + # use tokenize to auto-detect encoding on systems where no + # default encoding is defined (e.g., LANG='C') + with tokenize.open(str(path)) as file: + assert_(all(not re.fullmatch(regexp, line) + for line in file), + f"{path} contains an import from fftpack") diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/test_pseudo_diffs.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/test_pseudo_diffs.py new file mode 100644 index 0000000000000000000000000000000000000000..0a92729626a280c12aa3197e99b0d58ce00812d9 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/test_pseudo_diffs.py @@ -0,0 +1,388 @@ +# Created by Pearu Peterson, September 2002 + +__usage__ = """ +Build fftpack: + python setup_fftpack.py build +Run tests if scipy is installed: + python -c 'import scipy;scipy.fftpack.test()' +Run tests if fftpack is not installed: + python tests/test_pseudo_diffs.py [] +""" + +from numpy.testing import (assert_equal, assert_almost_equal, + assert_array_almost_equal) +from scipy.fftpack import (diff, fft, ifft, tilbert, itilbert, hilbert, + ihilbert, shift, fftfreq, cs_diff, sc_diff, + ss_diff, cc_diff) + +import numpy as np +from numpy import arange, sin, cos, pi, exp, tanh, sum, sign +from numpy.random import random + + +def direct_diff(x,k=1,period=None): + fx = fft(x) + n = len(fx) + if period is None: + period = 2*pi + w = fftfreq(n)*2j*pi/period*n + if k < 0: + w = 1 / w**k + w[0] = 0.0 + else: + w = w**k + if n > 2000: + w[250:n-250] = 0.0 + return ifft(w*fx).real + + +def direct_tilbert(x,h=1,period=None): + fx = fft(x) + n = len(fx) + if period is None: + period = 2*pi + w = fftfreq(n)*h*2*pi/period*n + w[0] = 1 + w = 1j/tanh(w) + w[0] = 0j + return ifft(w*fx) + + +def direct_itilbert(x,h=1,period=None): + fx = fft(x) + n = len(fx) + if period is None: + period = 2*pi + w = fftfreq(n)*h*2*pi/period*n + w = -1j*tanh(w) + return ifft(w*fx) + + +def direct_hilbert(x): + fx = fft(x) + n = len(fx) + w = fftfreq(n)*n + w = 1j*sign(w) + return ifft(w*fx) + + +def direct_ihilbert(x): + return -direct_hilbert(x) + + +def direct_shift(x,a,period=None): + n = len(x) + if period is None: + k = fftfreq(n)*1j*n + else: + k = fftfreq(n)*2j*pi/period*n + return ifft(fft(x)*exp(k*a)).real + + +class TestDiff: + + def test_definition(self): + for n in [16,17,64,127,32]: + x = arange(n)*2*pi/n + assert_array_almost_equal(diff(sin(x)),direct_diff(sin(x))) + assert_array_almost_equal(diff(sin(x),2),direct_diff(sin(x),2)) + assert_array_almost_equal(diff(sin(x),3),direct_diff(sin(x),3)) + assert_array_almost_equal(diff(sin(x),4),direct_diff(sin(x),4)) + assert_array_almost_equal(diff(sin(x),5),direct_diff(sin(x),5)) + assert_array_almost_equal(diff(sin(2*x),3),direct_diff(sin(2*x),3)) + assert_array_almost_equal(diff(sin(2*x),4),direct_diff(sin(2*x),4)) + assert_array_almost_equal(diff(cos(x)),direct_diff(cos(x))) + assert_array_almost_equal(diff(cos(x),2),direct_diff(cos(x),2)) + assert_array_almost_equal(diff(cos(x),3),direct_diff(cos(x),3)) + assert_array_almost_equal(diff(cos(x),4),direct_diff(cos(x),4)) + assert_array_almost_equal(diff(cos(2*x)),direct_diff(cos(2*x))) + assert_array_almost_equal(diff(sin(x*n/8)),direct_diff(sin(x*n/8))) + assert_array_almost_equal(diff(cos(x*n/8)),direct_diff(cos(x*n/8))) + for k in range(5): + assert_array_almost_equal(diff(sin(4*x),k),direct_diff(sin(4*x),k)) + assert_array_almost_equal(diff(cos(4*x),k),direct_diff(cos(4*x),k)) + + def test_period(self): + for n in [17,64]: + x = arange(n)/float(n) + assert_array_almost_equal(diff(sin(2*pi*x),period=1), + 2*pi*cos(2*pi*x)) + assert_array_almost_equal(diff(sin(2*pi*x),3,period=1), + -(2*pi)**3*cos(2*pi*x)) + + def test_sin(self): + for n in [32,64,77]: + x = arange(n)*2*pi/n + assert_array_almost_equal(diff(sin(x)),cos(x)) + assert_array_almost_equal(diff(cos(x)),-sin(x)) + assert_array_almost_equal(diff(sin(x),2),-sin(x)) + assert_array_almost_equal(diff(sin(x),4),sin(x)) + assert_array_almost_equal(diff(sin(4*x)),4*cos(4*x)) + assert_array_almost_equal(diff(sin(sin(x))),cos(x)*cos(sin(x))) + + def test_expr(self): + for n in [64,77,100,128,256,512,1024,2048,4096,8192][:5]: + x = arange(n)*2*pi/n + f = sin(x)*cos(4*x)+exp(sin(3*x)) + df = cos(x)*cos(4*x)-4*sin(x)*sin(4*x)+3*cos(3*x)*exp(sin(3*x)) + ddf = -17*sin(x)*cos(4*x)-8*cos(x)*sin(4*x)\ + - 9*sin(3*x)*exp(sin(3*x))+9*cos(3*x)**2*exp(sin(3*x)) + d1 = diff(f) + assert_array_almost_equal(d1,df) + assert_array_almost_equal(diff(df),ddf) + assert_array_almost_equal(diff(f,2),ddf) + assert_array_almost_equal(diff(ddf,-1),df) + + def test_expr_large(self): + for n in [2048,4096]: + x = arange(n)*2*pi/n + f = sin(x)*cos(4*x)+exp(sin(3*x)) + df = cos(x)*cos(4*x)-4*sin(x)*sin(4*x)+3*cos(3*x)*exp(sin(3*x)) + ddf = -17*sin(x)*cos(4*x)-8*cos(x)*sin(4*x)\ + - 9*sin(3*x)*exp(sin(3*x))+9*cos(3*x)**2*exp(sin(3*x)) + assert_array_almost_equal(diff(f),df) + assert_array_almost_equal(diff(df),ddf) + assert_array_almost_equal(diff(ddf,-1),df) + assert_array_almost_equal(diff(f,2),ddf) + + def test_int(self): + n = 64 + x = arange(n)*2*pi/n + assert_array_almost_equal(diff(sin(x),-1),-cos(x)) + assert_array_almost_equal(diff(sin(x),-2),-sin(x)) + assert_array_almost_equal(diff(sin(x),-4),sin(x)) + assert_array_almost_equal(diff(2*cos(2*x),-1),sin(2*x)) + + def test_random_even(self): + rng = np.random.default_rng(1234) + for k in [0,2,4,6]: + for n in [60,32,64,56,55]: + f = rng.random((n,)) + af = sum(f,axis=0)/n + f = f-af + # zeroing Nyquist mode: + f = diff(diff(f,1),-1) + assert_almost_equal(sum(f,axis=0),0.0) + assert_array_almost_equal(diff(diff(f,k),-k),f) + assert_array_almost_equal(diff(diff(f,-k),k),f) + + def test_random_odd(self): + rng = np.random.default_rng(1234) + for k in [0,1,2,3,4,5,6]: + for n in [33,65,55]: + f = rng.random((n,)) + af = sum(f,axis=0)/n + f = f-af + assert_almost_equal(sum(f,axis=0),0.0) + assert_array_almost_equal(diff(diff(f,k),-k),f) + assert_array_almost_equal(diff(diff(f,-k),k),f) + + def test_zero_nyquist(self): + rng = np.random.default_rng(1234) + for k in [0,1,2,3,4,5,6]: + for n in [32,33,64,56,55]: + f = rng.random((n,)) + af = sum(f,axis=0)/n + f = f-af + # zeroing Nyquist mode: + f = diff(diff(f,1),-1) + assert_almost_equal(sum(f,axis=0),0.0) + assert_array_almost_equal(diff(diff(f,k),-k),f) + assert_array_almost_equal(diff(diff(f,-k),k),f) + + +class TestTilbert: + + def test_definition(self): + for h in [0.1,0.5,1,5.5,10]: + for n in [16,17,64,127]: + x = arange(n)*2*pi/n + y = tilbert(sin(x),h) + y1 = direct_tilbert(sin(x),h) + assert_array_almost_equal(y,y1) + assert_array_almost_equal(tilbert(sin(x),h), + direct_tilbert(sin(x),h)) + assert_array_almost_equal(tilbert(sin(2*x),h), + direct_tilbert(sin(2*x),h)) + + def test_random_even(self): + for h in [0.1,0.5,1,5.5,10]: + for n in [32,64,56]: + f = random((n,)) + af = sum(f,axis=0)/n + f = f-af + assert_almost_equal(sum(f,axis=0),0.0) + assert_array_almost_equal(direct_tilbert(direct_itilbert(f,h),h),f) + + def test_random_odd(self): + rng = np.random.default_rng(1234) + for h in [0.1,0.5,1,5.5,10]: + for n in [33,65,55]: + f = rng.random((n,)) + af = sum(f,axis=0)/n + f = f-af + assert_almost_equal(sum(f,axis=0),0.0) + assert_array_almost_equal(itilbert(tilbert(f,h),h),f) + assert_array_almost_equal(tilbert(itilbert(f,h),h),f) + + +class TestITilbert: + + def test_definition(self): + for h in [0.1,0.5,1,5.5,10]: + for n in [16,17,64,127]: + x = arange(n)*2*pi/n + y = itilbert(sin(x),h) + y1 = direct_itilbert(sin(x),h) + assert_array_almost_equal(y,y1) + assert_array_almost_equal(itilbert(sin(x),h), + direct_itilbert(sin(x),h)) + assert_array_almost_equal(itilbert(sin(2*x),h), + direct_itilbert(sin(2*x),h)) + + +class TestHilbert: + + def test_definition(self): + for n in [16,17,64,127]: + x = arange(n)*2*pi/n + y = hilbert(sin(x)) + y1 = direct_hilbert(sin(x)) + assert_array_almost_equal(y,y1) + assert_array_almost_equal(hilbert(sin(2*x)), + direct_hilbert(sin(2*x))) + + def test_tilbert_relation(self): + for n in [16,17,64,127]: + x = arange(n)*2*pi/n + f = sin(x)+cos(2*x)*sin(x) + y = hilbert(f) + y1 = direct_hilbert(f) + assert_array_almost_equal(y,y1) + y2 = tilbert(f,h=10) + assert_array_almost_equal(y,y2) + + def test_random_odd(self): + rng = np.random.default_rng(1234) + for n in [33,65,55]: + f = rng.random((n,)) + af = sum(f,axis=0)/n + f = f-af + assert_almost_equal(sum(f,axis=0),0.0) + assert_array_almost_equal(ihilbert(hilbert(f)),f) + assert_array_almost_equal(hilbert(ihilbert(f)),f) + + def test_random_even(self): + rng = np.random.default_rng(1234) + for n in [32,64,56]: + f = rng.random((n,)) + af = sum(f,axis=0)/n + f = f-af + # zeroing Nyquist mode: + f = diff(diff(f,1),-1) + assert_almost_equal(sum(f,axis=0),0.0) + assert_array_almost_equal(direct_hilbert(direct_ihilbert(f)),f) + assert_array_almost_equal(hilbert(ihilbert(f)),f) + + +class TestIHilbert: + + def test_definition(self): + for n in [16,17,64,127]: + x = arange(n)*2*pi/n + y = ihilbert(sin(x)) + y1 = direct_ihilbert(sin(x)) + assert_array_almost_equal(y,y1) + assert_array_almost_equal(ihilbert(sin(2*x)), + direct_ihilbert(sin(2*x))) + + def test_itilbert_relation(self): + for n in [16,17,64,127]: + x = arange(n)*2*pi/n + f = sin(x)+cos(2*x)*sin(x) + y = ihilbert(f) + y1 = direct_ihilbert(f) + assert_array_almost_equal(y,y1) + y2 = itilbert(f,h=10) + assert_array_almost_equal(y,y2) + + +class TestShift: + + def test_definition(self): + for n in [18,17,64,127,32,2048,256]: + x = arange(n)*2*pi/n + for a in [0.1,3]: + assert_array_almost_equal(shift(sin(x),a),direct_shift(sin(x),a)) + assert_array_almost_equal(shift(sin(x),a),sin(x+a)) + assert_array_almost_equal(shift(cos(x),a),cos(x+a)) + assert_array_almost_equal(shift(cos(2*x)+sin(x),a), + cos(2*(x+a))+sin(x+a)) + assert_array_almost_equal(shift(exp(sin(x)),a),exp(sin(x+a))) + assert_array_almost_equal(shift(sin(x),2*pi),sin(x)) + assert_array_almost_equal(shift(sin(x),pi),-sin(x)) + assert_array_almost_equal(shift(sin(x),pi/2),cos(x)) + + +class TestOverwrite: + """Check input overwrite behavior """ + + real_dtypes = (np.float32, np.float64) + dtypes = real_dtypes + (np.complex64, np.complex128) + + def _check(self, x, routine, *args, **kwargs): + x2 = x.copy() + routine(x2, *args, **kwargs) + sig = routine.__name__ + if args: + sig += repr(args) + if kwargs: + sig += repr(kwargs) + assert_equal(x2, x, err_msg=f"spurious overwrite in {sig}") + + def _check_1d(self, routine, dtype, shape, *args, **kwargs): + # rng = np.random.default_rng(1234) + rng = np.random.RandomState(1234) + # np.random.seed(1234) + if np.issubdtype(dtype, np.complexfloating): + data = rng.randn(*shape) + 1j*rng.randn(*shape) + else: + data = rng.randn(*shape) + data = data.astype(dtype) + self._check(data, routine, *args, **kwargs) + + def test_diff(self): + for dtype in self.dtypes: + self._check_1d(diff, dtype, (16,)) + + def test_tilbert(self): + for dtype in self.dtypes: + self._check_1d(tilbert, dtype, (16,), 1.6) + + def test_itilbert(self): + for dtype in self.dtypes: + self._check_1d(itilbert, dtype, (16,), 1.6) + + def test_hilbert(self): + for dtype in self.dtypes: + self._check_1d(hilbert, dtype, (16,)) + + def test_cs_diff(self): + for dtype in self.dtypes: + self._check_1d(cs_diff, dtype, (16,), 1.0, 4.0) + + def test_sc_diff(self): + for dtype in self.dtypes: + self._check_1d(sc_diff, dtype, (16,), 1.0, 4.0) + + def test_ss_diff(self): + for dtype in self.dtypes: + self._check_1d(ss_diff, dtype, (16,), 1.0, 4.0) + + def test_cc_diff(self): + for dtype in self.dtypes: + self._check_1d(cc_diff, dtype, (16,), 1.0, 4.0) + + def test_shift(self): + for dtype in self.dtypes: + self._check_1d(shift, dtype, (16,), 1.0) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/test_real_transforms.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/test_real_transforms.py new file mode 100644 index 0000000000000000000000000000000000000000..fc8d657a7fe36f28de3f94fa8f933bf6855499ab --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/fftpack/tests/test_real_transforms.py @@ -0,0 +1,836 @@ +from os.path import join, dirname +import threading + +import numpy as np +from numpy.testing import assert_array_almost_equal, assert_equal +import pytest +from pytest import raises as assert_raises + +from scipy.fftpack._realtransforms import ( + dct, idct, dst, idst, dctn, idctn, dstn, idstn) + +# Matlab reference data +MDATA = np.load(join(dirname(__file__), 'test.npz')) +X = [MDATA[f'x{i}'] for i in range(8)] +Y = [MDATA[f'y{i}'] for i in range(8)] + +# FFTW reference data: the data are organized as follows: +# * SIZES is an array containing all available sizes +# * for every type (1, 2, 3, 4) and every size, the array dct_type_size +# contains the output of the DCT applied to the input np.linspace(0, size-1, +# size) +FFTWDATA_DOUBLE = np.load(join(dirname(__file__), 'fftw_double_ref.npz')) +FFTWDATA_SINGLE = np.load(join(dirname(__file__), 'fftw_single_ref.npz')) +FFTWDATA_SIZES = FFTWDATA_DOUBLE['sizes'] + + +def fftw_dct_ref(type, size, dt): + x = np.linspace(0, size-1, size).astype(dt) + dt = np.result_type(np.float32, dt) + if dt == np.float64: + data = FFTWDATA_DOUBLE + elif dt == np.float32: + data = FFTWDATA_SINGLE + else: + raise ValueError() + y = (data[f'dct_{type}_{size}']).astype(dt) + return x, y, dt + + +def fftw_dst_ref(type, size, dt): + x = np.linspace(0, size-1, size).astype(dt) + dt = np.result_type(np.float32, dt) + if dt == np.float64: + data = FFTWDATA_DOUBLE + elif dt == np.float32: + data = FFTWDATA_SINGLE + else: + raise ValueError() + y = (data[f'dst_{type}_{size}']).astype(dt) + return x, y, dt + + +def dct_2d_ref(x, **kwargs): + """Calculate reference values for testing dct2.""" + x = np.array(x, copy=True) + for row in range(x.shape[0]): + x[row, :] = dct(x[row, :], **kwargs) + for col in range(x.shape[1]): + x[:, col] = dct(x[:, col], **kwargs) + return x + + +def idct_2d_ref(x, **kwargs): + """Calculate reference values for testing idct2.""" + x = np.array(x, copy=True) + for row in range(x.shape[0]): + x[row, :] = idct(x[row, :], **kwargs) + for col in range(x.shape[1]): + x[:, col] = idct(x[:, col], **kwargs) + return x + + +def dst_2d_ref(x, **kwargs): + """Calculate reference values for testing dst2.""" + x = np.array(x, copy=True) + for row in range(x.shape[0]): + x[row, :] = dst(x[row, :], **kwargs) + for col in range(x.shape[1]): + x[:, col] = dst(x[:, col], **kwargs) + return x + + +def idst_2d_ref(x, **kwargs): + """Calculate reference values for testing idst2.""" + x = np.array(x, copy=True) + for row in range(x.shape[0]): + x[row, :] = idst(x[row, :], **kwargs) + for col in range(x.shape[1]): + x[:, col] = idst(x[:, col], **kwargs) + return x + + +def naive_dct1(x, norm=None): + """Calculate textbook definition version of DCT-I.""" + x = np.array(x, copy=True) + N = len(x) + M = N-1 + y = np.zeros(N) + m0, m = 1, 2 + if norm == 'ortho': + m0 = np.sqrt(1.0/M) + m = np.sqrt(2.0/M) + for k in range(N): + for n in range(1, N-1): + y[k] += m*x[n]*np.cos(np.pi*n*k/M) + y[k] += m0 * x[0] + y[k] += m0 * x[N-1] * (1 if k % 2 == 0 else -1) + if norm == 'ortho': + y[0] *= 1/np.sqrt(2) + y[N-1] *= 1/np.sqrt(2) + return y + + +def naive_dst1(x, norm=None): + """Calculate textbook definition version of DST-I.""" + x = np.array(x, copy=True) + N = len(x) + M = N+1 + y = np.zeros(N) + for k in range(N): + for n in range(N): + y[k] += 2*x[n]*np.sin(np.pi*(n+1.0)*(k+1.0)/M) + if norm == 'ortho': + y *= np.sqrt(0.5/M) + return y + + +def naive_dct4(x, norm=None): + """Calculate textbook definition version of DCT-IV.""" + x = np.array(x, copy=True) + N = len(x) + y = np.zeros(N) + for k in range(N): + for n in range(N): + y[k] += x[n]*np.cos(np.pi*(n+0.5)*(k+0.5)/(N)) + if norm == 'ortho': + y *= np.sqrt(2.0/N) + else: + y *= 2 + return y + + +def naive_dst4(x, norm=None): + """Calculate textbook definition version of DST-IV.""" + x = np.array(x, copy=True) + N = len(x) + y = np.zeros(N) + for k in range(N): + for n in range(N): + y[k] += x[n]*np.sin(np.pi*(n+0.5)*(k+0.5)/(N)) + if norm == 'ortho': + y *= np.sqrt(2.0/N) + else: + y *= 2 + return y + + +class TestComplex: + def test_dct_complex64(self): + y = dct(1j*np.arange(5, dtype=np.complex64)) + x = 1j*dct(np.arange(5)) + assert_array_almost_equal(x, y) + + def test_dct_complex(self): + y = dct(np.arange(5)*1j) + x = 1j*dct(np.arange(5)) + assert_array_almost_equal(x, y) + + def test_idct_complex(self): + y = idct(np.arange(5)*1j) + x = 1j*idct(np.arange(5)) + assert_array_almost_equal(x, y) + + def test_dst_complex64(self): + y = dst(np.arange(5, dtype=np.complex64)*1j) + x = 1j*dst(np.arange(5)) + assert_array_almost_equal(x, y) + + def test_dst_complex(self): + y = dst(np.arange(5)*1j) + x = 1j*dst(np.arange(5)) + assert_array_almost_equal(x, y) + + def test_idst_complex(self): + y = idst(np.arange(5)*1j) + x = 1j*idst(np.arange(5)) + assert_array_almost_equal(x, y) + + +class _TestDCTBase: + def setup_method(self): + self.rdt = None + self.dec = 14 + self.type = None + + @pytest.fixture + def dct_lock(self): + return threading.Lock() + + def test_definition(self, dct_lock): + for i in FFTWDATA_SIZES: + with dct_lock: + x, yr, dt = fftw_dct_ref(self.type, i, self.rdt) + y = dct(x, type=self.type) + assert_equal(y.dtype, dt) + # XXX: we divide by np.max(y) because the tests fail otherwise. We + # should really use something like assert_array_approx_equal. The + # difference is due to fftw using a better algorithm w.r.t error + # propagation compared to the ones from fftpack. + assert_array_almost_equal(y / np.max(y), yr / np.max(y), decimal=self.dec, + err_msg=f"Size {i} failed") + + def test_axis(self): + nt = 2 + rng = np.random.RandomState(1234) + for i in [7, 8, 9, 16, 32, 64]: + x = rng.randn(nt, i) + y = dct(x, type=self.type) + for j in range(nt): + assert_array_almost_equal(y[j], dct(x[j], type=self.type), + decimal=self.dec) + + x = x.T + y = dct(x, axis=0, type=self.type) + for j in range(nt): + assert_array_almost_equal(y[:,j], dct(x[:,j], type=self.type), + decimal=self.dec) + + +class _TestDCTIBase(_TestDCTBase): + def test_definition_ortho(self): + # Test orthornomal mode. + dt = np.result_type(np.float32, self.rdt) + for xr in X: + x = np.array(xr, dtype=self.rdt) + y = dct(x, norm='ortho', type=1) + y2 = naive_dct1(x, norm='ortho') + assert_equal(y.dtype, dt) + assert_array_almost_equal(y / np.max(y), y2 / np.max(y), decimal=self.dec) + +class _TestDCTIIBase(_TestDCTBase): + def test_definition_matlab(self): + # Test correspondence with MATLAB (orthornomal mode). + dt = np.result_type(np.float32, self.rdt) + for xr, yr in zip(X, Y): + x = np.array(xr, dtype=dt) + y = dct(x, norm="ortho", type=2) + assert_equal(y.dtype, dt) + assert_array_almost_equal(y, yr, decimal=self.dec) + + +class _TestDCTIIIBase(_TestDCTBase): + def test_definition_ortho(self): + # Test orthornomal mode. + dt = np.result_type(np.float32, self.rdt) + for xr in X: + x = np.array(xr, dtype=self.rdt) + y = dct(x, norm='ortho', type=2) + xi = dct(y, norm="ortho", type=3) + assert_equal(xi.dtype, dt) + assert_array_almost_equal(xi, x, decimal=self.dec) + +class _TestDCTIVBase(_TestDCTBase): + def test_definition_ortho(self): + # Test orthornomal mode. + dt = np.result_type(np.float32, self.rdt) + for xr in X: + x = np.array(xr, dtype=self.rdt) + y = dct(x, norm='ortho', type=4) + y2 = naive_dct4(x, norm='ortho') + assert_equal(y.dtype, dt) + assert_array_almost_equal(y / np.max(y), y2 / np.max(y), decimal=self.dec) + + +class TestDCTIDouble(_TestDCTIBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 10 + self.type = 1 + + +class TestDCTIFloat(_TestDCTIBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 4 + self.type = 1 + + +class TestDCTIInt(_TestDCTIBase): + def setup_method(self): + self.rdt = int + self.dec = 5 + self.type = 1 + + +class TestDCTIIDouble(_TestDCTIIBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 10 + self.type = 2 + + +class TestDCTIIFloat(_TestDCTIIBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 5 + self.type = 2 + + +class TestDCTIIInt(_TestDCTIIBase): + def setup_method(self): + self.rdt = int + self.dec = 5 + self.type = 2 + + +class TestDCTIIIDouble(_TestDCTIIIBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 14 + self.type = 3 + + +class TestDCTIIIFloat(_TestDCTIIIBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 5 + self.type = 3 + + +class TestDCTIIIInt(_TestDCTIIIBase): + def setup_method(self): + self.rdt = int + self.dec = 5 + self.type = 3 + + +class TestDCTIVDouble(_TestDCTIVBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 12 + self.type = 3 + + +class TestDCTIVFloat(_TestDCTIVBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 5 + self.type = 3 + + +class TestDCTIVInt(_TestDCTIVBase): + def setup_method(self): + self.rdt = int + self.dec = 5 + self.type = 3 + + +class _TestIDCTBase: + def setup_method(self): + self.rdt = None + self.dec = 14 + self.type = None + + @pytest.fixture + def idct_lock(self): + return threading.Lock() + + def test_definition(self, idct_lock): + for i in FFTWDATA_SIZES: + with idct_lock: + xr, yr, dt = fftw_dct_ref(self.type, i, self.rdt) + x = idct(yr, type=self.type) + if self.type == 1: + x /= 2 * (i-1) + else: + x /= 2 * i + assert_equal(x.dtype, dt) + # XXX: we divide by np.max(y) because the tests fail otherwise. We + # should really use something like assert_array_approx_equal. The + # difference is due to fftw using a better algorithm w.r.t error + # propagation compared to the ones from fftpack. + assert_array_almost_equal(x / np.max(x), xr / np.max(x), decimal=self.dec, + err_msg=f"Size {i} failed") + +class TestIDCTIDouble(_TestIDCTBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 10 + self.type = 1 + + +class TestIDCTIFloat(_TestIDCTBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 4 + self.type = 1 + + +class TestIDCTIInt(_TestIDCTBase): + def setup_method(self): + self.rdt = int + self.dec = 4 + self.type = 1 + + +class TestIDCTIIDouble(_TestIDCTBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 10 + self.type = 2 + + +class TestIDCTIIFloat(_TestIDCTBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 5 + self.type = 2 + + +class TestIDCTIIInt(_TestIDCTBase): + def setup_method(self): + self.rdt = int + self.dec = 5 + self.type = 2 + + +class TestIDCTIIIDouble(_TestIDCTBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 14 + self.type = 3 + + +class TestIDCTIIIFloat(_TestIDCTBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 5 + self.type = 3 + + +class TestIDCTIIIInt(_TestIDCTBase): + def setup_method(self): + self.rdt = int + self.dec = 5 + self.type = 3 + +class TestIDCTIVDouble(_TestIDCTBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 12 + self.type = 4 + + +class TestIDCTIVFloat(_TestIDCTBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 5 + self.type = 4 + + +class TestIDCTIVInt(_TestIDCTBase): + def setup_method(self): + self.rdt = int + self.dec = 5 + self.type = 4 + +class _TestDSTBase: + def setup_method(self): + self.rdt = None # dtype + self.dec = None # number of decimals to match + self.type = None # dst type + + @pytest.fixture + def dst_lock(self): + return threading.Lock() + + def test_definition(self, dst_lock): + for i in FFTWDATA_SIZES: + with dst_lock: + xr, yr, dt = fftw_dst_ref(self.type, i, self.rdt) + y = dst(xr, type=self.type) + assert_equal(y.dtype, dt) + # XXX: we divide by np.max(y) because the tests fail otherwise. We + # should really use something like assert_array_approx_equal. The + # difference is due to fftw using a better algorithm w.r.t error + # propagation compared to the ones from fftpack. + assert_array_almost_equal(y / np.max(y), yr / np.max(y), decimal=self.dec, + err_msg=f"Size {i} failed") + + +class _TestDSTIBase(_TestDSTBase): + def test_definition_ortho(self): + # Test orthornomal mode. + dt = np.result_type(np.float32, self.rdt) + for xr in X: + x = np.array(xr, dtype=self.rdt) + y = dst(x, norm='ortho', type=1) + y2 = naive_dst1(x, norm='ortho') + assert_equal(y.dtype, dt) + assert_array_almost_equal(y / np.max(y), y2 / np.max(y), decimal=self.dec) + +class _TestDSTIVBase(_TestDSTBase): + def test_definition_ortho(self): + # Test orthornomal mode. + dt = np.result_type(np.float32, self.rdt) + for xr in X: + x = np.array(xr, dtype=self.rdt) + y = dst(x, norm='ortho', type=4) + y2 = naive_dst4(x, norm='ortho') + assert_equal(y.dtype, dt) + assert_array_almost_equal(y, y2, decimal=self.dec) + +class TestDSTIDouble(_TestDSTIBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 12 + self.type = 1 + + +class TestDSTIFloat(_TestDSTIBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 4 + self.type = 1 + + +class TestDSTIInt(_TestDSTIBase): + def setup_method(self): + self.rdt = int + self.dec = 5 + self.type = 1 + + +class TestDSTIIDouble(_TestDSTBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 14 + self.type = 2 + + +class TestDSTIIFloat(_TestDSTBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 6 + self.type = 2 + + +class TestDSTIIInt(_TestDSTBase): + def setup_method(self): + self.rdt = int + self.dec = 6 + self.type = 2 + + +class TestDSTIIIDouble(_TestDSTBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 14 + self.type = 3 + + +class TestDSTIIIFloat(_TestDSTBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 7 + self.type = 3 + + +class TestDSTIIIInt(_TestDSTBase): + def setup_method(self): + self.rdt = int + self.dec = 7 + self.type = 3 + + +class TestDSTIVDouble(_TestDSTIVBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 12 + self.type = 4 + + +class TestDSTIVFloat(_TestDSTIVBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 4 + self.type = 4 + + +class TestDSTIVInt(_TestDSTIVBase): + def setup_method(self): + self.rdt = int + self.dec = 5 + self.type = 4 + + +class _TestIDSTBase: + def setup_method(self): + self.rdt = None + self.dec = None + self.type = None + + @pytest.fixture + def idst_lock(self): + return threading.Lock() + + def test_definition(self, idst_lock): + for i in FFTWDATA_SIZES: + with idst_lock: + xr, yr, dt = fftw_dst_ref(self.type, i, self.rdt) + x = idst(yr, type=self.type) + if self.type == 1: + x /= 2 * (i+1) + else: + x /= 2 * i + assert_equal(x.dtype, dt) + # XXX: we divide by np.max(x) because the tests fail otherwise. We + # should really use something like assert_array_approx_equal. The + # difference is due to fftw using a better algorithm w.r.t error + # propagation compared to the ones from fftpack. + assert_array_almost_equal(x / np.max(x), xr / np.max(x), decimal=self.dec, + err_msg=f"Size {i} failed") + + +class TestIDSTIDouble(_TestIDSTBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 12 + self.type = 1 + + +class TestIDSTIFloat(_TestIDSTBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 4 + self.type = 1 + + +class TestIDSTIInt(_TestIDSTBase): + def setup_method(self): + self.rdt = int + self.dec = 4 + self.type = 1 + + +class TestIDSTIIDouble(_TestIDSTBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 14 + self.type = 2 + + +class TestIDSTIIFloat(_TestIDSTBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 6 + self.type = 2 + + +class TestIDSTIIInt(_TestIDSTBase): + def setup_method(self): + self.rdt = int + self.dec = 6 + self.type = 2 + + +class TestIDSTIIIDouble(_TestIDSTBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 14 + self.type = 3 + + +class TestIDSTIIIFloat(_TestIDSTBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 6 + self.type = 3 + + +class TestIDSTIIIInt(_TestIDSTBase): + def setup_method(self): + self.rdt = int + self.dec = 6 + self.type = 3 + + +class TestIDSTIVDouble(_TestIDSTBase): + def setup_method(self): + self.rdt = np.float64 + self.dec = 12 + self.type = 4 + + +class TestIDSTIVFloat(_TestIDSTBase): + def setup_method(self): + self.rdt = np.float32 + self.dec = 6 + self.type = 4 + + +class TestIDSTIVnt(_TestIDSTBase): + def setup_method(self): + self.rdt = int + self.dec = 6 + self.type = 4 + + +class TestOverwrite: + """Check input overwrite behavior.""" + + real_dtypes = [np.float32, np.float64] + + def _check(self, x, routine, type, fftsize, axis, norm, overwrite_x, **kw): + x2 = x.copy() + routine(x2, type, fftsize, axis, norm, overwrite_x=overwrite_x) + + sig = (f"{routine.__name__}({x.dtype}{x.shape!r}, {fftsize!r}, " + f"axis={axis!r}, overwrite_x={overwrite_x!r})") + if not overwrite_x: + assert_equal(x2, x, err_msg=f"spurious overwrite in {sig}") + + def _check_1d(self, routine, dtype, shape, axis): + rng = np.random.RandomState(1234) + if np.issubdtype(dtype, np.complexfloating): + data = rng.randn(*shape) + 1j*rng.randn(*shape) + else: + data = rng.randn(*shape) + data = data.astype(dtype) + + for type in [1, 2, 3, 4]: + for overwrite_x in [True, False]: + for norm in [None, 'ortho']: + self._check(data, routine, type, None, axis, norm, + overwrite_x) + + def test_dct(self): + for dtype in self.real_dtypes: + self._check_1d(dct, dtype, (16,), -1) + self._check_1d(dct, dtype, (16, 2), 0) + self._check_1d(dct, dtype, (2, 16), 1) + + def test_idct(self): + for dtype in self.real_dtypes: + self._check_1d(idct, dtype, (16,), -1) + self._check_1d(idct, dtype, (16, 2), 0) + self._check_1d(idct, dtype, (2, 16), 1) + + def test_dst(self): + for dtype in self.real_dtypes: + self._check_1d(dst, dtype, (16,), -1) + self._check_1d(dst, dtype, (16, 2), 0) + self._check_1d(dst, dtype, (2, 16), 1) + + def test_idst(self): + for dtype in self.real_dtypes: + self._check_1d(idst, dtype, (16,), -1) + self._check_1d(idst, dtype, (16, 2), 0) + self._check_1d(idst, dtype, (2, 16), 1) + + +class Test_DCTN_IDCTN: + dec = 14 + dct_type = [1, 2, 3, 4] + norms = [None, 'ortho'] + rstate = np.random.RandomState(1234) + shape = (32, 16) + data = rstate.randn(*shape) + + @pytest.mark.parametrize('fforward,finverse', [(dctn, idctn), + (dstn, idstn)]) + @pytest.mark.parametrize('axes', [None, + 1, (1,), [1], + 0, (0,), [0], + (0, 1), [0, 1], + (-2, -1), [-2, -1]]) + @pytest.mark.parametrize('dct_type', dct_type) + @pytest.mark.parametrize('norm', ['ortho']) + def test_axes_round_trip(self, fforward, finverse, axes, dct_type, norm): + tmp = fforward(self.data, type=dct_type, axes=axes, norm=norm) + tmp = finverse(tmp, type=dct_type, axes=axes, norm=norm) + assert_array_almost_equal(self.data, tmp, decimal=12) + + @pytest.mark.parametrize('fforward,fforward_ref', [(dctn, dct_2d_ref), + (dstn, dst_2d_ref)]) + @pytest.mark.parametrize('dct_type', dct_type) + @pytest.mark.parametrize('norm', norms) + def test_dctn_vs_2d_reference(self, fforward, fforward_ref, + dct_type, norm): + y1 = fforward(self.data, type=dct_type, axes=None, norm=norm) + y2 = fforward_ref(self.data, type=dct_type, norm=norm) + assert_array_almost_equal(y1, y2, decimal=11) + + @pytest.mark.parametrize('finverse,finverse_ref', [(idctn, idct_2d_ref), + (idstn, idst_2d_ref)]) + @pytest.mark.parametrize('dct_type', dct_type) + @pytest.mark.parametrize('norm', [None, 'ortho']) + def test_idctn_vs_2d_reference(self, finverse, finverse_ref, + dct_type, norm): + fdata = dctn(self.data, type=dct_type, norm=norm) + y1 = finverse(fdata, type=dct_type, norm=norm) + y2 = finverse_ref(fdata, type=dct_type, norm=norm) + assert_array_almost_equal(y1, y2, decimal=11) + + @pytest.mark.parametrize('fforward,finverse', [(dctn, idctn), + (dstn, idstn)]) + def test_axes_and_shape(self, fforward, finverse): + with assert_raises(ValueError, + match="when given, axes and shape arguments" + " have to be of the same length"): + fforward(self.data, shape=self.data.shape[0], axes=(0, 1)) + + with assert_raises(ValueError, + match="when given, axes and shape arguments" + " have to be of the same length"): + fforward(self.data, shape=self.data.shape[0], axes=None) + + with assert_raises(ValueError, + match="when given, axes and shape arguments" + " have to be of the same length"): + fforward(self.data, shape=self.data.shape, axes=0) + + @pytest.mark.parametrize('fforward', [dctn, dstn]) + def test_shape(self, fforward): + tmp = fforward(self.data, shape=(128, 128), axes=None) + assert_equal(tmp.shape, (128, 128)) + + @pytest.mark.parametrize('fforward,finverse', [(dctn, idctn), + (dstn, idstn)]) + @pytest.mark.parametrize('axes', [1, (1,), [1], + 0, (0,), [0]]) + def test_shape_is_none_with_axes(self, fforward, finverse, axes): + tmp = fforward(self.data, shape=None, axes=axes, norm='ortho') + tmp = finverse(tmp, shape=None, axes=axes, norm='ortho') + assert_array_almost_equal(self.data, tmp, decimal=self.dec) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4da53f1b922c4e030c067710e2cde68334000350 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/_fortran.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/_fortran.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b03f6dbe9921bc92ff826a24c82d516166895a93 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/_fortran.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/_idl.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/_idl.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..48c10423836451afefab2998712c0acf4d6b939e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/_idl.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/_mmio.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/_mmio.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86e1e6a1a606eb18071bbfbd78eb66c3a3e21764 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/_mmio.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/_netcdf.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/_netcdf.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2030ab487b7643c6827f380d401639f92b38fce7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/_netcdf.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/harwell_boeing.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/harwell_boeing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..465af568e027b556ee179aa93c4d086e8b745951 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/harwell_boeing.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/idl.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/idl.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0b6fc5757fab31e8ba8672e28450a4c78b90e396 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/idl.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/mmio.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/mmio.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..78699d3836dc1677f332b5f88de4f369bf77452c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/mmio.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/netcdf.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/netcdf.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f2f47cb18c2512126c73d9a441500afd0509fd06 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/netcdf.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/wavfile.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/wavfile.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f08869223cf0db33fb0be711613c0018a3329fb6 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/__pycache__/wavfile.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_fast_matrix_market/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_fast_matrix_market/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..00e2b16c0fa63ad92983e0a62c6cc3401ef9f907 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_fast_matrix_market/__init__.py @@ -0,0 +1,600 @@ +# Copyright (C) 2022-2023 Adam Lugowski. All rights reserved. +# Use of this source code is governed by the BSD 2-clause license found in +# the LICENSE.txt file. +# SPDX-License-Identifier: BSD-2-Clause +""" +Matrix Market I/O with a C++ backend. +See http://math.nist.gov/MatrixMarket/formats.html +for information about the Matrix Market format. + +.. versionadded:: 1.12.0 +""" +import io +import os + +import numpy as np +from scipy.sparse import coo_array, issparse, coo_matrix +from scipy.io import _mmio + +__all__ = ['mminfo', 'mmread', 'mmwrite'] + +PARALLELISM = 0 +""" +Number of threads that `mmread()` and `mmwrite()` use. +0 means number of CPUs in the system. +Use `threadpoolctl` to set this value. +""" + +ALWAYS_FIND_SYMMETRY = False +""" +Whether mmwrite() with symmetry='AUTO' will always search for symmetry +inside the matrix. This is scipy.io._mmio.mmwrite()'s default behavior, +but has a significant performance cost on large matrices. +""" + +_field_to_dtype = { + "integer": "int64", + "unsigned-integer": "uint64", + "real": "float64", + "complex": "complex", + "pattern": "float64", +} + + +def _fmm_version(): + from . import _fmm_core + return _fmm_core.__version__ + + +# Register with threadpoolctl, if available +try: + import threadpoolctl + + class _FMMThreadPoolCtlController(threadpoolctl.LibController): + user_api = "scipy" + internal_api = "scipy_mmio" + + filename_prefixes = ("_fmm_core",) + + def get_num_threads(self): + global PARALLELISM + return PARALLELISM + + def set_num_threads(self, num_threads): + global PARALLELISM + PARALLELISM = num_threads + + def get_version(self): + return _fmm_version + + def set_additional_attributes(self): + pass + + threadpoolctl.register(_FMMThreadPoolCtlController) +except (ImportError, AttributeError): + # threadpoolctl not installed or version too old + pass + + +class _TextToBytesWrapper(io.BufferedReader): + """ + Convert a TextIOBase string stream to a byte stream. + """ + + def __init__(self, text_io_buffer, encoding=None, errors=None, **kwargs): + super().__init__(text_io_buffer, **kwargs) + self.encoding = encoding or text_io_buffer.encoding or 'utf-8' + self.errors = errors or text_io_buffer.errors or 'strict' + + def __del__(self): + # do not close the wrapped stream + self.detach() + + def _encoding_call(self, method_name, *args, **kwargs): + raw_method = getattr(self.raw, method_name) + val = raw_method(*args, **kwargs) + return val.encode(self.encoding, errors=self.errors) + + def read(self, size=-1): + return self._encoding_call('read', size) + + def read1(self, size=-1): + return self._encoding_call('read1', size) + + def peek(self, size=-1): + return self._encoding_call('peek', size) + + def seek(self, offset, whence=0): + # Random seeks are not allowed because of non-trivial conversion + # between byte and character offsets, + # with the possibility of a byte offset landing within a character. + if offset == 0 and whence == 0 or \ + offset == 0 and whence == 2: + # seek to start or end is ok + super().seek(offset, whence) + else: + # Drop any other seek + # In this application this may happen when pystreambuf seeks during sync(), + # which can happen when closing a partially-read stream. + # Ex. when mminfo() only reads the header then exits. + pass + + +def _read_body_array(cursor): + """ + Read MatrixMarket array body + """ + from . import _fmm_core + + vals = np.zeros(cursor.header.shape, dtype=_field_to_dtype.get(cursor.header.field)) + _fmm_core.read_body_array(cursor, vals) + return vals + + +def _read_body_coo(cursor, generalize_symmetry=True): + """ + Read MatrixMarket coordinate body + """ + from . import _fmm_core + + index_dtype = "int32" + if cursor.header.nrows >= 2**31 or cursor.header.ncols >= 2**31: + # Dimensions are too large to fit in int32 + index_dtype = "int64" + + i = np.zeros(cursor.header.nnz, dtype=index_dtype) + j = np.zeros(cursor.header.nnz, dtype=index_dtype) + data = np.zeros(cursor.header.nnz, dtype=_field_to_dtype.get(cursor.header.field)) + + _fmm_core.read_body_coo(cursor, i, j, data) + + if generalize_symmetry and cursor.header.symmetry != "general": + off_diagonal_mask = (i != j) + off_diagonal_rows = i[off_diagonal_mask] + off_diagonal_cols = j[off_diagonal_mask] + off_diagonal_data = data[off_diagonal_mask] + + if cursor.header.symmetry == "skew-symmetric": + off_diagonal_data *= -1 + elif cursor.header.symmetry == "hermitian": + off_diagonal_data = off_diagonal_data.conjugate() + + i = np.concatenate((i, off_diagonal_cols)) + j = np.concatenate((j, off_diagonal_rows)) + data = np.concatenate((data, off_diagonal_data)) + + return (data, (i, j)), cursor.header.shape + + +def _get_read_cursor(source, parallelism=None): + """ + Open file for reading. + """ + from . import _fmm_core + + ret_stream_to_close = None + if parallelism is None: + parallelism = PARALLELISM + + try: + source = os.fspath(source) + # It's a file path + is_path = True + except TypeError: + is_path = False + + if is_path: + path = str(source) + if path.endswith('.gz'): + import gzip + source = gzip.GzipFile(path, 'r') + ret_stream_to_close = source + elif path.endswith('.bz2'): + import bz2 + source = bz2.BZ2File(path, 'rb') + ret_stream_to_close = source + else: + if not os.path.exists(path): + raise FileNotFoundError(f"The source file does not exist: {path}") + return _fmm_core.open_read_file(path, parallelism), ret_stream_to_close + + # Stream object. + if hasattr(source, "read"): + if isinstance(source, io.TextIOBase): + source = _TextToBytesWrapper(source) + return _fmm_core.open_read_stream(source, parallelism), ret_stream_to_close + else: + raise TypeError("Unknown source type") + + +def _get_write_cursor(target, h=None, comment=None, parallelism=None, + symmetry="general", precision=None): + """ + Open file for writing. + """ + from . import _fmm_core + + if parallelism is None: + parallelism = PARALLELISM + if comment is None: + comment = '' + if symmetry is None: + symmetry = "general" + if precision is None: + precision = -1 + + if not h: + h = _fmm_core.header(comment=comment, symmetry=symmetry) + + try: + target = os.fspath(target) + # It's a file path + if target[-4:] != '.mtx': + target += '.mtx' + return _fmm_core.open_write_file(str(target), h, parallelism, precision) + except TypeError: + pass + + if hasattr(target, "write"): + # Stream object. + if isinstance(target, io.TextIOBase): + raise TypeError("target stream must be open in binary mode.") + return _fmm_core.open_write_stream(target, h, parallelism, precision) + else: + raise TypeError("Unknown source object") + + +def _apply_field(data, field, no_pattern=False): + """ + Ensure that ``data.dtype`` is compatible with the specified MatrixMarket field type. + + Parameters + ---------- + data : ndarray + Input array. + + field : str + Matrix Market field, such as 'real', 'complex', 'integer', 'pattern'. + + no_pattern : bool, optional + Whether an empty array may be returned for a 'pattern' field. + + Returns + ------- + data : ndarray + Input data if no conversion necessary, or a converted version + """ + + if field is None: + return data + if field == "pattern": + if no_pattern: + return data + else: + return np.zeros(0) + + dtype = _field_to_dtype.get(field, None) + if dtype is None: + raise ValueError("Invalid field.") + + return np.asarray(data, dtype=dtype) + + +def _validate_symmetry(symmetry): + """ + Check that the symmetry parameter is one that MatrixMarket allows.. + """ + if symmetry is None: + return "general" + + symmetry = str(symmetry).lower() + symmetries = ["general", "symmetric", "skew-symmetric", "hermitian"] + if symmetry not in symmetries: + raise ValueError("Invalid symmetry. Must be one of: " + ", ".join(symmetries)) + + return symmetry + + +def mmread(source, *, spmatrix=True): + """ + Reads the contents of a Matrix Market file-like 'source' into a matrix. + + Parameters + ---------- + source : str or file-like + Matrix Market filename (extensions .mtx, .mtz.gz) + or open file-like object. + spmatrix : bool, optional (default: True) + If ``True``, return sparse matrix. Otherwise return sparse array. + + Returns + ------- + a : ndarray or coo_array + Dense or sparse array depending on the matrix format in the + Matrix Market file. + + Notes + ----- + .. versionchanged:: 1.12.0 + C++ implementation. + + Examples + -------- + >>> from io import StringIO + >>> from scipy.io import mmread + + >>> text = '''%%MatrixMarket matrix coordinate real general + ... 5 5 7 + ... 2 3 1.0 + ... 3 4 2.0 + ... 3 5 3.0 + ... 4 1 4.0 + ... 4 2 5.0 + ... 4 3 6.0 + ... 4 4 7.0 + ... ''' + + ``mmread(source)`` returns the data as sparse array in COO format. + + >>> m = mmread(StringIO(text), spmatrix=False) + >>> m + + >>> m.toarray() + array([[0., 0., 0., 0., 0.], + [0., 0., 1., 0., 0.], + [0., 0., 0., 2., 3.], + [4., 5., 6., 7., 0.], + [0., 0., 0., 0., 0.]]) + + This method is threaded. + The default number of threads is equal to the number of CPUs in the system. + Use `threadpoolctl `_ to override: + + >>> import threadpoolctl + >>> + >>> with threadpoolctl.threadpool_limits(limits=2): + ... m = mmread(StringIO(text), spmatrix=False) + + """ + cursor, stream_to_close = _get_read_cursor(source) + + if cursor.header.format == "array": + mat = _read_body_array(cursor) + if stream_to_close: + stream_to_close.close() + return mat + else: + triplet, shape = _read_body_coo(cursor, generalize_symmetry=True) + if stream_to_close: + stream_to_close.close() + if spmatrix: + return coo_matrix(triplet, shape=shape) + return coo_array(triplet, shape=shape) + + +def mmwrite(target, a, comment=None, field=None, precision=None, symmetry="AUTO"): + r""" + Writes the sparse or dense array `a` to Matrix Market file-like `target`. + + Parameters + ---------- + target : str or file-like + Matrix Market filename (extension .mtx) or open file-like object. + a : array like + Sparse or dense 2-D array. + comment : str, optional + Comments to be prepended to the Matrix Market file. + field : None or str, optional + Either 'real', 'complex', 'pattern', or 'integer'. + precision : None or int, optional + Number of digits to display for real or complex values. + symmetry : None or str, optional + Either 'AUTO', 'general', 'symmetric', 'skew-symmetric', or 'hermitian'. + If symmetry is None the symmetry type of 'a' is determined by its + values. If symmetry is 'AUTO' the symmetry type of 'a' is either + determined or set to 'general', at mmwrite's discretion. + + Returns + ------- + None + + Notes + ----- + .. versionchanged:: 1.12.0 + C++ implementation. + + Examples + -------- + >>> from io import BytesIO + >>> import numpy as np + >>> from scipy.sparse import coo_array + >>> from scipy.io import mmwrite + + Write a small NumPy array to a matrix market file. The file will be + written in the ``'array'`` format. + + >>> a = np.array([[1.0, 0, 0, 0], [0, 2.5, 0, 6.25]]) + >>> target = BytesIO() + >>> mmwrite(target, a) + >>> print(target.getvalue().decode('latin1')) + %%MatrixMarket matrix array real general + % + 2 4 + 1 + 0 + 0 + 2.5 + 0 + 0 + 0 + 6.25 + + Add a comment to the output file, and set the precision to 3. + + >>> target = BytesIO() + >>> mmwrite(target, a, comment='\n Some test data.\n', precision=3) + >>> print(target.getvalue().decode('latin1')) + %%MatrixMarket matrix array real general + % + % Some test data. + % + 2 4 + 1.00e+00 + 0.00e+00 + 0.00e+00 + 2.50e+00 + 0.00e+00 + 0.00e+00 + 0.00e+00 + 6.25e+00 + + Convert to a sparse matrix before calling ``mmwrite``. This will + result in the output format being ``'coordinate'`` rather than + ``'array'``. + + >>> target = BytesIO() + >>> mmwrite(target, coo_array(a), precision=3) + >>> print(target.getvalue().decode('latin1')) + %%MatrixMarket matrix coordinate real general + % + 2 4 3 + 1 1 1.00e+00 + 2 2 2.50e+00 + 2 4 6.25e+00 + + Write a complex Hermitian array to a matrix market file. Note that + only six values are actually written to the file; the other values + are implied by the symmetry. + + >>> z = np.array([[3, 1+2j, 4-3j], [1-2j, 1, -5j], [4+3j, 5j, 2.5]]) + >>> z + array([[ 3. +0.j, 1. +2.j, 4. -3.j], + [ 1. -2.j, 1. +0.j, -0. -5.j], + [ 4. +3.j, 0. +5.j, 2.5+0.j]]) + + >>> target = BytesIO() + >>> mmwrite(target, z, precision=2) + >>> print(target.getvalue().decode('latin1')) + %%MatrixMarket matrix array complex hermitian + % + 3 3 + 3.0e+00 0.0e+00 + 1.0e+00 -2.0e+00 + 4.0e+00 3.0e+00 + 1.0e+00 0.0e+00 + 0.0e+00 5.0e+00 + 2.5e+00 0.0e+00 + + This method is threaded. + The default number of threads is equal to the number of CPUs in the system. + Use `threadpoolctl `_ to override: + + >>> import threadpoolctl + >>> + >>> target = BytesIO() + >>> with threadpoolctl.threadpool_limits(limits=2): + ... mmwrite(target, a) + + """ + from . import _fmm_core + + if isinstance(a, list) or isinstance(a, tuple) or hasattr(a, "__array__"): + a = np.asarray(a) + + if symmetry == "AUTO": + if ALWAYS_FIND_SYMMETRY or (hasattr(a, "shape") and max(a.shape) < 100): + symmetry = None + else: + symmetry = "general" + + if symmetry is None: + symmetry = _mmio.MMFile()._get_symmetry(a) + + symmetry = _validate_symmetry(symmetry) + cursor = _get_write_cursor(target, comment=comment, + precision=precision, symmetry=symmetry) + + if isinstance(a, np.ndarray): + # Write dense numpy arrays + a = _apply_field(a, field, no_pattern=True) + _fmm_core.write_body_array(cursor, a) + + elif issparse(a): + # Write sparse scipy matrices + a = a.tocoo() + + if symmetry is not None and symmetry != "general": + # A symmetric matrix only specifies the elements below the diagonal. + # Ensure that the matrix satisfies this requirement. + lower_triangle_mask = a.row >= a.col + a = coo_array((a.data[lower_triangle_mask], + (a.row[lower_triangle_mask], + a.col[lower_triangle_mask])), shape=a.shape) + + data = _apply_field(a.data, field) + _fmm_core.write_body_coo(cursor, a.shape, a.row, a.col, data) + + else: + raise ValueError(f"unknown matrix type: {type(a)}") + + +def mminfo(source): + """ + Return size and storage parameters from Matrix Market file-like 'source'. + + Parameters + ---------- + source : str or file-like + Matrix Market filename (extension .mtx) or open file-like object + + Returns + ------- + rows : int + Number of matrix rows. + cols : int + Number of matrix columns. + entries : int + Number of non-zero entries of a sparse matrix + or rows*cols for a dense matrix. + format : str + Either 'coordinate' or 'array'. + field : str + Either 'real', 'complex', 'pattern', or 'integer'. + symmetry : str + Either 'general', 'symmetric', 'skew-symmetric', or 'hermitian'. + + Notes + ----- + .. versionchanged:: 1.12.0 + C++ implementation. + + Examples + -------- + >>> from io import StringIO + >>> from scipy.io import mminfo + + >>> text = '''%%MatrixMarket matrix coordinate real general + ... 5 5 7 + ... 2 3 1.0 + ... 3 4 2.0 + ... 3 5 3.0 + ... 4 1 4.0 + ... 4 2 5.0 + ... 4 3 6.0 + ... 4 4 7.0 + ... ''' + + + ``mminfo(source)`` returns the number of rows, number of columns, + format, field type and symmetry attribute of the source file. + + >>> mminfo(StringIO(text)) + (5, 5, 7, 'coordinate', 'real', 'general') + """ + cursor, stream_to_close = _get_read_cursor(source, 1) + h = cursor.header + cursor.close() + if stream_to_close: + stream_to_close.close() + return h.nrows, h.ncols, h.nnz, h.format, h.field, h.symmetry diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_fast_matrix_market/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_fast_matrix_market/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..38c01907c7c2de9dcec4e00718fa890ee4e063b1 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_fast_matrix_market/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e56f374b42abac05c2a8b8375a4bf9dab8fd8e81 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/__init__.py @@ -0,0 +1,7 @@ +from .hb import hb_read, hb_write + +__all__ = ["hb_read", "hb_write"] + +from scipy._lib._testutils import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6208b5905d67ad5f9a1b8670e2e70195cdad3e5b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/__pycache__/_fortran_format_parser.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/__pycache__/_fortran_format_parser.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..60fdf30e74166e06a2ae41b7207edf24de9a546b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/__pycache__/_fortran_format_parser.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/__pycache__/hb.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/__pycache__/hb.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..820cc9f5647e8f27ae059fcf05b6161a2758d9ba Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/__pycache__/hb.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/_fortran_format_parser.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/_fortran_format_parser.py new file mode 100644 index 0000000000000000000000000000000000000000..1175fed672d0502e5d155c86ab98003140c0d72c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/_fortran_format_parser.py @@ -0,0 +1,316 @@ +""" +Preliminary module to handle Fortran formats for IO. Does not use this outside +scipy.sparse io for now, until the API is deemed reasonable. + +The *Format classes handle conversion between Fortran and Python format, and +FortranFormatParser can create *Format instances from raw Fortran format +strings (e.g. '(3I4)', '(10I3)', etc...) +""" +import re +import threading + +import numpy as np + + +__all__ = ["BadFortranFormat", "FortranFormatParser", "IntFormat", "ExpFormat"] + + +TOKENS = { + "LPAR": r"\(", + "RPAR": r"\)", + "INT_ID": r"I", + "EXP_ID": r"E", + "INT": r"\d+", + "DOT": r"\.", +} + + +class BadFortranFormat(SyntaxError): + pass + + +def number_digits(n): + return int(np.floor(np.log10(np.abs(n))) + 1) + + +class IntFormat: + @classmethod + def from_number(cls, n, min=None): + """Given an integer, returns a "reasonable" IntFormat instance to represent + any number between 0 and n if n > 0, -n and n if n < 0 + + Parameters + ---------- + n : int + max number one wants to be able to represent + min : int + minimum number of characters to use for the format + + Returns + ------- + res : IntFormat + IntFormat instance with reasonable (see Notes) computed width + + Notes + ----- + Reasonable should be understood as the minimal string length necessary + without losing precision. For example, IntFormat.from_number(1) will + return an IntFormat instance of width 2, so that any 0 and 1 may be + represented as 1-character strings without loss of information. + """ + width = number_digits(n) + 1 + if n < 0: + width += 1 + repeat = 80 // width + return cls(width, min, repeat=repeat) + + def __init__(self, width, min=None, repeat=None): + self.width = width + self.repeat = repeat + self.min = min + + def __repr__(self): + r = "IntFormat(" + if self.repeat: + r += f"{self.repeat}" + r += f"I{self.width}" + if self.min: + r += f".{self.min}" + return r + ")" + + @property + def fortran_format(self): + r = "(" + if self.repeat: + r += f"{self.repeat}" + r += f"I{self.width}" + if self.min: + r += f".{self.min}" + return r + ")" + + @property + def python_format(self): + return "%" + str(self.width) + "d" + + +class ExpFormat: + @classmethod + def from_number(cls, n, min=None): + """Given a float number, returns a "reasonable" ExpFormat instance to + represent any number between -n and n. + + Parameters + ---------- + n : float + max number one wants to be able to represent + min : int + minimum number of characters to use for the format + + Returns + ------- + res : ExpFormat + ExpFormat instance with reasonable (see Notes) computed width + + Notes + ----- + Reasonable should be understood as the minimal string length necessary + to avoid losing precision. + """ + # len of one number in exp format: sign + 1|0 + "." + + # number of digit for fractional part + 'E' + sign of exponent + + # len of exponent + finfo = np.finfo(n.dtype) + # Number of digits for fractional part + n_prec = finfo.precision + 1 + # Number of digits for exponential part + n_exp = number_digits(np.max(np.abs([finfo.maxexp, finfo.minexp]))) + width = 1 + 1 + n_prec + 1 + n_exp + 1 + if n < 0: + width += 1 + repeat = int(np.floor(80 / width)) + return cls(width, n_prec, min, repeat=repeat) + + def __init__(self, width, significand, min=None, repeat=None): + """\ + Parameters + ---------- + width : int + number of characters taken by the string (includes space). + """ + self.width = width + self.significand = significand + self.repeat = repeat + self.min = min + + def __repr__(self): + r = "ExpFormat(" + if self.repeat: + r += f"{self.repeat}" + r += f"E{self.width}.{self.significand}" + if self.min: + r += f"E{self.min}" + return r + ")" + + @property + def fortran_format(self): + r = "(" + if self.repeat: + r += f"{self.repeat}" + r += f"E{self.width}.{self.significand}" + if self.min: + r += f"E{self.min}" + return r + ")" + + @property + def python_format(self): + return "%" + str(self.width-1) + "." + str(self.significand) + "E" + + +class Token: + def __init__(self, type, value, pos): + self.type = type + self.value = value + self.pos = pos + + def __str__(self): + return f"""Token('{self.type}', "{self.value}")""" + + def __repr__(self): + return self.__str__() + + +class Tokenizer: + def __init__(self): + self.tokens = list(TOKENS.keys()) + self.res = [re.compile(TOKENS[i]) for i in self.tokens] + + def input(self, s): + self.data = s + self.curpos = 0 + self.len = len(s) + + def next_token(self): + curpos = self.curpos + + while curpos < self.len: + for i, r in enumerate(self.res): + m = r.match(self.data, curpos) + if m is None: + continue + else: + self.curpos = m.end() + return Token(self.tokens[i], m.group(), self.curpos) + raise SyntaxError( + f"Unknown character at position {self.curpos} " + f"({self.data[self.curpos]})" + ) + + +# Grammar for fortran format: +# format : LPAR format_string RPAR +# format_string : repeated | simple +# repeated : repeat simple +# simple : int_fmt | exp_fmt +# int_fmt : INT_ID width +# exp_fmt : simple_exp_fmt +# simple_exp_fmt : EXP_ID width DOT significand +# extended_exp_fmt : EXP_ID width DOT significand EXP_ID ndigits +# repeat : INT +# width : INT +# significand : INT +# ndigits : INT + +# Naive fortran formatter - parser is hand-made +class FortranFormatParser: + """Parser for Fortran format strings. The parse method returns a *Format + instance. + + Notes + ----- + Only ExpFormat (exponential format for floating values) and IntFormat + (integer format) for now. + """ + def __init__(self): + self.tokenizer = threading.local() + + def parse(self, s): + if not hasattr(self.tokenizer, 't'): + self.tokenizer.t = Tokenizer() + + self.tokenizer.t.input(s) + + tokens = [] + + try: + while True: + t = self.tokenizer.t.next_token() + if t is None: + break + else: + tokens.append(t) + return self._parse_format(tokens) + except SyntaxError as e: + raise BadFortranFormat(str(e)) from e + + def _get_min(self, tokens): + next = tokens.pop(0) + if not next.type == "DOT": + raise SyntaxError() + next = tokens.pop(0) + return next.value + + def _expect(self, token, tp): + if not token.type == tp: + raise SyntaxError() + + def _parse_format(self, tokens): + if not tokens[0].type == "LPAR": + raise SyntaxError( + f"Expected left parenthesis at position {0} (got '{tokens[0].value}')" + ) + elif not tokens[-1].type == "RPAR": + raise SyntaxError("Expected right parenthesis at position " + f"{len(tokens)} (got '{tokens[-1].value}')") + + tokens = tokens[1:-1] + types = [t.type for t in tokens] + if types[0] == "INT": + repeat = int(tokens.pop(0).value) + else: + repeat = None + + next = tokens.pop(0) + if next.type == "INT_ID": + next = self._next(tokens, "INT") + width = int(next.value) + if tokens: + min = int(self._get_min(tokens)) + else: + min = None + return IntFormat(width, min, repeat) + elif next.type == "EXP_ID": + next = self._next(tokens, "INT") + width = int(next.value) + + next = self._next(tokens, "DOT") + + next = self._next(tokens, "INT") + significand = int(next.value) + + if tokens: + next = self._next(tokens, "EXP_ID") + + next = self._next(tokens, "INT") + min = int(next.value) + else: + min = None + return ExpFormat(width, significand, min, repeat) + else: + raise SyntaxError(f"Invalid formatter type {next.value}") + + def _next(self, tokens, tp): + if not len(tokens) > 0: + raise SyntaxError() + next = tokens.pop(0) + self._expect(next, tp) + return next diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/hb.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/hb.py new file mode 100644 index 0000000000000000000000000000000000000000..2b6f6b0a873a91d5042c53bd7c82083f02c268e2 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/hb.py @@ -0,0 +1,571 @@ +""" +Implementation of Harwell-Boeing read/write. + +At the moment not the full Harwell-Boeing format is supported. Supported +features are: + + - assembled, non-symmetric, real matrices + - integer for pointer/indices + - exponential format for float values, and int format + +""" +# TODO: +# - Add more support (symmetric/complex matrices, non-assembled matrices ?) + +# XXX: reading is reasonably efficient (>= 85 % is in numpy.fromstring), but +# takes a lot of memory. Being faster would require compiled code. +# write is not efficient. Although not a terribly exciting task, +# having reusable facilities to efficiently read/write fortran-formatted files +# would be useful outside this module. + +import warnings + +import numpy as np +from scipy.sparse import csc_array, csc_matrix +from ._fortran_format_parser import FortranFormatParser, IntFormat, ExpFormat + +__all__ = ["hb_read", "hb_write"] + + +class MalformedHeader(Exception): + pass + + +class LineOverflow(Warning): + pass + + +def _nbytes_full(fmt, nlines): + """Return the number of bytes to read to get every full lines for the + given parsed fortran format.""" + return (fmt.repeat * fmt.width + 1) * (nlines - 1) + + +class HBInfo: + @classmethod + def from_data(cls, m, title="Default title", key="0", mxtype=None, fmt=None): + """Create a HBInfo instance from an existing sparse matrix. + + Parameters + ---------- + m : sparse array or matrix + the HBInfo instance will derive its parameters from m + title : str + Title to put in the HB header + key : str + Key + mxtype : HBMatrixType + type of the input matrix + fmt : dict + not implemented + + Returns + ------- + hb_info : HBInfo instance + """ + m = m.tocsc(copy=False) + + pointer = m.indptr + indices = m.indices + values = m.data + + nrows, ncols = m.shape + nnon_zeros = m.nnz + + if fmt is None: + # +1 because HB use one-based indexing (Fortran), and we will write + # the indices /pointer as such + pointer_fmt = IntFormat.from_number(np.max(pointer+1)) + indices_fmt = IntFormat.from_number(np.max(indices+1)) + + if values.dtype.kind in np.typecodes["AllFloat"]: + values_fmt = ExpFormat.from_number(-np.max(np.abs(values))) + elif values.dtype.kind in np.typecodes["AllInteger"]: + values_fmt = IntFormat.from_number(-np.max(np.abs(values))) + else: + message = f"type {values.dtype.kind} not implemented yet" + raise NotImplementedError(message) + else: + raise NotImplementedError("fmt argument not supported yet.") + + if mxtype is None: + if not np.isrealobj(values): + raise ValueError("Complex values not supported yet") + if values.dtype.kind in np.typecodes["AllInteger"]: + tp = "integer" + elif values.dtype.kind in np.typecodes["AllFloat"]: + tp = "real" + else: + raise NotImplementedError( + f"type {values.dtype} for values not implemented") + mxtype = HBMatrixType(tp, "unsymmetric", "assembled") + else: + raise ValueError("mxtype argument not handled yet.") + + def _nlines(fmt, size): + nlines = size // fmt.repeat + if nlines * fmt.repeat != size: + nlines += 1 + return nlines + + pointer_nlines = _nlines(pointer_fmt, pointer.size) + indices_nlines = _nlines(indices_fmt, indices.size) + values_nlines = _nlines(values_fmt, values.size) + + total_nlines = pointer_nlines + indices_nlines + values_nlines + + return cls(title, key, + total_nlines, pointer_nlines, indices_nlines, values_nlines, + mxtype, nrows, ncols, nnon_zeros, + pointer_fmt.fortran_format, indices_fmt.fortran_format, + values_fmt.fortran_format) + + @classmethod + def from_file(cls, fid): + """Create a HBInfo instance from a file object containing a matrix in the + HB format. + + Parameters + ---------- + fid : file-like matrix + File or file-like object containing a matrix in the HB format. + + Returns + ------- + hb_info : HBInfo instance + """ + # First line + line = fid.readline().strip("\n") + if not len(line) > 72: + raise ValueError("Expected at least 72 characters for first line, " + f"got: \n{line}") + title = line[:72] + key = line[72:] + + # Second line + line = fid.readline().strip("\n") + if not len(line.rstrip()) >= 56: + raise ValueError("Expected at least 56 characters for second line, " + f"got: \n{line}") + total_nlines = _expect_int(line[:14]) + pointer_nlines = _expect_int(line[14:28]) + indices_nlines = _expect_int(line[28:42]) + values_nlines = _expect_int(line[42:56]) + + rhs_nlines = line[56:72].strip() + if rhs_nlines == '': + rhs_nlines = 0 + else: + rhs_nlines = _expect_int(rhs_nlines) + if not rhs_nlines == 0: + raise ValueError("Only files without right hand side supported for " + "now.") + + # Third line + line = fid.readline().strip("\n") + if not len(line) >= 70: + raise ValueError(f"Expected at least 72 character for third line, " + f"got:\n{line}") + + mxtype_s = line[:3].upper() + if not len(mxtype_s) == 3: + raise ValueError("mxtype expected to be 3 characters long") + + mxtype = HBMatrixType.from_fortran(mxtype_s) + if mxtype.value_type not in ["real", "integer"]: + raise ValueError("Only real or integer matrices supported for " + f"now (detected {mxtype})") + if not mxtype.structure == "unsymmetric": + raise ValueError("Only unsymmetric matrices supported for " + f"now (detected {mxtype})") + if not mxtype.storage == "assembled": + raise ValueError("Only assembled matrices supported for now") + + if not line[3:14] == " " * 11: + raise ValueError(f"Malformed data for third line: {line}") + + nrows = _expect_int(line[14:28]) + ncols = _expect_int(line[28:42]) + nnon_zeros = _expect_int(line[42:56]) + nelementals = _expect_int(line[56:70]) + if not nelementals == 0: + raise ValueError( + f"Unexpected value {nelementals} for nltvl (last entry of line 3)" + ) + + # Fourth line + line = fid.readline().strip("\n") + + ct = line.split() + if not len(ct) == 3: + raise ValueError(f"Expected 3 formats, got {ct}") + + return cls(title, key, + total_nlines, pointer_nlines, indices_nlines, values_nlines, + mxtype, nrows, ncols, nnon_zeros, + ct[0], ct[1], ct[2], + rhs_nlines, nelementals) + + def __init__(self, title, key, + total_nlines, pointer_nlines, indices_nlines, values_nlines, + mxtype, nrows, ncols, nnon_zeros, + pointer_format_str, indices_format_str, values_format_str, + right_hand_sides_nlines=0, nelementals=0): + """Do not use this directly, but the class ctrs (from_* functions).""" + if title is None: + title = "No Title" + if len(title) > 72: + raise ValueError("title cannot be > 72 characters") + + if key is None: + key = "|No Key" + if len(key) > 8: + warnings.warn(f"key is > 8 characters (key is {key})", + LineOverflow, stacklevel=3) + self.title = title + self.key = key + + self.total_nlines = total_nlines + self.pointer_nlines = pointer_nlines + self.indices_nlines = indices_nlines + self.values_nlines = values_nlines + + parser = FortranFormatParser() + pointer_format = parser.parse(pointer_format_str) + if not isinstance(pointer_format, IntFormat): + raise ValueError("Expected int format for pointer format, got " + f"{pointer_format}") + + indices_format = parser.parse(indices_format_str) + if not isinstance(indices_format, IntFormat): + raise ValueError("Expected int format for indices format, got " + f"{indices_format}") + + values_format = parser.parse(values_format_str) + if isinstance(values_format, ExpFormat): + if mxtype.value_type not in ["real", "complex"]: + raise ValueError(f"Inconsistency between matrix type {mxtype} and " + f"value type {values_format}") + values_dtype = np.float64 + elif isinstance(values_format, IntFormat): + if mxtype.value_type not in ["integer"]: + raise ValueError(f"Inconsistency between matrix type {mxtype} and " + f"value type {values_format}") + # XXX: fortran int -> dtype association ? + values_dtype = int + else: + raise ValueError(f"Unsupported format for values {values_format!r}") + + self.pointer_format = pointer_format + self.indices_format = indices_format + self.values_format = values_format + + self.pointer_dtype = np.int32 + self.indices_dtype = np.int32 + self.values_dtype = values_dtype + + self.pointer_nlines = pointer_nlines + self.pointer_nbytes_full = _nbytes_full(pointer_format, pointer_nlines) + + self.indices_nlines = indices_nlines + self.indices_nbytes_full = _nbytes_full(indices_format, indices_nlines) + + self.values_nlines = values_nlines + self.values_nbytes_full = _nbytes_full(values_format, values_nlines) + + self.nrows = nrows + self.ncols = ncols + self.nnon_zeros = nnon_zeros + self.nelementals = nelementals + self.mxtype = mxtype + + def dump(self): + """Gives the header corresponding to this instance as a string.""" + header = [self.title.ljust(72) + self.key.ljust(8)] + + header.append(f"{self.total_nlines:14d}{self.pointer_nlines:14d}{self.indices_nlines:14d}{self.values_nlines:14d}") + header.append(f"{self.mxtype.fortran_format.ljust(14):14s}{self.nrows:14d}{self.ncols:14d}{self.nnon_zeros:14d}{0:14d}") + + pffmt = self.pointer_format.fortran_format + iffmt = self.indices_format.fortran_format + vffmt = self.values_format.fortran_format + header.append(f"{pffmt.ljust(16):16s}{iffmt.ljust(16):16s}{vffmt.ljust(20):20s}") + return "\n".join(header) + + +def _expect_int(value, msg=None): + try: + return int(value) + except ValueError as e: + if msg is None: + msg = "Expected an int, got %s" + raise ValueError(msg % value) from e + + +def _read_hb_data(content, header): + # XXX: look at a way to reduce memory here (big string creation) + ptr_string = "".join([content.read(header.pointer_nbytes_full), + content.readline()]) + ptr = np.fromstring(ptr_string, + dtype=int, sep=' ') + + ind_string = "".join([content.read(header.indices_nbytes_full), + content.readline()]) + ind = np.fromstring(ind_string, + dtype=int, sep=' ') + + val_string = "".join([content.read(header.values_nbytes_full), + content.readline()]) + val = np.fromstring(val_string, + dtype=header.values_dtype, sep=' ') + + return csc_array((val, ind-1, ptr-1), shape=(header.nrows, header.ncols)) + + +def _write_data(m, fid, header): + m = m.tocsc(copy=False) + + def write_array(f, ar, nlines, fmt): + # ar_nlines is the number of full lines, n is the number of items per + # line, ffmt the fortran format + pyfmt = fmt.python_format + pyfmt_full = pyfmt * fmt.repeat + + # for each array to write, we first write the full lines, and special + # case for partial line + full = ar[:(nlines - 1) * fmt.repeat] + for row in full.reshape((nlines-1, fmt.repeat)): + f.write(pyfmt_full % tuple(row) + "\n") + nremain = ar.size - full.size + if nremain > 0: + f.write((pyfmt * nremain) % tuple(ar[ar.size - nremain:]) + "\n") + + fid.write(header.dump()) + fid.write("\n") + # +1 is for Fortran one-based indexing + write_array(fid, m.indptr+1, header.pointer_nlines, + header.pointer_format) + write_array(fid, m.indices+1, header.indices_nlines, + header.indices_format) + write_array(fid, m.data, header.values_nlines, + header.values_format) + + +class HBMatrixType: + """Class to hold the matrix type.""" + # q2f* translates qualified names to Fortran character + _q2f_type = { + "real": "R", + "complex": "C", + "pattern": "P", + "integer": "I", + } + _q2f_structure = { + "symmetric": "S", + "unsymmetric": "U", + "hermitian": "H", + "skewsymmetric": "Z", + "rectangular": "R" + } + _q2f_storage = { + "assembled": "A", + "elemental": "E", + } + + _f2q_type = {j: i for i, j in _q2f_type.items()} + _f2q_structure = {j: i for i, j in _q2f_structure.items()} + _f2q_storage = {j: i for i, j in _q2f_storage.items()} + + @classmethod + def from_fortran(cls, fmt): + if not len(fmt) == 3: + raise ValueError("Fortran format for matrix type should be 3 " + "characters long") + try: + value_type = cls._f2q_type[fmt[0]] + structure = cls._f2q_structure[fmt[1]] + storage = cls._f2q_storage[fmt[2]] + return cls(value_type, structure, storage) + except KeyError as e: + raise ValueError(f"Unrecognized format {fmt}") from e + + def __init__(self, value_type, structure, storage="assembled"): + self.value_type = value_type + self.structure = structure + self.storage = storage + + if value_type not in self._q2f_type: + raise ValueError(f"Unrecognized type {value_type}") + if structure not in self._q2f_structure: + raise ValueError(f"Unrecognized structure {structure}") + if storage not in self._q2f_storage: + raise ValueError(f"Unrecognized storage {storage}") + + @property + def fortran_format(self): + return self._q2f_type[self.value_type] + \ + self._q2f_structure[self.structure] + \ + self._q2f_storage[self.storage] + + def __repr__(self): + return f"HBMatrixType({self.value_type}, {self.structure}, {self.storage})" + + +class HBFile: + def __init__(self, file, hb_info=None): + """Create a HBFile instance. + + Parameters + ---------- + file : file-object + StringIO work as well + hb_info : HBInfo, optional + Should be given as an argument for writing, in which case the file + should be writable. + """ + self._fid = file + if hb_info is None: + self._hb_info = HBInfo.from_file(file) + else: + #raise OSError("file %s is not writable, and hb_info " + # "was given." % file) + self._hb_info = hb_info + + @property + def title(self): + return self._hb_info.title + + @property + def key(self): + return self._hb_info.key + + @property + def type(self): + return self._hb_info.mxtype.value_type + + @property + def structure(self): + return self._hb_info.mxtype.structure + + @property + def storage(self): + return self._hb_info.mxtype.storage + + def read_matrix(self): + return _read_hb_data(self._fid, self._hb_info) + + def write_matrix(self, m): + return _write_data(m, self._fid, self._hb_info) + + +def hb_read(path_or_open_file, *, spmatrix=True): + """Read HB-format file. + + Parameters + ---------- + path_or_open_file : path-like or file-like + If a file-like object, it is used as-is. Otherwise, it is opened + before reading. + spmatrix : bool, optional (default: True) + If ``True``, return sparse matrix. Otherwise return sparse array. + + Returns + ------- + data : csc_array or csc_matrix + The data read from the HB file as a sparse array. + + Notes + ----- + At the moment not the full Harwell-Boeing format is supported. Supported + features are: + + - assembled, non-symmetric, real matrices + - integer for pointer/indices + - exponential format for float values, and int format + + Examples + -------- + We can read and write a harwell-boeing format file: + + >>> from scipy.io import hb_read, hb_write + >>> from scipy.sparse import csr_array, eye + >>> data = csr_array(eye(3)) # create a sparse array + >>> hb_write("data.hb", data) # write a hb file + >>> print(hb_read("data.hb", spmatrix=False)) # read a hb file + + Coords Values + (0, 0) 1.0 + (1, 1) 1.0 + (2, 2) 1.0 + """ + def _get_matrix(fid): + hb = HBFile(fid) + return hb.read_matrix() + + if hasattr(path_or_open_file, 'read'): + data = _get_matrix(path_or_open_file) + else: + with open(path_or_open_file) as f: + data = _get_matrix(f) + if spmatrix: + return csc_matrix(data) + return data + + +def hb_write(path_or_open_file, m, hb_info=None): + """Write HB-format file. + + Parameters + ---------- + path_or_open_file : path-like or file-like + If a file-like object, it is used as-is. Otherwise, it is opened + before writing. + m : sparse array or matrix + the sparse array to write + hb_info : HBInfo + contains the meta-data for write + + Returns + ------- + None + + Notes + ----- + At the moment not the full Harwell-Boeing format is supported. Supported + features are: + + - assembled, non-symmetric, real matrices + - integer for pointer/indices + - exponential format for float values, and int format + + Examples + -------- + We can read and write a harwell-boeing format file: + + >>> from scipy.io import hb_read, hb_write + >>> from scipy.sparse import csr_array, eye + >>> data = csr_array(eye(3)) # create a sparse array + >>> hb_write("data.hb", data) # write a hb file + >>> print(hb_read("data.hb", spmatrix=False)) # read a hb file + + Coords Values + (0, 0) 1.0 + (1, 1) 1.0 + (2, 2) 1.0 + """ + m = m.tocsc(copy=False) + + if hb_info is None: + hb_info = HBInfo.from_data(m) + + def _set_matrix(fid): + hb = HBFile(fid, hb_info) + return hb.write_matrix(m) + + if hasattr(path_or_open_file, 'write'): + return _set_matrix(path_or_open_file) + else: + with open(path_or_open_file, 'w') as f: + return _set_matrix(f) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..472b05b43e5a68ef03dd566417555c587ec00325 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/__pycache__/test_fortran_format.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/__pycache__/test_fortran_format.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..90e460087090e83fd55c4ffc5b9f224c407d9b5a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/__pycache__/test_fortran_format.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/__pycache__/test_hb.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/__pycache__/test_hb.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f951067238e2a98af9d235d4422316bd5b10bb9f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/__pycache__/test_hb.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/test_fortran_format.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/test_fortran_format.py new file mode 100644 index 0000000000000000000000000000000000000000..dae040c523d6a6d618e89402d39a0cb05bad927a --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/test_fortran_format.py @@ -0,0 +1,74 @@ +import numpy as np + +from numpy.testing import assert_equal +from pytest import raises as assert_raises + +from scipy.io._harwell_boeing._fortran_format_parser import ( + FortranFormatParser, IntFormat, ExpFormat, BadFortranFormat) + + +class TestFortranFormatParser: + def setup_method(self): + self.parser = FortranFormatParser() + + def _test_equal(self, format, ref): + ret = self.parser.parse(format) + assert_equal(ret.__dict__, ref.__dict__) + + def test_simple_int(self): + self._test_equal("(I4)", IntFormat(4)) + + def test_simple_repeated_int(self): + self._test_equal("(3I4)", IntFormat(4, repeat=3)) + + def test_simple_exp(self): + self._test_equal("(E4.3)", ExpFormat(4, 3)) + + def test_exp_exp(self): + self._test_equal("(E8.3E3)", ExpFormat(8, 3, 3)) + + def test_repeat_exp(self): + self._test_equal("(2E4.3)", ExpFormat(4, 3, repeat=2)) + + def test_repeat_exp_exp(self): + self._test_equal("(2E8.3E3)", ExpFormat(8, 3, 3, repeat=2)) + + def test_wrong_formats(self): + def _test_invalid(bad_format): + assert_raises(BadFortranFormat, lambda: self.parser.parse(bad_format)) + _test_invalid("I4") + _test_invalid("(E4)") + _test_invalid("(E4.)") + _test_invalid("(E4.E3)") + + +class TestIntFormat: + def test_to_fortran(self): + f = [IntFormat(10), IntFormat(12, 10), IntFormat(12, 10, 3)] + res = ["(I10)", "(I12.10)", "(3I12.10)"] + + for i, j in zip(f, res): + assert_equal(i.fortran_format, j) + + def test_from_number(self): + f = [10, -12, 123456789] + r_f = [IntFormat(3, repeat=26), IntFormat(4, repeat=20), + IntFormat(10, repeat=8)] + for i, j in zip(f, r_f): + assert_equal(IntFormat.from_number(i).__dict__, j.__dict__) + + +class TestExpFormat: + def test_to_fortran(self): + f = [ExpFormat(10, 5), ExpFormat(12, 10), ExpFormat(12, 10, min=3), + ExpFormat(10, 5, repeat=3)] + res = ["(E10.5)", "(E12.10)", "(E12.10E3)", "(3E10.5)"] + + for i, j in zip(f, res): + assert_equal(i.fortran_format, j) + + def test_from_number(self): + f = np.array([1.0, -1.2]) + r_f = [ExpFormat(24, 16, repeat=3), ExpFormat(25, 16, repeat=3)] + for i, j in zip(f, r_f): + assert_equal(ExpFormat.from_number(i).__dict__, j.__dict__) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/test_hb.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/test_hb.py new file mode 100644 index 0000000000000000000000000000000000000000..d0c9ee5635fdd45c0f6560e686c9e40176ef95e4 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/_harwell_boeing/tests/test_hb.py @@ -0,0 +1,70 @@ +from io import StringIO +import tempfile + +import numpy as np + +from numpy.testing import assert_equal, \ + assert_array_almost_equal_nulp + +from scipy.sparse import coo_array, csc_array, random_array, isspmatrix + +from scipy.io import hb_read, hb_write + + +SIMPLE = """\ +No Title |No Key + 9 4 1 4 +RUA 100 100 10 0 +(26I3) (26I3) (3E23.15) +1 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 4 4 4 6 6 6 6 6 6 6 6 6 6 6 8 9 9 9 9 +9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 11 +37 71 89 18 30 45 70 19 25 52 +2.971243799687726e-01 3.662366682877375e-01 4.786962174699534e-01 +6.490068647991184e-01 6.617490424831662e-02 8.870370343191623e-01 +4.196478590163001e-01 5.649603072111251e-01 9.934423887087086e-01 +6.912334991524289e-01 +""" + +SIMPLE_MATRIX = coo_array( + ((0.297124379969, 0.366236668288, 0.47869621747, 0.649006864799, + 0.0661749042483, 0.887037034319, 0.419647859016, + 0.564960307211, 0.993442388709, 0.691233499152,), + (np.array([[36, 70, 88, 17, 29, 44, 69, 18, 24, 51], + [0, 4, 58, 61, 61, 72, 72, 73, 99, 99]])))) + + +def assert_csc_almost_equal(r, l): + r = csc_array(r) + l = csc_array(l) + assert_equal(r.indptr, l.indptr) + assert_equal(r.indices, l.indices) + assert_array_almost_equal_nulp(r.data, l.data, 10000) + + +class TestHBReader: + def test_simple(self): + m = hb_read(StringIO(SIMPLE), spmatrix=False) + assert_csc_almost_equal(m, SIMPLE_MATRIX) + assert not isspmatrix(m) + m = hb_read(StringIO(SIMPLE), spmatrix=True) + assert isspmatrix(m) + m = hb_read(StringIO(SIMPLE)) # default + assert isspmatrix(m) + + +class TestHBReadWrite: + + def check_save_load(self, value): + with tempfile.NamedTemporaryFile(mode='w+t') as file: + hb_write(file, value) + file.file.seek(0) + value_loaded = hb_read(file, spmatrix=False) + assert_csc_almost_equal(value, value_loaded) + + def test_simple(self): + random_arr = random_array((10, 100), density=0.1) + for format in ('coo', 'csc', 'csr', 'bsr', 'dia', 'dok', 'lil'): + arr = random_arr.asformat(format, copy=False) + self.check_save_load(arr) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..dcfe1c4237e69054b582a0fa52f710b25a1d7914 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/__init__.py @@ -0,0 +1,28 @@ +""" +Module to read ARFF files +========================= +ARFF is the standard data format for WEKA. +It is a text file format which support numerical, string and data values. +The format can also represent missing data and sparse data. + +Notes +----- +The ARFF support in ``scipy.io`` provides file reading functionality only. +For more extensive ARFF functionality, see `liac-arff +`_. + +See the `WEKA website `_ +for more details about the ARFF format and available datasets. + +""" +from ._arffread import * +from . import _arffread + +# Deprecated namespaces, to be removed in v2.0.0 +from .import arffread + +__all__ = _arffread.__all__ + ['arffread'] + +from scipy._lib._testutils import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ea920eba34c12482964e8843f28747281eb058b8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/__pycache__/_arffread.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/__pycache__/_arffread.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cab4d176954c87d60829820317c6677f75966fbc Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/__pycache__/_arffread.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/__pycache__/arffread.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/__pycache__/arffread.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..96477a92171029f1ff73d9ad72dd96a3e3a7e2df Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/__pycache__/arffread.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/_arffread.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/_arffread.py new file mode 100644 index 0000000000000000000000000000000000000000..a7f3b78199b21106a2a21e5c605365766559bee3 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/_arffread.py @@ -0,0 +1,885 @@ +# Last Change: Mon Aug 20 08:00 PM 2007 J +import re +import datetime + +import numpy as np + +import csv +import ctypes + +"""A module to read arff files.""" + +__all__ = ['MetaData', 'loadarff', 'ArffError', 'ParseArffError'] + +# An Arff file is basically two parts: +# - header +# - data +# +# A header has each of its components starting by @META where META is one of +# the keyword (attribute of relation, for now). + +# TODO: +# - both integer and reals are treated as numeric -> the integer info +# is lost! +# - Replace ValueError by ParseError or something + +# We know can handle the following: +# - numeric and nominal attributes +# - missing values for numeric attributes + +r_meta = re.compile(r'^\s*@') +# Match a comment +r_comment = re.compile(r'^%') +# Match an empty line +r_empty = re.compile(r'^\s+$') +# Match a header line, that is a line which starts by @ + a word +r_headerline = re.compile(r'^\s*@\S*') +r_datameta = re.compile(r'^@[Dd][Aa][Tt][Aa]') +r_relation = re.compile(r'^@[Rr][Ee][Ll][Aa][Tt][Ii][Oo][Nn]\s*(\S*)') +r_attribute = re.compile(r'^\s*@[Aa][Tt][Tt][Rr][Ii][Bb][Uu][Tt][Ee]\s*(..*$)') + +r_nominal = re.compile(r'{(.+)}') +r_date = re.compile(r"[Dd][Aa][Tt][Ee]\s+[\"']?(.+?)[\"']?$") + +# To get attributes name enclosed with '' +r_comattrval = re.compile(r"'(..+)'\s+(..+$)") +# To get normal attributes +r_wcomattrval = re.compile(r"(\S+)\s+(..+$)") + +# ------------------------ +# Module defined exception +# ------------------------ + + +class ArffError(OSError): + """ + Base exception for errors when reading ARFF files. + + Raised when an ARFF file cannot be read due to file access issues, + corruption, or unsupported features. + """ + pass + + +class ParseArffError(ArffError): + """ + Exception for syntax and parsing errors in ARFF files. + + Raised when an ARFF file has invalid syntax, malformed attributes, + or data that doesn't match the expected format. + """ + pass + + +# ---------- +# Attributes +# ---------- +class Attribute: + + type_name = None + + def __init__(self, name): + self.name = name + self.range = None + self.dtype = np.object_ + + @classmethod + def parse_attribute(cls, name, attr_string): + """ + Parse the attribute line if it knows how. Returns the parsed + attribute, or None. + """ + return None + + def parse_data(self, data_str): + """ + Parse a value of this type. + """ + return None + + def __str__(self): + """ + Parse a value of this type. + """ + return self.name + ',' + self.type_name + + +class NominalAttribute(Attribute): + + type_name = 'nominal' + + def __init__(self, name, values): + super().__init__(name) + self.values = values + self.range = values + self.dtype = (np.bytes_, max(len(i) for i in values)) + + @staticmethod + def _get_nom_val(atrv): + """Given a string containing a nominal type, returns a tuple of the + possible values. + + A nominal type is defined as something framed between braces ({}). + + Parameters + ---------- + atrv : str + Nominal type definition + + Returns + ------- + poss_vals : tuple + possible values + + Examples + -------- + >>> from scipy.io.arff._arffread import NominalAttribute + >>> NominalAttribute._get_nom_val("{floup, bouga, fl, ratata}") + ('floup', 'bouga', 'fl', 'ratata') + """ + m = r_nominal.match(atrv) + if m: + attrs, _ = split_data_line(m.group(1)) + return tuple(attrs) + else: + raise ValueError("This does not look like a nominal string") + + @classmethod + def parse_attribute(cls, name, attr_string): + """ + Parse the attribute line if it knows how. Returns the parsed + attribute, or None. + + For nominal attributes, the attribute string would be like '{, + , }'. + """ + if attr_string[0] == '{': + values = cls._get_nom_val(attr_string) + return cls(name, values) + else: + return None + + def parse_data(self, data_str): + """ + Parse a value of this type. + """ + if data_str in self.values: + return data_str + elif data_str == '?': + return data_str + else: + raise ValueError(f"{str(data_str)} value not in {str(self.values)}") + + def __str__(self): + msg = self.name + ",{" + for i in range(len(self.values)-1): + msg += self.values[i] + "," + msg += self.values[-1] + msg += "}" + return msg + + +class NumericAttribute(Attribute): + + def __init__(self, name): + super().__init__(name) + self.type_name = 'numeric' + self.dtype = np.float64 + + @classmethod + def parse_attribute(cls, name, attr_string): + """ + Parse the attribute line if it knows how. Returns the parsed + attribute, or None. + + For numeric attributes, the attribute string would be like + 'numeric' or 'int' or 'real'. + """ + + attr_string = attr_string.lower().strip() + + if (attr_string[:len('numeric')] == 'numeric' or + attr_string[:len('int')] == 'int' or + attr_string[:len('real')] == 'real'): + return cls(name) + else: + return None + + def parse_data(self, data_str): + """ + Parse a value of this type. + + Parameters + ---------- + data_str : str + string to convert + + Returns + ------- + f : float + where float can be nan + + Examples + -------- + >>> from scipy.io.arff._arffread import NumericAttribute + >>> atr = NumericAttribute('atr') + >>> atr.parse_data('1') + 1.0 + >>> atr.parse_data('1\\n') + 1.0 + >>> atr.parse_data('?\\n') + nan + """ + if '?' in data_str: + return np.nan + else: + return float(data_str) + + def _basic_stats(self, data): + nbfac = data.size * 1. / (data.size - 1) + return (np.nanmin(data), np.nanmax(data), + np.mean(data), np.std(data) * nbfac) + + +class StringAttribute(Attribute): + + def __init__(self, name): + super().__init__(name) + self.type_name = 'string' + + @classmethod + def parse_attribute(cls, name, attr_string): + """ + Parse the attribute line if it knows how. Returns the parsed + attribute, or None. + + For string attributes, the attribute string would be like + 'string'. + """ + + attr_string = attr_string.lower().strip() + + if attr_string[:len('string')] == 'string': + return cls(name) + else: + return None + + +class DateAttribute(Attribute): + + def __init__(self, name, date_format, datetime_unit): + super().__init__(name) + self.date_format = date_format + self.datetime_unit = datetime_unit + self.type_name = 'date' + self.range = date_format + self.dtype = np.datetime64(0, self.datetime_unit) + + @staticmethod + def _get_date_format(atrv): + m = r_date.match(atrv) + if m: + pattern = m.group(1).strip() + # convert time pattern from Java's SimpleDateFormat to C's format + datetime_unit = None + if "yyyy" in pattern: + pattern = pattern.replace("yyyy", "%Y") + datetime_unit = "Y" + elif "yy": + pattern = pattern.replace("yy", "%y") + datetime_unit = "Y" + if "MM" in pattern: + pattern = pattern.replace("MM", "%m") + datetime_unit = "M" + if "dd" in pattern: + pattern = pattern.replace("dd", "%d") + datetime_unit = "D" + if "HH" in pattern: + pattern = pattern.replace("HH", "%H") + datetime_unit = "h" + if "mm" in pattern: + pattern = pattern.replace("mm", "%M") + datetime_unit = "m" + if "ss" in pattern: + pattern = pattern.replace("ss", "%S") + datetime_unit = "s" + if "z" in pattern or "Z" in pattern: + raise ValueError("Date type attributes with time zone not " + "supported, yet") + + if datetime_unit is None: + raise ValueError("Invalid or unsupported date format") + + return pattern, datetime_unit + else: + raise ValueError("Invalid or no date format") + + @classmethod + def parse_attribute(cls, name, attr_string): + """ + Parse the attribute line if it knows how. Returns the parsed + attribute, or None. + + For date attributes, the attribute string would be like + 'date '. + """ + + attr_string_lower = attr_string.lower().strip() + + if attr_string_lower[:len('date')] == 'date': + date_format, datetime_unit = cls._get_date_format(attr_string) + return cls(name, date_format, datetime_unit) + else: + return None + + def parse_data(self, data_str): + """ + Parse a value of this type. + """ + date_str = data_str.strip().strip("'").strip('"') + if date_str == '?': + return np.datetime64('NaT', self.datetime_unit) + else: + dt = datetime.datetime.strptime(date_str, self.date_format) + return np.datetime64(dt).astype( + f"datetime64[{self.datetime_unit}]") + + def __str__(self): + return super().__str__() + ',' + self.date_format + + +class RelationalAttribute(Attribute): + + def __init__(self, name): + super().__init__(name) + self.type_name = 'relational' + self.dtype = np.object_ + self.attributes = [] + self.dialect = None + + @classmethod + def parse_attribute(cls, name, attr_string): + """ + Parse the attribute line if it knows how. Returns the parsed + attribute, or None. + + For date attributes, the attribute string would be like + 'date '. + """ + + attr_string_lower = attr_string.lower().strip() + + if attr_string_lower[:len('relational')] == 'relational': + return cls(name) + else: + return None + + def parse_data(self, data_str): + # Copy-pasted + elems = list(range(len(self.attributes))) + + escaped_string = data_str.encode().decode("unicode-escape") + + row_tuples = [] + + for raw in escaped_string.split("\n"): + row, self.dialect = split_data_line(raw, self.dialect) + + row_tuples.append(tuple( + [self.attributes[i].parse_data(row[i]) for i in elems])) + + return np.array(row_tuples, + [(a.name, a.dtype) for a in self.attributes]) + + def __str__(self): + return (super().__str__() + '\n\t' + + '\n\t'.join(str(a) for a in self.attributes)) + + +# ----------------- +# Various utilities +# ----------------- +def to_attribute(name, attr_string): + attr_classes = (NominalAttribute, NumericAttribute, DateAttribute, + StringAttribute, RelationalAttribute) + + for cls in attr_classes: + attr = cls.parse_attribute(name, attr_string) + if attr is not None: + return attr + + raise ParseArffError(f"unknown attribute {attr_string}") + + +def csv_sniffer_has_bug_last_field(): + """ + Checks if the bug https://bugs.python.org/issue30157 is unpatched. + """ + + # We only compute this once. + has_bug = getattr(csv_sniffer_has_bug_last_field, "has_bug", None) + + if has_bug is None: + dialect = csv.Sniffer().sniff("3, 'a'") + csv_sniffer_has_bug_last_field.has_bug = dialect.quotechar != "'" + has_bug = csv_sniffer_has_bug_last_field.has_bug + + return has_bug + + +def workaround_csv_sniffer_bug_last_field(sniff_line, dialect, delimiters): + """ + Workaround for the bug https://bugs.python.org/issue30157 if is unpatched. + """ + if csv_sniffer_has_bug_last_field(): + # Reuses code from the csv module + right_regex = r'(?P[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?:$|\n)' # noqa: E501 + + for restr in (r'(?P[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?P=delim)', # ,".*?", # noqa: E501 + r'(?:^|\n)(?P["\']).*?(?P=quote)(?P[^\w\n"\'])(?P ?)', # .*?", # noqa: E501 + right_regex, # ,".*?" + r'(?:^|\n)(?P["\']).*?(?P=quote)(?:$|\n)'): # ".*?" (no delim, no space) # noqa: E501 + regexp = re.compile(restr, re.DOTALL | re.MULTILINE) + matches = regexp.findall(sniff_line) + if matches: + break + + # If it does not match the expression that was bugged, + # then this bug does not apply + if restr != right_regex: + return + + groupindex = regexp.groupindex + + # There is only one end of the string + assert len(matches) == 1 + m = matches[0] + + n = groupindex['quote'] - 1 + quote = m[n] + + n = groupindex['delim'] - 1 + delim = m[n] + + n = groupindex['space'] - 1 + space = bool(m[n]) + + dq_regexp = re.compile( + rf"(({re.escape(delim)})|^)\W*{quote}[^{re.escape(delim)}\n]*{quote}[^{re.escape(delim)}\n]*{quote}\W*(({re.escape(delim)})|$)", re.MULTILINE # noqa: E501 + ) + + doublequote = bool(dq_regexp.search(sniff_line)) + + dialect.quotechar = quote + if delim in delimiters: + dialect.delimiter = delim + dialect.doublequote = doublequote + dialect.skipinitialspace = space + + +def split_data_line(line, dialect=None): + delimiters = ",\t" + + # This can not be done in a per reader basis, and relational fields + # can be HUGE + csv.field_size_limit(int(ctypes.c_ulong(-1).value // 2)) + + # Remove the line end if any + if line[-1] == '\n': + line = line[:-1] + + # Remove potential trailing whitespace + line = line.strip() + + sniff_line = line + + # Add a delimiter if none is present, so that the csv.Sniffer + # does not complain for a single-field CSV. + if not any(d in line for d in delimiters): + sniff_line += "," + + if dialect is None: + dialect = csv.Sniffer().sniff(sniff_line, delimiters=delimiters) + workaround_csv_sniffer_bug_last_field(sniff_line=sniff_line, + dialect=dialect, + delimiters=delimiters) + + row = next(csv.reader([line], dialect)) + + return row, dialect + + +# -------------- +# Parsing header +# -------------- +def tokenize_attribute(iterable, attribute): + """Parse a raw string in header (e.g., starts by @attribute). + + Given a raw string attribute, try to get the name and type of the + attribute. Constraints: + + * The first line must start with @attribute (case insensitive, and + space like characters before @attribute are allowed) + * Works also if the attribute is spread on multilines. + * Works if empty lines or comments are in between + + Parameters + ---------- + attribute : str + the attribute string. + + Returns + ------- + name : str + name of the attribute + value : str + value of the attribute + next : str + next line to be parsed + + Examples + -------- + If attribute is a string defined in python as r"floupi real", will + return floupi as name, and real as value. + + >>> from scipy.io.arff._arffread import tokenize_attribute + >>> iterable = iter([0] * 10) # dummy iterator + >>> tokenize_attribute(iterable, r"@attribute floupi real") + ('floupi', 'real', 0) + + If attribute is r"'floupi 2' real", will return 'floupi 2' as name, + and real as value. + + >>> tokenize_attribute(iterable, r" @attribute 'floupi 2' real ") + ('floupi 2', 'real', 0) + + """ + sattr = attribute.strip() + mattr = r_attribute.match(sattr) + if mattr: + # atrv is everything after @attribute + atrv = mattr.group(1) + if r_comattrval.match(atrv): + name, type = tokenize_single_comma(atrv) + next_item = next(iterable) + elif r_wcomattrval.match(atrv): + name, type = tokenize_single_wcomma(atrv) + next_item = next(iterable) + else: + # Not sure we should support this, as it does not seem supported by + # weka. + raise ValueError("multi line not supported yet") + else: + raise ValueError(f"First line unparsable: {sattr}") + + attribute = to_attribute(name, type) + + if type.lower() == 'relational': + next_item = read_relational_attribute(iterable, attribute, next_item) + # raise ValueError("relational attributes not supported yet") + + return attribute, next_item + + +def tokenize_single_comma(val): + # XXX we match twice the same string (here and at the caller level). It is + # stupid, but it is easier for now... + m = r_comattrval.match(val) + if m: + try: + name = m.group(1).strip() + type = m.group(2).strip() + except IndexError as e: + raise ValueError("Error while tokenizing attribute") from e + else: + raise ValueError(f"Error while tokenizing single {val}") + return name, type + + +def tokenize_single_wcomma(val): + # XXX we match twice the same string (here and at the caller level). It is + # stupid, but it is easier for now... + m = r_wcomattrval.match(val) + if m: + try: + name = m.group(1).strip() + type = m.group(2).strip() + except IndexError as e: + raise ValueError("Error while tokenizing attribute") from e + else: + raise ValueError(f"Error while tokenizing single {val}") + return name, type + + +def read_relational_attribute(ofile, relational_attribute, i): + """Read the nested attributes of a relational attribute""" + + r_end_relational = re.compile(r'^@[Ee][Nn][Dd]\s*' + + relational_attribute.name + r'\s*$') + + while not r_end_relational.match(i): + m = r_headerline.match(i) + if m: + isattr = r_attribute.match(i) + if isattr: + attr, i = tokenize_attribute(ofile, i) + relational_attribute.attributes.append(attr) + else: + raise ValueError(f"Error parsing line {i}") + else: + i = next(ofile) + + i = next(ofile) + return i + + +def read_header(ofile): + """Read the header of the iterable ofile.""" + i = next(ofile) + + # Pass first comments + while r_comment.match(i): + i = next(ofile) + + # Header is everything up to DATA attribute ? + relation = None + attributes = [] + while not r_datameta.match(i): + m = r_headerline.match(i) + if m: + isattr = r_attribute.match(i) + if isattr: + attr, i = tokenize_attribute(ofile, i) + attributes.append(attr) + else: + isrel = r_relation.match(i) + if isrel: + relation = isrel.group(1) + else: + raise ValueError(f"Error parsing line {i}") + i = next(ofile) + else: + i = next(ofile) + + return relation, attributes + + +class MetaData: + """Small container to keep useful information on a ARFF dataset. + + Knows about attributes names and types. + + Examples + -------- + :: + + data, meta = loadarff('iris.arff') + # This will print the attributes names of the iris.arff dataset + for i in meta: + print(i) + # This works too + meta.names() + # Getting attribute type + types = meta.types() + + Methods + ------- + names + types + + Notes + ----- + Also maintains the list of attributes in order, i.e., doing for i in + meta, where meta is an instance of MetaData, will return the + different attribute names in the order they were defined. + """ + def __init__(self, rel, attr): + self.name = rel + self._attributes = {a.name: a for a in attr} + + def __repr__(self): + msg = "" + msg += f"Dataset: {self.name}\n" + for i in self._attributes: + msg += f"\t{i}'s type is {self._attributes[i].type_name}" + if self._attributes[i].range: + msg += f", range is {str(self._attributes[i].range)}" + msg += '\n' + return msg + + def __iter__(self): + return iter(self._attributes) + + def __getitem__(self, key): + attr = self._attributes[key] + + return (attr.type_name, attr.range) + + def names(self): + """Return the list of attribute names. + + Returns + ------- + attrnames : list of str + The attribute names. + """ + return list(self._attributes) + + def types(self): + """Return the list of attribute types. + + Returns + ------- + attr_types : list of str + The attribute types. + """ + attr_types = [self._attributes[name].type_name + for name in self._attributes] + return attr_types + + +def loadarff(f): + """ + Read an arff file. + + The data is returned as a record array, which can be accessed much like + a dictionary of NumPy arrays. For example, if one of the attributes is + called 'pressure', then its first 10 data points can be accessed from the + ``data`` record array like so: ``data['pressure'][0:10]`` + + + Parameters + ---------- + f : file-like or str + File-like object to read from, or filename to open. + + Returns + ------- + data : record array + The data of the arff file, accessible by attribute names. + meta : `MetaData` + Contains information about the arff file such as name and + type of attributes, the relation (name of the dataset), etc. + + Raises + ------ + ParseArffError + This is raised if the given file is not ARFF-formatted. + NotImplementedError + The ARFF file has an attribute which is not supported yet. + + Notes + ----- + + This function should be able to read most arff files. Not + implemented functionality include: + + * date type attributes + * string type attributes + + It can read files with numeric and nominal attributes. It cannot read + files with sparse data ({} in the file). However, this function can + read files with missing data (? in the file), representing the data + points as NaNs. + + Examples + -------- + >>> from scipy.io import arff + >>> from io import StringIO + >>> content = \"\"\" + ... @relation foo + ... @attribute width numeric + ... @attribute height numeric + ... @attribute color {red,green,blue,yellow,black} + ... @data + ... 5.0,3.25,blue + ... 4.5,3.75,green + ... 3.0,4.00,red + ... \"\"\" + >>> f = StringIO(content) + >>> data, meta = arff.loadarff(f) + >>> data + array([(5.0, 3.25, 'blue'), (4.5, 3.75, 'green'), (3.0, 4.0, 'red')], + dtype=[('width', '>> meta + Dataset: foo + \twidth's type is numeric + \theight's type is numeric + \tcolor's type is nominal, range is ('red', 'green', 'blue', 'yellow', 'black') + + """ + if hasattr(f, 'read'): + ofile = f + else: + ofile = open(f) + try: + return _loadarff(ofile) + finally: + if ofile is not f: # only close what we opened + ofile.close() + + +def _loadarff(ofile): + # Parse the header file + try: + rel, attr = read_header(ofile) + except ValueError as e: + msg = "Error while parsing header, error was: " + str(e) + raise ParseArffError(msg) from e + + # Check whether we have a string attribute (not supported yet) + hasstr = False + for a in attr: + if isinstance(a, StringAttribute): + hasstr = True + + meta = MetaData(rel, attr) + + # XXX The following code is not great + # Build the type descriptor descr and the list of converters to convert + # each attribute to the suitable type (which should match the one in + # descr). + + # This can be used once we want to support integer as integer values and + # not as numeric anymore (using masked arrays ?). + + if hasstr: + # How to support string efficiently ? Ideally, we should know the max + # size of the string before allocating the numpy array. + raise NotImplementedError("String attributes not supported yet, sorry") + + ni = len(attr) + + def generator(row_iter, delim=','): + # TODO: this is where we are spending time (~80%). I think things + # could be made more efficiently: + # - We could for example "compile" the function, because some values + # do not change here. + # - The function to convert a line to dtyped values could also be + # generated on the fly from a string and be executed instead of + # looping. + # - The regex are overkill: for comments, checking that a line starts + # by % should be enough and faster, and for empty lines, same thing + # --> this does not seem to change anything. + + # 'compiling' the range since it does not change + # Note, I have already tried zipping the converters and + # row elements and got slightly worse performance. + elems = list(range(ni)) + + dialect = None + for raw in row_iter: + # We do not abstract skipping comments and empty lines for + # performance reasons. + if r_comment.match(raw) or r_empty.match(raw): + continue + + row, dialect = split_data_line(raw, dialect) + + yield tuple([attr[i].parse_data(row[i]) for i in elems]) + + a = list(generator(ofile)) + # No error should happen here: it is a bug otherwise + data = np.array(a, [(a.name, a.dtype) for a in attr]) + return data, meta + diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/arffread.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/arffread.py new file mode 100644 index 0000000000000000000000000000000000000000..c42ae31db6bde3987bd059cc7451d1ae87f0073c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/arffread.py @@ -0,0 +1,19 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.io.arff` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + +__all__ = [ # noqa: F822 + 'MetaData', 'loadarff', 'ArffError', 'ParseArffError', +] + + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="io.arff", module="arffread", + private_modules=["_arffread"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f8baed18972560e1cbbf1f1e89e8e60d306b48c4 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/__pycache__/test_arffread.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/__pycache__/test_arffread.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5e0907252225768aa3b29addfbc61564a8ffe93b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/__pycache__/test_arffread.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/iris.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/iris.arff new file mode 100644 index 0000000000000000000000000000000000000000..780480c7c6b9a68bf71aaf357c7d3f7a5b3b3f57 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/iris.arff @@ -0,0 +1,225 @@ +% 1. Title: Iris Plants Database +% +% 2. Sources: +% (a) Creator: R.A. Fisher +% (b) Donor: Michael Marshall (MARSHALL%PLU@io.arc.nasa.gov) +% (c) Date: July, 1988 +% +% 3. Past Usage: +% - Publications: too many to mention!!! Here are a few. +% 1. Fisher,R.A. "The use of multiple measurements in taxonomic problems" +% Annual Eugenics, 7, Part II, 179-188 (1936); also in "Contributions +% to Mathematical Statistics" (John Wiley, NY, 1950). +% 2. Duda,R.O., & Hart,P.E. (1973) Pattern Classification and Scene Analysis. +% (Q327.D83) John Wiley & Sons. ISBN 0-471-22361-1. See page 218. +% 3. Dasarathy, B.V. (1980) "Nosing Around the Neighborhood: A New System +% Structure and Classification Rule for Recognition in Partially Exposed +% Environments". IEEE Transactions on Pattern Analysis and Machine +% Intelligence, Vol. PAMI-2, No. 1, 67-71. +% -- Results: +% -- very low misclassification rates (0% for the setosa class) +% 4. Gates, G.W. (1972) "The Reduced Nearest Neighbor Rule". IEEE +% Transactions on Information Theory, May 1972, 431-433. +% -- Results: +% -- very low misclassification rates again +% 5. See also: 1988 MLC Proceedings, 54-64. Cheeseman et al's AUTOCLASS II +% conceptual clustering system finds 3 classes in the data. +% +% 4. Relevant Information: +% --- This is perhaps the best known database to be found in the pattern +% recognition literature. Fisher's paper is a classic in the field +% and is referenced frequently to this day. (See Duda & Hart, for +% example.) The data set contains 3 classes of 50 instances each, +% where each class refers to a type of iris plant. One class is +% linearly separable from the other 2; the latter are NOT linearly +% separable from each other. +% --- Predicted attribute: class of iris plant. +% --- This is an exceedingly simple domain. +% +% 5. Number of Instances: 150 (50 in each of three classes) +% +% 6. Number of Attributes: 4 numeric, predictive attributes and the class +% +% 7. Attribute Information: +% 1. sepal length in cm +% 2. sepal width in cm +% 3. petal length in cm +% 4. petal width in cm +% 5. class: +% -- Iris Setosa +% -- Iris Versicolour +% -- Iris Virginica +% +% 8. Missing Attribute Values: None +% +% Summary Statistics: +% Min Max Mean SD Class Correlation +% sepal length: 4.3 7.9 5.84 0.83 0.7826 +% sepal width: 2.0 4.4 3.05 0.43 -0.4194 +% petal length: 1.0 6.9 3.76 1.76 0.9490 (high!) +% petal width: 0.1 2.5 1.20 0.76 0.9565 (high!) +% +% 9. Class Distribution: 33.3% for each of 3 classes. + +@RELATION iris + +@ATTRIBUTE sepallength REAL +@ATTRIBUTE sepalwidth REAL +@ATTRIBUTE petallength REAL +@ATTRIBUTE petalwidth REAL +@ATTRIBUTE class {Iris-setosa,Iris-versicolor,Iris-virginica} + +@DATA +5.1,3.5,1.4,0.2,Iris-setosa +4.9,3.0,1.4,0.2,Iris-setosa +4.7,3.2,1.3,0.2,Iris-setosa +4.6,3.1,1.5,0.2,Iris-setosa +5.0,3.6,1.4,0.2,Iris-setosa +5.4,3.9,1.7,0.4,Iris-setosa +4.6,3.4,1.4,0.3,Iris-setosa +5.0,3.4,1.5,0.2,Iris-setosa +4.4,2.9,1.4,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +5.4,3.7,1.5,0.2,Iris-setosa +4.8,3.4,1.6,0.2,Iris-setosa +4.8,3.0,1.4,0.1,Iris-setosa +4.3,3.0,1.1,0.1,Iris-setosa +5.8,4.0,1.2,0.2,Iris-setosa +5.7,4.4,1.5,0.4,Iris-setosa +5.4,3.9,1.3,0.4,Iris-setosa +5.1,3.5,1.4,0.3,Iris-setosa +5.7,3.8,1.7,0.3,Iris-setosa +5.1,3.8,1.5,0.3,Iris-setosa +5.4,3.4,1.7,0.2,Iris-setosa +5.1,3.7,1.5,0.4,Iris-setosa +4.6,3.6,1.0,0.2,Iris-setosa +5.1,3.3,1.7,0.5,Iris-setosa +4.8,3.4,1.9,0.2,Iris-setosa +5.0,3.0,1.6,0.2,Iris-setosa +5.0,3.4,1.6,0.4,Iris-setosa +5.2,3.5,1.5,0.2,Iris-setosa +5.2,3.4,1.4,0.2,Iris-setosa +4.7,3.2,1.6,0.2,Iris-setosa +4.8,3.1,1.6,0.2,Iris-setosa +5.4,3.4,1.5,0.4,Iris-setosa +5.2,4.1,1.5,0.1,Iris-setosa +5.5,4.2,1.4,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +5.0,3.2,1.2,0.2,Iris-setosa +5.5,3.5,1.3,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +4.4,3.0,1.3,0.2,Iris-setosa +5.1,3.4,1.5,0.2,Iris-setosa +5.0,3.5,1.3,0.3,Iris-setosa +4.5,2.3,1.3,0.3,Iris-setosa +4.4,3.2,1.3,0.2,Iris-setosa +5.0,3.5,1.6,0.6,Iris-setosa +5.1,3.8,1.9,0.4,Iris-setosa +4.8,3.0,1.4,0.3,Iris-setosa +5.1,3.8,1.6,0.2,Iris-setosa +4.6,3.2,1.4,0.2,Iris-setosa +5.3,3.7,1.5,0.2,Iris-setosa +5.0,3.3,1.4,0.2,Iris-setosa +7.0,3.2,4.7,1.4,Iris-versicolor +6.4,3.2,4.5,1.5,Iris-versicolor +6.9,3.1,4.9,1.5,Iris-versicolor +5.5,2.3,4.0,1.3,Iris-versicolor +6.5,2.8,4.6,1.5,Iris-versicolor +5.7,2.8,4.5,1.3,Iris-versicolor +6.3,3.3,4.7,1.6,Iris-versicolor +4.9,2.4,3.3,1.0,Iris-versicolor +6.6,2.9,4.6,1.3,Iris-versicolor +5.2,2.7,3.9,1.4,Iris-versicolor +5.0,2.0,3.5,1.0,Iris-versicolor +5.9,3.0,4.2,1.5,Iris-versicolor +6.0,2.2,4.0,1.0,Iris-versicolor +6.1,2.9,4.7,1.4,Iris-versicolor +5.6,2.9,3.6,1.3,Iris-versicolor +6.7,3.1,4.4,1.4,Iris-versicolor +5.6,3.0,4.5,1.5,Iris-versicolor +5.8,2.7,4.1,1.0,Iris-versicolor +6.2,2.2,4.5,1.5,Iris-versicolor +5.6,2.5,3.9,1.1,Iris-versicolor +5.9,3.2,4.8,1.8,Iris-versicolor +6.1,2.8,4.0,1.3,Iris-versicolor +6.3,2.5,4.9,1.5,Iris-versicolor +6.1,2.8,4.7,1.2,Iris-versicolor +6.4,2.9,4.3,1.3,Iris-versicolor +6.6,3.0,4.4,1.4,Iris-versicolor +6.8,2.8,4.8,1.4,Iris-versicolor +6.7,3.0,5.0,1.7,Iris-versicolor +6.0,2.9,4.5,1.5,Iris-versicolor +5.7,2.6,3.5,1.0,Iris-versicolor +5.5,2.4,3.8,1.1,Iris-versicolor +5.5,2.4,3.7,1.0,Iris-versicolor +5.8,2.7,3.9,1.2,Iris-versicolor +6.0,2.7,5.1,1.6,Iris-versicolor +5.4,3.0,4.5,1.5,Iris-versicolor +6.0,3.4,4.5,1.6,Iris-versicolor +6.7,3.1,4.7,1.5,Iris-versicolor +6.3,2.3,4.4,1.3,Iris-versicolor +5.6,3.0,4.1,1.3,Iris-versicolor +5.5,2.5,4.0,1.3,Iris-versicolor +5.5,2.6,4.4,1.2,Iris-versicolor +6.1,3.0,4.6,1.4,Iris-versicolor +5.8,2.6,4.0,1.2,Iris-versicolor +5.0,2.3,3.3,1.0,Iris-versicolor +5.6,2.7,4.2,1.3,Iris-versicolor +5.7,3.0,4.2,1.2,Iris-versicolor +5.7,2.9,4.2,1.3,Iris-versicolor +6.2,2.9,4.3,1.3,Iris-versicolor +5.1,2.5,3.0,1.1,Iris-versicolor +5.7,2.8,4.1,1.3,Iris-versicolor +6.3,3.3,6.0,2.5,Iris-virginica +5.8,2.7,5.1,1.9,Iris-virginica +7.1,3.0,5.9,2.1,Iris-virginica +6.3,2.9,5.6,1.8,Iris-virginica +6.5,3.0,5.8,2.2,Iris-virginica +7.6,3.0,6.6,2.1,Iris-virginica +4.9,2.5,4.5,1.7,Iris-virginica +7.3,2.9,6.3,1.8,Iris-virginica +6.7,2.5,5.8,1.8,Iris-virginica +7.2,3.6,6.1,2.5,Iris-virginica +6.5,3.2,5.1,2.0,Iris-virginica +6.4,2.7,5.3,1.9,Iris-virginica +6.8,3.0,5.5,2.1,Iris-virginica +5.7,2.5,5.0,2.0,Iris-virginica +5.8,2.8,5.1,2.4,Iris-virginica +6.4,3.2,5.3,2.3,Iris-virginica +6.5,3.0,5.5,1.8,Iris-virginica +7.7,3.8,6.7,2.2,Iris-virginica +7.7,2.6,6.9,2.3,Iris-virginica +6.0,2.2,5.0,1.5,Iris-virginica +6.9,3.2,5.7,2.3,Iris-virginica +5.6,2.8,4.9,2.0,Iris-virginica +7.7,2.8,6.7,2.0,Iris-virginica +6.3,2.7,4.9,1.8,Iris-virginica +6.7,3.3,5.7,2.1,Iris-virginica +7.2,3.2,6.0,1.8,Iris-virginica +6.2,2.8,4.8,1.8,Iris-virginica +6.1,3.0,4.9,1.8,Iris-virginica +6.4,2.8,5.6,2.1,Iris-virginica +7.2,3.0,5.8,1.6,Iris-virginica +7.4,2.8,6.1,1.9,Iris-virginica +7.9,3.8,6.4,2.0,Iris-virginica +6.4,2.8,5.6,2.2,Iris-virginica +6.3,2.8,5.1,1.5,Iris-virginica +6.1,2.6,5.6,1.4,Iris-virginica +7.7,3.0,6.1,2.3,Iris-virginica +6.3,3.4,5.6,2.4,Iris-virginica +6.4,3.1,5.5,1.8,Iris-virginica +6.0,3.0,4.8,1.8,Iris-virginica +6.9,3.1,5.4,2.1,Iris-virginica +6.7,3.1,5.6,2.4,Iris-virginica +6.9,3.1,5.1,2.3,Iris-virginica +5.8,2.7,5.1,1.9,Iris-virginica +6.8,3.2,5.9,2.3,Iris-virginica +6.7,3.3,5.7,2.5,Iris-virginica +6.7,3.0,5.2,2.3,Iris-virginica +6.3,2.5,5.0,1.9,Iris-virginica +6.5,3.0,5.2,2.0,Iris-virginica +6.2,3.4,5.4,2.3,Iris-virginica +5.9,3.0,5.1,1.8,Iris-virginica +% +% +% diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/missing.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/missing.arff new file mode 100644 index 0000000000000000000000000000000000000000..dedc64c8fa2fcdc0081b30b7804be85114495ce2 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/missing.arff @@ -0,0 +1,8 @@ +% This arff file contains some missing data +@relation missing +@attribute yop real +@attribute yap real +@data +1,5 +2,4 +?,? diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/nodata.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/nodata.arff new file mode 100644 index 0000000000000000000000000000000000000000..5766aeb229a1b31378026274c366e8e9e44fd487 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/nodata.arff @@ -0,0 +1,11 @@ +@RELATION iris + +@ATTRIBUTE sepallength REAL +@ATTRIBUTE sepalwidth REAL +@ATTRIBUTE petallength REAL +@ATTRIBUTE petalwidth REAL +@ATTRIBUTE class {Iris-setosa,Iris-versicolor,Iris-virginica} + +@DATA + +% This file has no data diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/quoted_nominal.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/quoted_nominal.arff new file mode 100644 index 0000000000000000000000000000000000000000..7cd16d1ef9b50cc1194d034ef4d458ef3cf0d417 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/quoted_nominal.arff @@ -0,0 +1,13 @@ +% Regression test for issue #10232 : Exception in loadarff with quoted nominal attributes +% Spaces between elements are stripped by the parser + +@relation SOME_DATA +@attribute age numeric +@attribute smoker {'yes', 'no'} +@data +18, 'no' +24, 'yes' +44, 'no' +56, 'no' +89,'yes' +11, 'no' diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/quoted_nominal_spaces.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/quoted_nominal_spaces.arff new file mode 100644 index 0000000000000000000000000000000000000000..c799127862b6060442b29c9a0382836cc9c55537 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/quoted_nominal_spaces.arff @@ -0,0 +1,13 @@ +% Regression test for issue #10232 : Exception in loadarff with quoted nominal attributes +% Spaces inside quotes are NOT stripped by the parser + +@relation SOME_DATA +@attribute age numeric +@attribute smoker {' yes', 'no '} +@data +18,'no ' +24,' yes' +44,'no ' +56,'no ' +89,' yes' +11,'no ' diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test1.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test1.arff new file mode 100644 index 0000000000000000000000000000000000000000..ccc8e0cc7c43dc66ad7b3a8e4738c3322d3f79d8 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test1.arff @@ -0,0 +1,10 @@ +@RELATION test1 + +@ATTRIBUTE attr0 REAL +@ATTRIBUTE attr1 REAL +@ATTRIBUTE attr2 REAL +@ATTRIBUTE attr3 REAL +@ATTRIBUTE class {class0, class1, class2, class3} + +@DATA +0.1, 0.2, 0.3, 0.4,class1 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test10.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test10.arff new file mode 100644 index 0000000000000000000000000000000000000000..094ac5094a842866666726b358d2c66bf927c9d2 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test10.arff @@ -0,0 +1,8 @@ +@relation test9 + +@attribute attr_relational relational + @attribute attr_number integer +@end attr_relational + +@data +'0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59\n60\n61\n62\n63\n64\n65\n66\n67\n68\n69\n70\n71\n72\n73\n74\n75\n76\n77\n78\n79\n80\n81\n82\n83\n84\n85\n86\n87\n88\n89\n90\n91\n92\n93\n94\n95\n96\n97\n98\n99\n100\n101\n102\n103\n104\n105\n106\n107\n108\n109\n110\n111\n112\n113\n114\n115\n116\n117\n118\n119\n120\n121\n122\n123\n124\n125\n126\n127\n128\n129\n130\n131\n132\n133\n134\n135\n136\n137\n138\n139\n140\n141\n142\n143\n144\n145\n146\n147\n148\n149\n150\n151\n152\n153\n154\n155\n156\n157\n158\n159\n160\n161\n162\n163\n164\n165\n166\n167\n168\n169\n170\n171\n172\n173\n174\n175\n176\n177\n178\n179\n180\n181\n182\n183\n184\n185\n186\n187\n188\n189\n190\n191\n192\n193\n194\n195\n196\n197\n198\n199\n200\n201\n202\n203\n204\n205\n206\n207\n208\n209\n210\n211\n212\n213\n214\n215\n216\n217\n218\n219\n220\n221\n222\n223\n224\n225\n226\n227\n228\n229\n230\n231\n232\n233\n234\n235\n236\n237\n238\n239\n240\n241\n242\n243\n244\n245\n246\n247\n248\n249\n250\n251\n252\n253\n254\n255\n256\n257\n258\n259\n260\n261\n262\n263\n264\n265\n266\n267\n268\n269\n270\n271\n272\n273\n274\n275\n276\n277\n278\n279\n280\n281\n282\n283\n284\n285\n286\n287\n288\n289\n290\n291\n292\n293\n294\n295\n296\n297\n298\n299\n300\n301\n302\n303\n304\n305\n306\n307\n308\n309\n310\n311\n312\n313\n314\n315\n316\n317\n318\n319\n320\n321\n322\n323\n324\n325\n326\n327\n328\n329\n330\n331\n332\n333\n334\n335\n336\n337\n338\n339\n340\n341\n342\n343\n344\n345\n346\n347\n348\n349\n350\n351\n352\n353\n354\n355\n356\n357\n358\n359\n360\n361\n362\n363\n364\n365\n366\n367\n368\n369\n370\n371\n372\n373\n374\n375\n376\n377\n378\n379\n380\n381\n382\n383\n384\n385\n386\n387\n388\n389\n390\n391\n392\n393\n394\n395\n396\n397\n398\n399\n400\n401\n402\n403\n404\n405\n406\n407\n408\n409\n410\n411\n412\n413\n414\n415\n416\n417\n418\n419\n420\n421\n422\n423\n424\n425\n426\n427\n428\n429\n430\n431\n432\n433\n434\n435\n436\n437\n438\n439\n440\n441\n442\n443\n444\n445\n446\n447\n448\n449\n450\n451\n452\n453\n454\n455\n456\n457\n458\n459\n460\n461\n462\n463\n464\n465\n466\n467\n468\n469\n470\n471\n472\n473\n474\n475\n476\n477\n478\n479\n480\n481\n482\n483\n484\n485\n486\n487\n488\n489\n490\n491\n492\n493\n494\n495\n496\n497\n498\n499\n500\n501\n502\n503\n504\n505\n506\n507\n508\n509\n510\n511\n512\n513\n514\n515\n516\n517\n518\n519\n520\n521\n522\n523\n524\n525\n526\n527\n528\n529\n530\n531\n532\n533\n534\n535\n536\n537\n538\n539\n540\n541\n542\n543\n544\n545\n546\n547\n548\n549\n550\n551\n552\n553\n554\n555\n556\n557\n558\n559\n560\n561\n562\n563\n564\n565\n566\n567\n568\n569\n570\n571\n572\n573\n574\n575\n576\n577\n578\n579\n580\n581\n582\n583\n584\n585\n586\n587\n588\n589\n590\n591\n592\n593\n594\n595\n596\n597\n598\n599\n600\n601\n602\n603\n604\n605\n606\n607\n608\n609\n610\n611\n612\n613\n614\n615\n616\n617\n618\n619\n620\n621\n622\n623\n624\n625\n626\n627\n628\n629\n630\n631\n632\n633\n634\n635\n636\n637\n638\n639\n640\n641\n642\n643\n644\n645\n646\n647\n648\n649\n650\n651\n652\n653\n654\n655\n656\n657\n658\n659\n660\n661\n662\n663\n664\n665\n666\n667\n668\n669\n670\n671\n672\n673\n674\n675\n676\n677\n678\n679\n680\n681\n682\n683\n684\n685\n686\n687\n688\n689\n690\n691\n692\n693\n694\n695\n696\n697\n698\n699\n700\n701\n702\n703\n704\n705\n706\n707\n708\n709\n710\n711\n712\n713\n714\n715\n716\n717\n718\n719\n720\n721\n722\n723\n724\n725\n726\n727\n728\n729\n730\n731\n732\n733\n734\n735\n736\n737\n738\n739\n740\n741\n742\n743\n744\n745\n746\n747\n748\n749\n750\n751\n752\n753\n754\n755\n756\n757\n758\n759\n760\n761\n762\n763\n764\n765\n766\n767\n768\n769\n770\n771\n772\n773\n774\n775\n776\n777\n778\n779\n780\n781\n782\n783\n784\n785\n786\n787\n788\n789\n790\n791\n792\n793\n794\n795\n796\n797\n798\n799\n800\n801\n802\n803\n804\n805\n806\n807\n808\n809\n810\n811\n812\n813\n814\n815\n816\n817\n818\n819\n820\n821\n822\n823\n824\n825\n826\n827\n828\n829\n830\n831\n832\n833\n834\n835\n836\n837\n838\n839\n840\n841\n842\n843\n844\n845\n846\n847\n848\n849\n850\n851\n852\n853\n854\n855\n856\n857\n858\n859\n860\n861\n862\n863\n864\n865\n866\n867\n868\n869\n870\n871\n872\n873\n874\n875\n876\n877\n878\n879\n880\n881\n882\n883\n884\n885\n886\n887\n888\n889\n890\n891\n892\n893\n894\n895\n896\n897\n898\n899\n900\n901\n902\n903\n904\n905\n906\n907\n908\n909\n910\n911\n912\n913\n914\n915\n916\n917\n918\n919\n920\n921\n922\n923\n924\n925\n926\n927\n928\n929\n930\n931\n932\n933\n934\n935\n936\n937\n938\n939\n940\n941\n942\n943\n944\n945\n946\n947\n948\n949\n950\n951\n952\n953\n954\n955\n956\n957\n958\n959\n960\n961\n962\n963\n964\n965\n966\n967\n968\n969\n970\n971\n972\n973\n974\n975\n976\n977\n978\n979\n980\n981\n982\n983\n984\n985\n986\n987\n988\n989\n990\n991\n992\n993\n994\n995\n996\n997\n998\n999\n1000\n1001\n1002\n1003\n1004\n1005\n1006\n1007\n1008\n1009\n1010\n1011\n1012\n1013\n1014\n1015\n1016\n1017\n1018\n1019\n1020\n1021\n1022\n1023\n1024\n1025\n1026\n1027\n1028\n1029\n1030\n1031\n1032\n1033\n1034\n1035\n1036\n1037\n1038\n1039\n1040\n1041\n1042\n1043\n1044\n1045\n1046\n1047\n1048\n1049\n1050\n1051\n1052\n1053\n1054\n1055\n1056\n1057\n1058\n1059\n1060\n1061\n1062\n1063\n1064\n1065\n1066\n1067\n1068\n1069\n1070\n1071\n1072\n1073\n1074\n1075\n1076\n1077\n1078\n1079\n1080\n1081\n1082\n1083\n1084\n1085\n1086\n1087\n1088\n1089\n1090\n1091\n1092\n1093\n1094\n1095\n1096\n1097\n1098\n1099\n1100\n1101\n1102\n1103\n1104\n1105\n1106\n1107\n1108\n1109\n1110\n1111\n1112\n1113\n1114\n1115\n1116\n1117\n1118\n1119\n1120\n1121\n1122\n1123\n1124\n1125\n1126\n1127\n1128\n1129\n1130\n1131\n1132\n1133\n1134\n1135\n1136\n1137\n1138\n1139\n1140\n1141\n1142\n1143\n1144\n1145\n1146\n1147\n1148\n1149\n1150\n1151\n1152\n1153\n1154\n1155\n1156\n1157\n1158\n1159\n1160\n1161\n1162\n1163\n1164\n1165\n1166\n1167\n1168\n1169\n1170\n1171\n1172\n1173\n1174\n1175\n1176\n1177\n1178\n1179\n1180\n1181\n1182\n1183\n1184\n1185\n1186\n1187\n1188\n1189\n1190\n1191\n1192\n1193\n1194\n1195\n1196\n1197\n1198\n1199\n1200\n1201\n1202\n1203\n1204\n1205\n1206\n1207\n1208\n1209\n1210\n1211\n1212\n1213\n1214\n1215\n1216\n1217\n1218\n1219\n1220\n1221\n1222\n1223\n1224\n1225\n1226\n1227\n1228\n1229\n1230\n1231\n1232\n1233\n1234\n1235\n1236\n1237\n1238\n1239\n1240\n1241\n1242\n1243\n1244\n1245\n1246\n1247\n1248\n1249\n1250\n1251\n1252\n1253\n1254\n1255\n1256\n1257\n1258\n1259\n1260\n1261\n1262\n1263\n1264\n1265\n1266\n1267\n1268\n1269\n1270\n1271\n1272\n1273\n1274\n1275\n1276\n1277\n1278\n1279\n1280\n1281\n1282\n1283\n1284\n1285\n1286\n1287\n1288\n1289\n1290\n1291\n1292\n1293\n1294\n1295\n1296\n1297\n1298\n1299\n1300\n1301\n1302\n1303\n1304\n1305\n1306\n1307\n1308\n1309\n1310\n1311\n1312\n1313\n1314\n1315\n1316\n1317\n1318\n1319\n1320\n1321\n1322\n1323\n1324\n1325\n1326\n1327\n1328\n1329\n1330\n1331\n1332\n1333\n1334\n1335\n1336\n1337\n1338\n1339\n1340\n1341\n1342\n1343\n1344\n1345\n1346\n1347\n1348\n1349\n1350\n1351\n1352\n1353\n1354\n1355\n1356\n1357\n1358\n1359\n1360\n1361\n1362\n1363\n1364\n1365\n1366\n1367\n1368\n1369\n1370\n1371\n1372\n1373\n1374\n1375\n1376\n1377\n1378\n1379\n1380\n1381\n1382\n1383\n1384\n1385\n1386\n1387\n1388\n1389\n1390\n1391\n1392\n1393\n1394\n1395\n1396\n1397\n1398\n1399\n1400\n1401\n1402\n1403\n1404\n1405\n1406\n1407\n1408\n1409\n1410\n1411\n1412\n1413\n1414\n1415\n1416\n1417\n1418\n1419\n1420\n1421\n1422\n1423\n1424\n1425\n1426\n1427\n1428\n1429\n1430\n1431\n1432\n1433\n1434\n1435\n1436\n1437\n1438\n1439\n1440\n1441\n1442\n1443\n1444\n1445\n1446\n1447\n1448\n1449\n1450\n1451\n1452\n1453\n1454\n1455\n1456\n1457\n1458\n1459\n1460\n1461\n1462\n1463\n1464\n1465\n1466\n1467\n1468\n1469\n1470\n1471\n1472\n1473\n1474\n1475\n1476\n1477\n1478\n1479\n1480\n1481\n1482\n1483\n1484\n1485\n1486\n1487\n1488\n1489\n1490\n1491\n1492\n1493\n1494\n1495\n1496\n1497\n1498\n1499\n1500\n1501\n1502\n1503\n1504\n1505\n1506\n1507\n1508\n1509\n1510\n1511\n1512\n1513\n1514\n1515\n1516\n1517\n1518\n1519\n1520\n1521\n1522\n1523\n1524\n1525\n1526\n1527\n1528\n1529\n1530\n1531\n1532\n1533\n1534\n1535\n1536\n1537\n1538\n1539\n1540\n1541\n1542\n1543\n1544\n1545\n1546\n1547\n1548\n1549\n1550\n1551\n1552\n1553\n1554\n1555\n1556\n1557\n1558\n1559\n1560\n1561\n1562\n1563\n1564\n1565\n1566\n1567\n1568\n1569\n1570\n1571\n1572\n1573\n1574\n1575\n1576\n1577\n1578\n1579\n1580\n1581\n1582\n1583\n1584\n1585\n1586\n1587\n1588\n1589\n1590\n1591\n1592\n1593\n1594\n1595\n1596\n1597\n1598\n1599\n1600\n1601\n1602\n1603\n1604\n1605\n1606\n1607\n1608\n1609\n1610\n1611\n1612\n1613\n1614\n1615\n1616\n1617\n1618\n1619\n1620\n1621\n1622\n1623\n1624\n1625\n1626\n1627\n1628\n1629\n1630\n1631\n1632\n1633\n1634\n1635\n1636\n1637\n1638\n1639\n1640\n1641\n1642\n1643\n1644\n1645\n1646\n1647\n1648\n1649\n1650\n1651\n1652\n1653\n1654\n1655\n1656\n1657\n1658\n1659\n1660\n1661\n1662\n1663\n1664\n1665\n1666\n1667\n1668\n1669\n1670\n1671\n1672\n1673\n1674\n1675\n1676\n1677\n1678\n1679\n1680\n1681\n1682\n1683\n1684\n1685\n1686\n1687\n1688\n1689\n1690\n1691\n1692\n1693\n1694\n1695\n1696\n1697\n1698\n1699\n1700\n1701\n1702\n1703\n1704\n1705\n1706\n1707\n1708\n1709\n1710\n1711\n1712\n1713\n1714\n1715\n1716\n1717\n1718\n1719\n1720\n1721\n1722\n1723\n1724\n1725\n1726\n1727\n1728\n1729\n1730\n1731\n1732\n1733\n1734\n1735\n1736\n1737\n1738\n1739\n1740\n1741\n1742\n1743\n1744\n1745\n1746\n1747\n1748\n1749\n1750\n1751\n1752\n1753\n1754\n1755\n1756\n1757\n1758\n1759\n1760\n1761\n1762\n1763\n1764\n1765\n1766\n1767\n1768\n1769\n1770\n1771\n1772\n1773\n1774\n1775\n1776\n1777\n1778\n1779\n1780\n1781\n1782\n1783\n1784\n1785\n1786\n1787\n1788\n1789\n1790\n1791\n1792\n1793\n1794\n1795\n1796\n1797\n1798\n1799\n1800\n1801\n1802\n1803\n1804\n1805\n1806\n1807\n1808\n1809\n1810\n1811\n1812\n1813\n1814\n1815\n1816\n1817\n1818\n1819\n1820\n1821\n1822\n1823\n1824\n1825\n1826\n1827\n1828\n1829\n1830\n1831\n1832\n1833\n1834\n1835\n1836\n1837\n1838\n1839\n1840\n1841\n1842\n1843\n1844\n1845\n1846\n1847\n1848\n1849\n1850\n1851\n1852\n1853\n1854\n1855\n1856\n1857\n1858\n1859\n1860\n1861\n1862\n1863\n1864\n1865\n1866\n1867\n1868\n1869\n1870\n1871\n1872\n1873\n1874\n1875\n1876\n1877\n1878\n1879\n1880\n1881\n1882\n1883\n1884\n1885\n1886\n1887\n1888\n1889\n1890\n1891\n1892\n1893\n1894\n1895\n1896\n1897\n1898\n1899\n1900\n1901\n1902\n1903\n1904\n1905\n1906\n1907\n1908\n1909\n1910\n1911\n1912\n1913\n1914\n1915\n1916\n1917\n1918\n1919\n1920\n1921\n1922\n1923\n1924\n1925\n1926\n1927\n1928\n1929\n1930\n1931\n1932\n1933\n1934\n1935\n1936\n1937\n1938\n1939\n1940\n1941\n1942\n1943\n1944\n1945\n1946\n1947\n1948\n1949\n1950\n1951\n1952\n1953\n1954\n1955\n1956\n1957\n1958\n1959\n1960\n1961\n1962\n1963\n1964\n1965\n1966\n1967\n1968\n1969\n1970\n1971\n1972\n1973\n1974\n1975\n1976\n1977\n1978\n1979\n1980\n1981\n1982\n1983\n1984\n1985\n1986\n1987\n1988\n1989\n1990\n1991\n1992\n1993\n1994\n1995\n1996\n1997\n1998\n1999\n2000\n2001\n2002\n2003\n2004\n2005\n2006\n2007\n2008\n2009\n2010\n2011\n2012\n2013\n2014\n2015\n2016\n2017\n2018\n2019\n2020\n2021\n2022\n2023\n2024\n2025\n2026\n2027\n2028\n2029\n2030\n2031\n2032\n2033\n2034\n2035\n2036\n2037\n2038\n2039\n2040\n2041\n2042\n2043\n2044\n2045\n2046\n2047\n2048\n2049\n2050\n2051\n2052\n2053\n2054\n2055\n2056\n2057\n2058\n2059\n2060\n2061\n2062\n2063\n2064\n2065\n2066\n2067\n2068\n2069\n2070\n2071\n2072\n2073\n2074\n2075\n2076\n2077\n2078\n2079\n2080\n2081\n2082\n2083\n2084\n2085\n2086\n2087\n2088\n2089\n2090\n2091\n2092\n2093\n2094\n2095\n2096\n2097\n2098\n2099\n2100\n2101\n2102\n2103\n2104\n2105\n2106\n2107\n2108\n2109\n2110\n2111\n2112\n2113\n2114\n2115\n2116\n2117\n2118\n2119\n2120\n2121\n2122\n2123\n2124\n2125\n2126\n2127\n2128\n2129\n2130\n2131\n2132\n2133\n2134\n2135\n2136\n2137\n2138\n2139\n2140\n2141\n2142\n2143\n2144\n2145\n2146\n2147\n2148\n2149\n2150\n2151\n2152\n2153\n2154\n2155\n2156\n2157\n2158\n2159\n2160\n2161\n2162\n2163\n2164\n2165\n2166\n2167\n2168\n2169\n2170\n2171\n2172\n2173\n2174\n2175\n2176\n2177\n2178\n2179\n2180\n2181\n2182\n2183\n2184\n2185\n2186\n2187\n2188\n2189\n2190\n2191\n2192\n2193\n2194\n2195\n2196\n2197\n2198\n2199\n2200\n2201\n2202\n2203\n2204\n2205\n2206\n2207\n2208\n2209\n2210\n2211\n2212\n2213\n2214\n2215\n2216\n2217\n2218\n2219\n2220\n2221\n2222\n2223\n2224\n2225\n2226\n2227\n2228\n2229\n2230\n2231\n2232\n2233\n2234\n2235\n2236\n2237\n2238\n2239\n2240\n2241\n2242\n2243\n2244\n2245\n2246\n2247\n2248\n2249\n2250\n2251\n2252\n2253\n2254\n2255\n2256\n2257\n2258\n2259\n2260\n2261\n2262\n2263\n2264\n2265\n2266\n2267\n2268\n2269\n2270\n2271\n2272\n2273\n2274\n2275\n2276\n2277\n2278\n2279\n2280\n2281\n2282\n2283\n2284\n2285\n2286\n2287\n2288\n2289\n2290\n2291\n2292\n2293\n2294\n2295\n2296\n2297\n2298\n2299\n2300\n2301\n2302\n2303\n2304\n2305\n2306\n2307\n2308\n2309\n2310\n2311\n2312\n2313\n2314\n2315\n2316\n2317\n2318\n2319\n2320\n2321\n2322\n2323\n2324\n2325\n2326\n2327\n2328\n2329\n2330\n2331\n2332\n2333\n2334\n2335\n2336\n2337\n2338\n2339\n2340\n2341\n2342\n2343\n2344\n2345\n2346\n2347\n2348\n2349\n2350\n2351\n2352\n2353\n2354\n2355\n2356\n2357\n2358\n2359\n2360\n2361\n2362\n2363\n2364\n2365\n2366\n2367\n2368\n2369\n2370\n2371\n2372\n2373\n2374\n2375\n2376\n2377\n2378\n2379\n2380\n2381\n2382\n2383\n2384\n2385\n2386\n2387\n2388\n2389\n2390\n2391\n2392\n2393\n2394\n2395\n2396\n2397\n2398\n2399\n2400\n2401\n2402\n2403\n2404\n2405\n2406\n2407\n2408\n2409\n2410\n2411\n2412\n2413\n2414\n2415\n2416\n2417\n2418\n2419\n2420\n2421\n2422\n2423\n2424\n2425\n2426\n2427\n2428\n2429\n2430\n2431\n2432\n2433\n2434\n2435\n2436\n2437\n2438\n2439\n2440\n2441\n2442\n2443\n2444\n2445\n2446\n2447\n2448\n2449\n2450\n2451\n2452\n2453\n2454\n2455\n2456\n2457\n2458\n2459\n2460\n2461\n2462\n2463\n2464\n2465\n2466\n2467\n2468\n2469\n2470\n2471\n2472\n2473\n2474\n2475\n2476\n2477\n2478\n2479\n2480\n2481\n2482\n2483\n2484\n2485\n2486\n2487\n2488\n2489\n2490\n2491\n2492\n2493\n2494\n2495\n2496\n2497\n2498\n2499\n2500\n2501\n2502\n2503\n2504\n2505\n2506\n2507\n2508\n2509\n2510\n2511\n2512\n2513\n2514\n2515\n2516\n2517\n2518\n2519\n2520\n2521\n2522\n2523\n2524\n2525\n2526\n2527\n2528\n2529\n2530\n2531\n2532\n2533\n2534\n2535\n2536\n2537\n2538\n2539\n2540\n2541\n2542\n2543\n2544\n2545\n2546\n2547\n2548\n2549\n2550\n2551\n2552\n2553\n2554\n2555\n2556\n2557\n2558\n2559\n2560\n2561\n2562\n2563\n2564\n2565\n2566\n2567\n2568\n2569\n2570\n2571\n2572\n2573\n2574\n2575\n2576\n2577\n2578\n2579\n2580\n2581\n2582\n2583\n2584\n2585\n2586\n2587\n2588\n2589\n2590\n2591\n2592\n2593\n2594\n2595\n2596\n2597\n2598\n2599\n2600\n2601\n2602\n2603\n2604\n2605\n2606\n2607\n2608\n2609\n2610\n2611\n2612\n2613\n2614\n2615\n2616\n2617\n2618\n2619\n2620\n2621\n2622\n2623\n2624\n2625\n2626\n2627\n2628\n2629\n2630\n2631\n2632\n2633\n2634\n2635\n2636\n2637\n2638\n2639\n2640\n2641\n2642\n2643\n2644\n2645\n2646\n2647\n2648\n2649\n2650\n2651\n2652\n2653\n2654\n2655\n2656\n2657\n2658\n2659\n2660\n2661\n2662\n2663\n2664\n2665\n2666\n2667\n2668\n2669\n2670\n2671\n2672\n2673\n2674\n2675\n2676\n2677\n2678\n2679\n2680\n2681\n2682\n2683\n2684\n2685\n2686\n2687\n2688\n2689\n2690\n2691\n2692\n2693\n2694\n2695\n2696\n2697\n2698\n2699\n2700\n2701\n2702\n2703\n2704\n2705\n2706\n2707\n2708\n2709\n2710\n2711\n2712\n2713\n2714\n2715\n2716\n2717\n2718\n2719\n2720\n2721\n2722\n2723\n2724\n2725\n2726\n2727\n2728\n2729\n2730\n2731\n2732\n2733\n2734\n2735\n2736\n2737\n2738\n2739\n2740\n2741\n2742\n2743\n2744\n2745\n2746\n2747\n2748\n2749\n2750\n2751\n2752\n2753\n2754\n2755\n2756\n2757\n2758\n2759\n2760\n2761\n2762\n2763\n2764\n2765\n2766\n2767\n2768\n2769\n2770\n2771\n2772\n2773\n2774\n2775\n2776\n2777\n2778\n2779\n2780\n2781\n2782\n2783\n2784\n2785\n2786\n2787\n2788\n2789\n2790\n2791\n2792\n2793\n2794\n2795\n2796\n2797\n2798\n2799\n2800\n2801\n2802\n2803\n2804\n2805\n2806\n2807\n2808\n2809\n2810\n2811\n2812\n2813\n2814\n2815\n2816\n2817\n2818\n2819\n2820\n2821\n2822\n2823\n2824\n2825\n2826\n2827\n2828\n2829\n2830\n2831\n2832\n2833\n2834\n2835\n2836\n2837\n2838\n2839\n2840\n2841\n2842\n2843\n2844\n2845\n2846\n2847\n2848\n2849\n2850\n2851\n2852\n2853\n2854\n2855\n2856\n2857\n2858\n2859\n2860\n2861\n2862\n2863\n2864\n2865\n2866\n2867\n2868\n2869\n2870\n2871\n2872\n2873\n2874\n2875\n2876\n2877\n2878\n2879\n2880\n2881\n2882\n2883\n2884\n2885\n2886\n2887\n2888\n2889\n2890\n2891\n2892\n2893\n2894\n2895\n2896\n2897\n2898\n2899\n2900\n2901\n2902\n2903\n2904\n2905\n2906\n2907\n2908\n2909\n2910\n2911\n2912\n2913\n2914\n2915\n2916\n2917\n2918\n2919\n2920\n2921\n2922\n2923\n2924\n2925\n2926\n2927\n2928\n2929\n2930\n2931\n2932\n2933\n2934\n2935\n2936\n2937\n2938\n2939\n2940\n2941\n2942\n2943\n2944\n2945\n2946\n2947\n2948\n2949\n2950\n2951\n2952\n2953\n2954\n2955\n2956\n2957\n2958\n2959\n2960\n2961\n2962\n2963\n2964\n2965\n2966\n2967\n2968\n2969\n2970\n2971\n2972\n2973\n2974\n2975\n2976\n2977\n2978\n2979\n2980\n2981\n2982\n2983\n2984\n2985\n2986\n2987\n2988\n2989\n2990\n2991\n2992\n2993\n2994\n2995\n2996\n2997\n2998\n2999\n3000\n3001\n3002\n3003\n3004\n3005\n3006\n3007\n3008\n3009\n3010\n3011\n3012\n3013\n3014\n3015\n3016\n3017\n3018\n3019\n3020\n3021\n3022\n3023\n3024\n3025\n3026\n3027\n3028\n3029\n3030\n3031\n3032\n3033\n3034\n3035\n3036\n3037\n3038\n3039\n3040\n3041\n3042\n3043\n3044\n3045\n3046\n3047\n3048\n3049\n3050\n3051\n3052\n3053\n3054\n3055\n3056\n3057\n3058\n3059\n3060\n3061\n3062\n3063\n3064\n3065\n3066\n3067\n3068\n3069\n3070\n3071\n3072\n3073\n3074\n3075\n3076\n3077\n3078\n3079\n3080\n3081\n3082\n3083\n3084\n3085\n3086\n3087\n3088\n3089\n3090\n3091\n3092\n3093\n3094\n3095\n3096\n3097\n3098\n3099\n3100\n3101\n3102\n3103\n3104\n3105\n3106\n3107\n3108\n3109\n3110\n3111\n3112\n3113\n3114\n3115\n3116\n3117\n3118\n3119\n3120\n3121\n3122\n3123\n3124\n3125\n3126\n3127\n3128\n3129\n3130\n3131\n3132\n3133\n3134\n3135\n3136\n3137\n3138\n3139\n3140\n3141\n3142\n3143\n3144\n3145\n3146\n3147\n3148\n3149\n3150\n3151\n3152\n3153\n3154\n3155\n3156\n3157\n3158\n3159\n3160\n3161\n3162\n3163\n3164\n3165\n3166\n3167\n3168\n3169\n3170\n3171\n3172\n3173\n3174\n3175\n3176\n3177\n3178\n3179\n3180\n3181\n3182\n3183\n3184\n3185\n3186\n3187\n3188\n3189\n3190\n3191\n3192\n3193\n3194\n3195\n3196\n3197\n3198\n3199\n3200\n3201\n3202\n3203\n3204\n3205\n3206\n3207\n3208\n3209\n3210\n3211\n3212\n3213\n3214\n3215\n3216\n3217\n3218\n3219\n3220\n3221\n3222\n3223\n3224\n3225\n3226\n3227\n3228\n3229\n3230\n3231\n3232\n3233\n3234\n3235\n3236\n3237\n3238\n3239\n3240\n3241\n3242\n3243\n3244\n3245\n3246\n3247\n3248\n3249\n3250\n3251\n3252\n3253\n3254\n3255\n3256\n3257\n3258\n3259\n3260\n3261\n3262\n3263\n3264\n3265\n3266\n3267\n3268\n3269\n3270\n3271\n3272\n3273\n3274\n3275\n3276\n3277\n3278\n3279\n3280\n3281\n3282\n3283\n3284\n3285\n3286\n3287\n3288\n3289\n3290\n3291\n3292\n3293\n3294\n3295\n3296\n3297\n3298\n3299\n3300\n3301\n3302\n3303\n3304\n3305\n3306\n3307\n3308\n3309\n3310\n3311\n3312\n3313\n3314\n3315\n3316\n3317\n3318\n3319\n3320\n3321\n3322\n3323\n3324\n3325\n3326\n3327\n3328\n3329\n3330\n3331\n3332\n3333\n3334\n3335\n3336\n3337\n3338\n3339\n3340\n3341\n3342\n3343\n3344\n3345\n3346\n3347\n3348\n3349\n3350\n3351\n3352\n3353\n3354\n3355\n3356\n3357\n3358\n3359\n3360\n3361\n3362\n3363\n3364\n3365\n3366\n3367\n3368\n3369\n3370\n3371\n3372\n3373\n3374\n3375\n3376\n3377\n3378\n3379\n3380\n3381\n3382\n3383\n3384\n3385\n3386\n3387\n3388\n3389\n3390\n3391\n3392\n3393\n3394\n3395\n3396\n3397\n3398\n3399\n3400\n3401\n3402\n3403\n3404\n3405\n3406\n3407\n3408\n3409\n3410\n3411\n3412\n3413\n3414\n3415\n3416\n3417\n3418\n3419\n3420\n3421\n3422\n3423\n3424\n3425\n3426\n3427\n3428\n3429\n3430\n3431\n3432\n3433\n3434\n3435\n3436\n3437\n3438\n3439\n3440\n3441\n3442\n3443\n3444\n3445\n3446\n3447\n3448\n3449\n3450\n3451\n3452\n3453\n3454\n3455\n3456\n3457\n3458\n3459\n3460\n3461\n3462\n3463\n3464\n3465\n3466\n3467\n3468\n3469\n3470\n3471\n3472\n3473\n3474\n3475\n3476\n3477\n3478\n3479\n3480\n3481\n3482\n3483\n3484\n3485\n3486\n3487\n3488\n3489\n3490\n3491\n3492\n3493\n3494\n3495\n3496\n3497\n3498\n3499\n3500\n3501\n3502\n3503\n3504\n3505\n3506\n3507\n3508\n3509\n3510\n3511\n3512\n3513\n3514\n3515\n3516\n3517\n3518\n3519\n3520\n3521\n3522\n3523\n3524\n3525\n3526\n3527\n3528\n3529\n3530\n3531\n3532\n3533\n3534\n3535\n3536\n3537\n3538\n3539\n3540\n3541\n3542\n3543\n3544\n3545\n3546\n3547\n3548\n3549\n3550\n3551\n3552\n3553\n3554\n3555\n3556\n3557\n3558\n3559\n3560\n3561\n3562\n3563\n3564\n3565\n3566\n3567\n3568\n3569\n3570\n3571\n3572\n3573\n3574\n3575\n3576\n3577\n3578\n3579\n3580\n3581\n3582\n3583\n3584\n3585\n3586\n3587\n3588\n3589\n3590\n3591\n3592\n3593\n3594\n3595\n3596\n3597\n3598\n3599\n3600\n3601\n3602\n3603\n3604\n3605\n3606\n3607\n3608\n3609\n3610\n3611\n3612\n3613\n3614\n3615\n3616\n3617\n3618\n3619\n3620\n3621\n3622\n3623\n3624\n3625\n3626\n3627\n3628\n3629\n3630\n3631\n3632\n3633\n3634\n3635\n3636\n3637\n3638\n3639\n3640\n3641\n3642\n3643\n3644\n3645\n3646\n3647\n3648\n3649\n3650\n3651\n3652\n3653\n3654\n3655\n3656\n3657\n3658\n3659\n3660\n3661\n3662\n3663\n3664\n3665\n3666\n3667\n3668\n3669\n3670\n3671\n3672\n3673\n3674\n3675\n3676\n3677\n3678\n3679\n3680\n3681\n3682\n3683\n3684\n3685\n3686\n3687\n3688\n3689\n3690\n3691\n3692\n3693\n3694\n3695\n3696\n3697\n3698\n3699\n3700\n3701\n3702\n3703\n3704\n3705\n3706\n3707\n3708\n3709\n3710\n3711\n3712\n3713\n3714\n3715\n3716\n3717\n3718\n3719\n3720\n3721\n3722\n3723\n3724\n3725\n3726\n3727\n3728\n3729\n3730\n3731\n3732\n3733\n3734\n3735\n3736\n3737\n3738\n3739\n3740\n3741\n3742\n3743\n3744\n3745\n3746\n3747\n3748\n3749\n3750\n3751\n3752\n3753\n3754\n3755\n3756\n3757\n3758\n3759\n3760\n3761\n3762\n3763\n3764\n3765\n3766\n3767\n3768\n3769\n3770\n3771\n3772\n3773\n3774\n3775\n3776\n3777\n3778\n3779\n3780\n3781\n3782\n3783\n3784\n3785\n3786\n3787\n3788\n3789\n3790\n3791\n3792\n3793\n3794\n3795\n3796\n3797\n3798\n3799\n3800\n3801\n3802\n3803\n3804\n3805\n3806\n3807\n3808\n3809\n3810\n3811\n3812\n3813\n3814\n3815\n3816\n3817\n3818\n3819\n3820\n3821\n3822\n3823\n3824\n3825\n3826\n3827\n3828\n3829\n3830\n3831\n3832\n3833\n3834\n3835\n3836\n3837\n3838\n3839\n3840\n3841\n3842\n3843\n3844\n3845\n3846\n3847\n3848\n3849\n3850\n3851\n3852\n3853\n3854\n3855\n3856\n3857\n3858\n3859\n3860\n3861\n3862\n3863\n3864\n3865\n3866\n3867\n3868\n3869\n3870\n3871\n3872\n3873\n3874\n3875\n3876\n3877\n3878\n3879\n3880\n3881\n3882\n3883\n3884\n3885\n3886\n3887\n3888\n3889\n3890\n3891\n3892\n3893\n3894\n3895\n3896\n3897\n3898\n3899\n3900\n3901\n3902\n3903\n3904\n3905\n3906\n3907\n3908\n3909\n3910\n3911\n3912\n3913\n3914\n3915\n3916\n3917\n3918\n3919\n3920\n3921\n3922\n3923\n3924\n3925\n3926\n3927\n3928\n3929\n3930\n3931\n3932\n3933\n3934\n3935\n3936\n3937\n3938\n3939\n3940\n3941\n3942\n3943\n3944\n3945\n3946\n3947\n3948\n3949\n3950\n3951\n3952\n3953\n3954\n3955\n3956\n3957\n3958\n3959\n3960\n3961\n3962\n3963\n3964\n3965\n3966\n3967\n3968\n3969\n3970\n3971\n3972\n3973\n3974\n3975\n3976\n3977\n3978\n3979\n3980\n3981\n3982\n3983\n3984\n3985\n3986\n3987\n3988\n3989\n3990\n3991\n3992\n3993\n3994\n3995\n3996\n3997\n3998\n3999\n4000\n4001\n4002\n4003\n4004\n4005\n4006\n4007\n4008\n4009\n4010\n4011\n4012\n4013\n4014\n4015\n4016\n4017\n4018\n4019\n4020\n4021\n4022\n4023\n4024\n4025\n4026\n4027\n4028\n4029\n4030\n4031\n4032\n4033\n4034\n4035\n4036\n4037\n4038\n4039\n4040\n4041\n4042\n4043\n4044\n4045\n4046\n4047\n4048\n4049\n4050\n4051\n4052\n4053\n4054\n4055\n4056\n4057\n4058\n4059\n4060\n4061\n4062\n4063\n4064\n4065\n4066\n4067\n4068\n4069\n4070\n4071\n4072\n4073\n4074\n4075\n4076\n4077\n4078\n4079\n4080\n4081\n4082\n4083\n4084\n4085\n4086\n4087\n4088\n4089\n4090\n4091\n4092\n4093\n4094\n4095\n4096\n4097\n4098\n4099\n4100\n4101\n4102\n4103\n4104\n4105\n4106\n4107\n4108\n4109\n4110\n4111\n4112\n4113\n4114\n4115\n4116\n4117\n4118\n4119\n4120\n4121\n4122\n4123\n4124\n4125\n4126\n4127\n4128\n4129\n4130\n4131\n4132\n4133\n4134\n4135\n4136\n4137\n4138\n4139\n4140\n4141\n4142\n4143\n4144\n4145\n4146\n4147\n4148\n4149\n4150\n4151\n4152\n4153\n4154\n4155\n4156\n4157\n4158\n4159\n4160\n4161\n4162\n4163\n4164\n4165\n4166\n4167\n4168\n4169\n4170\n4171\n4172\n4173\n4174\n4175\n4176\n4177\n4178\n4179\n4180\n4181\n4182\n4183\n4184\n4185\n4186\n4187\n4188\n4189\n4190\n4191\n4192\n4193\n4194\n4195\n4196\n4197\n4198\n4199\n4200\n4201\n4202\n4203\n4204\n4205\n4206\n4207\n4208\n4209\n4210\n4211\n4212\n4213\n4214\n4215\n4216\n4217\n4218\n4219\n4220\n4221\n4222\n4223\n4224\n4225\n4226\n4227\n4228\n4229\n4230\n4231\n4232\n4233\n4234\n4235\n4236\n4237\n4238\n4239\n4240\n4241\n4242\n4243\n4244\n4245\n4246\n4247\n4248\n4249\n4250\n4251\n4252\n4253\n4254\n4255\n4256\n4257\n4258\n4259\n4260\n4261\n4262\n4263\n4264\n4265\n4266\n4267\n4268\n4269\n4270\n4271\n4272\n4273\n4274\n4275\n4276\n4277\n4278\n4279\n4280\n4281\n4282\n4283\n4284\n4285\n4286\n4287\n4288\n4289\n4290\n4291\n4292\n4293\n4294\n4295\n4296\n4297\n4298\n4299\n4300\n4301\n4302\n4303\n4304\n4305\n4306\n4307\n4308\n4309\n4310\n4311\n4312\n4313\n4314\n4315\n4316\n4317\n4318\n4319\n4320\n4321\n4322\n4323\n4324\n4325\n4326\n4327\n4328\n4329\n4330\n4331\n4332\n4333\n4334\n4335\n4336\n4337\n4338\n4339\n4340\n4341\n4342\n4343\n4344\n4345\n4346\n4347\n4348\n4349\n4350\n4351\n4352\n4353\n4354\n4355\n4356\n4357\n4358\n4359\n4360\n4361\n4362\n4363\n4364\n4365\n4366\n4367\n4368\n4369\n4370\n4371\n4372\n4373\n4374\n4375\n4376\n4377\n4378\n4379\n4380\n4381\n4382\n4383\n4384\n4385\n4386\n4387\n4388\n4389\n4390\n4391\n4392\n4393\n4394\n4395\n4396\n4397\n4398\n4399\n4400\n4401\n4402\n4403\n4404\n4405\n4406\n4407\n4408\n4409\n4410\n4411\n4412\n4413\n4414\n4415\n4416\n4417\n4418\n4419\n4420\n4421\n4422\n4423\n4424\n4425\n4426\n4427\n4428\n4429\n4430\n4431\n4432\n4433\n4434\n4435\n4436\n4437\n4438\n4439\n4440\n4441\n4442\n4443\n4444\n4445\n4446\n4447\n4448\n4449\n4450\n4451\n4452\n4453\n4454\n4455\n4456\n4457\n4458\n4459\n4460\n4461\n4462\n4463\n4464\n4465\n4466\n4467\n4468\n4469\n4470\n4471\n4472\n4473\n4474\n4475\n4476\n4477\n4478\n4479\n4480\n4481\n4482\n4483\n4484\n4485\n4486\n4487\n4488\n4489\n4490\n4491\n4492\n4493\n4494\n4495\n4496\n4497\n4498\n4499\n4500\n4501\n4502\n4503\n4504\n4505\n4506\n4507\n4508\n4509\n4510\n4511\n4512\n4513\n4514\n4515\n4516\n4517\n4518\n4519\n4520\n4521\n4522\n4523\n4524\n4525\n4526\n4527\n4528\n4529\n4530\n4531\n4532\n4533\n4534\n4535\n4536\n4537\n4538\n4539\n4540\n4541\n4542\n4543\n4544\n4545\n4546\n4547\n4548\n4549\n4550\n4551\n4552\n4553\n4554\n4555\n4556\n4557\n4558\n4559\n4560\n4561\n4562\n4563\n4564\n4565\n4566\n4567\n4568\n4569\n4570\n4571\n4572\n4573\n4574\n4575\n4576\n4577\n4578\n4579\n4580\n4581\n4582\n4583\n4584\n4585\n4586\n4587\n4588\n4589\n4590\n4591\n4592\n4593\n4594\n4595\n4596\n4597\n4598\n4599\n4600\n4601\n4602\n4603\n4604\n4605\n4606\n4607\n4608\n4609\n4610\n4611\n4612\n4613\n4614\n4615\n4616\n4617\n4618\n4619\n4620\n4621\n4622\n4623\n4624\n4625\n4626\n4627\n4628\n4629\n4630\n4631\n4632\n4633\n4634\n4635\n4636\n4637\n4638\n4639\n4640\n4641\n4642\n4643\n4644\n4645\n4646\n4647\n4648\n4649\n4650\n4651\n4652\n4653\n4654\n4655\n4656\n4657\n4658\n4659\n4660\n4661\n4662\n4663\n4664\n4665\n4666\n4667\n4668\n4669\n4670\n4671\n4672\n4673\n4674\n4675\n4676\n4677\n4678\n4679\n4680\n4681\n4682\n4683\n4684\n4685\n4686\n4687\n4688\n4689\n4690\n4691\n4692\n4693\n4694\n4695\n4696\n4697\n4698\n4699\n4700\n4701\n4702\n4703\n4704\n4705\n4706\n4707\n4708\n4709\n4710\n4711\n4712\n4713\n4714\n4715\n4716\n4717\n4718\n4719\n4720\n4721\n4722\n4723\n4724\n4725\n4726\n4727\n4728\n4729\n4730\n4731\n4732\n4733\n4734\n4735\n4736\n4737\n4738\n4739\n4740\n4741\n4742\n4743\n4744\n4745\n4746\n4747\n4748\n4749\n4750\n4751\n4752\n4753\n4754\n4755\n4756\n4757\n4758\n4759\n4760\n4761\n4762\n4763\n4764\n4765\n4766\n4767\n4768\n4769\n4770\n4771\n4772\n4773\n4774\n4775\n4776\n4777\n4778\n4779\n4780\n4781\n4782\n4783\n4784\n4785\n4786\n4787\n4788\n4789\n4790\n4791\n4792\n4793\n4794\n4795\n4796\n4797\n4798\n4799\n4800\n4801\n4802\n4803\n4804\n4805\n4806\n4807\n4808\n4809\n4810\n4811\n4812\n4813\n4814\n4815\n4816\n4817\n4818\n4819\n4820\n4821\n4822\n4823\n4824\n4825\n4826\n4827\n4828\n4829\n4830\n4831\n4832\n4833\n4834\n4835\n4836\n4837\n4838\n4839\n4840\n4841\n4842\n4843\n4844\n4845\n4846\n4847\n4848\n4849\n4850\n4851\n4852\n4853\n4854\n4855\n4856\n4857\n4858\n4859\n4860\n4861\n4862\n4863\n4864\n4865\n4866\n4867\n4868\n4869\n4870\n4871\n4872\n4873\n4874\n4875\n4876\n4877\n4878\n4879\n4880\n4881\n4882\n4883\n4884\n4885\n4886\n4887\n4888\n4889\n4890\n4891\n4892\n4893\n4894\n4895\n4896\n4897\n4898\n4899\n4900\n4901\n4902\n4903\n4904\n4905\n4906\n4907\n4908\n4909\n4910\n4911\n4912\n4913\n4914\n4915\n4916\n4917\n4918\n4919\n4920\n4921\n4922\n4923\n4924\n4925\n4926\n4927\n4928\n4929\n4930\n4931\n4932\n4933\n4934\n4935\n4936\n4937\n4938\n4939\n4940\n4941\n4942\n4943\n4944\n4945\n4946\n4947\n4948\n4949\n4950\n4951\n4952\n4953\n4954\n4955\n4956\n4957\n4958\n4959\n4960\n4961\n4962\n4963\n4964\n4965\n4966\n4967\n4968\n4969\n4970\n4971\n4972\n4973\n4974\n4975\n4976\n4977\n4978\n4979\n4980\n4981\n4982\n4983\n4984\n4985\n4986\n4987\n4988\n4989\n4990\n4991\n4992\n4993\n4994\n4995\n4996\n4997\n4998\n4999\n5000\n5001\n5002\n5003\n5004\n5005\n5006\n5007\n5008\n5009\n5010\n5011\n5012\n5013\n5014\n5015\n5016\n5017\n5018\n5019\n5020\n5021\n5022\n5023\n5024\n5025\n5026\n5027\n5028\n5029\n5030\n5031\n5032\n5033\n5034\n5035\n5036\n5037\n5038\n5039\n5040\n5041\n5042\n5043\n5044\n5045\n5046\n5047\n5048\n5049\n5050\n5051\n5052\n5053\n5054\n5055\n5056\n5057\n5058\n5059\n5060\n5061\n5062\n5063\n5064\n5065\n5066\n5067\n5068\n5069\n5070\n5071\n5072\n5073\n5074\n5075\n5076\n5077\n5078\n5079\n5080\n5081\n5082\n5083\n5084\n5085\n5086\n5087\n5088\n5089\n5090\n5091\n5092\n5093\n5094\n5095\n5096\n5097\n5098\n5099\n5100\n5101\n5102\n5103\n5104\n5105\n5106\n5107\n5108\n5109\n5110\n5111\n5112\n5113\n5114\n5115\n5116\n5117\n5118\n5119\n5120\n5121\n5122\n5123\n5124\n5125\n5126\n5127\n5128\n5129\n5130\n5131\n5132\n5133\n5134\n5135\n5136\n5137\n5138\n5139\n5140\n5141\n5142\n5143\n5144\n5145\n5146\n5147\n5148\n5149\n5150\n5151\n5152\n5153\n5154\n5155\n5156\n5157\n5158\n5159\n5160\n5161\n5162\n5163\n5164\n5165\n5166\n5167\n5168\n5169\n5170\n5171\n5172\n5173\n5174\n5175\n5176\n5177\n5178\n5179\n5180\n5181\n5182\n5183\n5184\n5185\n5186\n5187\n5188\n5189\n5190\n5191\n5192\n5193\n5194\n5195\n5196\n5197\n5198\n5199\n5200\n5201\n5202\n5203\n5204\n5205\n5206\n5207\n5208\n5209\n5210\n5211\n5212\n5213\n5214\n5215\n5216\n5217\n5218\n5219\n5220\n5221\n5222\n5223\n5224\n5225\n5226\n5227\n5228\n5229\n5230\n5231\n5232\n5233\n5234\n5235\n5236\n5237\n5238\n5239\n5240\n5241\n5242\n5243\n5244\n5245\n5246\n5247\n5248\n5249\n5250\n5251\n5252\n5253\n5254\n5255\n5256\n5257\n5258\n5259\n5260\n5261\n5262\n5263\n5264\n5265\n5266\n5267\n5268\n5269\n5270\n5271\n5272\n5273\n5274\n5275\n5276\n5277\n5278\n5279\n5280\n5281\n5282\n5283\n5284\n5285\n5286\n5287\n5288\n5289\n5290\n5291\n5292\n5293\n5294\n5295\n5296\n5297\n5298\n5299\n5300\n5301\n5302\n5303\n5304\n5305\n5306\n5307\n5308\n5309\n5310\n5311\n5312\n5313\n5314\n5315\n5316\n5317\n5318\n5319\n5320\n5321\n5322\n5323\n5324\n5325\n5326\n5327\n5328\n5329\n5330\n5331\n5332\n5333\n5334\n5335\n5336\n5337\n5338\n5339\n5340\n5341\n5342\n5343\n5344\n5345\n5346\n5347\n5348\n5349\n5350\n5351\n5352\n5353\n5354\n5355\n5356\n5357\n5358\n5359\n5360\n5361\n5362\n5363\n5364\n5365\n5366\n5367\n5368\n5369\n5370\n5371\n5372\n5373\n5374\n5375\n5376\n5377\n5378\n5379\n5380\n5381\n5382\n5383\n5384\n5385\n5386\n5387\n5388\n5389\n5390\n5391\n5392\n5393\n5394\n5395\n5396\n5397\n5398\n5399\n5400\n5401\n5402\n5403\n5404\n5405\n5406\n5407\n5408\n5409\n5410\n5411\n5412\n5413\n5414\n5415\n5416\n5417\n5418\n5419\n5420\n5421\n5422\n5423\n5424\n5425\n5426\n5427\n5428\n5429\n5430\n5431\n5432\n5433\n5434\n5435\n5436\n5437\n5438\n5439\n5440\n5441\n5442\n5443\n5444\n5445\n5446\n5447\n5448\n5449\n5450\n5451\n5452\n5453\n5454\n5455\n5456\n5457\n5458\n5459\n5460\n5461\n5462\n5463\n5464\n5465\n5466\n5467\n5468\n5469\n5470\n5471\n5472\n5473\n5474\n5475\n5476\n5477\n5478\n5479\n5480\n5481\n5482\n5483\n5484\n5485\n5486\n5487\n5488\n5489\n5490\n5491\n5492\n5493\n5494\n5495\n5496\n5497\n5498\n5499\n5500\n5501\n5502\n5503\n5504\n5505\n5506\n5507\n5508\n5509\n5510\n5511\n5512\n5513\n5514\n5515\n5516\n5517\n5518\n5519\n5520\n5521\n5522\n5523\n5524\n5525\n5526\n5527\n5528\n5529\n5530\n5531\n5532\n5533\n5534\n5535\n5536\n5537\n5538\n5539\n5540\n5541\n5542\n5543\n5544\n5545\n5546\n5547\n5548\n5549\n5550\n5551\n5552\n5553\n5554\n5555\n5556\n5557\n5558\n5559\n5560\n5561\n5562\n5563\n5564\n5565\n5566\n5567\n5568\n5569\n5570\n5571\n5572\n5573\n5574\n5575\n5576\n5577\n5578\n5579\n5580\n5581\n5582\n5583\n5584\n5585\n5586\n5587\n5588\n5589\n5590\n5591\n5592\n5593\n5594\n5595\n5596\n5597\n5598\n5599\n5600\n5601\n5602\n5603\n5604\n5605\n5606\n5607\n5608\n5609\n5610\n5611\n5612\n5613\n5614\n5615\n5616\n5617\n5618\n5619\n5620\n5621\n5622\n5623\n5624\n5625\n5626\n5627\n5628\n5629\n5630\n5631\n5632\n5633\n5634\n5635\n5636\n5637\n5638\n5639\n5640\n5641\n5642\n5643\n5644\n5645\n5646\n5647\n5648\n5649\n5650\n5651\n5652\n5653\n5654\n5655\n5656\n5657\n5658\n5659\n5660\n5661\n5662\n5663\n5664\n5665\n5666\n5667\n5668\n5669\n5670\n5671\n5672\n5673\n5674\n5675\n5676\n5677\n5678\n5679\n5680\n5681\n5682\n5683\n5684\n5685\n5686\n5687\n5688\n5689\n5690\n5691\n5692\n5693\n5694\n5695\n5696\n5697\n5698\n5699\n5700\n5701\n5702\n5703\n5704\n5705\n5706\n5707\n5708\n5709\n5710\n5711\n5712\n5713\n5714\n5715\n5716\n5717\n5718\n5719\n5720\n5721\n5722\n5723\n5724\n5725\n5726\n5727\n5728\n5729\n5730\n5731\n5732\n5733\n5734\n5735\n5736\n5737\n5738\n5739\n5740\n5741\n5742\n5743\n5744\n5745\n5746\n5747\n5748\n5749\n5750\n5751\n5752\n5753\n5754\n5755\n5756\n5757\n5758\n5759\n5760\n5761\n5762\n5763\n5764\n5765\n5766\n5767\n5768\n5769\n5770\n5771\n5772\n5773\n5774\n5775\n5776\n5777\n5778\n5779\n5780\n5781\n5782\n5783\n5784\n5785\n5786\n5787\n5788\n5789\n5790\n5791\n5792\n5793\n5794\n5795\n5796\n5797\n5798\n5799\n5800\n5801\n5802\n5803\n5804\n5805\n5806\n5807\n5808\n5809\n5810\n5811\n5812\n5813\n5814\n5815\n5816\n5817\n5818\n5819\n5820\n5821\n5822\n5823\n5824\n5825\n5826\n5827\n5828\n5829\n5830\n5831\n5832\n5833\n5834\n5835\n5836\n5837\n5838\n5839\n5840\n5841\n5842\n5843\n5844\n5845\n5846\n5847\n5848\n5849\n5850\n5851\n5852\n5853\n5854\n5855\n5856\n5857\n5858\n5859\n5860\n5861\n5862\n5863\n5864\n5865\n5866\n5867\n5868\n5869\n5870\n5871\n5872\n5873\n5874\n5875\n5876\n5877\n5878\n5879\n5880\n5881\n5882\n5883\n5884\n5885\n5886\n5887\n5888\n5889\n5890\n5891\n5892\n5893\n5894\n5895\n5896\n5897\n5898\n5899\n5900\n5901\n5902\n5903\n5904\n5905\n5906\n5907\n5908\n5909\n5910\n5911\n5912\n5913\n5914\n5915\n5916\n5917\n5918\n5919\n5920\n5921\n5922\n5923\n5924\n5925\n5926\n5927\n5928\n5929\n5930\n5931\n5932\n5933\n5934\n5935\n5936\n5937\n5938\n5939\n5940\n5941\n5942\n5943\n5944\n5945\n5946\n5947\n5948\n5949\n5950\n5951\n5952\n5953\n5954\n5955\n5956\n5957\n5958\n5959\n5960\n5961\n5962\n5963\n5964\n5965\n5966\n5967\n5968\n5969\n5970\n5971\n5972\n5973\n5974\n5975\n5976\n5977\n5978\n5979\n5980\n5981\n5982\n5983\n5984\n5985\n5986\n5987\n5988\n5989\n5990\n5991\n5992\n5993\n5994\n5995\n5996\n5997\n5998\n5999\n6000\n6001\n6002\n6003\n6004\n6005\n6006\n6007\n6008\n6009\n6010\n6011\n6012\n6013\n6014\n6015\n6016\n6017\n6018\n6019\n6020\n6021\n6022\n6023\n6024\n6025\n6026\n6027\n6028\n6029\n6030\n6031\n6032\n6033\n6034\n6035\n6036\n6037\n6038\n6039\n6040\n6041\n6042\n6043\n6044\n6045\n6046\n6047\n6048\n6049\n6050\n6051\n6052\n6053\n6054\n6055\n6056\n6057\n6058\n6059\n6060\n6061\n6062\n6063\n6064\n6065\n6066\n6067\n6068\n6069\n6070\n6071\n6072\n6073\n6074\n6075\n6076\n6077\n6078\n6079\n6080\n6081\n6082\n6083\n6084\n6085\n6086\n6087\n6088\n6089\n6090\n6091\n6092\n6093\n6094\n6095\n6096\n6097\n6098\n6099\n6100\n6101\n6102\n6103\n6104\n6105\n6106\n6107\n6108\n6109\n6110\n6111\n6112\n6113\n6114\n6115\n6116\n6117\n6118\n6119\n6120\n6121\n6122\n6123\n6124\n6125\n6126\n6127\n6128\n6129\n6130\n6131\n6132\n6133\n6134\n6135\n6136\n6137\n6138\n6139\n6140\n6141\n6142\n6143\n6144\n6145\n6146\n6147\n6148\n6149\n6150\n6151\n6152\n6153\n6154\n6155\n6156\n6157\n6158\n6159\n6160\n6161\n6162\n6163\n6164\n6165\n6166\n6167\n6168\n6169\n6170\n6171\n6172\n6173\n6174\n6175\n6176\n6177\n6178\n6179\n6180\n6181\n6182\n6183\n6184\n6185\n6186\n6187\n6188\n6189\n6190\n6191\n6192\n6193\n6194\n6195\n6196\n6197\n6198\n6199\n6200\n6201\n6202\n6203\n6204\n6205\n6206\n6207\n6208\n6209\n6210\n6211\n6212\n6213\n6214\n6215\n6216\n6217\n6218\n6219\n6220\n6221\n6222\n6223\n6224\n6225\n6226\n6227\n6228\n6229\n6230\n6231\n6232\n6233\n6234\n6235\n6236\n6237\n6238\n6239\n6240\n6241\n6242\n6243\n6244\n6245\n6246\n6247\n6248\n6249\n6250\n6251\n6252\n6253\n6254\n6255\n6256\n6257\n6258\n6259\n6260\n6261\n6262\n6263\n6264\n6265\n6266\n6267\n6268\n6269\n6270\n6271\n6272\n6273\n6274\n6275\n6276\n6277\n6278\n6279\n6280\n6281\n6282\n6283\n6284\n6285\n6286\n6287\n6288\n6289\n6290\n6291\n6292\n6293\n6294\n6295\n6296\n6297\n6298\n6299\n6300\n6301\n6302\n6303\n6304\n6305\n6306\n6307\n6308\n6309\n6310\n6311\n6312\n6313\n6314\n6315\n6316\n6317\n6318\n6319\n6320\n6321\n6322\n6323\n6324\n6325\n6326\n6327\n6328\n6329\n6330\n6331\n6332\n6333\n6334\n6335\n6336\n6337\n6338\n6339\n6340\n6341\n6342\n6343\n6344\n6345\n6346\n6347\n6348\n6349\n6350\n6351\n6352\n6353\n6354\n6355\n6356\n6357\n6358\n6359\n6360\n6361\n6362\n6363\n6364\n6365\n6366\n6367\n6368\n6369\n6370\n6371\n6372\n6373\n6374\n6375\n6376\n6377\n6378\n6379\n6380\n6381\n6382\n6383\n6384\n6385\n6386\n6387\n6388\n6389\n6390\n6391\n6392\n6393\n6394\n6395\n6396\n6397\n6398\n6399\n6400\n6401\n6402\n6403\n6404\n6405\n6406\n6407\n6408\n6409\n6410\n6411\n6412\n6413\n6414\n6415\n6416\n6417\n6418\n6419\n6420\n6421\n6422\n6423\n6424\n6425\n6426\n6427\n6428\n6429\n6430\n6431\n6432\n6433\n6434\n6435\n6436\n6437\n6438\n6439\n6440\n6441\n6442\n6443\n6444\n6445\n6446\n6447\n6448\n6449\n6450\n6451\n6452\n6453\n6454\n6455\n6456\n6457\n6458\n6459\n6460\n6461\n6462\n6463\n6464\n6465\n6466\n6467\n6468\n6469\n6470\n6471\n6472\n6473\n6474\n6475\n6476\n6477\n6478\n6479\n6480\n6481\n6482\n6483\n6484\n6485\n6486\n6487\n6488\n6489\n6490\n6491\n6492\n6493\n6494\n6495\n6496\n6497\n6498\n6499\n6500\n6501\n6502\n6503\n6504\n6505\n6506\n6507\n6508\n6509\n6510\n6511\n6512\n6513\n6514\n6515\n6516\n6517\n6518\n6519\n6520\n6521\n6522\n6523\n6524\n6525\n6526\n6527\n6528\n6529\n6530\n6531\n6532\n6533\n6534\n6535\n6536\n6537\n6538\n6539\n6540\n6541\n6542\n6543\n6544\n6545\n6546\n6547\n6548\n6549\n6550\n6551\n6552\n6553\n6554\n6555\n6556\n6557\n6558\n6559\n6560\n6561\n6562\n6563\n6564\n6565\n6566\n6567\n6568\n6569\n6570\n6571\n6572\n6573\n6574\n6575\n6576\n6577\n6578\n6579\n6580\n6581\n6582\n6583\n6584\n6585\n6586\n6587\n6588\n6589\n6590\n6591\n6592\n6593\n6594\n6595\n6596\n6597\n6598\n6599\n6600\n6601\n6602\n6603\n6604\n6605\n6606\n6607\n6608\n6609\n6610\n6611\n6612\n6613\n6614\n6615\n6616\n6617\n6618\n6619\n6620\n6621\n6622\n6623\n6624\n6625\n6626\n6627\n6628\n6629\n6630\n6631\n6632\n6633\n6634\n6635\n6636\n6637\n6638\n6639\n6640\n6641\n6642\n6643\n6644\n6645\n6646\n6647\n6648\n6649\n6650\n6651\n6652\n6653\n6654\n6655\n6656\n6657\n6658\n6659\n6660\n6661\n6662\n6663\n6664\n6665\n6666\n6667\n6668\n6669\n6670\n6671\n6672\n6673\n6674\n6675\n6676\n6677\n6678\n6679\n6680\n6681\n6682\n6683\n6684\n6685\n6686\n6687\n6688\n6689\n6690\n6691\n6692\n6693\n6694\n6695\n6696\n6697\n6698\n6699\n6700\n6701\n6702\n6703\n6704\n6705\n6706\n6707\n6708\n6709\n6710\n6711\n6712\n6713\n6714\n6715\n6716\n6717\n6718\n6719\n6720\n6721\n6722\n6723\n6724\n6725\n6726\n6727\n6728\n6729\n6730\n6731\n6732\n6733\n6734\n6735\n6736\n6737\n6738\n6739\n6740\n6741\n6742\n6743\n6744\n6745\n6746\n6747\n6748\n6749\n6750\n6751\n6752\n6753\n6754\n6755\n6756\n6757\n6758\n6759\n6760\n6761\n6762\n6763\n6764\n6765\n6766\n6767\n6768\n6769\n6770\n6771\n6772\n6773\n6774\n6775\n6776\n6777\n6778\n6779\n6780\n6781\n6782\n6783\n6784\n6785\n6786\n6787\n6788\n6789\n6790\n6791\n6792\n6793\n6794\n6795\n6796\n6797\n6798\n6799\n6800\n6801\n6802\n6803\n6804\n6805\n6806\n6807\n6808\n6809\n6810\n6811\n6812\n6813\n6814\n6815\n6816\n6817\n6818\n6819\n6820\n6821\n6822\n6823\n6824\n6825\n6826\n6827\n6828\n6829\n6830\n6831\n6832\n6833\n6834\n6835\n6836\n6837\n6838\n6839\n6840\n6841\n6842\n6843\n6844\n6845\n6846\n6847\n6848\n6849\n6850\n6851\n6852\n6853\n6854\n6855\n6856\n6857\n6858\n6859\n6860\n6861\n6862\n6863\n6864\n6865\n6866\n6867\n6868\n6869\n6870\n6871\n6872\n6873\n6874\n6875\n6876\n6877\n6878\n6879\n6880\n6881\n6882\n6883\n6884\n6885\n6886\n6887\n6888\n6889\n6890\n6891\n6892\n6893\n6894\n6895\n6896\n6897\n6898\n6899\n6900\n6901\n6902\n6903\n6904\n6905\n6906\n6907\n6908\n6909\n6910\n6911\n6912\n6913\n6914\n6915\n6916\n6917\n6918\n6919\n6920\n6921\n6922\n6923\n6924\n6925\n6926\n6927\n6928\n6929\n6930\n6931\n6932\n6933\n6934\n6935\n6936\n6937\n6938\n6939\n6940\n6941\n6942\n6943\n6944\n6945\n6946\n6947\n6948\n6949\n6950\n6951\n6952\n6953\n6954\n6955\n6956\n6957\n6958\n6959\n6960\n6961\n6962\n6963\n6964\n6965\n6966\n6967\n6968\n6969\n6970\n6971\n6972\n6973\n6974\n6975\n6976\n6977\n6978\n6979\n6980\n6981\n6982\n6983\n6984\n6985\n6986\n6987\n6988\n6989\n6990\n6991\n6992\n6993\n6994\n6995\n6996\n6997\n6998\n6999\n7000\n7001\n7002\n7003\n7004\n7005\n7006\n7007\n7008\n7009\n7010\n7011\n7012\n7013\n7014\n7015\n7016\n7017\n7018\n7019\n7020\n7021\n7022\n7023\n7024\n7025\n7026\n7027\n7028\n7029\n7030\n7031\n7032\n7033\n7034\n7035\n7036\n7037\n7038\n7039\n7040\n7041\n7042\n7043\n7044\n7045\n7046\n7047\n7048\n7049\n7050\n7051\n7052\n7053\n7054\n7055\n7056\n7057\n7058\n7059\n7060\n7061\n7062\n7063\n7064\n7065\n7066\n7067\n7068\n7069\n7070\n7071\n7072\n7073\n7074\n7075\n7076\n7077\n7078\n7079\n7080\n7081\n7082\n7083\n7084\n7085\n7086\n7087\n7088\n7089\n7090\n7091\n7092\n7093\n7094\n7095\n7096\n7097\n7098\n7099\n7100\n7101\n7102\n7103\n7104\n7105\n7106\n7107\n7108\n7109\n7110\n7111\n7112\n7113\n7114\n7115\n7116\n7117\n7118\n7119\n7120\n7121\n7122\n7123\n7124\n7125\n7126\n7127\n7128\n7129\n7130\n7131\n7132\n7133\n7134\n7135\n7136\n7137\n7138\n7139\n7140\n7141\n7142\n7143\n7144\n7145\n7146\n7147\n7148\n7149\n7150\n7151\n7152\n7153\n7154\n7155\n7156\n7157\n7158\n7159\n7160\n7161\n7162\n7163\n7164\n7165\n7166\n7167\n7168\n7169\n7170\n7171\n7172\n7173\n7174\n7175\n7176\n7177\n7178\n7179\n7180\n7181\n7182\n7183\n7184\n7185\n7186\n7187\n7188\n7189\n7190\n7191\n7192\n7193\n7194\n7195\n7196\n7197\n7198\n7199\n7200\n7201\n7202\n7203\n7204\n7205\n7206\n7207\n7208\n7209\n7210\n7211\n7212\n7213\n7214\n7215\n7216\n7217\n7218\n7219\n7220\n7221\n7222\n7223\n7224\n7225\n7226\n7227\n7228\n7229\n7230\n7231\n7232\n7233\n7234\n7235\n7236\n7237\n7238\n7239\n7240\n7241\n7242\n7243\n7244\n7245\n7246\n7247\n7248\n7249\n7250\n7251\n7252\n7253\n7254\n7255\n7256\n7257\n7258\n7259\n7260\n7261\n7262\n7263\n7264\n7265\n7266\n7267\n7268\n7269\n7270\n7271\n7272\n7273\n7274\n7275\n7276\n7277\n7278\n7279\n7280\n7281\n7282\n7283\n7284\n7285\n7286\n7287\n7288\n7289\n7290\n7291\n7292\n7293\n7294\n7295\n7296\n7297\n7298\n7299\n7300\n7301\n7302\n7303\n7304\n7305\n7306\n7307\n7308\n7309\n7310\n7311\n7312\n7313\n7314\n7315\n7316\n7317\n7318\n7319\n7320\n7321\n7322\n7323\n7324\n7325\n7326\n7327\n7328\n7329\n7330\n7331\n7332\n7333\n7334\n7335\n7336\n7337\n7338\n7339\n7340\n7341\n7342\n7343\n7344\n7345\n7346\n7347\n7348\n7349\n7350\n7351\n7352\n7353\n7354\n7355\n7356\n7357\n7358\n7359\n7360\n7361\n7362\n7363\n7364\n7365\n7366\n7367\n7368\n7369\n7370\n7371\n7372\n7373\n7374\n7375\n7376\n7377\n7378\n7379\n7380\n7381\n7382\n7383\n7384\n7385\n7386\n7387\n7388\n7389\n7390\n7391\n7392\n7393\n7394\n7395\n7396\n7397\n7398\n7399\n7400\n7401\n7402\n7403\n7404\n7405\n7406\n7407\n7408\n7409\n7410\n7411\n7412\n7413\n7414\n7415\n7416\n7417\n7418\n7419\n7420\n7421\n7422\n7423\n7424\n7425\n7426\n7427\n7428\n7429\n7430\n7431\n7432\n7433\n7434\n7435\n7436\n7437\n7438\n7439\n7440\n7441\n7442\n7443\n7444\n7445\n7446\n7447\n7448\n7449\n7450\n7451\n7452\n7453\n7454\n7455\n7456\n7457\n7458\n7459\n7460\n7461\n7462\n7463\n7464\n7465\n7466\n7467\n7468\n7469\n7470\n7471\n7472\n7473\n7474\n7475\n7476\n7477\n7478\n7479\n7480\n7481\n7482\n7483\n7484\n7485\n7486\n7487\n7488\n7489\n7490\n7491\n7492\n7493\n7494\n7495\n7496\n7497\n7498\n7499\n7500\n7501\n7502\n7503\n7504\n7505\n7506\n7507\n7508\n7509\n7510\n7511\n7512\n7513\n7514\n7515\n7516\n7517\n7518\n7519\n7520\n7521\n7522\n7523\n7524\n7525\n7526\n7527\n7528\n7529\n7530\n7531\n7532\n7533\n7534\n7535\n7536\n7537\n7538\n7539\n7540\n7541\n7542\n7543\n7544\n7545\n7546\n7547\n7548\n7549\n7550\n7551\n7552\n7553\n7554\n7555\n7556\n7557\n7558\n7559\n7560\n7561\n7562\n7563\n7564\n7565\n7566\n7567\n7568\n7569\n7570\n7571\n7572\n7573\n7574\n7575\n7576\n7577\n7578\n7579\n7580\n7581\n7582\n7583\n7584\n7585\n7586\n7587\n7588\n7589\n7590\n7591\n7592\n7593\n7594\n7595\n7596\n7597\n7598\n7599\n7600\n7601\n7602\n7603\n7604\n7605\n7606\n7607\n7608\n7609\n7610\n7611\n7612\n7613\n7614\n7615\n7616\n7617\n7618\n7619\n7620\n7621\n7622\n7623\n7624\n7625\n7626\n7627\n7628\n7629\n7630\n7631\n7632\n7633\n7634\n7635\n7636\n7637\n7638\n7639\n7640\n7641\n7642\n7643\n7644\n7645\n7646\n7647\n7648\n7649\n7650\n7651\n7652\n7653\n7654\n7655\n7656\n7657\n7658\n7659\n7660\n7661\n7662\n7663\n7664\n7665\n7666\n7667\n7668\n7669\n7670\n7671\n7672\n7673\n7674\n7675\n7676\n7677\n7678\n7679\n7680\n7681\n7682\n7683\n7684\n7685\n7686\n7687\n7688\n7689\n7690\n7691\n7692\n7693\n7694\n7695\n7696\n7697\n7698\n7699\n7700\n7701\n7702\n7703\n7704\n7705\n7706\n7707\n7708\n7709\n7710\n7711\n7712\n7713\n7714\n7715\n7716\n7717\n7718\n7719\n7720\n7721\n7722\n7723\n7724\n7725\n7726\n7727\n7728\n7729\n7730\n7731\n7732\n7733\n7734\n7735\n7736\n7737\n7738\n7739\n7740\n7741\n7742\n7743\n7744\n7745\n7746\n7747\n7748\n7749\n7750\n7751\n7752\n7753\n7754\n7755\n7756\n7757\n7758\n7759\n7760\n7761\n7762\n7763\n7764\n7765\n7766\n7767\n7768\n7769\n7770\n7771\n7772\n7773\n7774\n7775\n7776\n7777\n7778\n7779\n7780\n7781\n7782\n7783\n7784\n7785\n7786\n7787\n7788\n7789\n7790\n7791\n7792\n7793\n7794\n7795\n7796\n7797\n7798\n7799\n7800\n7801\n7802\n7803\n7804\n7805\n7806\n7807\n7808\n7809\n7810\n7811\n7812\n7813\n7814\n7815\n7816\n7817\n7818\n7819\n7820\n7821\n7822\n7823\n7824\n7825\n7826\n7827\n7828\n7829\n7830\n7831\n7832\n7833\n7834\n7835\n7836\n7837\n7838\n7839\n7840\n7841\n7842\n7843\n7844\n7845\n7846\n7847\n7848\n7849\n7850\n7851\n7852\n7853\n7854\n7855\n7856\n7857\n7858\n7859\n7860\n7861\n7862\n7863\n7864\n7865\n7866\n7867\n7868\n7869\n7870\n7871\n7872\n7873\n7874\n7875\n7876\n7877\n7878\n7879\n7880\n7881\n7882\n7883\n7884\n7885\n7886\n7887\n7888\n7889\n7890\n7891\n7892\n7893\n7894\n7895\n7896\n7897\n7898\n7899\n7900\n7901\n7902\n7903\n7904\n7905\n7906\n7907\n7908\n7909\n7910\n7911\n7912\n7913\n7914\n7915\n7916\n7917\n7918\n7919\n7920\n7921\n7922\n7923\n7924\n7925\n7926\n7927\n7928\n7929\n7930\n7931\n7932\n7933\n7934\n7935\n7936\n7937\n7938\n7939\n7940\n7941\n7942\n7943\n7944\n7945\n7946\n7947\n7948\n7949\n7950\n7951\n7952\n7953\n7954\n7955\n7956\n7957\n7958\n7959\n7960\n7961\n7962\n7963\n7964\n7965\n7966\n7967\n7968\n7969\n7970\n7971\n7972\n7973\n7974\n7975\n7976\n7977\n7978\n7979\n7980\n7981\n7982\n7983\n7984\n7985\n7986\n7987\n7988\n7989\n7990\n7991\n7992\n7993\n7994\n7995\n7996\n7997\n7998\n7999\n8000\n8001\n8002\n8003\n8004\n8005\n8006\n8007\n8008\n8009\n8010\n8011\n8012\n8013\n8014\n8015\n8016\n8017\n8018\n8019\n8020\n8021\n8022\n8023\n8024\n8025\n8026\n8027\n8028\n8029\n8030\n8031\n8032\n8033\n8034\n8035\n8036\n8037\n8038\n8039\n8040\n8041\n8042\n8043\n8044\n8045\n8046\n8047\n8048\n8049\n8050\n8051\n8052\n8053\n8054\n8055\n8056\n8057\n8058\n8059\n8060\n8061\n8062\n8063\n8064\n8065\n8066\n8067\n8068\n8069\n8070\n8071\n8072\n8073\n8074\n8075\n8076\n8077\n8078\n8079\n8080\n8081\n8082\n8083\n8084\n8085\n8086\n8087\n8088\n8089\n8090\n8091\n8092\n8093\n8094\n8095\n8096\n8097\n8098\n8099\n8100\n8101\n8102\n8103\n8104\n8105\n8106\n8107\n8108\n8109\n8110\n8111\n8112\n8113\n8114\n8115\n8116\n8117\n8118\n8119\n8120\n8121\n8122\n8123\n8124\n8125\n8126\n8127\n8128\n8129\n8130\n8131\n8132\n8133\n8134\n8135\n8136\n8137\n8138\n8139\n8140\n8141\n8142\n8143\n8144\n8145\n8146\n8147\n8148\n8149\n8150\n8151\n8152\n8153\n8154\n8155\n8156\n8157\n8158\n8159\n8160\n8161\n8162\n8163\n8164\n8165\n8166\n8167\n8168\n8169\n8170\n8171\n8172\n8173\n8174\n8175\n8176\n8177\n8178\n8179\n8180\n8181\n8182\n8183\n8184\n8185\n8186\n8187\n8188\n8189\n8190\n8191\n8192\n8193\n8194\n8195\n8196\n8197\n8198\n8199\n8200\n8201\n8202\n8203\n8204\n8205\n8206\n8207\n8208\n8209\n8210\n8211\n8212\n8213\n8214\n8215\n8216\n8217\n8218\n8219\n8220\n8221\n8222\n8223\n8224\n8225\n8226\n8227\n8228\n8229\n8230\n8231\n8232\n8233\n8234\n8235\n8236\n8237\n8238\n8239\n8240\n8241\n8242\n8243\n8244\n8245\n8246\n8247\n8248\n8249\n8250\n8251\n8252\n8253\n8254\n8255\n8256\n8257\n8258\n8259\n8260\n8261\n8262\n8263\n8264\n8265\n8266\n8267\n8268\n8269\n8270\n8271\n8272\n8273\n8274\n8275\n8276\n8277\n8278\n8279\n8280\n8281\n8282\n8283\n8284\n8285\n8286\n8287\n8288\n8289\n8290\n8291\n8292\n8293\n8294\n8295\n8296\n8297\n8298\n8299\n8300\n8301\n8302\n8303\n8304\n8305\n8306\n8307\n8308\n8309\n8310\n8311\n8312\n8313\n8314\n8315\n8316\n8317\n8318\n8319\n8320\n8321\n8322\n8323\n8324\n8325\n8326\n8327\n8328\n8329\n8330\n8331\n8332\n8333\n8334\n8335\n8336\n8337\n8338\n8339\n8340\n8341\n8342\n8343\n8344\n8345\n8346\n8347\n8348\n8349\n8350\n8351\n8352\n8353\n8354\n8355\n8356\n8357\n8358\n8359\n8360\n8361\n8362\n8363\n8364\n8365\n8366\n8367\n8368\n8369\n8370\n8371\n8372\n8373\n8374\n8375\n8376\n8377\n8378\n8379\n8380\n8381\n8382\n8383\n8384\n8385\n8386\n8387\n8388\n8389\n8390\n8391\n8392\n8393\n8394\n8395\n8396\n8397\n8398\n8399\n8400\n8401\n8402\n8403\n8404\n8405\n8406\n8407\n8408\n8409\n8410\n8411\n8412\n8413\n8414\n8415\n8416\n8417\n8418\n8419\n8420\n8421\n8422\n8423\n8424\n8425\n8426\n8427\n8428\n8429\n8430\n8431\n8432\n8433\n8434\n8435\n8436\n8437\n8438\n8439\n8440\n8441\n8442\n8443\n8444\n8445\n8446\n8447\n8448\n8449\n8450\n8451\n8452\n8453\n8454\n8455\n8456\n8457\n8458\n8459\n8460\n8461\n8462\n8463\n8464\n8465\n8466\n8467\n8468\n8469\n8470\n8471\n8472\n8473\n8474\n8475\n8476\n8477\n8478\n8479\n8480\n8481\n8482\n8483\n8484\n8485\n8486\n8487\n8488\n8489\n8490\n8491\n8492\n8493\n8494\n8495\n8496\n8497\n8498\n8499\n8500\n8501\n8502\n8503\n8504\n8505\n8506\n8507\n8508\n8509\n8510\n8511\n8512\n8513\n8514\n8515\n8516\n8517\n8518\n8519\n8520\n8521\n8522\n8523\n8524\n8525\n8526\n8527\n8528\n8529\n8530\n8531\n8532\n8533\n8534\n8535\n8536\n8537\n8538\n8539\n8540\n8541\n8542\n8543\n8544\n8545\n8546\n8547\n8548\n8549\n8550\n8551\n8552\n8553\n8554\n8555\n8556\n8557\n8558\n8559\n8560\n8561\n8562\n8563\n8564\n8565\n8566\n8567\n8568\n8569\n8570\n8571\n8572\n8573\n8574\n8575\n8576\n8577\n8578\n8579\n8580\n8581\n8582\n8583\n8584\n8585\n8586\n8587\n8588\n8589\n8590\n8591\n8592\n8593\n8594\n8595\n8596\n8597\n8598\n8599\n8600\n8601\n8602\n8603\n8604\n8605\n8606\n8607\n8608\n8609\n8610\n8611\n8612\n8613\n8614\n8615\n8616\n8617\n8618\n8619\n8620\n8621\n8622\n8623\n8624\n8625\n8626\n8627\n8628\n8629\n8630\n8631\n8632\n8633\n8634\n8635\n8636\n8637\n8638\n8639\n8640\n8641\n8642\n8643\n8644\n8645\n8646\n8647\n8648\n8649\n8650\n8651\n8652\n8653\n8654\n8655\n8656\n8657\n8658\n8659\n8660\n8661\n8662\n8663\n8664\n8665\n8666\n8667\n8668\n8669\n8670\n8671\n8672\n8673\n8674\n8675\n8676\n8677\n8678\n8679\n8680\n8681\n8682\n8683\n8684\n8685\n8686\n8687\n8688\n8689\n8690\n8691\n8692\n8693\n8694\n8695\n8696\n8697\n8698\n8699\n8700\n8701\n8702\n8703\n8704\n8705\n8706\n8707\n8708\n8709\n8710\n8711\n8712\n8713\n8714\n8715\n8716\n8717\n8718\n8719\n8720\n8721\n8722\n8723\n8724\n8725\n8726\n8727\n8728\n8729\n8730\n8731\n8732\n8733\n8734\n8735\n8736\n8737\n8738\n8739\n8740\n8741\n8742\n8743\n8744\n8745\n8746\n8747\n8748\n8749\n8750\n8751\n8752\n8753\n8754\n8755\n8756\n8757\n8758\n8759\n8760\n8761\n8762\n8763\n8764\n8765\n8766\n8767\n8768\n8769\n8770\n8771\n8772\n8773\n8774\n8775\n8776\n8777\n8778\n8779\n8780\n8781\n8782\n8783\n8784\n8785\n8786\n8787\n8788\n8789\n8790\n8791\n8792\n8793\n8794\n8795\n8796\n8797\n8798\n8799\n8800\n8801\n8802\n8803\n8804\n8805\n8806\n8807\n8808\n8809\n8810\n8811\n8812\n8813\n8814\n8815\n8816\n8817\n8818\n8819\n8820\n8821\n8822\n8823\n8824\n8825\n8826\n8827\n8828\n8829\n8830\n8831\n8832\n8833\n8834\n8835\n8836\n8837\n8838\n8839\n8840\n8841\n8842\n8843\n8844\n8845\n8846\n8847\n8848\n8849\n8850\n8851\n8852\n8853\n8854\n8855\n8856\n8857\n8858\n8859\n8860\n8861\n8862\n8863\n8864\n8865\n8866\n8867\n8868\n8869\n8870\n8871\n8872\n8873\n8874\n8875\n8876\n8877\n8878\n8879\n8880\n8881\n8882\n8883\n8884\n8885\n8886\n8887\n8888\n8889\n8890\n8891\n8892\n8893\n8894\n8895\n8896\n8897\n8898\n8899\n8900\n8901\n8902\n8903\n8904\n8905\n8906\n8907\n8908\n8909\n8910\n8911\n8912\n8913\n8914\n8915\n8916\n8917\n8918\n8919\n8920\n8921\n8922\n8923\n8924\n8925\n8926\n8927\n8928\n8929\n8930\n8931\n8932\n8933\n8934\n8935\n8936\n8937\n8938\n8939\n8940\n8941\n8942\n8943\n8944\n8945\n8946\n8947\n8948\n8949\n8950\n8951\n8952\n8953\n8954\n8955\n8956\n8957\n8958\n8959\n8960\n8961\n8962\n8963\n8964\n8965\n8966\n8967\n8968\n8969\n8970\n8971\n8972\n8973\n8974\n8975\n8976\n8977\n8978\n8979\n8980\n8981\n8982\n8983\n8984\n8985\n8986\n8987\n8988\n8989\n8990\n8991\n8992\n8993\n8994\n8995\n8996\n8997\n8998\n8999\n9000\n9001\n9002\n9003\n9004\n9005\n9006\n9007\n9008\n9009\n9010\n9011\n9012\n9013\n9014\n9015\n9016\n9017\n9018\n9019\n9020\n9021\n9022\n9023\n9024\n9025\n9026\n9027\n9028\n9029\n9030\n9031\n9032\n9033\n9034\n9035\n9036\n9037\n9038\n9039\n9040\n9041\n9042\n9043\n9044\n9045\n9046\n9047\n9048\n9049\n9050\n9051\n9052\n9053\n9054\n9055\n9056\n9057\n9058\n9059\n9060\n9061\n9062\n9063\n9064\n9065\n9066\n9067\n9068\n9069\n9070\n9071\n9072\n9073\n9074\n9075\n9076\n9077\n9078\n9079\n9080\n9081\n9082\n9083\n9084\n9085\n9086\n9087\n9088\n9089\n9090\n9091\n9092\n9093\n9094\n9095\n9096\n9097\n9098\n9099\n9100\n9101\n9102\n9103\n9104\n9105\n9106\n9107\n9108\n9109\n9110\n9111\n9112\n9113\n9114\n9115\n9116\n9117\n9118\n9119\n9120\n9121\n9122\n9123\n9124\n9125\n9126\n9127\n9128\n9129\n9130\n9131\n9132\n9133\n9134\n9135\n9136\n9137\n9138\n9139\n9140\n9141\n9142\n9143\n9144\n9145\n9146\n9147\n9148\n9149\n9150\n9151\n9152\n9153\n9154\n9155\n9156\n9157\n9158\n9159\n9160\n9161\n9162\n9163\n9164\n9165\n9166\n9167\n9168\n9169\n9170\n9171\n9172\n9173\n9174\n9175\n9176\n9177\n9178\n9179\n9180\n9181\n9182\n9183\n9184\n9185\n9186\n9187\n9188\n9189\n9190\n9191\n9192\n9193\n9194\n9195\n9196\n9197\n9198\n9199\n9200\n9201\n9202\n9203\n9204\n9205\n9206\n9207\n9208\n9209\n9210\n9211\n9212\n9213\n9214\n9215\n9216\n9217\n9218\n9219\n9220\n9221\n9222\n9223\n9224\n9225\n9226\n9227\n9228\n9229\n9230\n9231\n9232\n9233\n9234\n9235\n9236\n9237\n9238\n9239\n9240\n9241\n9242\n9243\n9244\n9245\n9246\n9247\n9248\n9249\n9250\n9251\n9252\n9253\n9254\n9255\n9256\n9257\n9258\n9259\n9260\n9261\n9262\n9263\n9264\n9265\n9266\n9267\n9268\n9269\n9270\n9271\n9272\n9273\n9274\n9275\n9276\n9277\n9278\n9279\n9280\n9281\n9282\n9283\n9284\n9285\n9286\n9287\n9288\n9289\n9290\n9291\n9292\n9293\n9294\n9295\n9296\n9297\n9298\n9299\n9300\n9301\n9302\n9303\n9304\n9305\n9306\n9307\n9308\n9309\n9310\n9311\n9312\n9313\n9314\n9315\n9316\n9317\n9318\n9319\n9320\n9321\n9322\n9323\n9324\n9325\n9326\n9327\n9328\n9329\n9330\n9331\n9332\n9333\n9334\n9335\n9336\n9337\n9338\n9339\n9340\n9341\n9342\n9343\n9344\n9345\n9346\n9347\n9348\n9349\n9350\n9351\n9352\n9353\n9354\n9355\n9356\n9357\n9358\n9359\n9360\n9361\n9362\n9363\n9364\n9365\n9366\n9367\n9368\n9369\n9370\n9371\n9372\n9373\n9374\n9375\n9376\n9377\n9378\n9379\n9380\n9381\n9382\n9383\n9384\n9385\n9386\n9387\n9388\n9389\n9390\n9391\n9392\n9393\n9394\n9395\n9396\n9397\n9398\n9399\n9400\n9401\n9402\n9403\n9404\n9405\n9406\n9407\n9408\n9409\n9410\n9411\n9412\n9413\n9414\n9415\n9416\n9417\n9418\n9419\n9420\n9421\n9422\n9423\n9424\n9425\n9426\n9427\n9428\n9429\n9430\n9431\n9432\n9433\n9434\n9435\n9436\n9437\n9438\n9439\n9440\n9441\n9442\n9443\n9444\n9445\n9446\n9447\n9448\n9449\n9450\n9451\n9452\n9453\n9454\n9455\n9456\n9457\n9458\n9459\n9460\n9461\n9462\n9463\n9464\n9465\n9466\n9467\n9468\n9469\n9470\n9471\n9472\n9473\n9474\n9475\n9476\n9477\n9478\n9479\n9480\n9481\n9482\n9483\n9484\n9485\n9486\n9487\n9488\n9489\n9490\n9491\n9492\n9493\n9494\n9495\n9496\n9497\n9498\n9499\n9500\n9501\n9502\n9503\n9504\n9505\n9506\n9507\n9508\n9509\n9510\n9511\n9512\n9513\n9514\n9515\n9516\n9517\n9518\n9519\n9520\n9521\n9522\n9523\n9524\n9525\n9526\n9527\n9528\n9529\n9530\n9531\n9532\n9533\n9534\n9535\n9536\n9537\n9538\n9539\n9540\n9541\n9542\n9543\n9544\n9545\n9546\n9547\n9548\n9549\n9550\n9551\n9552\n9553\n9554\n9555\n9556\n9557\n9558\n9559\n9560\n9561\n9562\n9563\n9564\n9565\n9566\n9567\n9568\n9569\n9570\n9571\n9572\n9573\n9574\n9575\n9576\n9577\n9578\n9579\n9580\n9581\n9582\n9583\n9584\n9585\n9586\n9587\n9588\n9589\n9590\n9591\n9592\n9593\n9594\n9595\n9596\n9597\n9598\n9599\n9600\n9601\n9602\n9603\n9604\n9605\n9606\n9607\n9608\n9609\n9610\n9611\n9612\n9613\n9614\n9615\n9616\n9617\n9618\n9619\n9620\n9621\n9622\n9623\n9624\n9625\n9626\n9627\n9628\n9629\n9630\n9631\n9632\n9633\n9634\n9635\n9636\n9637\n9638\n9639\n9640\n9641\n9642\n9643\n9644\n9645\n9646\n9647\n9648\n9649\n9650\n9651\n9652\n9653\n9654\n9655\n9656\n9657\n9658\n9659\n9660\n9661\n9662\n9663\n9664\n9665\n9666\n9667\n9668\n9669\n9670\n9671\n9672\n9673\n9674\n9675\n9676\n9677\n9678\n9679\n9680\n9681\n9682\n9683\n9684\n9685\n9686\n9687\n9688\n9689\n9690\n9691\n9692\n9693\n9694\n9695\n9696\n9697\n9698\n9699\n9700\n9701\n9702\n9703\n9704\n9705\n9706\n9707\n9708\n9709\n9710\n9711\n9712\n9713\n9714\n9715\n9716\n9717\n9718\n9719\n9720\n9721\n9722\n9723\n9724\n9725\n9726\n9727\n9728\n9729\n9730\n9731\n9732\n9733\n9734\n9735\n9736\n9737\n9738\n9739\n9740\n9741\n9742\n9743\n9744\n9745\n9746\n9747\n9748\n9749\n9750\n9751\n9752\n9753\n9754\n9755\n9756\n9757\n9758\n9759\n9760\n9761\n9762\n9763\n9764\n9765\n9766\n9767\n9768\n9769\n9770\n9771\n9772\n9773\n9774\n9775\n9776\n9777\n9778\n9779\n9780\n9781\n9782\n9783\n9784\n9785\n9786\n9787\n9788\n9789\n9790\n9791\n9792\n9793\n9794\n9795\n9796\n9797\n9798\n9799\n9800\n9801\n9802\n9803\n9804\n9805\n9806\n9807\n9808\n9809\n9810\n9811\n9812\n9813\n9814\n9815\n9816\n9817\n9818\n9819\n9820\n9821\n9822\n9823\n9824\n9825\n9826\n9827\n9828\n9829\n9830\n9831\n9832\n9833\n9834\n9835\n9836\n9837\n9838\n9839\n9840\n9841\n9842\n9843\n9844\n9845\n9846\n9847\n9848\n9849\n9850\n9851\n9852\n9853\n9854\n9855\n9856\n9857\n9858\n9859\n9860\n9861\n9862\n9863\n9864\n9865\n9866\n9867\n9868\n9869\n9870\n9871\n9872\n9873\n9874\n9875\n9876\n9877\n9878\n9879\n9880\n9881\n9882\n9883\n9884\n9885\n9886\n9887\n9888\n9889\n9890\n9891\n9892\n9893\n9894\n9895\n9896\n9897\n9898\n9899\n9900\n9901\n9902\n9903\n9904\n9905\n9906\n9907\n9908\n9909\n9910\n9911\n9912\n9913\n9914\n9915\n9916\n9917\n9918\n9919\n9920\n9921\n9922\n9923\n9924\n9925\n9926\n9927\n9928\n9929\n9930\n9931\n9932\n9933\n9934\n9935\n9936\n9937\n9938\n9939\n9940\n9941\n9942\n9943\n9944\n9945\n9946\n9947\n9948\n9949\n9950\n9951\n9952\n9953\n9954\n9955\n9956\n9957\n9958\n9959\n9960\n9961\n9962\n9963\n9964\n9965\n9966\n9967\n9968\n9969\n9970\n9971\n9972\n9973\n9974\n9975\n9976\n9977\n9978\n9979\n9980\n9981\n9982\n9983\n9984\n9985\n9986\n9987\n9988\n9989\n9990\n9991\n9992\n9993\n9994\n9995\n9996\n9997\n9998\n9999\n10000\n10001\n10002\n10003\n10004\n10005\n10006\n10007\n10008\n10009\n10010\n10011\n10012\n10013\n10014\n10015\n10016\n10017\n10018\n10019\n10020\n10021\n10022\n10023\n10024\n10025\n10026\n10027\n10028\n10029\n10030\n10031\n10032\n10033\n10034\n10035\n10036\n10037\n10038\n10039\n10040\n10041\n10042\n10043\n10044\n10045\n10046\n10047\n10048\n10049\n10050\n10051\n10052\n10053\n10054\n10055\n10056\n10057\n10058\n10059\n10060\n10061\n10062\n10063\n10064\n10065\n10066\n10067\n10068\n10069\n10070\n10071\n10072\n10073\n10074\n10075\n10076\n10077\n10078\n10079\n10080\n10081\n10082\n10083\n10084\n10085\n10086\n10087\n10088\n10089\n10090\n10091\n10092\n10093\n10094\n10095\n10096\n10097\n10098\n10099\n10100\n10101\n10102\n10103\n10104\n10105\n10106\n10107\n10108\n10109\n10110\n10111\n10112\n10113\n10114\n10115\n10116\n10117\n10118\n10119\n10120\n10121\n10122\n10123\n10124\n10125\n10126\n10127\n10128\n10129\n10130\n10131\n10132\n10133\n10134\n10135\n10136\n10137\n10138\n10139\n10140\n10141\n10142\n10143\n10144\n10145\n10146\n10147\n10148\n10149\n10150\n10151\n10152\n10153\n10154\n10155\n10156\n10157\n10158\n10159\n10160\n10161\n10162\n10163\n10164\n10165\n10166\n10167\n10168\n10169\n10170\n10171\n10172\n10173\n10174\n10175\n10176\n10177\n10178\n10179\n10180\n10181\n10182\n10183\n10184\n10185\n10186\n10187\n10188\n10189\n10190\n10191\n10192\n10193\n10194\n10195\n10196\n10197\n10198\n10199\n10200\n10201\n10202\n10203\n10204\n10205\n10206\n10207\n10208\n10209\n10210\n10211\n10212\n10213\n10214\n10215\n10216\n10217\n10218\n10219\n10220\n10221\n10222\n10223\n10224\n10225\n10226\n10227\n10228\n10229\n10230\n10231\n10232\n10233\n10234\n10235\n10236\n10237\n10238\n10239\n10240\n10241\n10242\n10243\n10244\n10245\n10246\n10247\n10248\n10249\n10250\n10251\n10252\n10253\n10254\n10255\n10256\n10257\n10258\n10259\n10260\n10261\n10262\n10263\n10264\n10265\n10266\n10267\n10268\n10269\n10270\n10271\n10272\n10273\n10274\n10275\n10276\n10277\n10278\n10279\n10280\n10281\n10282\n10283\n10284\n10285\n10286\n10287\n10288\n10289\n10290\n10291\n10292\n10293\n10294\n10295\n10296\n10297\n10298\n10299\n10300\n10301\n10302\n10303\n10304\n10305\n10306\n10307\n10308\n10309\n10310\n10311\n10312\n10313\n10314\n10315\n10316\n10317\n10318\n10319\n10320\n10321\n10322\n10323\n10324\n10325\n10326\n10327\n10328\n10329\n10330\n10331\n10332\n10333\n10334\n10335\n10336\n10337\n10338\n10339\n10340\n10341\n10342\n10343\n10344\n10345\n10346\n10347\n10348\n10349\n10350\n10351\n10352\n10353\n10354\n10355\n10356\n10357\n10358\n10359\n10360\n10361\n10362\n10363\n10364\n10365\n10366\n10367\n10368\n10369\n10370\n10371\n10372\n10373\n10374\n10375\n10376\n10377\n10378\n10379\n10380\n10381\n10382\n10383\n10384\n10385\n10386\n10387\n10388\n10389\n10390\n10391\n10392\n10393\n10394\n10395\n10396\n10397\n10398\n10399\n10400\n10401\n10402\n10403\n10404\n10405\n10406\n10407\n10408\n10409\n10410\n10411\n10412\n10413\n10414\n10415\n10416\n10417\n10418\n10419\n10420\n10421\n10422\n10423\n10424\n10425\n10426\n10427\n10428\n10429\n10430\n10431\n10432\n10433\n10434\n10435\n10436\n10437\n10438\n10439\n10440\n10441\n10442\n10443\n10444\n10445\n10446\n10447\n10448\n10449\n10450\n10451\n10452\n10453\n10454\n10455\n10456\n10457\n10458\n10459\n10460\n10461\n10462\n10463\n10464\n10465\n10466\n10467\n10468\n10469\n10470\n10471\n10472\n10473\n10474\n10475\n10476\n10477\n10478\n10479\n10480\n10481\n10482\n10483\n10484\n10485\n10486\n10487\n10488\n10489\n10490\n10491\n10492\n10493\n10494\n10495\n10496\n10497\n10498\n10499\n10500\n10501\n10502\n10503\n10504\n10505\n10506\n10507\n10508\n10509\n10510\n10511\n10512\n10513\n10514\n10515\n10516\n10517\n10518\n10519\n10520\n10521\n10522\n10523\n10524\n10525\n10526\n10527\n10528\n10529\n10530\n10531\n10532\n10533\n10534\n10535\n10536\n10537\n10538\n10539\n10540\n10541\n10542\n10543\n10544\n10545\n10546\n10547\n10548\n10549\n10550\n10551\n10552\n10553\n10554\n10555\n10556\n10557\n10558\n10559\n10560\n10561\n10562\n10563\n10564\n10565\n10566\n10567\n10568\n10569\n10570\n10571\n10572\n10573\n10574\n10575\n10576\n10577\n10578\n10579\n10580\n10581\n10582\n10583\n10584\n10585\n10586\n10587\n10588\n10589\n10590\n10591\n10592\n10593\n10594\n10595\n10596\n10597\n10598\n10599\n10600\n10601\n10602\n10603\n10604\n10605\n10606\n10607\n10608\n10609\n10610\n10611\n10612\n10613\n10614\n10615\n10616\n10617\n10618\n10619\n10620\n10621\n10622\n10623\n10624\n10625\n10626\n10627\n10628\n10629\n10630\n10631\n10632\n10633\n10634\n10635\n10636\n10637\n10638\n10639\n10640\n10641\n10642\n10643\n10644\n10645\n10646\n10647\n10648\n10649\n10650\n10651\n10652\n10653\n10654\n10655\n10656\n10657\n10658\n10659\n10660\n10661\n10662\n10663\n10664\n10665\n10666\n10667\n10668\n10669\n10670\n10671\n10672\n10673\n10674\n10675\n10676\n10677\n10678\n10679\n10680\n10681\n10682\n10683\n10684\n10685\n10686\n10687\n10688\n10689\n10690\n10691\n10692\n10693\n10694\n10695\n10696\n10697\n10698\n10699\n10700\n10701\n10702\n10703\n10704\n10705\n10706\n10707\n10708\n10709\n10710\n10711\n10712\n10713\n10714\n10715\n10716\n10717\n10718\n10719\n10720\n10721\n10722\n10723\n10724\n10725\n10726\n10727\n10728\n10729\n10730\n10731\n10732\n10733\n10734\n10735\n10736\n10737\n10738\n10739\n10740\n10741\n10742\n10743\n10744\n10745\n10746\n10747\n10748\n10749\n10750\n10751\n10752\n10753\n10754\n10755\n10756\n10757\n10758\n10759\n10760\n10761\n10762\n10763\n10764\n10765\n10766\n10767\n10768\n10769\n10770\n10771\n10772\n10773\n10774\n10775\n10776\n10777\n10778\n10779\n10780\n10781\n10782\n10783\n10784\n10785\n10786\n10787\n10788\n10789\n10790\n10791\n10792\n10793\n10794\n10795\n10796\n10797\n10798\n10799\n10800\n10801\n10802\n10803\n10804\n10805\n10806\n10807\n10808\n10809\n10810\n10811\n10812\n10813\n10814\n10815\n10816\n10817\n10818\n10819\n10820\n10821\n10822\n10823\n10824\n10825\n10826\n10827\n10828\n10829\n10830\n10831\n10832\n10833\n10834\n10835\n10836\n10837\n10838\n10839\n10840\n10841\n10842\n10843\n10844\n10845\n10846\n10847\n10848\n10849\n10850\n10851\n10852\n10853\n10854\n10855\n10856\n10857\n10858\n10859\n10860\n10861\n10862\n10863\n10864\n10865\n10866\n10867\n10868\n10869\n10870\n10871\n10872\n10873\n10874\n10875\n10876\n10877\n10878\n10879\n10880\n10881\n10882\n10883\n10884\n10885\n10886\n10887\n10888\n10889\n10890\n10891\n10892\n10893\n10894\n10895\n10896\n10897\n10898\n10899\n10900\n10901\n10902\n10903\n10904\n10905\n10906\n10907\n10908\n10909\n10910\n10911\n10912\n10913\n10914\n10915\n10916\n10917\n10918\n10919\n10920\n10921\n10922\n10923\n10924\n10925\n10926\n10927\n10928\n10929\n10930\n10931\n10932\n10933\n10934\n10935\n10936\n10937\n10938\n10939\n10940\n10941\n10942\n10943\n10944\n10945\n10946\n10947\n10948\n10949\n10950\n10951\n10952\n10953\n10954\n10955\n10956\n10957\n10958\n10959\n10960\n10961\n10962\n10963\n10964\n10965\n10966\n10967\n10968\n10969\n10970\n10971\n10972\n10973\n10974\n10975\n10976\n10977\n10978\n10979\n10980\n10981\n10982\n10983\n10984\n10985\n10986\n10987\n10988\n10989\n10990\n10991\n10992\n10993\n10994\n10995\n10996\n10997\n10998\n10999\n11000\n11001\n11002\n11003\n11004\n11005\n11006\n11007\n11008\n11009\n11010\n11011\n11012\n11013\n11014\n11015\n11016\n11017\n11018\n11019\n11020\n11021\n11022\n11023\n11024\n11025\n11026\n11027\n11028\n11029\n11030\n11031\n11032\n11033\n11034\n11035\n11036\n11037\n11038\n11039\n11040\n11041\n11042\n11043\n11044\n11045\n11046\n11047\n11048\n11049\n11050\n11051\n11052\n11053\n11054\n11055\n11056\n11057\n11058\n11059\n11060\n11061\n11062\n11063\n11064\n11065\n11066\n11067\n11068\n11069\n11070\n11071\n11072\n11073\n11074\n11075\n11076\n11077\n11078\n11079\n11080\n11081\n11082\n11083\n11084\n11085\n11086\n11087\n11088\n11089\n11090\n11091\n11092\n11093\n11094\n11095\n11096\n11097\n11098\n11099\n11100\n11101\n11102\n11103\n11104\n11105\n11106\n11107\n11108\n11109\n11110\n11111\n11112\n11113\n11114\n11115\n11116\n11117\n11118\n11119\n11120\n11121\n11122\n11123\n11124\n11125\n11126\n11127\n11128\n11129\n11130\n11131\n11132\n11133\n11134\n11135\n11136\n11137\n11138\n11139\n11140\n11141\n11142\n11143\n11144\n11145\n11146\n11147\n11148\n11149\n11150\n11151\n11152\n11153\n11154\n11155\n11156\n11157\n11158\n11159\n11160\n11161\n11162\n11163\n11164\n11165\n11166\n11167\n11168\n11169\n11170\n11171\n11172\n11173\n11174\n11175\n11176\n11177\n11178\n11179\n11180\n11181\n11182\n11183\n11184\n11185\n11186\n11187\n11188\n11189\n11190\n11191\n11192\n11193\n11194\n11195\n11196\n11197\n11198\n11199\n11200\n11201\n11202\n11203\n11204\n11205\n11206\n11207\n11208\n11209\n11210\n11211\n11212\n11213\n11214\n11215\n11216\n11217\n11218\n11219\n11220\n11221\n11222\n11223\n11224\n11225\n11226\n11227\n11228\n11229\n11230\n11231\n11232\n11233\n11234\n11235\n11236\n11237\n11238\n11239\n11240\n11241\n11242\n11243\n11244\n11245\n11246\n11247\n11248\n11249\n11250\n11251\n11252\n11253\n11254\n11255\n11256\n11257\n11258\n11259\n11260\n11261\n11262\n11263\n11264\n11265\n11266\n11267\n11268\n11269\n11270\n11271\n11272\n11273\n11274\n11275\n11276\n11277\n11278\n11279\n11280\n11281\n11282\n11283\n11284\n11285\n11286\n11287\n11288\n11289\n11290\n11291\n11292\n11293\n11294\n11295\n11296\n11297\n11298\n11299\n11300\n11301\n11302\n11303\n11304\n11305\n11306\n11307\n11308\n11309\n11310\n11311\n11312\n11313\n11314\n11315\n11316\n11317\n11318\n11319\n11320\n11321\n11322\n11323\n11324\n11325\n11326\n11327\n11328\n11329\n11330\n11331\n11332\n11333\n11334\n11335\n11336\n11337\n11338\n11339\n11340\n11341\n11342\n11343\n11344\n11345\n11346\n11347\n11348\n11349\n11350\n11351\n11352\n11353\n11354\n11355\n11356\n11357\n11358\n11359\n11360\n11361\n11362\n11363\n11364\n11365\n11366\n11367\n11368\n11369\n11370\n11371\n11372\n11373\n11374\n11375\n11376\n11377\n11378\n11379\n11380\n11381\n11382\n11383\n11384\n11385\n11386\n11387\n11388\n11389\n11390\n11391\n11392\n11393\n11394\n11395\n11396\n11397\n11398\n11399\n11400\n11401\n11402\n11403\n11404\n11405\n11406\n11407\n11408\n11409\n11410\n11411\n11412\n11413\n11414\n11415\n11416\n11417\n11418\n11419\n11420\n11421\n11422\n11423\n11424\n11425\n11426\n11427\n11428\n11429\n11430\n11431\n11432\n11433\n11434\n11435\n11436\n11437\n11438\n11439\n11440\n11441\n11442\n11443\n11444\n11445\n11446\n11447\n11448\n11449\n11450\n11451\n11452\n11453\n11454\n11455\n11456\n11457\n11458\n11459\n11460\n11461\n11462\n11463\n11464\n11465\n11466\n11467\n11468\n11469\n11470\n11471\n11472\n11473\n11474\n11475\n11476\n11477\n11478\n11479\n11480\n11481\n11482\n11483\n11484\n11485\n11486\n11487\n11488\n11489\n11490\n11491\n11492\n11493\n11494\n11495\n11496\n11497\n11498\n11499\n11500\n11501\n11502\n11503\n11504\n11505\n11506\n11507\n11508\n11509\n11510\n11511\n11512\n11513\n11514\n11515\n11516\n11517\n11518\n11519\n11520\n11521\n11522\n11523\n11524\n11525\n11526\n11527\n11528\n11529\n11530\n11531\n11532\n11533\n11534\n11535\n11536\n11537\n11538\n11539\n11540\n11541\n11542\n11543\n11544\n11545\n11546\n11547\n11548\n11549\n11550\n11551\n11552\n11553\n11554\n11555\n11556\n11557\n11558\n11559\n11560\n11561\n11562\n11563\n11564\n11565\n11566\n11567\n11568\n11569\n11570\n11571\n11572\n11573\n11574\n11575\n11576\n11577\n11578\n11579\n11580\n11581\n11582\n11583\n11584\n11585\n11586\n11587\n11588\n11589\n11590\n11591\n11592\n11593\n11594\n11595\n11596\n11597\n11598\n11599\n11600\n11601\n11602\n11603\n11604\n11605\n11606\n11607\n11608\n11609\n11610\n11611\n11612\n11613\n11614\n11615\n11616\n11617\n11618\n11619\n11620\n11621\n11622\n11623\n11624\n11625\n11626\n11627\n11628\n11629\n11630\n11631\n11632\n11633\n11634\n11635\n11636\n11637\n11638\n11639\n11640\n11641\n11642\n11643\n11644\n11645\n11646\n11647\n11648\n11649\n11650\n11651\n11652\n11653\n11654\n11655\n11656\n11657\n11658\n11659\n11660\n11661\n11662\n11663\n11664\n11665\n11666\n11667\n11668\n11669\n11670\n11671\n11672\n11673\n11674\n11675\n11676\n11677\n11678\n11679\n11680\n11681\n11682\n11683\n11684\n11685\n11686\n11687\n11688\n11689\n11690\n11691\n11692\n11693\n11694\n11695\n11696\n11697\n11698\n11699\n11700\n11701\n11702\n11703\n11704\n11705\n11706\n11707\n11708\n11709\n11710\n11711\n11712\n11713\n11714\n11715\n11716\n11717\n11718\n11719\n11720\n11721\n11722\n11723\n11724\n11725\n11726\n11727\n11728\n11729\n11730\n11731\n11732\n11733\n11734\n11735\n11736\n11737\n11738\n11739\n11740\n11741\n11742\n11743\n11744\n11745\n11746\n11747\n11748\n11749\n11750\n11751\n11752\n11753\n11754\n11755\n11756\n11757\n11758\n11759\n11760\n11761\n11762\n11763\n11764\n11765\n11766\n11767\n11768\n11769\n11770\n11771\n11772\n11773\n11774\n11775\n11776\n11777\n11778\n11779\n11780\n11781\n11782\n11783\n11784\n11785\n11786\n11787\n11788\n11789\n11790\n11791\n11792\n11793\n11794\n11795\n11796\n11797\n11798\n11799\n11800\n11801\n11802\n11803\n11804\n11805\n11806\n11807\n11808\n11809\n11810\n11811\n11812\n11813\n11814\n11815\n11816\n11817\n11818\n11819\n11820\n11821\n11822\n11823\n11824\n11825\n11826\n11827\n11828\n11829\n11830\n11831\n11832\n11833\n11834\n11835\n11836\n11837\n11838\n11839\n11840\n11841\n11842\n11843\n11844\n11845\n11846\n11847\n11848\n11849\n11850\n11851\n11852\n11853\n11854\n11855\n11856\n11857\n11858\n11859\n11860\n11861\n11862\n11863\n11864\n11865\n11866\n11867\n11868\n11869\n11870\n11871\n11872\n11873\n11874\n11875\n11876\n11877\n11878\n11879\n11880\n11881\n11882\n11883\n11884\n11885\n11886\n11887\n11888\n11889\n11890\n11891\n11892\n11893\n11894\n11895\n11896\n11897\n11898\n11899\n11900\n11901\n11902\n11903\n11904\n11905\n11906\n11907\n11908\n11909\n11910\n11911\n11912\n11913\n11914\n11915\n11916\n11917\n11918\n11919\n11920\n11921\n11922\n11923\n11924\n11925\n11926\n11927\n11928\n11929\n11930\n11931\n11932\n11933\n11934\n11935\n11936\n11937\n11938\n11939\n11940\n11941\n11942\n11943\n11944\n11945\n11946\n11947\n11948\n11949\n11950\n11951\n11952\n11953\n11954\n11955\n11956\n11957\n11958\n11959\n11960\n11961\n11962\n11963\n11964\n11965\n11966\n11967\n11968\n11969\n11970\n11971\n11972\n11973\n11974\n11975\n11976\n11977\n11978\n11979\n11980\n11981\n11982\n11983\n11984\n11985\n11986\n11987\n11988\n11989\n11990\n11991\n11992\n11993\n11994\n11995\n11996\n11997\n11998\n11999\n12000\n12001\n12002\n12003\n12004\n12005\n12006\n12007\n12008\n12009\n12010\n12011\n12012\n12013\n12014\n12015\n12016\n12017\n12018\n12019\n12020\n12021\n12022\n12023\n12024\n12025\n12026\n12027\n12028\n12029\n12030\n12031\n12032\n12033\n12034\n12035\n12036\n12037\n12038\n12039\n12040\n12041\n12042\n12043\n12044\n12045\n12046\n12047\n12048\n12049\n12050\n12051\n12052\n12053\n12054\n12055\n12056\n12057\n12058\n12059\n12060\n12061\n12062\n12063\n12064\n12065\n12066\n12067\n12068\n12069\n12070\n12071\n12072\n12073\n12074\n12075\n12076\n12077\n12078\n12079\n12080\n12081\n12082\n12083\n12084\n12085\n12086\n12087\n12088\n12089\n12090\n12091\n12092\n12093\n12094\n12095\n12096\n12097\n12098\n12099\n12100\n12101\n12102\n12103\n12104\n12105\n12106\n12107\n12108\n12109\n12110\n12111\n12112\n12113\n12114\n12115\n12116\n12117\n12118\n12119\n12120\n12121\n12122\n12123\n12124\n12125\n12126\n12127\n12128\n12129\n12130\n12131\n12132\n12133\n12134\n12135\n12136\n12137\n12138\n12139\n12140\n12141\n12142\n12143\n12144\n12145\n12146\n12147\n12148\n12149\n12150\n12151\n12152\n12153\n12154\n12155\n12156\n12157\n12158\n12159\n12160\n12161\n12162\n12163\n12164\n12165\n12166\n12167\n12168\n12169\n12170\n12171\n12172\n12173\n12174\n12175\n12176\n12177\n12178\n12179\n12180\n12181\n12182\n12183\n12184\n12185\n12186\n12187\n12188\n12189\n12190\n12191\n12192\n12193\n12194\n12195\n12196\n12197\n12198\n12199\n12200\n12201\n12202\n12203\n12204\n12205\n12206\n12207\n12208\n12209\n12210\n12211\n12212\n12213\n12214\n12215\n12216\n12217\n12218\n12219\n12220\n12221\n12222\n12223\n12224\n12225\n12226\n12227\n12228\n12229\n12230\n12231\n12232\n12233\n12234\n12235\n12236\n12237\n12238\n12239\n12240\n12241\n12242\n12243\n12244\n12245\n12246\n12247\n12248\n12249\n12250\n12251\n12252\n12253\n12254\n12255\n12256\n12257\n12258\n12259\n12260\n12261\n12262\n12263\n12264\n12265\n12266\n12267\n12268\n12269\n12270\n12271\n12272\n12273\n12274\n12275\n12276\n12277\n12278\n12279\n12280\n12281\n12282\n12283\n12284\n12285\n12286\n12287\n12288\n12289\n12290\n12291\n12292\n12293\n12294\n12295\n12296\n12297\n12298\n12299\n12300\n12301\n12302\n12303\n12304\n12305\n12306\n12307\n12308\n12309\n12310\n12311\n12312\n12313\n12314\n12315\n12316\n12317\n12318\n12319\n12320\n12321\n12322\n12323\n12324\n12325\n12326\n12327\n12328\n12329\n12330\n12331\n12332\n12333\n12334\n12335\n12336\n12337\n12338\n12339\n12340\n12341\n12342\n12343\n12344\n12345\n12346\n12347\n12348\n12349\n12350\n12351\n12352\n12353\n12354\n12355\n12356\n12357\n12358\n12359\n12360\n12361\n12362\n12363\n12364\n12365\n12366\n12367\n12368\n12369\n12370\n12371\n12372\n12373\n12374\n12375\n12376\n12377\n12378\n12379\n12380\n12381\n12382\n12383\n12384\n12385\n12386\n12387\n12388\n12389\n12390\n12391\n12392\n12393\n12394\n12395\n12396\n12397\n12398\n12399\n12400\n12401\n12402\n12403\n12404\n12405\n12406\n12407\n12408\n12409\n12410\n12411\n12412\n12413\n12414\n12415\n12416\n12417\n12418\n12419\n12420\n12421\n12422\n12423\n12424\n12425\n12426\n12427\n12428\n12429\n12430\n12431\n12432\n12433\n12434\n12435\n12436\n12437\n12438\n12439\n12440\n12441\n12442\n12443\n12444\n12445\n12446\n12447\n12448\n12449\n12450\n12451\n12452\n12453\n12454\n12455\n12456\n12457\n12458\n12459\n12460\n12461\n12462\n12463\n12464\n12465\n12466\n12467\n12468\n12469\n12470\n12471\n12472\n12473\n12474\n12475\n12476\n12477\n12478\n12479\n12480\n12481\n12482\n12483\n12484\n12485\n12486\n12487\n12488\n12489\n12490\n12491\n12492\n12493\n12494\n12495\n12496\n12497\n12498\n12499\n12500\n12501\n12502\n12503\n12504\n12505\n12506\n12507\n12508\n12509\n12510\n12511\n12512\n12513\n12514\n12515\n12516\n12517\n12518\n12519\n12520\n12521\n12522\n12523\n12524\n12525\n12526\n12527\n12528\n12529\n12530\n12531\n12532\n12533\n12534\n12535\n12536\n12537\n12538\n12539\n12540\n12541\n12542\n12543\n12544\n12545\n12546\n12547\n12548\n12549\n12550\n12551\n12552\n12553\n12554\n12555\n12556\n12557\n12558\n12559\n12560\n12561\n12562\n12563\n12564\n12565\n12566\n12567\n12568\n12569\n12570\n12571\n12572\n12573\n12574\n12575\n12576\n12577\n12578\n12579\n12580\n12581\n12582\n12583\n12584\n12585\n12586\n12587\n12588\n12589\n12590\n12591\n12592\n12593\n12594\n12595\n12596\n12597\n12598\n12599\n12600\n12601\n12602\n12603\n12604\n12605\n12606\n12607\n12608\n12609\n12610\n12611\n12612\n12613\n12614\n12615\n12616\n12617\n12618\n12619\n12620\n12621\n12622\n12623\n12624\n12625\n12626\n12627\n12628\n12629\n12630\n12631\n12632\n12633\n12634\n12635\n12636\n12637\n12638\n12639\n12640\n12641\n12642\n12643\n12644\n12645\n12646\n12647\n12648\n12649\n12650\n12651\n12652\n12653\n12654\n12655\n12656\n12657\n12658\n12659\n12660\n12661\n12662\n12663\n12664\n12665\n12666\n12667\n12668\n12669\n12670\n12671\n12672\n12673\n12674\n12675\n12676\n12677\n12678\n12679\n12680\n12681\n12682\n12683\n12684\n12685\n12686\n12687\n12688\n12689\n12690\n12691\n12692\n12693\n12694\n12695\n12696\n12697\n12698\n12699\n12700\n12701\n12702\n12703\n12704\n12705\n12706\n12707\n12708\n12709\n12710\n12711\n12712\n12713\n12714\n12715\n12716\n12717\n12718\n12719\n12720\n12721\n12722\n12723\n12724\n12725\n12726\n12727\n12728\n12729\n12730\n12731\n12732\n12733\n12734\n12735\n12736\n12737\n12738\n12739\n12740\n12741\n12742\n12743\n12744\n12745\n12746\n12747\n12748\n12749\n12750\n12751\n12752\n12753\n12754\n12755\n12756\n12757\n12758\n12759\n12760\n12761\n12762\n12763\n12764\n12765\n12766\n12767\n12768\n12769\n12770\n12771\n12772\n12773\n12774\n12775\n12776\n12777\n12778\n12779\n12780\n12781\n12782\n12783\n12784\n12785\n12786\n12787\n12788\n12789\n12790\n12791\n12792\n12793\n12794\n12795\n12796\n12797\n12798\n12799\n12800\n12801\n12802\n12803\n12804\n12805\n12806\n12807\n12808\n12809\n12810\n12811\n12812\n12813\n12814\n12815\n12816\n12817\n12818\n12819\n12820\n12821\n12822\n12823\n12824\n12825\n12826\n12827\n12828\n12829\n12830\n12831\n12832\n12833\n12834\n12835\n12836\n12837\n12838\n12839\n12840\n12841\n12842\n12843\n12844\n12845\n12846\n12847\n12848\n12849\n12850\n12851\n12852\n12853\n12854\n12855\n12856\n12857\n12858\n12859\n12860\n12861\n12862\n12863\n12864\n12865\n12866\n12867\n12868\n12869\n12870\n12871\n12872\n12873\n12874\n12875\n12876\n12877\n12878\n12879\n12880\n12881\n12882\n12883\n12884\n12885\n12886\n12887\n12888\n12889\n12890\n12891\n12892\n12893\n12894\n12895\n12896\n12897\n12898\n12899\n12900\n12901\n12902\n12903\n12904\n12905\n12906\n12907\n12908\n12909\n12910\n12911\n12912\n12913\n12914\n12915\n12916\n12917\n12918\n12919\n12920\n12921\n12922\n12923\n12924\n12925\n12926\n12927\n12928\n12929\n12930\n12931\n12932\n12933\n12934\n12935\n12936\n12937\n12938\n12939\n12940\n12941\n12942\n12943\n12944\n12945\n12946\n12947\n12948\n12949\n12950\n12951\n12952\n12953\n12954\n12955\n12956\n12957\n12958\n12959\n12960\n12961\n12962\n12963\n12964\n12965\n12966\n12967\n12968\n12969\n12970\n12971\n12972\n12973\n12974\n12975\n12976\n12977\n12978\n12979\n12980\n12981\n12982\n12983\n12984\n12985\n12986\n12987\n12988\n12989\n12990\n12991\n12992\n12993\n12994\n12995\n12996\n12997\n12998\n12999\n13000\n13001\n13002\n13003\n13004\n13005\n13006\n13007\n13008\n13009\n13010\n13011\n13012\n13013\n13014\n13015\n13016\n13017\n13018\n13019\n13020\n13021\n13022\n13023\n13024\n13025\n13026\n13027\n13028\n13029\n13030\n13031\n13032\n13033\n13034\n13035\n13036\n13037\n13038\n13039\n13040\n13041\n13042\n13043\n13044\n13045\n13046\n13047\n13048\n13049\n13050\n13051\n13052\n13053\n13054\n13055\n13056\n13057\n13058\n13059\n13060\n13061\n13062\n13063\n13064\n13065\n13066\n13067\n13068\n13069\n13070\n13071\n13072\n13073\n13074\n13075\n13076\n13077\n13078\n13079\n13080\n13081\n13082\n13083\n13084\n13085\n13086\n13087\n13088\n13089\n13090\n13091\n13092\n13093\n13094\n13095\n13096\n13097\n13098\n13099\n13100\n13101\n13102\n13103\n13104\n13105\n13106\n13107\n13108\n13109\n13110\n13111\n13112\n13113\n13114\n13115\n13116\n13117\n13118\n13119\n13120\n13121\n13122\n13123\n13124\n13125\n13126\n13127\n13128\n13129\n13130\n13131\n13132\n13133\n13134\n13135\n13136\n13137\n13138\n13139\n13140\n13141\n13142\n13143\n13144\n13145\n13146\n13147\n13148\n13149\n13150\n13151\n13152\n13153\n13154\n13155\n13156\n13157\n13158\n13159\n13160\n13161\n13162\n13163\n13164\n13165\n13166\n13167\n13168\n13169\n13170\n13171\n13172\n13173\n13174\n13175\n13176\n13177\n13178\n13179\n13180\n13181\n13182\n13183\n13184\n13185\n13186\n13187\n13188\n13189\n13190\n13191\n13192\n13193\n13194\n13195\n13196\n13197\n13198\n13199\n13200\n13201\n13202\n13203\n13204\n13205\n13206\n13207\n13208\n13209\n13210\n13211\n13212\n13213\n13214\n13215\n13216\n13217\n13218\n13219\n13220\n13221\n13222\n13223\n13224\n13225\n13226\n13227\n13228\n13229\n13230\n13231\n13232\n13233\n13234\n13235\n13236\n13237\n13238\n13239\n13240\n13241\n13242\n13243\n13244\n13245\n13246\n13247\n13248\n13249\n13250\n13251\n13252\n13253\n13254\n13255\n13256\n13257\n13258\n13259\n13260\n13261\n13262\n13263\n13264\n13265\n13266\n13267\n13268\n13269\n13270\n13271\n13272\n13273\n13274\n13275\n13276\n13277\n13278\n13279\n13280\n13281\n13282\n13283\n13284\n13285\n13286\n13287\n13288\n13289\n13290\n13291\n13292\n13293\n13294\n13295\n13296\n13297\n13298\n13299\n13300\n13301\n13302\n13303\n13304\n13305\n13306\n13307\n13308\n13309\n13310\n13311\n13312\n13313\n13314\n13315\n13316\n13317\n13318\n13319\n13320\n13321\n13322\n13323\n13324\n13325\n13326\n13327\n13328\n13329\n13330\n13331\n13332\n13333\n13334\n13335\n13336\n13337\n13338\n13339\n13340\n13341\n13342\n13343\n13344\n13345\n13346\n13347\n13348\n13349\n13350\n13351\n13352\n13353\n13354\n13355\n13356\n13357\n13358\n13359\n13360\n13361\n13362\n13363\n13364\n13365\n13366\n13367\n13368\n13369\n13370\n13371\n13372\n13373\n13374\n13375\n13376\n13377\n13378\n13379\n13380\n13381\n13382\n13383\n13384\n13385\n13386\n13387\n13388\n13389\n13390\n13391\n13392\n13393\n13394\n13395\n13396\n13397\n13398\n13399\n13400\n13401\n13402\n13403\n13404\n13405\n13406\n13407\n13408\n13409\n13410\n13411\n13412\n13413\n13414\n13415\n13416\n13417\n13418\n13419\n13420\n13421\n13422\n13423\n13424\n13425\n13426\n13427\n13428\n13429\n13430\n13431\n13432\n13433\n13434\n13435\n13436\n13437\n13438\n13439\n13440\n13441\n13442\n13443\n13444\n13445\n13446\n13447\n13448\n13449\n13450\n13451\n13452\n13453\n13454\n13455\n13456\n13457\n13458\n13459\n13460\n13461\n13462\n13463\n13464\n13465\n13466\n13467\n13468\n13469\n13470\n13471\n13472\n13473\n13474\n13475\n13476\n13477\n13478\n13479\n13480\n13481\n13482\n13483\n13484\n13485\n13486\n13487\n13488\n13489\n13490\n13491\n13492\n13493\n13494\n13495\n13496\n13497\n13498\n13499\n13500\n13501\n13502\n13503\n13504\n13505\n13506\n13507\n13508\n13509\n13510\n13511\n13512\n13513\n13514\n13515\n13516\n13517\n13518\n13519\n13520\n13521\n13522\n13523\n13524\n13525\n13526\n13527\n13528\n13529\n13530\n13531\n13532\n13533\n13534\n13535\n13536\n13537\n13538\n13539\n13540\n13541\n13542\n13543\n13544\n13545\n13546\n13547\n13548\n13549\n13550\n13551\n13552\n13553\n13554\n13555\n13556\n13557\n13558\n13559\n13560\n13561\n13562\n13563\n13564\n13565\n13566\n13567\n13568\n13569\n13570\n13571\n13572\n13573\n13574\n13575\n13576\n13577\n13578\n13579\n13580\n13581\n13582\n13583\n13584\n13585\n13586\n13587\n13588\n13589\n13590\n13591\n13592\n13593\n13594\n13595\n13596\n13597\n13598\n13599\n13600\n13601\n13602\n13603\n13604\n13605\n13606\n13607\n13608\n13609\n13610\n13611\n13612\n13613\n13614\n13615\n13616\n13617\n13618\n13619\n13620\n13621\n13622\n13623\n13624\n13625\n13626\n13627\n13628\n13629\n13630\n13631\n13632\n13633\n13634\n13635\n13636\n13637\n13638\n13639\n13640\n13641\n13642\n13643\n13644\n13645\n13646\n13647\n13648\n13649\n13650\n13651\n13652\n13653\n13654\n13655\n13656\n13657\n13658\n13659\n13660\n13661\n13662\n13663\n13664\n13665\n13666\n13667\n13668\n13669\n13670\n13671\n13672\n13673\n13674\n13675\n13676\n13677\n13678\n13679\n13680\n13681\n13682\n13683\n13684\n13685\n13686\n13687\n13688\n13689\n13690\n13691\n13692\n13693\n13694\n13695\n13696\n13697\n13698\n13699\n13700\n13701\n13702\n13703\n13704\n13705\n13706\n13707\n13708\n13709\n13710\n13711\n13712\n13713\n13714\n13715\n13716\n13717\n13718\n13719\n13720\n13721\n13722\n13723\n13724\n13725\n13726\n13727\n13728\n13729\n13730\n13731\n13732\n13733\n13734\n13735\n13736\n13737\n13738\n13739\n13740\n13741\n13742\n13743\n13744\n13745\n13746\n13747\n13748\n13749\n13750\n13751\n13752\n13753\n13754\n13755\n13756\n13757\n13758\n13759\n13760\n13761\n13762\n13763\n13764\n13765\n13766\n13767\n13768\n13769\n13770\n13771\n13772\n13773\n13774\n13775\n13776\n13777\n13778\n13779\n13780\n13781\n13782\n13783\n13784\n13785\n13786\n13787\n13788\n13789\n13790\n13791\n13792\n13793\n13794\n13795\n13796\n13797\n13798\n13799\n13800\n13801\n13802\n13803\n13804\n13805\n13806\n13807\n13808\n13809\n13810\n13811\n13812\n13813\n13814\n13815\n13816\n13817\n13818\n13819\n13820\n13821\n13822\n13823\n13824\n13825\n13826\n13827\n13828\n13829\n13830\n13831\n13832\n13833\n13834\n13835\n13836\n13837\n13838\n13839\n13840\n13841\n13842\n13843\n13844\n13845\n13846\n13847\n13848\n13849\n13850\n13851\n13852\n13853\n13854\n13855\n13856\n13857\n13858\n13859\n13860\n13861\n13862\n13863\n13864\n13865\n13866\n13867\n13868\n13869\n13870\n13871\n13872\n13873\n13874\n13875\n13876\n13877\n13878\n13879\n13880\n13881\n13882\n13883\n13884\n13885\n13886\n13887\n13888\n13889\n13890\n13891\n13892\n13893\n13894\n13895\n13896\n13897\n13898\n13899\n13900\n13901\n13902\n13903\n13904\n13905\n13906\n13907\n13908\n13909\n13910\n13911\n13912\n13913\n13914\n13915\n13916\n13917\n13918\n13919\n13920\n13921\n13922\n13923\n13924\n13925\n13926\n13927\n13928\n13929\n13930\n13931\n13932\n13933\n13934\n13935\n13936\n13937\n13938\n13939\n13940\n13941\n13942\n13943\n13944\n13945\n13946\n13947\n13948\n13949\n13950\n13951\n13952\n13953\n13954\n13955\n13956\n13957\n13958\n13959\n13960\n13961\n13962\n13963\n13964\n13965\n13966\n13967\n13968\n13969\n13970\n13971\n13972\n13973\n13974\n13975\n13976\n13977\n13978\n13979\n13980\n13981\n13982\n13983\n13984\n13985\n13986\n13987\n13988\n13989\n13990\n13991\n13992\n13993\n13994\n13995\n13996\n13997\n13998\n13999\n14000\n14001\n14002\n14003\n14004\n14005\n14006\n14007\n14008\n14009\n14010\n14011\n14012\n14013\n14014\n14015\n14016\n14017\n14018\n14019\n14020\n14021\n14022\n14023\n14024\n14025\n14026\n14027\n14028\n14029\n14030\n14031\n14032\n14033\n14034\n14035\n14036\n14037\n14038\n14039\n14040\n14041\n14042\n14043\n14044\n14045\n14046\n14047\n14048\n14049\n14050\n14051\n14052\n14053\n14054\n14055\n14056\n14057\n14058\n14059\n14060\n14061\n14062\n14063\n14064\n14065\n14066\n14067\n14068\n14069\n14070\n14071\n14072\n14073\n14074\n14075\n14076\n14077\n14078\n14079\n14080\n14081\n14082\n14083\n14084\n14085\n14086\n14087\n14088\n14089\n14090\n14091\n14092\n14093\n14094\n14095\n14096\n14097\n14098\n14099\n14100\n14101\n14102\n14103\n14104\n14105\n14106\n14107\n14108\n14109\n14110\n14111\n14112\n14113\n14114\n14115\n14116\n14117\n14118\n14119\n14120\n14121\n14122\n14123\n14124\n14125\n14126\n14127\n14128\n14129\n14130\n14131\n14132\n14133\n14134\n14135\n14136\n14137\n14138\n14139\n14140\n14141\n14142\n14143\n14144\n14145\n14146\n14147\n14148\n14149\n14150\n14151\n14152\n14153\n14154\n14155\n14156\n14157\n14158\n14159\n14160\n14161\n14162\n14163\n14164\n14165\n14166\n14167\n14168\n14169\n14170\n14171\n14172\n14173\n14174\n14175\n14176\n14177\n14178\n14179\n14180\n14181\n14182\n14183\n14184\n14185\n14186\n14187\n14188\n14189\n14190\n14191\n14192\n14193\n14194\n14195\n14196\n14197\n14198\n14199\n14200\n14201\n14202\n14203\n14204\n14205\n14206\n14207\n14208\n14209\n14210\n14211\n14212\n14213\n14214\n14215\n14216\n14217\n14218\n14219\n14220\n14221\n14222\n14223\n14224\n14225\n14226\n14227\n14228\n14229\n14230\n14231\n14232\n14233\n14234\n14235\n14236\n14237\n14238\n14239\n14240\n14241\n14242\n14243\n14244\n14245\n14246\n14247\n14248\n14249\n14250\n14251\n14252\n14253\n14254\n14255\n14256\n14257\n14258\n14259\n14260\n14261\n14262\n14263\n14264\n14265\n14266\n14267\n14268\n14269\n14270\n14271\n14272\n14273\n14274\n14275\n14276\n14277\n14278\n14279\n14280\n14281\n14282\n14283\n14284\n14285\n14286\n14287\n14288\n14289\n14290\n14291\n14292\n14293\n14294\n14295\n14296\n14297\n14298\n14299\n14300\n14301\n14302\n14303\n14304\n14305\n14306\n14307\n14308\n14309\n14310\n14311\n14312\n14313\n14314\n14315\n14316\n14317\n14318\n14319\n14320\n14321\n14322\n14323\n14324\n14325\n14326\n14327\n14328\n14329\n14330\n14331\n14332\n14333\n14334\n14335\n14336\n14337\n14338\n14339\n14340\n14341\n14342\n14343\n14344\n14345\n14346\n14347\n14348\n14349\n14350\n14351\n14352\n14353\n14354\n14355\n14356\n14357\n14358\n14359\n14360\n14361\n14362\n14363\n14364\n14365\n14366\n14367\n14368\n14369\n14370\n14371\n14372\n14373\n14374\n14375\n14376\n14377\n14378\n14379\n14380\n14381\n14382\n14383\n14384\n14385\n14386\n14387\n14388\n14389\n14390\n14391\n14392\n14393\n14394\n14395\n14396\n14397\n14398\n14399\n14400\n14401\n14402\n14403\n14404\n14405\n14406\n14407\n14408\n14409\n14410\n14411\n14412\n14413\n14414\n14415\n14416\n14417\n14418\n14419\n14420\n14421\n14422\n14423\n14424\n14425\n14426\n14427\n14428\n14429\n14430\n14431\n14432\n14433\n14434\n14435\n14436\n14437\n14438\n14439\n14440\n14441\n14442\n14443\n14444\n14445\n14446\n14447\n14448\n14449\n14450\n14451\n14452\n14453\n14454\n14455\n14456\n14457\n14458\n14459\n14460\n14461\n14462\n14463\n14464\n14465\n14466\n14467\n14468\n14469\n14470\n14471\n14472\n14473\n14474\n14475\n14476\n14477\n14478\n14479\n14480\n14481\n14482\n14483\n14484\n14485\n14486\n14487\n14488\n14489\n14490\n14491\n14492\n14493\n14494\n14495\n14496\n14497\n14498\n14499\n14500\n14501\n14502\n14503\n14504\n14505\n14506\n14507\n14508\n14509\n14510\n14511\n14512\n14513\n14514\n14515\n14516\n14517\n14518\n14519\n14520\n14521\n14522\n14523\n14524\n14525\n14526\n14527\n14528\n14529\n14530\n14531\n14532\n14533\n14534\n14535\n14536\n14537\n14538\n14539\n14540\n14541\n14542\n14543\n14544\n14545\n14546\n14547\n14548\n14549\n14550\n14551\n14552\n14553\n14554\n14555\n14556\n14557\n14558\n14559\n14560\n14561\n14562\n14563\n14564\n14565\n14566\n14567\n14568\n14569\n14570\n14571\n14572\n14573\n14574\n14575\n14576\n14577\n14578\n14579\n14580\n14581\n14582\n14583\n14584\n14585\n14586\n14587\n14588\n14589\n14590\n14591\n14592\n14593\n14594\n14595\n14596\n14597\n14598\n14599\n14600\n14601\n14602\n14603\n14604\n14605\n14606\n14607\n14608\n14609\n14610\n14611\n14612\n14613\n14614\n14615\n14616\n14617\n14618\n14619\n14620\n14621\n14622\n14623\n14624\n14625\n14626\n14627\n14628\n14629\n14630\n14631\n14632\n14633\n14634\n14635\n14636\n14637\n14638\n14639\n14640\n14641\n14642\n14643\n14644\n14645\n14646\n14647\n14648\n14649\n14650\n14651\n14652\n14653\n14654\n14655\n14656\n14657\n14658\n14659\n14660\n14661\n14662\n14663\n14664\n14665\n14666\n14667\n14668\n14669\n14670\n14671\n14672\n14673\n14674\n14675\n14676\n14677\n14678\n14679\n14680\n14681\n14682\n14683\n14684\n14685\n14686\n14687\n14688\n14689\n14690\n14691\n14692\n14693\n14694\n14695\n14696\n14697\n14698\n14699\n14700\n14701\n14702\n14703\n14704\n14705\n14706\n14707\n14708\n14709\n14710\n14711\n14712\n14713\n14714\n14715\n14716\n14717\n14718\n14719\n14720\n14721\n14722\n14723\n14724\n14725\n14726\n14727\n14728\n14729\n14730\n14731\n14732\n14733\n14734\n14735\n14736\n14737\n14738\n14739\n14740\n14741\n14742\n14743\n14744\n14745\n14746\n14747\n14748\n14749\n14750\n14751\n14752\n14753\n14754\n14755\n14756\n14757\n14758\n14759\n14760\n14761\n14762\n14763\n14764\n14765\n14766\n14767\n14768\n14769\n14770\n14771\n14772\n14773\n14774\n14775\n14776\n14777\n14778\n14779\n14780\n14781\n14782\n14783\n14784\n14785\n14786\n14787\n14788\n14789\n14790\n14791\n14792\n14793\n14794\n14795\n14796\n14797\n14798\n14799\n14800\n14801\n14802\n14803\n14804\n14805\n14806\n14807\n14808\n14809\n14810\n14811\n14812\n14813\n14814\n14815\n14816\n14817\n14818\n14819\n14820\n14821\n14822\n14823\n14824\n14825\n14826\n14827\n14828\n14829\n14830\n14831\n14832\n14833\n14834\n14835\n14836\n14837\n14838\n14839\n14840\n14841\n14842\n14843\n14844\n14845\n14846\n14847\n14848\n14849\n14850\n14851\n14852\n14853\n14854\n14855\n14856\n14857\n14858\n14859\n14860\n14861\n14862\n14863\n14864\n14865\n14866\n14867\n14868\n14869\n14870\n14871\n14872\n14873\n14874\n14875\n14876\n14877\n14878\n14879\n14880\n14881\n14882\n14883\n14884\n14885\n14886\n14887\n14888\n14889\n14890\n14891\n14892\n14893\n14894\n14895\n14896\n14897\n14898\n14899\n14900\n14901\n14902\n14903\n14904\n14905\n14906\n14907\n14908\n14909\n14910\n14911\n14912\n14913\n14914\n14915\n14916\n14917\n14918\n14919\n14920\n14921\n14922\n14923\n14924\n14925\n14926\n14927\n14928\n14929\n14930\n14931\n14932\n14933\n14934\n14935\n14936\n14937\n14938\n14939\n14940\n14941\n14942\n14943\n14944\n14945\n14946\n14947\n14948\n14949\n14950\n14951\n14952\n14953\n14954\n14955\n14956\n14957\n14958\n14959\n14960\n14961\n14962\n14963\n14964\n14965\n14966\n14967\n14968\n14969\n14970\n14971\n14972\n14973\n14974\n14975\n14976\n14977\n14978\n14979\n14980\n14981\n14982\n14983\n14984\n14985\n14986\n14987\n14988\n14989\n14990\n14991\n14992\n14993\n14994\n14995\n14996\n14997\n14998\n14999\n15000\n15001\n15002\n15003\n15004\n15005\n15006\n15007\n15008\n15009\n15010\n15011\n15012\n15013\n15014\n15015\n15016\n15017\n15018\n15019\n15020\n15021\n15022\n15023\n15024\n15025\n15026\n15027\n15028\n15029\n15030\n15031\n15032\n15033\n15034\n15035\n15036\n15037\n15038\n15039\n15040\n15041\n15042\n15043\n15044\n15045\n15046\n15047\n15048\n15049\n15050\n15051\n15052\n15053\n15054\n15055\n15056\n15057\n15058\n15059\n15060\n15061\n15062\n15063\n15064\n15065\n15066\n15067\n15068\n15069\n15070\n15071\n15072\n15073\n15074\n15075\n15076\n15077\n15078\n15079\n15080\n15081\n15082\n15083\n15084\n15085\n15086\n15087\n15088\n15089\n15090\n15091\n15092\n15093\n15094\n15095\n15096\n15097\n15098\n15099\n15100\n15101\n15102\n15103\n15104\n15105\n15106\n15107\n15108\n15109\n15110\n15111\n15112\n15113\n15114\n15115\n15116\n15117\n15118\n15119\n15120\n15121\n15122\n15123\n15124\n15125\n15126\n15127\n15128\n15129\n15130\n15131\n15132\n15133\n15134\n15135\n15136\n15137\n15138\n15139\n15140\n15141\n15142\n15143\n15144\n15145\n15146\n15147\n15148\n15149\n15150\n15151\n15152\n15153\n15154\n15155\n15156\n15157\n15158\n15159\n15160\n15161\n15162\n15163\n15164\n15165\n15166\n15167\n15168\n15169\n15170\n15171\n15172\n15173\n15174\n15175\n15176\n15177\n15178\n15179\n15180\n15181\n15182\n15183\n15184\n15185\n15186\n15187\n15188\n15189\n15190\n15191\n15192\n15193\n15194\n15195\n15196\n15197\n15198\n15199\n15200\n15201\n15202\n15203\n15204\n15205\n15206\n15207\n15208\n15209\n15210\n15211\n15212\n15213\n15214\n15215\n15216\n15217\n15218\n15219\n15220\n15221\n15222\n15223\n15224\n15225\n15226\n15227\n15228\n15229\n15230\n15231\n15232\n15233\n15234\n15235\n15236\n15237\n15238\n15239\n15240\n15241\n15242\n15243\n15244\n15245\n15246\n15247\n15248\n15249\n15250\n15251\n15252\n15253\n15254\n15255\n15256\n15257\n15258\n15259\n15260\n15261\n15262\n15263\n15264\n15265\n15266\n15267\n15268\n15269\n15270\n15271\n15272\n15273\n15274\n15275\n15276\n15277\n15278\n15279\n15280\n15281\n15282\n15283\n15284\n15285\n15286\n15287\n15288\n15289\n15290\n15291\n15292\n15293\n15294\n15295\n15296\n15297\n15298\n15299\n15300\n15301\n15302\n15303\n15304\n15305\n15306\n15307\n15308\n15309\n15310\n15311\n15312\n15313\n15314\n15315\n15316\n15317\n15318\n15319\n15320\n15321\n15322\n15323\n15324\n15325\n15326\n15327\n15328\n15329\n15330\n15331\n15332\n15333\n15334\n15335\n15336\n15337\n15338\n15339\n15340\n15341\n15342\n15343\n15344\n15345\n15346\n15347\n15348\n15349\n15350\n15351\n15352\n15353\n15354\n15355\n15356\n15357\n15358\n15359\n15360\n15361\n15362\n15363\n15364\n15365\n15366\n15367\n15368\n15369\n15370\n15371\n15372\n15373\n15374\n15375\n15376\n15377\n15378\n15379\n15380\n15381\n15382\n15383\n15384\n15385\n15386\n15387\n15388\n15389\n15390\n15391\n15392\n15393\n15394\n15395\n15396\n15397\n15398\n15399\n15400\n15401\n15402\n15403\n15404\n15405\n15406\n15407\n15408\n15409\n15410\n15411\n15412\n15413\n15414\n15415\n15416\n15417\n15418\n15419\n15420\n15421\n15422\n15423\n15424\n15425\n15426\n15427\n15428\n15429\n15430\n15431\n15432\n15433\n15434\n15435\n15436\n15437\n15438\n15439\n15440\n15441\n15442\n15443\n15444\n15445\n15446\n15447\n15448\n15449\n15450\n15451\n15452\n15453\n15454\n15455\n15456\n15457\n15458\n15459\n15460\n15461\n15462\n15463\n15464\n15465\n15466\n15467\n15468\n15469\n15470\n15471\n15472\n15473\n15474\n15475\n15476\n15477\n15478\n15479\n15480\n15481\n15482\n15483\n15484\n15485\n15486\n15487\n15488\n15489\n15490\n15491\n15492\n15493\n15494\n15495\n15496\n15497\n15498\n15499\n15500\n15501\n15502\n15503\n15504\n15505\n15506\n15507\n15508\n15509\n15510\n15511\n15512\n15513\n15514\n15515\n15516\n15517\n15518\n15519\n15520\n15521\n15522\n15523\n15524\n15525\n15526\n15527\n15528\n15529\n15530\n15531\n15532\n15533\n15534\n15535\n15536\n15537\n15538\n15539\n15540\n15541\n15542\n15543\n15544\n15545\n15546\n15547\n15548\n15549\n15550\n15551\n15552\n15553\n15554\n15555\n15556\n15557\n15558\n15559\n15560\n15561\n15562\n15563\n15564\n15565\n15566\n15567\n15568\n15569\n15570\n15571\n15572\n15573\n15574\n15575\n15576\n15577\n15578\n15579\n15580\n15581\n15582\n15583\n15584\n15585\n15586\n15587\n15588\n15589\n15590\n15591\n15592\n15593\n15594\n15595\n15596\n15597\n15598\n15599\n15600\n15601\n15602\n15603\n15604\n15605\n15606\n15607\n15608\n15609\n15610\n15611\n15612\n15613\n15614\n15615\n15616\n15617\n15618\n15619\n15620\n15621\n15622\n15623\n15624\n15625\n15626\n15627\n15628\n15629\n15630\n15631\n15632\n15633\n15634\n15635\n15636\n15637\n15638\n15639\n15640\n15641\n15642\n15643\n15644\n15645\n15646\n15647\n15648\n15649\n15650\n15651\n15652\n15653\n15654\n15655\n15656\n15657\n15658\n15659\n15660\n15661\n15662\n15663\n15664\n15665\n15666\n15667\n15668\n15669\n15670\n15671\n15672\n15673\n15674\n15675\n15676\n15677\n15678\n15679\n15680\n15681\n15682\n15683\n15684\n15685\n15686\n15687\n15688\n15689\n15690\n15691\n15692\n15693\n15694\n15695\n15696\n15697\n15698\n15699\n15700\n15701\n15702\n15703\n15704\n15705\n15706\n15707\n15708\n15709\n15710\n15711\n15712\n15713\n15714\n15715\n15716\n15717\n15718\n15719\n15720\n15721\n15722\n15723\n15724\n15725\n15726\n15727\n15728\n15729\n15730\n15731\n15732\n15733\n15734\n15735\n15736\n15737\n15738\n15739\n15740\n15741\n15742\n15743\n15744\n15745\n15746\n15747\n15748\n15749\n15750\n15751\n15752\n15753\n15754\n15755\n15756\n15757\n15758\n15759\n15760\n15761\n15762\n15763\n15764\n15765\n15766\n15767\n15768\n15769\n15770\n15771\n15772\n15773\n15774\n15775\n15776\n15777\n15778\n15779\n15780\n15781\n15782\n15783\n15784\n15785\n15786\n15787\n15788\n15789\n15790\n15791\n15792\n15793\n15794\n15795\n15796\n15797\n15798\n15799\n15800\n15801\n15802\n15803\n15804\n15805\n15806\n15807\n15808\n15809\n15810\n15811\n15812\n15813\n15814\n15815\n15816\n15817\n15818\n15819\n15820\n15821\n15822\n15823\n15824\n15825\n15826\n15827\n15828\n15829\n15830\n15831\n15832\n15833\n15834\n15835\n15836\n15837\n15838\n15839\n15840\n15841\n15842\n15843\n15844\n15845\n15846\n15847\n15848\n15849\n15850\n15851\n15852\n15853\n15854\n15855\n15856\n15857\n15858\n15859\n15860\n15861\n15862\n15863\n15864\n15865\n15866\n15867\n15868\n15869\n15870\n15871\n15872\n15873\n15874\n15875\n15876\n15877\n15878\n15879\n15880\n15881\n15882\n15883\n15884\n15885\n15886\n15887\n15888\n15889\n15890\n15891\n15892\n15893\n15894\n15895\n15896\n15897\n15898\n15899\n15900\n15901\n15902\n15903\n15904\n15905\n15906\n15907\n15908\n15909\n15910\n15911\n15912\n15913\n15914\n15915\n15916\n15917\n15918\n15919\n15920\n15921\n15922\n15923\n15924\n15925\n15926\n15927\n15928\n15929\n15930\n15931\n15932\n15933\n15934\n15935\n15936\n15937\n15938\n15939\n15940\n15941\n15942\n15943\n15944\n15945\n15946\n15947\n15948\n15949\n15950\n15951\n15952\n15953\n15954\n15955\n15956\n15957\n15958\n15959\n15960\n15961\n15962\n15963\n15964\n15965\n15966\n15967\n15968\n15969\n15970\n15971\n15972\n15973\n15974\n15975\n15976\n15977\n15978\n15979\n15980\n15981\n15982\n15983\n15984\n15985\n15986\n15987\n15988\n15989\n15990\n15991\n15992\n15993\n15994\n15995\n15996\n15997\n15998\n15999\n16000\n16001\n16002\n16003\n16004\n16005\n16006\n16007\n16008\n16009\n16010\n16011\n16012\n16013\n16014\n16015\n16016\n16017\n16018\n16019\n16020\n16021\n16022\n16023\n16024\n16025\n16026\n16027\n16028\n16029\n16030\n16031\n16032\n16033\n16034\n16035\n16036\n16037\n16038\n16039\n16040\n16041\n16042\n16043\n16044\n16045\n16046\n16047\n16048\n16049\n16050\n16051\n16052\n16053\n16054\n16055\n16056\n16057\n16058\n16059\n16060\n16061\n16062\n16063\n16064\n16065\n16066\n16067\n16068\n16069\n16070\n16071\n16072\n16073\n16074\n16075\n16076\n16077\n16078\n16079\n16080\n16081\n16082\n16083\n16084\n16085\n16086\n16087\n16088\n16089\n16090\n16091\n16092\n16093\n16094\n16095\n16096\n16097\n16098\n16099\n16100\n16101\n16102\n16103\n16104\n16105\n16106\n16107\n16108\n16109\n16110\n16111\n16112\n16113\n16114\n16115\n16116\n16117\n16118\n16119\n16120\n16121\n16122\n16123\n16124\n16125\n16126\n16127\n16128\n16129\n16130\n16131\n16132\n16133\n16134\n16135\n16136\n16137\n16138\n16139\n16140\n16141\n16142\n16143\n16144\n16145\n16146\n16147\n16148\n16149\n16150\n16151\n16152\n16153\n16154\n16155\n16156\n16157\n16158\n16159\n16160\n16161\n16162\n16163\n16164\n16165\n16166\n16167\n16168\n16169\n16170\n16171\n16172\n16173\n16174\n16175\n16176\n16177\n16178\n16179\n16180\n16181\n16182\n16183\n16184\n16185\n16186\n16187\n16188\n16189\n16190\n16191\n16192\n16193\n16194\n16195\n16196\n16197\n16198\n16199\n16200\n16201\n16202\n16203\n16204\n16205\n16206\n16207\n16208\n16209\n16210\n16211\n16212\n16213\n16214\n16215\n16216\n16217\n16218\n16219\n16220\n16221\n16222\n16223\n16224\n16225\n16226\n16227\n16228\n16229\n16230\n16231\n16232\n16233\n16234\n16235\n16236\n16237\n16238\n16239\n16240\n16241\n16242\n16243\n16244\n16245\n16246\n16247\n16248\n16249\n16250\n16251\n16252\n16253\n16254\n16255\n16256\n16257\n16258\n16259\n16260\n16261\n16262\n16263\n16264\n16265\n16266\n16267\n16268\n16269\n16270\n16271\n16272\n16273\n16274\n16275\n16276\n16277\n16278\n16279\n16280\n16281\n16282\n16283\n16284\n16285\n16286\n16287\n16288\n16289\n16290\n16291\n16292\n16293\n16294\n16295\n16296\n16297\n16298\n16299\n16300\n16301\n16302\n16303\n16304\n16305\n16306\n16307\n16308\n16309\n16310\n16311\n16312\n16313\n16314\n16315\n16316\n16317\n16318\n16319\n16320\n16321\n16322\n16323\n16324\n16325\n16326\n16327\n16328\n16329\n16330\n16331\n16332\n16333\n16334\n16335\n16336\n16337\n16338\n16339\n16340\n16341\n16342\n16343\n16344\n16345\n16346\n16347\n16348\n16349\n16350\n16351\n16352\n16353\n16354\n16355\n16356\n16357\n16358\n16359\n16360\n16361\n16362\n16363\n16364\n16365\n16366\n16367\n16368\n16369\n16370\n16371\n16372\n16373\n16374\n16375\n16376\n16377\n16378\n16379\n16380\n16381\n16382\n16383\n16384\n16385\n16386\n16387\n16388\n16389\n16390\n16391\n16392\n16393\n16394\n16395\n16396\n16397\n16398\n16399\n16400\n16401\n16402\n16403\n16404\n16405\n16406\n16407\n16408\n16409\n16410\n16411\n16412\n16413\n16414\n16415\n16416\n16417\n16418\n16419\n16420\n16421\n16422\n16423\n16424\n16425\n16426\n16427\n16428\n16429\n16430\n16431\n16432\n16433\n16434\n16435\n16436\n16437\n16438\n16439\n16440\n16441\n16442\n16443\n16444\n16445\n16446\n16447\n16448\n16449\n16450\n16451\n16452\n16453\n16454\n16455\n16456\n16457\n16458\n16459\n16460\n16461\n16462\n16463\n16464\n16465\n16466\n16467\n16468\n16469\n16470\n16471\n16472\n16473\n16474\n16475\n16476\n16477\n16478\n16479\n16480\n16481\n16482\n16483\n16484\n16485\n16486\n16487\n16488\n16489\n16490\n16491\n16492\n16493\n16494\n16495\n16496\n16497\n16498\n16499\n16500\n16501\n16502\n16503\n16504\n16505\n16506\n16507\n16508\n16509\n16510\n16511\n16512\n16513\n16514\n16515\n16516\n16517\n16518\n16519\n16520\n16521\n16522\n16523\n16524\n16525\n16526\n16527\n16528\n16529\n16530\n16531\n16532\n16533\n16534\n16535\n16536\n16537\n16538\n16539\n16540\n16541\n16542\n16543\n16544\n16545\n16546\n16547\n16548\n16549\n16550\n16551\n16552\n16553\n16554\n16555\n16556\n16557\n16558\n16559\n16560\n16561\n16562\n16563\n16564\n16565\n16566\n16567\n16568\n16569\n16570\n16571\n16572\n16573\n16574\n16575\n16576\n16577\n16578\n16579\n16580\n16581\n16582\n16583\n16584\n16585\n16586\n16587\n16588\n16589\n16590\n16591\n16592\n16593\n16594\n16595\n16596\n16597\n16598\n16599\n16600\n16601\n16602\n16603\n16604\n16605\n16606\n16607\n16608\n16609\n16610\n16611\n16612\n16613\n16614\n16615\n16616\n16617\n16618\n16619\n16620\n16621\n16622\n16623\n16624\n16625\n16626\n16627\n16628\n16629\n16630\n16631\n16632\n16633\n16634\n16635\n16636\n16637\n16638\n16639\n16640\n16641\n16642\n16643\n16644\n16645\n16646\n16647\n16648\n16649\n16650\n16651\n16652\n16653\n16654\n16655\n16656\n16657\n16658\n16659\n16660\n16661\n16662\n16663\n16664\n16665\n16666\n16667\n16668\n16669\n16670\n16671\n16672\n16673\n16674\n16675\n16676\n16677\n16678\n16679\n16680\n16681\n16682\n16683\n16684\n16685\n16686\n16687\n16688\n16689\n16690\n16691\n16692\n16693\n16694\n16695\n16696\n16697\n16698\n16699\n16700\n16701\n16702\n16703\n16704\n16705\n16706\n16707\n16708\n16709\n16710\n16711\n16712\n16713\n16714\n16715\n16716\n16717\n16718\n16719\n16720\n16721\n16722\n16723\n16724\n16725\n16726\n16727\n16728\n16729\n16730\n16731\n16732\n16733\n16734\n16735\n16736\n16737\n16738\n16739\n16740\n16741\n16742\n16743\n16744\n16745\n16746\n16747\n16748\n16749\n16750\n16751\n16752\n16753\n16754\n16755\n16756\n16757\n16758\n16759\n16760\n16761\n16762\n16763\n16764\n16765\n16766\n16767\n16768\n16769\n16770\n16771\n16772\n16773\n16774\n16775\n16776\n16777\n16778\n16779\n16780\n16781\n16782\n16783\n16784\n16785\n16786\n16787\n16788\n16789\n16790\n16791\n16792\n16793\n16794\n16795\n16796\n16797\n16798\n16799\n16800\n16801\n16802\n16803\n16804\n16805\n16806\n16807\n16808\n16809\n16810\n16811\n16812\n16813\n16814\n16815\n16816\n16817\n16818\n16819\n16820\n16821\n16822\n16823\n16824\n16825\n16826\n16827\n16828\n16829\n16830\n16831\n16832\n16833\n16834\n16835\n16836\n16837\n16838\n16839\n16840\n16841\n16842\n16843\n16844\n16845\n16846\n16847\n16848\n16849\n16850\n16851\n16852\n16853\n16854\n16855\n16856\n16857\n16858\n16859\n16860\n16861\n16862\n16863\n16864\n16865\n16866\n16867\n16868\n16869\n16870\n16871\n16872\n16873\n16874\n16875\n16876\n16877\n16878\n16879\n16880\n16881\n16882\n16883\n16884\n16885\n16886\n16887\n16888\n16889\n16890\n16891\n16892\n16893\n16894\n16895\n16896\n16897\n16898\n16899\n16900\n16901\n16902\n16903\n16904\n16905\n16906\n16907\n16908\n16909\n16910\n16911\n16912\n16913\n16914\n16915\n16916\n16917\n16918\n16919\n16920\n16921\n16922\n16923\n16924\n16925\n16926\n16927\n16928\n16929\n16930\n16931\n16932\n16933\n16934\n16935\n16936\n16937\n16938\n16939\n16940\n16941\n16942\n16943\n16944\n16945\n16946\n16947\n16948\n16949\n16950\n16951\n16952\n16953\n16954\n16955\n16956\n16957\n16958\n16959\n16960\n16961\n16962\n16963\n16964\n16965\n16966\n16967\n16968\n16969\n16970\n16971\n16972\n16973\n16974\n16975\n16976\n16977\n16978\n16979\n16980\n16981\n16982\n16983\n16984\n16985\n16986\n16987\n16988\n16989\n16990\n16991\n16992\n16993\n16994\n16995\n16996\n16997\n16998\n16999\n17000\n17001\n17002\n17003\n17004\n17005\n17006\n17007\n17008\n17009\n17010\n17011\n17012\n17013\n17014\n17015\n17016\n17017\n17018\n17019\n17020\n17021\n17022\n17023\n17024\n17025\n17026\n17027\n17028\n17029\n17030\n17031\n17032\n17033\n17034\n17035\n17036\n17037\n17038\n17039\n17040\n17041\n17042\n17043\n17044\n17045\n17046\n17047\n17048\n17049\n17050\n17051\n17052\n17053\n17054\n17055\n17056\n17057\n17058\n17059\n17060\n17061\n17062\n17063\n17064\n17065\n17066\n17067\n17068\n17069\n17070\n17071\n17072\n17073\n17074\n17075\n17076\n17077\n17078\n17079\n17080\n17081\n17082\n17083\n17084\n17085\n17086\n17087\n17088\n17089\n17090\n17091\n17092\n17093\n17094\n17095\n17096\n17097\n17098\n17099\n17100\n17101\n17102\n17103\n17104\n17105\n17106\n17107\n17108\n17109\n17110\n17111\n17112\n17113\n17114\n17115\n17116\n17117\n17118\n17119\n17120\n17121\n17122\n17123\n17124\n17125\n17126\n17127\n17128\n17129\n17130\n17131\n17132\n17133\n17134\n17135\n17136\n17137\n17138\n17139\n17140\n17141\n17142\n17143\n17144\n17145\n17146\n17147\n17148\n17149\n17150\n17151\n17152\n17153\n17154\n17155\n17156\n17157\n17158\n17159\n17160\n17161\n17162\n17163\n17164\n17165\n17166\n17167\n17168\n17169\n17170\n17171\n17172\n17173\n17174\n17175\n17176\n17177\n17178\n17179\n17180\n17181\n17182\n17183\n17184\n17185\n17186\n17187\n17188\n17189\n17190\n17191\n17192\n17193\n17194\n17195\n17196\n17197\n17198\n17199\n17200\n17201\n17202\n17203\n17204\n17205\n17206\n17207\n17208\n17209\n17210\n17211\n17212\n17213\n17214\n17215\n17216\n17217\n17218\n17219\n17220\n17221\n17222\n17223\n17224\n17225\n17226\n17227\n17228\n17229\n17230\n17231\n17232\n17233\n17234\n17235\n17236\n17237\n17238\n17239\n17240\n17241\n17242\n17243\n17244\n17245\n17246\n17247\n17248\n17249\n17250\n17251\n17252\n17253\n17254\n17255\n17256\n17257\n17258\n17259\n17260\n17261\n17262\n17263\n17264\n17265\n17266\n17267\n17268\n17269\n17270\n17271\n17272\n17273\n17274\n17275\n17276\n17277\n17278\n17279\n17280\n17281\n17282\n17283\n17284\n17285\n17286\n17287\n17288\n17289\n17290\n17291\n17292\n17293\n17294\n17295\n17296\n17297\n17298\n17299\n17300\n17301\n17302\n17303\n17304\n17305\n17306\n17307\n17308\n17309\n17310\n17311\n17312\n17313\n17314\n17315\n17316\n17317\n17318\n17319\n17320\n17321\n17322\n17323\n17324\n17325\n17326\n17327\n17328\n17329\n17330\n17331\n17332\n17333\n17334\n17335\n17336\n17337\n17338\n17339\n17340\n17341\n17342\n17343\n17344\n17345\n17346\n17347\n17348\n17349\n17350\n17351\n17352\n17353\n17354\n17355\n17356\n17357\n17358\n17359\n17360\n17361\n17362\n17363\n17364\n17365\n17366\n17367\n17368\n17369\n17370\n17371\n17372\n17373\n17374\n17375\n17376\n17377\n17378\n17379\n17380\n17381\n17382\n17383\n17384\n17385\n17386\n17387\n17388\n17389\n17390\n17391\n17392\n17393\n17394\n17395\n17396\n17397\n17398\n17399\n17400\n17401\n17402\n17403\n17404\n17405\n17406\n17407\n17408\n17409\n17410\n17411\n17412\n17413\n17414\n17415\n17416\n17417\n17418\n17419\n17420\n17421\n17422\n17423\n17424\n17425\n17426\n17427\n17428\n17429\n17430\n17431\n17432\n17433\n17434\n17435\n17436\n17437\n17438\n17439\n17440\n17441\n17442\n17443\n17444\n17445\n17446\n17447\n17448\n17449\n17450\n17451\n17452\n17453\n17454\n17455\n17456\n17457\n17458\n17459\n17460\n17461\n17462\n17463\n17464\n17465\n17466\n17467\n17468\n17469\n17470\n17471\n17472\n17473\n17474\n17475\n17476\n17477\n17478\n17479\n17480\n17481\n17482\n17483\n17484\n17485\n17486\n17487\n17488\n17489\n17490\n17491\n17492\n17493\n17494\n17495\n17496\n17497\n17498\n17499\n17500\n17501\n17502\n17503\n17504\n17505\n17506\n17507\n17508\n17509\n17510\n17511\n17512\n17513\n17514\n17515\n17516\n17517\n17518\n17519\n17520\n17521\n17522\n17523\n17524\n17525\n17526\n17527\n17528\n17529\n17530\n17531\n17532\n17533\n17534\n17535\n17536\n17537\n17538\n17539\n17540\n17541\n17542\n17543\n17544\n17545\n17546\n17547\n17548\n17549\n17550\n17551\n17552\n17553\n17554\n17555\n17556\n17557\n17558\n17559\n17560\n17561\n17562\n17563\n17564\n17565\n17566\n17567\n17568\n17569\n17570\n17571\n17572\n17573\n17574\n17575\n17576\n17577\n17578\n17579\n17580\n17581\n17582\n17583\n17584\n17585\n17586\n17587\n17588\n17589\n17590\n17591\n17592\n17593\n17594\n17595\n17596\n17597\n17598\n17599\n17600\n17601\n17602\n17603\n17604\n17605\n17606\n17607\n17608\n17609\n17610\n17611\n17612\n17613\n17614\n17615\n17616\n17617\n17618\n17619\n17620\n17621\n17622\n17623\n17624\n17625\n17626\n17627\n17628\n17629\n17630\n17631\n17632\n17633\n17634\n17635\n17636\n17637\n17638\n17639\n17640\n17641\n17642\n17643\n17644\n17645\n17646\n17647\n17648\n17649\n17650\n17651\n17652\n17653\n17654\n17655\n17656\n17657\n17658\n17659\n17660\n17661\n17662\n17663\n17664\n17665\n17666\n17667\n17668\n17669\n17670\n17671\n17672\n17673\n17674\n17675\n17676\n17677\n17678\n17679\n17680\n17681\n17682\n17683\n17684\n17685\n17686\n17687\n17688\n17689\n17690\n17691\n17692\n17693\n17694\n17695\n17696\n17697\n17698\n17699\n17700\n17701\n17702\n17703\n17704\n17705\n17706\n17707\n17708\n17709\n17710\n17711\n17712\n17713\n17714\n17715\n17716\n17717\n17718\n17719\n17720\n17721\n17722\n17723\n17724\n17725\n17726\n17727\n17728\n17729\n17730\n17731\n17732\n17733\n17734\n17735\n17736\n17737\n17738\n17739\n17740\n17741\n17742\n17743\n17744\n17745\n17746\n17747\n17748\n17749\n17750\n17751\n17752\n17753\n17754\n17755\n17756\n17757\n17758\n17759\n17760\n17761\n17762\n17763\n17764\n17765\n17766\n17767\n17768\n17769\n17770\n17771\n17772\n17773\n17774\n17775\n17776\n17777\n17778\n17779\n17780\n17781\n17782\n17783\n17784\n17785\n17786\n17787\n17788\n17789\n17790\n17791\n17792\n17793\n17794\n17795\n17796\n17797\n17798\n17799\n17800\n17801\n17802\n17803\n17804\n17805\n17806\n17807\n17808\n17809\n17810\n17811\n17812\n17813\n17814\n17815\n17816\n17817\n17818\n17819\n17820\n17821\n17822\n17823\n17824\n17825\n17826\n17827\n17828\n17829\n17830\n17831\n17832\n17833\n17834\n17835\n17836\n17837\n17838\n17839\n17840\n17841\n17842\n17843\n17844\n17845\n17846\n17847\n17848\n17849\n17850\n17851\n17852\n17853\n17854\n17855\n17856\n17857\n17858\n17859\n17860\n17861\n17862\n17863\n17864\n17865\n17866\n17867\n17868\n17869\n17870\n17871\n17872\n17873\n17874\n17875\n17876\n17877\n17878\n17879\n17880\n17881\n17882\n17883\n17884\n17885\n17886\n17887\n17888\n17889\n17890\n17891\n17892\n17893\n17894\n17895\n17896\n17897\n17898\n17899\n17900\n17901\n17902\n17903\n17904\n17905\n17906\n17907\n17908\n17909\n17910\n17911\n17912\n17913\n17914\n17915\n17916\n17917\n17918\n17919\n17920\n17921\n17922\n17923\n17924\n17925\n17926\n17927\n17928\n17929\n17930\n17931\n17932\n17933\n17934\n17935\n17936\n17937\n17938\n17939\n17940\n17941\n17942\n17943\n17944\n17945\n17946\n17947\n17948\n17949\n17950\n17951\n17952\n17953\n17954\n17955\n17956\n17957\n17958\n17959\n17960\n17961\n17962\n17963\n17964\n17965\n17966\n17967\n17968\n17969\n17970\n17971\n17972\n17973\n17974\n17975\n17976\n17977\n17978\n17979\n17980\n17981\n17982\n17983\n17984\n17985\n17986\n17987\n17988\n17989\n17990\n17991\n17992\n17993\n17994\n17995\n17996\n17997\n17998\n17999\n18000\n18001\n18002\n18003\n18004\n18005\n18006\n18007\n18008\n18009\n18010\n18011\n18012\n18013\n18014\n18015\n18016\n18017\n18018\n18019\n18020\n18021\n18022\n18023\n18024\n18025\n18026\n18027\n18028\n18029\n18030\n18031\n18032\n18033\n18034\n18035\n18036\n18037\n18038\n18039\n18040\n18041\n18042\n18043\n18044\n18045\n18046\n18047\n18048\n18049\n18050\n18051\n18052\n18053\n18054\n18055\n18056\n18057\n18058\n18059\n18060\n18061\n18062\n18063\n18064\n18065\n18066\n18067\n18068\n18069\n18070\n18071\n18072\n18073\n18074\n18075\n18076\n18077\n18078\n18079\n18080\n18081\n18082\n18083\n18084\n18085\n18086\n18087\n18088\n18089\n18090\n18091\n18092\n18093\n18094\n18095\n18096\n18097\n18098\n18099\n18100\n18101\n18102\n18103\n18104\n18105\n18106\n18107\n18108\n18109\n18110\n18111\n18112\n18113\n18114\n18115\n18116\n18117\n18118\n18119\n18120\n18121\n18122\n18123\n18124\n18125\n18126\n18127\n18128\n18129\n18130\n18131\n18132\n18133\n18134\n18135\n18136\n18137\n18138\n18139\n18140\n18141\n18142\n18143\n18144\n18145\n18146\n18147\n18148\n18149\n18150\n18151\n18152\n18153\n18154\n18155\n18156\n18157\n18158\n18159\n18160\n18161\n18162\n18163\n18164\n18165\n18166\n18167\n18168\n18169\n18170\n18171\n18172\n18173\n18174\n18175\n18176\n18177\n18178\n18179\n18180\n18181\n18182\n18183\n18184\n18185\n18186\n18187\n18188\n18189\n18190\n18191\n18192\n18193\n18194\n18195\n18196\n18197\n18198\n18199\n18200\n18201\n18202\n18203\n18204\n18205\n18206\n18207\n18208\n18209\n18210\n18211\n18212\n18213\n18214\n18215\n18216\n18217\n18218\n18219\n18220\n18221\n18222\n18223\n18224\n18225\n18226\n18227\n18228\n18229\n18230\n18231\n18232\n18233\n18234\n18235\n18236\n18237\n18238\n18239\n18240\n18241\n18242\n18243\n18244\n18245\n18246\n18247\n18248\n18249\n18250\n18251\n18252\n18253\n18254\n18255\n18256\n18257\n18258\n18259\n18260\n18261\n18262\n18263\n18264\n18265\n18266\n18267\n18268\n18269\n18270\n18271\n18272\n18273\n18274\n18275\n18276\n18277\n18278\n18279\n18280\n18281\n18282\n18283\n18284\n18285\n18286\n18287\n18288\n18289\n18290\n18291\n18292\n18293\n18294\n18295\n18296\n18297\n18298\n18299\n18300\n18301\n18302\n18303\n18304\n18305\n18306\n18307\n18308\n18309\n18310\n18311\n18312\n18313\n18314\n18315\n18316\n18317\n18318\n18319\n18320\n18321\n18322\n18323\n18324\n18325\n18326\n18327\n18328\n18329\n18330\n18331\n18332\n18333\n18334\n18335\n18336\n18337\n18338\n18339\n18340\n18341\n18342\n18343\n18344\n18345\n18346\n18347\n18348\n18349\n18350\n18351\n18352\n18353\n18354\n18355\n18356\n18357\n18358\n18359\n18360\n18361\n18362\n18363\n18364\n18365\n18366\n18367\n18368\n18369\n18370\n18371\n18372\n18373\n18374\n18375\n18376\n18377\n18378\n18379\n18380\n18381\n18382\n18383\n18384\n18385\n18386\n18387\n18388\n18389\n18390\n18391\n18392\n18393\n18394\n18395\n18396\n18397\n18398\n18399\n18400\n18401\n18402\n18403\n18404\n18405\n18406\n18407\n18408\n18409\n18410\n18411\n18412\n18413\n18414\n18415\n18416\n18417\n18418\n18419\n18420\n18421\n18422\n18423\n18424\n18425\n18426\n18427\n18428\n18429\n18430\n18431\n18432\n18433\n18434\n18435\n18436\n18437\n18438\n18439\n18440\n18441\n18442\n18443\n18444\n18445\n18446\n18447\n18448\n18449\n18450\n18451\n18452\n18453\n18454\n18455\n18456\n18457\n18458\n18459\n18460\n18461\n18462\n18463\n18464\n18465\n18466\n18467\n18468\n18469\n18470\n18471\n18472\n18473\n18474\n18475\n18476\n18477\n18478\n18479\n18480\n18481\n18482\n18483\n18484\n18485\n18486\n18487\n18488\n18489\n18490\n18491\n18492\n18493\n18494\n18495\n18496\n18497\n18498\n18499\n18500\n18501\n18502\n18503\n18504\n18505\n18506\n18507\n18508\n18509\n18510\n18511\n18512\n18513\n18514\n18515\n18516\n18517\n18518\n18519\n18520\n18521\n18522\n18523\n18524\n18525\n18526\n18527\n18528\n18529\n18530\n18531\n18532\n18533\n18534\n18535\n18536\n18537\n18538\n18539\n18540\n18541\n18542\n18543\n18544\n18545\n18546\n18547\n18548\n18549\n18550\n18551\n18552\n18553\n18554\n18555\n18556\n18557\n18558\n18559\n18560\n18561\n18562\n18563\n18564\n18565\n18566\n18567\n18568\n18569\n18570\n18571\n18572\n18573\n18574\n18575\n18576\n18577\n18578\n18579\n18580\n18581\n18582\n18583\n18584\n18585\n18586\n18587\n18588\n18589\n18590\n18591\n18592\n18593\n18594\n18595\n18596\n18597\n18598\n18599\n18600\n18601\n18602\n18603\n18604\n18605\n18606\n18607\n18608\n18609\n18610\n18611\n18612\n18613\n18614\n18615\n18616\n18617\n18618\n18619\n18620\n18621\n18622\n18623\n18624\n18625\n18626\n18627\n18628\n18629\n18630\n18631\n18632\n18633\n18634\n18635\n18636\n18637\n18638\n18639\n18640\n18641\n18642\n18643\n18644\n18645\n18646\n18647\n18648\n18649\n18650\n18651\n18652\n18653\n18654\n18655\n18656\n18657\n18658\n18659\n18660\n18661\n18662\n18663\n18664\n18665\n18666\n18667\n18668\n18669\n18670\n18671\n18672\n18673\n18674\n18675\n18676\n18677\n18678\n18679\n18680\n18681\n18682\n18683\n18684\n18685\n18686\n18687\n18688\n18689\n18690\n18691\n18692\n18693\n18694\n18695\n18696\n18697\n18698\n18699\n18700\n18701\n18702\n18703\n18704\n18705\n18706\n18707\n18708\n18709\n18710\n18711\n18712\n18713\n18714\n18715\n18716\n18717\n18718\n18719\n18720\n18721\n18722\n18723\n18724\n18725\n18726\n18727\n18728\n18729\n18730\n18731\n18732\n18733\n18734\n18735\n18736\n18737\n18738\n18739\n18740\n18741\n18742\n18743\n18744\n18745\n18746\n18747\n18748\n18749\n18750\n18751\n18752\n18753\n18754\n18755\n18756\n18757\n18758\n18759\n18760\n18761\n18762\n18763\n18764\n18765\n18766\n18767\n18768\n18769\n18770\n18771\n18772\n18773\n18774\n18775\n18776\n18777\n18778\n18779\n18780\n18781\n18782\n18783\n18784\n18785\n18786\n18787\n18788\n18789\n18790\n18791\n18792\n18793\n18794\n18795\n18796\n18797\n18798\n18799\n18800\n18801\n18802\n18803\n18804\n18805\n18806\n18807\n18808\n18809\n18810\n18811\n18812\n18813\n18814\n18815\n18816\n18817\n18818\n18819\n18820\n18821\n18822\n18823\n18824\n18825\n18826\n18827\n18828\n18829\n18830\n18831\n18832\n18833\n18834\n18835\n18836\n18837\n18838\n18839\n18840\n18841\n18842\n18843\n18844\n18845\n18846\n18847\n18848\n18849\n18850\n18851\n18852\n18853\n18854\n18855\n18856\n18857\n18858\n18859\n18860\n18861\n18862\n18863\n18864\n18865\n18866\n18867\n18868\n18869\n18870\n18871\n18872\n18873\n18874\n18875\n18876\n18877\n18878\n18879\n18880\n18881\n18882\n18883\n18884\n18885\n18886\n18887\n18888\n18889\n18890\n18891\n18892\n18893\n18894\n18895\n18896\n18897\n18898\n18899\n18900\n18901\n18902\n18903\n18904\n18905\n18906\n18907\n18908\n18909\n18910\n18911\n18912\n18913\n18914\n18915\n18916\n18917\n18918\n18919\n18920\n18921\n18922\n18923\n18924\n18925\n18926\n18927\n18928\n18929\n18930\n18931\n18932\n18933\n18934\n18935\n18936\n18937\n18938\n18939\n18940\n18941\n18942\n18943\n18944\n18945\n18946\n18947\n18948\n18949\n18950\n18951\n18952\n18953\n18954\n18955\n18956\n18957\n18958\n18959\n18960\n18961\n18962\n18963\n18964\n18965\n18966\n18967\n18968\n18969\n18970\n18971\n18972\n18973\n18974\n18975\n18976\n18977\n18978\n18979\n18980\n18981\n18982\n18983\n18984\n18985\n18986\n18987\n18988\n18989\n18990\n18991\n18992\n18993\n18994\n18995\n18996\n18997\n18998\n18999\n19000\n19001\n19002\n19003\n19004\n19005\n19006\n19007\n19008\n19009\n19010\n19011\n19012\n19013\n19014\n19015\n19016\n19017\n19018\n19019\n19020\n19021\n19022\n19023\n19024\n19025\n19026\n19027\n19028\n19029\n19030\n19031\n19032\n19033\n19034\n19035\n19036\n19037\n19038\n19039\n19040\n19041\n19042\n19043\n19044\n19045\n19046\n19047\n19048\n19049\n19050\n19051\n19052\n19053\n19054\n19055\n19056\n19057\n19058\n19059\n19060\n19061\n19062\n19063\n19064\n19065\n19066\n19067\n19068\n19069\n19070\n19071\n19072\n19073\n19074\n19075\n19076\n19077\n19078\n19079\n19080\n19081\n19082\n19083\n19084\n19085\n19086\n19087\n19088\n19089\n19090\n19091\n19092\n19093\n19094\n19095\n19096\n19097\n19098\n19099\n19100\n19101\n19102\n19103\n19104\n19105\n19106\n19107\n19108\n19109\n19110\n19111\n19112\n19113\n19114\n19115\n19116\n19117\n19118\n19119\n19120\n19121\n19122\n19123\n19124\n19125\n19126\n19127\n19128\n19129\n19130\n19131\n19132\n19133\n19134\n19135\n19136\n19137\n19138\n19139\n19140\n19141\n19142\n19143\n19144\n19145\n19146\n19147\n19148\n19149\n19150\n19151\n19152\n19153\n19154\n19155\n19156\n19157\n19158\n19159\n19160\n19161\n19162\n19163\n19164\n19165\n19166\n19167\n19168\n19169\n19170\n19171\n19172\n19173\n19174\n19175\n19176\n19177\n19178\n19179\n19180\n19181\n19182\n19183\n19184\n19185\n19186\n19187\n19188\n19189\n19190\n19191\n19192\n19193\n19194\n19195\n19196\n19197\n19198\n19199\n19200\n19201\n19202\n19203\n19204\n19205\n19206\n19207\n19208\n19209\n19210\n19211\n19212\n19213\n19214\n19215\n19216\n19217\n19218\n19219\n19220\n19221\n19222\n19223\n19224\n19225\n19226\n19227\n19228\n19229\n19230\n19231\n19232\n19233\n19234\n19235\n19236\n19237\n19238\n19239\n19240\n19241\n19242\n19243\n19244\n19245\n19246\n19247\n19248\n19249\n19250\n19251\n19252\n19253\n19254\n19255\n19256\n19257\n19258\n19259\n19260\n19261\n19262\n19263\n19264\n19265\n19266\n19267\n19268\n19269\n19270\n19271\n19272\n19273\n19274\n19275\n19276\n19277\n19278\n19279\n19280\n19281\n19282\n19283\n19284\n19285\n19286\n19287\n19288\n19289\n19290\n19291\n19292\n19293\n19294\n19295\n19296\n19297\n19298\n19299\n19300\n19301\n19302\n19303\n19304\n19305\n19306\n19307\n19308\n19309\n19310\n19311\n19312\n19313\n19314\n19315\n19316\n19317\n19318\n19319\n19320\n19321\n19322\n19323\n19324\n19325\n19326\n19327\n19328\n19329\n19330\n19331\n19332\n19333\n19334\n19335\n19336\n19337\n19338\n19339\n19340\n19341\n19342\n19343\n19344\n19345\n19346\n19347\n19348\n19349\n19350\n19351\n19352\n19353\n19354\n19355\n19356\n19357\n19358\n19359\n19360\n19361\n19362\n19363\n19364\n19365\n19366\n19367\n19368\n19369\n19370\n19371\n19372\n19373\n19374\n19375\n19376\n19377\n19378\n19379\n19380\n19381\n19382\n19383\n19384\n19385\n19386\n19387\n19388\n19389\n19390\n19391\n19392\n19393\n19394\n19395\n19396\n19397\n19398\n19399\n19400\n19401\n19402\n19403\n19404\n19405\n19406\n19407\n19408\n19409\n19410\n19411\n19412\n19413\n19414\n19415\n19416\n19417\n19418\n19419\n19420\n19421\n19422\n19423\n19424\n19425\n19426\n19427\n19428\n19429\n19430\n19431\n19432\n19433\n19434\n19435\n19436\n19437\n19438\n19439\n19440\n19441\n19442\n19443\n19444\n19445\n19446\n19447\n19448\n19449\n19450\n19451\n19452\n19453\n19454\n19455\n19456\n19457\n19458\n19459\n19460\n19461\n19462\n19463\n19464\n19465\n19466\n19467\n19468\n19469\n19470\n19471\n19472\n19473\n19474\n19475\n19476\n19477\n19478\n19479\n19480\n19481\n19482\n19483\n19484\n19485\n19486\n19487\n19488\n19489\n19490\n19491\n19492\n19493\n19494\n19495\n19496\n19497\n19498\n19499\n19500\n19501\n19502\n19503\n19504\n19505\n19506\n19507\n19508\n19509\n19510\n19511\n19512\n19513\n19514\n19515\n19516\n19517\n19518\n19519\n19520\n19521\n19522\n19523\n19524\n19525\n19526\n19527\n19528\n19529\n19530\n19531\n19532\n19533\n19534\n19535\n19536\n19537\n19538\n19539\n19540\n19541\n19542\n19543\n19544\n19545\n19546\n19547\n19548\n19549\n19550\n19551\n19552\n19553\n19554\n19555\n19556\n19557\n19558\n19559\n19560\n19561\n19562\n19563\n19564\n19565\n19566\n19567\n19568\n19569\n19570\n19571\n19572\n19573\n19574\n19575\n19576\n19577\n19578\n19579\n19580\n19581\n19582\n19583\n19584\n19585\n19586\n19587\n19588\n19589\n19590\n19591\n19592\n19593\n19594\n19595\n19596\n19597\n19598\n19599\n19600\n19601\n19602\n19603\n19604\n19605\n19606\n19607\n19608\n19609\n19610\n19611\n19612\n19613\n19614\n19615\n19616\n19617\n19618\n19619\n19620\n19621\n19622\n19623\n19624\n19625\n19626\n19627\n19628\n19629\n19630\n19631\n19632\n19633\n19634\n19635\n19636\n19637\n19638\n19639\n19640\n19641\n19642\n19643\n19644\n19645\n19646\n19647\n19648\n19649\n19650\n19651\n19652\n19653\n19654\n19655\n19656\n19657\n19658\n19659\n19660\n19661\n19662\n19663\n19664\n19665\n19666\n19667\n19668\n19669\n19670\n19671\n19672\n19673\n19674\n19675\n19676\n19677\n19678\n19679\n19680\n19681\n19682\n19683\n19684\n19685\n19686\n19687\n19688\n19689\n19690\n19691\n19692\n19693\n19694\n19695\n19696\n19697\n19698\n19699\n19700\n19701\n19702\n19703\n19704\n19705\n19706\n19707\n19708\n19709\n19710\n19711\n19712\n19713\n19714\n19715\n19716\n19717\n19718\n19719\n19720\n19721\n19722\n19723\n19724\n19725\n19726\n19727\n19728\n19729\n19730\n19731\n19732\n19733\n19734\n19735\n19736\n19737\n19738\n19739\n19740\n19741\n19742\n19743\n19744\n19745\n19746\n19747\n19748\n19749\n19750\n19751\n19752\n19753\n19754\n19755\n19756\n19757\n19758\n19759\n19760\n19761\n19762\n19763\n19764\n19765\n19766\n19767\n19768\n19769\n19770\n19771\n19772\n19773\n19774\n19775\n19776\n19777\n19778\n19779\n19780\n19781\n19782\n19783\n19784\n19785\n19786\n19787\n19788\n19789\n19790\n19791\n19792\n19793\n19794\n19795\n19796\n19797\n19798\n19799\n19800\n19801\n19802\n19803\n19804\n19805\n19806\n19807\n19808\n19809\n19810\n19811\n19812\n19813\n19814\n19815\n19816\n19817\n19818\n19819\n19820\n19821\n19822\n19823\n19824\n19825\n19826\n19827\n19828\n19829\n19830\n19831\n19832\n19833\n19834\n19835\n19836\n19837\n19838\n19839\n19840\n19841\n19842\n19843\n19844\n19845\n19846\n19847\n19848\n19849\n19850\n19851\n19852\n19853\n19854\n19855\n19856\n19857\n19858\n19859\n19860\n19861\n19862\n19863\n19864\n19865\n19866\n19867\n19868\n19869\n19870\n19871\n19872\n19873\n19874\n19875\n19876\n19877\n19878\n19879\n19880\n19881\n19882\n19883\n19884\n19885\n19886\n19887\n19888\n19889\n19890\n19891\n19892\n19893\n19894\n19895\n19896\n19897\n19898\n19899\n19900\n19901\n19902\n19903\n19904\n19905\n19906\n19907\n19908\n19909\n19910\n19911\n19912\n19913\n19914\n19915\n19916\n19917\n19918\n19919\n19920\n19921\n19922\n19923\n19924\n19925\n19926\n19927\n19928\n19929\n19930\n19931\n19932\n19933\n19934\n19935\n19936\n19937\n19938\n19939\n19940\n19941\n19942\n19943\n19944\n19945\n19946\n19947\n19948\n19949\n19950\n19951\n19952\n19953\n19954\n19955\n19956\n19957\n19958\n19959\n19960\n19961\n19962\n19963\n19964\n19965\n19966\n19967\n19968\n19969\n19970\n19971\n19972\n19973\n19974\n19975\n19976\n19977\n19978\n19979\n19980\n19981\n19982\n19983\n19984\n19985\n19986\n19987\n19988\n19989\n19990\n19991\n19992\n19993\n19994\n19995\n19996\n19997\n19998\n19999\n20000\n20001\n20002\n20003\n20004\n20005\n20006\n20007\n20008\n20009\n20010\n20011\n20012\n20013\n20014\n20015\n20016\n20017\n20018\n20019\n20020\n20021\n20022\n20023\n20024\n20025\n20026\n20027\n20028\n20029\n20030\n20031\n20032\n20033\n20034\n20035\n20036\n20037\n20038\n20039\n20040\n20041\n20042\n20043\n20044\n20045\n20046\n20047\n20048\n20049\n20050\n20051\n20052\n20053\n20054\n20055\n20056\n20057\n20058\n20059\n20060\n20061\n20062\n20063\n20064\n20065\n20066\n20067\n20068\n20069\n20070\n20071\n20072\n20073\n20074\n20075\n20076\n20077\n20078\n20079\n20080\n20081\n20082\n20083\n20084\n20085\n20086\n20087\n20088\n20089\n20090\n20091\n20092\n20093\n20094\n20095\n20096\n20097\n20098\n20099\n20100\n20101\n20102\n20103\n20104\n20105\n20106\n20107\n20108\n20109\n20110\n20111\n20112\n20113\n20114\n20115\n20116\n20117\n20118\n20119\n20120\n20121\n20122\n20123\n20124\n20125\n20126\n20127\n20128\n20129\n20130\n20131\n20132\n20133\n20134\n20135\n20136\n20137\n20138\n20139\n20140\n20141\n20142\n20143\n20144\n20145\n20146\n20147\n20148\n20149\n20150\n20151\n20152\n20153\n20154\n20155\n20156\n20157\n20158\n20159\n20160\n20161\n20162\n20163\n20164\n20165\n20166\n20167\n20168\n20169\n20170\n20171\n20172\n20173\n20174\n20175\n20176\n20177\n20178\n20179\n20180\n20181\n20182\n20183\n20184\n20185\n20186\n20187\n20188\n20189\n20190\n20191\n20192\n20193\n20194\n20195\n20196\n20197\n20198\n20199\n20200\n20201\n20202\n20203\n20204\n20205\n20206\n20207\n20208\n20209\n20210\n20211\n20212\n20213\n20214\n20215\n20216\n20217\n20218\n20219\n20220\n20221\n20222\n20223\n20224\n20225\n20226\n20227\n20228\n20229\n20230\n20231\n20232\n20233\n20234\n20235\n20236\n20237\n20238\n20239\n20240\n20241\n20242\n20243\n20244\n20245\n20246\n20247\n20248\n20249\n20250\n20251\n20252\n20253\n20254\n20255\n20256\n20257\n20258\n20259\n20260\n20261\n20262\n20263\n20264\n20265\n20266\n20267\n20268\n20269\n20270\n20271\n20272\n20273\n20274\n20275\n20276\n20277\n20278\n20279\n20280\n20281\n20282\n20283\n20284\n20285\n20286\n20287\n20288\n20289\n20290\n20291\n20292\n20293\n20294\n20295\n20296\n20297\n20298\n20299\n20300\n20301\n20302\n20303\n20304\n20305\n20306\n20307\n20308\n20309\n20310\n20311\n20312\n20313\n20314\n20315\n20316\n20317\n20318\n20319\n20320\n20321\n20322\n20323\n20324\n20325\n20326\n20327\n20328\n20329\n20330\n20331\n20332\n20333\n20334\n20335\n20336\n20337\n20338\n20339\n20340\n20341\n20342\n20343\n20344\n20345\n20346\n20347\n20348\n20349\n20350\n20351\n20352\n20353\n20354\n20355\n20356\n20357\n20358\n20359\n20360\n20361\n20362\n20363\n20364\n20365\n20366\n20367\n20368\n20369\n20370\n20371\n20372\n20373\n20374\n20375\n20376\n20377\n20378\n20379\n20380\n20381\n20382\n20383\n20384\n20385\n20386\n20387\n20388\n20389\n20390\n20391\n20392\n20393\n20394\n20395\n20396\n20397\n20398\n20399\n20400\n20401\n20402\n20403\n20404\n20405\n20406\n20407\n20408\n20409\n20410\n20411\n20412\n20413\n20414\n20415\n20416\n20417\n20418\n20419\n20420\n20421\n20422\n20423\n20424\n20425\n20426\n20427\n20428\n20429\n20430\n20431\n20432\n20433\n20434\n20435\n20436\n20437\n20438\n20439\n20440\n20441\n20442\n20443\n20444\n20445\n20446\n20447\n20448\n20449\n20450\n20451\n20452\n20453\n20454\n20455\n20456\n20457\n20458\n20459\n20460\n20461\n20462\n20463\n20464\n20465\n20466\n20467\n20468\n20469\n20470\n20471\n20472\n20473\n20474\n20475\n20476\n20477\n20478\n20479\n20480\n20481\n20482\n20483\n20484\n20485\n20486\n20487\n20488\n20489\n20490\n20491\n20492\n20493\n20494\n20495\n20496\n20497\n20498\n20499\n20500\n20501\n20502\n20503\n20504\n20505\n20506\n20507\n20508\n20509\n20510\n20511\n20512\n20513\n20514\n20515\n20516\n20517\n20518\n20519\n20520\n20521\n20522\n20523\n20524\n20525\n20526\n20527\n20528\n20529\n20530\n20531\n20532\n20533\n20534\n20535\n20536\n20537\n20538\n20539\n20540\n20541\n20542\n20543\n20544\n20545\n20546\n20547\n20548\n20549\n20550\n20551\n20552\n20553\n20554\n20555\n20556\n20557\n20558\n20559\n20560\n20561\n20562\n20563\n20564\n20565\n20566\n20567\n20568\n20569\n20570\n20571\n20572\n20573\n20574\n20575\n20576\n20577\n20578\n20579\n20580\n20581\n20582\n20583\n20584\n20585\n20586\n20587\n20588\n20589\n20590\n20591\n20592\n20593\n20594\n20595\n20596\n20597\n20598\n20599\n20600\n20601\n20602\n20603\n20604\n20605\n20606\n20607\n20608\n20609\n20610\n20611\n20612\n20613\n20614\n20615\n20616\n20617\n20618\n20619\n20620\n20621\n20622\n20623\n20624\n20625\n20626\n20627\n20628\n20629\n20630\n20631\n20632\n20633\n20634\n20635\n20636\n20637\n20638\n20639\n20640\n20641\n20642\n20643\n20644\n20645\n20646\n20647\n20648\n20649\n20650\n20651\n20652\n20653\n20654\n20655\n20656\n20657\n20658\n20659\n20660\n20661\n20662\n20663\n20664\n20665\n20666\n20667\n20668\n20669\n20670\n20671\n20672\n20673\n20674\n20675\n20676\n20677\n20678\n20679\n20680\n20681\n20682\n20683\n20684\n20685\n20686\n20687\n20688\n20689\n20690\n20691\n20692\n20693\n20694\n20695\n20696\n20697\n20698\n20699\n20700\n20701\n20702\n20703\n20704\n20705\n20706\n20707\n20708\n20709\n20710\n20711\n20712\n20713\n20714\n20715\n20716\n20717\n20718\n20719\n20720\n20721\n20722\n20723\n20724\n20725\n20726\n20727\n20728\n20729\n20730\n20731\n20732\n20733\n20734\n20735\n20736\n20737\n20738\n20739\n20740\n20741\n20742\n20743\n20744\n20745\n20746\n20747\n20748\n20749\n20750\n20751\n20752\n20753\n20754\n20755\n20756\n20757\n20758\n20759\n20760\n20761\n20762\n20763\n20764\n20765\n20766\n20767\n20768\n20769\n20770\n20771\n20772\n20773\n20774\n20775\n20776\n20777\n20778\n20779\n20780\n20781\n20782\n20783\n20784\n20785\n20786\n20787\n20788\n20789\n20790\n20791\n20792\n20793\n20794\n20795\n20796\n20797\n20798\n20799\n20800\n20801\n20802\n20803\n20804\n20805\n20806\n20807\n20808\n20809\n20810\n20811\n20812\n20813\n20814\n20815\n20816\n20817\n20818\n20819\n20820\n20821\n20822\n20823\n20824\n20825\n20826\n20827\n20828\n20829\n20830\n20831\n20832\n20833\n20834\n20835\n20836\n20837\n20838\n20839\n20840\n20841\n20842\n20843\n20844\n20845\n20846\n20847\n20848\n20849\n20850\n20851\n20852\n20853\n20854\n20855\n20856\n20857\n20858\n20859\n20860\n20861\n20862\n20863\n20864\n20865\n20866\n20867\n20868\n20869\n20870\n20871\n20872\n20873\n20874\n20875\n20876\n20877\n20878\n20879\n20880\n20881\n20882\n20883\n20884\n20885\n20886\n20887\n20888\n20889\n20890\n20891\n20892\n20893\n20894\n20895\n20896\n20897\n20898\n20899\n20900\n20901\n20902\n20903\n20904\n20905\n20906\n20907\n20908\n20909\n20910\n20911\n20912\n20913\n20914\n20915\n20916\n20917\n20918\n20919\n20920\n20921\n20922\n20923\n20924\n20925\n20926\n20927\n20928\n20929\n20930\n20931\n20932\n20933\n20934\n20935\n20936\n20937\n20938\n20939\n20940\n20941\n20942\n20943\n20944\n20945\n20946\n20947\n20948\n20949\n20950\n20951\n20952\n20953\n20954\n20955\n20956\n20957\n20958\n20959\n20960\n20961\n20962\n20963\n20964\n20965\n20966\n20967\n20968\n20969\n20970\n20971\n20972\n20973\n20974\n20975\n20976\n20977\n20978\n20979\n20980\n20981\n20982\n20983\n20984\n20985\n20986\n20987\n20988\n20989\n20990\n20991\n20992\n20993\n20994\n20995\n20996\n20997\n20998\n20999\n21000\n21001\n21002\n21003\n21004\n21005\n21006\n21007\n21008\n21009\n21010\n21011\n21012\n21013\n21014\n21015\n21016\n21017\n21018\n21019\n21020\n21021\n21022\n21023\n21024\n21025\n21026\n21027\n21028\n21029\n21030\n21031\n21032\n21033\n21034\n21035\n21036\n21037\n21038\n21039\n21040\n21041\n21042\n21043\n21044\n21045\n21046\n21047\n21048\n21049\n21050\n21051\n21052\n21053\n21054\n21055\n21056\n21057\n21058\n21059\n21060\n21061\n21062\n21063\n21064\n21065\n21066\n21067\n21068\n21069\n21070\n21071\n21072\n21073\n21074\n21075\n21076\n21077\n21078\n21079\n21080\n21081\n21082\n21083\n21084\n21085\n21086\n21087\n21088\n21089\n21090\n21091\n21092\n21093\n21094\n21095\n21096\n21097\n21098\n21099\n21100\n21101\n21102\n21103\n21104\n21105\n21106\n21107\n21108\n21109\n21110\n21111\n21112\n21113\n21114\n21115\n21116\n21117\n21118\n21119\n21120\n21121\n21122\n21123\n21124\n21125\n21126\n21127\n21128\n21129\n21130\n21131\n21132\n21133\n21134\n21135\n21136\n21137\n21138\n21139\n21140\n21141\n21142\n21143\n21144\n21145\n21146\n21147\n21148\n21149\n21150\n21151\n21152\n21153\n21154\n21155\n21156\n21157\n21158\n21159\n21160\n21161\n21162\n21163\n21164\n21165\n21166\n21167\n21168\n21169\n21170\n21171\n21172\n21173\n21174\n21175\n21176\n21177\n21178\n21179\n21180\n21181\n21182\n21183\n21184\n21185\n21186\n21187\n21188\n21189\n21190\n21191\n21192\n21193\n21194\n21195\n21196\n21197\n21198\n21199\n21200\n21201\n21202\n21203\n21204\n21205\n21206\n21207\n21208\n21209\n21210\n21211\n21212\n21213\n21214\n21215\n21216\n21217\n21218\n21219\n21220\n21221\n21222\n21223\n21224\n21225\n21226\n21227\n21228\n21229\n21230\n21231\n21232\n21233\n21234\n21235\n21236\n21237\n21238\n21239\n21240\n21241\n21242\n21243\n21244\n21245\n21246\n21247\n21248\n21249\n21250\n21251\n21252\n21253\n21254\n21255\n21256\n21257\n21258\n21259\n21260\n21261\n21262\n21263\n21264\n21265\n21266\n21267\n21268\n21269\n21270\n21271\n21272\n21273\n21274\n21275\n21276\n21277\n21278\n21279\n21280\n21281\n21282\n21283\n21284\n21285\n21286\n21287\n21288\n21289\n21290\n21291\n21292\n21293\n21294\n21295\n21296\n21297\n21298\n21299\n21300\n21301\n21302\n21303\n21304\n21305\n21306\n21307\n21308\n21309\n21310\n21311\n21312\n21313\n21314\n21315\n21316\n21317\n21318\n21319\n21320\n21321\n21322\n21323\n21324\n21325\n21326\n21327\n21328\n21329\n21330\n21331\n21332\n21333\n21334\n21335\n21336\n21337\n21338\n21339\n21340\n21341\n21342\n21343\n21344\n21345\n21346\n21347\n21348\n21349\n21350\n21351\n21352\n21353\n21354\n21355\n21356\n21357\n21358\n21359\n21360\n21361\n21362\n21363\n21364\n21365\n21366\n21367\n21368\n21369\n21370\n21371\n21372\n21373\n21374\n21375\n21376\n21377\n21378\n21379\n21380\n21381\n21382\n21383\n21384\n21385\n21386\n21387\n21388\n21389\n21390\n21391\n21392\n21393\n21394\n21395\n21396\n21397\n21398\n21399\n21400\n21401\n21402\n21403\n21404\n21405\n21406\n21407\n21408\n21409\n21410\n21411\n21412\n21413\n21414\n21415\n21416\n21417\n21418\n21419\n21420\n21421\n21422\n21423\n21424\n21425\n21426\n21427\n21428\n21429\n21430\n21431\n21432\n21433\n21434\n21435\n21436\n21437\n21438\n21439\n21440\n21441\n21442\n21443\n21444\n21445\n21446\n21447\n21448\n21449\n21450\n21451\n21452\n21453\n21454\n21455\n21456\n21457\n21458\n21459\n21460\n21461\n21462\n21463\n21464\n21465\n21466\n21467\n21468\n21469\n21470\n21471\n21472\n21473\n21474\n21475\n21476\n21477\n21478\n21479\n21480\n21481\n21482\n21483\n21484\n21485\n21486\n21487\n21488\n21489\n21490\n21491\n21492\n21493\n21494\n21495\n21496\n21497\n21498\n21499\n21500\n21501\n21502\n21503\n21504\n21505\n21506\n21507\n21508\n21509\n21510\n21511\n21512\n21513\n21514\n21515\n21516\n21517\n21518\n21519\n21520\n21521\n21522\n21523\n21524\n21525\n21526\n21527\n21528\n21529\n21530\n21531\n21532\n21533\n21534\n21535\n21536\n21537\n21538\n21539\n21540\n21541\n21542\n21543\n21544\n21545\n21546\n21547\n21548\n21549\n21550\n21551\n21552\n21553\n21554\n21555\n21556\n21557\n21558\n21559\n21560\n21561\n21562\n21563\n21564\n21565\n21566\n21567\n21568\n21569\n21570\n21571\n21572\n21573\n21574\n21575\n21576\n21577\n21578\n21579\n21580\n21581\n21582\n21583\n21584\n21585\n21586\n21587\n21588\n21589\n21590\n21591\n21592\n21593\n21594\n21595\n21596\n21597\n21598\n21599\n21600\n21601\n21602\n21603\n21604\n21605\n21606\n21607\n21608\n21609\n21610\n21611\n21612\n21613\n21614\n21615\n21616\n21617\n21618\n21619\n21620\n21621\n21622\n21623\n21624\n21625\n21626\n21627\n21628\n21629\n21630\n21631\n21632\n21633\n21634\n21635\n21636\n21637\n21638\n21639\n21640\n21641\n21642\n21643\n21644\n21645\n21646\n21647\n21648\n21649\n21650\n21651\n21652\n21653\n21654\n21655\n21656\n21657\n21658\n21659\n21660\n21661\n21662\n21663\n21664\n21665\n21666\n21667\n21668\n21669\n21670\n21671\n21672\n21673\n21674\n21675\n21676\n21677\n21678\n21679\n21680\n21681\n21682\n21683\n21684\n21685\n21686\n21687\n21688\n21689\n21690\n21691\n21692\n21693\n21694\n21695\n21696\n21697\n21698\n21699\n21700\n21701\n21702\n21703\n21704\n21705\n21706\n21707\n21708\n21709\n21710\n21711\n21712\n21713\n21714\n21715\n21716\n21717\n21718\n21719\n21720\n21721\n21722\n21723\n21724\n21725\n21726\n21727\n21728\n21729\n21730\n21731\n21732\n21733\n21734\n21735\n21736\n21737\n21738\n21739\n21740\n21741\n21742\n21743\n21744\n21745\n21746\n21747\n21748\n21749\n21750\n21751\n21752\n21753\n21754\n21755\n21756\n21757\n21758\n21759\n21760\n21761\n21762\n21763\n21764\n21765\n21766\n21767\n21768\n21769\n21770\n21771\n21772\n21773\n21774\n21775\n21776\n21777\n21778\n21779\n21780\n21781\n21782\n21783\n21784\n21785\n21786\n21787\n21788\n21789\n21790\n21791\n21792\n21793\n21794\n21795\n21796\n21797\n21798\n21799\n21800\n21801\n21802\n21803\n21804\n21805\n21806\n21807\n21808\n21809\n21810\n21811\n21812\n21813\n21814\n21815\n21816\n21817\n21818\n21819\n21820\n21821\n21822\n21823\n21824\n21825\n21826\n21827\n21828\n21829\n21830\n21831\n21832\n21833\n21834\n21835\n21836\n21837\n21838\n21839\n21840\n21841\n21842\n21843\n21844\n21845\n21846\n21847\n21848\n21849\n21850\n21851\n21852\n21853\n21854\n21855\n21856\n21857\n21858\n21859\n21860\n21861\n21862\n21863\n21864\n21865\n21866\n21867\n21868\n21869\n21870\n21871\n21872\n21873\n21874\n21875\n21876\n21877\n21878\n21879\n21880\n21881\n21882\n21883\n21884\n21885\n21886\n21887\n21888\n21889\n21890\n21891\n21892\n21893\n21894\n21895\n21896\n21897\n21898\n21899\n21900\n21901\n21902\n21903\n21904\n21905\n21906\n21907\n21908\n21909\n21910\n21911\n21912\n21913\n21914\n21915\n21916\n21917\n21918\n21919\n21920\n21921\n21922\n21923\n21924\n21925\n21926\n21927\n21928\n21929\n21930\n21931\n21932\n21933\n21934\n21935\n21936\n21937\n21938\n21939\n21940\n21941\n21942\n21943\n21944\n21945\n21946\n21947\n21948\n21949\n21950\n21951\n21952\n21953\n21954\n21955\n21956\n21957\n21958\n21959\n21960\n21961\n21962\n21963\n21964\n21965\n21966\n21967\n21968\n21969\n21970\n21971\n21972\n21973\n21974\n21975\n21976\n21977\n21978\n21979\n21980\n21981\n21982\n21983\n21984\n21985\n21986\n21987\n21988\n21989\n21990\n21991\n21992\n21993\n21994\n21995\n21996\n21997\n21998\n21999\n22000\n22001\n22002\n22003\n22004\n22005\n22006\n22007\n22008\n22009\n22010\n22011\n22012\n22013\n22014\n22015\n22016\n22017\n22018\n22019\n22020\n22021\n22022\n22023\n22024\n22025\n22026\n22027\n22028\n22029\n22030\n22031\n22032\n22033\n22034\n22035\n22036\n22037\n22038\n22039\n22040\n22041\n22042\n22043\n22044\n22045\n22046\n22047\n22048\n22049\n22050\n22051\n22052\n22053\n22054\n22055\n22056\n22057\n22058\n22059\n22060\n22061\n22062\n22063\n22064\n22065\n22066\n22067\n22068\n22069\n22070\n22071\n22072\n22073\n22074\n22075\n22076\n22077\n22078\n22079\n22080\n22081\n22082\n22083\n22084\n22085\n22086\n22087\n22088\n22089\n22090\n22091\n22092\n22093\n22094\n22095\n22096\n22097\n22098\n22099\n22100\n22101\n22102\n22103\n22104\n22105\n22106\n22107\n22108\n22109\n22110\n22111\n22112\n22113\n22114\n22115\n22116\n22117\n22118\n22119\n22120\n22121\n22122\n22123\n22124\n22125\n22126\n22127\n22128\n22129\n22130\n22131\n22132\n22133\n22134\n22135\n22136\n22137\n22138\n22139\n22140\n22141\n22142\n22143\n22144\n22145\n22146\n22147\n22148\n22149\n22150\n22151\n22152\n22153\n22154\n22155\n22156\n22157\n22158\n22159\n22160\n22161\n22162\n22163\n22164\n22165\n22166\n22167\n22168\n22169\n22170\n22171\n22172\n22173\n22174\n22175\n22176\n22177\n22178\n22179\n22180\n22181\n22182\n22183\n22184\n22185\n22186\n22187\n22188\n22189\n22190\n22191\n22192\n22193\n22194\n22195\n22196\n22197\n22198\n22199\n22200\n22201\n22202\n22203\n22204\n22205\n22206\n22207\n22208\n22209\n22210\n22211\n22212\n22213\n22214\n22215\n22216\n22217\n22218\n22219\n22220\n22221\n22222\n22223\n22224\n22225\n22226\n22227\n22228\n22229\n22230\n22231\n22232\n22233\n22234\n22235\n22236\n22237\n22238\n22239\n22240\n22241\n22242\n22243\n22244\n22245\n22246\n22247\n22248\n22249\n22250\n22251\n22252\n22253\n22254\n22255\n22256\n22257\n22258\n22259\n22260\n22261\n22262\n22263\n22264\n22265\n22266\n22267\n22268\n22269\n22270\n22271\n22272\n22273\n22274\n22275\n22276\n22277\n22278\n22279\n22280\n22281\n22282\n22283\n22284\n22285\n22286\n22287\n22288\n22289\n22290\n22291\n22292\n22293\n22294\n22295\n22296\n22297\n22298\n22299\n22300\n22301\n22302\n22303\n22304\n22305\n22306\n22307\n22308\n22309\n22310\n22311\n22312\n22313\n22314\n22315\n22316\n22317\n22318\n22319\n22320\n22321\n22322\n22323\n22324\n22325\n22326\n22327\n22328\n22329\n22330\n22331\n22332\n22333\n22334\n22335\n22336\n22337\n22338\n22339\n22340\n22341\n22342\n22343\n22344\n22345\n22346\n22347\n22348\n22349\n22350\n22351\n22352\n22353\n22354\n22355\n22356\n22357\n22358\n22359\n22360\n22361\n22362\n22363\n22364\n22365\n22366\n22367\n22368\n22369\n22370\n22371\n22372\n22373\n22374\n22375\n22376\n22377\n22378\n22379\n22380\n22381\n22382\n22383\n22384\n22385\n22386\n22387\n22388\n22389\n22390\n22391\n22392\n22393\n22394\n22395\n22396\n22397\n22398\n22399\n22400\n22401\n22402\n22403\n22404\n22405\n22406\n22407\n22408\n22409\n22410\n22411\n22412\n22413\n22414\n22415\n22416\n22417\n22418\n22419\n22420\n22421\n22422\n22423\n22424\n22425\n22426\n22427\n22428\n22429\n22430\n22431\n22432\n22433\n22434\n22435\n22436\n22437\n22438\n22439\n22440\n22441\n22442\n22443\n22444\n22445\n22446\n22447\n22448\n22449\n22450\n22451\n22452\n22453\n22454\n22455\n22456\n22457\n22458\n22459\n22460\n22461\n22462\n22463\n22464\n22465\n22466\n22467\n22468\n22469\n22470\n22471\n22472\n22473\n22474\n22475\n22476\n22477\n22478\n22479\n22480\n22481\n22482\n22483\n22484\n22485\n22486\n22487\n22488\n22489\n22490\n22491\n22492\n22493\n22494\n22495\n22496\n22497\n22498\n22499\n22500\n22501\n22502\n22503\n22504\n22505\n22506\n22507\n22508\n22509\n22510\n22511\n22512\n22513\n22514\n22515\n22516\n22517\n22518\n22519\n22520\n22521\n22522\n22523\n22524\n22525\n22526\n22527\n22528\n22529\n22530\n22531\n22532\n22533\n22534\n22535\n22536\n22537\n22538\n22539\n22540\n22541\n22542\n22543\n22544\n22545\n22546\n22547\n22548\n22549\n22550\n22551\n22552\n22553\n22554\n22555\n22556\n22557\n22558\n22559\n22560\n22561\n22562\n22563\n22564\n22565\n22566\n22567\n22568\n22569\n22570\n22571\n22572\n22573\n22574\n22575\n22576\n22577\n22578\n22579\n22580\n22581\n22582\n22583\n22584\n22585\n22586\n22587\n22588\n22589\n22590\n22591\n22592\n22593\n22594\n22595\n22596\n22597\n22598\n22599\n22600\n22601\n22602\n22603\n22604\n22605\n22606\n22607\n22608\n22609\n22610\n22611\n22612\n22613\n22614\n22615\n22616\n22617\n22618\n22619\n22620\n22621\n22622\n22623\n22624\n22625\n22626\n22627\n22628\n22629\n22630\n22631\n22632\n22633\n22634\n22635\n22636\n22637\n22638\n22639\n22640\n22641\n22642\n22643\n22644\n22645\n22646\n22647\n22648\n22649\n22650\n22651\n22652\n22653\n22654\n22655\n22656\n22657\n22658\n22659\n22660\n22661\n22662\n22663\n22664\n22665\n22666\n22667\n22668\n22669\n22670\n22671\n22672\n22673\n22674\n22675\n22676\n22677\n22678\n22679\n22680\n22681\n22682\n22683\n22684\n22685\n22686\n22687\n22688\n22689\n22690\n22691\n22692\n22693\n22694\n22695\n22696\n22697\n22698\n22699\n22700\n22701\n22702\n22703\n22704\n22705\n22706\n22707\n22708\n22709\n22710\n22711\n22712\n22713\n22714\n22715\n22716\n22717\n22718\n22719\n22720\n22721\n22722\n22723\n22724\n22725\n22726\n22727\n22728\n22729\n22730\n22731\n22732\n22733\n22734\n22735\n22736\n22737\n22738\n22739\n22740\n22741\n22742\n22743\n22744\n22745\n22746\n22747\n22748\n22749\n22750\n22751\n22752\n22753\n22754\n22755\n22756\n22757\n22758\n22759\n22760\n22761\n22762\n22763\n22764\n22765\n22766\n22767\n22768\n22769\n22770\n22771\n22772\n22773\n22774\n22775\n22776\n22777\n22778\n22779\n22780\n22781\n22782\n22783\n22784\n22785\n22786\n22787\n22788\n22789\n22790\n22791\n22792\n22793\n22794\n22795\n22796\n22797\n22798\n22799\n22800\n22801\n22802\n22803\n22804\n22805\n22806\n22807\n22808\n22809\n22810\n22811\n22812\n22813\n22814\n22815\n22816\n22817\n22818\n22819\n22820\n22821\n22822\n22823\n22824\n22825\n22826\n22827\n22828\n22829\n22830\n22831\n22832\n22833\n22834\n22835\n22836\n22837\n22838\n22839\n22840\n22841\n22842\n22843\n22844\n22845\n22846\n22847\n22848\n22849\n22850\n22851\n22852\n22853\n22854\n22855\n22856\n22857\n22858\n22859\n22860\n22861\n22862\n22863\n22864\n22865\n22866\n22867\n22868\n22869\n22870\n22871\n22872\n22873\n22874\n22875\n22876\n22877\n22878\n22879\n22880\n22881\n22882\n22883\n22884\n22885\n22886\n22887\n22888\n22889\n22890\n22891\n22892\n22893\n22894\n22895\n22896\n22897\n22898\n22899\n22900\n22901\n22902\n22903\n22904\n22905\n22906\n22907\n22908\n22909\n22910\n22911\n22912\n22913\n22914\n22915\n22916\n22917\n22918\n22919\n22920\n22921\n22922\n22923\n22924\n22925\n22926\n22927\n22928\n22929\n22930\n22931\n22932\n22933\n22934\n22935\n22936\n22937\n22938\n22939\n22940\n22941\n22942\n22943\n22944\n22945\n22946\n22947\n22948\n22949\n22950\n22951\n22952\n22953\n22954\n22955\n22956\n22957\n22958\n22959\n22960\n22961\n22962\n22963\n22964\n22965\n22966\n22967\n22968\n22969\n22970\n22971\n22972\n22973\n22974\n22975\n22976\n22977\n22978\n22979\n22980\n22981\n22982\n22983\n22984\n22985\n22986\n22987\n22988\n22989\n22990\n22991\n22992\n22993\n22994\n22995\n22996\n22997\n22998\n22999\n23000\n23001\n23002\n23003\n23004\n23005\n23006\n23007\n23008\n23009\n23010\n23011\n23012\n23013\n23014\n23015\n23016\n23017\n23018\n23019\n23020\n23021\n23022\n23023\n23024\n23025\n23026\n23027\n23028\n23029\n23030\n23031\n23032\n23033\n23034\n23035\n23036\n23037\n23038\n23039\n23040\n23041\n23042\n23043\n23044\n23045\n23046\n23047\n23048\n23049\n23050\n23051\n23052\n23053\n23054\n23055\n23056\n23057\n23058\n23059\n23060\n23061\n23062\n23063\n23064\n23065\n23066\n23067\n23068\n23069\n23070\n23071\n23072\n23073\n23074\n23075\n23076\n23077\n23078\n23079\n23080\n23081\n23082\n23083\n23084\n23085\n23086\n23087\n23088\n23089\n23090\n23091\n23092\n23093\n23094\n23095\n23096\n23097\n23098\n23099\n23100\n23101\n23102\n23103\n23104\n23105\n23106\n23107\n23108\n23109\n23110\n23111\n23112\n23113\n23114\n23115\n23116\n23117\n23118\n23119\n23120\n23121\n23122\n23123\n23124\n23125\n23126\n23127\n23128\n23129\n23130\n23131\n23132\n23133\n23134\n23135\n23136\n23137\n23138\n23139\n23140\n23141\n23142\n23143\n23144\n23145\n23146\n23147\n23148\n23149\n23150\n23151\n23152\n23153\n23154\n23155\n23156\n23157\n23158\n23159\n23160\n23161\n23162\n23163\n23164\n23165\n23166\n23167\n23168\n23169\n23170\n23171\n23172\n23173\n23174\n23175\n23176\n23177\n23178\n23179\n23180\n23181\n23182\n23183\n23184\n23185\n23186\n23187\n23188\n23189\n23190\n23191\n23192\n23193\n23194\n23195\n23196\n23197\n23198\n23199\n23200\n23201\n23202\n23203\n23204\n23205\n23206\n23207\n23208\n23209\n23210\n23211\n23212\n23213\n23214\n23215\n23216\n23217\n23218\n23219\n23220\n23221\n23222\n23223\n23224\n23225\n23226\n23227\n23228\n23229\n23230\n23231\n23232\n23233\n23234\n23235\n23236\n23237\n23238\n23239\n23240\n23241\n23242\n23243\n23244\n23245\n23246\n23247\n23248\n23249\n23250\n23251\n23252\n23253\n23254\n23255\n23256\n23257\n23258\n23259\n23260\n23261\n23262\n23263\n23264\n23265\n23266\n23267\n23268\n23269\n23270\n23271\n23272\n23273\n23274\n23275\n23276\n23277\n23278\n23279\n23280\n23281\n23282\n23283\n23284\n23285\n23286\n23287\n23288\n23289\n23290\n23291\n23292\n23293\n23294\n23295\n23296\n23297\n23298\n23299\n23300\n23301\n23302\n23303\n23304\n23305\n23306\n23307\n23308\n23309\n23310\n23311\n23312\n23313\n23314\n23315\n23316\n23317\n23318\n23319\n23320\n23321\n23322\n23323\n23324\n23325\n23326\n23327\n23328\n23329\n23330\n23331\n23332\n23333\n23334\n23335\n23336\n23337\n23338\n23339\n23340\n23341\n23342\n23343\n23344\n23345\n23346\n23347\n23348\n23349\n23350\n23351\n23352\n23353\n23354\n23355\n23356\n23357\n23358\n23359\n23360\n23361\n23362\n23363\n23364\n23365\n23366\n23367\n23368\n23369\n23370\n23371\n23372\n23373\n23374\n23375\n23376\n23377\n23378\n23379\n23380\n23381\n23382\n23383\n23384\n23385\n23386\n23387\n23388\n23389\n23390\n23391\n23392\n23393\n23394\n23395\n23396\n23397\n23398\n23399\n23400\n23401\n23402\n23403\n23404\n23405\n23406\n23407\n23408\n23409\n23410\n23411\n23412\n23413\n23414\n23415\n23416\n23417\n23418\n23419\n23420\n23421\n23422\n23423\n23424\n23425\n23426\n23427\n23428\n23429\n23430\n23431\n23432\n23433\n23434\n23435\n23436\n23437\n23438\n23439\n23440\n23441\n23442\n23443\n23444\n23445\n23446\n23447\n23448\n23449\n23450\n23451\n23452\n23453\n23454\n23455\n23456\n23457\n23458\n23459\n23460\n23461\n23462\n23463\n23464\n23465\n23466\n23467\n23468\n23469\n23470\n23471\n23472\n23473\n23474\n23475\n23476\n23477\n23478\n23479\n23480\n23481\n23482\n23483\n23484\n23485\n23486\n23487\n23488\n23489\n23490\n23491\n23492\n23493\n23494\n23495\n23496\n23497\n23498\n23499\n23500\n23501\n23502\n23503\n23504\n23505\n23506\n23507\n23508\n23509\n23510\n23511\n23512\n23513\n23514\n23515\n23516\n23517\n23518\n23519\n23520\n23521\n23522\n23523\n23524\n23525\n23526\n23527\n23528\n23529\n23530\n23531\n23532\n23533\n23534\n23535\n23536\n23537\n23538\n23539\n23540\n23541\n23542\n23543\n23544\n23545\n23546\n23547\n23548\n23549\n23550\n23551\n23552\n23553\n23554\n23555\n23556\n23557\n23558\n23559\n23560\n23561\n23562\n23563\n23564\n23565\n23566\n23567\n23568\n23569\n23570\n23571\n23572\n23573\n23574\n23575\n23576\n23577\n23578\n23579\n23580\n23581\n23582\n23583\n23584\n23585\n23586\n23587\n23588\n23589\n23590\n23591\n23592\n23593\n23594\n23595\n23596\n23597\n23598\n23599\n23600\n23601\n23602\n23603\n23604\n23605\n23606\n23607\n23608\n23609\n23610\n23611\n23612\n23613\n23614\n23615\n23616\n23617\n23618\n23619\n23620\n23621\n23622\n23623\n23624\n23625\n23626\n23627\n23628\n23629\n23630\n23631\n23632\n23633\n23634\n23635\n23636\n23637\n23638\n23639\n23640\n23641\n23642\n23643\n23644\n23645\n23646\n23647\n23648\n23649\n23650\n23651\n23652\n23653\n23654\n23655\n23656\n23657\n23658\n23659\n23660\n23661\n23662\n23663\n23664\n23665\n23666\n23667\n23668\n23669\n23670\n23671\n23672\n23673\n23674\n23675\n23676\n23677\n23678\n23679\n23680\n23681\n23682\n23683\n23684\n23685\n23686\n23687\n23688\n23689\n23690\n23691\n23692\n23693\n23694\n23695\n23696\n23697\n23698\n23699\n23700\n23701\n23702\n23703\n23704\n23705\n23706\n23707\n23708\n23709\n23710\n23711\n23712\n23713\n23714\n23715\n23716\n23717\n23718\n23719\n23720\n23721\n23722\n23723\n23724\n23725\n23726\n23727\n23728\n23729\n23730\n23731\n23732\n23733\n23734\n23735\n23736\n23737\n23738\n23739\n23740\n23741\n23742\n23743\n23744\n23745\n23746\n23747\n23748\n23749\n23750\n23751\n23752\n23753\n23754\n23755\n23756\n23757\n23758\n23759\n23760\n23761\n23762\n23763\n23764\n23765\n23766\n23767\n23768\n23769\n23770\n23771\n23772\n23773\n23774\n23775\n23776\n23777\n23778\n23779\n23780\n23781\n23782\n23783\n23784\n23785\n23786\n23787\n23788\n23789\n23790\n23791\n23792\n23793\n23794\n23795\n23796\n23797\n23798\n23799\n23800\n23801\n23802\n23803\n23804\n23805\n23806\n23807\n23808\n23809\n23810\n23811\n23812\n23813\n23814\n23815\n23816\n23817\n23818\n23819\n23820\n23821\n23822\n23823\n23824\n23825\n23826\n23827\n23828\n23829\n23830\n23831\n23832\n23833\n23834\n23835\n23836\n23837\n23838\n23839\n23840\n23841\n23842\n23843\n23844\n23845\n23846\n23847\n23848\n23849\n23850\n23851\n23852\n23853\n23854\n23855\n23856\n23857\n23858\n23859\n23860\n23861\n23862\n23863\n23864\n23865\n23866\n23867\n23868\n23869\n23870\n23871\n23872\n23873\n23874\n23875\n23876\n23877\n23878\n23879\n23880\n23881\n23882\n23883\n23884\n23885\n23886\n23887\n23888\n23889\n23890\n23891\n23892\n23893\n23894\n23895\n23896\n23897\n23898\n23899\n23900\n23901\n23902\n23903\n23904\n23905\n23906\n23907\n23908\n23909\n23910\n23911\n23912\n23913\n23914\n23915\n23916\n23917\n23918\n23919\n23920\n23921\n23922\n23923\n23924\n23925\n23926\n23927\n23928\n23929\n23930\n23931\n23932\n23933\n23934\n23935\n23936\n23937\n23938\n23939\n23940\n23941\n23942\n23943\n23944\n23945\n23946\n23947\n23948\n23949\n23950\n23951\n23952\n23953\n23954\n23955\n23956\n23957\n23958\n23959\n23960\n23961\n23962\n23963\n23964\n23965\n23966\n23967\n23968\n23969\n23970\n23971\n23972\n23973\n23974\n23975\n23976\n23977\n23978\n23979\n23980\n23981\n23982\n23983\n23984\n23985\n23986\n23987\n23988\n23989\n23990\n23991\n23992\n23993\n23994\n23995\n23996\n23997\n23998\n23999\n24000\n24001\n24002\n24003\n24004\n24005\n24006\n24007\n24008\n24009\n24010\n24011\n24012\n24013\n24014\n24015\n24016\n24017\n24018\n24019\n24020\n24021\n24022\n24023\n24024\n24025\n24026\n24027\n24028\n24029\n24030\n24031\n24032\n24033\n24034\n24035\n24036\n24037\n24038\n24039\n24040\n24041\n24042\n24043\n24044\n24045\n24046\n24047\n24048\n24049\n24050\n24051\n24052\n24053\n24054\n24055\n24056\n24057\n24058\n24059\n24060\n24061\n24062\n24063\n24064\n24065\n24066\n24067\n24068\n24069\n24070\n24071\n24072\n24073\n24074\n24075\n24076\n24077\n24078\n24079\n24080\n24081\n24082\n24083\n24084\n24085\n24086\n24087\n24088\n24089\n24090\n24091\n24092\n24093\n24094\n24095\n24096\n24097\n24098\n24099\n24100\n24101\n24102\n24103\n24104\n24105\n24106\n24107\n24108\n24109\n24110\n24111\n24112\n24113\n24114\n24115\n24116\n24117\n24118\n24119\n24120\n24121\n24122\n24123\n24124\n24125\n24126\n24127\n24128\n24129\n24130\n24131\n24132\n24133\n24134\n24135\n24136\n24137\n24138\n24139\n24140\n24141\n24142\n24143\n24144\n24145\n24146\n24147\n24148\n24149\n24150\n24151\n24152\n24153\n24154\n24155\n24156\n24157\n24158\n24159\n24160\n24161\n24162\n24163\n24164\n24165\n24166\n24167\n24168\n24169\n24170\n24171\n24172\n24173\n24174\n24175\n24176\n24177\n24178\n24179\n24180\n24181\n24182\n24183\n24184\n24185\n24186\n24187\n24188\n24189\n24190\n24191\n24192\n24193\n24194\n24195\n24196\n24197\n24198\n24199\n24200\n24201\n24202\n24203\n24204\n24205\n24206\n24207\n24208\n24209\n24210\n24211\n24212\n24213\n24214\n24215\n24216\n24217\n24218\n24219\n24220\n24221\n24222\n24223\n24224\n24225\n24226\n24227\n24228\n24229\n24230\n24231\n24232\n24233\n24234\n24235\n24236\n24237\n24238\n24239\n24240\n24241\n24242\n24243\n24244\n24245\n24246\n24247\n24248\n24249\n24250\n24251\n24252\n24253\n24254\n24255\n24256\n24257\n24258\n24259\n24260\n24261\n24262\n24263\n24264\n24265\n24266\n24267\n24268\n24269\n24270\n24271\n24272\n24273\n24274\n24275\n24276\n24277\n24278\n24279\n24280\n24281\n24282\n24283\n24284\n24285\n24286\n24287\n24288\n24289\n24290\n24291\n24292\n24293\n24294\n24295\n24296\n24297\n24298\n24299\n24300\n24301\n24302\n24303\n24304\n24305\n24306\n24307\n24308\n24309\n24310\n24311\n24312\n24313\n24314\n24315\n24316\n24317\n24318\n24319\n24320\n24321\n24322\n24323\n24324\n24325\n24326\n24327\n24328\n24329\n24330\n24331\n24332\n24333\n24334\n24335\n24336\n24337\n24338\n24339\n24340\n24341\n24342\n24343\n24344\n24345\n24346\n24347\n24348\n24349\n24350\n24351\n24352\n24353\n24354\n24355\n24356\n24357\n24358\n24359\n24360\n24361\n24362\n24363\n24364\n24365\n24366\n24367\n24368\n24369\n24370\n24371\n24372\n24373\n24374\n24375\n24376\n24377\n24378\n24379\n24380\n24381\n24382\n24383\n24384\n24385\n24386\n24387\n24388\n24389\n24390\n24391\n24392\n24393\n24394\n24395\n24396\n24397\n24398\n24399\n24400\n24401\n24402\n24403\n24404\n24405\n24406\n24407\n24408\n24409\n24410\n24411\n24412\n24413\n24414\n24415\n24416\n24417\n24418\n24419\n24420\n24421\n24422\n24423\n24424\n24425\n24426\n24427\n24428\n24429\n24430\n24431\n24432\n24433\n24434\n24435\n24436\n24437\n24438\n24439\n24440\n24441\n24442\n24443\n24444\n24445\n24446\n24447\n24448\n24449\n24450\n24451\n24452\n24453\n24454\n24455\n24456\n24457\n24458\n24459\n24460\n24461\n24462\n24463\n24464\n24465\n24466\n24467\n24468\n24469\n24470\n24471\n24472\n24473\n24474\n24475\n24476\n24477\n24478\n24479\n24480\n24481\n24482\n24483\n24484\n24485\n24486\n24487\n24488\n24489\n24490\n24491\n24492\n24493\n24494\n24495\n24496\n24497\n24498\n24499\n24500\n24501\n24502\n24503\n24504\n24505\n24506\n24507\n24508\n24509\n24510\n24511\n24512\n24513\n24514\n24515\n24516\n24517\n24518\n24519\n24520\n24521\n24522\n24523\n24524\n24525\n24526\n24527\n24528\n24529\n24530\n24531\n24532\n24533\n24534\n24535\n24536\n24537\n24538\n24539\n24540\n24541\n24542\n24543\n24544\n24545\n24546\n24547\n24548\n24549\n24550\n24551\n24552\n24553\n24554\n24555\n24556\n24557\n24558\n24559\n24560\n24561\n24562\n24563\n24564\n24565\n24566\n24567\n24568\n24569\n24570\n24571\n24572\n24573\n24574\n24575\n24576\n24577\n24578\n24579\n24580\n24581\n24582\n24583\n24584\n24585\n24586\n24587\n24588\n24589\n24590\n24591\n24592\n24593\n24594\n24595\n24596\n24597\n24598\n24599\n24600\n24601\n24602\n24603\n24604\n24605\n24606\n24607\n24608\n24609\n24610\n24611\n24612\n24613\n24614\n24615\n24616\n24617\n24618\n24619\n24620\n24621\n24622\n24623\n24624\n24625\n24626\n24627\n24628\n24629\n24630\n24631\n24632\n24633\n24634\n24635\n24636\n24637\n24638\n24639\n24640\n24641\n24642\n24643\n24644\n24645\n24646\n24647\n24648\n24649\n24650\n24651\n24652\n24653\n24654\n24655\n24656\n24657\n24658\n24659\n24660\n24661\n24662\n24663\n24664\n24665\n24666\n24667\n24668\n24669\n24670\n24671\n24672\n24673\n24674\n24675\n24676\n24677\n24678\n24679\n24680\n24681\n24682\n24683\n24684\n24685\n24686\n24687\n24688\n24689\n24690\n24691\n24692\n24693\n24694\n24695\n24696\n24697\n24698\n24699\n24700\n24701\n24702\n24703\n24704\n24705\n24706\n24707\n24708\n24709\n24710\n24711\n24712\n24713\n24714\n24715\n24716\n24717\n24718\n24719\n24720\n24721\n24722\n24723\n24724\n24725\n24726\n24727\n24728\n24729\n24730\n24731\n24732\n24733\n24734\n24735\n24736\n24737\n24738\n24739\n24740\n24741\n24742\n24743\n24744\n24745\n24746\n24747\n24748\n24749\n24750\n24751\n24752\n24753\n24754\n24755\n24756\n24757\n24758\n24759\n24760\n24761\n24762\n24763\n24764\n24765\n24766\n24767\n24768\n24769\n24770\n24771\n24772\n24773\n24774\n24775\n24776\n24777\n24778\n24779\n24780\n24781\n24782\n24783\n24784\n24785\n24786\n24787\n24788\n24789\n24790\n24791\n24792\n24793\n24794\n24795\n24796\n24797\n24798\n24799\n24800\n24801\n24802\n24803\n24804\n24805\n24806\n24807\n24808\n24809\n24810\n24811\n24812\n24813\n24814\n24815\n24816\n24817\n24818\n24819\n24820\n24821\n24822\n24823\n24824\n24825\n24826\n24827\n24828\n24829\n24830\n24831\n24832\n24833\n24834\n24835\n24836\n24837\n24838\n24839\n24840\n24841\n24842\n24843\n24844\n24845\n24846\n24847\n24848\n24849\n24850\n24851\n24852\n24853\n24854\n24855\n24856\n24857\n24858\n24859\n24860\n24861\n24862\n24863\n24864\n24865\n24866\n24867\n24868\n24869\n24870\n24871\n24872\n24873\n24874\n24875\n24876\n24877\n24878\n24879\n24880\n24881\n24882\n24883\n24884\n24885\n24886\n24887\n24888\n24889\n24890\n24891\n24892\n24893\n24894\n24895\n24896\n24897\n24898\n24899\n24900\n24901\n24902\n24903\n24904\n24905\n24906\n24907\n24908\n24909\n24910\n24911\n24912\n24913\n24914\n24915\n24916\n24917\n24918\n24919\n24920\n24921\n24922\n24923\n24924\n24925\n24926\n24927\n24928\n24929\n24930\n24931\n24932\n24933\n24934\n24935\n24936\n24937\n24938\n24939\n24940\n24941\n24942\n24943\n24944\n24945\n24946\n24947\n24948\n24949\n24950\n24951\n24952\n24953\n24954\n24955\n24956\n24957\n24958\n24959\n24960\n24961\n24962\n24963\n24964\n24965\n24966\n24967\n24968\n24969\n24970\n24971\n24972\n24973\n24974\n24975\n24976\n24977\n24978\n24979\n24980\n24981\n24982\n24983\n24984\n24985\n24986\n24987\n24988\n24989\n24990\n24991\n24992\n24993\n24994\n24995\n24996\n24997\n24998\n24999\n25000\n25001\n25002\n25003\n25004\n25005\n25006\n25007\n25008\n25009\n25010\n25011\n25012\n25013\n25014\n25015\n25016\n25017\n25018\n25019\n25020\n25021\n25022\n25023\n25024\n25025\n25026\n25027\n25028\n25029\n25030\n25031\n25032\n25033\n25034\n25035\n25036\n25037\n25038\n25039\n25040\n25041\n25042\n25043\n25044\n25045\n25046\n25047\n25048\n25049\n25050\n25051\n25052\n25053\n25054\n25055\n25056\n25057\n25058\n25059\n25060\n25061\n25062\n25063\n25064\n25065\n25066\n25067\n25068\n25069\n25070\n25071\n25072\n25073\n25074\n25075\n25076\n25077\n25078\n25079\n25080\n25081\n25082\n25083\n25084\n25085\n25086\n25087\n25088\n25089\n25090\n25091\n25092\n25093\n25094\n25095\n25096\n25097\n25098\n25099\n25100\n25101\n25102\n25103\n25104\n25105\n25106\n25107\n25108\n25109\n25110\n25111\n25112\n25113\n25114\n25115\n25116\n25117\n25118\n25119\n25120\n25121\n25122\n25123\n25124\n25125\n25126\n25127\n25128\n25129\n25130\n25131\n25132\n25133\n25134\n25135\n25136\n25137\n25138\n25139\n25140\n25141\n25142\n25143\n25144\n25145\n25146\n25147\n25148\n25149\n25150\n25151\n25152\n25153\n25154\n25155\n25156\n25157\n25158\n25159\n25160\n25161\n25162\n25163\n25164\n25165\n25166\n25167\n25168\n25169\n25170\n25171\n25172\n25173\n25174\n25175\n25176\n25177\n25178\n25179\n25180\n25181\n25182\n25183\n25184\n25185\n25186\n25187\n25188\n25189\n25190\n25191\n25192\n25193\n25194\n25195\n25196\n25197\n25198\n25199\n25200\n25201\n25202\n25203\n25204\n25205\n25206\n25207\n25208\n25209\n25210\n25211\n25212\n25213\n25214\n25215\n25216\n25217\n25218\n25219\n25220\n25221\n25222\n25223\n25224\n25225\n25226\n25227\n25228\n25229\n25230\n25231\n25232\n25233\n25234\n25235\n25236\n25237\n25238\n25239\n25240\n25241\n25242\n25243\n25244\n25245\n25246\n25247\n25248\n25249\n25250\n25251\n25252\n25253\n25254\n25255\n25256\n25257\n25258\n25259\n25260\n25261\n25262\n25263\n25264\n25265\n25266\n25267\n25268\n25269\n25270\n25271\n25272\n25273\n25274\n25275\n25276\n25277\n25278\n25279\n25280\n25281\n25282\n25283\n25284\n25285\n25286\n25287\n25288\n25289\n25290\n25291\n25292\n25293\n25294\n25295\n25296\n25297\n25298\n25299\n25300\n25301\n25302\n25303\n25304\n25305\n25306\n25307\n25308\n25309\n25310\n25311\n25312\n25313\n25314\n25315\n25316\n25317\n25318\n25319\n25320\n25321\n25322\n25323\n25324\n25325\n25326\n25327\n25328\n25329\n25330\n25331\n25332\n25333\n25334\n25335\n25336\n25337\n25338\n25339\n25340\n25341\n25342\n25343\n25344\n25345\n25346\n25347\n25348\n25349\n25350\n25351\n25352\n25353\n25354\n25355\n25356\n25357\n25358\n25359\n25360\n25361\n25362\n25363\n25364\n25365\n25366\n25367\n25368\n25369\n25370\n25371\n25372\n25373\n25374\n25375\n25376\n25377\n25378\n25379\n25380\n25381\n25382\n25383\n25384\n25385\n25386\n25387\n25388\n25389\n25390\n25391\n25392\n25393\n25394\n25395\n25396\n25397\n25398\n25399\n25400\n25401\n25402\n25403\n25404\n25405\n25406\n25407\n25408\n25409\n25410\n25411\n25412\n25413\n25414\n25415\n25416\n25417\n25418\n25419\n25420\n25421\n25422\n25423\n25424\n25425\n25426\n25427\n25428\n25429\n25430\n25431\n25432\n25433\n25434\n25435\n25436\n25437\n25438\n25439\n25440\n25441\n25442\n25443\n25444\n25445\n25446\n25447\n25448\n25449\n25450\n25451\n25452\n25453\n25454\n25455\n25456\n25457\n25458\n25459\n25460\n25461\n25462\n25463\n25464\n25465\n25466\n25467\n25468\n25469\n25470\n25471\n25472\n25473\n25474\n25475\n25476\n25477\n25478\n25479\n25480\n25481\n25482\n25483\n25484\n25485\n25486\n25487\n25488\n25489\n25490\n25491\n25492\n25493\n25494\n25495\n25496\n25497\n25498\n25499\n25500\n25501\n25502\n25503\n25504\n25505\n25506\n25507\n25508\n25509\n25510\n25511\n25512\n25513\n25514\n25515\n25516\n25517\n25518\n25519\n25520\n25521\n25522\n25523\n25524\n25525\n25526\n25527\n25528\n25529\n25530\n25531\n25532\n25533\n25534\n25535\n25536\n25537\n25538\n25539\n25540\n25541\n25542\n25543\n25544\n25545\n25546\n25547\n25548\n25549\n25550\n25551\n25552\n25553\n25554\n25555\n25556\n25557\n25558\n25559\n25560\n25561\n25562\n25563\n25564\n25565\n25566\n25567\n25568\n25569\n25570\n25571\n25572\n25573\n25574\n25575\n25576\n25577\n25578\n25579\n25580\n25581\n25582\n25583\n25584\n25585\n25586\n25587\n25588\n25589\n25590\n25591\n25592\n25593\n25594\n25595\n25596\n25597\n25598\n25599\n25600\n25601\n25602\n25603\n25604\n25605\n25606\n25607\n25608\n25609\n25610\n25611\n25612\n25613\n25614\n25615\n25616\n25617\n25618\n25619\n25620\n25621\n25622\n25623\n25624\n25625\n25626\n25627\n25628\n25629\n25630\n25631\n25632\n25633\n25634\n25635\n25636\n25637\n25638\n25639\n25640\n25641\n25642\n25643\n25644\n25645\n25646\n25647\n25648\n25649\n25650\n25651\n25652\n25653\n25654\n25655\n25656\n25657\n25658\n25659\n25660\n25661\n25662\n25663\n25664\n25665\n25666\n25667\n25668\n25669\n25670\n25671\n25672\n25673\n25674\n25675\n25676\n25677\n25678\n25679\n25680\n25681\n25682\n25683\n25684\n25685\n25686\n25687\n25688\n25689\n25690\n25691\n25692\n25693\n25694\n25695\n25696\n25697\n25698\n25699\n25700\n25701\n25702\n25703\n25704\n25705\n25706\n25707\n25708\n25709\n25710\n25711\n25712\n25713\n25714\n25715\n25716\n25717\n25718\n25719\n25720\n25721\n25722\n25723\n25724\n25725\n25726\n25727\n25728\n25729\n25730\n25731\n25732\n25733\n25734\n25735\n25736\n25737\n25738\n25739\n25740\n25741\n25742\n25743\n25744\n25745\n25746\n25747\n25748\n25749\n25750\n25751\n25752\n25753\n25754\n25755\n25756\n25757\n25758\n25759\n25760\n25761\n25762\n25763\n25764\n25765\n25766\n25767\n25768\n25769\n25770\n25771\n25772\n25773\n25774\n25775\n25776\n25777\n25778\n25779\n25780\n25781\n25782\n25783\n25784\n25785\n25786\n25787\n25788\n25789\n25790\n25791\n25792\n25793\n25794\n25795\n25796\n25797\n25798\n25799\n25800\n25801\n25802\n25803\n25804\n25805\n25806\n25807\n25808\n25809\n25810\n25811\n25812\n25813\n25814\n25815\n25816\n25817\n25818\n25819\n25820\n25821\n25822\n25823\n25824\n25825\n25826\n25827\n25828\n25829\n25830\n25831\n25832\n25833\n25834\n25835\n25836\n25837\n25838\n25839\n25840\n25841\n25842\n25843\n25844\n25845\n25846\n25847\n25848\n25849\n25850\n25851\n25852\n25853\n25854\n25855\n25856\n25857\n25858\n25859\n25860\n25861\n25862\n25863\n25864\n25865\n25866\n25867\n25868\n25869\n25870\n25871\n25872\n25873\n25874\n25875\n25876\n25877\n25878\n25879\n25880\n25881\n25882\n25883\n25884\n25885\n25886\n25887\n25888\n25889\n25890\n25891\n25892\n25893\n25894\n25895\n25896\n25897\n25898\n25899\n25900\n25901\n25902\n25903\n25904\n25905\n25906\n25907\n25908\n25909\n25910\n25911\n25912\n25913\n25914\n25915\n25916\n25917\n25918\n25919\n25920\n25921\n25922\n25923\n25924\n25925\n25926\n25927\n25928\n25929\n25930\n25931\n25932\n25933\n25934\n25935\n25936\n25937\n25938\n25939\n25940\n25941\n25942\n25943\n25944\n25945\n25946\n25947\n25948\n25949\n25950\n25951\n25952\n25953\n25954\n25955\n25956\n25957\n25958\n25959\n25960\n25961\n25962\n25963\n25964\n25965\n25966\n25967\n25968\n25969\n25970\n25971\n25972\n25973\n25974\n25975\n25976\n25977\n25978\n25979\n25980\n25981\n25982\n25983\n25984\n25985\n25986\n25987\n25988\n25989\n25990\n25991\n25992\n25993\n25994\n25995\n25996\n25997\n25998\n25999\n26000\n26001\n26002\n26003\n26004\n26005\n26006\n26007\n26008\n26009\n26010\n26011\n26012\n26013\n26014\n26015\n26016\n26017\n26018\n26019\n26020\n26021\n26022\n26023\n26024\n26025\n26026\n26027\n26028\n26029\n26030\n26031\n26032\n26033\n26034\n26035\n26036\n26037\n26038\n26039\n26040\n26041\n26042\n26043\n26044\n26045\n26046\n26047\n26048\n26049\n26050\n26051\n26052\n26053\n26054\n26055\n26056\n26057\n26058\n26059\n26060\n26061\n26062\n26063\n26064\n26065\n26066\n26067\n26068\n26069\n26070\n26071\n26072\n26073\n26074\n26075\n26076\n26077\n26078\n26079\n26080\n26081\n26082\n26083\n26084\n26085\n26086\n26087\n26088\n26089\n26090\n26091\n26092\n26093\n26094\n26095\n26096\n26097\n26098\n26099\n26100\n26101\n26102\n26103\n26104\n26105\n26106\n26107\n26108\n26109\n26110\n26111\n26112\n26113\n26114\n26115\n26116\n26117\n26118\n26119\n26120\n26121\n26122\n26123\n26124\n26125\n26126\n26127\n26128\n26129\n26130\n26131\n26132\n26133\n26134\n26135\n26136\n26137\n26138\n26139\n26140\n26141\n26142\n26143\n26144\n26145\n26146\n26147\n26148\n26149\n26150\n26151\n26152\n26153\n26154\n26155\n26156\n26157\n26158\n26159\n26160\n26161\n26162\n26163\n26164\n26165\n26166\n26167\n26168\n26169\n26170\n26171\n26172\n26173\n26174\n26175\n26176\n26177\n26178\n26179\n26180\n26181\n26182\n26183\n26184\n26185\n26186\n26187\n26188\n26189\n26190\n26191\n26192\n26193\n26194\n26195\n26196\n26197\n26198\n26199\n26200\n26201\n26202\n26203\n26204\n26205\n26206\n26207\n26208\n26209\n26210\n26211\n26212\n26213\n26214\n26215\n26216\n26217\n26218\n26219\n26220\n26221\n26222\n26223\n26224\n26225\n26226\n26227\n26228\n26229\n26230\n26231\n26232\n26233\n26234\n26235\n26236\n26237\n26238\n26239\n26240\n26241\n26242\n26243\n26244\n26245\n26246\n26247\n26248\n26249\n26250\n26251\n26252\n26253\n26254\n26255\n26256\n26257\n26258\n26259\n26260\n26261\n26262\n26263\n26264\n26265\n26266\n26267\n26268\n26269\n26270\n26271\n26272\n26273\n26274\n26275\n26276\n26277\n26278\n26279\n26280\n26281\n26282\n26283\n26284\n26285\n26286\n26287\n26288\n26289\n26290\n26291\n26292\n26293\n26294\n26295\n26296\n26297\n26298\n26299\n26300\n26301\n26302\n26303\n26304\n26305\n26306\n26307\n26308\n26309\n26310\n26311\n26312\n26313\n26314\n26315\n26316\n26317\n26318\n26319\n26320\n26321\n26322\n26323\n26324\n26325\n26326\n26327\n26328\n26329\n26330\n26331\n26332\n26333\n26334\n26335\n26336\n26337\n26338\n26339\n26340\n26341\n26342\n26343\n26344\n26345\n26346\n26347\n26348\n26349\n26350\n26351\n26352\n26353\n26354\n26355\n26356\n26357\n26358\n26359\n26360\n26361\n26362\n26363\n26364\n26365\n26366\n26367\n26368\n26369\n26370\n26371\n26372\n26373\n26374\n26375\n26376\n26377\n26378\n26379\n26380\n26381\n26382\n26383\n26384\n26385\n26386\n26387\n26388\n26389\n26390\n26391\n26392\n26393\n26394\n26395\n26396\n26397\n26398\n26399\n26400\n26401\n26402\n26403\n26404\n26405\n26406\n26407\n26408\n26409\n26410\n26411\n26412\n26413\n26414\n26415\n26416\n26417\n26418\n26419\n26420\n26421\n26422\n26423\n26424\n26425\n26426\n26427\n26428\n26429\n26430\n26431\n26432\n26433\n26434\n26435\n26436\n26437\n26438\n26439\n26440\n26441\n26442\n26443\n26444\n26445\n26446\n26447\n26448\n26449\n26450\n26451\n26452\n26453\n26454\n26455\n26456\n26457\n26458\n26459\n26460\n26461\n26462\n26463\n26464\n26465\n26466\n26467\n26468\n26469\n26470\n26471\n26472\n26473\n26474\n26475\n26476\n26477\n26478\n26479\n26480\n26481\n26482\n26483\n26484\n26485\n26486\n26487\n26488\n26489\n26490\n26491\n26492\n26493\n26494\n26495\n26496\n26497\n26498\n26499\n26500\n26501\n26502\n26503\n26504\n26505\n26506\n26507\n26508\n26509\n26510\n26511\n26512\n26513\n26514\n26515\n26516\n26517\n26518\n26519\n26520\n26521\n26522\n26523\n26524\n26525\n26526\n26527\n26528\n26529\n26530\n26531\n26532\n26533\n26534\n26535\n26536\n26537\n26538\n26539\n26540\n26541\n26542\n26543\n26544\n26545\n26546\n26547\n26548\n26549\n26550\n26551\n26552\n26553\n26554\n26555\n26556\n26557\n26558\n26559\n26560\n26561\n26562\n26563\n26564\n26565\n26566\n26567\n26568\n26569\n26570\n26571\n26572\n26573\n26574\n26575\n26576\n26577\n26578\n26579\n26580\n26581\n26582\n26583\n26584\n26585\n26586\n26587\n26588\n26589\n26590\n26591\n26592\n26593\n26594\n26595\n26596\n26597\n26598\n26599\n26600\n26601\n26602\n26603\n26604\n26605\n26606\n26607\n26608\n26609\n26610\n26611\n26612\n26613\n26614\n26615\n26616\n26617\n26618\n26619\n26620\n26621\n26622\n26623\n26624\n26625\n26626\n26627\n26628\n26629\n26630\n26631\n26632\n26633\n26634\n26635\n26636\n26637\n26638\n26639\n26640\n26641\n26642\n26643\n26644\n26645\n26646\n26647\n26648\n26649\n26650\n26651\n26652\n26653\n26654\n26655\n26656\n26657\n26658\n26659\n26660\n26661\n26662\n26663\n26664\n26665\n26666\n26667\n26668\n26669\n26670\n26671\n26672\n26673\n26674\n26675\n26676\n26677\n26678\n26679\n26680\n26681\n26682\n26683\n26684\n26685\n26686\n26687\n26688\n26689\n26690\n26691\n26692\n26693\n26694\n26695\n26696\n26697\n26698\n26699\n26700\n26701\n26702\n26703\n26704\n26705\n26706\n26707\n26708\n26709\n26710\n26711\n26712\n26713\n26714\n26715\n26716\n26717\n26718\n26719\n26720\n26721\n26722\n26723\n26724\n26725\n26726\n26727\n26728\n26729\n26730\n26731\n26732\n26733\n26734\n26735\n26736\n26737\n26738\n26739\n26740\n26741\n26742\n26743\n26744\n26745\n26746\n26747\n26748\n26749\n26750\n26751\n26752\n26753\n26754\n26755\n26756\n26757\n26758\n26759\n26760\n26761\n26762\n26763\n26764\n26765\n26766\n26767\n26768\n26769\n26770\n26771\n26772\n26773\n26774\n26775\n26776\n26777\n26778\n26779\n26780\n26781\n26782\n26783\n26784\n26785\n26786\n26787\n26788\n26789\n26790\n26791\n26792\n26793\n26794\n26795\n26796\n26797\n26798\n26799\n26800\n26801\n26802\n26803\n26804\n26805\n26806\n26807\n26808\n26809\n26810\n26811\n26812\n26813\n26814\n26815\n26816\n26817\n26818\n26819\n26820\n26821\n26822\n26823\n26824\n26825\n26826\n26827\n26828\n26829\n26830\n26831\n26832\n26833\n26834\n26835\n26836\n26837\n26838\n26839\n26840\n26841\n26842\n26843\n26844\n26845\n26846\n26847\n26848\n26849\n26850\n26851\n26852\n26853\n26854\n26855\n26856\n26857\n26858\n26859\n26860\n26861\n26862\n26863\n26864\n26865\n26866\n26867\n26868\n26869\n26870\n26871\n26872\n26873\n26874\n26875\n26876\n26877\n26878\n26879\n26880\n26881\n26882\n26883\n26884\n26885\n26886\n26887\n26888\n26889\n26890\n26891\n26892\n26893\n26894\n26895\n26896\n26897\n26898\n26899\n26900\n26901\n26902\n26903\n26904\n26905\n26906\n26907\n26908\n26909\n26910\n26911\n26912\n26913\n26914\n26915\n26916\n26917\n26918\n26919\n26920\n26921\n26922\n26923\n26924\n26925\n26926\n26927\n26928\n26929\n26930\n26931\n26932\n26933\n26934\n26935\n26936\n26937\n26938\n26939\n26940\n26941\n26942\n26943\n26944\n26945\n26946\n26947\n26948\n26949\n26950\n26951\n26952\n26953\n26954\n26955\n26956\n26957\n26958\n26959\n26960\n26961\n26962\n26963\n26964\n26965\n26966\n26967\n26968\n26969\n26970\n26971\n26972\n26973\n26974\n26975\n26976\n26977\n26978\n26979\n26980\n26981\n26982\n26983\n26984\n26985\n26986\n26987\n26988\n26989\n26990\n26991\n26992\n26993\n26994\n26995\n26996\n26997\n26998\n26999\n27000\n27001\n27002\n27003\n27004\n27005\n27006\n27007\n27008\n27009\n27010\n27011\n27012\n27013\n27014\n27015\n27016\n27017\n27018\n27019\n27020\n27021\n27022\n27023\n27024\n27025\n27026\n27027\n27028\n27029\n27030\n27031\n27032\n27033\n27034\n27035\n27036\n27037\n27038\n27039\n27040\n27041\n27042\n27043\n27044\n27045\n27046\n27047\n27048\n27049\n27050\n27051\n27052\n27053\n27054\n27055\n27056\n27057\n27058\n27059\n27060\n27061\n27062\n27063\n27064\n27065\n27066\n27067\n27068\n27069\n27070\n27071\n27072\n27073\n27074\n27075\n27076\n27077\n27078\n27079\n27080\n27081\n27082\n27083\n27084\n27085\n27086\n27087\n27088\n27089\n27090\n27091\n27092\n27093\n27094\n27095\n27096\n27097\n27098\n27099\n27100\n27101\n27102\n27103\n27104\n27105\n27106\n27107\n27108\n27109\n27110\n27111\n27112\n27113\n27114\n27115\n27116\n27117\n27118\n27119\n27120\n27121\n27122\n27123\n27124\n27125\n27126\n27127\n27128\n27129\n27130\n27131\n27132\n27133\n27134\n27135\n27136\n27137\n27138\n27139\n27140\n27141\n27142\n27143\n27144\n27145\n27146\n27147\n27148\n27149\n27150\n27151\n27152\n27153\n27154\n27155\n27156\n27157\n27158\n27159\n27160\n27161\n27162\n27163\n27164\n27165\n27166\n27167\n27168\n27169\n27170\n27171\n27172\n27173\n27174\n27175\n27176\n27177\n27178\n27179\n27180\n27181\n27182\n27183\n27184\n27185\n27186\n27187\n27188\n27189\n27190\n27191\n27192\n27193\n27194\n27195\n27196\n27197\n27198\n27199\n27200\n27201\n27202\n27203\n27204\n27205\n27206\n27207\n27208\n27209\n27210\n27211\n27212\n27213\n27214\n27215\n27216\n27217\n27218\n27219\n27220\n27221\n27222\n27223\n27224\n27225\n27226\n27227\n27228\n27229\n27230\n27231\n27232\n27233\n27234\n27235\n27236\n27237\n27238\n27239\n27240\n27241\n27242\n27243\n27244\n27245\n27246\n27247\n27248\n27249\n27250\n27251\n27252\n27253\n27254\n27255\n27256\n27257\n27258\n27259\n27260\n27261\n27262\n27263\n27264\n27265\n27266\n27267\n27268\n27269\n27270\n27271\n27272\n27273\n27274\n27275\n27276\n27277\n27278\n27279\n27280\n27281\n27282\n27283\n27284\n27285\n27286\n27287\n27288\n27289\n27290\n27291\n27292\n27293\n27294\n27295\n27296\n27297\n27298\n27299\n27300\n27301\n27302\n27303\n27304\n27305\n27306\n27307\n27308\n27309\n27310\n27311\n27312\n27313\n27314\n27315\n27316\n27317\n27318\n27319\n27320\n27321\n27322\n27323\n27324\n27325\n27326\n27327\n27328\n27329\n27330\n27331\n27332\n27333\n27334\n27335\n27336\n27337\n27338\n27339\n27340\n27341\n27342\n27343\n27344\n27345\n27346\n27347\n27348\n27349\n27350\n27351\n27352\n27353\n27354\n27355\n27356\n27357\n27358\n27359\n27360\n27361\n27362\n27363\n27364\n27365\n27366\n27367\n27368\n27369\n27370\n27371\n27372\n27373\n27374\n27375\n27376\n27377\n27378\n27379\n27380\n27381\n27382\n27383\n27384\n27385\n27386\n27387\n27388\n27389\n27390\n27391\n27392\n27393\n27394\n27395\n27396\n27397\n27398\n27399\n27400\n27401\n27402\n27403\n27404\n27405\n27406\n27407\n27408\n27409\n27410\n27411\n27412\n27413\n27414\n27415\n27416\n27417\n27418\n27419\n27420\n27421\n27422\n27423\n27424\n27425\n27426\n27427\n27428\n27429\n27430\n27431\n27432\n27433\n27434\n27435\n27436\n27437\n27438\n27439\n27440\n27441\n27442\n27443\n27444\n27445\n27446\n27447\n27448\n27449\n27450\n27451\n27452\n27453\n27454\n27455\n27456\n27457\n27458\n27459\n27460\n27461\n27462\n27463\n27464\n27465\n27466\n27467\n27468\n27469\n27470\n27471\n27472\n27473\n27474\n27475\n27476\n27477\n27478\n27479\n27480\n27481\n27482\n27483\n27484\n27485\n27486\n27487\n27488\n27489\n27490\n27491\n27492\n27493\n27494\n27495\n27496\n27497\n27498\n27499\n27500\n27501\n27502\n27503\n27504\n27505\n27506\n27507\n27508\n27509\n27510\n27511\n27512\n27513\n27514\n27515\n27516\n27517\n27518\n27519\n27520\n27521\n27522\n27523\n27524\n27525\n27526\n27527\n27528\n27529\n27530\n27531\n27532\n27533\n27534\n27535\n27536\n27537\n27538\n27539\n27540\n27541\n27542\n27543\n27544\n27545\n27546\n27547\n27548\n27549\n27550\n27551\n27552\n27553\n27554\n27555\n27556\n27557\n27558\n27559\n27560\n27561\n27562\n27563\n27564\n27565\n27566\n27567\n27568\n27569\n27570\n27571\n27572\n27573\n27574\n27575\n27576\n27577\n27578\n27579\n27580\n27581\n27582\n27583\n27584\n27585\n27586\n27587\n27588\n27589\n27590\n27591\n27592\n27593\n27594\n27595\n27596\n27597\n27598\n27599\n27600\n27601\n27602\n27603\n27604\n27605\n27606\n27607\n27608\n27609\n27610\n27611\n27612\n27613\n27614\n27615\n27616\n27617\n27618\n27619\n27620\n27621\n27622\n27623\n27624\n27625\n27626\n27627\n27628\n27629\n27630\n27631\n27632\n27633\n27634\n27635\n27636\n27637\n27638\n27639\n27640\n27641\n27642\n27643\n27644\n27645\n27646\n27647\n27648\n27649\n27650\n27651\n27652\n27653\n27654\n27655\n27656\n27657\n27658\n27659\n27660\n27661\n27662\n27663\n27664\n27665\n27666\n27667\n27668\n27669\n27670\n27671\n27672\n27673\n27674\n27675\n27676\n27677\n27678\n27679\n27680\n27681\n27682\n27683\n27684\n27685\n27686\n27687\n27688\n27689\n27690\n27691\n27692\n27693\n27694\n27695\n27696\n27697\n27698\n27699\n27700\n27701\n27702\n27703\n27704\n27705\n27706\n27707\n27708\n27709\n27710\n27711\n27712\n27713\n27714\n27715\n27716\n27717\n27718\n27719\n27720\n27721\n27722\n27723\n27724\n27725\n27726\n27727\n27728\n27729\n27730\n27731\n27732\n27733\n27734\n27735\n27736\n27737\n27738\n27739\n27740\n27741\n27742\n27743\n27744\n27745\n27746\n27747\n27748\n27749\n27750\n27751\n27752\n27753\n27754\n27755\n27756\n27757\n27758\n27759\n27760\n27761\n27762\n27763\n27764\n27765\n27766\n27767\n27768\n27769\n27770\n27771\n27772\n27773\n27774\n27775\n27776\n27777\n27778\n27779\n27780\n27781\n27782\n27783\n27784\n27785\n27786\n27787\n27788\n27789\n27790\n27791\n27792\n27793\n27794\n27795\n27796\n27797\n27798\n27799\n27800\n27801\n27802\n27803\n27804\n27805\n27806\n27807\n27808\n27809\n27810\n27811\n27812\n27813\n27814\n27815\n27816\n27817\n27818\n27819\n27820\n27821\n27822\n27823\n27824\n27825\n27826\n27827\n27828\n27829\n27830\n27831\n27832\n27833\n27834\n27835\n27836\n27837\n27838\n27839\n27840\n27841\n27842\n27843\n27844\n27845\n27846\n27847\n27848\n27849\n27850\n27851\n27852\n27853\n27854\n27855\n27856\n27857\n27858\n27859\n27860\n27861\n27862\n27863\n27864\n27865\n27866\n27867\n27868\n27869\n27870\n27871\n27872\n27873\n27874\n27875\n27876\n27877\n27878\n27879\n27880\n27881\n27882\n27883\n27884\n27885\n27886\n27887\n27888\n27889\n27890\n27891\n27892\n27893\n27894\n27895\n27896\n27897\n27898\n27899\n27900\n27901\n27902\n27903\n27904\n27905\n27906\n27907\n27908\n27909\n27910\n27911\n27912\n27913\n27914\n27915\n27916\n27917\n27918\n27919\n27920\n27921\n27922\n27923\n27924\n27925\n27926\n27927\n27928\n27929\n27930\n27931\n27932\n27933\n27934\n27935\n27936\n27937\n27938\n27939\n27940\n27941\n27942\n27943\n27944\n27945\n27946\n27947\n27948\n27949\n27950\n27951\n27952\n27953\n27954\n27955\n27956\n27957\n27958\n27959\n27960\n27961\n27962\n27963\n27964\n27965\n27966\n27967\n27968\n27969\n27970\n27971\n27972\n27973\n27974\n27975\n27976\n27977\n27978\n27979\n27980\n27981\n27982\n27983\n27984\n27985\n27986\n27987\n27988\n27989\n27990\n27991\n27992\n27993\n27994\n27995\n27996\n27997\n27998\n27999\n28000\n28001\n28002\n28003\n28004\n28005\n28006\n28007\n28008\n28009\n28010\n28011\n28012\n28013\n28014\n28015\n28016\n28017\n28018\n28019\n28020\n28021\n28022\n28023\n28024\n28025\n28026\n28027\n28028\n28029\n28030\n28031\n28032\n28033\n28034\n28035\n28036\n28037\n28038\n28039\n28040\n28041\n28042\n28043\n28044\n28045\n28046\n28047\n28048\n28049\n28050\n28051\n28052\n28053\n28054\n28055\n28056\n28057\n28058\n28059\n28060\n28061\n28062\n28063\n28064\n28065\n28066\n28067\n28068\n28069\n28070\n28071\n28072\n28073\n28074\n28075\n28076\n28077\n28078\n28079\n28080\n28081\n28082\n28083\n28084\n28085\n28086\n28087\n28088\n28089\n28090\n28091\n28092\n28093\n28094\n28095\n28096\n28097\n28098\n28099\n28100\n28101\n28102\n28103\n28104\n28105\n28106\n28107\n28108\n28109\n28110\n28111\n28112\n28113\n28114\n28115\n28116\n28117\n28118\n28119\n28120\n28121\n28122\n28123\n28124\n28125\n28126\n28127\n28128\n28129\n28130\n28131\n28132\n28133\n28134\n28135\n28136\n28137\n28138\n28139\n28140\n28141\n28142\n28143\n28144\n28145\n28146\n28147\n28148\n28149\n28150\n28151\n28152\n28153\n28154\n28155\n28156\n28157\n28158\n28159\n28160\n28161\n28162\n28163\n28164\n28165\n28166\n28167\n28168\n28169\n28170\n28171\n28172\n28173\n28174\n28175\n28176\n28177\n28178\n28179\n28180\n28181\n28182\n28183\n28184\n28185\n28186\n28187\n28188\n28189\n28190\n28191\n28192\n28193\n28194\n28195\n28196\n28197\n28198\n28199\n28200\n28201\n28202\n28203\n28204\n28205\n28206\n28207\n28208\n28209\n28210\n28211\n28212\n28213\n28214\n28215\n28216\n28217\n28218\n28219\n28220\n28221\n28222\n28223\n28224\n28225\n28226\n28227\n28228\n28229\n28230\n28231\n28232\n28233\n28234\n28235\n28236\n28237\n28238\n28239\n28240\n28241\n28242\n28243\n28244\n28245\n28246\n28247\n28248\n28249\n28250\n28251\n28252\n28253\n28254\n28255\n28256\n28257\n28258\n28259\n28260\n28261\n28262\n28263\n28264\n28265\n28266\n28267\n28268\n28269\n28270\n28271\n28272\n28273\n28274\n28275\n28276\n28277\n28278\n28279\n28280\n28281\n28282\n28283\n28284\n28285\n28286\n28287\n28288\n28289\n28290\n28291\n28292\n28293\n28294\n28295\n28296\n28297\n28298\n28299\n28300\n28301\n28302\n28303\n28304\n28305\n28306\n28307\n28308\n28309\n28310\n28311\n28312\n28313\n28314\n28315\n28316\n28317\n28318\n28319\n28320\n28321\n28322\n28323\n28324\n28325\n28326\n28327\n28328\n28329\n28330\n28331\n28332\n28333\n28334\n28335\n28336\n28337\n28338\n28339\n28340\n28341\n28342\n28343\n28344\n28345\n28346\n28347\n28348\n28349\n28350\n28351\n28352\n28353\n28354\n28355\n28356\n28357\n28358\n28359\n28360\n28361\n28362\n28363\n28364\n28365\n28366\n28367\n28368\n28369\n28370\n28371\n28372\n28373\n28374\n28375\n28376\n28377\n28378\n28379\n28380\n28381\n28382\n28383\n28384\n28385\n28386\n28387\n28388\n28389\n28390\n28391\n28392\n28393\n28394\n28395\n28396\n28397\n28398\n28399\n28400\n28401\n28402\n28403\n28404\n28405\n28406\n28407\n28408\n28409\n28410\n28411\n28412\n28413\n28414\n28415\n28416\n28417\n28418\n28419\n28420\n28421\n28422\n28423\n28424\n28425\n28426\n28427\n28428\n28429\n28430\n28431\n28432\n28433\n28434\n28435\n28436\n28437\n28438\n28439\n28440\n28441\n28442\n28443\n28444\n28445\n28446\n28447\n28448\n28449\n28450\n28451\n28452\n28453\n28454\n28455\n28456\n28457\n28458\n28459\n28460\n28461\n28462\n28463\n28464\n28465\n28466\n28467\n28468\n28469\n28470\n28471\n28472\n28473\n28474\n28475\n28476\n28477\n28478\n28479\n28480\n28481\n28482\n28483\n28484\n28485\n28486\n28487\n28488\n28489\n28490\n28491\n28492\n28493\n28494\n28495\n28496\n28497\n28498\n28499\n28500\n28501\n28502\n28503\n28504\n28505\n28506\n28507\n28508\n28509\n28510\n28511\n28512\n28513\n28514\n28515\n28516\n28517\n28518\n28519\n28520\n28521\n28522\n28523\n28524\n28525\n28526\n28527\n28528\n28529\n28530\n28531\n28532\n28533\n28534\n28535\n28536\n28537\n28538\n28539\n28540\n28541\n28542\n28543\n28544\n28545\n28546\n28547\n28548\n28549\n28550\n28551\n28552\n28553\n28554\n28555\n28556\n28557\n28558\n28559\n28560\n28561\n28562\n28563\n28564\n28565\n28566\n28567\n28568\n28569\n28570\n28571\n28572\n28573\n28574\n28575\n28576\n28577\n28578\n28579\n28580\n28581\n28582\n28583\n28584\n28585\n28586\n28587\n28588\n28589\n28590\n28591\n28592\n28593\n28594\n28595\n28596\n28597\n28598\n28599\n28600\n28601\n28602\n28603\n28604\n28605\n28606\n28607\n28608\n28609\n28610\n28611\n28612\n28613\n28614\n28615\n28616\n28617\n28618\n28619\n28620\n28621\n28622\n28623\n28624\n28625\n28626\n28627\n28628\n28629\n28630\n28631\n28632\n28633\n28634\n28635\n28636\n28637\n28638\n28639\n28640\n28641\n28642\n28643\n28644\n28645\n28646\n28647\n28648\n28649\n28650\n28651\n28652\n28653\n28654\n28655\n28656\n28657\n28658\n28659\n28660\n28661\n28662\n28663\n28664\n28665\n28666\n28667\n28668\n28669\n28670\n28671\n28672\n28673\n28674\n28675\n28676\n28677\n28678\n28679\n28680\n28681\n28682\n28683\n28684\n28685\n28686\n28687\n28688\n28689\n28690\n28691\n28692\n28693\n28694\n28695\n28696\n28697\n28698\n28699\n28700\n28701\n28702\n28703\n28704\n28705\n28706\n28707\n28708\n28709\n28710\n28711\n28712\n28713\n28714\n28715\n28716\n28717\n28718\n28719\n28720\n28721\n28722\n28723\n28724\n28725\n28726\n28727\n28728\n28729\n28730\n28731\n28732\n28733\n28734\n28735\n28736\n28737\n28738\n28739\n28740\n28741\n28742\n28743\n28744\n28745\n28746\n28747\n28748\n28749\n28750\n28751\n28752\n28753\n28754\n28755\n28756\n28757\n28758\n28759\n28760\n28761\n28762\n28763\n28764\n28765\n28766\n28767\n28768\n28769\n28770\n28771\n28772\n28773\n28774\n28775\n28776\n28777\n28778\n28779\n28780\n28781\n28782\n28783\n28784\n28785\n28786\n28787\n28788\n28789\n28790\n28791\n28792\n28793\n28794\n28795\n28796\n28797\n28798\n28799\n28800\n28801\n28802\n28803\n28804\n28805\n28806\n28807\n28808\n28809\n28810\n28811\n28812\n28813\n28814\n28815\n28816\n28817\n28818\n28819\n28820\n28821\n28822\n28823\n28824\n28825\n28826\n28827\n28828\n28829\n28830\n28831\n28832\n28833\n28834\n28835\n28836\n28837\n28838\n28839\n28840\n28841\n28842\n28843\n28844\n28845\n28846\n28847\n28848\n28849\n28850\n28851\n28852\n28853\n28854\n28855\n28856\n28857\n28858\n28859\n28860\n28861\n28862\n28863\n28864\n28865\n28866\n28867\n28868\n28869\n28870\n28871\n28872\n28873\n28874\n28875\n28876\n28877\n28878\n28879\n28880\n28881\n28882\n28883\n28884\n28885\n28886\n28887\n28888\n28889\n28890\n28891\n28892\n28893\n28894\n28895\n28896\n28897\n28898\n28899\n28900\n28901\n28902\n28903\n28904\n28905\n28906\n28907\n28908\n28909\n28910\n28911\n28912\n28913\n28914\n28915\n28916\n28917\n28918\n28919\n28920\n28921\n28922\n28923\n28924\n28925\n28926\n28927\n28928\n28929\n28930\n28931\n28932\n28933\n28934\n28935\n28936\n28937\n28938\n28939\n28940\n28941\n28942\n28943\n28944\n28945\n28946\n28947\n28948\n28949\n28950\n28951\n28952\n28953\n28954\n28955\n28956\n28957\n28958\n28959\n28960\n28961\n28962\n28963\n28964\n28965\n28966\n28967\n28968\n28969\n28970\n28971\n28972\n28973\n28974\n28975\n28976\n28977\n28978\n28979\n28980\n28981\n28982\n28983\n28984\n28985\n28986\n28987\n28988\n28989\n28990\n28991\n28992\n28993\n28994\n28995\n28996\n28997\n28998\n28999\n29000\n29001\n29002\n29003\n29004\n29005\n29006\n29007\n29008\n29009\n29010\n29011\n29012\n29013\n29014\n29015\n29016\n29017\n29018\n29019\n29020\n29021\n29022\n29023\n29024\n29025\n29026\n29027\n29028\n29029\n29030\n29031\n29032\n29033\n29034\n29035\n29036\n29037\n29038\n29039\n29040\n29041\n29042\n29043\n29044\n29045\n29046\n29047\n29048\n29049\n29050\n29051\n29052\n29053\n29054\n29055\n29056\n29057\n29058\n29059\n29060\n29061\n29062\n29063\n29064\n29065\n29066\n29067\n29068\n29069\n29070\n29071\n29072\n29073\n29074\n29075\n29076\n29077\n29078\n29079\n29080\n29081\n29082\n29083\n29084\n29085\n29086\n29087\n29088\n29089\n29090\n29091\n29092\n29093\n29094\n29095\n29096\n29097\n29098\n29099\n29100\n29101\n29102\n29103\n29104\n29105\n29106\n29107\n29108\n29109\n29110\n29111\n29112\n29113\n29114\n29115\n29116\n29117\n29118\n29119\n29120\n29121\n29122\n29123\n29124\n29125\n29126\n29127\n29128\n29129\n29130\n29131\n29132\n29133\n29134\n29135\n29136\n29137\n29138\n29139\n29140\n29141\n29142\n29143\n29144\n29145\n29146\n29147\n29148\n29149\n29150\n29151\n29152\n29153\n29154\n29155\n29156\n29157\n29158\n29159\n29160\n29161\n29162\n29163\n29164\n29165\n29166\n29167\n29168\n29169\n29170\n29171\n29172\n29173\n29174\n29175\n29176\n29177\n29178\n29179\n29180\n29181\n29182\n29183\n29184\n29185\n29186\n29187\n29188\n29189\n29190\n29191\n29192\n29193\n29194\n29195\n29196\n29197\n29198\n29199\n29200\n29201\n29202\n29203\n29204\n29205\n29206\n29207\n29208\n29209\n29210\n29211\n29212\n29213\n29214\n29215\n29216\n29217\n29218\n29219\n29220\n29221\n29222\n29223\n29224\n29225\n29226\n29227\n29228\n29229\n29230\n29231\n29232\n29233\n29234\n29235\n29236\n29237\n29238\n29239\n29240\n29241\n29242\n29243\n29244\n29245\n29246\n29247\n29248\n29249\n29250\n29251\n29252\n29253\n29254\n29255\n29256\n29257\n29258\n29259\n29260\n29261\n29262\n29263\n29264\n29265\n29266\n29267\n29268\n29269\n29270\n29271\n29272\n29273\n29274\n29275\n29276\n29277\n29278\n29279\n29280\n29281\n29282\n29283\n29284\n29285\n29286\n29287\n29288\n29289\n29290\n29291\n29292\n29293\n29294\n29295\n29296\n29297\n29298\n29299\n29300\n29301\n29302\n29303\n29304\n29305\n29306\n29307\n29308\n29309\n29310\n29311\n29312\n29313\n29314\n29315\n29316\n29317\n29318\n29319\n29320\n29321\n29322\n29323\n29324\n29325\n29326\n29327\n29328\n29329\n29330\n29331\n29332\n29333\n29334\n29335\n29336\n29337\n29338\n29339\n29340\n29341\n29342\n29343\n29344\n29345\n29346\n29347\n29348\n29349\n29350\n29351\n29352\n29353\n29354\n29355\n29356\n29357\n29358\n29359\n29360\n29361\n29362\n29363\n29364\n29365\n29366\n29367\n29368\n29369\n29370\n29371\n29372\n29373\n29374\n29375\n29376\n29377\n29378\n29379\n29380\n29381\n29382\n29383\n29384\n29385\n29386\n29387\n29388\n29389\n29390\n29391\n29392\n29393\n29394\n29395\n29396\n29397\n29398\n29399\n29400\n29401\n29402\n29403\n29404\n29405\n29406\n29407\n29408\n29409\n29410\n29411\n29412\n29413\n29414\n29415\n29416\n29417\n29418\n29419\n29420\n29421\n29422\n29423\n29424\n29425\n29426\n29427\n29428\n29429\n29430\n29431\n29432\n29433\n29434\n29435\n29436\n29437\n29438\n29439\n29440\n29441\n29442\n29443\n29444\n29445\n29446\n29447\n29448\n29449\n29450\n29451\n29452\n29453\n29454\n29455\n29456\n29457\n29458\n29459\n29460\n29461\n29462\n29463\n29464\n29465\n29466\n29467\n29468\n29469\n29470\n29471\n29472\n29473\n29474\n29475\n29476\n29477\n29478\n29479\n29480\n29481\n29482\n29483\n29484\n29485\n29486\n29487\n29488\n29489\n29490\n29491\n29492\n29493\n29494\n29495\n29496\n29497\n29498\n29499\n29500\n29501\n29502\n29503\n29504\n29505\n29506\n29507\n29508\n29509\n29510\n29511\n29512\n29513\n29514\n29515\n29516\n29517\n29518\n29519\n29520\n29521\n29522\n29523\n29524\n29525\n29526\n29527\n29528\n29529\n29530\n29531\n29532\n29533\n29534\n29535\n29536\n29537\n29538\n29539\n29540\n29541\n29542\n29543\n29544\n29545\n29546\n29547\n29548\n29549\n29550\n29551\n29552\n29553\n29554\n29555\n29556\n29557\n29558\n29559\n29560\n29561\n29562\n29563\n29564\n29565\n29566\n29567\n29568\n29569\n29570\n29571\n29572\n29573\n29574\n29575\n29576\n29577\n29578\n29579\n29580\n29581\n29582\n29583\n29584\n29585\n29586\n29587\n29588\n29589\n29590\n29591\n29592\n29593\n29594\n29595\n29596\n29597\n29598\n29599\n29600\n29601\n29602\n29603\n29604\n29605\n29606\n29607\n29608\n29609\n29610\n29611\n29612\n29613\n29614\n29615\n29616\n29617\n29618\n29619\n29620\n29621\n29622\n29623\n29624\n29625\n29626\n29627\n29628\n29629\n29630\n29631\n29632\n29633\n29634\n29635\n29636\n29637\n29638\n29639\n29640\n29641\n29642\n29643\n29644\n29645\n29646\n29647\n29648\n29649\n29650\n29651\n29652\n29653\n29654\n29655\n29656\n29657\n29658\n29659\n29660\n29661\n29662\n29663\n29664\n29665\n29666\n29667\n29668\n29669\n29670\n29671\n29672\n29673\n29674\n29675\n29676\n29677\n29678\n29679\n29680\n29681\n29682\n29683\n29684\n29685\n29686\n29687\n29688\n29689\n29690\n29691\n29692\n29693\n29694\n29695\n29696\n29697\n29698\n29699\n29700\n29701\n29702\n29703\n29704\n29705\n29706\n29707\n29708\n29709\n29710\n29711\n29712\n29713\n29714\n29715\n29716\n29717\n29718\n29719\n29720\n29721\n29722\n29723\n29724\n29725\n29726\n29727\n29728\n29729\n29730\n29731\n29732\n29733\n29734\n29735\n29736\n29737\n29738\n29739\n29740\n29741\n29742\n29743\n29744\n29745\n29746\n29747\n29748\n29749\n29750\n29751\n29752\n29753\n29754\n29755\n29756\n29757\n29758\n29759\n29760\n29761\n29762\n29763\n29764\n29765\n29766\n29767\n29768\n29769\n29770\n29771\n29772\n29773\n29774\n29775\n29776\n29777\n29778\n29779\n29780\n29781\n29782\n29783\n29784\n29785\n29786\n29787\n29788\n29789\n29790\n29791\n29792\n29793\n29794\n29795\n29796\n29797\n29798\n29799\n29800\n29801\n29802\n29803\n29804\n29805\n29806\n29807\n29808\n29809\n29810\n29811\n29812\n29813\n29814\n29815\n29816\n29817\n29818\n29819\n29820\n29821\n29822\n29823\n29824\n29825\n29826\n29827\n29828\n29829\n29830\n29831\n29832\n29833\n29834\n29835\n29836\n29837\n29838\n29839\n29840\n29841\n29842\n29843\n29844\n29845\n29846\n29847\n29848\n29849\n29850\n29851\n29852\n29853\n29854\n29855\n29856\n29857\n29858\n29859\n29860\n29861\n29862\n29863\n29864\n29865\n29866\n29867\n29868\n29869\n29870\n29871\n29872\n29873\n29874\n29875\n29876\n29877\n29878\n29879\n29880\n29881\n29882\n29883\n29884\n29885\n29886\n29887\n29888\n29889\n29890\n29891\n29892\n29893\n29894\n29895\n29896\n29897\n29898\n29899\n29900\n29901\n29902\n29903\n29904\n29905\n29906\n29907\n29908\n29909\n29910\n29911\n29912\n29913\n29914\n29915\n29916\n29917\n29918\n29919\n29920\n29921\n29922\n29923\n29924\n29925\n29926\n29927\n29928\n29929\n29930\n29931\n29932\n29933\n29934\n29935\n29936\n29937\n29938\n29939\n29940\n29941\n29942\n29943\n29944\n29945\n29946\n29947\n29948\n29949\n29950\n29951\n29952\n29953\n29954\n29955\n29956\n29957\n29958\n29959\n29960\n29961\n29962\n29963\n29964\n29965\n29966\n29967\n29968\n29969\n29970\n29971\n29972\n29973\n29974\n29975\n29976\n29977\n29978\n29979\n29980\n29981\n29982\n29983\n29984\n29985\n29986\n29987\n29988\n29989\n29990\n29991\n29992\n29993\n29994\n29995\n29996\n29997\n29998\n29999' \ No newline at end of file diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test11.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test11.arff new file mode 100644 index 0000000000000000000000000000000000000000..fadfaee884e3e91cd59f691afd954a6a6d4042da --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test11.arff @@ -0,0 +1,11 @@ +@RELATION test11 + +@ATTRIBUTE attr0 REAL +@ATTRIBUTE attr1 REAL +@ATTRIBUTE attr2 REAL +@ATTRIBUTE attr3 REAL +@ATTRIBUTE class { class0, class1, class2, class3 } +@DATA +0.1, 0.2, 0.3, 0.4,class1 +-0.1, -0.2, -0.3, -0.4,class2 +1, 2, 3, 4,class3 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test2.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test2.arff new file mode 100644 index 0000000000000000000000000000000000000000..30f0dbf91b078ef670868d5e7321f956a6a7a506 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test2.arff @@ -0,0 +1,15 @@ +@RELATION test2 + +@ATTRIBUTE attr0 REAL +@ATTRIBUTE attr1 real +@ATTRIBUTE attr2 integer +@ATTRIBUTE attr3 Integer +@ATTRIBUTE attr4 Numeric +@ATTRIBUTE attr5 numeric +@ATTRIBUTE attr6 string +@ATTRIBUTE attr7 STRING +@ATTRIBUTE attr8 {bla} +@ATTRIBUTE attr9 {bla, bla} + +@DATA +0.1, 0.2, 0.3, 0.4,class1 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test3.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test3.arff new file mode 100644 index 0000000000000000000000000000000000000000..23da3b30967fcc95d70883f70be9ef6e39d577fa --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test3.arff @@ -0,0 +1,6 @@ +@RELATION test3 + +@ATTRIBUTE attr0 crap + +@DATA +0.1, 0.2, 0.3, 0.4,class1 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test4.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test4.arff new file mode 100644 index 0000000000000000000000000000000000000000..bf5f99ca89375fbd980185fd25711901f23ff844 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test4.arff @@ -0,0 +1,11 @@ +@RELATION test5 + +@ATTRIBUTE attr0 REAL +@ATTRIBUTE attr1 REAL +@ATTRIBUTE attr2 REAL +@ATTRIBUTE attr3 REAL +@ATTRIBUTE class {class0, class1, class2, class3} +@DATA +0.1, 0.2, 0.3, 0.4,class1 +-0.1, -0.2, -0.3, -0.4,class2 +1, 2, 3, 4,class3 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test5.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test5.arff new file mode 100644 index 0000000000000000000000000000000000000000..0075daf05e7792e80dcd565e791ce40e4dd49e85 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test5.arff @@ -0,0 +1,26 @@ +@RELATION test4 + +@ATTRIBUTE attr0 REAL +@ATTRIBUTE attr1 REAL +@ATTRIBUTE attr2 REAL +@ATTRIBUTE attr3 REAL +@ATTRIBUTE class {class0, class1, class2, class3} + +@DATA + +% lsdflkjhaksjdhf + +% lsdflkjhaksjdhf + +0.1, 0.2, 0.3, 0.4,class1 +% laksjdhf + +% lsdflkjhaksjdhf +-0.1, -0.2, -0.3, -0.4,class2 + +% lsdflkjhaksjdhf +% lsdflkjhaksjdhf + +% lsdflkjhaksjdhf + +1, 2, 3, 4,class3 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test6.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test6.arff new file mode 100644 index 0000000000000000000000000000000000000000..b63280b03aef8e0553a83fbf96692d280a3f86b7 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test6.arff @@ -0,0 +1,12 @@ +@RELATION test6 + +@ATTRIBUTE attr0 REAL +@ATTRIBUTE attr1 REAL +@ATTRIBUTE attr2 REAL +@ATTRIBUTE attr3 REAL +@ATTRIBUTE class {C} + +@DATA +0.1, 0.2, 0.3, 0.4,C +-0.1, -0.2, -0.3, -0.4,C +1, 2, 3, 4,C diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test7.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test7.arff new file mode 100644 index 0000000000000000000000000000000000000000..38ef6c9a7a10afb10caa5913687ea3636ab1d38e --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test7.arff @@ -0,0 +1,15 @@ +@RELATION test7 + +@ATTRIBUTE attr_year DATE yyyy +@ATTRIBUTE attr_month DATE yyyy-MM +@ATTRIBUTE attr_date DATE yyyy-MM-dd +@ATTRIBUTE attr_datetime_local DATE "yyyy-MM-dd HH:mm" +@ATTRIBUTE attr_datetime_missing DATE "yyyy-MM-dd HH:mm" + +@DATA +1999,1999-01,1999-01-31,"1999-01-31 00:01",? +2004,2004-12,2004-12-01,"2004-12-01 23:59","2004-12-01 23:59" +1817,1817-04,1817-04-28,"1817-04-28 13:00",? +2100,2100-09,2100-09-10,"2100-09-10 12:00",? +2013,2013-11,2013-11-30,"2013-11-30 04:55","2013-11-30 04:55" +1631,1631-10,1631-10-15,"1631-10-15 20:04","1631-10-15 20:04" \ No newline at end of file diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test8.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test8.arff new file mode 100644 index 0000000000000000000000000000000000000000..776deb4c9e7550eafdb26d16826f5651da37ef12 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test8.arff @@ -0,0 +1,12 @@ +@RELATION test8 + +@ATTRIBUTE attr_datetime_utc DATE "yyyy-MM-dd HH:mm Z" +@ATTRIBUTE attr_datetime_full DATE "yy-MM-dd HH:mm:ss z" + +@DATA +"1999-01-31 00:01 UTC","99-01-31 00:01:08 +0430" +"2004-12-01 23:59 UTC","04-12-01 23:59:59 -0800" +"1817-04-28 13:00 UTC","17-04-28 13:00:33 +1000" +"2100-09-10 12:00 UTC","21-09-10 12:00:21 -0300" +"2013-11-30 04:55 UTC","13-11-30 04:55:48 -1100" +"1631-10-15 20:04 UTC","31-10-15 20:04:10 +0000" \ No newline at end of file diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test9.arff b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test9.arff new file mode 100644 index 0000000000000000000000000000000000000000..b3f97e32a3fd4909a3f9cbf8d5d2e8d250f8dbad --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/data/test9.arff @@ -0,0 +1,14 @@ +@RELATION test9 + +@ATTRIBUTE attr_date_number RELATIONAL + @ATTRIBUTE attr_date DATE "yyyy-MM-dd" + @ATTRIBUTE attr_number INTEGER +@END attr_date_number + +@DATA +"1999-01-31 1\n1935-11-27 10" +"2004-12-01 2\n1942-08-13 20" +"1817-04-28 3" +"2100-09-10 4\n1957-04-17 40\n1721-01-14 400" +"2013-11-30 5" +"1631-10-15 6" \ No newline at end of file diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/test_arffread.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/test_arffread.py new file mode 100644 index 0000000000000000000000000000000000000000..b8882e73bbae7b6a423638d87255bdfae77797a9 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/arff/tests/test_arffread.py @@ -0,0 +1,421 @@ +import datetime +import os +import sys +from os.path import join as pjoin + +from io import StringIO + +import numpy as np + +from numpy.testing import (assert_array_almost_equal, + assert_array_equal, assert_equal, assert_) +from pytest import raises as assert_raises + +from scipy.io.arff import loadarff +from scipy.io.arff._arffread import read_header, ParseArffError + + +data_path = pjoin(os.path.dirname(__file__), 'data') + +test1 = pjoin(data_path, 'test1.arff') +test2 = pjoin(data_path, 'test2.arff') +test3 = pjoin(data_path, 'test3.arff') + +test4 = pjoin(data_path, 'test4.arff') +test5 = pjoin(data_path, 'test5.arff') +test6 = pjoin(data_path, 'test6.arff') +test7 = pjoin(data_path, 'test7.arff') +test8 = pjoin(data_path, 'test8.arff') +test9 = pjoin(data_path, 'test9.arff') +test10 = pjoin(data_path, 'test10.arff') +test11 = pjoin(data_path, 'test11.arff') +test_quoted_nominal = pjoin(data_path, 'quoted_nominal.arff') +test_quoted_nominal_spaces = pjoin(data_path, 'quoted_nominal_spaces.arff') + +expect4_data = [(0.1, 0.2, 0.3, 0.4, 'class1'), + (-0.1, -0.2, -0.3, -0.4, 'class2'), + (1, 2, 3, 4, 'class3')] +expected_types = ['numeric', 'numeric', 'numeric', 'numeric', 'nominal'] + +missing = pjoin(data_path, 'missing.arff') +expect_missing_raw = np.array([[1, 5], [2, 4], [np.nan, np.nan]]) +expect_missing = np.empty(3, [('yop', float), ('yap', float)]) +expect_missing['yop'] = expect_missing_raw[:, 0] +expect_missing['yap'] = expect_missing_raw[:, 1] + + +class TestData: + def test1(self): + # Parsing trivial file with nothing. + self._test(test4) + + def test2(self): + # Parsing trivial file with some comments in the data section. + self._test(test5) + + def test3(self): + # Parsing trivial file with nominal attribute of 1 character. + self._test(test6) + + def test4(self): + # Parsing trivial file with trailing spaces in attribute declaration. + self._test(test11) + + def _test(self, test_file): + data, meta = loadarff(test_file) + for i in range(len(data)): + for j in range(4): + assert_array_almost_equal(expect4_data[i][j], data[i][j]) + assert_equal(meta.types(), expected_types) + + def test_filelike(self): + # Test reading from file-like object (StringIO) + with open(test1) as f1: + data1, meta1 = loadarff(f1) + with open(test1) as f2: + data2, meta2 = loadarff(StringIO(f2.read())) + assert_(data1 == data2) + assert_(repr(meta1) == repr(meta2)) + + def test_path(self): + # Test reading from `pathlib.Path` object + from pathlib import Path + + with open(test1) as f1: + data1, meta1 = loadarff(f1) + + data2, meta2 = loadarff(Path(test1)) + + assert_(data1 == data2) + assert_(repr(meta1) == repr(meta2)) + + +class TestMissingData: + def test_missing(self): + data, meta = loadarff(missing) + for i in ['yop', 'yap']: + assert_array_almost_equal(data[i], expect_missing[i]) + + +class TestNoData: + def test_nodata(self): + # The file nodata.arff has no data in the @DATA section. + # Reading it should result in an array with length 0. + nodata_filename = os.path.join(data_path, 'nodata.arff') + data, meta = loadarff(nodata_filename) + if sys.byteorder == 'big': + end = '>' + else: + end = '<' + expected_dtype = np.dtype([('sepallength', f'{end}f8'), + ('sepalwidth', f'{end}f8'), + ('petallength', f'{end}f8'), + ('petalwidth', f'{end}f8'), + ('class', 'S15')]) + assert_equal(data.dtype, expected_dtype) + assert_equal(data.size, 0) + + +class TestHeader: + def test_type_parsing(self): + # Test parsing type of attribute from their value. + with open(test2) as ofile: + rel, attrs = read_header(ofile) + + expected = ['numeric', 'numeric', 'numeric', 'numeric', 'numeric', + 'numeric', 'string', 'string', 'nominal', 'nominal'] + + for i in range(len(attrs)): + assert_(attrs[i].type_name == expected[i]) + + def test_badtype_parsing(self): + # Test parsing wrong type of attribute from their value. + def badtype_read(): + with open(test3) as ofile: + _, _ = read_header(ofile) + + assert_raises(ParseArffError, badtype_read) + + def test_fullheader1(self): + # Parsing trivial header with nothing. + with open(test1) as ofile: + rel, attrs = read_header(ofile) + + # Test relation + assert_(rel == 'test1') + + # Test numerical attributes + assert_(len(attrs) == 5) + for i in range(4): + assert_(attrs[i].name == f'attr{i}') + assert_(attrs[i].type_name == 'numeric') + + # Test nominal attribute + assert_(attrs[4].name == 'class') + assert_(attrs[4].values == ('class0', 'class1', 'class2', 'class3')) + + def test_dateheader(self): + with open(test7) as ofile: + rel, attrs = read_header(ofile) + + assert_(rel == 'test7') + + assert_(len(attrs) == 5) + + assert_(attrs[0].name == 'attr_year') + assert_(attrs[0].date_format == '%Y') + + assert_(attrs[1].name == 'attr_month') + assert_(attrs[1].date_format == '%Y-%m') + + assert_(attrs[2].name == 'attr_date') + assert_(attrs[2].date_format == '%Y-%m-%d') + + assert_(attrs[3].name == 'attr_datetime_local') + assert_(attrs[3].date_format == '%Y-%m-%d %H:%M') + + assert_(attrs[4].name == 'attr_datetime_missing') + assert_(attrs[4].date_format == '%Y-%m-%d %H:%M') + + def test_dateheader_unsupported(self): + def read_dateheader_unsupported(): + with open(test8) as ofile: + _, _ = read_header(ofile) + + assert_raises(ValueError, read_dateheader_unsupported) + + +class TestDateAttribute: + def setup_method(self): + self.data, self.meta = loadarff(test7) + + def test_year_attribute(self): + expected = np.array([ + '1999', + '2004', + '1817', + '2100', + '2013', + '1631' + ], dtype='datetime64[Y]') + + assert_array_equal(self.data["attr_year"], expected) + + def test_month_attribute(self): + expected = np.array([ + '1999-01', + '2004-12', + '1817-04', + '2100-09', + '2013-11', + '1631-10' + ], dtype='datetime64[M]') + + assert_array_equal(self.data["attr_month"], expected) + + def test_date_attribute(self): + expected = np.array([ + '1999-01-31', + '2004-12-01', + '1817-04-28', + '2100-09-10', + '2013-11-30', + '1631-10-15' + ], dtype='datetime64[D]') + + assert_array_equal(self.data["attr_date"], expected) + + def test_datetime_local_attribute(self): + expected = np.array([ + datetime.datetime(year=1999, month=1, day=31, hour=0, minute=1), + datetime.datetime(year=2004, month=12, day=1, hour=23, minute=59), + datetime.datetime(year=1817, month=4, day=28, hour=13, minute=0), + datetime.datetime(year=2100, month=9, day=10, hour=12, minute=0), + datetime.datetime(year=2013, month=11, day=30, hour=4, minute=55), + datetime.datetime(year=1631, month=10, day=15, hour=20, minute=4) + ], dtype='datetime64[m]') + + assert_array_equal(self.data["attr_datetime_local"], expected) + + def test_datetime_missing(self): + expected = np.array([ + 'nat', + '2004-12-01T23:59', + 'nat', + 'nat', + '2013-11-30T04:55', + '1631-10-15T20:04' + ], dtype='datetime64[m]') + + assert_array_equal(self.data["attr_datetime_missing"], expected) + + def test_datetime_timezone(self): + assert_raises(ParseArffError, loadarff, test8) + + +class TestRelationalAttribute: + def setup_method(self): + self.data, self.meta = loadarff(test9) + + def test_attributes(self): + assert_equal(len(self.meta._attributes), 1) + + relational = list(self.meta._attributes.values())[0] + + assert_equal(relational.name, 'attr_date_number') + assert_equal(relational.type_name, 'relational') + assert_equal(len(relational.attributes), 2) + assert_equal(relational.attributes[0].name, + 'attr_date') + assert_equal(relational.attributes[0].type_name, + 'date') + assert_equal(relational.attributes[1].name, + 'attr_number') + assert_equal(relational.attributes[1].type_name, + 'numeric') + + def test_data(self): + dtype_instance = [('attr_date', 'datetime64[D]'), + ('attr_number', np.float64)] + + expected = [ + np.array([('1999-01-31', 1), ('1935-11-27', 10)], + dtype=dtype_instance), + np.array([('2004-12-01', 2), ('1942-08-13', 20)], + dtype=dtype_instance), + np.array([('1817-04-28', 3)], + dtype=dtype_instance), + np.array([('2100-09-10', 4), ('1957-04-17', 40), + ('1721-01-14', 400)], + dtype=dtype_instance), + np.array([('2013-11-30', 5)], + dtype=dtype_instance), + np.array([('1631-10-15', 6)], + dtype=dtype_instance) + ] + + for i in range(len(self.data["attr_date_number"])): + assert_array_equal(self.data["attr_date_number"][i], + expected[i]) + + +class TestRelationalAttributeLong: + def setup_method(self): + self.data, self.meta = loadarff(test10) + + def test_attributes(self): + assert_equal(len(self.meta._attributes), 1) + + relational = list(self.meta._attributes.values())[0] + + assert_equal(relational.name, 'attr_relational') + assert_equal(relational.type_name, 'relational') + assert_equal(len(relational.attributes), 1) + assert_equal(relational.attributes[0].name, + 'attr_number') + assert_equal(relational.attributes[0].type_name, 'numeric') + + def test_data(self): + dtype_instance = [('attr_number', np.float64)] + + expected = np.array([(n,) for n in range(30000)], + dtype=dtype_instance) + + assert_array_equal(self.data["attr_relational"][0], + expected) + + +class TestQuotedNominal: + """ + Regression test for issue #10232: + + Exception in loadarff with quoted nominal attributes. + """ + + def setup_method(self): + self.data, self.meta = loadarff(test_quoted_nominal) + + def test_attributes(self): + assert_equal(len(self.meta._attributes), 2) + + age, smoker = self.meta._attributes.values() + + assert_equal(age.name, 'age') + assert_equal(age.type_name, 'numeric') + assert_equal(smoker.name, 'smoker') + assert_equal(smoker.type_name, 'nominal') + assert_equal(smoker.values, ['yes', 'no']) + + def test_data(self): + + age_dtype_instance = np.float64 + smoker_dtype_instance = '' (big endian) + +''' +import sys + +__all__ = [ + 'aliases', 'native_code', 'swapped_code', + 'sys_is_le', 'to_numpy_code' +] + +sys_is_le = sys.byteorder == 'little' +native_code = sys_is_le and '<' or '>' +swapped_code = sys_is_le and '>' or '<' + +aliases = {'little': ('little', '<', 'l', 'le'), + 'big': ('big', '>', 'b', 'be'), + 'native': ('native', '='), + 'swapped': ('swapped', 'S')} + + +def to_numpy_code(code): + """ + Convert various order codings to NumPy format. + + Parameters + ---------- + code : str + The code to convert. It is converted to lower case before parsing. + Legal values are: + 'little', 'big', 'l', 'b', 'le', 'be', '<', '>', 'native', '=', + 'swapped', 's'. + + Returns + ------- + out_code : {'<', '>'} + Here '<' is the numpy dtype code for little endian, + and '>' is the code for big endian. + + Examples + -------- + >>> import sys + >>> from scipy.io.matlab._byteordercodes import to_numpy_code + >>> sys_is_le = (sys.byteorder == 'little') + >>> sys_is_le + True + >>> to_numpy_code('big') + '>' + >>> to_numpy_code('little') + '<' + >>> nc = to_numpy_code('native') + >>> nc == '<' if sys_is_le else nc == '>' + True + >>> sc = to_numpy_code('swapped') + >>> sc == '>' if sys_is_le else sc == '<' + True + + """ + code = code.lower() + if code is None: + return native_code + if code in aliases['little']: + return '<' + elif code in aliases['big']: + return '>' + elif code in aliases['native']: + return native_code + elif code in aliases['swapped']: + return swapped_code + else: + raise ValueError( + f'We cannot handle byte order {code}') diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_mio.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_mio.py new file mode 100644 index 0000000000000000000000000000000000000000..b7c6a47fa4e648e30d7bead268cbab53d5ca03a0 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_mio.py @@ -0,0 +1,377 @@ +""" +Module for reading and writing matlab (TM) .mat files +""" +# Authors: Travis Oliphant, Matthew Brett + +from contextlib import contextmanager + +from ._miobase import _get_matfile_version, docfiller +from ._mio4 import MatFile4Reader, MatFile4Writer +from ._mio5 import MatFile5Reader, MatFile5Writer + +__all__ = ['loadmat', 'savemat', 'whosmat'] + + +@contextmanager +def _open_file_context(file_like, appendmat, mode='rb'): + f, opened = _open_file(file_like, appendmat, mode) + try: + yield f + finally: + if opened: + f.close() + + +def _open_file(file_like, appendmat, mode='rb'): + """ + Open `file_like` and return as file-like object. First, check if object is + already file-like; if so, return it as-is. Otherwise, try to pass it + to open(). If that fails, and `file_like` is a string, and `appendmat` is true, + append '.mat' and try again. + """ + reqs = {'read'} if set(mode) & set('r+') else set() + if set(mode) & set('wax+'): + reqs.add('write') + if reqs.issubset(dir(file_like)): + return file_like, False + + try: + return open(file_like, mode), True + except OSError as e: + # Probably "not found" + if isinstance(file_like, str): + if appendmat and not file_like.endswith('.mat'): + file_like += '.mat' + return open(file_like, mode), True + else: + raise OSError( + 'Reader needs file name or open file-like object' + ) from e + + +@docfiller +def mat_reader_factory(file_name, appendmat=True, **kwargs): + """ + Create reader for matlab .mat format files. + + Parameters + ---------- + %(file_arg)s + %(append_arg)s + %(load_args)s + %(struct_arg)s + + Returns + ------- + matreader : MatFileReader object + Initialized instance of MatFileReader class matching the mat file + type detected in `filename`. + file_opened : bool + Whether the file was opened by this routine. + + """ + byte_stream, file_opened = _open_file(file_name, appendmat) + mjv, mnv = _get_matfile_version(byte_stream) + if mjv == 0: + return MatFile4Reader(byte_stream, **kwargs), file_opened + elif mjv == 1: + return MatFile5Reader(byte_stream, **kwargs), file_opened + elif mjv == 2: + raise NotImplementedError('Please use HDF reader for matlab v7.3 ' + 'files, e.g. h5py') + else: + raise TypeError(f'Did not recognize version {mjv}') + + +@docfiller +def loadmat(file_name, mdict=None, appendmat=True, *, spmatrix=True, **kwargs): + """ + Load MATLAB file. + + Parameters + ---------- + file_name : str + Name of the mat file (do not need .mat extension if + appendmat==True). Can also pass open file-like object. + mdict : dict, optional + Dictionary in which to insert matfile variables. + appendmat : bool, optional + True to append the .mat extension to the end of the given + filename, if not already present. Default is True. + spmatrix : bool, optional (default: True) + If ``True``, return sparse matrix. Otherwise return sparse array. + Format is `COO` for MatFile 4 and `CSC` for MatFile 5. + Only relevant for sparse variables. + byte_order : str or None, optional + None by default, implying byte order guessed from mat + file. Otherwise can be one of ('native', '=', 'little', '<', + 'BIG', '>'). + mat_dtype : bool, optional + If True, return arrays in same dtype as would be loaded into + MATLAB (instead of the dtype with which they are saved). + squeeze_me : bool, optional + Whether to squeeze unit matrix dimensions or not. + chars_as_strings : bool, optional + Whether to convert char arrays to string arrays. + matlab_compatible : bool, optional + Returns matrices as would be loaded by MATLAB (implies + squeeze_me=False, chars_as_strings=False, mat_dtype=True, + struct_as_record=True). + struct_as_record : bool, optional + Whether to load MATLAB structs as NumPy record arrays, or as + old-style NumPy arrays with dtype=object. Setting this flag to + False replicates the behavior of scipy version 0.7.x (returning + NumPy object arrays). The default setting is True, because it + allows easier round-trip load and save of MATLAB files. + verify_compressed_data_integrity : bool, optional + Whether the length of compressed sequences in the MATLAB file + should be checked, to ensure that they are not longer than we expect. + It is advisable to enable this (the default) because overlong + compressed sequences in MATLAB files generally indicate that the + files have experienced some sort of corruption. + variable_names : None or sequence + If None (the default) - read all variables in file. Otherwise, + `variable_names` should be a sequence of strings, giving names of the + MATLAB variables to read from the file. The reader will skip any + variable with a name not in this sequence, possibly saving some read + processing. + simplify_cells : False, optional + If True, return a simplified dict structure (which is useful if the mat + file contains cell arrays). Note that this only affects the structure + of the result and not its contents (which is identical for both output + structures). If True, this automatically sets `struct_as_record` to + False and `squeeze_me` to True, which is required to simplify cells. + uint16_codec : str, optional + The codec to use for decoding characters, which are stored as uint16 + values. The default uses the system encoding, but this can be manually + set to other values such as 'ascii', 'latin1', and 'utf-8'. This + parameter is relevant only for files stored as v6 and above, and not + for files stored as v4. + + Returns + ------- + mat_dict : dict + dictionary with variable names as keys, and loaded matrices as values. + + Notes + ----- + v4 (Level 1.0), v6 and v7 to 7.2 matfiles are supported. + + You will need an HDF5 Python library to read MATLAB 7.3 format mat + files. Because SciPy does not supply one, we do not implement the + HDF5 / 7.3 interface here. + + Examples + -------- + >>> from os.path import dirname, join as pjoin + >>> import scipy.io as sio + + Get the filename for an example .mat file from the tests/data directory. + + >>> data_dir = pjoin(dirname(sio.__file__), 'matlab', 'tests', 'data') + >>> mat_fname = pjoin(data_dir, 'testdouble_7.4_GLNX86.mat') + + Load the .mat file contents. + + >>> mat_contents = sio.loadmat(mat_fname, spmatrix=False) + + The result is a dictionary, one key/value pair for each variable: + + >>> sorted(mat_contents.keys()) + ['__globals__', '__header__', '__version__', 'testdouble'] + >>> mat_contents['testdouble'] + array([[0. , 0.78539816, 1.57079633, 2.35619449, 3.14159265, + 3.92699082, 4.71238898, 5.49778714, 6.28318531]]) + + By default SciPy reads MATLAB structs as structured NumPy arrays where the + dtype fields are of type `object` and the names correspond to the MATLAB + struct field names. This can be disabled by setting the optional argument + `struct_as_record=False`. + + Get the filename for an example .mat file that contains a MATLAB struct + called `teststruct` and load the contents. + + >>> matstruct_fname = pjoin(data_dir, 'teststruct_7.4_GLNX86.mat') + >>> matstruct_contents = sio.loadmat(matstruct_fname) + >>> teststruct = matstruct_contents['teststruct'] + >>> teststruct.dtype + dtype([('stringfield', 'O'), ('doublefield', 'O'), ('complexfield', 'O')]) + + The size of the structured array is the size of the MATLAB struct, not the + number of elements in any particular field. The shape defaults to 2-D + unless the optional argument `squeeze_me=True`, in which case all length 1 + dimensions are removed. + + >>> teststruct.size + 1 + >>> teststruct.shape + (1, 1) + + Get the 'stringfield' of the first element in the MATLAB struct. + + >>> teststruct[0, 0]['stringfield'] + array(['Rats live on no evil star.'], + dtype='>> teststruct['doublefield'][0, 0] + array([[ 1.41421356, 2.71828183, 3.14159265]]) + + Load the MATLAB struct, squeezing out length 1 dimensions, and get the item + from the 'complexfield'. + + >>> matstruct_squeezed = sio.loadmat(matstruct_fname, squeeze_me=True) + >>> matstruct_squeezed['teststruct'].shape + () + >>> matstruct_squeezed['teststruct']['complexfield'].shape + () + >>> matstruct_squeezed['teststruct']['complexfield'].item() + array([ 1.41421356+1.41421356j, 2.71828183+2.71828183j, + 3.14159265+3.14159265j]) + """ + variable_names = kwargs.pop('variable_names', None) + with _open_file_context(file_name, appendmat) as f: + MR, _ = mat_reader_factory(f, **kwargs) + matfile_dict = MR.get_variables(variable_names) + if spmatrix: + from scipy.sparse import issparse, coo_matrix, csc_matrix + for name, var in list(matfile_dict.items()): + if issparse(var): + fmt_matrix = coo_matrix if var.format == "coo" else csc_matrix + matfile_dict[name] = fmt_matrix(var) + + if mdict is not None: + mdict.update(matfile_dict) + else: + mdict = matfile_dict + + return mdict + + +@docfiller +def savemat(file_name, mdict, + appendmat=True, + format='5', + long_field_names=False, + do_compression=False, + oned_as='row'): + """ + Save a dictionary of names and arrays into a MATLAB-style .mat file. + + This saves the array objects in the given dictionary to a MATLAB- + style .mat file. + + Parameters + ---------- + file_name : str or file-like object + Name of the .mat file (.mat extension not needed if ``appendmat == + True``). + Can also pass open file_like object. + mdict : dict + Dictionary from which to save matfile variables. Note that if this dict + has a key starting with ``_`` or a sub-dict has a key starting with ``_`` + or a digit, these key's items will not be saved in the mat file and + `MatWriteWarning` will be issued. + appendmat : bool, optional + True (the default) to append the .mat extension to the end of the + given filename, if not already present. + format : {'5', '4'}, string, optional + '5' (the default) for MATLAB 5 and up (to 7.2), + '4' for MATLAB 4 .mat files. + long_field_names : bool, optional + False (the default) - maximum field name length in a structure is + 31 characters which is the documented maximum length. + True - maximum field name length in a structure is 63 characters + which works for MATLAB 7.6+. + do_compression : bool, optional + Whether or not to compress matrices on write. Default is False. + oned_as : {'row', 'column'}, optional + If 'column', write 1-D NumPy arrays as column vectors. + If 'row', write 1-D NumPy arrays as row vectors. + + Examples + -------- + >>> from scipy.io import savemat + >>> import numpy as np + >>> a = np.arange(20) + >>> mdic = {"a": a, "label": "experiment"} + >>> mdic + {'a': array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19]), + 'label': 'experiment'} + >>> savemat("matlab_matrix.mat", mdic) + """ + with _open_file_context(file_name, appendmat, 'wb') as file_stream: + if format == '4': + if long_field_names: + message = "Long field names are not available for version 4 files" + raise ValueError(message) + MW = MatFile4Writer(file_stream, oned_as) + elif format == '5': + MW = MatFile5Writer(file_stream, + do_compression=do_compression, + unicode_strings=True, + long_field_names=long_field_names, + oned_as=oned_as) + else: + raise ValueError("Format should be '4' or '5'") + MW.put_variables(mdict) + + +@docfiller +def whosmat(file_name, appendmat=True, **kwargs): + """ + List variables inside a MATLAB file. + + Parameters + ---------- + %(file_arg)s + %(append_arg)s + %(load_args)s + %(struct_arg)s + + Returns + ------- + variables : list of tuples + A list of tuples, where each tuple holds the matrix name (a string), + its shape (tuple of ints), and its data class (a string). + Possible data classes are: int8, uint8, int16, uint16, int32, uint32, + int64, uint64, single, double, cell, struct, object, char, sparse, + function, opaque, logical, unknown. + + Notes + ----- + v4 (Level 1.0), v6 and v7 to 7.2 matfiles are supported. + + You will need an HDF5 python library to read matlab 7.3 format mat + files (e.g. h5py). Because SciPy does not supply one, we do not implement the + HDF5 / 7.3 interface here. + + .. versionadded:: 0.12.0 + + Examples + -------- + >>> from io import BytesIO + >>> import numpy as np + >>> from scipy.io import savemat, whosmat + + Create some arrays, and use `savemat` to write them to a ``BytesIO`` + instance. + + >>> a = np.array([[10, 20, 30], [11, 21, 31]], dtype=np.int32) + >>> b = np.geomspace(1, 10, 5) + >>> f = BytesIO() + >>> savemat(f, {'a': a, 'b': b}) + + Use `whosmat` to inspect ``f``. Each tuple in the output list gives + the name, shape and data type of the array in ``f``. + + >>> whosmat(f) + [('a', (2, 3), 'int32'), ('b', (1, 5), 'double')] + + """ + with _open_file_context(file_name, appendmat) as f: + ML, file_opened = mat_reader_factory(f, **kwargs) + variables = ML.list_variables() + return variables diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_mio4.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_mio4.py new file mode 100644 index 0000000000000000000000000000000000000000..b108386d110e6062d088498259e849603583eb94 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_mio4.py @@ -0,0 +1,632 @@ +''' Classes for read / write of matlab (TM) 4 files +''' +import sys +import warnings +import math +from operator import mul + +import numpy as np + +import scipy.sparse + +from ._miobase import (MatFileReader, docfiller, matdims, read_dtype, + convert_dtypes, arr_to_chars, arr_dtype_number) + +from ._mio_utils import squeeze_element, chars_to_strings +from functools import reduce + + +__all__ = [ + 'MatFile4Reader', 'MatFile4Writer', 'SYS_LITTLE_ENDIAN', + 'VarHeader4', 'VarReader4', 'VarWriter4', 'arr_to_2d', 'mclass_info', + 'mdtypes_template', 'miDOUBLE', 'miINT16', 'miINT32', 'miSINGLE', + 'miUINT16', 'miUINT8', 'mxCHAR_CLASS', 'mxFULL_CLASS', 'mxSPARSE_CLASS', + 'np_to_mtypes', 'order_codes' +] + + +SYS_LITTLE_ENDIAN = sys.byteorder == 'little' + +miDOUBLE = 0 +miSINGLE = 1 +miINT32 = 2 +miINT16 = 3 +miUINT16 = 4 +miUINT8 = 5 + +mdtypes_template = { + miDOUBLE: 'f8', + miSINGLE: 'f4', + miINT32: 'i4', + miINT16: 'i2', + miUINT16: 'u2', + miUINT8: 'u1', + 'header': [('mopt', 'i4'), + ('mrows', 'i4'), + ('ncols', 'i4'), + ('imagf', 'i4'), + ('namlen', 'i4')], + 'U1': 'U1', + } + +np_to_mtypes = { + 'f8': miDOUBLE, + 'c32': miDOUBLE, + 'c24': miDOUBLE, + 'c16': miDOUBLE, + 'f4': miSINGLE, + 'c8': miSINGLE, + 'i4': miINT32, + 'i2': miINT16, + 'u2': miUINT16, + 'u1': miUINT8, + 'S1': miUINT8, + } + +# matrix classes +mxFULL_CLASS = 0 +mxCHAR_CLASS = 1 +mxSPARSE_CLASS = 2 + +order_codes = { + 0: '<', + 1: '>', + 2: 'VAX D-float', # ! + 3: 'VAX G-float', + 4: 'Cray', # !! + } + +mclass_info = { + mxFULL_CLASS: 'double', + mxCHAR_CLASS: 'char', + mxSPARSE_CLASS: 'sparse', + } + + +_MAX_INTP = np.iinfo(np.intp).max + + +class VarHeader4: + # Mat4 variables never logical or global + is_logical = False + is_global = False + + def __init__(self, + name, + dtype, + mclass, + dims, + is_complex): + self.name = name + self.dtype = dtype + self.mclass = mclass + self.dims = dims + self.is_complex = is_complex + + +class VarReader4: + ''' Class to read matlab 4 variables ''' + + def __init__(self, file_reader): + self.file_reader = file_reader + self.mat_stream = file_reader.mat_stream + self.dtypes = file_reader.dtypes + self.chars_as_strings = file_reader.chars_as_strings + self.squeeze_me = file_reader.squeeze_me + + def read_header(self): + ''' Read and return header for variable ''' + data = read_dtype(self.mat_stream, self.dtypes['header']) + name = self.mat_stream.read(int(data['namlen'])).strip(b'\x00') + if data['mopt'] < 0 or data['mopt'] > 5000: + raise ValueError('Mat 4 mopt wrong format, byteswapping problem?') + M, rest = divmod(data['mopt'], 1000) # order code + if M not in (0, 1): + warnings.warn(f"We do not support byte ordering '{order_codes[M]}';" + " returned data may be corrupt", + UserWarning, stacklevel=3) + O, rest = divmod(rest, 100) # unused, should be 0 + if O != 0: + raise ValueError('O in MOPT integer should be 0, wrong format?') + P, rest = divmod(rest, 10) # data type code e.g miDOUBLE (see above) + T = rest # matrix type code e.g., mxFULL_CLASS (see above) + dims = (data['mrows'], data['ncols']) + is_complex = data['imagf'] == 1 + dtype = self.dtypes[P] + return VarHeader4( + name, + dtype, + T, + dims, + is_complex) + + def array_from_header(self, hdr, process=True): + mclass = hdr.mclass + if mclass == mxFULL_CLASS: + arr = self.read_full_array(hdr) + elif mclass == mxCHAR_CLASS: + arr = self.read_char_array(hdr) + if process and self.chars_as_strings: + arr = chars_to_strings(arr) + elif mclass == mxSPARSE_CLASS: + # no current processing (below) makes sense for sparse + return self.read_sparse_array(hdr) + else: + raise TypeError(f'No reader for class code {mclass}') + if process and self.squeeze_me: + return squeeze_element(arr) + return arr + + def read_sub_array(self, hdr, copy=True): + ''' Mat4 read using header `hdr` dtype and dims + + Parameters + ---------- + hdr : object + object with attributes ``dtype``, ``dims``. dtype is assumed to be + the correct endianness + copy : bool, optional + copies array before return if True (default True) + (buffer is usually read only) + + Returns + ------- + arr : ndarray + of dtype given by `hdr` ``dtype`` and shape given by `hdr` ``dims`` + ''' + dt = hdr.dtype + # Fast product for large (>2GB) arrays. + num_bytes = reduce(mul, hdr.dims, np.int64(dt.itemsize)) + if num_bytes > _MAX_INTP: + raise ValueError( + f"Variable '{hdr.name.decode('latin1')}' has byte length " + f"longer than largest possible NumPy array on this platform.") + buffer = self.mat_stream.read(num_bytes) + if len(buffer) != num_bytes: + raise ValueError( + f"Not enough bytes to read matrix " + f"'{hdr.name.decode('latin1')}'; is this a badly-formed file? " + f"Consider listing matrices with `whosmat` and loading named " + f"matrices with `variable_names` kwarg to `loadmat`") + arr = np.ndarray(shape=hdr.dims, + dtype=dt, + buffer=buffer, + order='F') + if copy: + arr = arr.copy() + return arr + + def read_full_array(self, hdr): + ''' Full (rather than sparse) matrix getter + + Read matrix (array) can be real or complex + + Parameters + ---------- + hdr : ``VarHeader4`` instance + + Returns + ------- + arr : ndarray + complex array if ``hdr.is_complex`` is True, otherwise a real + numeric array + ''' + if hdr.is_complex: + # avoid array copy to save memory + res = self.read_sub_array(hdr, copy=False) + res_j = self.read_sub_array(hdr, copy=False) + return res + (res_j * 1j) + return self.read_sub_array(hdr) + + def read_char_array(self, hdr): + ''' latin-1 text matrix (char matrix) reader + + Parameters + ---------- + hdr : ``VarHeader4`` instance + + Returns + ------- + arr : ndarray + with dtype 'U1', shape given by `hdr` ``dims`` + ''' + arr = self.read_sub_array(hdr).astype(np.uint8) + S = arr.tobytes().decode('latin-1') + return np.ndarray(shape=hdr.dims, + dtype=np.dtype('U1'), + buffer=np.array(S)).copy() + + def read_sparse_array(self, hdr): + ''' Read and return sparse matrix type + + Parameters + ---------- + hdr : ``VarHeader4`` instance + + Returns + ------- + arr : coo_array + with dtype ``float`` and shape read from the sparse array data + + Notes + ----- + MATLAB 4 real sparse arrays are saved in a N+1 by 3 array format, where + N is the number of non-zero values. Column 1 values [0:N] are the + (1-based) row indices of the each non-zero value, column 2 [0:N] are the + column indices, column 3 [0:N] are the (real) values. The last values + [-1,0:2] of the rows, column indices are shape[0] and shape[1] + respectively of the output matrix. The last value for the values column + is a padding 0. mrows and ncols values from the header give the shape of + the stored matrix, here [N+1, 3]. Complex data are saved as a 4 column + matrix, where the fourth column contains the imaginary component; the + last value is again 0. Complex sparse data do *not* have the header + ``imagf`` field set to True; the fact that the data are complex is only + detectable because there are 4 storage columns. + ''' + res = self.read_sub_array(hdr) + tmp = res[:-1,:] + # All numbers are float64 in Matlab, but SciPy sparse expects int shape + dims = (int(res[-1,0]), int(res[-1,1])) + I = np.ascontiguousarray(tmp[:,0],dtype='intc') # fixes byte order also + J = np.ascontiguousarray(tmp[:,1],dtype='intc') + I -= 1 # for 1-based indexing + J -= 1 + if res.shape[1] == 3: + V = np.ascontiguousarray(tmp[:,2],dtype='float') + else: + V = np.ascontiguousarray(tmp[:,2],dtype='complex') + V.imag = tmp[:,3] + return scipy.sparse.coo_array((V,(I,J)), dims) + + def shape_from_header(self, hdr): + '''Read the shape of the array described by the header. + The file position after this call is unspecified. + ''' + mclass = hdr.mclass + if mclass == mxFULL_CLASS: + shape = tuple(map(int, hdr.dims)) + elif mclass == mxCHAR_CLASS: + shape = tuple(map(int, hdr.dims)) + if self.chars_as_strings: + shape = shape[:-1] + elif mclass == mxSPARSE_CLASS: + dt = hdr.dtype + dims = hdr.dims + + if not (len(dims) == 2 and dims[0] >= 1 and dims[1] >= 1): + return () + + # Read only the row and column counts + self.mat_stream.seek(dt.itemsize * (dims[0] - 1), 1) + rows = np.ndarray(shape=(), dtype=dt, + buffer=self.mat_stream.read(dt.itemsize)) + self.mat_stream.seek(dt.itemsize * (dims[0] - 1), 1) + cols = np.ndarray(shape=(), dtype=dt, + buffer=self.mat_stream.read(dt.itemsize)) + + shape = (int(rows), int(cols)) + else: + raise TypeError(f'No reader for class code {mclass}') + + if self.squeeze_me: + shape = tuple([x for x in shape if x != 1]) + return shape + + +class MatFile4Reader(MatFileReader): + ''' Reader for Mat4 files ''' + @docfiller + def __init__(self, mat_stream, *args, **kwargs): + ''' Initialize matlab 4 file reader + + %(matstream_arg)s + %(load_args)s + ''' + super().__init__(mat_stream, *args, **kwargs) + self._matrix_reader = None + + def guess_byte_order(self): + self.mat_stream.seek(0) + mopt = read_dtype(self.mat_stream, np.dtype('i4')) + self.mat_stream.seek(0) + if mopt == 0: + return '<' + if mopt < 0 or mopt > 5000: + # Number must have been byteswapped + return SYS_LITTLE_ENDIAN and '>' or '<' + # Not byteswapped + return SYS_LITTLE_ENDIAN and '<' or '>' + + def initialize_read(self): + ''' Run when beginning read of variables + + Sets up readers from parameters in `self` + ''' + self.dtypes = convert_dtypes(mdtypes_template, self.byte_order) + self._matrix_reader = VarReader4(self) + + def read_var_header(self): + ''' Read and return header, next position + + Parameters + ---------- + None + + Returns + ------- + header : object + object that can be passed to self.read_var_array, and that + has attributes ``name`` and ``is_global`` + next_position : int + position in stream of next variable + ''' + hdr = self._matrix_reader.read_header() + # Fast product for large (>2GB) arrays. + remaining_bytes = reduce(mul, hdr.dims, np.int64(hdr.dtype.itemsize)) + if hdr.is_complex and not hdr.mclass == mxSPARSE_CLASS: + remaining_bytes *= 2 + next_position = self.mat_stream.tell() + remaining_bytes + return hdr, next_position + + def read_var_array(self, header, process=True): + ''' Read array, given `header` + + Parameters + ---------- + header : header object + object with fields defining variable header + process : {True, False}, optional + If True, apply recursive post-processing during loading of array. + + Returns + ------- + arr : array + array with post-processing applied or not according to + `process`. + ''' + return self._matrix_reader.array_from_header(header, process) + + def get_variables(self, variable_names=None): + ''' get variables from stream as dictionary + + Parameters + ---------- + variable_names : None or str or sequence of str, optional + variable name, or sequence of variable names to get from Mat file / + file stream. If None, then get all variables in file. + ''' + if isinstance(variable_names, str): + variable_names = [variable_names] + elif variable_names is not None: + variable_names = list(variable_names) + self.mat_stream.seek(0) + # set up variable reader + self.initialize_read() + mdict = {} + while not self.end_of_stream(): + hdr, next_position = self.read_var_header() + name = 'None' if hdr.name is None else hdr.name.decode('latin1') + if variable_names is not None and name not in variable_names: + self.mat_stream.seek(next_position) + continue + mdict[name] = self.read_var_array(hdr) + self.mat_stream.seek(next_position) + if variable_names is not None: + variable_names.remove(name) + if len(variable_names) == 0: + break + return mdict + + def list_variables(self): + ''' list variables from stream ''' + self.mat_stream.seek(0) + # set up variable reader + self.initialize_read() + vars = [] + while not self.end_of_stream(): + hdr, next_position = self.read_var_header() + name = 'None' if hdr.name is None else hdr.name.decode('latin1') + shape = self._matrix_reader.shape_from_header(hdr) + info = mclass_info.get(hdr.mclass, 'unknown') + vars.append((name, shape, info)) + + self.mat_stream.seek(next_position) + return vars + + +def arr_to_2d(arr, oned_as='row'): + ''' Make ``arr`` exactly two dimensional + + If `arr` has more than 2 dimensions, raise a ValueError + + Parameters + ---------- + arr : array + oned_as : {'row', 'column'}, optional + Whether to reshape 1-D vectors as row vectors or column vectors. + See documentation for ``matdims`` for more detail + + Returns + ------- + arr2d : array + 2-D version of the array + ''' + dims = matdims(arr, oned_as) + if len(dims) > 2: + raise ValueError('Matlab 4 files cannot save arrays with more than ' + '2 dimensions') + return arr.reshape(dims) + + +class VarWriter4: + def __init__(self, file_writer): + self.file_stream = file_writer.file_stream + self.oned_as = file_writer.oned_as + + def write_bytes(self, arr): + self.file_stream.write(arr.tobytes(order='F')) + + def write_string(self, s): + self.file_stream.write(s) + + def write_header(self, name, shape, P=miDOUBLE, T=mxFULL_CLASS, imagf=0): + ''' Write header for given data options + + Parameters + ---------- + name : str + name of variable + shape : sequence + Shape of array as it will be read in matlab + P : int, optional + code for mat4 data type, one of ``miDOUBLE, miSINGLE, miINT32, + miINT16, miUINT16, miUINT8`` + T : int, optional + code for mat4 matrix class, one of ``mxFULL_CLASS, mxCHAR_CLASS, + mxSPARSE_CLASS`` + imagf : int, optional + flag indicating complex + ''' + header = np.empty((), mdtypes_template['header']) + M = not SYS_LITTLE_ENDIAN + O = 0 + header['mopt'] = (M * 1000 + + O * 100 + + P * 10 + + T) + header['mrows'] = shape[0] + header['ncols'] = shape[1] + header['imagf'] = imagf + header['namlen'] = len(name) + 1 + self.write_bytes(header) + data = name + '\0' + self.write_string(data.encode('latin1')) + + def write(self, arr, name): + ''' Write matrix `arr`, with name `name` + + Parameters + ---------- + arr : array_like + array to write + name : str + name in matlab workspace + ''' + # we need to catch sparse first, because np.asarray returns an + # an object array for scipy.sparse + if scipy.sparse.issparse(arr): + self.write_sparse(arr, name) + return + arr = np.asarray(arr) + dt = arr.dtype + if not dt.isnative: + arr = arr.astype(dt.newbyteorder('=')) + dtt = dt.type + if dtt is np.object_: + raise TypeError('Cannot save object arrays in Mat4') + elif dtt is np.void: + raise TypeError('Cannot save void type arrays') + elif dtt in (np.str_, np.bytes_): + self.write_char(arr, name) + return + self.write_numeric(arr, name) + + def write_numeric(self, arr, name): + arr = arr_to_2d(arr, self.oned_as) + imagf = arr.dtype.kind == 'c' + try: + P = np_to_mtypes[arr.dtype.str[1:]] + except KeyError: + if imagf: + arr = arr.astype('c128') + else: + arr = arr.astype('f8') + P = miDOUBLE + self.write_header(name, + arr.shape, + P=P, + T=mxFULL_CLASS, + imagf=imagf) + if imagf: + self.write_bytes(arr.real) + self.write_bytes(arr.imag) + else: + self.write_bytes(arr) + + def write_char(self, arr, name): + if arr.dtype.type == np.str_ and arr.dtype.itemsize != np.dtype('U1').itemsize: + arr = arr_to_chars(arr) + arr = arr_to_2d(arr, self.oned_as) + dims = arr.shape + self.write_header( + name, + dims, + P=miUINT8, + T=mxCHAR_CLASS) + if arr.dtype.kind == 'U': + # Recode unicode to latin1 + n_chars = math.prod(dims) + st_arr = np.ndarray(shape=(), + dtype=arr_dtype_number(arr, n_chars), + buffer=arr) + st = st_arr.item().encode('latin-1') + arr = np.ndarray(shape=dims, dtype='S1', buffer=st) + self.write_bytes(arr) + + def write_sparse(self, arr, name): + ''' Sparse matrices are 2-D + + See docstring for VarReader4.read_sparse_array + ''' + A = arr.tocoo() # convert to sparse COO format (ijv) + imagf = A.dtype.kind == 'c' + ijv = np.zeros((A.nnz + 1, 3+imagf), dtype='f8') + ijv[:-1,0] = A.row + ijv[:-1,1] = A.col + ijv[:-1,0:2] += 1 # 1 based indexing + if imagf: + ijv[:-1,2] = A.data.real + ijv[:-1,3] = A.data.imag + else: + ijv[:-1,2] = A.data + ijv[-1,0:2] = A.shape + self.write_header( + name, + ijv.shape, + P=miDOUBLE, + T=mxSPARSE_CLASS) + self.write_bytes(ijv) + + +class MatFile4Writer: + ''' Class for writing matlab 4 format files ''' + def __init__(self, file_stream, oned_as=None): + self.file_stream = file_stream + if oned_as is None: + oned_as = 'row' + self.oned_as = oned_as + self._matrix_writer = None + + def put_variables(self, mdict, write_header=None): + ''' Write variables in `mdict` to stream + + Parameters + ---------- + mdict : mapping + mapping with method ``items`` return name, contents pairs + where ``name`` which will appeak in the matlab workspace in + file load, and ``contents`` is something writeable to a + matlab file, such as a NumPy array. + write_header : {None, True, False} + If True, then write the matlab file header before writing the + variables. If None (the default) then write the file header + if we are at position 0 in the stream. By setting False + here, and setting the stream position to the end of the file, + you can append variables to a matlab file + ''' + # there is no header for a matlab 4 mat file, so we ignore the + # ``write_header`` input argument. It's there for compatibility + # with the matlab 5 version of this method + self._matrix_writer = VarWriter4(self) + for name, var in mdict.items(): + self._matrix_writer.write(var, name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_mio5.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_mio5.py new file mode 100644 index 0000000000000000000000000000000000000000..7200b75b3391d989fcab9c5b3ea14f5fc1b4dc0d --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_mio5.py @@ -0,0 +1,901 @@ +''' Classes for read / write of matlab (TM) 5 files + +The matfile specification last found here: + +https://www.mathworks.com/access/helpdesk/help/pdf_doc/matlab/matfile_format.pdf + +(as of December 5 2008) + +================================= + Note on functions and mat files +================================= + +The document above does not give any hints as to the storage of matlab +function handles, or anonymous function handles. I had, therefore, to +guess the format of matlab arrays of ``mxFUNCTION_CLASS`` and +``mxOPAQUE_CLASS`` by looking at example mat files. + +``mxFUNCTION_CLASS`` stores all types of matlab functions. It seems to +contain a struct matrix with a set pattern of fields. For anonymous +functions, a sub-fields of one of these fields seems to contain the +well-named ``mxOPAQUE_CLASS``. This seems to contain: + +* array flags as for any matlab matrix +* 3 int8 strings +* a matrix + +It seems that whenever the mat file contains a ``mxOPAQUE_CLASS`` +instance, there is also an un-named matrix (name == '') at the end of +the mat file. I'll call this the ``__function_workspace__`` matrix. + +When I saved two anonymous functions in a mat file, or appended another +anonymous function to the mat file, there was still only one +``__function_workspace__`` un-named matrix at the end, but larger than +that for a mat file with a single anonymous function, suggesting that +the workspaces for the two functions had been merged. + +The ``__function_workspace__`` matrix appears to be of double class +(``mxCLASS_DOUBLE``), but stored as uint8, the memory for which is in +the format of a mini .mat file, without the first 124 bytes of the file +header (the description and the subsystem_offset), but with the version +U2 bytes, and the S2 endian test bytes. There follow 4 zero bytes, +presumably for 8 byte padding, and then a series of ``miMATRIX`` +entries, as in a standard mat file. The ``miMATRIX`` entries appear to +be series of un-named (name == '') matrices, and may also contain arrays +of this same mini-mat format. + +I guess that: + +* saving an anonymous function back to a mat file will need the + associated ``__function_workspace__`` matrix saved as well for the + anonymous function to work correctly. +* appending to a mat file that has a ``__function_workspace__`` would + involve first pulling off this workspace, appending, checking whether + there were any more anonymous functions appended, and then somehow + merging the relevant workspaces, and saving at the end of the mat + file. + +The mat files I was playing with are in ``tests/data``: + +* sqr.mat +* parabola.mat +* some_functions.mat + +See ``tests/test_mio.py:test_mio_funcs.py`` for the debugging +script I was working with. + +Small fragments of current code adapted from matfile.py by Heiko +Henkelmann; parts of the code for simplify_cells=True adapted from +http://blog.nephics.com/2019/08/28/better-loadmat-for-scipy/. +''' + +import math +import os +import time +import sys +import zlib + +from io import BytesIO + +import warnings + +import numpy as np + +import scipy.sparse + +from ._byteordercodes import native_code, swapped_code + +from ._miobase import (MatFileReader, docfiller, matdims, read_dtype, + arr_to_chars, arr_dtype_number, MatWriteError, + MatReadError, MatReadWarning, MatWriteWarning) + +# Reader object for matlab 5 format variables +from ._mio5_utils import VarReader5 + +# Constants and helper objects +from ._mio5_params import (MatlabObject, MatlabFunction, MDTYPES, NP_TO_MTYPES, + NP_TO_MXTYPES, miCOMPRESSED, miMATRIX, miINT8, + miUTF8, miUINT32, mxCELL_CLASS, mxSTRUCT_CLASS, + mxOBJECT_CLASS, mxCHAR_CLASS, mxSPARSE_CLASS, + mxDOUBLE_CLASS, mclass_info, mat_struct) + +from ._streams import ZlibInputStream + + +def _has_struct(elem): + """Determine if elem is an array and if first array item is a struct.""" + return (isinstance(elem, np.ndarray) and (elem.size > 0) and (elem.ndim > 0) and + isinstance(elem[0], mat_struct)) + + +def _inspect_cell_array(ndarray): + """Construct lists from cell arrays (loaded as numpy ndarrays), recursing + into items if they contain mat_struct objects.""" + elem_list = [] + for sub_elem in ndarray: + if isinstance(sub_elem, mat_struct): + elem_list.append(_matstruct_to_dict(sub_elem)) + elif _has_struct(sub_elem): + elem_list.append(_inspect_cell_array(sub_elem)) + else: + elem_list.append(sub_elem) + return elem_list + + +def _matstruct_to_dict(matobj): + """Construct nested dicts from mat_struct objects.""" + d = {} + for f in matobj._fieldnames: + elem = matobj.__dict__[f] + if isinstance(elem, mat_struct): + d[f] = _matstruct_to_dict(elem) + elif _has_struct(elem): + d[f] = _inspect_cell_array(elem) + else: + d[f] = elem + return d + + +def _simplify_cells(d): + """Convert mat objects in dict to nested dicts.""" + for key in d: + if isinstance(d[key], mat_struct): + d[key] = _matstruct_to_dict(d[key]) + elif _has_struct(d[key]): + d[key] = _inspect_cell_array(d[key]) + return d + + +class MatFile5Reader(MatFileReader): + ''' Reader for Mat 5 mat files + Adds the following attribute to base class + + uint16_codec - char codec to use for uint16 char arrays + (defaults to system default codec) + + Uses variable reader that has the following standard interface (see + abstract class in ``miobase``:: + + __init__(self, file_reader) + read_header(self) + array_from_header(self) + + and added interface:: + + set_stream(self, stream) + read_full_tag(self) + + ''' + @docfiller + def __init__(self, + mat_stream, + byte_order=None, + mat_dtype=False, + squeeze_me=False, + chars_as_strings=True, + matlab_compatible=False, + struct_as_record=True, + verify_compressed_data_integrity=True, + uint16_codec=None, + simplify_cells=False): + '''Initializer for matlab 5 file format reader + + %(matstream_arg)s + %(load_args)s + %(struct_arg)s + uint16_codec : {None, string} + Set codec to use for uint16 char arrays (e.g., 'utf-8'). + Use system default codec if None + ''' + super().__init__( + mat_stream, + byte_order, + mat_dtype, + squeeze_me, + chars_as_strings, + matlab_compatible, + struct_as_record, + verify_compressed_data_integrity, + simplify_cells) + # Set uint16 codec + if not uint16_codec: + uint16_codec = sys.getdefaultencoding() + self.uint16_codec = uint16_codec + # placeholders for readers - see initialize_read method + self._file_reader = None + self._matrix_reader = None + + def guess_byte_order(self): + ''' Guess byte order. + Sets stream pointer to 0''' + self.mat_stream.seek(126) + mi = self.mat_stream.read(2) + self.mat_stream.seek(0) + return mi == b'IM' and '<' or '>' + + def read_file_header(self): + ''' Read in mat 5 file header ''' + hdict = {} + hdr_dtype = MDTYPES[self.byte_order]['dtypes']['file_header'] + hdr = read_dtype(self.mat_stream, hdr_dtype) + hdict['__header__'] = hdr['description'].item().strip(b' \t\n\000') + v_major = hdr['version'] >> 8 + v_minor = hdr['version'] & 0xFF + hdict['__version__'] = f'{v_major}.{v_minor}' + return hdict + + def initialize_read(self): + ''' Run when beginning read of variables + + Sets up readers from parameters in `self` + ''' + # reader for top level stream. We need this extra top-level + # reader because we use the matrix_reader object to contain + # compressed matrices (so they have their own stream) + self._file_reader = VarReader5(self) + # reader for matrix streams + self._matrix_reader = VarReader5(self) + + def read_var_header(self): + ''' Read header, return header, next position + + Header has to define at least .name and .is_global + + Parameters + ---------- + None + + Returns + ------- + header : object + object that can be passed to self.read_var_array, and that + has attributes .name and .is_global + next_position : int + position in stream of next variable + ''' + mdtype, byte_count = self._file_reader.read_full_tag() + if not byte_count > 0: + raise ValueError("Did not read any bytes") + next_pos = self.mat_stream.tell() + byte_count + if mdtype == miCOMPRESSED: + # Make new stream from compressed data + stream = ZlibInputStream(self.mat_stream, byte_count) + self._matrix_reader.set_stream(stream) + check_stream_limit = self.verify_compressed_data_integrity + mdtype, byte_count = self._matrix_reader.read_full_tag() + else: + check_stream_limit = False + self._matrix_reader.set_stream(self.mat_stream) + if not mdtype == miMATRIX: + raise TypeError(f'Expecting miMATRIX type here, got {mdtype}') + header = self._matrix_reader.read_header(check_stream_limit) + return header, next_pos + + def read_var_array(self, header, process=True): + ''' Read array, given `header` + + Parameters + ---------- + header : header object + object with fields defining variable header + process : {True, False} bool, optional + If True, apply recursive post-processing during loading of + array. + + Returns + ------- + arr : array + array with post-processing applied or not according to + `process`. + ''' + return self._matrix_reader.array_from_header(header, process) + + def get_variables(self, variable_names=None): + ''' get variables from stream as dictionary + + variable_names - optional list of variable names to get + + If variable_names is None, then get all variables in file + ''' + if isinstance(variable_names, str): + variable_names = [variable_names] + elif variable_names is not None: + variable_names = list(variable_names) + + self.mat_stream.seek(0) + # Here we pass all the parameters in self to the reading objects + self.initialize_read() + mdict = self.read_file_header() + mdict['__globals__'] = [] + while not self.end_of_stream(): + hdr, next_position = self.read_var_header() + name = 'None' if hdr.name is None else hdr.name.decode('latin1') + if name in mdict: + msg = ( + f'Duplicate variable name "{name}" in stream' + " - replacing previous with new\nConsider" + "scipy.io.matlab.varmats_from_mat to split " + "file into single variable files" + ) + warnings.warn(msg, MatReadWarning, stacklevel=2) + if name == '': + # can only be a matlab 7 function workspace + name = '__function_workspace__' + # We want to keep this raw because mat_dtype processing + # will break the format (uint8 as mxDOUBLE_CLASS) + process = False + else: + process = True + if variable_names is not None and name not in variable_names: + self.mat_stream.seek(next_position) + continue + try: + res = self.read_var_array(hdr, process) + except MatReadError as err: + warnings.warn( + f'Unreadable variable "{name}", because "{err}"', + Warning, stacklevel=2) + res = f"Read error: {err}" + self.mat_stream.seek(next_position) + mdict[name] = res + if hdr.is_global: + mdict['__globals__'].append(name) + if variable_names is not None: + variable_names.remove(name) + if len(variable_names) == 0: + break + if self.simplify_cells: + return _simplify_cells(mdict) + else: + return mdict + + def list_variables(self): + ''' list variables from stream ''' + self.mat_stream.seek(0) + # Here we pass all the parameters in self to the reading objects + self.initialize_read() + self.read_file_header() + vars = [] + while not self.end_of_stream(): + hdr, next_position = self.read_var_header() + name = 'None' if hdr.name is None else hdr.name.decode('latin1') + if name == '': + # can only be a matlab 7 function workspace + name = '__function_workspace__' + + shape = self._matrix_reader.shape_from_header(hdr) + if hdr.is_logical: + info = 'logical' + else: + info = mclass_info.get(hdr.mclass, 'unknown') + vars.append((name, shape, info)) + + self.mat_stream.seek(next_position) + return vars + + +def varmats_from_mat(file_obj): + """ Pull variables out of mat 5 file as a sequence of mat file objects + + This can be useful with a difficult mat file, containing unreadable + variables. This routine pulls the variables out in raw form and puts them, + unread, back into a file stream for saving or reading. Another use is the + pathological case where there is more than one variable of the same name in + the file; this routine returns the duplicates, whereas the standard reader + will overwrite duplicates in the returned dictionary. + + The file pointer in `file_obj` will be undefined. File pointers for the + returned file-like objects are set at 0. + + Parameters + ---------- + file_obj : file-like + file object containing mat file + + Returns + ------- + named_mats : list + list contains tuples of (name, BytesIO) where BytesIO is a file-like + object containing mat file contents as for a single variable. The + BytesIO contains a string with the original header and a single var. If + ``var_file_obj`` is an individual BytesIO instance, then save as a mat + file with something like ``open('test.mat', + 'wb').write(var_file_obj.read())`` + + Examples + -------- + >>> import scipy.io + >>> import numpy as np + >>> from io import BytesIO + >>> from scipy.io.matlab._mio5 import varmats_from_mat + >>> mat_fileobj = BytesIO() + >>> scipy.io.savemat(mat_fileobj, {'b': np.arange(10), 'a': 'a string'}) + >>> varmats = varmats_from_mat(mat_fileobj) + >>> sorted([name for name, str_obj in varmats]) + ['a', 'b'] + """ + rdr = MatFile5Reader(file_obj) + file_obj.seek(0) + # Raw read of top-level file header + hdr_len = MDTYPES[native_code]['dtypes']['file_header'].itemsize + raw_hdr = file_obj.read(hdr_len) + # Initialize variable reading + file_obj.seek(0) + rdr.initialize_read() + rdr.read_file_header() + next_position = file_obj.tell() + named_mats = [] + while not rdr.end_of_stream(): + start_position = next_position + hdr, next_position = rdr.read_var_header() + name = 'None' if hdr.name is None else hdr.name.decode('latin1') + # Read raw variable string + file_obj.seek(start_position) + byte_count = next_position - start_position + var_str = file_obj.read(byte_count) + # write to stringio object + out_obj = BytesIO() + out_obj.write(raw_hdr) + out_obj.write(var_str) + out_obj.seek(0) + named_mats.append((name, out_obj)) + return named_mats + + +class EmptyStructMarker: + """ Class to indicate presence of empty matlab struct on output """ + + +def to_writeable(source): + ''' Convert input object ``source`` to something we can write + + Parameters + ---------- + source : object + + Returns + ------- + arr : None or ndarray or EmptyStructMarker + If `source` cannot be converted to something we can write to a matfile, + return None. If `source` is equivalent to an empty dictionary, return + ``EmptyStructMarker``. Otherwise return `source` converted to an + ndarray with contents for writing to matfile. + ''' + if isinstance(source, np.ndarray): + return source + if source is None: + return None + if hasattr(source, "__array__"): + return np.asarray(source) + # Objects that implement mappings + is_mapping = (hasattr(source, 'keys') and hasattr(source, 'values') and + hasattr(source, 'items')) + # Objects that don't implement mappings, but do have dicts + if isinstance(source, np.generic): + # NumPy scalars are never mappings (PyPy issue workaround) + pass + elif not is_mapping and hasattr(source, '__dict__'): + source = {key: value for key, value in source.__dict__.items() + if not key.startswith('_')} + is_mapping = True + if is_mapping: + dtype = [] + values = [] + for field, value in source.items(): + if isinstance(field, str): + if field[0] not in '_0123456789': + dtype.append((str(field), object)) + values.append(value) + else: + msg = (f"Starting field name with a underscore " + f"or a digit ({field}) is ignored") + warnings.warn(msg, MatWriteWarning, stacklevel=2) + if dtype: + return np.array([tuple(values)], dtype) + else: + return EmptyStructMarker + # Next try and convert to an array + try: + narr = np.asanyarray(source) + except ValueError: + narr = np.asanyarray(source, dtype=object) + if narr.dtype.type in (object, np.object_) and \ + narr.shape == () and narr == source: + # No interesting conversion possible + return None + return narr + + +# Native byte ordered dtypes for convenience for writers +NDT_FILE_HDR = MDTYPES[native_code]['dtypes']['file_header'] +NDT_TAG_FULL = MDTYPES[native_code]['dtypes']['tag_full'] +NDT_TAG_SMALL = MDTYPES[native_code]['dtypes']['tag_smalldata'] +NDT_ARRAY_FLAGS = MDTYPES[native_code]['dtypes']['array_flags'] + + +class VarWriter5: + ''' Generic matlab matrix writing class ''' + mat_tag = np.zeros((), NDT_TAG_FULL) + mat_tag['mdtype'] = miMATRIX + + def __init__(self, file_writer): + self.file_stream = file_writer.file_stream + self.unicode_strings = file_writer.unicode_strings + self.long_field_names = file_writer.long_field_names + self.oned_as = file_writer.oned_as + # These are used for top level writes, and unset after + self._var_name = None + self._var_is_global = False + + def write_bytes(self, arr): + self.file_stream.write(arr.tobytes(order='F')) + + def write_string(self, s): + self.file_stream.write(s) + + def write_element(self, arr, mdtype=None): + ''' write tag and data ''' + if mdtype is None: + mdtype = NP_TO_MTYPES[arr.dtype.str[1:]] + # Array needs to be in native byte order + if arr.dtype.byteorder == swapped_code: + arr = arr.byteswap().view(arr.dtype.newbyteorder()) + byte_count = arr.size*arr.itemsize + if byte_count <= 4: + self.write_smalldata_element(arr, mdtype, byte_count) + else: + self.write_regular_element(arr, mdtype, byte_count) + + def write_smalldata_element(self, arr, mdtype, byte_count): + # write tag with embedded data + tag = np.zeros((), NDT_TAG_SMALL) + tag['byte_count_mdtype'] = (byte_count << 16) + mdtype + # if arr.tobytes is < 4, the element will be zero-padded as needed. + tag['data'] = arr.tobytes(order='F') + self.write_bytes(tag) + + def write_regular_element(self, arr, mdtype, byte_count): + # write tag, data + tag = np.zeros((), NDT_TAG_FULL) + tag['mdtype'] = mdtype + tag['byte_count'] = byte_count + self.write_bytes(tag) + self.write_bytes(arr) + # pad to next 64-bit boundary + bc_mod_8 = byte_count % 8 + if bc_mod_8: + self.file_stream.write(b'\x00' * (8-bc_mod_8)) + + def write_header(self, + shape, + mclass, + is_complex=False, + is_logical=False, + nzmax=0): + ''' Write header for given data options + shape : sequence + array shape + mclass - mat5 matrix class + is_complex - True if matrix is complex + is_logical - True if matrix is logical + nzmax - max non zero elements for sparse arrays + + We get the name and the global flag from the object, and reset + them to defaults after we've used them + ''' + # get name and is_global from one-shot object store + name = self._var_name + is_global = self._var_is_global + # initialize the top-level matrix tag, store position + self._mat_tag_pos = self.file_stream.tell() + self.write_bytes(self.mat_tag) + # write array flags (complex, global, logical, class, nzmax) + af = np.zeros((), NDT_ARRAY_FLAGS) + af['data_type'] = miUINT32 + af['byte_count'] = 8 + flags = is_complex << 3 | is_global << 2 | is_logical << 1 + af['flags_class'] = mclass | flags << 8 + af['nzmax'] = nzmax + self.write_bytes(af) + # shape + self.write_element(np.array(shape, dtype='i4')) + # write name + name = np.asarray(name) + if name == '': # empty string zero-terminated + self.write_smalldata_element(name, miINT8, 0) + else: + self.write_element(name, miINT8) + # reset the one-shot store to defaults + self._var_name = '' + self._var_is_global = False + + def update_matrix_tag(self, start_pos): + curr_pos = self.file_stream.tell() + self.file_stream.seek(start_pos) + byte_count = curr_pos - start_pos - 8 + if byte_count >= 2**32: + raise MatWriteError("Matrix too large to save with Matlab " + "5 format") + self.mat_tag['byte_count'] = byte_count + self.write_bytes(self.mat_tag) + self.file_stream.seek(curr_pos) + + def write_top(self, arr, name, is_global): + """ Write variable at top level of mat file + + Parameters + ---------- + arr : array_like + array-like object to create writer for + name : str, optional + name as it will appear in matlab workspace + default is empty string + is_global : {False, True}, optional + whether variable will be global on load into matlab + """ + # these are set before the top-level header write, and unset at + # the end of the same write, because they do not apply for lower levels + self._var_is_global = is_global + self._var_name = name + # write the header and data + self.write(arr) + + def write(self, arr): + ''' Write `arr` to stream at top and sub levels + + Parameters + ---------- + arr : array_like + array-like object to create writer for + ''' + # store position, so we can update the matrix tag + mat_tag_pos = self.file_stream.tell() + # First check if these are sparse + if scipy.sparse.issparse(arr): + self.write_sparse(arr) + self.update_matrix_tag(mat_tag_pos) + return + # Try to convert things that aren't arrays + narr = to_writeable(arr) + if narr is None: + raise TypeError(f'Could not convert {arr} (type {type(arr)}) to array') + if isinstance(narr, MatlabObject): + self.write_object(narr) + elif isinstance(narr, MatlabFunction): + raise MatWriteError('Cannot write matlab functions') + elif narr is EmptyStructMarker: # empty struct array + self.write_empty_struct() + elif narr.dtype.fields: # struct array + self.write_struct(narr) + elif narr.dtype.hasobject: # cell array + self.write_cells(narr) + elif narr.dtype.kind in ('U', 'S'): + if self.unicode_strings: + codec = 'UTF8' + else: + codec = 'ascii' + self.write_char(narr, codec) + else: + self.write_numeric(narr) + self.update_matrix_tag(mat_tag_pos) + + def write_numeric(self, arr): + imagf = arr.dtype.kind == 'c' + logif = arr.dtype.kind == 'b' + try: + mclass = NP_TO_MXTYPES[arr.dtype.str[1:]] + except KeyError: + # No matching matlab type, probably complex256 / float128 / float96 + # Cast data to complex128 / float64. + if imagf: + arr = arr.astype('c128') + elif logif: + arr = arr.astype('i1') # Should only contain 0/1 + else: + arr = arr.astype('f8') + mclass = mxDOUBLE_CLASS + self.write_header(matdims(arr, self.oned_as), + mclass, + is_complex=imagf, + is_logical=logif) + if imagf: + self.write_element(arr.real) + self.write_element(arr.imag) + else: + self.write_element(arr) + + def write_char(self, arr, codec='ascii'): + ''' Write string array `arr` with given `codec` + ''' + if arr.size == 0 or np.all(arr == ''): + # This an empty string array or a string array containing + # only empty strings. Matlab cannot distinguish between a + # string array that is empty, and a string array containing + # only empty strings, because it stores strings as arrays of + # char. There is no way of having an array of char that is + # not empty, but contains an empty string. We have to + # special-case the array-with-empty-strings because even + # empty strings have zero padding, which would otherwise + # appear in matlab as a string with a space. + shape = (0,) * np.max([arr.ndim, 2]) + self.write_header(shape, mxCHAR_CLASS) + self.write_smalldata_element(arr, miUTF8, 0) + return + # non-empty string. + # + # Convert to char array + arr = arr_to_chars(arr) + # We have to write the shape directly, because we are going + # recode the characters, and the resulting stream of chars + # may have a different length + shape = arr.shape + self.write_header(shape, mxCHAR_CLASS) + if arr.dtype.kind == 'U' and arr.size: + # Make one long string from all the characters. We need to + # transpose here, because we're flattening the array, before + # we write the bytes. The bytes have to be written in + # Fortran order. + n_chars = math.prod(shape) + st_arr = np.ndarray(shape=(), + dtype=arr_dtype_number(arr, n_chars), + buffer=arr.T.copy()) # Fortran order + # Recode with codec to give byte string + st = st_arr.item().encode(codec) + # Reconstruct as 1-D byte array + arr = np.ndarray(shape=(len(st),), + dtype='S1', + buffer=st) + self.write_element(arr, mdtype=miUTF8) + + def write_sparse(self, arr): + ''' Sparse matrices are 2D + ''' + A = arr.tocsc() # convert to sparse CSC format + A.sort_indices() # MATLAB expects sorted row indices + is_complex = (A.dtype.kind == 'c') + is_logical = (A.dtype.kind == 'b') + nz = A.nnz + self.write_header(matdims(arr, self.oned_as), + mxSPARSE_CLASS, + is_complex=is_complex, + is_logical=is_logical, + # matlab won't load file with 0 nzmax + nzmax=1 if nz == 0 else nz) + self.write_element(A.indices.astype('i4')) + self.write_element(A.indptr.astype('i4')) + self.write_element(A.data.real) + if is_complex: + self.write_element(A.data.imag) + + def write_cells(self, arr): + self.write_header(matdims(arr, self.oned_as), + mxCELL_CLASS) + # loop over data, column major + A = np.atleast_2d(arr).flatten('F') + for el in A: + self.write(el) + + def write_empty_struct(self): + self.write_header((1, 1), mxSTRUCT_CLASS) + # max field name length set to 1 in an example matlab struct + self.write_element(np.array(1, dtype=np.int32)) + # Field names element is empty + self.write_element(np.array([], dtype=np.int8)) + + def write_struct(self, arr): + self.write_header(matdims(arr, self.oned_as), + mxSTRUCT_CLASS) + self._write_items(arr) + + def _write_items(self, arr): + # write fieldnames + fieldnames = [f[0] for f in arr.dtype.descr] + length = max([len(fieldname) for fieldname in fieldnames])+1 + max_length = (self.long_field_names and 64) or 32 + if length > max_length: + raise ValueError( + f"Field names are restricted to {max_length - 1} characters" + ) + self.write_element(np.array([length], dtype='i4')) + self.write_element(np.array(fieldnames, dtype=f'S{length}'), mdtype=miINT8) + A = np.atleast_2d(arr).flatten('F') + for el in A: + for f in fieldnames: + self.write(el[f]) + + def write_object(self, arr): + '''Same as writing structs, except different mx class, and extra + classname element after header + ''' + self.write_header(matdims(arr, self.oned_as), + mxOBJECT_CLASS) + self.write_element(np.array(arr.classname, dtype='S'), + mdtype=miINT8) + self._write_items(arr) + + +class MatFile5Writer: + ''' Class for writing mat5 files ''' + + @docfiller + def __init__(self, file_stream, + do_compression=False, + unicode_strings=False, + global_vars=None, + long_field_names=False, + oned_as='row'): + ''' Initialize writer for matlab 5 format files + + Parameters + ---------- + %(do_compression)s + %(unicode_strings)s + global_vars : None or sequence of strings, optional + Names of variables to be marked as global for matlab + %(long_fields)s + %(oned_as)s + ''' + self.file_stream = file_stream + self.do_compression = do_compression + self.unicode_strings = unicode_strings + if global_vars: + self.global_vars = global_vars + else: + self.global_vars = [] + self.long_field_names = long_field_names + self.oned_as = oned_as + self._matrix_writer = None + + def write_file_header(self): + # write header + hdr = np.zeros((), NDT_FILE_HDR) + hdr['description'] = (f'MATLAB 5.0 MAT-file Platform: {os.name}, ' + f'Created on: {time.asctime()}') + hdr['version'] = 0x0100 + hdr['endian_test'] = np.ndarray(shape=(), + dtype='S2', + buffer=np.uint16(0x4d49)) + self.file_stream.write(hdr.tobytes()) + + def put_variables(self, mdict, write_header=None): + ''' Write variables in `mdict` to stream + + Parameters + ---------- + mdict : mapping + mapping with method ``items`` returns name, contents pairs where + ``name`` which will appear in the matlab workspace in file load, and + ``contents`` is something writeable to a matlab file, such as a NumPy + array. + write_header : {None, True, False}, optional + If True, then write the matlab file header before writing the + variables. If None (the default) then write the file header + if we are at position 0 in the stream. By setting False + here, and setting the stream position to the end of the file, + you can append variables to a matlab file + ''' + # write header if requested, or None and start of file + if write_header is None: + write_header = self.file_stream.tell() == 0 + if write_header: + self.write_file_header() + self._matrix_writer = VarWriter5(self) + for name, var in mdict.items(): + if name[0] == '_': + msg = (f"Starting field name with a " + f"underscore ({name}) is ignored") + warnings.warn(msg, MatWriteWarning, stacklevel=2) + continue + is_global = name in self.global_vars + if self.do_compression: + stream = BytesIO() + self._matrix_writer.file_stream = stream + self._matrix_writer.write_top(var, name.encode('latin1'), is_global) + out_str = zlib.compress(stream.getvalue()) + tag = np.empty((), NDT_TAG_FULL) + tag['mdtype'] = miCOMPRESSED + tag['byte_count'] = len(out_str) + self.file_stream.write(tag.tobytes()) + self.file_stream.write(out_str) + else: # not compressing + self._matrix_writer.write_top(var, name.encode('latin1'), is_global) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_mio5_params.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_mio5_params.py new file mode 100644 index 0000000000000000000000000000000000000000..0d60b8e7a4a2dd1e6a336139f67ce984743e27bb --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_mio5_params.py @@ -0,0 +1,281 @@ +''' Constants and classes for matlab 5 read and write + +See also mio5_utils.pyx where these same constants arise as c enums. + +If you make changes in this file, don't forget to change mio5_utils.pyx +''' +import numpy as np + +from ._miobase import convert_dtypes + + +__all__ = [ + 'MDTYPES', 'MatlabFunction', 'MatlabObject', 'MatlabOpaque', + 'NP_TO_MTYPES', 'NP_TO_MXTYPES', 'OPAQUE_DTYPE', 'codecs_template', + 'mat_struct', 'mclass_dtypes_template', 'mclass_info', 'mdtypes_template', + 'miCOMPRESSED', 'miDOUBLE', 'miINT16', 'miINT32', 'miINT64', 'miINT8', + 'miMATRIX', 'miSINGLE', 'miUINT16', 'miUINT32', 'miUINT64', 'miUINT8', + 'miUTF16', 'miUTF32', 'miUTF8', 'mxCELL_CLASS', 'mxCHAR_CLASS', + 'mxDOUBLE_CLASS', 'mxFUNCTION_CLASS', 'mxINT16_CLASS', 'mxINT32_CLASS', + 'mxINT64_CLASS', 'mxINT8_CLASS', 'mxOBJECT_CLASS', + 'mxOBJECT_CLASS_FROM_MATRIX_H', 'mxOPAQUE_CLASS', 'mxSINGLE_CLASS', + 'mxSPARSE_CLASS', 'mxSTRUCT_CLASS', 'mxUINT16_CLASS', 'mxUINT32_CLASS', + 'mxUINT64_CLASS', 'mxUINT8_CLASS' +] +miINT8 = 1 +miUINT8 = 2 +miINT16 = 3 +miUINT16 = 4 +miINT32 = 5 +miUINT32 = 6 +miSINGLE = 7 +miDOUBLE = 9 +miINT64 = 12 +miUINT64 = 13 +miMATRIX = 14 +miCOMPRESSED = 15 +miUTF8 = 16 +miUTF16 = 17 +miUTF32 = 18 + +mxCELL_CLASS = 1 +mxSTRUCT_CLASS = 2 +# The March 2008 edition of "Matlab 7 MAT-File Format" says that +# mxOBJECT_CLASS = 3, whereas matrix.h says that mxLOGICAL = 3. +# Matlab 2008a appears to save logicals as type 9, so we assume that +# the document is correct. See type 18, below. +mxOBJECT_CLASS = 3 +mxCHAR_CLASS = 4 +mxSPARSE_CLASS = 5 +mxDOUBLE_CLASS = 6 +mxSINGLE_CLASS = 7 +mxINT8_CLASS = 8 +mxUINT8_CLASS = 9 +mxINT16_CLASS = 10 +mxUINT16_CLASS = 11 +mxINT32_CLASS = 12 +mxUINT32_CLASS = 13 +# The following are not in the March 2008 edition of "Matlab 7 +# MAT-File Format," but were guessed from matrix.h. +mxINT64_CLASS = 14 +mxUINT64_CLASS = 15 +mxFUNCTION_CLASS = 16 +# Not doing anything with these at the moment. +mxOPAQUE_CLASS = 17 # This appears to be a function workspace +# Thread 'saving/loading symbol table of annymous functions', +# octave-maintainers, April-May 2007 +# https://lists.gnu.org/archive/html/octave-maintainers/2007-04/msg00031.html +# https://lists.gnu.org/archive/html/octave-maintainers/2007-05/msg00032.html +# (Was/Deprecated: https://www-old.cae.wisc.edu/pipermail/octave-maintainers/2007-May/002824.html) +mxOBJECT_CLASS_FROM_MATRIX_H = 18 + +mdtypes_template = { + miINT8: 'i1', + miUINT8: 'u1', + miINT16: 'i2', + miUINT16: 'u2', + miINT32: 'i4', + miUINT32: 'u4', + miSINGLE: 'f4', + miDOUBLE: 'f8', + miINT64: 'i8', + miUINT64: 'u8', + miUTF8: 'u1', + miUTF16: 'u2', + miUTF32: 'u4', + 'file_header': [('description', 'S116'), + ('subsystem_offset', 'i8'), + ('version', 'u2'), + ('endian_test', 'S2')], + 'tag_full': [('mdtype', 'u4'), ('byte_count', 'u4')], + 'tag_smalldata':[('byte_count_mdtype', 'u4'), ('data', 'S4')], + 'array_flags': [('data_type', 'u4'), + ('byte_count', 'u4'), + ('flags_class','u4'), + ('nzmax', 'u4')], + 'U1': 'U1', + } + +mclass_dtypes_template = { + mxINT8_CLASS: 'i1', + mxUINT8_CLASS: 'u1', + mxINT16_CLASS: 'i2', + mxUINT16_CLASS: 'u2', + mxINT32_CLASS: 'i4', + mxUINT32_CLASS: 'u4', + mxINT64_CLASS: 'i8', + mxUINT64_CLASS: 'u8', + mxSINGLE_CLASS: 'f4', + mxDOUBLE_CLASS: 'f8', + } + +mclass_info = { + mxINT8_CLASS: 'int8', + mxUINT8_CLASS: 'uint8', + mxINT16_CLASS: 'int16', + mxUINT16_CLASS: 'uint16', + mxINT32_CLASS: 'int32', + mxUINT32_CLASS: 'uint32', + mxINT64_CLASS: 'int64', + mxUINT64_CLASS: 'uint64', + mxSINGLE_CLASS: 'single', + mxDOUBLE_CLASS: 'double', + mxCELL_CLASS: 'cell', + mxSTRUCT_CLASS: 'struct', + mxOBJECT_CLASS: 'object', + mxCHAR_CLASS: 'char', + mxSPARSE_CLASS: 'sparse', + mxFUNCTION_CLASS: 'function', + mxOPAQUE_CLASS: 'opaque', + } + +NP_TO_MTYPES = { + 'f8': miDOUBLE, + 'c32': miDOUBLE, + 'c24': miDOUBLE, + 'c16': miDOUBLE, + 'f4': miSINGLE, + 'c8': miSINGLE, + 'i8': miINT64, + 'i4': miINT32, + 'i2': miINT16, + 'i1': miINT8, + 'u8': miUINT64, + 'u4': miUINT32, + 'u2': miUINT16, + 'u1': miUINT8, + 'S1': miUINT8, + 'U1': miUTF16, + 'b1': miUINT8, # not standard but seems MATLAB uses this (gh-4022) + } + + +NP_TO_MXTYPES = { + 'f8': mxDOUBLE_CLASS, + 'c32': mxDOUBLE_CLASS, + 'c24': mxDOUBLE_CLASS, + 'c16': mxDOUBLE_CLASS, + 'f4': mxSINGLE_CLASS, + 'c8': mxSINGLE_CLASS, + 'i8': mxINT64_CLASS, + 'i4': mxINT32_CLASS, + 'i2': mxINT16_CLASS, + 'i1': mxINT8_CLASS, + 'u8': mxUINT64_CLASS, + 'u4': mxUINT32_CLASS, + 'u2': mxUINT16_CLASS, + 'u1': mxUINT8_CLASS, + 'S1': mxUINT8_CLASS, + 'b1': mxUINT8_CLASS, # not standard but seems MATLAB uses this + } + +''' Before release v7.1 (release 14) matlab (TM) used the system +default character encoding scheme padded out to 16-bits. Release 14 +and later use Unicode. When saving character data, R14 checks if it +can be encoded in 7-bit ascii, and saves in that format if so.''' + +codecs_template = { + miUTF8: {'codec': 'utf_8', 'width': 1}, + miUTF16: {'codec': 'utf_16', 'width': 2}, + miUTF32: {'codec': 'utf_32','width': 4}, + } + + +def _convert_codecs(template, byte_order): + ''' Convert codec template mapping to byte order + + Set codecs not on this system to None + + Parameters + ---------- + template : mapping + key, value are respectively codec name, and root name for codec + (without byte order suffix) + byte_order : {'<', '>'} + code for little or big endian + + Returns + ------- + codecs : dict + key, value are name, codec (as in .encode(codec)) + ''' + codecs = {} + postfix = byte_order == '<' and '_le' or '_be' + for k, v in template.items(): + codec = v['codec'] + try: + " ".encode(codec) + except LookupError: + codecs[k] = None + continue + if v['width'] > 1: + codec += postfix + codecs[k] = codec + return codecs.copy() + + +MDTYPES = {} +for _bytecode in '<>': + _def = {'dtypes': convert_dtypes(mdtypes_template, _bytecode), + 'classes': convert_dtypes(mclass_dtypes_template, _bytecode), + 'codecs': _convert_codecs(codecs_template, _bytecode)} + MDTYPES[_bytecode] = _def + + +class mat_struct: + """Placeholder for holding read data from structs. + + We use instances of this class when the user passes False as a value to the + ``struct_as_record`` parameter of the :func:`scipy.io.loadmat` function. + """ + pass + + +class MatlabObject(np.ndarray): + """Subclass of ndarray to signal this is a matlab object. + + This is a simple subclass of :class:`numpy.ndarray` meant to be used + by :func:`scipy.io.loadmat` and should not be instantiated directly. + """ + + def __new__(cls, input_array, classname=None): + # Input array is an already formed ndarray instance + # We first cast to be our class type + obj = np.asarray(input_array).view(cls) + # add the new attribute to the created instance + obj.classname = classname + # Finally, we must return the newly created object: + return obj + + def __array_finalize__(self,obj): + # reset the attribute from passed original object + self.classname = getattr(obj, 'classname', None) + # We do not need to return anything + + +class MatlabFunction(np.ndarray): + """Subclass for a MATLAB function. + + This is a simple subclass of :class:`numpy.ndarray` meant to be used + by :func:`scipy.io.loadmat` and should not be directly instantiated. + """ + + def __new__(cls, input_array): + obj = np.asarray(input_array).view(cls) + return obj + + +class MatlabOpaque(np.ndarray): + """Subclass for a MATLAB opaque matrix. + + This is a simple subclass of :class:`numpy.ndarray` meant to be used + by :func:`scipy.io.loadmat` and should not be directly instantiated. + """ + + def __new__(cls, input_array): + obj = np.asarray(input_array).view(cls) + return obj + + +OPAQUE_DTYPE = np.dtype( + [('s0', 'O'), ('s1', 'O'), ('s2', 'O'), ('arr', 'O')]) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_mio_utils.cpython-312-x86_64-linux-gnu.so b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_mio_utils.cpython-312-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..b02adc610469df6cf7e0cbb784831b11a0b1a88d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_mio_utils.cpython-312-x86_64-linux-gnu.so differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_miobase.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_miobase.py new file mode 100644 index 0000000000000000000000000000000000000000..0cf6bf5260b60e537127b4ce098c011b20c53503 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/_miobase.py @@ -0,0 +1,435 @@ +# Authors: Travis Oliphant, Matthew Brett + +""" +Base classes for MATLAB file stream reading. + +MATLAB is a registered trademark of the Mathworks inc. +""" + +from typing import Final + +import numpy as np +from scipy._lib import doccer + +from . import _byteordercodes as boc + +__all__ = [ + 'MatReadError', 'MatReadWarning', 'MatWriteError', 'MatWriteWarning', +] + +class MatReadError(Exception): + """Exception indicating a read issue.""" + + +class MatWriteError(Exception): + """Exception indicating a write issue.""" + + +class MatReadWarning(UserWarning): + """Warning class for read issues.""" + +class MatWriteWarning(UserWarning): + """Warning class for write issues.""" + + +doc_dict = \ + {'file_arg': + '''file_name : str + Name of the mat file (do not need .mat extension if + appendmat==True) Can also pass open file-like object.''', + 'append_arg': + '''appendmat : bool, optional + True to append the .mat extension to the end of the given + filename, if not already present. Default is True.''', + 'load_args': + '''byte_order : str or None, optional + None by default, implying byte order guessed from mat + file. Otherwise can be one of ('native', '=', 'little', '<', + 'BIG', '>'). +mat_dtype : bool, optional + If True, return arrays in same dtype as would be loaded into + MATLAB (instead of the dtype with which they are saved). +squeeze_me : bool, optional + Whether to squeeze unit matrix dimensions or not. +chars_as_strings : bool, optional + Whether to convert char arrays to string arrays. +matlab_compatible : bool, optional + Returns matrices as would be loaded by MATLAB (implies + squeeze_me=False, chars_as_strings=False, mat_dtype=True, + struct_as_record=True).''', + 'struct_arg': + '''struct_as_record : bool, optional + Whether to load MATLAB structs as NumPy record arrays, or as + old-style NumPy arrays with dtype=object. Setting this flag to + False replicates the behavior of SciPy version 0.7.x (returning + numpy object arrays). The default setting is True, because it + allows easier round-trip load and save of MATLAB files.''', + 'matstream_arg': + '''mat_stream : file-like + Object with file API, open for reading.''', + 'long_fields': + '''long_field_names : bool, optional + * False - maximum field name length in a structure is 31 characters + which is the documented maximum length. This is the default. + * True - maximum field name length in a structure is 63 characters + which works for MATLAB 7.6''', + 'do_compression': + '''do_compression : bool, optional + Whether to compress matrices on write. Default is False.''', + 'oned_as': + '''oned_as : {'row', 'column'}, optional + If 'column', write 1-D NumPy arrays as column vectors. + If 'row', write 1D NumPy arrays as row vectors.''', + 'unicode_strings': + '''unicode_strings : bool, optional + If True, write strings as Unicode, else MATLAB usual encoding.'''} + +docfiller: Final = doccer.filldoc(doc_dict) + +''' + + Note on architecture +====================== + +There are three sets of parameters relevant for reading files. The +first are *file read parameters* - containing options that are common +for reading the whole file, and therefore every variable within that +file. At the moment these are: + +* mat_stream +* dtypes (derived from byte code) +* byte_order +* chars_as_strings +* squeeze_me +* struct_as_record (MATLAB 5 files) +* class_dtypes (derived from order code, MATLAB 5 files) +* codecs (MATLAB 5 files) +* uint16_codec (MATLAB 5 files) + +Another set of parameters are those that apply only to the current +variable being read - the *header*: + +* header related variables (different for v4 and v5 mat files) +* is_complex +* mclass +* var_stream + +With the header, we need ``next_position`` to tell us where the next +variable in the stream is. + +Then, for each element in a matrix, there can be *element read +parameters*. An element is, for example, one element in a MATLAB cell +array. At the moment, these are: + +* mat_dtype + +The file-reading object contains the *file read parameters*. The +*header* is passed around as a data object, or may be read and discarded +in a single function. The *element read parameters* - the mat_dtype in +this instance, is passed into a general post-processing function - see +``mio_utils`` for details. +''' + + +def convert_dtypes(dtype_template, order_code): + ''' Convert dtypes in mapping to given order + + Parameters + ---------- + dtype_template : mapping + mapping with values returning numpy dtype from ``np.dtype(val)`` + order_code : str + an order code suitable for using in ``dtype.newbyteorder()`` + + Returns + ------- + dtypes : mapping + mapping where values have been replaced by + ``np.dtype(val).newbyteorder(order_code)`` + + ''' + dtypes = dtype_template.copy() + for k in dtypes: + dtypes[k] = np.dtype(dtypes[k]).newbyteorder(order_code) + return dtypes + + +def read_dtype(mat_stream, a_dtype): + """ + Generic get of byte stream data of known type + + Parameters + ---------- + mat_stream : file_like object + MATLAB (tm) mat file stream + a_dtype : dtype + dtype of array to read. `a_dtype` is assumed to be correct + endianness. + + Returns + ------- + arr : ndarray + Array of dtype `a_dtype` read from stream. + + """ + num_bytes = a_dtype.itemsize + arr = np.ndarray(shape=(), + dtype=a_dtype, + buffer=mat_stream.read(num_bytes), + order='F') + return arr + + +def matfile_version(file_name, *, appendmat=True): + """ + Return major, minor tuple depending on apparent mat file type + + Where: + + #. 0,x -> version 4 format mat files + #. 1,x -> version 5 format mat files + #. 2,x -> version 7.3 format mat files (HDF format) + + Parameters + ---------- + file_name : str + Name of the mat file (do not need .mat extension if + appendmat==True). Can also pass open file-like object. + appendmat : bool, optional + True to append the .mat extension to the end of the given + filename, if not already present. Default is True. + + Returns + ------- + major_version : {0, 1, 2} + major MATLAB File format version + minor_version : int + minor MATLAB file format version + + Raises + ------ + MatReadError + If the file is empty. + ValueError + The matfile version is unknown. + + Notes + ----- + Has the side effect of setting the file read pointer to 0 + """ + from ._mio import _open_file_context + with _open_file_context(file_name, appendmat=appendmat) as fileobj: + return _get_matfile_version(fileobj) + + +get_matfile_version = matfile_version + + +_HDR_N_BYTES = 20 + + +def _get_matfile_version(fileobj): + # Mat4 files have a zero somewhere in first 4 bytes + fileobj.seek(0) + hdr_bytes = fileobj.read(_HDR_N_BYTES) + if len(hdr_bytes) < _HDR_N_BYTES: + raise MatReadError("Mat file appears to be truncated") + if hdr_bytes.count(0) == _HDR_N_BYTES: + raise MatReadError("Mat file appears to be corrupt " + f"(first {_HDR_N_BYTES} bytes == 0)") + mopt_ints = np.ndarray(shape=(4,), dtype=np.uint8, buffer=hdr_bytes[:4]) + if 0 in mopt_ints: + fileobj.seek(0) + return (0,0) + # For 5 format or 7.3 format we need to read an integer in the + # header. Bytes 124 through 128 contain a version integer and an + # endian test string + fileobj.seek(124) + tst_str = fileobj.read(4) + fileobj.seek(0) + maj_ind = int(tst_str[2] == b'I'[0]) + maj_val = int(tst_str[maj_ind]) + min_val = int(tst_str[1 - maj_ind]) + ret = (maj_val, min_val) + if maj_val in (1, 2): + return ret + raise ValueError('Unknown mat file type, version {}, {}'.format(*ret)) + + +def matdims(arr, oned_as='column'): + """ + Determine equivalent MATLAB dimensions for given array + + Parameters + ---------- + arr : ndarray + Input array + oned_as : {'column', 'row'}, optional + Whether 1-D arrays are returned as MATLAB row or column matrices. + Default is 'column'. + + Returns + ------- + dims : tuple + Shape tuple, in the form MATLAB expects it. + + Notes + ----- + We had to decide what shape a 1 dimensional array would be by + default. ``np.atleast_2d`` thinks it is a row vector. The + default for a vector in MATLAB (e.g., ``>> 1:12``) is a row vector. + + Versions of scipy up to and including 0.11 resulted (accidentally) + in 1-D arrays being read as column vectors. For the moment, we + maintain the same tradition here. + + Examples + -------- + >>> import numpy as np + >>> from scipy.io.matlab._miobase import matdims + >>> matdims(np.array(1)) # NumPy scalar + (1, 1) + >>> matdims(np.array([1])) # 1-D array, 1 element + (1, 1) + >>> matdims(np.array([1,2])) # 1-D array, 2 elements + (2, 1) + >>> matdims(np.array([[2],[3]])) # 2-D array, column vector + (2, 1) + >>> matdims(np.array([[2,3]])) # 2-D array, row vector + (1, 2) + >>> matdims(np.array([[[2,3]]])) # 3-D array, rowish vector + (1, 1, 2) + >>> matdims(np.array([])) # empty 1-D array + (0, 0) + >>> matdims(np.array([[]])) # empty 2-D array + (0, 0) + >>> matdims(np.array([[[]]])) # empty 3-D array + (0, 0, 0) + + Optional argument flips 1-D shape behavior. + + >>> matdims(np.array([1,2]), 'row') # 1-D array, 2 elements + (1, 2) + + The argument has to make sense though + + >>> matdims(np.array([1,2]), 'bizarre') + Traceback (most recent call last): + ... + ValueError: 1-D option "bizarre" is strange + + """ + shape = arr.shape + if shape == (): # scalar + return (1, 1) + if len(shape) == 1: # 1D + if shape[0] == 0: + return (0, 0) + elif oned_as == 'column': + return shape + (1,) + elif oned_as == 'row': + return (1,) + shape + else: + raise ValueError(f'1-D option "{oned_as}" is strange') + return shape + + +class MatVarReader: + ''' Abstract class defining required interface for var readers''' + def __init__(self, file_reader): + pass + + def read_header(self): + ''' Returns header ''' + pass + + def array_from_header(self, header): + ''' Reads array given header ''' + pass + + +class MatFileReader: + """ Base object for reading mat files + + To make this class functional, you will need to override the + following methods: + + matrix_getter_factory - gives object to fetch next matrix from stream + guess_byte_order - guesses file byte order from file + """ + + @docfiller + def __init__(self, mat_stream, + byte_order=None, + mat_dtype=False, + squeeze_me=False, + chars_as_strings=True, + matlab_compatible=False, + struct_as_record=True, + verify_compressed_data_integrity=True, + simplify_cells=False): + ''' + Initializer for mat file reader + + mat_stream : file-like + object with file API, open for reading + %(load_args)s + ''' + # Initialize stream + self.mat_stream = mat_stream + self.dtypes = {} + if not byte_order: + byte_order = self.guess_byte_order() + else: + byte_order = boc.to_numpy_code(byte_order) + self.byte_order = byte_order + self.struct_as_record = struct_as_record + if matlab_compatible: + self.set_matlab_compatible() + else: + self.squeeze_me = squeeze_me + self.chars_as_strings = chars_as_strings + self.mat_dtype = mat_dtype + self.verify_compressed_data_integrity = verify_compressed_data_integrity + self.simplify_cells = simplify_cells + if simplify_cells: + self.squeeze_me = True + self.struct_as_record = False + + def set_matlab_compatible(self): + ''' Sets options to return arrays as MATLAB loads them ''' + self.mat_dtype = True + self.squeeze_me = False + self.chars_as_strings = False + + def guess_byte_order(self): + ''' As we do not know what file type we have, assume native ''' + return boc.native_code + + def end_of_stream(self): + b = self.mat_stream.read(1) + curpos = self.mat_stream.tell() + self.mat_stream.seek(curpos-1) + return len(b) == 0 + + +def arr_dtype_number(arr, num): + ''' Return dtype for given number of items per element''' + return np.dtype(arr.dtype.str[:2] + str(num)) + + +def arr_to_chars(arr): + ''' Convert string array to char array ''' + dims = list(arr.shape) + if not dims: + dims = [1] + dims.append(int(arr.dtype.str[2:])) + arr = np.ndarray(shape=dims, + dtype=arr_dtype_number(arr, 1), + buffer=arr) + empties = [arr == np.array('', dtype=arr.dtype)] + if not np.any(empties): + return arr + arr = arr.copy() + arr[tuple(empties)] = ' ' + return arr diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/byteordercodes.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/byteordercodes.py new file mode 100644 index 0000000000000000000000000000000000000000..0a1c5b0f5e77fdd461d6085037bfdf2850f40fa0 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/byteordercodes.py @@ -0,0 +1,17 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.io.matlab` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + +__all__: list[str] = [] + + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="io.matlab", module="byteordercodes", + private_modules=["_byteordercodes"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio.py new file mode 100644 index 0000000000000000000000000000000000000000..65bb31e52dc719b485b12ba1294fc3d09806c9d0 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio.py @@ -0,0 +1,16 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.io.matlab` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + +__all__ = ["loadmat", "savemat", "whosmat"] # noqa: F822 + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="io.matlab", module="mio", + private_modules=["_mio"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio4.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio4.py new file mode 100644 index 0000000000000000000000000000000000000000..d13b99a0bcedc9746f7681843989791e0918df2e --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio4.py @@ -0,0 +1,17 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.io.matlab` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + +__all__: list[str] = [] + + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="io.matlab", module="mio4", + private_modules=["_mio4"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio5.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio5.py new file mode 100644 index 0000000000000000000000000000000000000000..b84ca19799b32999032833b4e1be1b21f6bc70da --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio5.py @@ -0,0 +1,19 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.io.matlab` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + +__all__ = [ # noqa: F822 + 'MatWriteError', 'MatReadError', 'MatReadWarning', 'MatlabObject', + 'MatlabFunction', 'mat_struct', 'varmats_from_mat', +] + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="io.matlab", module="mio5", + private_modules=["_mio5"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio5_params.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio5_params.py new file mode 100644 index 0000000000000000000000000000000000000000..2dcc9a4f353794546f0d8c07f9afe369baa992f5 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio5_params.py @@ -0,0 +1,18 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.io.matlab` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + +__all__ = [ # noqa: F822 + 'MatlabFunction', 'MatlabObject', 'MatlabOpaque', 'mat_struct', +] + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="io.matlab", module="mio5_params", + private_modules=["_mio5_params"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio5_utils.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio5_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..37ad9e2dc2f50b85bf5aba517c4ac7d661b5039a --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio5_utils.py @@ -0,0 +1,17 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.io.matlab` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + +__all__: list[str] = [] + + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="io.matlab", module="mio5_utils", + private_modules=["_mio5_utils"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio_utils.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..6920511d2635b44acd33ce6f5e00247daf6578d9 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/mio_utils.py @@ -0,0 +1,17 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.io.matlab` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + +__all__: list[str] = [] + + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="io.matlab", module="mio_utils", + private_modules=["_mio_utils"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/miobase.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/miobase.py new file mode 100644 index 0000000000000000000000000000000000000000..13e16848394471f9a1744a7b27fa4e6c86a9248b --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/miobase.py @@ -0,0 +1,16 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.io.matlab` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + +__all__ = ["MatReadError", "MatReadWarning", "MatWriteError"] # noqa: F822 + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="io.matlab", module="miobase", + private_modules=["_miobase"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/streams.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/streams.py new file mode 100644 index 0000000000000000000000000000000000000000..8125271b06cc6f44cee19b2f6079d26b8f32e268 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/streams.py @@ -0,0 +1,16 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.io.matlab` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + +__all__: list[str] = [] + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="io.matlab", module="streams", + private_modules=["_streams"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..52f5f9840543d06f092b749025ee7b4ca6659cb2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_byteordercodes.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_byteordercodes.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2fa707d7903b37938e0c4fe8ab35f58ebc4e05bc Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_byteordercodes.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_mio.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_mio.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a0be51e945287e5b6fdf3a6f4bcf6294625a4b3f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_mio.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_mio5_utils.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_mio5_utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65f5ccf1b13db4cdd307c334a2b919707efe5277 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_mio5_utils.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_mio_funcs.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_mio_funcs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c1c5e0e4bdcc82319cea2b44f075399b08f5e889 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_mio_funcs.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_mio_utils.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_mio_utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7b7c24b93602a423df7dc484985fa6f4d0913ce2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_mio_utils.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_miobase.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_miobase.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8744a2b19fb932833c8228a120bc68903c7ab9bf Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_miobase.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_pathological.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_pathological.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ba2859333b803a639334e75a7d9e1a80b1ac6371 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_pathological.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_streams.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_streams.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..648ec92405f08df4df4a4d1b093e7999ced17ae0 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/__pycache__/test_streams.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/bad_miuint32.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/bad_miuint32.mat new file mode 100644 index 0000000000000000000000000000000000000000..c9ab357ec85972cf0014752a1e0ccb08ff284af9 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/bad_miuint32.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/bad_miutf8_array_name.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/bad_miutf8_array_name.mat new file mode 100644 index 0000000000000000000000000000000000000000..a17203fbb2a7628db644b953ac7723b866a2a0a4 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/bad_miutf8_array_name.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/big_endian.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/big_endian.mat new file mode 100644 index 0000000000000000000000000000000000000000..2a0c982c298fba9df96fd5a927a9c08ee12b09df Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/big_endian.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/broken_utf8.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/broken_utf8.mat new file mode 100644 index 0000000000000000000000000000000000000000..4f6323870368cd97a6294e108ffea9067cf5e69b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/broken_utf8.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/corrupted_zlib_checksum.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/corrupted_zlib_checksum.mat new file mode 100644 index 0000000000000000000000000000000000000000..c88cbb6f54b70d4e795de7cf43f7b46ff6d4d5ef Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/corrupted_zlib_checksum.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/corrupted_zlib_data.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/corrupted_zlib_data.mat new file mode 100644 index 0000000000000000000000000000000000000000..45a2ef4e39755ea1f41aab045f18a035af58ea07 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/corrupted_zlib_data.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/debigged_m4.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/debigged_m4.mat new file mode 100644 index 0000000000000000000000000000000000000000..28aad199045d0b3bf31060300aff9231ee6d9a71 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/debigged_m4.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/japanese_utf8.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/japanese_utf8.txt new file mode 100644 index 0000000000000000000000000000000000000000..1459b6b6ea635b17b5eb04c941e197f98cf04bf1 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/japanese_utf8.txt @@ -0,0 +1,5 @@ +Japanese: +すべての人間は、生まれながらにして自由であり、 +かつ、尊厳と権利と について平等である。 +人間は、理性と良心とを授けられており、 +互いに同胞の精神をもって行動しなければならない。 \ No newline at end of file diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/little_endian.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/little_endian.mat new file mode 100644 index 0000000000000000000000000000000000000000..df6db666dcf2b98d66e04933bd4011f649dcbe30 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/little_endian.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/logical_sparse.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/logical_sparse.mat new file mode 100644 index 0000000000000000000000000000000000000000..a60ad5b605a9dc6b0d85eb0a0e3e655c4955dd34 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/logical_sparse.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/malformed1.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/malformed1.mat new file mode 100644 index 0000000000000000000000000000000000000000..54462e27d663770bc33ef73ed70baae65767719d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/malformed1.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/miuint32_for_miint32.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/miuint32_for_miint32.mat new file mode 100644 index 0000000000000000000000000000000000000000..fd2c4994578edbf31431902ecfcb601b11f60b0b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/miuint32_for_miint32.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/miutf8_array_name.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/miutf8_array_name.mat new file mode 100644 index 0000000000000000000000000000000000000000..ccfdaa8adb7879ba852eab9ce55b602e11dad06d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/miutf8_array_name.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/nasty_duplicate_fieldnames.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/nasty_duplicate_fieldnames.mat new file mode 100644 index 0000000000000000000000000000000000000000..35dcb715bca4cb7f4b0dca287648ef8ee797cd73 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/nasty_duplicate_fieldnames.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/one_by_zero_char.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/one_by_zero_char.mat new file mode 100644 index 0000000000000000000000000000000000000000..07e7dca456843004dcfd9023a800ea91d309814d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/one_by_zero_char.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/parabola.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/parabola.mat new file mode 100644 index 0000000000000000000000000000000000000000..66350532a7737c475a3ae6ef1b1d8406543d890e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/parabola.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/single_empty_string.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/single_empty_string.mat new file mode 100644 index 0000000000000000000000000000000000000000..293f387719e8bdcacb075e0de5737894e5dafed3 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/single_empty_string.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/some_functions.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/some_functions.mat new file mode 100644 index 0000000000000000000000000000000000000000..cc818593b48dd8d29a40a827210b54373e5acf50 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/some_functions.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/sqr.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/sqr.mat new file mode 100644 index 0000000000000000000000000000000000000000..2436d87cc5dfb6d558b841c2367bfe2363bd1b3c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/sqr.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test3dmatrix_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test3dmatrix_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..453712610bf46501d8dd3667ff72d8033f49d81c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test3dmatrix_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test3dmatrix_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test3dmatrix_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..e04d27d30378655ed14634330c7a8ddcd0b98c10 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test3dmatrix_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test3dmatrix_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test3dmatrix_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..4c0303039826af6f6caa928e505cec10ebb3fa81 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test3dmatrix_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test3dmatrix_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test3dmatrix_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..232a051c774105176c28c9718c2cd46f1a1ee1af Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test3dmatrix_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test_empty_struct.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test_empty_struct.mat new file mode 100644 index 0000000000000000000000000000000000000000..30c8c8ad5378be4508bd785da8b7cef38adbd13e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test_empty_struct.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test_mat4_le_floats.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test_mat4_le_floats.mat new file mode 100644 index 0000000000000000000000000000000000000000..6643c42ddcc9579930980b7eb30e11f339638404 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test_mat4_le_floats.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test_skip_variable.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test_skip_variable.mat new file mode 100644 index 0000000000000000000000000000000000000000..efbe3fec64ee54c9f8b3998e5035ccfa251e74ff Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/test_skip_variable.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testbool_8_WIN64.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testbool_8_WIN64.mat new file mode 100644 index 0000000000000000000000000000000000000000..faa30b10bc61ea4889bd9e776c0a1a079e2c2a90 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testbool_8_WIN64.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcell_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcell_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..512f7d889420a016094a903585f27acaa50bc658 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcell_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcell_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcell_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..a7633104c1e4f32fe30fd43f389d7559527c8211 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcell_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcell_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcell_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..2ac1da15873c5edac27758b6f91563d2b8aaace0 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcell_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcell_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcell_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..fc893f331c985cf17b7ce9b7b8c179eaf2103659 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcell_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcellnest_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcellnest_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..4198a4f2aeb8effcccf94a9c0114539f98124179 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcellnest_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcellnest_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcellnest_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..2c7826eeacdb456e5290cafba343703c7596d191 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcellnest_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcellnest_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcellnest_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..b3b086cc31dce2de1e300a1d018b0bf5661b69f3 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcellnest_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcellnest_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcellnest_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..316f8894c5ecc88468cfa0908c277f730e3163e8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcellnest_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcomplex_4.2c_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcomplex_4.2c_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..36621b25c08f18e4545100c6eaec015123c3bf9f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcomplex_4.2c_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcomplex_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcomplex_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..32fcd2a93c91eff478a3ab3076e5c78e31f09bf1 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcomplex_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcomplex_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcomplex_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..f3ecd203376c17b09d97a24aceab824dae0f91c1 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcomplex_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcomplex_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcomplex_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..c0c083855f38e62e3a29460b745f198c9c79313d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcomplex_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcomplex_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcomplex_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..6a187edb1828256362617d3fe24d26cf58e7ca3b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testcomplex_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testdouble_4.2c_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testdouble_4.2c_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..5dbfcf17dd0e01dc0325dd009340291158906e8d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testdouble_4.2c_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testdouble_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testdouble_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..8e36c0c8ce62d7559b60fde454a96e8eefcbcb92 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testdouble_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testdouble_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testdouble_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..a003b6d866f77a25d3b8b236bc95e343221e3019 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testdouble_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testdouble_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testdouble_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..3106712e1099345b48dc4e4125d5e739c24b5341 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testdouble_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testdouble_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testdouble_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..9097bb08712d5bfccf172b0366573f503136228d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testdouble_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testemptycell_5.3_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testemptycell_5.3_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..e7dec3b81abdae8769e0ae0329948548f4038adf Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testemptycell_5.3_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testemptycell_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testemptycell_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..a1c93483597f364443158132b31b86693891b02a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testemptycell_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testemptycell_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testemptycell_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..f29d4f9327aa906729234a38caa05ebfc50cfc30 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testemptycell_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testemptycell_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testemptycell_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..8b244044cf3028df9a019a259d8fc533b80f7fb7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testemptycell_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testfunc_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testfunc_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..adb6c28ee95d1cf8bf3bfeb72295d1a7848020f8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testfunc_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testhdf5_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testhdf5_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..6066c1e30f69b76afdb8d251ecefd8cd9e1acde5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testhdf5_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmatrix_4.2c_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmatrix_4.2c_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..3698c8853b46d4a42194002523b57fddfb225908 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmatrix_4.2c_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmatrix_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmatrix_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..164be1109d977cf7681b1ea00a5df80d5e8f8e71 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmatrix_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmatrix_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmatrix_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..a8735e9a23558ce86a528ceafa8f3475b053e43b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmatrix_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmatrix_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmatrix_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..b6fb05bb7564c863d5bb6c145fe8b06928d3805a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmatrix_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmatrix_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmatrix_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..eb537ab1042b0f989d49711b1a36cc508946fe55 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmatrix_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testminus_4.2c_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testminus_4.2c_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..cc207ed9f32095f39b7690e2dc1e2dc0d55ee8e0 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testminus_4.2c_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testminus_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testminus_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..c2f0ba2ae4c8a1750cace6eae0267e9736272fc0 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testminus_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testminus_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testminus_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..b4dbd152d6e9f3d289b3c4a9792729d2735a4c5c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testminus_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testminus_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testminus_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..fadcd2366b1867239782f073291ff327c2af3001 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testminus_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testminus_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testminus_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..9ce65f91116f68332d1c16e21319e965541d0d73 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testminus_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmulti_4.2c_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmulti_4.2c_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..9c6ba793cf41bf36447ab7a1890447fe5e939614 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmulti_4.2c_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmulti_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmulti_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..0c4729c56b6ab1e8945249a4d3144c79d8538e9e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmulti_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmulti_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmulti_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..6d3e068977edfe6407f29404f0a7d1737f7d3eba Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testmulti_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testobject_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testobject_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..fc13642263a64874f6c2ac602be9cdcb9b788996 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testobject_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testobject_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testobject_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..f68323b0c8eb7fc999dead349ea3bd3a6da66bd4 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testobject_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testobject_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testobject_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..83dcad34249afa543bf66dae9b836276246aab4a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testobject_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testobject_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testobject_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..59d243c4de4fbb3fa653753e40651a6d0a4f4967 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testobject_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testonechar_4.2c_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testonechar_4.2c_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..cdb4191c7d2eb0ac66d4f6add250e1f6a604d892 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testonechar_4.2c_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testonechar_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testonechar_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..3b5a428501a53ae7308c7b6edc42f4881820664d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testonechar_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testonechar_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testonechar_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..8cef2dd7ea6df8aac26ed067a9427935b81c7ac7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testonechar_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testonechar_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testonechar_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..5ba4810ac67756c17b0ef3163a496e913c0b5e57 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testonechar_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testonechar_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testonechar_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..8964765f7bd207bfab63b4d16569cb1c3763bda7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testonechar_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testscalarcell_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testscalarcell_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..1dcd72e51a51abdcf48bd37f68b9927421c17cb0 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testscalarcell_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsimplecell.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsimplecell.mat new file mode 100644 index 0000000000000000000000000000000000000000..2a98f48917f8f275e541eeac5ef1fe741c40bb0b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsimplecell.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparse_4.2c_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparse_4.2c_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..55cbd3c1b3d65630beae47832ffbcc7a6fd43354 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparse_4.2c_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparse_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparse_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..194ca4d7d4d4d22be5669041a25c3ca24ae6edcb Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparse_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparse_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparse_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..3e1e9a1ec916040e94c231f428725add10a2709c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparse_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparse_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparse_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..55b510762ee9b0ac04776e38f6b4bb46b0d10021 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparse_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparse_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparse_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..bdb6ce66ce79b808f044124156db4b803dab155e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparse_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsecomplex_4.2c_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsecomplex_4.2c_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..81c536d0b067b92cae1b7a2ee71824e2c5e730d9 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsecomplex_4.2c_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsecomplex_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsecomplex_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..520e1cedb3823b859666b1fa8872e073904fd4c6 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsecomplex_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsecomplex_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsecomplex_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..969b7143dfff3bb817dbf70c54af8303c3b5822e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsecomplex_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsecomplex_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsecomplex_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..9117dce3092e3e6a39b67da9a7ad1dcfc3ded385 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsecomplex_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsecomplex_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsecomplex_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..a8a615a320f9c8db068a9120c1ceb2e49bb0ea6d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsecomplex_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsefloat_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsefloat_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..15424266a3bd4aa1e7525a8fdc4945b51d2b5ad6 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testsparsefloat_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststring_4.2c_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststring_4.2c_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..137561e1f636d7b08959e43e969a6984eb7a3b37 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststring_4.2c_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststring_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststring_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..2ad75f2e17d8b3fda285490d52b426d1f27d0d95 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststring_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststring_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststring_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..6fd12d884d19df65f1534c13944e988e636166f1 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststring_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststring_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststring_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..ab93994f7befe7d1505c84c238d6409bcb3d438a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststring_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststring_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststring_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..63059b84476749119f44ebefda795f85f6ab27d7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststring_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststringarray_4.2c_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststringarray_4.2c_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..fa687ee988ce530bca87f46235667baa30ac038b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststringarray_4.2c_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststringarray_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststringarray_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..11afb412056ad803f0d8ac1d9dcb188d42285fdf Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststringarray_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststringarray_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststringarray_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..75e07a0b55e008b070f41dabba7480a4e463b67a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststringarray_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststringarray_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststringarray_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..7d76f63643737834053f80539188c9dad75ed0cb Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststringarray_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststringarray_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststringarray_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..954e39beb8156b460ca904ff66261d8f2fc338cb Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststringarray_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststruct_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststruct_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..5086bb7acdc3773186e903000aace436c90dc565 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststruct_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststruct_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststruct_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..6feb6e42375ebebf6dd9440ee09312204cbf1a33 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststruct_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststruct_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststruct_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..b2ff2226223181ec5c42d36afe4f56728f25972d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststruct_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststruct_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststruct_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..028841f9d3aae42d6cf782db14634cbe375f0a05 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststruct_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructarr_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructarr_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..da57365926afe1e8d7dd424a6fcd5b52bc3233ac Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructarr_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructarr_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructarr_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..d1c97a7a2e1edf9683959ec36e899ef8e355073c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructarr_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructarr_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructarr_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..c7ca09594106a765e815a55e942019d17c181270 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructarr_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructarr_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructarr_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..8716f7e3db67d1fd479f913d12286715029ed1a4 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructarr_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructnest_6.1_SOL2.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructnest_6.1_SOL2.mat new file mode 100644 index 0000000000000000000000000000000000000000..2c34c4d8c1477bc4859880a8d2f800073825dcd1 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructnest_6.1_SOL2.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructnest_6.5.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructnest_6.5.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..c6dccc00289f61787b235f4299aa5a14ab4f6d07 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructnest_6.5.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructnest_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructnest_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..0f6f5444b0c1e4bcd80dc0f63b28523d655b05d0 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructnest_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructnest_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructnest_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..faf9221b776eee67cd5d2971da5ba77732ef8016 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/teststructnest_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testunicode_7.1_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testunicode_7.1_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..1b7b3d7f002080839f672e4eb858bbfbddda27ec Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testunicode_7.1_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testunicode_7.4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testunicode_7.4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..d22fb57c81fc3ec9ee7e9b447a05e8a89ff1fcfe Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testunicode_7.4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testvec_4_GLNX86.mat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testvec_4_GLNX86.mat new file mode 100644 index 0000000000000000000000000000000000000000..76c51d01388a1770b348bc603ebfdd51bc011f0c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/data/testvec_4_GLNX86.mat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_byteordercodes.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_byteordercodes.py new file mode 100644 index 0000000000000000000000000000000000000000..535434d188ff575029cc7a0de807b0daa7348f73 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_byteordercodes.py @@ -0,0 +1,29 @@ +''' Tests for byteorder module ''' + +import sys + +from numpy.testing import assert_ +from pytest import raises as assert_raises + +import scipy.io.matlab._byteordercodes as sibc + + +def test_native(): + native_is_le = sys.byteorder == 'little' + assert_(sibc.sys_is_le == native_is_le) + + +def test_to_numpy(): + if sys.byteorder == 'little': + assert_(sibc.to_numpy_code('native') == '<') + assert_(sibc.to_numpy_code('swapped') == '>') + else: + assert_(sibc.to_numpy_code('native') == '>') + assert_(sibc.to_numpy_code('swapped') == '<') + assert_(sibc.to_numpy_code('native') == sibc.to_numpy_code('=')) + assert_(sibc.to_numpy_code('big') == '>') + for code in ('little', '<', 'l', 'L', 'le'): + assert_(sibc.to_numpy_code(code) == '<') + for code in ('big', '>', 'b', 'B', 'be'): + assert_(sibc.to_numpy_code(code) == '>') + assert_raises(ValueError, sibc.to_numpy_code, 'silly string') diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_mio.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_mio.py new file mode 100644 index 0000000000000000000000000000000000000000..ce86a6014da44f5dfa9960fd627db02d78d3413b --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_mio.py @@ -0,0 +1,1399 @@ +import os +from collections import OrderedDict +from os.path import join as pjoin, dirname +from glob import glob +from io import BytesIO +import re +from tempfile import mkdtemp + +import warnings +import shutil +import gzip + +from numpy.testing import (assert_array_equal, assert_array_almost_equal, + assert_equal, assert_, assert_allclose) +import pytest +from pytest import raises as assert_raises, warns as assert_warns + +import numpy as np +from numpy import array +from scipy.sparse import issparse, eye_array, coo_array, csc_array + +import scipy.io +from scipy.io.matlab import MatlabOpaque, MatlabFunction, MatlabObject +import scipy.io.matlab._byteordercodes as boc +from scipy.io.matlab._miobase import (matdims, MatWriteError, MatReadError, + matfile_version, MatWriteWarning) +from scipy.io.matlab._mio import mat_reader_factory, loadmat, savemat, whosmat +from scipy.io.matlab._mio5 import ( + MatFile5Writer, MatFile5Reader, varmats_from_mat, to_writeable, + EmptyStructMarker) +import scipy.io.matlab._mio5_params as mio5p + + +test_data_path = pjoin(dirname(__file__), 'data') +pytestmark = pytest.mark.thread_unsafe + + +def mlarr(*args, **kwargs): + """Convenience function to return matlab-compatible 2-D array.""" + arr = np.array(*args, **kwargs) + arr = arr.reshape(matdims(arr)) + return arr + + +# Define cases to test +theta = np.pi/4*np.arange(9,dtype=float).reshape(1,9) +case_table4 = [ + {'name': 'double', + 'classes': {'testdouble': 'double'}, + 'expected': {'testdouble': theta} + }] +case_table4.append( + {'name': 'string', + 'classes': {'teststring': 'char'}, + 'expected': {'teststring': + array(['"Do nine men interpret?" "Nine men," I nod.'])} + }) +case_table4.append( + {'name': 'complex', + 'classes': {'testcomplex': 'double'}, + 'expected': {'testcomplex': np.cos(theta) + 1j*np.sin(theta)} + }) +A = np.zeros((3,5)) +A[0] = list(range(1,6)) +A[:,0] = list(range(1,4)) +case_table4.append( + {'name': 'matrix', + 'classes': {'testmatrix': 'double'}, + 'expected': {'testmatrix': A}, + }) +case_table4.append( + {'name': 'sparse', + 'classes': {'testsparse': 'sparse'}, + 'expected': {'testsparse': coo_array(A)}, + }) +B = A.astype(complex) +B[0,0] += 1j +case_table4.append( + {'name': 'sparsecomplex', + 'classes': {'testsparsecomplex': 'sparse'}, + 'expected': {'testsparsecomplex': coo_array(B)}, + }) +case_table4.append( + {'name': 'multi', + 'classes': {'theta': 'double', 'a': 'double'}, + 'expected': {'theta': theta, 'a': A}, + }) +case_table4.append( + {'name': 'minus', + 'classes': {'testminus': 'double'}, + 'expected': {'testminus': mlarr(-1)}, + }) +case_table4.append( + {'name': 'onechar', + 'classes': {'testonechar': 'char'}, + 'expected': {'testonechar': array(['r'])}, + }) +# Cell arrays stored as object arrays +CA = mlarr(( # tuple for object array creation + [], + mlarr([1]), + mlarr([[1,2]]), + mlarr([[1,2,3]])), dtype=object).reshape(1,-1) +CA[0,0] = array( + ['This cell contains this string and 3 arrays of increasing length']) +case_table5 = [ + {'name': 'cell', + 'classes': {'testcell': 'cell'}, + 'expected': {'testcell': CA}}] +CAE = mlarr(( # tuple for object array creation + mlarr(1), + mlarr(2), + mlarr([]), + mlarr([]), + mlarr(3)), dtype=object).reshape(1,-1) +objarr = np.empty((1,1),dtype=object) +objarr[0,0] = mlarr(1) +case_table5.append( + {'name': 'scalarcell', + 'classes': {'testscalarcell': 'cell'}, + 'expected': {'testscalarcell': objarr} + }) +case_table5.append( + {'name': 'emptycell', + 'classes': {'testemptycell': 'cell'}, + 'expected': {'testemptycell': CAE}}) +case_table5.append( + {'name': 'stringarray', + 'classes': {'teststringarray': 'char'}, + 'expected': {'teststringarray': array( + ['one ', 'two ', 'three'])}, + }) +case_table5.append( + {'name': '3dmatrix', + 'classes': {'test3dmatrix': 'double'}, + 'expected': { + 'test3dmatrix': np.transpose(np.reshape(list(range(1,25)), (4,3,2)))} + }) +st_sub_arr = array([np.sqrt(2),np.exp(1),np.pi]).reshape(1,3) +dtype = [(n, object) for n in ['stringfield', 'doublefield', 'complexfield']] +st1 = np.zeros((1,1), dtype) +st1['stringfield'][0,0] = array(['Rats live on no evil star.']) +st1['doublefield'][0,0] = st_sub_arr +st1['complexfield'][0,0] = st_sub_arr * (1 + 1j) +case_table5.append( + {'name': 'struct', + 'classes': {'teststruct': 'struct'}, + 'expected': {'teststruct': st1} + }) +CN = np.zeros((1,2), dtype=object) +CN[0,0] = mlarr(1) +CN[0,1] = np.zeros((1,3), dtype=object) +CN[0,1][0,0] = mlarr(2, dtype=np.uint8) +CN[0,1][0,1] = mlarr([[3]], dtype=np.uint8) +CN[0,1][0,2] = np.zeros((1,2), dtype=object) +CN[0,1][0,2][0,0] = mlarr(4, dtype=np.uint8) +CN[0,1][0,2][0,1] = mlarr(5, dtype=np.uint8) +case_table5.append( + {'name': 'cellnest', + 'classes': {'testcellnest': 'cell'}, + 'expected': {'testcellnest': CN}, + }) +st2 = np.empty((1,1), dtype=[(n, object) for n in ['one', 'two']]) +st2[0,0]['one'] = mlarr(1) +st2[0,0]['two'] = np.empty((1,1), dtype=[('three', object)]) +st2[0,0]['two'][0,0]['three'] = array(['number 3']) +case_table5.append( + {'name': 'structnest', + 'classes': {'teststructnest': 'struct'}, + 'expected': {'teststructnest': st2} + }) +a = np.empty((1,2), dtype=[(n, object) for n in ['one', 'two']]) +a[0,0]['one'] = mlarr(1) +a[0,0]['two'] = mlarr(2) +a[0,1]['one'] = array(['number 1']) +a[0,1]['two'] = array(['number 2']) +case_table5.append( + {'name': 'structarr', + 'classes': {'teststructarr': 'struct'}, + 'expected': {'teststructarr': a} + }) +ODT = np.dtype([(n, object) for n in + ['expr', 'inputExpr', 'args', + 'isEmpty', 'numArgs', 'version']]) +MO = MatlabObject(np.zeros((1,1), dtype=ODT), 'inline') +m0 = MO[0,0] +m0['expr'] = array(['x']) +m0['inputExpr'] = array([' x = INLINE_INPUTS_{1};']) +m0['args'] = array(['x']) +m0['isEmpty'] = mlarr(0) +m0['numArgs'] = mlarr(1) +m0['version'] = mlarr(1) +case_table5.append( + {'name': 'object', + 'classes': {'testobject': 'object'}, + 'expected': {'testobject': MO} + }) +fp_u_str = open(pjoin(test_data_path, 'japanese_utf8.txt'), 'rb') +u_str = fp_u_str.read().decode('utf-8') +fp_u_str.close() +case_table5.append( + {'name': 'unicode', + 'classes': {'testunicode': 'char'}, + 'expected': {'testunicode': array([u_str])} + }) +case_table5.append( + {'name': 'sparse', + 'classes': {'testsparse': 'sparse'}, + 'expected': {'testsparse': coo_array(A)}, + }) +case_table5.append( + {'name': 'sparsecomplex', + 'classes': {'testsparsecomplex': 'sparse'}, + 'expected': {'testsparsecomplex': coo_array(B)}, + }) +case_table5.append( + {'name': 'bool', + 'classes': {'testbools': 'logical'}, + 'expected': {'testbools': + array([[True], [False]])}, + }) + +case_table5_rt = case_table5[:] +# Inline functions can't be concatenated in matlab, so RT only +case_table5_rt.append( + {'name': 'objectarray', + 'classes': {'testobjectarray': 'object'}, + 'expected': {'testobjectarray': np.repeat(MO, 2).reshape(1,2)}}) + + +def types_compatible(var1, var2): + """Check if types are same or compatible. + + 0-D numpy scalars are compatible with bare python scalars. + """ + type1 = type(var1) + type2 = type(var2) + if type1 is type2: + return True + if type1 is np.ndarray and var1.shape == (): + return type(var1.item()) is type2 + if type2 is np.ndarray and var2.shape == (): + return type(var2.item()) is type1 + return False + + +def _check_level(label, expected, actual): + """ Check one level of a potentially nested array """ + if issparse(expected): # allow different types of sparse matrices + assert_(issparse(actual)) + assert_array_almost_equal(actual.toarray(), + expected.toarray(), + err_msg=label, + decimal=5) + return + # Check types are as expected + assert_(types_compatible(expected, actual), + f"Expected type {type(expected)}, got {type(actual)} at {label}") + # A field in a record array may not be an ndarray + # A scalar from a record array will be type np.void + if not isinstance(expected, np.void | np.ndarray | MatlabObject): + assert_equal(expected, actual) + return + # This is an ndarray-like thing + assert_(expected.shape == actual.shape, + msg=f'Expected shape {expected.shape}, got {actual.shape} at {label}') + ex_dtype = expected.dtype + if ex_dtype.hasobject: # array of objects + if isinstance(expected, MatlabObject): + assert_equal(expected.classname, actual.classname) + for i, ev in enumerate(expected): + level_label = f"{label}, [{i}], " + _check_level(level_label, ev, actual[i]) + return + if ex_dtype.fields: # probably recarray + for fn in ex_dtype.fields: + level_label = f"{label}, field {fn}, " + _check_level(level_label, + expected[fn], actual[fn]) + return + if ex_dtype.type in (str, # string or bool + np.str_, + np.bool_): + assert_equal(actual, expected, err_msg=label) + return + # Something numeric + assert_array_almost_equal(actual, expected, err_msg=label, decimal=5) + + +def _load_check_case(name, files, case): + for file_name in files: + matdict = loadmat(file_name, struct_as_record=True, spmatrix=False) + label = f"test {name}; file {file_name}" + for k, expected in case.items(): + k_label = f"{label}, variable {k}" + assert_(k in matdict, f"Missing key at {k_label}") + _check_level(k_label, expected, matdict[k]) + + +def _whos_check_case(name, files, case, classes): + for file_name in files: + label = f"test {name}; file {file_name}" + + whos = whosmat(file_name) + + expected_whos = [ + (k, expected.shape, classes[k]) for k, expected in case.items()] + + whos.sort() + expected_whos.sort() + assert_equal(whos, expected_whos, + f"{label}: {whos!r} != {expected_whos!r}" + ) + + +# Round trip tests +def _rt_check_case(name, expected, format): + mat_stream = BytesIO() + savemat(mat_stream, expected, format=format) + mat_stream.seek(0) + _load_check_case(name, [mat_stream], expected) + + +# generator for tests +def _cases(version, filt='test%(name)s_*.mat'): + if version == '4': + cases = case_table4 + elif version == '5': + cases = case_table5 + else: + assert version == '5_rt' + cases = case_table5_rt + for case in cases: + name = case['name'] + expected = case['expected'] + if filt is None: + files = None + else: + use_filt = pjoin(test_data_path, filt % dict(name=name)) + files = glob(use_filt) + assert len(files) > 0, \ + f"No files for test {name} using filter {filt}" + classes = case['classes'] + yield name, files, expected, classes + + +@pytest.mark.parametrize('version', ('4', '5')) +def test_load(version): + for case in _cases(version): + _load_check_case(*case[:3]) + + +@pytest.mark.parametrize('version', ('4', '5')) +def test_whos(version): + for case in _cases(version): + _whos_check_case(*case) + + +# generator for round trip tests +@pytest.mark.parametrize('version, fmts', [ + ('4', ['4', '5']), + ('5_rt', ['5']), +]) +def test_round_trip(version, fmts): + for case in _cases(version, filt=None): + for fmt in fmts: + _rt_check_case(case[0], case[2], fmt) + + +def test_gzip_simple(): + xdense = np.zeros((20,20)) + xdense[2,3] = 2.3 + xdense[4,5] = 4.5 + x = csc_array(xdense) + + name = 'gzip_test' + expected = {'x':x} + format = '4' + + tmpdir = mkdtemp() + try: + fname = pjoin(tmpdir,name) + mat_stream = gzip.open(fname, mode='wb') + savemat(mat_stream, expected, format=format) + mat_stream.close() + + mat_stream = gzip.open(fname, mode='rb') + actual = loadmat(mat_stream, struct_as_record=True, spmatrix=False) + mat_stream.close() + finally: + shutil.rmtree(tmpdir) + + assert_array_almost_equal(actual['x'].toarray(), + expected['x'].toarray(), + err_msg=repr(actual)) + + +def test_multiple_open(): + # Ticket #1039, on Windows: check that files are not left open + tmpdir = mkdtemp() + try: + x = dict(x=np.zeros((2, 2))) + + fname = pjoin(tmpdir, "a.mat") + + # Check that file is not left open + savemat(fname, x) + os.unlink(fname) + savemat(fname, x) + loadmat(fname) + os.unlink(fname) + + # Check that stream is left open + f = open(fname, 'wb') + savemat(f, x) + f.seek(0) + f.close() + + f = open(fname, 'rb') + loadmat(f) + f.seek(0) + f.close() + finally: + shutil.rmtree(tmpdir) + + +def test_mat73(): + # Check any hdf5 files raise an error + filenames = glob( + pjoin(test_data_path, 'testhdf5*.mat')) + assert_(len(filenames) > 0) + for filename in filenames: + fp = open(filename, 'rb') + assert_raises(NotImplementedError, + loadmat, + fp, + struct_as_record=True) + fp.close() + + +def test_warnings(): + # This test is an echo of the previous behavior, which was to raise a + # warning if the user triggered a search for mat files on the Python system + # path. We can remove the test in the next version after upcoming (0.13). + fname = pjoin(test_data_path, 'testdouble_7.1_GLNX86.mat') + with warnings.catch_warnings(): + warnings.simplefilter('error') + # This should not generate a warning + loadmat(fname, struct_as_record=True) + # This neither + loadmat(fname, struct_as_record=False) + + +def test_regression_653(): + # Saving a dictionary with only invalid keys used to raise an error. Now we + # save this as an empty struct in matlab space. + sio = BytesIO() + savemat(sio, {'d':{1:2}}, format='5') + back = loadmat(sio)['d'] + # Check we got an empty struct equivalent + assert_equal(back.shape, (1,1)) + assert_equal(back.dtype, np.dtype(object)) + assert_(back[0,0] is None) + + +def test_structname_len(): + # Test limit for length of field names in structs + lim = 31 + fldname = 'a' * lim + st1 = np.zeros((1,1), dtype=[(fldname, object)]) + savemat(BytesIO(), {'longstruct': st1}, format='5') + fldname = 'a' * (lim+1) + st1 = np.zeros((1,1), dtype=[(fldname, object)]) + assert_raises(ValueError, savemat, BytesIO(), + {'longstruct': st1}, format='5') + + +def test_4_and_long_field_names_incompatible(): + # Long field names option not supported in 4 + my_struct = np.zeros((1,1),dtype=[('my_fieldname',object)]) + assert_raises(ValueError, savemat, BytesIO(), + {'my_struct':my_struct}, format='4', long_field_names=True) + + +def test_long_field_names(): + # Test limit for length of field names in structs + lim = 63 + fldname = 'a' * lim + st1 = np.zeros((1,1), dtype=[(fldname, object)]) + savemat(BytesIO(), {'longstruct': st1}, format='5',long_field_names=True) + fldname = 'a' * (lim+1) + st1 = np.zeros((1,1), dtype=[(fldname, object)]) + assert_raises(ValueError, savemat, BytesIO(), + {'longstruct': st1}, format='5',long_field_names=True) + + +def test_long_field_names_in_struct(): + # Regression test - long_field_names was erased if you passed a struct + # within a struct + lim = 63 + fldname = 'a' * lim + cell = np.ndarray((1,2),dtype=object) + st1 = np.zeros((1,1), dtype=[(fldname, object)]) + cell[0,0] = st1 + cell[0,1] = st1 + savemat(BytesIO(), {'longstruct': cell}, format='5',long_field_names=True) + # + # Check to make sure it fails with long field names off + # + assert_raises(ValueError, savemat, BytesIO(), + {'longstruct': cell}, format='5', long_field_names=False) + + +def test_cell_with_one_thing_in_it(): + # Regression test - make a cell array that's 1 x 2 and put two + # strings in it. It works. Make a cell array that's 1 x 1 and put + # a string in it. It should work but, in the old days, it didn't. + cells = np.ndarray((1,2),dtype=object) + cells[0,0] = 'Hello' + cells[0,1] = 'World' + savemat(BytesIO(), {'x': cells}, format='5') + + cells = np.ndarray((1,1),dtype=object) + cells[0,0] = 'Hello, world' + savemat(BytesIO(), {'x': cells}, format='5') + + +def test_writer_properties(): + # Tests getting, setting of properties of matrix writer + mfw = MatFile5Writer(BytesIO()) + assert_equal(mfw.global_vars, []) + mfw.global_vars = ['avar'] + assert_equal(mfw.global_vars, ['avar']) + assert_equal(mfw.unicode_strings, False) + mfw.unicode_strings = True + assert_equal(mfw.unicode_strings, True) + assert_equal(mfw.long_field_names, False) + mfw.long_field_names = True + assert_equal(mfw.long_field_names, True) + + +def test_use_small_element(): + # Test whether we're using small data element or not + sio = BytesIO() + wtr = MatFile5Writer(sio) + # First check size for no sde for name + arr = np.zeros(10) + wtr.put_variables({'aaaaa': arr}) + w_sz = len(sio.getvalue()) + # Check small name results in largish difference in size + sio.truncate(0) + sio.seek(0) + wtr.put_variables({'aaaa': arr}) + assert_(w_sz - len(sio.getvalue()) > 4) + # Whereas increasing name size makes less difference + sio.truncate(0) + sio.seek(0) + wtr.put_variables({'aaaaaa': arr}) + assert_(len(sio.getvalue()) - w_sz < 4) + + +def test_save_dict(): + # Test that both dict and OrderedDict can be saved (as recarray), + # loaded as matstruct, and preserve order + ab_exp = np.array([[(1, 2)]], dtype=[('a', object), ('b', object)]) + for dict_type in (dict, OrderedDict): + # Initialize with tuples to keep order + d = dict_type([('a', 1), ('b', 2)]) + stream = BytesIO() + savemat(stream, {'dict': d}) + stream.seek(0) + vals = loadmat(stream)['dict'] + assert_equal(vals.dtype.names, ('a', 'b')) + assert_array_equal(vals, ab_exp) + + +def test_1d_shape(): + # New 5 behavior is 1D -> row vector + arr = np.arange(5) + for format in ('4', '5'): + # Column is the default + stream = BytesIO() + savemat(stream, {'oned': arr}, format=format) + vals = loadmat(stream) + assert_equal(vals['oned'].shape, (1, 5)) + # can be explicitly 'column' for oned_as + stream = BytesIO() + savemat(stream, {'oned':arr}, + format=format, + oned_as='column') + vals = loadmat(stream) + assert_equal(vals['oned'].shape, (5,1)) + # but different from 'row' + stream = BytesIO() + savemat(stream, {'oned':arr}, + format=format, + oned_as='row') + vals = loadmat(stream) + assert_equal(vals['oned'].shape, (1,5)) + + +def test_compression(): + arr = np.zeros(100).reshape((5,20)) + arr[2,10] = 1 + stream = BytesIO() + savemat(stream, {'arr':arr}) + raw_len = len(stream.getvalue()) + vals = loadmat(stream) + assert_array_equal(vals['arr'], arr) + stream = BytesIO() + savemat(stream, {'arr':arr}, do_compression=True) + compressed_len = len(stream.getvalue()) + vals = loadmat(stream) + assert_array_equal(vals['arr'], arr) + assert_(raw_len > compressed_len) + # Concatenate, test later + arr2 = arr.copy() + arr2[0,0] = 1 + stream = BytesIO() + savemat(stream, {'arr':arr, 'arr2':arr2}, do_compression=False) + vals = loadmat(stream) + assert_array_equal(vals['arr2'], arr2) + stream = BytesIO() + savemat(stream, {'arr':arr, 'arr2':arr2}, do_compression=True) + vals = loadmat(stream) + assert_array_equal(vals['arr2'], arr2) + + +def test_single_object(): + stream = BytesIO() + savemat(stream, {'A':np.array(1, dtype=object)}) + + +def test_skip_variable(): + # Test skipping over the first of two variables in a MAT file + # using mat_reader_factory and put_variables to read them in. + # + # This is a regression test of a problem that's caused by + # using the compressed file reader seek instead of the raw file + # I/O seek when skipping over a compressed chunk. + # + # The problem arises when the chunk is large: this file has + # a 256x256 array of random (uncompressible) doubles. + # + filename = pjoin(test_data_path,'test_skip_variable.mat') + # + # Prove that it loads with loadmat + # + d = loadmat(filename, struct_as_record=True) + assert_('first' in d) + assert_('second' in d) + # + # Make the factory + # + factory, file_opened = mat_reader_factory(filename, struct_as_record=True) + # + # This is where the factory breaks with an error in MatMatrixGetter.to_next + # + d = factory.get_variables('second') + assert_('second' in d) + factory.mat_stream.close() + + +def test_empty_struct(): + # ticket 885 + filename = pjoin(test_data_path,'test_empty_struct.mat') + # before ticket fix, this would crash with ValueError, empty data + # type + d = loadmat(filename, struct_as_record=True) + a = d['a'] + assert_equal(a.shape, (1,1)) + assert_equal(a.dtype, np.dtype(object)) + assert_(a[0,0] is None) + stream = BytesIO() + arr = np.array((), dtype='U') + # before ticket fix, this used to give data type not understood + savemat(stream, {'arr':arr}) + d = loadmat(stream) + a2 = d['arr'] + assert_array_equal(a2, arr) + + +def test_save_empty_dict(): + # saving empty dict also gives empty struct + stream = BytesIO() + savemat(stream, {'arr': {}}) + d = loadmat(stream) + a = d['arr'] + assert_equal(a.shape, (1,1)) + assert_equal(a.dtype, np.dtype(object)) + assert_(a[0,0] is None) + + +def assert_any_equal(output, alternatives): + """ Assert `output` is equal to at least one element in `alternatives` + """ + one_equal = False + for expected in alternatives: + if np.all(output == expected): + one_equal = True + break + assert_(one_equal) + + +def test_to_writeable(): + # Test to_writeable function + res = to_writeable(np.array([1])) # pass through ndarrays + assert_equal(res.shape, (1,)) + assert_array_equal(res, 1) + # Dict fields can be written in any order + expected1 = np.array([(1, 2)], dtype=[('a', '|O8'), ('b', '|O8')]) + expected2 = np.array([(2, 1)], dtype=[('b', '|O8'), ('a', '|O8')]) + alternatives = (expected1, expected2) + assert_any_equal(to_writeable({'a':1,'b':2}), alternatives) + # Fields with underscores discarded with a warning message. + with pytest.warns(MatWriteWarning, match='Starting field name with'): + assert_any_equal(to_writeable({'a':1, 'b':2, '_c':3}), alternatives) + # Not-string fields discarded + assert_any_equal(to_writeable({'a':1,'b':2, 100:3}), alternatives) + # String fields that are valid Python identifiers discarded + with pytest.warns(MatWriteWarning, match='Starting field name with'): + assert_any_equal(to_writeable({'a':1, 'b':2, '99':3}), alternatives) + # Object with field names is equivalent + + class klass: + pass + + c = klass + c.a = 1 + c.b = 2 + assert_any_equal(to_writeable(c), alternatives) + # empty list and tuple go to empty array + res = to_writeable([]) + assert_equal(res.shape, (0,)) + assert_equal(res.dtype.type, np.float64) + res = to_writeable(()) + assert_equal(res.shape, (0,)) + assert_equal(res.dtype.type, np.float64) + # None -> None + assert_(to_writeable(None) is None) + # String to strings + assert_equal(to_writeable('a string').dtype.type, np.str_) + # Scalars to numpy to NumPy scalars + res = to_writeable(1) + assert_equal(res.shape, ()) + assert_equal(res.dtype.type, np.array(1).dtype.type) + assert_array_equal(res, 1) + # Empty dict returns EmptyStructMarker + assert_(to_writeable({}) is EmptyStructMarker) + # Object does not have (even empty) __dict__ + assert_(to_writeable(object()) is None) + # Custom object does have empty __dict__, returns EmptyStructMarker + + class C: + pass + + assert_(to_writeable(c()) is EmptyStructMarker) + # dict keys with legal characters are convertible + res = to_writeable({'a': 1})['a'] + assert_equal(res.shape, (1,)) + assert_equal(res.dtype.type, np.object_) + # Only fields with illegal characters, falls back to EmptyStruct + with pytest.warns(MatWriteWarning, match='Starting field name with'): + assert_(to_writeable({'1':1}) is EmptyStructMarker) + + with pytest.warns(MatWriteWarning, match='Starting field name with'): + assert_(to_writeable({'_a':1}) is EmptyStructMarker) + # Unless there are valid fields, in which case structured array + with pytest.warns(MatWriteWarning, match='Starting field name with'): + assert_equal(to_writeable({'1':1, 'f': 2}), + np.array([(2,)], dtype=[('f', '|O8')])) + + +def test_recarray(): + # check roundtrip of structured array + dt = [('f1', 'f8'), + ('f2', 'S10')] + arr = np.zeros((2,), dtype=dt) + arr[0]['f1'] = 0.5 + arr[0]['f2'] = 'python' + arr[1]['f1'] = 99 + arr[1]['f2'] = 'not perl' + stream = BytesIO() + savemat(stream, {'arr': arr}) + d = loadmat(stream, struct_as_record=False) + a20 = d['arr'][0,0] + assert_equal(a20.f1, 0.5) + assert_equal(a20.f2, 'python') + d = loadmat(stream, struct_as_record=True) + a20 = d['arr'][0,0] + assert_equal(a20['f1'], 0.5) + assert_equal(a20['f2'], 'python') + # structs always come back as object types + assert_equal(a20.dtype, np.dtype([('f1', 'O'), + ('f2', 'O')])) + a21 = d['arr'].flat[1] + assert_equal(a21['f1'], 99) + assert_equal(a21['f2'], 'not perl') + + +def test_save_object(): + class C: + pass + c = C() + c.field1 = 1 + c.field2 = 'a string' + stream = BytesIO() + savemat(stream, {'c': c}) + d = loadmat(stream, struct_as_record=False) + c2 = d['c'][0,0] + assert_equal(c2.field1, 1) + assert_equal(c2.field2, 'a string') + d = loadmat(stream, struct_as_record=True) + c2 = d['c'][0,0] + assert_equal(c2['field1'], 1) + assert_equal(c2['field2'], 'a string') + + +def test_read_opts(): + # tests if read is seeing option sets, at initialization and after + # initialization + arr = np.arange(6).reshape(1,6) + stream = BytesIO() + savemat(stream, {'a': arr}) + rdr = MatFile5Reader(stream) + back_dict = rdr.get_variables() + rarr = back_dict['a'] + assert_array_equal(rarr, arr) + rdr = MatFile5Reader(stream, squeeze_me=True) + assert_array_equal(rdr.get_variables()['a'], arr.reshape((6,))) + rdr.squeeze_me = False + assert_array_equal(rarr, arr) + rdr = MatFile5Reader(stream, byte_order=boc.native_code) + assert_array_equal(rdr.get_variables()['a'], arr) + # inverted byte code leads to error on read because of swapped + # header etc. + rdr = MatFile5Reader(stream, byte_order=boc.swapped_code) + assert_raises(Exception, rdr.get_variables) + rdr.byte_order = boc.native_code + assert_array_equal(rdr.get_variables()['a'], arr) + arr = np.array(['a string']) + stream.truncate(0) + stream.seek(0) + savemat(stream, {'a': arr}) + rdr = MatFile5Reader(stream) + assert_array_equal(rdr.get_variables()['a'], arr) + rdr = MatFile5Reader(stream, chars_as_strings=False) + carr = np.atleast_2d(np.array(list(arr.item()), dtype='U1')) + assert_array_equal(rdr.get_variables()['a'], carr) + rdr.chars_as_strings = True + assert_array_equal(rdr.get_variables()['a'], arr) + + +def test_empty_string(): + # make sure reading empty string does not raise error + estring_fname = pjoin(test_data_path, 'single_empty_string.mat') + fp = open(estring_fname, 'rb') + rdr = MatFile5Reader(fp) + d = rdr.get_variables() + fp.close() + assert_array_equal(d['a'], np.array([], dtype='U1')) + # Empty string round trip. Matlab cannot distinguish + # between a string array that is empty, and a string array + # containing a single empty string, because it stores strings as + # arrays of char. There is no way of having an array of char that + # is not empty, but contains an empty string. + stream = BytesIO() + savemat(stream, {'a': np.array([''])}) + rdr = MatFile5Reader(stream) + d = rdr.get_variables() + assert_array_equal(d['a'], np.array([], dtype='U1')) + stream.truncate(0) + stream.seek(0) + savemat(stream, {'a': np.array([], dtype='U1')}) + rdr = MatFile5Reader(stream) + d = rdr.get_variables() + assert_array_equal(d['a'], np.array([], dtype='U1')) + stream.close() + + +def test_corrupted_data(): + import zlib + for exc, fname in [(ValueError, 'corrupted_zlib_data.mat'), + (zlib.error, 'corrupted_zlib_checksum.mat')]: + with open(pjoin(test_data_path, fname), 'rb') as fp: + rdr = MatFile5Reader(fp) + assert_raises(exc, rdr.get_variables) + + +def test_corrupted_data_check_can_be_disabled(): + with open(pjoin(test_data_path, 'corrupted_zlib_data.mat'), 'rb') as fp: + rdr = MatFile5Reader(fp, verify_compressed_data_integrity=False) + rdr.get_variables() + + +def test_read_both_endian(): + # make sure big- and little- endian data is read correctly + for fname in ('big_endian.mat', 'little_endian.mat'): + fp = open(pjoin(test_data_path, fname), 'rb') + rdr = MatFile5Reader(fp) + d = rdr.get_variables() + fp.close() + assert_array_equal(d['strings'], + np.array([['hello'], + ['world']], dtype=object)) + assert_array_equal(d['floats'], + np.array([[2., 3.], + [3., 4.]], dtype=np.float32)) + + +def test_write_opposite_endian(): + # We don't support writing opposite endian .mat files, but we need to behave + # correctly if the user supplies an other-endian NumPy array to write out. + float_arr = np.array([[2., 3.], + [3., 4.]]) + int_arr = np.arange(6).reshape((2, 3)) + uni_arr = np.array(['hello', 'world'], dtype='U') + stream = BytesIO() + savemat(stream, { + 'floats': float_arr.byteswap().view(float_arr.dtype.newbyteorder()), + 'ints': int_arr.byteswap().view(int_arr.dtype.newbyteorder()), + 'uni_arr': uni_arr.byteswap().view(uni_arr.dtype.newbyteorder()), + }) + rdr = MatFile5Reader(stream) + d = rdr.get_variables() + assert_array_equal(d['floats'], float_arr) + assert_array_equal(d['ints'], int_arr) + assert_array_equal(d['uni_arr'], uni_arr) + stream.close() + + +def test_logical_array(): + # The roundtrip test doesn't verify that we load the data up with the + # correct (bool) dtype + with open(pjoin(test_data_path, 'testbool_8_WIN64.mat'), 'rb') as fobj: + rdr = MatFile5Reader(fobj, mat_dtype=True) + d = rdr.get_variables() + x = np.array([[True], [False]], dtype=np.bool_) + assert_array_equal(d['testbools'], x) + assert_equal(d['testbools'].dtype, x.dtype) + + +def test_logical_out_type(): + # Confirm that bool type written as uint8, uint8 class + # See gh-4022 + stream = BytesIO() + barr = np.array([False, True, False]) + savemat(stream, {'barray': barr}) + stream.seek(0) + reader = MatFile5Reader(stream) + reader.initialize_read() + reader.read_file_header() + hdr, _ = reader.read_var_header() + assert_equal(hdr.mclass, mio5p.mxUINT8_CLASS) + assert_equal(hdr.is_logical, True) + var = reader.read_var_array(hdr, False) + assert_equal(var.dtype.type, np.uint8) + + +def test_roundtrip_zero_dimensions(): + stream = BytesIO() + savemat(stream, {'d':np.empty((10, 0))}) + d = loadmat(stream) + assert d['d'].shape == (10, 0) + + +def test_mat4_3d(): + # test behavior when writing 3-D arrays to matlab 4 files + stream = BytesIO() + arr = np.arange(24).reshape((2,3,4)) + assert_raises(ValueError, savemat, stream, {'a': arr}, True, '4') + + +def test_func_read(): + func_eg = pjoin(test_data_path, 'testfunc_7.4_GLNX86.mat') + fp = open(func_eg, 'rb') + rdr = MatFile5Reader(fp) + d = rdr.get_variables() + fp.close() + assert isinstance(d['testfunc'], MatlabFunction) + stream = BytesIO() + wtr = MatFile5Writer(stream) + # This test mat file has `__header__` field. + with pytest.warns(MatWriteWarning, match='Starting field name with'): + assert_raises(MatWriteError, wtr.put_variables, d) + + +def test_mat_dtype(): + double_eg = pjoin(test_data_path, 'testmatrix_6.1_SOL2.mat') + fp = open(double_eg, 'rb') + rdr = MatFile5Reader(fp, mat_dtype=False) + d = rdr.get_variables() + fp.close() + assert_equal(d['testmatrix'].dtype.kind, 'u') + + fp = open(double_eg, 'rb') + rdr = MatFile5Reader(fp, mat_dtype=True) + d = rdr.get_variables() + fp.close() + assert_equal(d['testmatrix'].dtype.kind, 'f') + + +def test_sparse_in_struct(): + # reproduces bug found by DC where Cython code was insisting on + # ndarray return type, but getting sparse matrix + st = {'sparsefield': eye_array(4)} + stream = BytesIO() + savemat(stream, {'a':st}) + d = loadmat(stream, struct_as_record=True) + assert_array_equal(d['a'][0, 0]['sparsefield'].toarray(), np.eye(4)) + + +def test_mat_struct_squeeze(): + stream = BytesIO() + in_d = {'st':{'one':1, 'two':2}} + savemat(stream, in_d) + # no error without squeeze + loadmat(stream, struct_as_record=False) + # previous error was with squeeze, with mat_struct + loadmat(stream, struct_as_record=False, squeeze_me=True) + + +def test_scalar_squeeze(): + stream = BytesIO() + in_d = {'scalar': [[0.1]], 'string': 'my name', 'st':{'one':1, 'two':2}} + savemat(stream, in_d) + out_d = loadmat(stream, squeeze_me=True) + assert_(isinstance(out_d['scalar'], float)) + assert_(isinstance(out_d['string'], str)) + assert_(isinstance(out_d['st'], np.ndarray)) + + +def test_str_round(): + # from report by Angus McMorland on mailing list 3 May 2010 + stream = BytesIO() + in_arr = np.array(['Hello', 'Foob']) + out_arr = np.array(['Hello', 'Foob ']) + savemat(stream, dict(a=in_arr)) + res = loadmat(stream) + # resulted in ['HloolFoa', 'elWrdobr'] + assert_array_equal(res['a'], out_arr) + stream.truncate(0) + stream.seek(0) + # Make Fortran ordered version of string + in_str = in_arr.tobytes(order='F') + in_from_str = np.ndarray(shape=a.shape, + dtype=in_arr.dtype, + order='F', + buffer=in_str) + savemat(stream, dict(a=in_from_str)) + assert_array_equal(res['a'], out_arr) + # unicode save did lead to buffer too small error + stream.truncate(0) + stream.seek(0) + in_arr_u = in_arr.astype('U') + out_arr_u = out_arr.astype('U') + savemat(stream, {'a': in_arr_u}) + res = loadmat(stream) + assert_array_equal(res['a'], out_arr_u) + + +def test_fieldnames(): + # Check that field names are as expected + stream = BytesIO() + savemat(stream, {'a': {'a':1, 'b':2}}) + res = loadmat(stream) + field_names = res['a'].dtype.names + assert_equal(set(field_names), {'a', 'b'}) + + +def test_loadmat_varnames(): + # Test that we can get just one variable from a mat file using loadmat + mat5_sys_names = ['__globals__', + '__header__', + '__version__'] + for eg_file, sys_v_names in ( + (pjoin(test_data_path, 'testmulti_4.2c_SOL2.mat'), []), (pjoin( + test_data_path, 'testmulti_7.4_GLNX86.mat'), mat5_sys_names)): + vars = loadmat(eg_file) + assert_equal(set(vars.keys()), set(['a', 'theta'] + sys_v_names)) + vars = loadmat(eg_file, variable_names='a') + assert_equal(set(vars.keys()), set(['a'] + sys_v_names)) + vars = loadmat(eg_file, variable_names=['a']) + assert_equal(set(vars.keys()), set(['a'] + sys_v_names)) + vars = loadmat(eg_file, variable_names=['theta']) + assert_equal(set(vars.keys()), set(['theta'] + sys_v_names)) + vars = loadmat(eg_file, variable_names=('theta',)) + assert_equal(set(vars.keys()), set(['theta'] + sys_v_names)) + vars = loadmat(eg_file, variable_names=[]) + assert_equal(set(vars.keys()), set(sys_v_names)) + vnames = ['theta'] + vars = loadmat(eg_file, variable_names=vnames) + assert_equal(vnames, ['theta']) + + +def test_round_types(): + # Check that saving, loading preserves dtype in most cases + arr = np.arange(10) + stream = BytesIO() + for dts in ('f8','f4','i8','i4','i2','i1', + 'u8','u4','u2','u1','c16','c8'): + stream.truncate(0) + stream.seek(0) # needed for BytesIO in Python 3 + savemat(stream, {'arr': arr.astype(dts)}) + vars = loadmat(stream) + assert_equal(np.dtype(dts), vars['arr'].dtype) + + +def test_varmats_from_mat(): + # Make a mat file with several variables, write it, read it back + names_vars = (('arr', mlarr(np.arange(10))), + ('mystr', mlarr('a string')), + ('mynum', mlarr(10))) + + # Dict like thing to give variables in defined order + class C: + def items(self): + return names_vars + stream = BytesIO() + savemat(stream, C()) + varmats = varmats_from_mat(stream) + assert_equal(len(varmats), 3) + for i in range(3): + name, var_stream = varmats[i] + exp_name, exp_res = names_vars[i] + assert_equal(name, exp_name) + res = loadmat(var_stream) + assert_array_equal(res[name], exp_res) + + +def test_one_by_zero(): + # Test 1x0 chars get read correctly + func_eg = pjoin(test_data_path, 'one_by_zero_char.mat') + fp = open(func_eg, 'rb') + rdr = MatFile5Reader(fp) + d = rdr.get_variables() + fp.close() + assert_equal(d['var'].shape, (0,)) + + +def test_load_mat4_le(): + # We were getting byte order wrong when reading little-endian floa64 dense + # matrices on big-endian platforms + mat4_fname = pjoin(test_data_path, 'test_mat4_le_floats.mat') + vars = loadmat(mat4_fname) + assert_array_equal(vars['a'], [[0.1, 1.2]]) + + +def test_unicode_mat4(): + # Mat4 should save unicode as latin1 + bio = BytesIO() + var = {'second_cat': 'Schrödinger'} + savemat(bio, var, format='4') + var_back = loadmat(bio) + assert_equal(var_back['second_cat'], var['second_cat']) + + +def test_logical_sparse(): + # Test we can read logical sparse stored in mat file as bytes. + # See https://github.com/scipy/scipy/issues/3539. + # In some files saved by MATLAB, the sparse data elements (Real Part + # Subelement in MATLAB speak) are stored with apparent type double + # (miDOUBLE) but are in fact single bytes. + filename = pjoin(test_data_path,'logical_sparse.mat') + # Before fix, this would crash with: + # ValueError: indices and data should have the same size + d = loadmat(filename, struct_as_record=True, spmatrix=False) + log_sp = d['sp_log_5_4'] + assert_(issparse(log_sp) and log_sp.format == "csc") + assert_equal(log_sp.dtype.type, np.bool_) + assert_array_equal(log_sp.toarray(), + [[True, True, True, False], + [False, False, True, False], + [False, False, True, False], + [False, False, False, False], + [False, False, False, False]]) + + +def test_empty_sparse(): + # Can we read empty sparse matrices? + sio = BytesIO() + import scipy.sparse + empty_sparse = scipy.sparse.csr_array([[0,0],[0,0]]) + savemat(sio, dict(x=empty_sparse)) + sio.seek(0) + + res = loadmat(sio, spmatrix=False) + assert not scipy.sparse.isspmatrix(res['x']) + res = loadmat(sio, spmatrix=True) + assert scipy.sparse.isspmatrix(res['x']) + res = loadmat(sio) # chk default + assert scipy.sparse.isspmatrix(res['x']) + + assert_array_equal(res['x'].shape, empty_sparse.shape) + assert_array_equal(res['x'].toarray(), 0) + # Do empty sparse matrices get written with max nnz 1? + # See https://github.com/scipy/scipy/issues/4208 + sio.seek(0) + reader = MatFile5Reader(sio) + reader.initialize_read() + reader.read_file_header() + hdr, _ = reader.read_var_header() + assert_equal(hdr.nzmax, 1) + + +def test_empty_mat_error(): + # Test we get a specific warning for an empty mat file + sio = BytesIO() + assert_raises(MatReadError, loadmat, sio) + + +def test_miuint32_compromise(): + # Reader should accept miUINT32 for miINT32, but check signs + # mat file with miUINT32 for miINT32, but OK values + filename = pjoin(test_data_path, 'miuint32_for_miint32.mat') + res = loadmat(filename) + assert_equal(res['an_array'], np.arange(10)[None, :]) + # mat file with miUINT32 for miINT32, with negative value + filename = pjoin(test_data_path, 'bad_miuint32.mat') + with assert_raises(ValueError): + loadmat(filename) + + +def test_miutf8_for_miint8_compromise(): + # Check reader accepts ascii as miUTF8 for array names + filename = pjoin(test_data_path, 'miutf8_array_name.mat') + res = loadmat(filename) + assert_equal(res['array_name'], [[1]]) + # mat file with non-ascii utf8 name raises error + filename = pjoin(test_data_path, 'bad_miutf8_array_name.mat') + with assert_raises(ValueError): + loadmat(filename) + + +def test_bad_utf8(): + # Check that reader reads bad UTF with 'replace' option + filename = pjoin(test_data_path,'broken_utf8.mat') + res = loadmat(filename) + assert_equal(res['bad_string'], + b'\x80 am broken'.decode('utf8', 'replace')) + + +def test_save_unicode_field(tmpdir): + filename = os.path.join(str(tmpdir), 'test.mat') + test_dict = {'a':{'b':1,'c':'test_str'}} + savemat(filename, test_dict) + + +def test_save_custom_array_type(tmpdir): + class CustomArray: + def __array__(self, dtype=None, copy=None): + return np.arange(6.0).reshape(2, 3) + a = CustomArray() + filename = os.path.join(str(tmpdir), 'test.mat') + savemat(filename, {'a': a}) + out = loadmat(filename) + assert_array_equal(out['a'], np.array(a)) + + +def test_filenotfound(): + # Check the correct error is thrown + assert_raises(OSError, loadmat, "NotExistentFile00.mat") + assert_raises(OSError, loadmat, "NotExistentFile00") + + +def test_simplify_cells(): + # Test output when simplify_cells=True + filename = pjoin(test_data_path, 'testsimplecell.mat') + res1 = loadmat(filename, simplify_cells=True) + res2 = loadmat(filename, simplify_cells=False) + assert_(isinstance(res1["s"], dict)) + assert_(isinstance(res2["s"], np.ndarray)) + assert_array_equal(res1["s"]["mycell"], np.array(["a", "b", "c"])) + + +@pytest.mark.parametrize('version, filt, regex', [ + (0, '_4*_*', None), + (1, '_5*_*', None), + (1, '_6*_*', None), + (1, '_7*_*', '^((?!hdf5).)*$'), # not containing hdf5 + (2, '_7*_*', '.*hdf5.*'), + (1, '8*_*', None), +]) +def test_matfile_version(version, filt, regex): + use_filt = pjoin(test_data_path, f'test*{filt}.mat') + files = glob(use_filt) + if regex is not None: + files = [file for file in files if re.match(regex, file) is not None] + assert len(files) > 0, \ + f"No files for version {version} using filter {filt}" + for file in files: + got_version = matfile_version(file) + assert got_version[0] == version + + +def test_opaque(): + """Test that we can read a MatlabOpaque object.""" + data = loadmat(pjoin(test_data_path, 'parabola.mat')) + assert isinstance(data['parabola'], MatlabFunction) + assert isinstance(data['parabola'].item()[3].item()[3], MatlabOpaque) + + +def test_opaque_simplify(): + """Test that we can read a MatlabOpaque object when simplify_cells=True.""" + data = loadmat(pjoin(test_data_path, 'parabola.mat'), simplify_cells=True) + assert isinstance(data['parabola'], MatlabFunction) + + +def test_deprecation(): + """Test that access to previous attributes still works.""" + # This should be accessible immediately from scipy.io import + with assert_warns(DeprecationWarning): + scipy.io.matlab.mio5_params.MatlabOpaque + + # These should be importable but warn as well + with assert_warns(DeprecationWarning): + from scipy.io.matlab.miobase import MatReadError # noqa: F401 + + +def test_gh_17992(tmp_path): + rng = np.random.default_rng(12345) + outfile = tmp_path / "lists.mat" + array_one = rng.random((5,3)) + array_two = rng.random((6,3)) + list_of_arrays = [array_one, array_two] + savemat(outfile, + {'data': list_of_arrays}, + long_field_names=True, + do_compression=True) + # round trip check + new_dict = {} + loadmat(outfile, + new_dict) + assert_allclose(new_dict["data"][0][0], array_one) + assert_allclose(new_dict["data"][0][1], array_two) + + +def test_gh_19659(tmp_path): + d = { + "char_array": np.array([list("char"), list("char")], dtype="U1"), + "string_array": np.array(["string", "string"]), + } + outfile = tmp_path / "tmp.mat" + # should not error: + savemat(outfile, d, format="4") + + +def test_large_m4(): + # Test we can read a Matlab 4 file with array > 2GB. + # (In fact, test we get the correct error from reading a truncated + # version). + # See https://github.com/scipy/scipy/issues/21256 + # Data file is first 1024 bytes of: + # >>> a = np.zeros((134217728, 3)) + # >>> siom.savemat('big_m4.mat', {'a': a}, format='4') + truncated_mat = pjoin(test_data_path, 'debigged_m4.mat') + match = ("Not enough bytes to read matrix 'a';" + if np.intp == np.int64 else + "Variable 'a' has byte length longer than largest possible") + with pytest.raises(ValueError, match=match): + loadmat(truncated_mat) + + +def test_gh_19223(): + from scipy.io.matlab import varmats_from_mat # noqa: F401 + + +def test_invalid_field_name_warning(): + names_vars = ( + ('_1', mlarr(np.arange(10))), + ('mystr', mlarr('a string'))) + check_mat_write_warning(names_vars) + + names_vars = (('mymap', {"a": 1, "_b": 2}),) + check_mat_write_warning(names_vars) + + names_vars = (('mymap', {"a": 1, "1a": 2}),) + check_mat_write_warning(names_vars) + + +def check_mat_write_warning(names_vars): + class C: + def items(self): + return names_vars + + stream = BytesIO() + with pytest.warns(MatWriteWarning, match='Starting field name with'): + savemat(stream, C()) + + +def test_corrupt_files(): + # Test we can detect truncated or corrupt (all zero) files. + for n in (2, 4, 10, 19): + with pytest.raises(MatReadError, + match="Mat file appears to be truncated"): + loadmat(BytesIO(b'\x00' * n)) + with pytest.raises(MatReadError, + match="Mat file appears to be corrupt"): + loadmat(BytesIO(b'\x00' * 20)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_mio5_utils.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_mio5_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..b3f27114c4a4ed10c1a2526058f4d0dbbd0e5638 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_mio5_utils.py @@ -0,0 +1,179 @@ +""" Testing mio5_utils Cython module + +""" +import sys + +from io import BytesIO + +import numpy as np + +from numpy.testing import assert_array_equal, assert_equal, assert_ +from pytest import raises as assert_raises + +import scipy.io.matlab._byteordercodes as boc +import scipy.io.matlab._streams as streams +import scipy.io.matlab._mio5_params as mio5p +import scipy.io.matlab._mio5_utils as m5u + + +def test_byteswap(): + for val in ( + 1, + 0x100, + 0x10000): + a = np.array(val, dtype=np.uint32) + b = a.byteswap() + c = m5u.byteswap_u4(a) + assert_equal(b.item(), c) + d = m5u.byteswap_u4(c) + assert_equal(a.item(), d) + + +def _make_tag(base_dt, val, mdtype, sde=False): + ''' Makes a simple matlab tag, full or sde ''' + base_dt = np.dtype(base_dt) + bo = boc.to_numpy_code(base_dt.byteorder) + byte_count = base_dt.itemsize + if not sde: + udt = bo + 'u4' + padding = 8 - (byte_count % 8) + all_dt = [('mdtype', udt), + ('byte_count', udt), + ('val', base_dt)] + if padding: + all_dt.append(('padding', 'u1', padding)) + else: # is sde + udt = bo + 'u2' + padding = 4-byte_count + if bo == '<': # little endian + all_dt = [('mdtype', udt), + ('byte_count', udt), + ('val', base_dt)] + else: # big endian + all_dt = [('byte_count', udt), + ('mdtype', udt), + ('val', base_dt)] + if padding: + all_dt.append(('padding', 'u1', padding)) + tag = np.zeros((1,), dtype=all_dt) + tag['mdtype'] = mdtype + tag['byte_count'] = byte_count + tag['val'] = val + return tag + + +def _write_stream(stream, *strings): + stream.truncate(0) + stream.seek(0) + for s in strings: + stream.write(s) + stream.seek(0) + + +def _make_readerlike(stream, byte_order=boc.native_code): + class R: + pass + r = R() + r.mat_stream = stream + r.byte_order = byte_order + r.struct_as_record = True + r.uint16_codec = sys.getdefaultencoding() + r.chars_as_strings = False + r.mat_dtype = False + r.squeeze_me = False + return r + + +def test_read_tag(): + # mainly to test errors + # make reader-like thing + str_io = BytesIO() + r = _make_readerlike(str_io) + c_reader = m5u.VarReader5(r) + # This works for StringIO but _not_ BytesIO + assert_raises(OSError, c_reader.read_tag) + # bad SDE + tag = _make_tag('i4', 1, mio5p.miINT32, sde=True) + tag['byte_count'] = 5 + _write_stream(str_io, tag.tobytes()) + assert_raises(ValueError, c_reader.read_tag) + + +def test_read_stream(): + tag = _make_tag('i4', 1, mio5p.miINT32, sde=True) + tag_str = tag.tobytes() + str_io = BytesIO(tag_str) + st = streams.make_stream(str_io) + s = streams._read_into(st, tag.itemsize) + assert_equal(s, tag.tobytes()) + + +def test_read_numeric(): + # make reader-like thing + str_io = BytesIO() + r = _make_readerlike(str_io) + # check simplest of tags + for base_dt, val, mdtype in (('u2', 30, mio5p.miUINT16), + ('i4', 1, mio5p.miINT32), + ('i2', -1, mio5p.miINT16)): + for byte_code in ('<', '>'): + r.byte_order = byte_code + c_reader = m5u.VarReader5(r) + assert_equal(c_reader.little_endian, byte_code == '<') + assert_equal(c_reader.is_swapped, byte_code != boc.native_code) + for sde_f in (False, True): + dt = np.dtype(base_dt).newbyteorder(byte_code) + a = _make_tag(dt, val, mdtype, sde_f) + a_str = a.tobytes() + _write_stream(str_io, a_str) + el = c_reader.read_numeric() + assert_equal(el, val) + # two sequential reads + _write_stream(str_io, a_str, a_str) + el = c_reader.read_numeric() + assert_equal(el, val) + el = c_reader.read_numeric() + assert_equal(el, val) + + +def test_read_numeric_writeable(): + # make reader-like thing + str_io = BytesIO() + r = _make_readerlike(str_io, '<') + c_reader = m5u.VarReader5(r) + dt = np.dtype('' + rdr.mat_stream.read(4) # presumably byte padding + mdict = read_minimat_vars(rdr) + fp.close() + return mdict + + +def test_jottings(): + # example + fname = os.path.join(test_data_path, 'parabola.mat') + read_workspace_vars(fname) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_mio_utils.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_mio_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..1d19a9797faa2221307a7330b69fffa26410f624 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_mio_utils.py @@ -0,0 +1,45 @@ +""" Testing + +""" + +import numpy as np + +from numpy.testing import assert_array_equal, assert_ + +from scipy.io.matlab._mio_utils import squeeze_element, chars_to_strings + + +def test_squeeze_element(): + a = np.zeros((1,3)) + assert_array_equal(np.squeeze(a), squeeze_element(a)) + # 0-D output from squeeze gives scalar + sq_int = squeeze_element(np.zeros((1,1), dtype=float)) + assert_(isinstance(sq_int, float)) + # Unless it's a structured array + sq_sa = squeeze_element(np.zeros((1,1),dtype=[('f1', 'f')])) + assert_(isinstance(sq_sa, np.ndarray)) + # Squeezing empty arrays maintain their dtypes. + sq_empty = squeeze_element(np.empty(0, np.uint8)) + assert sq_empty.dtype == np.uint8 + + +def test_chars_strings(): + # chars as strings + strings = ['learn ', 'python', 'fast ', 'here '] + str_arr = np.array(strings, dtype='U6') # shape (4,) + chars = [list(s) for s in strings] + char_arr = np.array(chars, dtype='U1') # shape (4,6) + assert_array_equal(chars_to_strings(char_arr), str_arr) + ca2d = char_arr.reshape((2,2,6)) + sa2d = str_arr.reshape((2,2)) + assert_array_equal(chars_to_strings(ca2d), sa2d) + ca3d = char_arr.reshape((1,2,2,6)) + sa3d = str_arr.reshape((1,2,2)) + assert_array_equal(chars_to_strings(ca3d), sa3d) + # Fortran ordered arrays + char_arrf = np.array(chars, dtype='U1', order='F') # shape (4,6) + assert_array_equal(chars_to_strings(char_arrf), str_arr) + # empty array + arr = np.array([['']], dtype='U1') + out_arr = np.array([''], dtype='U1') + assert_array_equal(chars_to_strings(arr), out_arr) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_miobase.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_miobase.py new file mode 100644 index 0000000000000000000000000000000000000000..d8c8eb2a56aaa1d1de77bfb90c859ed0af0b7bc4 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_miobase.py @@ -0,0 +1,32 @@ +""" Testing miobase module +""" + +import numpy as np + +from numpy.testing import assert_equal +from pytest import raises as assert_raises + +from scipy.io.matlab._miobase import matdims + + +def test_matdims(): + # Test matdims dimension finder + assert_equal(matdims(np.array(1)), (1, 1)) # NumPy scalar + assert_equal(matdims(np.array([1])), (1, 1)) # 1-D array, 1 element + assert_equal(matdims(np.array([1,2])), (2, 1)) # 1-D array, 2 elements + assert_equal(matdims(np.array([[2],[3]])), (2, 1)) # 2-D array, column vector + assert_equal(matdims(np.array([[2,3]])), (1, 2)) # 2-D array, row vector + # 3d array, rowish vector + assert_equal(matdims(np.array([[[2,3]]])), (1, 1, 2)) + assert_equal(matdims(np.array([])), (0, 0)) # empty 1-D array + assert_equal(matdims(np.array([[]])), (1, 0)) # empty 2-D array + assert_equal(matdims(np.array([[[]]])), (1, 1, 0)) # empty 3-D array + assert_equal(matdims(np.empty((1, 0, 1))), (1, 0, 1)) # empty 3-D array + # Optional argument flips 1-D shape behavior. + assert_equal(matdims(np.array([1,2]), 'row'), (1, 2)) # 1-D array, 2 elements + # The argument has to make sense though + assert_raises(ValueError, matdims, np.array([1,2]), 'bizarre') + # Check empty sparse matrices get their own shape + from scipy.sparse import csr_array, csc_array + assert_equal(matdims(csr_array(np.zeros((3, 3)))), (3, 3)) + assert_equal(matdims(csc_array(np.zeros((2, 2)))), (2, 2)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_pathological.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_pathological.py new file mode 100644 index 0000000000000000000000000000000000000000..c5c86decb7e90f69f293e90eba74fb47dd4f1277 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_pathological.py @@ -0,0 +1,33 @@ +""" Test reading of files not conforming to matlab specification + +We try and read any file that matlab reads, these files included +""" +from os.path import dirname, join as pjoin + +from numpy.testing import assert_ +from pytest import raises as assert_raises + +from scipy.io.matlab._mio import loadmat + +TEST_DATA_PATH = pjoin(dirname(__file__), 'data') + + +def test_multiple_fieldnames(): + # Example provided by Dharhas Pothina + # Extracted using mio5.varmats_from_mat + multi_fname = pjoin(TEST_DATA_PATH, 'nasty_duplicate_fieldnames.mat') + vars = loadmat(multi_fname) + funny_names = vars['Summary'].dtype.names + assert_({'_1_Station_Q', '_2_Station_Q', + '_3_Station_Q'}.issubset(funny_names)) + + +def test_malformed1(): + # Example from gh-6072 + # Contains malformed header data, which previously resulted into a + # buffer overflow. + # + # Should raise an exception, not segfault + fname = pjoin(TEST_DATA_PATH, 'malformed1.mat') + with open(fname, 'rb') as f: + assert_raises(ValueError, loadmat, f) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_streams.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_streams.py new file mode 100644 index 0000000000000000000000000000000000000000..5449a7d7070e6e4f1655e1071a9098259e4f47cd --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/matlab/tests/test_streams.py @@ -0,0 +1,241 @@ +""" Testing + +""" + +import platform +import os +import random +import sys +import zlib + +from io import BytesIO + + +from tempfile import mkstemp +from contextlib import contextmanager + +import numpy as np + +from numpy.testing import assert_, assert_equal +from pytest import raises as assert_raises +import pytest + +from scipy.io.matlab._streams import (make_stream, + GenericStream, ZlibInputStream, + _read_into, _read_string, BLOCK_SIZE) + + +@contextmanager +def setup_test_file(): + val = b'a\x00string' + fd, fname = mkstemp() + + with os.fdopen(fd, 'wb') as fs: + fs.write(val) + with open(fname, 'rb') as fs: + gs = BytesIO(val) + cs = BytesIO(val) + yield fs, gs, cs + os.unlink(fname) + + +def test_make_stream(): + with setup_test_file() as (fs, gs, cs): + # test stream initialization + assert_(isinstance(make_stream(gs), GenericStream)) + + +def test_tell_seek(): + with setup_test_file() as (fs, gs, cs): + for s in (fs, gs, cs): + st = make_stream(s) + res = st.seek(0) + assert_equal(res, 0) + assert_equal(st.tell(), 0) + res = st.seek(5) + assert_equal(res, 0) + assert_equal(st.tell(), 5) + res = st.seek(2, 1) + assert_equal(res, 0) + assert_equal(st.tell(), 7) + res = st.seek(-2, 2) + assert_equal(res, 0) + assert_equal(st.tell(), 6) + + +def test_read(): + with setup_test_file() as (fs, gs, cs): + for s in (fs, gs, cs): + st = make_stream(s) + st.seek(0) + res = st.read(-1) + assert_equal(res, b'a\x00string') + st.seek(0) + res = st.read(4) + assert_equal(res, b'a\x00st') + # read into + st.seek(0) + res = _read_into(st, 4) + assert_equal(res, b'a\x00st') + res = _read_into(st, 4) + assert_equal(res, b'ring') + assert_raises(OSError, _read_into, st, 2) + # read alloc + st.seek(0) + res = _read_string(st, 4) + assert_equal(res, b'a\x00st') + res = _read_string(st, 4) + assert_equal(res, b'ring') + assert_raises(OSError, _read_string, st, 2) + + +class TestZlibInputStream: + def _get_data(self, size): + data = random.randbytes(size) + compressed_data = zlib.compress(data) + stream = BytesIO(compressed_data) + return stream, len(compressed_data), data + + def test_read(self): + SIZES = [0, 1, 10, BLOCK_SIZE//2, BLOCK_SIZE-1, + BLOCK_SIZE, BLOCK_SIZE+1, 2*BLOCK_SIZE-1] + + READ_SIZES = [BLOCK_SIZE//2, BLOCK_SIZE-1, + BLOCK_SIZE, BLOCK_SIZE+1] + + def check(size, read_size): + compressed_stream, compressed_data_len, data = self._get_data(size) + stream = ZlibInputStream(compressed_stream, compressed_data_len) + data2 = b'' + so_far = 0 + while True: + block = stream.read(min(read_size, + size - so_far)) + if not block: + break + so_far += len(block) + data2 += block + assert_equal(data, data2) + + for size in SIZES: + for read_size in READ_SIZES: + check(size, read_size) + + def test_read_max_length(self): + data = random.randbytes(1234) + compressed_data = zlib.compress(data) + compressed_stream = BytesIO(compressed_data + b"abbacaca") + stream = ZlibInputStream(compressed_stream, len(compressed_data)) + + stream.read(len(data)) + assert_equal(compressed_stream.tell(), len(compressed_data)) + + assert_raises(OSError, stream.read, 1) + + def test_read_bad_checksum(self): + data = random.randbytes(10) + compressed_data = zlib.compress(data) + + # break checksum + compressed_data = (compressed_data[:-1] + + bytes([(compressed_data[-1] + 1) & 255])) + + compressed_stream = BytesIO(compressed_data) + stream = ZlibInputStream(compressed_stream, len(compressed_data)) + + assert_raises(zlib.error, stream.read, len(data)) + + def test_seek(self): + compressed_stream, compressed_data_len, data = self._get_data(1024) + + stream = ZlibInputStream(compressed_stream, compressed_data_len) + + stream.seek(123) + p = 123 + assert_equal(stream.tell(), p) + d1 = stream.read(11) + assert_equal(d1, data[p:p+11]) + + stream.seek(321, 1) + p = 123+11+321 + assert_equal(stream.tell(), p) + d2 = stream.read(21) + assert_equal(d2, data[p:p+21]) + + stream.seek(641, 0) + p = 641 + assert_equal(stream.tell(), p) + d3 = stream.read(11) + assert_equal(d3, data[p:p+11]) + + assert_raises(OSError, stream.seek, 10, 2) + assert_raises(OSError, stream.seek, -1, 1) + assert_raises(ValueError, stream.seek, 1, 123) + + stream.seek(10000, 1) + assert_raises(OSError, stream.read, 12) + + def test_seek_bad_checksum(self): + data = random.randbytes(10) + compressed_data = zlib.compress(data) + + # break checksum + compressed_data = (compressed_data[:-1] + + bytes([(compressed_data[-1] + 1) & 255])) + + compressed_stream = BytesIO(compressed_data) + stream = ZlibInputStream(compressed_stream, len(compressed_data)) + + assert_raises(zlib.error, stream.seek, len(data)) + + def test_all_data_read(self): + compressed_stream, compressed_data_len, data = self._get_data(1024) + stream = ZlibInputStream(compressed_stream, compressed_data_len) + assert_(not stream.all_data_read()) + stream.seek(512) + assert_(not stream.all_data_read()) + stream.seek(1024) + assert_(stream.all_data_read()) + + @pytest.mark.skipif( + (platform.system() == 'Windows' and sys.version_info >= (3, 14)), + reason='gh-23185') + def test_all_data_read_overlap(self): + COMPRESSION_LEVEL = 6 + + data = np.arange(33707000, dtype=np.uint8) + compressed_data = zlib.compress(data, COMPRESSION_LEVEL) + compressed_data_len = len(compressed_data) + + # check that part of the checksum overlaps + assert_(compressed_data_len == BLOCK_SIZE + 2) + + compressed_stream = BytesIO(compressed_data) + stream = ZlibInputStream(compressed_stream, compressed_data_len) + assert_(not stream.all_data_read()) + stream.seek(len(data)) + assert_(stream.all_data_read()) + + @pytest.mark.skipif( + (platform.system() == 'Windows' and sys.version_info >= (3, 14)), + reason='gh-23185') + def test_all_data_read_bad_checksum(self): + COMPRESSION_LEVEL = 6 + + data = np.arange(33707000, dtype=np.uint8) + compressed_data = zlib.compress(data, COMPRESSION_LEVEL) + compressed_data_len = len(compressed_data) + + # check that part of the checksum overlaps + assert_(compressed_data_len == BLOCK_SIZE + 2) + + # break checksum + compressed_data = (compressed_data[:-1] + + bytes([(compressed_data[-1] + 1) & 255])) + + compressed_stream = BytesIO(compressed_data) + stream = ZlibInputStream(compressed_stream, compressed_data_len) + assert_(not stream.all_data_read()) + stream.seek(len(data)) + + assert_raises(zlib.error, stream.all_data_read) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bb88ece80f954b780912d1559bb7ac1c3d58b3bc Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_fortran.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_fortran.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9d1768c88f29be1eb7d4f0212f6e9ccaa2c27f40 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_fortran.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_idl.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_idl.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6b9befd299db50cd45a7111ded9197e96b20547f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_idl.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_mmio.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_mmio.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7540928eab0c30c7803bcbc4c969a4d7df8086f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_mmio.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_netcdf.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_netcdf.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2717c6842313db9d5c5900cbaf53741a62173c39 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_netcdf.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_paths.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_paths.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6cb05a8726a0490b0d5acec61a03d1cdaab0828d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_paths.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_wavfile.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_wavfile.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b03fab92d1f8674e7eb3b80c2dfb4b9b2251d14b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/__pycache__/test_wavfile.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/Transparent Busy.ani b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/Transparent Busy.ani new file mode 100644 index 0000000000000000000000000000000000000000..3be500032786398c3efdbd9f873f705b6c1636bd Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/Transparent Busy.ani differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_1d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_1d.sav new file mode 100644 index 0000000000000000000000000000000000000000..619a1259670a361ac76ffa86c481a813dbaec07a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_1d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_2d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_2d.sav new file mode 100644 index 0000000000000000000000000000000000000000..804d8b1a8a90636c880e974b6f85bd385033306b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_2d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_3d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_3d.sav new file mode 100644 index 0000000000000000000000000000000000000000..3fa56c450eaa916d9c91b492ba17e7e843df2d53 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_3d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_4d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_4d.sav new file mode 100644 index 0000000000000000000000000000000000000000..4bb951e274a399f091ff70b639d6e3b55ee1e122 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_4d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_5d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_5d.sav new file mode 100644 index 0000000000000000000000000000000000000000..2854dbc8b1e53f298ac3b135eac1f06e73940152 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_5d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_6d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_6d.sav new file mode 100644 index 0000000000000000000000000000000000000000..91588d348d5f89af354209840062202d5b28c1df Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_6d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_7d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_7d.sav new file mode 100644 index 0000000000000000000000000000000000000000..3e978fad540a8979435d4561de151573696affd8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_7d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_8d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_8d.sav new file mode 100644 index 0000000000000000000000000000000000000000..f699fe2427dfe876283de0fcade2c2325a262061 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_8d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_1d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_1d.sav new file mode 100644 index 0000000000000000000000000000000000000000..8e3a402c60a515149811e2ca21628e97180c4956 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_1d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_2d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_2d.sav new file mode 100644 index 0000000000000000000000000000000000000000..dd3504f0ecfaed178ace02e1a8a84650111c3936 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_2d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_3d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_3d.sav new file mode 100644 index 0000000000000000000000000000000000000000..285da7f78ffbbf2155fd2e4e648f19a1d3a42ac3 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_3d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_4d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_4d.sav new file mode 100644 index 0000000000000000000000000000000000000000..d99fa48f0a43ec06c3101560f9cade829c8b1940 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_4d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_5d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_5d.sav new file mode 100644 index 0000000000000000000000000000000000000000..de5e984e49f507ae550b1ae2fd54b799e742a195 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_5d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_6d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_6d.sav new file mode 100644 index 0000000000000000000000000000000000000000..bb76671a65be41fd2a426146c6c366f1e7fb07c3 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_6d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_7d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_7d.sav new file mode 100644 index 0000000000000000000000000000000000000000..995d23c6ed05b095442b6247b09191126f797f23 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_7d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_8d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_8d.sav new file mode 100644 index 0000000000000000000000000000000000000000..4249ec62119e264d55a81d3faf9c87dcaed1c7c8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/array_float32_pointer_8d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/example_1.nc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/example_1.nc new file mode 100644 index 0000000000000000000000000000000000000000..5775622d0ef85828b436dffcd21366f7538fc55c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/example_1.nc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/example_2.nc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/example_2.nc new file mode 100644 index 0000000000000000000000000000000000000000..07db1cd986a4c3b9929c01c1f22bcc3f562b1c16 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/example_2.nc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/example_3_maskedvals.nc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/example_3_maskedvals.nc new file mode 100644 index 0000000000000000000000000000000000000000..57f8bf9da3bca295c15508963c77a870222af0bc Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/example_3_maskedvals.nc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-3x3d-2i.dat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-3x3d-2i.dat new file mode 100644 index 0000000000000000000000000000000000000000..87731eb9d4b1f2ac827a212436fe6de175431e11 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-3x3d-2i.dat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-mixed.dat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-mixed.dat new file mode 100644 index 0000000000000000000000000000000000000000..a165a7a30424b20af9a3a0636c5e655239ea6fa5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-mixed.dat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-11x1x10.dat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-11x1x10.dat new file mode 100644 index 0000000000000000000000000000000000000000..c3bb9dcbe50ef784ce3282b28e53f4c40beb48ce Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-11x1x10.dat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-15x10x22.dat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-15x10x22.dat new file mode 100644 index 0000000000000000000000000000000000000000..351801fd47a2e3e48d9b63034fbae28f8318c9f9 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-15x10x22.dat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-1x1x1.dat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-1x1x1.dat new file mode 100644 index 0000000000000000000000000000000000000000..64bf92f74a457d2f4bc42798493db15cc3ab1008 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-1x1x1.dat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-1x1x5.dat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-1x1x5.dat new file mode 100644 index 0000000000000000000000000000000000000000..3d3f27f88eef4e02451d18204cdcfd51f96f6d15 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-1x1x5.dat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-1x1x7.dat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-1x1x7.dat new file mode 100644 index 0000000000000000000000000000000000000000..0bd683096f18eadceb7168f811c75bf072baecfe Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-1x1x7.dat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-1x3x5.dat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-1x3x5.dat new file mode 100644 index 0000000000000000000000000000000000000000..25269ff9ea4f6dd3f8a9ca0c8ad27d399e4248f5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-sf8-1x3x5.dat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-11x1x10.dat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-11x1x10.dat new file mode 100644 index 0000000000000000000000000000000000000000..9850de37cf86af622b759625c15e6b1a9477ce47 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-11x1x10.dat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-15x10x22.dat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-15x10x22.dat new file mode 100644 index 0000000000000000000000000000000000000000..98c09c2dff6e1ef605e25ed1d00afe94597abddc Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-15x10x22.dat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-1x1x1.dat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-1x1x1.dat new file mode 100644 index 0000000000000000000000000000000000000000..959098d2a9cdd6140758843e059d4ca529b14279 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-1x1x1.dat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-1x1x5.dat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-1x1x5.dat new file mode 100644 index 0000000000000000000000000000000000000000..49c0ec1d18d9f08111fe2d2a269ed407da71b158 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-1x1x5.dat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-1x1x7.dat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-1x1x7.dat new file mode 100644 index 0000000000000000000000000000000000000000..bb936b8789920ce18281fa754a5c048b31e59ba8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-1x1x7.dat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-1x3x5.dat b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-1x3x5.dat new file mode 100644 index 0000000000000000000000000000000000000000..cb3e9e4876249f42924a43232b74f05b91123815 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/fortran-si4-1x3x5.dat differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/invalid_pointer.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/invalid_pointer.sav new file mode 100644 index 0000000000000000000000000000000000000000..d53893c6c734e6c7771e08042c16874623dc6f0e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/invalid_pointer.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/null_pointer.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/null_pointer.sav new file mode 100644 index 0000000000000000000000000000000000000000..8cee5ebecc3bef248ed37c438e0731160b31a310 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/null_pointer.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_byte.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_byte.sav new file mode 100644 index 0000000000000000000000000000000000000000..e4027b3cf302b8610b87d9ef8b0aac39d5a40ef9 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_byte.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_byte_descr.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_byte_descr.sav new file mode 100644 index 0000000000000000000000000000000000000000..182e29bc57dc05154388553a71876820025bca8d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_byte_descr.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_complex32.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_complex32.sav new file mode 100644 index 0000000000000000000000000000000000000000..593e8c6208ab0bf3aa869de89e213b8aa9f8c071 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_complex32.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_complex64.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_complex64.sav new file mode 100644 index 0000000000000000000000000000000000000000..edb19d388afbaff44e5f0883978e6a74e9755613 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_complex64.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_float32.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_float32.sav new file mode 100644 index 0000000000000000000000000000000000000000..be9e3877ea845da76d9466c14d70c4cce882368c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_float32.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_float64.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_float64.sav new file mode 100644 index 0000000000000000000000000000000000000000..9680b2878c6008a27c8fc9ae6966903ff936cc4a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_float64.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_heap_pointer.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_heap_pointer.sav new file mode 100644 index 0000000000000000000000000000000000000000..d02b1756ac043a4ba6119acb28ef34c40359a4dd Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_heap_pointer.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_int16.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_int16.sav new file mode 100644 index 0000000000000000000000000000000000000000..603525694cc307d47412717c4c2f85ddc960897b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_int16.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_int32.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_int32.sav new file mode 100644 index 0000000000000000000000000000000000000000..40210b889402c0f27562296ab39ce1a714f0d0ef Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_int32.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_int64.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_int64.sav new file mode 100644 index 0000000000000000000000000000000000000000..c91cd0a561e011a2f18c86119e45392fbc0be825 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_int64.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_string.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_string.sav new file mode 100644 index 0000000000000000000000000000000000000000..ee6e69fe8461edfa580f682761118c8afe2add3a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_string.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_uint16.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_uint16.sav new file mode 100644 index 0000000000000000000000000000000000000000..759c2e64fa034c6ddbdbe6181efae1e699a0c314 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_uint16.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_uint32.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_uint32.sav new file mode 100644 index 0000000000000000000000000000000000000000..74dec7b8933418d30d17c83d617443a73ceef0c6 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_uint32.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_uint64.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_uint64.sav new file mode 100644 index 0000000000000000000000000000000000000000..fc9da5796eab6ce9fb59488b836ba2f567de7b25 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/scalar_uint64.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_arrays.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_arrays.sav new file mode 100644 index 0000000000000000000000000000000000000000..40c9cd330e0c731968d71dbbfeae9bd8c4a745a2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_arrays.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_arrays_byte_idl80.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_arrays_byte_idl80.sav new file mode 100644 index 0000000000000000000000000000000000000000..f1aa416f8e661893be282a490005536953d4b7af Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_arrays_byte_idl80.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_arrays_replicated.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_arrays_replicated.sav new file mode 100644 index 0000000000000000000000000000000000000000..6f01fbfd109e76c94b6e6e9bfd9eb388f39d99ee Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_arrays_replicated.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_arrays_replicated_3d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_arrays_replicated_3d.sav new file mode 100644 index 0000000000000000000000000000000000000000..bac9b207488eb9712ec27fb3567155f0dd773f34 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_arrays_replicated_3d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_inherit.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_inherit.sav new file mode 100644 index 0000000000000000000000000000000000000000..8babd56306f09fa612f731ce593ae13c75f84f4c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_inherit.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointer_arrays.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointer_arrays.sav new file mode 100644 index 0000000000000000000000000000000000000000..a3c678162911426702a9a6e932761385a01f247e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointer_arrays.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointer_arrays_replicated.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointer_arrays_replicated.sav new file mode 100644 index 0000000000000000000000000000000000000000..38b812261125e6aabef8618955b234f6c7b04955 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointer_arrays_replicated.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointer_arrays_replicated_3d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointer_arrays_replicated_3d.sav new file mode 100644 index 0000000000000000000000000000000000000000..db1c256c85a707f0a0d78c28241b78d1eddcab1e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointer_arrays_replicated_3d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointers.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointers.sav new file mode 100644 index 0000000000000000000000000000000000000000..acbb058a307090f6c9e2d8402c7badf6bb48144c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointers.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointers_replicated.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointers_replicated.sav new file mode 100644 index 0000000000000000000000000000000000000000..d16f4655cc20318db2b0d629cd5ed6d7be01b518 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointers_replicated.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointers_replicated_3d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointers_replicated_3d.sav new file mode 100644 index 0000000000000000000000000000000000000000..732dd2cbfa9c7fd029bb59b4cfcb630cc1077f54 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_pointers_replicated_3d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_scalars.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_scalars.sav new file mode 100644 index 0000000000000000000000000000000000000000..69d7eaf4ecf8747c21d07e14edcf65b4e394974c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_scalars.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_scalars_replicated.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_scalars_replicated.sav new file mode 100644 index 0000000000000000000000000000000000000000..2222391ae5b93ba34c1fdb982c02eb97d9658b58 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_scalars_replicated.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_scalars_replicated_3d.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_scalars_replicated_3d.sav new file mode 100644 index 0000000000000000000000000000000000000000..a35f1acfb4cb93ecb637310bbfa7fc1a2151d483 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/struct_scalars_replicated_3d.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-1234Hz-le-1ch-10S-20bit-extra.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-1234Hz-le-1ch-10S-20bit-extra.wav new file mode 100644 index 0000000000000000000000000000000000000000..13f131e399996bb28ce3df0e3f17d1dcd79df1c8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-1234Hz-le-1ch-10S-20bit-extra.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-2ch-32bit-float-be.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-2ch-32bit-float-be.wav new file mode 100644 index 0000000000000000000000000000000000000000..056333e713fb53b71d762b3623232a63830fb5aa Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-2ch-32bit-float-be.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-2ch-32bit-float-le.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-2ch-32bit-float-le.wav new file mode 100644 index 0000000000000000000000000000000000000000..57e6f17898dcd84aa0f446dab8e5d4435e9b11e2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-2ch-32bit-float-le.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-be-1ch-4bytes.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-be-1ch-4bytes.wav new file mode 100644 index 0000000000000000000000000000000000000000..1825dfcf4c4689e7fa27e2d61120aff3ae158111 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-be-1ch-4bytes.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-early-eof-no-data.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-early-eof-no-data.wav new file mode 100644 index 0000000000000000000000000000000000000000..bb86f2f3c80bcaa0e0e1af8e1ef7e1cf47cf5ca7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-early-eof-no-data.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-early-eof.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-early-eof.wav new file mode 100644 index 0000000000000000000000000000000000000000..d1b7065caabe860f1bc1c3f0775cb16c3217f5dd Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-early-eof.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-incomplete-chunk.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-incomplete-chunk.wav new file mode 100644 index 0000000000000000000000000000000000000000..7271fdd2e62c10bdc2e5c0d95efac9d9fc2131c0 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-incomplete-chunk.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-rf64.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-rf64.wav new file mode 100644 index 0000000000000000000000000000000000000000..0bc723300b760e338a28c85c27224ae7d768ed89 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-le-1ch-4bytes-rf64.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-le-1ch-4bytes.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-le-1ch-4bytes.wav new file mode 100644 index 0000000000000000000000000000000000000000..8aae8e2c6aba3ce8ccceb9bea7efa5d23223c06b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-44100Hz-le-1ch-4bytes.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-48000Hz-2ch-64bit-float-le-wavex.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-48000Hz-2ch-64bit-float-le-wavex.wav new file mode 100644 index 0000000000000000000000000000000000000000..31221b2ad7e4fe25cd8010fb1aadb4ddffd43c8f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-48000Hz-2ch-64bit-float-le-wavex.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-be-3ch-5S-24bit.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-be-3ch-5S-24bit.wav new file mode 100644 index 0000000000000000000000000000000000000000..db596cc521e4e7b1610a1171abc4a0f65cb10f45 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-be-3ch-5S-24bit.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-1ch-1byte-ulaw.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-1ch-1byte-ulaw.wav new file mode 100644 index 0000000000000000000000000000000000000000..c4fed62668e80a436f2e3d4268604ff0a2ebe91f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-1ch-1byte-ulaw.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-2ch-1byteu.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-2ch-1byteu.wav new file mode 100644 index 0000000000000000000000000000000000000000..709008194a30544056b82971df02b275bd04c570 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-2ch-1byteu.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit-inconsistent.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit-inconsistent.wav new file mode 100644 index 0000000000000000000000000000000000000000..8e79d54dee97945acbb35198f228c5cefdba80e5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit-inconsistent.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit-rf64.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit-rf64.wav new file mode 100644 index 0000000000000000000000000000000000000000..8f5a81d4bad96fbc2f4db341c64724c666de9fdb Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit-rf64.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit.wav new file mode 100644 index 0000000000000000000000000000000000000000..9c4312bce7408f2a39577903527892e4ed1527ed Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-24bit.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-36bit.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-36bit.wav new file mode 100644 index 0000000000000000000000000000000000000000..5c28ed81b1b49ccad1aab0d739ff11c901a8a95b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-36bit.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-45bit.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-45bit.wav new file mode 100644 index 0000000000000000000000000000000000000000..2d4eea22db22512462368a32047b1bba5f081d94 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-45bit.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-53bit.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-53bit.wav new file mode 100644 index 0000000000000000000000000000000000000000..68437dad75a2691985bc532b740c11830dd06765 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-53bit.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-64bit.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-64bit.wav new file mode 100644 index 0000000000000000000000000000000000000000..ef478def8a98686257753d485b9d838f97142305 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-3ch-5S-64bit.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-4ch-9S-12bit.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-4ch-9S-12bit.wav new file mode 100644 index 0000000000000000000000000000000000000000..9c93e1323ed5554777541328408ad1d019c63f80 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-4ch-9S-12bit.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-5ch-9S-5bit.wav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-5ch-9S-5bit.wav new file mode 100644 index 0000000000000000000000000000000000000000..b95bcdf33448f246828aafe7985e77db40befcbe Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/test-8000Hz-le-5ch-9S-5bit.wav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/various_compressed.sav b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/various_compressed.sav new file mode 100644 index 0000000000000000000000000000000000000000..dcdb0b0d433939d6a240c86e5060214cd8875732 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/data/various_compressed.sav differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/test_fortran.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/test_fortran.py new file mode 100644 index 0000000000000000000000000000000000000000..d370b3098d0465f8d133da58c6aebbfec85d294b --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/test_fortran.py @@ -0,0 +1,344 @@ +''' Tests for fortran sequential files ''' + +import tempfile +import shutil +import os +from os import path +from glob import iglob +import threading +import re + +from numpy.testing import assert_equal, assert_allclose +import numpy as np +import pytest + +from scipy.io import (FortranFile, + FortranEOFError, + FortranFormattingError) + + +DATA_PATH = path.join(path.dirname(__file__), 'data') + + +@pytest.fixture +def io_lock(): + return threading.Lock() + + +def test_fortranfiles_read(io_lock): + for filename in iglob(path.join(DATA_PATH, "fortran-*-*x*x*.dat")): + m = re.search(r'fortran-([^-]+)-(\d+)x(\d+)x(\d+).dat', filename, re.I) + if not m: + raise RuntimeError(f"Couldn't match {filename} filename to regex") + + dims = (int(m.group(2)), int(m.group(3)), int(m.group(4))) + + dtype = m.group(1).replace('s', '<') + + with io_lock: + f = FortranFile(filename, 'r', ' 0] = 1 + info = (2, 2, 3, 'coordinate', 'pattern', 'general') + mmwrite(self.fn, a, field='pattern') + assert_equal(mminfo(self.fn), info) + b = mmread(self.fn, spmatrix=False) + assert_array_almost_equal(p, b.toarray()) + assert not scipy.sparse.isspmatrix(b) + + b = mmread(self.fn, spmatrix=True) + assert scipy.sparse.isspmatrix(b) + b = mmread(self.fn) # chk default + assert scipy.sparse.isspmatrix(b) + + def test_gh13634_non_skew_symmetric_int(self): + a = scipy.sparse.csr_array([[1, 2], [-2, 99]], dtype=np.int32) + self.check_exact(a, (2, 2, 4, 'coordinate', 'integer', 'general')) + + def test_gh13634_non_skew_symmetric_float(self): + a = scipy.sparse.csr_array([[1, 2], [-2, 99.]], dtype=np.float32) + self.check(a, (2, 2, 4, 'coordinate', 'real', 'general')) + + +_32bit_integer_dense_example = '''\ +%%MatrixMarket matrix array integer general +2 2 +2147483647 +2147483646 +2147483647 +2147483646 +''' + +_32bit_integer_sparse_example = '''\ +%%MatrixMarket matrix coordinate integer symmetric +2 2 2 +1 1 2147483647 +2 2 2147483646 +''' + +_64bit_integer_dense_example = '''\ +%%MatrixMarket matrix array integer general +2 2 + 2147483648 +-9223372036854775806 + -2147483648 + 9223372036854775807 +''' + +_64bit_integer_sparse_general_example = '''\ +%%MatrixMarket matrix coordinate integer general +2 2 3 +1 1 2147483648 +1 2 9223372036854775807 +2 2 9223372036854775807 +''' + +_64bit_integer_sparse_symmetric_example = '''\ +%%MatrixMarket matrix coordinate integer symmetric +2 2 3 +1 1 2147483648 +1 2 -9223372036854775807 +2 2 9223372036854775807 +''' + +_64bit_integer_sparse_skew_example = '''\ +%%MatrixMarket matrix coordinate integer skew-symmetric +2 2 3 +1 1 2147483648 +1 2 -9223372036854775807 +2 2 9223372036854775807 +''' + +_over64bit_integer_dense_example = '''\ +%%MatrixMarket matrix array integer general +2 2 + 2147483648 +9223372036854775807 + 2147483648 +9223372036854775808 +''' + +_over64bit_integer_sparse_example = '''\ +%%MatrixMarket matrix coordinate integer symmetric +2 2 2 +1 1 2147483648 +2 2 19223372036854775808 +''' + + +class TestMMIOReadLargeIntegers: + def setup_method(self): + self.tmpdir = mkdtemp(suffix=str(threading.get_native_id())) + self.fn = os.path.join(self.tmpdir, 'testfile.mtx') + + def teardown_method(self): + shutil.rmtree(self.tmpdir) + + def check_read(self, example, a, info, dense, over32, over64): + with open(self.fn, 'w') as f: + f.write(example) + assert_equal(mminfo(self.fn), info) + if ((over32 and (np.intp(0).itemsize < 8) and mmwrite == scipy.io._mmio.mmwrite) + or over64): + assert_raises(OverflowError, mmread, self.fn) + else: + b = mmread(self.fn, spmatrix=False) + if not dense: + b = b.toarray() + assert_equal(a, b) + + def test_read_32bit_integer_dense(self): + a = array([[2**31-1, 2**31-1], + [2**31-2, 2**31-2]], dtype=np.int64) + self.check_read(_32bit_integer_dense_example, + a, + (2, 2, 4, 'array', 'integer', 'general'), + dense=True, + over32=False, + over64=False) + + def test_read_32bit_integer_sparse(self): + a = array([[2**31-1, 0], + [0, 2**31-2]], dtype=np.int64) + self.check_read(_32bit_integer_sparse_example, + a, + (2, 2, 2, 'coordinate', 'integer', 'symmetric'), + dense=False, + over32=False, + over64=False) + + def test_read_64bit_integer_dense(self): + a = array([[2**31, -2**31], + [-2**63+2, 2**63-1]], dtype=np.int64) + self.check_read(_64bit_integer_dense_example, + a, + (2, 2, 4, 'array', 'integer', 'general'), + dense=True, + over32=True, + over64=False) + + def test_read_64bit_integer_sparse_general(self): + a = array([[2**31, 2**63-1], + [0, 2**63-1]], dtype=np.int64) + self.check_read(_64bit_integer_sparse_general_example, + a, + (2, 2, 3, 'coordinate', 'integer', 'general'), + dense=False, + over32=True, + over64=False) + + def test_read_64bit_integer_sparse_symmetric(self): + a = array([[2**31, -2**63+1], + [-2**63+1, 2**63-1]], dtype=np.int64) + self.check_read(_64bit_integer_sparse_symmetric_example, + a, + (2, 2, 3, 'coordinate', 'integer', 'symmetric'), + dense=False, + over32=True, + over64=False) + + def test_read_64bit_integer_sparse_skew(self): + a = array([[2**31, -2**63+1], + [2**63-1, 2**63-1]], dtype=np.int64) + self.check_read(_64bit_integer_sparse_skew_example, + a, + (2, 2, 3, 'coordinate', 'integer', 'skew-symmetric'), + dense=False, + over32=True, + over64=False) + + def test_read_over64bit_integer_dense(self): + self.check_read(_over64bit_integer_dense_example, + None, + (2, 2, 4, 'array', 'integer', 'general'), + dense=True, + over32=True, + over64=True) + + def test_read_over64bit_integer_sparse(self): + self.check_read(_over64bit_integer_sparse_example, + None, + (2, 2, 2, 'coordinate', 'integer', 'symmetric'), + dense=False, + over32=True, + over64=True) + + +_general_example = '''\ +%%MatrixMarket matrix coordinate real general +%================================================================================= +% +% This ASCII file represents a sparse MxN matrix with L +% nonzeros in the following Matrix Market format: +% +% +----------------------------------------------+ +% |%%MatrixMarket matrix coordinate real general | <--- header line +% |% | <--+ +% |% comments | |-- 0 or more comment lines +% |% | <--+ +% | M N L | <--- rows, columns, entries +% | I1 J1 A(I1, J1) | <--+ +% | I2 J2 A(I2, J2) | | +% | I3 J3 A(I3, J3) | |-- L lines +% | . . . | | +% | IL JL A(IL, JL) | <--+ +% +----------------------------------------------+ +% +% Indices are 1-based, i.e. A(1,1) is the first element. +% +%================================================================================= + 5 5 8 + 1 1 1.000e+00 + 2 2 1.050e+01 + 3 3 1.500e-02 + 1 4 6.000e+00 + 4 2 2.505e+02 + 4 4 -2.800e+02 + 4 5 3.332e+01 + 5 5 1.200e+01 +''' + +_hermitian_example = '''\ +%%MatrixMarket matrix coordinate complex hermitian + 5 5 7 + 1 1 1.0 0 + 2 2 10.5 0 + 4 2 250.5 22.22 + 3 3 1.5e-2 0 + 4 4 -2.8e2 0 + 5 5 12. 0 + 5 4 0 33.32 +''' + +_skew_example = '''\ +%%MatrixMarket matrix coordinate real skew-symmetric + 5 5 7 + 1 1 1.0 + 2 2 10.5 + 4 2 250.5 + 3 3 1.5e-2 + 4 4 -2.8e2 + 5 5 12. + 5 4 0 +''' + +_symmetric_example = '''\ +%%MatrixMarket matrix coordinate real symmetric + 5 5 7 + 1 1 1.0 + 2 2 10.5 + 4 2 250.5 + 3 3 1.5e-2 + 4 4 -2.8e2 + 5 5 12. + 5 4 8 +''' + +_symmetric_pattern_example = '''\ +%%MatrixMarket matrix coordinate pattern symmetric + 5 5 7 + 1 1 + 2 2 + 4 2 + 3 3 + 4 4 + 5 5 + 5 4 +''' + +# example (without comment lines) from Figure 1 in +# https://math.nist.gov/MatrixMarket/reports/MMformat.ps +_empty_lines_example = '''\ +%%MatrixMarket MATRIX Coordinate Real General + + 5 5 8 + +1 1 1.0 +2 2 10.5 +3 3 1.5e-2 +4 4 -2.8E2 +5 5 12. + 1 4 6 + 4 2 250.5 + 4 5 33.32 + +''' + + +class TestMMIOCoordinate: + def setup_method(self): + self.tmpdir = mkdtemp(suffix=str(threading.get_native_id())) + self.fn = os.path.join(self.tmpdir, 'testfile.mtx') + + def teardown_method(self): + shutil.rmtree(self.tmpdir) + + def check_read(self, example, a, info): + f = open(self.fn, 'w') + f.write(example) + f.close() + assert_equal(mminfo(self.fn), info) + b = mmread(self.fn, spmatrix=False).toarray() + assert_array_almost_equal(a, b) + + def test_read_general(self): + a = [[1, 0, 0, 6, 0], + [0, 10.5, 0, 0, 0], + [0, 0, .015, 0, 0], + [0, 250.5, 0, -280, 33.32], + [0, 0, 0, 0, 12]] + self.check_read(_general_example, a, + (5, 5, 8, 'coordinate', 'real', 'general')) + + def test_read_hermitian(self): + a = [[1, 0, 0, 0, 0], + [0, 10.5, 0, 250.5 - 22.22j, 0], + [0, 0, .015, 0, 0], + [0, 250.5 + 22.22j, 0, -280, -33.32j], + [0, 0, 0, 33.32j, 12]] + self.check_read(_hermitian_example, a, + (5, 5, 7, 'coordinate', 'complex', 'hermitian')) + + def test_read_skew(self): + a = [[1, 0, 0, 0, 0], + [0, 10.5, 0, -250.5, 0], + [0, 0, .015, 0, 0], + [0, 250.5, 0, -280, 0], + [0, 0, 0, 0, 12]] + self.check_read(_skew_example, a, + (5, 5, 7, 'coordinate', 'real', 'skew-symmetric')) + + def test_read_symmetric(self): + a = [[1, 0, 0, 0, 0], + [0, 10.5, 0, 250.5, 0], + [0, 0, .015, 0, 0], + [0, 250.5, 0, -280, 8], + [0, 0, 0, 8, 12]] + self.check_read(_symmetric_example, a, + (5, 5, 7, 'coordinate', 'real', 'symmetric')) + + def test_read_symmetric_pattern(self): + a = [[1, 0, 0, 0, 0], + [0, 1, 0, 1, 0], + [0, 0, 1, 0, 0], + [0, 1, 0, 1, 1], + [0, 0, 0, 1, 1]] + self.check_read(_symmetric_pattern_example, a, + (5, 5, 7, 'coordinate', 'pattern', 'symmetric')) + + def test_read_empty_lines(self): + a = [[1, 0, 0, 6, 0], + [0, 10.5, 0, 0, 0], + [0, 0, .015, 0, 0], + [0, 250.5, 0, -280, 33.32], + [0, 0, 0, 0, 12]] + self.check_read(_empty_lines_example, a, + (5, 5, 8, 'coordinate', 'real', 'general')) + + def test_empty_write_read(self): + # https://github.com/scipy/scipy/issues/1410 (Trac #883) + + b = scipy.sparse.coo_array((10, 10)) + mmwrite(self.fn, b) + + assert_equal(mminfo(self.fn), + (10, 10, 0, 'coordinate', 'real', 'symmetric')) + a = b.toarray() + b = mmread(self.fn, spmatrix=False).toarray() + assert_array_almost_equal(a, b) + + def test_bzip2_py3(self): + # test if fix for #2152 works + try: + # bz2 module isn't always built when building Python. + import bz2 + except ImportError: + return + I = array([0, 0, 1, 2, 3, 3, 3, 4]) + J = array([0, 3, 1, 2, 1, 3, 4, 4]) + V = array([1.0, 6.0, 10.5, 0.015, 250.5, -280.0, 33.32, 12.0]) + + b = scipy.sparse.coo_array((V, (I, J)), shape=(5, 5)) + + mmwrite(self.fn, b) + + fn_bzip2 = f"{self.fn}.bz2" + with open(self.fn, 'rb') as f_in: + f_out = bz2.BZ2File(fn_bzip2, 'wb') + f_out.write(f_in.read()) + f_out.close() + + a = mmread(fn_bzip2, spmatrix=False).toarray() + assert_array_almost_equal(a, b.toarray()) + + def test_gzip_py3(self): + # test if fix for #2152 works + try: + # gzip module can be missing from Python installation + import gzip + except ImportError: + return + I = array([0, 0, 1, 2, 3, 3, 3, 4]) + J = array([0, 3, 1, 2, 1, 3, 4, 4]) + V = array([1.0, 6.0, 10.5, 0.015, 250.5, -280.0, 33.32, 12.0]) + + b = scipy.sparse.coo_array((V, (I, J)), shape=(5, 5)) + + mmwrite(self.fn, b) + + fn_gzip = f"{self.fn}.gz" + with open(self.fn, 'rb') as f_in: + f_out = gzip.open(fn_gzip, 'wb') + f_out.write(f_in.read()) + f_out.close() + + a = mmread(fn_gzip, spmatrix=False).toarray() + assert_array_almost_equal(a, b.toarray()) + + def test_real_write_read(self): + I = array([0, 0, 1, 2, 3, 3, 3, 4]) + J = array([0, 3, 1, 2, 1, 3, 4, 4]) + V = array([1.0, 6.0, 10.5, 0.015, 250.5, -280.0, 33.32, 12.0]) + + b = scipy.sparse.coo_array((V, (I, J)), shape=(5, 5)) + + mmwrite(self.fn, b) + + assert_equal(mminfo(self.fn), + (5, 5, 8, 'coordinate', 'real', 'general')) + a = b.toarray() + b = mmread(self.fn, spmatrix=False).toarray() + assert_array_almost_equal(a, b) + + def test_complex_write_read(self): + I = array([0, 0, 1, 2, 3, 3, 3, 4]) + J = array([0, 3, 1, 2, 1, 3, 4, 4]) + V = array([1.0 + 3j, 6.0 + 2j, 10.50 + 0.9j, 0.015 + -4.4j, + 250.5 + 0j, -280.0 + 5j, 33.32 + 6.4j, 12.00 + 0.8j]) + + b = scipy.sparse.coo_array((V, (I, J)), shape=(5, 5)) + + mmwrite(self.fn, b) + + assert_equal(mminfo(self.fn), + (5, 5, 8, 'coordinate', 'complex', 'general')) + a = b.toarray() + b = mmread(self.fn, spmatrix=False).toarray() + assert_array_almost_equal(a, b) + + def test_sparse_formats(self, tmp_path): + # Note: `tmp_path` is a pytest fixture, it handles cleanup + tmpdir = tmp_path / 'sparse_formats' + tmpdir.mkdir() + + mats = [] + I = array([0, 0, 1, 2, 3, 3, 3, 4]) + J = array([0, 3, 1, 2, 1, 3, 4, 4]) + + V = array([1.0, 6.0, 10.5, 0.015, 250.5, -280.0, 33.32, 12.0]) + mats.append(scipy.sparse.coo_array((V, (I, J)), shape=(5, 5))) + + V = array([1.0 + 3j, 6.0 + 2j, 10.50 + 0.9j, 0.015 + -4.4j, + 250.5 + 0j, -280.0 + 5j, 33.32 + 6.4j, 12.00 + 0.8j]) + mats.append(scipy.sparse.coo_array((V, (I, J)), shape=(5, 5))) + + for mat in mats: + expected = mat.toarray() + for fmt in ['csr', 'csc', 'coo']: + fname = tmpdir / (fmt + '.mtx') + mmwrite(fname, mat.asformat(fmt)) + result = mmread(fname, spmatrix=False).toarray() + assert_array_almost_equal(result, expected) + + def test_precision(self): + test_values = [pi] + [10**(i) for i in range(0, -10, -1)] + test_precisions = range(1, 10) + for value in test_values: + for precision in test_precisions: + # construct sparse matrix with test value at last main diagonal + n = 10**precision + 1 + A = scipy.sparse.dok_array((n, n)) + A[n-1, n-1] = value + # write matrix with test precision and read again + mmwrite(self.fn, A, precision=precision) + A = scipy.io.mmread(self.fn, spmatrix=False) + # check for right entries in matrix + assert_array_equal(A.row, [n-1]) + assert_array_equal(A.col, [n-1]) + assert_allclose(A.data, [float(f'{value:.{precision}g}')]) + + def test_bad_number_of_coordinate_header_fields(self): + s = """\ + %%MatrixMarket matrix coordinate real general + 5 5 8 999 + 1 1 1.000e+00 + 2 2 1.050e+01 + 3 3 1.500e-02 + 1 4 6.000e+00 + 4 2 2.505e+02 + 4 4 -2.800e+02 + 4 5 3.332e+01 + 5 5 1.200e+01 + """ + text = textwrap.dedent(s).encode('ascii') + with pytest.raises(ValueError, match='not of length 3'): + scipy.io.mmread(io.BytesIO(text)) + + +def test_gh11389(): + mmread(io.StringIO("%%MatrixMarket matrix coordinate complex symmetric\n" + " 1 1 1\n" + "1 1 -2.1846000000000e+02 0.0000000000000e+00"), + spmatrix=False) + + +def test_gh18123(tmp_path): + lines = [" %%MatrixMarket matrix coordinate real general\n", + "5 5 3\n", + "2 3 1.0\n", + "3 4 2.0\n", + "3 5 3.0\n"] + test_file = tmp_path / "test.mtx" + with open(test_file, "w") as f: + f.writelines(lines) + mmread(test_file, spmatrix=False) + +def test_mtx_append(tmp_path): + a = mmread(io.StringIO("%%MatrixMarket matrix coordinate complex symmetric\n" + " 1 1 1\n" + "1 1 -2.1846000000000e+02 0.0000000000000e+00"), + spmatrix=False) + test_writefile = tmp_path / "test_mtx" + test_readfile = tmp_path / "test_mtx.mtx" + mmwrite(test_writefile, a) + mmread(test_readfile, spmatrix=False) + + +def test_threadpoolctl(): + try: + import threadpoolctl + if not hasattr(threadpoolctl, "register"): + pytest.skip("threadpoolctl too old") + return + except ImportError: + pytest.skip("no threadpoolctl") + return + + with threadpoolctl.threadpool_limits(limits=4): + assert_equal(fmm.PARALLELISM, 4) + + with threadpoolctl.threadpool_limits(limits=2, user_api='scipy'): + assert_equal(fmm.PARALLELISM, 2) + + +def test_gh21999_file_not_exist(): + tmpdir = mkdtemp(suffix=str(threading.get_native_id())) + wrong_fn = os.path.join(tmpdir, 'not_exist_test_file.mtx') + assert_raises(FileNotFoundError, mmread, wrong_fn) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/test_netcdf.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/test_netcdf.py new file mode 100644 index 0000000000000000000000000000000000000000..cf0ba2ca6667399c25d16ca3632494cfeee52352 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/test_netcdf.py @@ -0,0 +1,553 @@ +''' Tests for netcdf ''' +import os +from os.path import join as pjoin, dirname +import shutil +import tempfile +import warnings +from io import BytesIO +from glob import glob +from contextlib import contextmanager + +import numpy as np +from numpy.testing import (assert_, assert_allclose, assert_equal, + break_cycles, IS_PYPY) +import pytest +from pytest import raises as assert_raises + +from scipy.io import netcdf_file +from scipy._lib._tmpdirs import in_tempdir + +TEST_DATA_PATH = pjoin(dirname(__file__), 'data') + +N_EG_ELS = 11 # number of elements for example variable +VARTYPE_EG = 'b' # var type for example variable + + +pytestmark = pytest.mark.thread_unsafe + + +@contextmanager +def make_simple(*args, **kwargs): + f = netcdf_file(*args, **kwargs) + f.history = 'Created for a test' + f.createDimension('time', N_EG_ELS) + time = f.createVariable('time', VARTYPE_EG, ('time',)) + time[:] = np.arange(N_EG_ELS) + time.units = 'days since 2008-01-01' + f.flush() + yield f + f.close() + + +def check_simple(ncfileobj): + '''Example fileobj tests ''' + assert_equal(ncfileobj.history, b'Created for a test') + time = ncfileobj.variables['time'] + assert_equal(time.units, b'days since 2008-01-01') + assert_equal(time.shape, (N_EG_ELS,)) + assert_equal(time[-1], N_EG_ELS-1) + +def assert_mask_matches(arr, expected_mask): + ''' + Asserts that the mask of arr is effectively the same as expected_mask. + + In contrast to numpy.ma.testutils.assert_mask_equal, this function allows + testing the 'mask' of a standard numpy array (the mask in this case is treated + as all False). + + Parameters + ---------- + arr : ndarray or MaskedArray + Array to test. + expected_mask : array_like of booleans + A list giving the expected mask. + ''' + + mask = np.ma.getmaskarray(arr) + assert_equal(mask, expected_mask) + + +def test_read_write_files(): + # test round trip for example file + cwd = os.getcwd() + try: + tmpdir = tempfile.mkdtemp() + os.chdir(tmpdir) + with make_simple('simple.nc', 'w') as f: + pass + # read the file we just created in 'a' mode + with netcdf_file('simple.nc', 'a') as f: + check_simple(f) + # add something + f._attributes['appendRan'] = 1 + + # To read the NetCDF file we just created:: + with netcdf_file('simple.nc') as f: + # Using mmap is the default (but not on pypy) + assert_equal(f.use_mmap, not IS_PYPY) + check_simple(f) + assert_equal(f._attributes['appendRan'], 1) + + # Read it in append (and check mmap is off) + with netcdf_file('simple.nc', 'a') as f: + assert_(not f.use_mmap) + check_simple(f) + assert_equal(f._attributes['appendRan'], 1) + + # Now without mmap + with netcdf_file('simple.nc', mmap=False) as f: + # Using mmap is the default + assert_(not f.use_mmap) + check_simple(f) + + # To read the NetCDF file we just created, as file object, no + # mmap. When n * n_bytes(var_type) is not divisible by 4, this + # raised an error in pupynere 1.0.12 and scipy rev 5893, because + # calculated vsize was rounding up in units of 4 - see + # https://www.unidata.ucar.edu/software/netcdf/guide_toc.html + with open('simple.nc', 'rb') as fobj: + with netcdf_file(fobj) as f: + # by default, don't use mmap for file-like + assert_(not f.use_mmap) + check_simple(f) + + # Read file from fileobj, with mmap + with warnings.catch_warnings(): + if IS_PYPY: + warnings.filterwarnings( + "ignore", + "Cannot close a netcdf_file opened with mmap=True.*", + RuntimeWarning + ) + with open('simple.nc', 'rb') as fobj: + with netcdf_file(fobj, mmap=True) as f: + assert_(f.use_mmap) + check_simple(f) + + # Again read it in append mode (adding another att) + with open('simple.nc', 'r+b') as fobj: + with netcdf_file(fobj, 'a') as f: + assert_(not f.use_mmap) + check_simple(f) + f.createDimension('app_dim', 1) + var = f.createVariable('app_var', 'i', ('app_dim',)) + var[:] = 42 + + # And... check that app_var made it in... + with netcdf_file('simple.nc') as f: + check_simple(f) + assert_equal(f.variables['app_var'][:], 42) + + finally: + if IS_PYPY: + # windows cannot remove a dead file held by a mmap + # that has not been collected in PyPy + break_cycles() + break_cycles() + os.chdir(cwd) + shutil.rmtree(tmpdir) + + +def test_read_write_sio(): + eg_sio1 = BytesIO() + with make_simple(eg_sio1, 'w'): + str_val = eg_sio1.getvalue() + + eg_sio2 = BytesIO(str_val) + with netcdf_file(eg_sio2) as f2: + check_simple(f2) + + # Test that error is raised if attempting mmap for sio + eg_sio3 = BytesIO(str_val) + assert_raises(ValueError, netcdf_file, eg_sio3, 'r', True) + # Test 64-bit offset write / read + eg_sio_64 = BytesIO() + with make_simple(eg_sio_64, 'w', version=2) as f_64: + str_val = eg_sio_64.getvalue() + + eg_sio_64 = BytesIO(str_val) + with netcdf_file(eg_sio_64) as f_64: + check_simple(f_64) + assert_equal(f_64.version_byte, 2) + # also when version 2 explicitly specified + eg_sio_64 = BytesIO(str_val) + with netcdf_file(eg_sio_64, version=2) as f_64: + check_simple(f_64) + assert_equal(f_64.version_byte, 2) + + +def test_bytes(): + raw_file = BytesIO() + f = netcdf_file(raw_file, mode='w') + # Dataset only has a single variable, dimension and attribute to avoid + # any ambiguity related to order. + f.a = 'b' + f.createDimension('dim', 1) + var = f.createVariable('var', np.int16, ('dim',)) + var[0] = -9999 + var.c = 'd' + f.sync() + + actual = raw_file.getvalue() + + expected = (b'CDF\x01' + b'\x00\x00\x00\x00' + b'\x00\x00\x00\x0a' + b'\x00\x00\x00\x01' + b'\x00\x00\x00\x03' + b'dim\x00' + b'\x00\x00\x00\x01' + b'\x00\x00\x00\x0c' + b'\x00\x00\x00\x01' + b'\x00\x00\x00\x01' + b'a\x00\x00\x00' + b'\x00\x00\x00\x02' + b'\x00\x00\x00\x01' + b'b\x00\x00\x00' + b'\x00\x00\x00\x0b' + b'\x00\x00\x00\x01' + b'\x00\x00\x00\x03' + b'var\x00' + b'\x00\x00\x00\x01' + b'\x00\x00\x00\x00' + b'\x00\x00\x00\x0c' + b'\x00\x00\x00\x01' + b'\x00\x00\x00\x01' + b'c\x00\x00\x00' + b'\x00\x00\x00\x02' + b'\x00\x00\x00\x01' + b'd\x00\x00\x00' + b'\x00\x00\x00\x03' + b'\x00\x00\x00\x04' + b'\x00\x00\x00\x78' + b'\xd8\xf1\x80\x01') + + assert_equal(actual, expected) + + +def test_encoded_fill_value(): + with netcdf_file(BytesIO(), mode='w') as f: + f.createDimension('x', 1) + var = f.createVariable('var', 'S1', ('x',)) + assert_equal(var._get_encoded_fill_value(), b'\x00') + var._FillValue = b'\x01' + assert_equal(var._get_encoded_fill_value(), b'\x01') + var._FillValue = b'\x00\x00' # invalid, wrong size + assert_equal(var._get_encoded_fill_value(), b'\x00') + + +def test_read_example_data(): + # read any example data files + for fname in glob(pjoin(TEST_DATA_PATH, '*.nc')): + with netcdf_file(fname, 'r'): + pass + with netcdf_file(fname, 'r', mmap=False): + pass + + +def test_itemset_no_segfault_on_readonly(): + # Regression test for ticket #1202. + # Open the test file in read-only mode. + + filename = pjoin(TEST_DATA_PATH, 'example_1.nc') + with warnings.catch_warnings(): + message = ("Cannot close a netcdf_file opened with mmap=True, when " + "netcdf_variables or arrays referring to its data still exist") + warnings.filterwarnings("ignore", message, RuntimeWarning) + with netcdf_file(filename, 'r', mmap=True) as f: + time_var = f.variables['time'] + + # time_var.assignValue(42) should raise a RuntimeError--not seg. fault! + assert_raises(RuntimeError, time_var.assignValue, 42) + + +def test_appending_issue_gh_8625(): + stream = BytesIO() + + with make_simple(stream, mode='w') as f: + f.createDimension('x', 2) + f.createVariable('x', float, ('x',)) + f.variables['x'][...] = 1 + f.flush() + contents = stream.getvalue() + + stream = BytesIO(contents) + with netcdf_file(stream, mode='a') as f: + f.variables['x'][...] = 2 + + +def test_write_invalid_dtype(): + dtypes = ['int64', 'uint64'] + if np.dtype('int').itemsize == 8: # 64-bit machines + dtypes.append('int') + if np.dtype('uint').itemsize == 8: # 64-bit machines + dtypes.append('uint') + + with netcdf_file(BytesIO(), 'w') as f: + f.createDimension('time', N_EG_ELS) + for dt in dtypes: + assert_raises(ValueError, f.createVariable, 'time', dt, ('time',)) + + +def test_flush_rewind(): + stream = BytesIO() + with make_simple(stream, mode='w') as f: + f.createDimension('x',4) # x is used in createVariable + v = f.createVariable('v', 'i2', ['x']) + v[:] = 1 + f.flush() + len_single = len(stream.getvalue()) + f.flush() + len_double = len(stream.getvalue()) + + assert_(len_single == len_double) + + +def test_dtype_specifiers(): + # Numpy 1.7.0-dev had a bug where 'i2' wouldn't work. + # Specifying np.int16 or similar only works from the same commit as this + # comment was made. + with make_simple(BytesIO(), mode='w') as f: + f.createDimension('x',4) + f.createVariable('v1', 'i2', ['x']) + f.createVariable('v2', np.int16, ['x']) + f.createVariable('v3', np.dtype(np.int16), ['x']) + + +def test_ticket_1720(): + io = BytesIO() + + items = [0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9] + + with netcdf_file(io, 'w') as f: + f.history = 'Created for a test' + f.createDimension('float_var', 10) + float_var = f.createVariable('float_var', 'f', ('float_var',)) + float_var[:] = items + float_var.units = 'metres' + f.flush() + contents = io.getvalue() + + io = BytesIO(contents) + with netcdf_file(io, 'r') as f: + assert_equal(f.history, b'Created for a test') + float_var = f.variables['float_var'] + assert_equal(float_var.units, b'metres') + assert_equal(float_var.shape, (10,)) + assert_allclose(float_var[:], items) + + +def test_mmaps_segfault(): + filename = pjoin(TEST_DATA_PATH, 'example_1.nc') + + if not IS_PYPY: + with warnings.catch_warnings(): + warnings.simplefilter("error") + with netcdf_file(filename, mmap=True) as f: + x = f.variables['lat'][:] + # should not raise warnings + del x + + def doit(): + with netcdf_file(filename, mmap=True) as f: + return f.variables['lat'][:] + + # should not crash + with warnings.catch_warnings(): + message = ("Cannot close a netcdf_file opened with mmap=True, when " + "netcdf_variables or arrays referring to its data still exist") + warnings.filterwarnings("ignore", message, RuntimeWarning) + x = doit() + x.sum() + + +def test_zero_dimensional_var(): + io = BytesIO() + with make_simple(io, 'w') as f: + v = f.createVariable('zerodim', 'i2', []) + # This is checking that .isrec returns a boolean - don't simplify it + # to 'assert not ...' + assert v.isrec is False, v.isrec + f.flush() + + +def test_byte_gatts(): + # Check that global "string" atts work like they did before py3k + # unicode and general bytes confusion + with in_tempdir(): + filename = 'g_byte_atts.nc' + f = netcdf_file(filename, 'w') + f._attributes['holy'] = b'grail' + f._attributes['witch'] = 'floats' + f.close() + f = netcdf_file(filename, 'r') + assert_equal(f._attributes['holy'], b'grail') + assert_equal(f._attributes['witch'], b'floats') + f.close() + + +def test_open_append(): + # open 'w' put one attr + with in_tempdir(): + filename = 'append_dat.nc' + f = netcdf_file(filename, 'w') + f._attributes['Kilroy'] = 'was here' + f.close() + + # open again in 'a', read the att and a new one + f = netcdf_file(filename, 'a') + assert_equal(f._attributes['Kilroy'], b'was here') + f._attributes['naughty'] = b'Zoot' + f.close() + + # open yet again in 'r' and check both atts + f = netcdf_file(filename, 'r') + assert_equal(f._attributes['Kilroy'], b'was here') + assert_equal(f._attributes['naughty'], b'Zoot') + f.close() + + +def test_append_recordDimension(): + dataSize = 100 + + with in_tempdir(): + # Create file with record time dimension + with netcdf_file('withRecordDimension.nc', 'w') as f: + f.createDimension('time', None) + f.createVariable('time', 'd', ('time',)) + f.createDimension('x', dataSize) + x = f.createVariable('x', 'd', ('x',)) + x[:] = np.array(range(dataSize)) + f.createDimension('y', dataSize) + y = f.createVariable('y', 'd', ('y',)) + y[:] = np.array(range(dataSize)) + f.createVariable('testData', 'i', ('time', 'x', 'y')) + f.flush() + f.close() + + for i in range(2): + # Open the file in append mode and add data + with netcdf_file('withRecordDimension.nc', 'a') as f: + f.variables['time'].data = np.append(f.variables["time"].data, i) + f.variables['testData'][i, :, :] = np.full((dataSize, dataSize), i) + f.flush() + + # Read the file and check that append worked + with netcdf_file('withRecordDimension.nc') as f: + assert_equal(f.variables['time'][-1], i) + assert_equal(f.variables['testData'][-1, :, :].copy(), + np.full((dataSize, dataSize), i)) + assert_equal(f.variables['time'].data.shape[0], i+1) + assert_equal(f.variables['testData'].data.shape[0], i+1) + + # Read the file and check that 'data' was not saved as user defined + # attribute of testData variable during append operation + with netcdf_file('withRecordDimension.nc') as f: + with assert_raises(KeyError) as ar: + f.variables['testData']._attributes['data'] + ex = ar.value + assert_equal(ex.args[0], 'data') + +def test_maskandscale(): + t = np.linspace(20, 30, 15) + t[3] = 100 + tm = np.ma.masked_greater(t, 99) + fname = pjoin(TEST_DATA_PATH, 'example_2.nc') + with netcdf_file(fname, maskandscale=True) as f: + Temp = f.variables['Temperature'] + assert_equal(Temp.missing_value, 9999) + assert_equal(Temp.add_offset, 20) + assert_equal(Temp.scale_factor, np.float32(0.01)) + found = Temp[:].compressed() + del Temp # Remove ref to mmap, so file can be closed. + expected = np.round(tm.compressed(), 2) + assert_allclose(found, expected) + + with in_tempdir(): + newfname = 'ms.nc' + f = netcdf_file(newfname, 'w', maskandscale=True) + f.createDimension('Temperature', len(tm)) + temp = f.createVariable('Temperature', 'i', ('Temperature',)) + temp.missing_value = 9999 + temp.scale_factor = 0.01 + temp.add_offset = 20 + temp[:] = tm + f.close() + + with netcdf_file(newfname, maskandscale=True) as f: + Temp = f.variables['Temperature'] + assert_equal(Temp.missing_value, 9999) + assert_equal(Temp.add_offset, 20) + assert_equal(Temp.scale_factor, np.float32(0.01)) + expected = np.round(tm.compressed(), 2) + found = Temp[:].compressed() + del Temp + assert_allclose(found, expected) + + +# ------------------------------------------------------------------------ +# Test reading with masked values (_FillValue / missing_value) +# ------------------------------------------------------------------------ + +def test_read_withValuesNearFillValue(): + # Regression test for ticket #5626 + fname = pjoin(TEST_DATA_PATH, 'example_3_maskedvals.nc') + with netcdf_file(fname, maskandscale=True) as f: + vardata = f.variables['var1_fillval0'][:] + assert_mask_matches(vardata, [False, True, False]) + +def test_read_withNoFillValue(): + # For a variable with no fill value, reading data with maskandscale=True + # should return unmasked data + fname = pjoin(TEST_DATA_PATH, 'example_3_maskedvals.nc') + with netcdf_file(fname, maskandscale=True) as f: + vardata = f.variables['var2_noFillval'][:] + assert_mask_matches(vardata, [False, False, False]) + assert_equal(vardata, [1,2,3]) + +def test_read_withFillValueAndMissingValue(): + # For a variable with both _FillValue and missing_value, the _FillValue + # should be used + IRRELEVANT_VALUE = 9999 + fname = pjoin(TEST_DATA_PATH, 'example_3_maskedvals.nc') + with netcdf_file(fname, maskandscale=True) as f: + vardata = f.variables['var3_fillvalAndMissingValue'][:] + assert_mask_matches(vardata, [True, False, False]) + assert_equal(vardata, [IRRELEVANT_VALUE, 2, 3]) + +def test_read_withMissingValue(): + # For a variable with missing_value but not _FillValue, the missing_value + # should be used + fname = pjoin(TEST_DATA_PATH, 'example_3_maskedvals.nc') + with netcdf_file(fname, maskandscale=True) as f: + vardata = f.variables['var4_missingValue'][:] + assert_mask_matches(vardata, [False, True, False]) + +def test_read_withFillValNaN(): + fname = pjoin(TEST_DATA_PATH, 'example_3_maskedvals.nc') + with netcdf_file(fname, maskandscale=True) as f: + vardata = f.variables['var5_fillvalNaN'][:] + assert_mask_matches(vardata, [False, True, False]) + +def test_read_withChar(): + fname = pjoin(TEST_DATA_PATH, 'example_3_maskedvals.nc') + with netcdf_file(fname, maskandscale=True) as f: + vardata = f.variables['var6_char'][:] + assert_mask_matches(vardata, [False, True, False]) + +def test_read_with2dVar(): + fname = pjoin(TEST_DATA_PATH, 'example_3_maskedvals.nc') + with netcdf_file(fname, maskandscale=True) as f: + vardata = f.variables['var7_2d'][:] + assert_mask_matches(vardata, [[True, False], [False, False], [False, True]]) + +def test_read_withMaskAndScaleFalse(): + # If a variable has a _FillValue (or missing_value) attribute, but is read + # with maskandscale set to False, the result should be unmasked + fname = pjoin(TEST_DATA_PATH, 'example_3_maskedvals.nc') + # Open file with mmap=False to avoid problems with closing a mmap'ed file + # when arrays referring to its data still exist: + with netcdf_file(fname, maskandscale=False, mmap=False) as f: + vardata = f.variables['var3_fillvalAndMissingValue'][:] + assert_mask_matches(vardata, [False, False, False]) + assert_equal(vardata, [1, 2, 3]) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/test_paths.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/test_paths.py new file mode 100644 index 0000000000000000000000000000000000000000..1e7c4167ace335fb5fc86f6499ee54c3360ded6e --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/test_paths.py @@ -0,0 +1,93 @@ +""" +Ensure that we can use pathlib.Path objects in all relevant IO functions. +""" +from pathlib import Path + +import numpy as np + +import scipy.io +import scipy.io.wavfile +from scipy._lib._tmpdirs import tempdir +import scipy.sparse + + +class TestPaths: + data = np.arange(5).astype(np.int64) + + def test_savemat(self): + with tempdir() as temp_dir: + path = Path(temp_dir) / 'data.mat' + scipy.io.savemat(path, {'data': self.data}) + assert path.is_file() + + def test_loadmat(self): + # Save data with string path, load with pathlib.Path + with tempdir() as temp_dir: + path = Path(temp_dir) / 'data.mat' + scipy.io.savemat(str(path), {'data': self.data}) + + mat_contents = scipy.io.loadmat(path) + assert (mat_contents['data'] == self.data).all() + + def test_whosmat(self): + # Save data with string path, load with pathlib.Path + with tempdir() as temp_dir: + path = Path(temp_dir) / 'data.mat' + scipy.io.savemat(str(path), {'data': self.data}) + + contents = scipy.io.whosmat(path) + assert contents[0] == ('data', (1, 5), 'int64') + + def test_readsav(self): + path = Path(__file__).parent / 'data/scalar_string.sav' + scipy.io.readsav(path) + + def test_hb_read(self): + # Save data with string path, load with pathlib.Path + with tempdir() as temp_dir: + data = scipy.sparse.eye_array(3, format='csr') + path = Path(temp_dir) / 'data.hb' + scipy.io.hb_write(str(path), data) + + data_new = scipy.io.hb_read(path, spmatrix=False) + assert (data_new != data).nnz == 0 + + def test_hb_write(self): + with tempdir() as temp_dir: + data = scipy.sparse.eye_array(3, format='csr') + path = Path(temp_dir) / 'data.hb' + scipy.io.hb_write(path, data) + assert path.is_file() + + def test_mmio_read(self): + # Save data with string path, load with pathlib.Path + with tempdir() as temp_dir: + data = scipy.sparse.eye_array(3, format='csr') + path = Path(temp_dir) / 'data.mtx' + scipy.io.mmwrite(str(path), data) + + data_new = scipy.io.mmread(path, spmatrix=False) + assert (data_new != data).nnz == 0 + + def test_mmio_write(self): + with tempdir() as temp_dir: + data = scipy.sparse.eye_array(3, format='csr') + path = Path(temp_dir) / 'data.mtx' + scipy.io.mmwrite(path, data) + + def test_netcdf_file(self): + path = Path(__file__).parent / 'data/example_1.nc' + scipy.io.netcdf_file(path) + + def test_wavfile_read(self): + path = Path(__file__).parent / 'data/test-8000Hz-le-2ch-1byteu.wav' + scipy.io.wavfile.read(path) + + def test_wavfile_write(self): + # Read from str path, write to Path + input_path = Path(__file__).parent / 'data/test-8000Hz-le-2ch-1byteu.wav' + rate, data = scipy.io.wavfile.read(str(input_path)) + + with tempdir() as temp_dir: + output_path = Path(temp_dir) / input_path.name + scipy.io.wavfile.write(output_path, rate, data) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/test_wavfile.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/test_wavfile.py new file mode 100644 index 0000000000000000000000000000000000000000..8a1d959a5faf87994858e6466479f3b32707b23f --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/io/tests/test_wavfile.py @@ -0,0 +1,520 @@ +import os +import sys +from io import (BytesIO, UnsupportedOperation) +import threading +import warnings + +import numpy as np +from numpy.testing import (assert_equal, assert_, assert_array_equal, + break_cycles, IS_PYPY) +import pytest +from pytest import raises, warns + +from scipy.io import wavfile + + +def datafile(fn): + return os.path.join(os.path.dirname(__file__), 'data', fn) + + +def test_read_1(): + # 32-bit PCM (which uses extensible format) + for mmap in [False, True]: + filename = 'test-44100Hz-le-1ch-4bytes.wav' + rate, data = wavfile.read(datafile(filename), mmap=mmap) + + assert_equal(rate, 44100) + assert_(np.issubdtype(data.dtype, np.int32)) + assert_equal(data.shape, (4410,)) + + del data + + +def test_read_2(): + # 8-bit unsigned PCM + for mmap in [False, True]: + filename = 'test-8000Hz-le-2ch-1byteu.wav' + rate, data = wavfile.read(datafile(filename), mmap=mmap) + + assert_equal(rate, 8000) + assert_(np.issubdtype(data.dtype, np.uint8)) + assert_equal(data.shape, (800, 2)) + + del data + + +def test_read_3(): + # Little-endian float + for mmap in [False, True]: + filename = 'test-44100Hz-2ch-32bit-float-le.wav' + rate, data = wavfile.read(datafile(filename), mmap=mmap) + + assert_equal(rate, 44100) + assert_(np.issubdtype(data.dtype, np.float32)) + assert_equal(data.shape, (441, 2)) + + del data + + +def test_read_4(): + # Contains unsupported 'PEAK' chunk + for mmap in [False, True]: + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "Chunk .non-data. not understood, skipping it", + wavfile.WavFileWarning + ) + filename = 'test-48000Hz-2ch-64bit-float-le-wavex.wav' + rate, data = wavfile.read(datafile(filename), mmap=mmap) + + assert_equal(rate, 48000) + assert_(np.issubdtype(data.dtype, np.float64)) + assert_equal(data.shape, (480, 2)) + + del data + + +def test_read_5(): + # Big-endian float + for mmap in [False, True]: + filename = 'test-44100Hz-2ch-32bit-float-be.wav' + rate, data = wavfile.read(datafile(filename), mmap=mmap) + + assert_equal(rate, 44100) + assert_(np.issubdtype(data.dtype, np.float32)) + assert_(data.dtype.byteorder == '>' or (sys.byteorder == 'big' and + data.dtype.byteorder == '=')) + assert_equal(data.shape, (441, 2)) + + del data + + +def test_5_bit_odd_size_no_pad(): + # 5-bit, 1 B container, 5 channels, 9 samples, 45 B data chunk + # Generated by LTspice, which incorrectly omits pad byte, but should be + # readable anyway + for mmap in [False, True]: + filename = 'test-8000Hz-le-5ch-9S-5bit.wav' + rate, data = wavfile.read(datafile(filename), mmap=mmap) + + assert_equal(rate, 8000) + assert_(np.issubdtype(data.dtype, np.uint8)) + assert_equal(data.shape, (9, 5)) + + # 8-5 = 3 LSBits should be 0 + assert_equal(data & 0b00000111, 0) + + # Unsigned + assert_equal(data.max(), 0b11111000) # Highest possible + assert_equal(data[0, 0], 128) # Midpoint is 128 for <= 8-bit + assert_equal(data.min(), 0) # Lowest possible + + del data + + +def test_12_bit_even_size(): + # 12-bit, 2 B container, 4 channels, 9 samples, 72 B data chunk + # Generated by LTspice from 1 Vpk sine waves + for mmap in [False, True]: + filename = 'test-8000Hz-le-4ch-9S-12bit.wav' + rate, data = wavfile.read(datafile(filename), mmap=mmap) + + assert_equal(rate, 8000) + assert_(np.issubdtype(data.dtype, np.int16)) + assert_equal(data.shape, (9, 4)) + + # 16-12 = 4 LSBits should be 0 + assert_equal(data & 0b00000000_00001111, 0) + + # Signed + assert_equal(data.max(), 0b01111111_11110000) # Highest possible + assert_equal(data[0, 0], 0) # Midpoint is 0 for >= 9-bit + assert_equal(data.min(), -0b10000000_00000000) # Lowest possible + + del data + + +def test_24_bit_odd_size_with_pad(): + # 24-bit, 3 B container, 3 channels, 5 samples, 45 B data chunk + # Should not raise any warnings about the data chunk pad byte + filename = 'test-8000Hz-le-3ch-5S-24bit.wav' + rate, data = wavfile.read(datafile(filename), mmap=False) + + assert_equal(rate, 8000) + assert_(np.issubdtype(data.dtype, np.int32)) + assert_equal(data.shape, (5, 3)) + + # All LSBytes should be 0 + assert_equal(data & 0xff, 0) + + # Hand-made max/min samples under different conventions: + # 2**(N-1) 2**(N-1)-1 LSB + assert_equal(data, [[-0x8000_0000, -0x7fff_ff00, -0x200], + [-0x4000_0000, -0x3fff_ff00, -0x100], + [+0x0000_0000, +0x0000_0000, +0x000], + [+0x4000_0000, +0x3fff_ff00, +0x100], + [+0x7fff_ff00, +0x7fff_ff00, +0x200]]) + # ^ clipped + + +def test_20_bit_extra_data(): + # 20-bit, 3 B container, 1 channel, 10 samples, 30 B data chunk + # with extra data filling container beyond the bit depth + filename = 'test-1234Hz-le-1ch-10S-20bit-extra.wav' + rate, data = wavfile.read(datafile(filename), mmap=False) + + assert_equal(rate, 1234) + assert_(np.issubdtype(data.dtype, np.int32)) + assert_equal(data.shape, (10,)) + + # All LSBytes should still be 0, because 3 B container in 4 B dtype + assert_equal(data & 0xff, 0) + + # But it should load the data beyond 20 bits + assert_((data & 0xf00).any()) + + # Full-scale positive/negative samples, then being halved each time + assert_equal(data, [+0x7ffff000, # +full-scale 20-bit + -0x7ffff000, # -full-scale 20-bit + +0x7ffff000 >> 1, # +1/2 + -0x7ffff000 >> 1, # -1/2 + +0x7ffff000 >> 2, # +1/4 + -0x7ffff000 >> 2, # -1/4 + +0x7ffff000 >> 3, # +1/8 + -0x7ffff000 >> 3, # -1/8 + +0x7ffff000 >> 4, # +1/16 + -0x7ffff000 >> 4, # -1/16 + ]) + + +def test_36_bit_odd_size(): + # 36-bit, 5 B container, 3 channels, 5 samples, 75 B data chunk + pad + filename = 'test-8000Hz-le-3ch-5S-36bit.wav' + rate, data = wavfile.read(datafile(filename), mmap=False) + + assert_equal(rate, 8000) + assert_(np.issubdtype(data.dtype, np.int64)) + assert_equal(data.shape, (5, 3)) + + # 28 LSBits should be 0 + assert_equal(data & 0xfffffff, 0) + + # Hand-made max/min samples under different conventions: + # Fixed-point 2**(N-1) Full-scale 2**(N-1)-1 LSB + correct = [[-0x8000_0000_0000_0000, -0x7fff_ffff_f000_0000, -0x2000_0000], + [-0x4000_0000_0000_0000, -0x3fff_ffff_f000_0000, -0x1000_0000], + [+0x0000_0000_0000_0000, +0x0000_0000_0000_0000, +0x0000_0000], + [+0x4000_0000_0000_0000, +0x3fff_ffff_f000_0000, +0x1000_0000], + [+0x7fff_ffff_f000_0000, +0x7fff_ffff_f000_0000, +0x2000_0000]] + # ^ clipped + + assert_equal(data, correct) + + +def test_45_bit_even_size(): + # 45-bit, 6 B container, 3 channels, 5 samples, 90 B data chunk + filename = 'test-8000Hz-le-3ch-5S-45bit.wav' + rate, data = wavfile.read(datafile(filename), mmap=False) + + assert_equal(rate, 8000) + assert_(np.issubdtype(data.dtype, np.int64)) + assert_equal(data.shape, (5, 3)) + + # 19 LSBits should be 0 + assert_equal(data & 0x7ffff, 0) + + # Hand-made max/min samples under different conventions: + # Fixed-point 2**(N-1) Full-scale 2**(N-1)-1 LSB + correct = [[-0x8000_0000_0000_0000, -0x7fff_ffff_fff8_0000, -0x10_0000], + [-0x4000_0000_0000_0000, -0x3fff_ffff_fff8_0000, -0x08_0000], + [+0x0000_0000_0000_0000, +0x0000_0000_0000_0000, +0x00_0000], + [+0x4000_0000_0000_0000, +0x3fff_ffff_fff8_0000, +0x08_0000], + [+0x7fff_ffff_fff8_0000, +0x7fff_ffff_fff8_0000, +0x10_0000]] + # ^ clipped + + assert_equal(data, correct) + + +def test_53_bit_odd_size(): + # 53-bit, 7 B container, 3 channels, 5 samples, 105 B data chunk + pad + filename = 'test-8000Hz-le-3ch-5S-53bit.wav' + rate, data = wavfile.read(datafile(filename), mmap=False) + + assert_equal(rate, 8000) + assert_(np.issubdtype(data.dtype, np.int64)) + assert_equal(data.shape, (5, 3)) + + # 11 LSBits should be 0 + assert_equal(data & 0x7ff, 0) + + # Hand-made max/min samples under different conventions: + # Fixed-point 2**(N-1) Full-scale 2**(N-1)-1 LSB + correct = [[-0x8000_0000_0000_0000, -0x7fff_ffff_ffff_f800, -0x1000], + [-0x4000_0000_0000_0000, -0x3fff_ffff_ffff_f800, -0x0800], + [+0x0000_0000_0000_0000, +0x0000_0000_0000_0000, +0x0000], + [+0x4000_0000_0000_0000, +0x3fff_ffff_ffff_f800, +0x0800], + [+0x7fff_ffff_ffff_f800, +0x7fff_ffff_ffff_f800, +0x1000]] + # ^ clipped + + assert_equal(data, correct) + + +def test_64_bit_even_size(): + # 64-bit, 8 B container, 3 channels, 5 samples, 120 B data chunk + for mmap in [False, True]: + filename = 'test-8000Hz-le-3ch-5S-64bit.wav' + rate, data = wavfile.read(datafile(filename), mmap=mmap) + + assert_equal(rate, 8000) + assert_(np.issubdtype(data.dtype, np.int64)) + assert_equal(data.shape, (5, 3)) + + # Hand-made max/min samples under different conventions: + # Fixed-point 2**(N-1) Full-scale 2**(N-1)-1 LSB + correct = [[-0x8000_0000_0000_0000, -0x7fff_ffff_ffff_ffff, -0x2], + [-0x4000_0000_0000_0000, -0x3fff_ffff_ffff_ffff, -0x1], + [+0x0000_0000_0000_0000, +0x0000_0000_0000_0000, +0x0], + [+0x4000_0000_0000_0000, +0x3fff_ffff_ffff_ffff, +0x1], + [+0x7fff_ffff_ffff_ffff, +0x7fff_ffff_ffff_ffff, +0x2]] + # ^ clipped + + assert_equal(data, correct) + + del data + + +def test_unsupported_mmap(): + # Test containers that cannot be mapped to numpy types + for filename in {'test-8000Hz-le-3ch-5S-24bit.wav', + 'test-8000Hz-le-3ch-5S-36bit.wav', + 'test-8000Hz-le-3ch-5S-45bit.wav', + 'test-8000Hz-le-3ch-5S-53bit.wav', + 'test-1234Hz-le-1ch-10S-20bit-extra.wav'}: + with raises(ValueError, match="mmap.*not compatible"): + rate, data = wavfile.read(datafile(filename), mmap=True) + + +def test_rifx(): + # Compare equivalent RIFX and RIFF files + for rifx, riff in {('test-44100Hz-be-1ch-4bytes.wav', + 'test-44100Hz-le-1ch-4bytes.wav'), + ('test-8000Hz-be-3ch-5S-24bit.wav', + 'test-8000Hz-le-3ch-5S-24bit.wav')}: + rate1, data1 = wavfile.read(datafile(rifx), mmap=False) + rate2, data2 = wavfile.read(datafile(riff), mmap=False) + assert_equal(rate1, rate2) + assert_equal(data1, data2) + + +def test_rf64(): + # Compare equivalent RF64 and RIFF files + for rf64, riff in {('test-44100Hz-le-1ch-4bytes-rf64.wav', + 'test-44100Hz-le-1ch-4bytes.wav'), + ('test-8000Hz-le-3ch-5S-24bit-rf64.wav', + 'test-8000Hz-le-3ch-5S-24bit.wav')}: + rate1, data1 = wavfile.read(datafile(rf64), mmap=False) + rate2, data2 = wavfile.read(datafile(riff), mmap=False) + assert_array_equal(rate1, rate2) + assert_array_equal(data1, data2) + + +@pytest.mark.xslow +def test_write_roundtrip_rf64(tmpdir): + dtype = np.dtype(" 0 + assert rate == 44100 + # also test writing (gh-12176) + data[0] = 0 + + +def test_read_early_eof(): + # File ends after 'fact' chunk at boundary, no data read + for mmap in [False, True]: + filename = 'test-44100Hz-le-1ch-4bytes-early-eof-no-data.wav' + with open(datafile(filename), 'rb') as fp: + with raises(ValueError, match="Unexpected end of file."): + wavfile.read(fp, mmap=mmap) + + +def test_read_incomplete_chunk(): + # File ends inside 'fmt ' chunk ID, no data read + for mmap in [False, True]: + filename = 'test-44100Hz-le-1ch-4bytes-incomplete-chunk.wav' + with open(datafile(filename), 'rb') as fp: + with raises(ValueError, match="Incomplete chunk ID.*b'f'"): + wavfile.read(fp, mmap=mmap) + + +def test_read_inconsistent_header(): + # File header's size fields contradict each other + for mmap in [False, True]: + filename = 'test-8000Hz-le-3ch-5S-24bit-inconsistent.wav' + with open(datafile(filename), 'rb') as fp: + with raises(ValueError, match="header is invalid"): + wavfile.read(fp, mmap=mmap) + + +# signed 8-bit integer PCM is not allowed +# unsigned > 8-bit integer PCM is not allowed +# 8- or 16-bit float PCM is not expected +# g and q are platform-dependent, so not included +@pytest.mark.parametrize("dt_str", ["i2", ">i4", ">i8", ">f4", ">f8", '|u1']) +@pytest.mark.parametrize("channels", [1, 2, 5]) +@pytest.mark.parametrize("rate", [8000, 32000]) +@pytest.mark.parametrize("mmap", [False, True]) +@pytest.mark.parametrize("realfile", [False, True]) +def test_write_roundtrip(realfile, mmap, rate, channels, dt_str, tmpdir): + dtype = np.dtype(dt_str) + if realfile: + tmpfile = str(tmpdir.join(str(threading.get_native_id()), 'temp.wav')) + os.makedirs(os.path.dirname(tmpfile), exist_ok=True) + else: + tmpfile = BytesIO() + data = np.random.rand(100, channels) + if channels == 1: + data = data[:, 0] + if dtype.kind == 'f': + # The range of the float type should be in [-1, 1] + data = data.astype(dtype) + else: + data = (data*128).astype(dtype) + + wavfile.write(tmpfile, rate, data) + + rate2, data2 = wavfile.read(tmpfile, mmap=mmap) + + assert_equal(rate, rate2) + assert_(data2.dtype.byteorder in ('<', '=', '|'), msg=data2.dtype) + assert_array_equal(data, data2) + # also test writing (gh-12176) + if realfile: + data2[0] = 0 + else: + with pytest.raises(ValueError, match='read-only'): + data2[0] = 0 + + if realfile and mmap and IS_PYPY and sys.platform == 'win32': + # windows cannot remove a dead file held by a mmap but not collected + # in PyPy; since the filename gets reused in this test, clean this up + break_cycles() + break_cycles() + + +@pytest.mark.parametrize("dtype", [np.float16]) +def test_wavfile_dtype_unsupported(tmpdir, dtype): + tmpfile = str(tmpdir.join('temp.wav')) + rng = np.random.default_rng(1234) + data = rng.random((100, 5)).astype(dtype) + rate = 8000 + with pytest.raises(ValueError, match="Unsupported"): + wavfile.write(tmpfile, rate, data) + +def test_seek_emulating_reader_invalid_seek(): + # Dummy data for the reader + reader = wavfile.SeekEmulatingReader(BytesIO(b'\x00\x00')) + + # Test SEEK_END with an invalid whence value + with pytest.raises(UnsupportedOperation): + reader.seek(0, 5) # Invalid whence value + + # Test with negative seek value + with pytest.raises(UnsupportedOperation): + reader.seek(-1, 0) # Negative position with SEEK_SET + + # Test SEEK_END with valid parameters (should not raise) + pos = reader.seek(0, os.SEEK_END) # Valid usage + assert pos == 2, f"Failed to seek to end, got position {pos}" diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/misc/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/misc/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f39aa55c38e6812d9632f8bad6697f5a3baa2d04 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/misc/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/misc/__pycache__/common.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/misc/__pycache__/common.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07405339f641cc80c85f33237632c6df1e698e13 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/misc/__pycache__/common.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/misc/__pycache__/doccer.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/misc/__pycache__/doccer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..773c1ef3a353e4f9b7697a416e4104cfbfe0d663 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/misc/__pycache__/doccer.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/__pycache__/_filters.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/__pycache__/_filters.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5aec1ab41480e368f4511261be1842d1c63d015b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/__pycache__/_filters.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/__pycache__/interpolation.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/__pycache__/interpolation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4d00ac11e97bced18a512ea80fc17a870a4eb6d5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/__pycache__/interpolation.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/__pycache__/morphology.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/__pycache__/morphology.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd0c91ee6203c2601079a77e85b6f465cdcb75a8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/__pycache__/morphology.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ad214005051010389bec70f86adf3c04c28d670a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_c_api.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_c_api.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c0da8eb13e03cadd8e8e2da220e79a8285e07bd2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_c_api.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_datatypes.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_datatypes.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..71c1a71977cd3eeaf5c03cd548a8eaacc6f8678b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_datatypes.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_fourier.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_fourier.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2078b50c5ad7c1cf83c809b4adeff7613dcc1fdb Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_fourier.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_interpolation.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_interpolation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..99e293eeb0cc519614e49f4e7c4202f14a8d062e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_interpolation.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_measurements.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_measurements.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7d78a9f98a7ef2a0db7a78b82fcaf1e4edd1ea92 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_measurements.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_ni_support.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_ni_support.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..76c795a05ca7733dc09b6c162e751045d3838f0d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_ni_support.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_splines.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_splines.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e4bdede214b297e419654ac81fdd5dbaf2685348 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/__pycache__/test_splines.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/data/label_inputs.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/data/label_inputs.txt new file mode 100644 index 0000000000000000000000000000000000000000..6c3cff3b12cec4ad050b31cc5d5c327f32784447 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/data/label_inputs.txt @@ -0,0 +1,21 @@ +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 0 1 1 1 +1 1 0 0 0 1 1 +1 0 1 0 1 0 1 +0 0 0 1 0 0 0 +1 0 1 0 1 0 1 +1 1 0 0 0 1 1 +1 1 1 0 1 1 1 +1 0 1 1 1 0 1 +0 0 0 1 0 0 0 +1 0 0 1 0 0 1 +1 1 1 1 1 1 1 +1 0 0 1 0 0 1 +0 0 0 1 0 0 0 +1 0 1 1 1 0 1 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/data/label_results.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/data/label_results.txt new file mode 100644 index 0000000000000000000000000000000000000000..c239b0369c9df3e06df9a2fbf048faec2f84941f --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/data/label_results.txt @@ -0,0 +1,294 @@ +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +2 2 2 2 2 2 2 +3 3 3 3 3 3 3 +4 4 4 4 4 4 4 +5 5 5 5 5 5 5 +6 6 6 6 6 6 6 +7 7 7 7 7 7 7 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 2 3 4 5 6 7 +8 9 10 11 12 13 14 +15 16 17 18 19 20 21 +22 23 24 25 26 27 28 +29 30 31 32 33 34 35 +36 37 38 39 40 41 42 +43 44 45 46 47 48 49 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 2 3 4 5 6 7 +8 1 2 3 4 5 6 +9 8 1 2 3 4 5 +10 9 8 1 2 3 4 +11 10 9 8 1 2 3 +12 11 10 9 8 1 2 +13 12 11 10 9 8 1 +1 2 3 4 5 6 7 +1 2 3 4 5 6 7 +1 2 3 4 5 6 7 +1 2 3 4 5 6 7 +1 2 3 4 5 6 7 +1 2 3 4 5 6 7 +1 2 3 4 5 6 7 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 2 1 2 1 2 1 +2 1 2 1 2 1 2 +1 2 1 2 1 2 1 +2 1 2 1 2 1 2 +1 2 1 2 1 2 1 +2 1 2 1 2 1 2 +1 2 1 2 1 2 1 +1 2 3 4 5 6 7 +2 3 4 5 6 7 8 +3 4 5 6 7 8 9 +4 5 6 7 8 9 10 +5 6 7 8 9 10 11 +6 7 8 9 10 11 12 +7 8 9 10 11 12 13 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 1 1 1 1 +1 1 1 0 2 2 2 +1 1 0 0 0 2 2 +1 0 3 0 2 0 4 +0 0 0 2 0 0 0 +5 0 2 0 6 0 7 +2 2 0 0 0 7 7 +2 2 2 0 7 7 7 +1 1 1 0 2 2 2 +1 1 0 0 0 2 2 +3 0 1 0 4 0 2 +0 0 0 1 0 0 0 +5 0 6 0 1 0 7 +5 5 0 0 0 1 1 +5 5 5 0 1 1 1 +1 1 1 0 2 2 2 +3 3 0 0 0 4 4 +5 0 6 0 7 0 8 +0 0 0 9 0 0 0 +10 0 11 0 12 0 13 +14 14 0 0 0 15 15 +16 16 16 0 17 17 17 +1 1 1 0 2 3 3 +1 1 0 0 0 3 3 +1 0 4 0 3 0 3 +0 0 0 3 0 0 0 +3 0 3 0 5 0 6 +3 3 0 0 0 6 6 +3 3 7 0 6 6 6 +1 2 3 0 4 5 6 +7 8 0 0 0 9 10 +11 0 12 0 13 0 14 +0 0 0 15 0 0 0 +16 0 17 0 18 0 19 +20 21 0 0 0 22 23 +24 25 26 0 27 28 29 +1 1 1 0 2 2 2 +1 1 0 0 0 2 2 +1 0 3 0 2 0 2 +0 0 0 2 0 0 0 +2 0 2 0 4 0 5 +2 2 0 0 0 5 5 +2 2 2 0 5 5 5 +1 1 1 0 2 2 2 +1 1 0 0 0 2 2 +1 0 3 0 4 0 2 +0 0 0 5 0 0 0 +6 0 7 0 8 0 9 +6 6 0 0 0 9 9 +6 6 6 0 9 9 9 +1 2 3 0 4 5 6 +7 1 0 0 0 4 5 +8 0 1 0 9 0 4 +0 0 0 1 0 0 0 +10 0 11 0 1 0 12 +13 10 0 0 0 1 14 +15 13 10 0 16 17 1 +1 2 3 0 4 5 6 +1 2 0 0 0 5 6 +1 0 7 0 8 0 6 +0 0 0 9 0 0 0 +10 0 11 0 12 0 13 +10 14 0 0 0 15 13 +10 14 16 0 17 15 13 +1 1 1 0 1 1 1 +1 1 0 0 0 1 1 +1 0 1 0 1 0 1 +0 0 0 1 0 0 0 +1 0 1 0 1 0 1 +1 1 0 0 0 1 1 +1 1 1 0 1 1 1 +1 1 2 0 3 3 3 +1 1 0 0 0 3 3 +1 0 1 0 4 0 3 +0 0 0 1 0 0 0 +5 0 6 0 1 0 1 +5 5 0 0 0 1 1 +5 5 5 0 7 1 1 +1 2 1 0 1 3 1 +2 1 0 0 0 1 3 +1 0 1 0 1 0 1 +0 0 0 1 0 0 0 +1 0 1 0 1 0 1 +4 1 0 0 0 1 5 +1 4 1 0 1 5 1 +1 2 3 0 4 5 6 +2 3 0 0 0 6 7 +3 0 8 0 6 0 9 +0 0 0 6 0 0 0 +10 0 6 0 11 0 12 +13 6 0 0 0 12 14 +6 15 16 0 12 14 17 +1 1 1 0 2 2 2 +1 1 0 0 0 2 2 +1 0 1 0 3 0 2 +0 0 0 1 0 0 0 +4 0 5 0 1 0 1 +4 4 0 0 0 1 1 +4 4 4 0 1 1 1 +1 0 2 2 2 0 3 +0 0 0 2 0 0 0 +4 0 0 5 0 0 5 +5 5 5 5 5 5 5 +5 0 0 5 0 0 6 +0 0 0 7 0 0 0 +8 0 7 7 7 0 9 +1 0 2 2 2 0 3 +0 0 0 2 0 0 0 +4 0 0 4 0 0 5 +4 4 4 4 4 4 4 +6 0 0 4 0 0 4 +0 0 0 7 0 0 0 +8 0 7 7 7 0 9 +1 0 2 2 2 0 3 +0 0 0 4 0 0 0 +5 0 0 6 0 0 7 +8 8 8 8 8 8 8 +9 0 0 10 0 0 11 +0 0 0 12 0 0 0 +13 0 14 14 14 0 15 +1 0 2 3 3 0 4 +0 0 0 3 0 0 0 +5 0 0 3 0 0 6 +5 5 3 3 3 6 6 +5 0 0 3 0 0 6 +0 0 0 3 0 0 0 +7 0 3 3 8 0 9 +1 0 2 3 4 0 5 +0 0 0 6 0 0 0 +7 0 0 8 0 0 9 +10 11 12 13 14 15 16 +17 0 0 18 0 0 19 +0 0 0 20 0 0 0 +21 0 22 23 24 0 25 +1 0 2 2 2 0 3 +0 0 0 2 0 0 0 +2 0 0 2 0 0 2 +2 2 2 2 2 2 2 +2 0 0 2 0 0 2 +0 0 0 2 0 0 0 +4 0 2 2 2 0 5 +1 0 2 2 2 0 3 +0 0 0 2 0 0 0 +2 0 0 2 0 0 2 +2 2 2 2 2 2 2 +2 0 0 2 0 0 2 +0 0 0 2 0 0 0 +4 0 2 2 2 0 5 +1 0 2 3 4 0 5 +0 0 0 2 0 0 0 +6 0 0 7 0 0 8 +9 6 10 11 7 12 13 +14 0 0 10 0 0 12 +0 0 0 15 0 0 0 +16 0 17 18 15 0 19 +1 0 2 3 4 0 5 +0 0 0 3 0 0 0 +6 0 0 3 0 0 7 +6 8 9 3 10 11 7 +6 0 0 3 0 0 7 +0 0 0 3 0 0 0 +12 0 13 3 14 0 15 +1 0 2 2 2 0 3 +0 0 0 2 0 0 0 +2 0 0 2 0 0 2 +2 2 2 2 2 2 2 +2 0 0 2 0 0 2 +0 0 0 2 0 0 0 +4 0 2 2 2 0 5 +1 0 2 2 3 0 4 +0 0 0 2 0 0 0 +5 0 0 2 0 0 6 +5 5 2 2 2 6 6 +5 0 0 2 0 0 6 +0 0 0 2 0 0 0 +7 0 8 2 2 0 9 +1 0 2 3 2 0 4 +0 0 0 2 0 0 0 +5 0 0 6 0 0 7 +8 5 6 9 6 7 10 +5 0 0 6 0 0 7 +0 0 0 11 0 0 0 +12 0 11 13 11 0 14 +1 0 2 3 4 0 5 +0 0 0 4 0 0 0 +6 0 0 7 0 0 8 +9 10 7 11 12 8 13 +10 0 0 12 0 0 14 +0 0 0 15 0 0 0 +16 0 15 17 18 0 19 +1 0 2 2 2 0 3 +0 0 0 2 0 0 0 +2 0 0 2 0 0 2 +2 2 2 2 2 2 2 +2 0 0 2 0 0 2 +0 0 0 2 0 0 0 +4 0 2 2 2 0 5 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/data/label_strels.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/data/label_strels.txt new file mode 100644 index 0000000000000000000000000000000000000000..35ae8121364d4fb3292c11f2a72333f456fa9c0a --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/ndimage/tests/data/label_strels.txt @@ -0,0 +1,42 @@ +0 0 1 +1 1 1 +1 0 0 +1 0 0 +1 1 1 +0 0 1 +0 0 0 +1 1 1 +0 0 0 +0 1 1 +0 1 0 +1 1 0 +0 0 0 +0 0 0 +0 0 0 +0 1 1 +1 1 1 +1 1 0 +0 1 0 +1 1 1 +0 1 0 +1 0 0 +0 1 0 +0 0 1 +0 1 0 +0 1 0 +0 1 0 +1 1 1 +1 1 1 +1 1 1 +1 1 0 +0 1 0 +0 1 1 +1 0 1 +0 1 0 +1 0 1 +0 0 1 +0 1 0 +1 0 0 +1 1 0 +1 1 1 +0 1 1 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7cb23a51694fd7aebff17ff378044a286d627955 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/_add_newdocs.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/_add_newdocs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b0ab2cf3b799921cc4dfd652e561cec281d3f097 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/_add_newdocs.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/_models.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/_models.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a45c3ceca21bb58903306126512af62e00931f07 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/_models.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/_odrpack.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/_odrpack.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..64e6acb58646038e10bd6f95ab9db41ef620a7c8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/_odrpack.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/models.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/models.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b90e0f12d2b240bf12e80b2b426d8f27ab3a1f00 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/models.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/odrpack.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/odrpack.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cb3616ea39b689eee199614810fab0ccc31aea58 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/__pycache__/odrpack.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a2c8cd8f10e74b60a5b37fd63cca1d422f97a3b6 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/tests/__pycache__/test_odr.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/tests/__pycache__/test_odr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2679a54329a807cc69a591cdad6bd990e9a6a26d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/tests/__pycache__/test_odr.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/tests/test_odr.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/tests/test_odr.py new file mode 100644 index 0000000000000000000000000000000000000000..5d0545b018097237377878fd085960587082903a --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/odr/tests/test_odr.py @@ -0,0 +1,621 @@ +import pickle +import tempfile +import shutil +import os + +import numpy as np +from numpy import pi +from numpy.testing import (assert_array_almost_equal, + assert_equal, + assert_allclose) +import pytest +from pytest import raises as assert_raises + +from scipy.odr import (Data, Model, ODR, RealData, OdrStop, OdrWarning, + OdrError, multilinear, exponential, unilinear, + quadratic, polynomial) + + +class TestODR: + + # Bad Data for 'x' + + def test_bad_data(self): + assert_raises(ValueError, Data, 2, 1) + assert_raises(ValueError, RealData, 2, 1) + + # Empty Data for 'x' + def empty_data_func(self, B, x): + return B[0]*x + B[1] + + def test_empty_data(self): + beta0 = [0.02, 0.0] + linear = Model(self.empty_data_func) + + empty_dat = Data([], []) + with pytest.warns(OdrWarning): + ODR(empty_dat, linear, beta0=beta0) + + empty_dat = RealData([], []) + with pytest.warns(OdrWarning): + ODR(empty_dat, linear, beta0=beta0) + + # Explicit Example + + def explicit_fcn(self, B, x): + ret = B[0] + B[1] * np.power(np.exp(B[2]*x) - 1.0, 2) + return ret + + def explicit_fjd(self, B, x): + eBx = np.exp(B[2]*x) + ret = B[1] * 2.0 * (eBx-1.0) * B[2] * eBx + return ret + + def explicit_fjb(self, B, x): + eBx = np.exp(B[2]*x) + res = np.vstack([np.ones(x.shape[-1]), + np.power(eBx-1.0, 2), + B[1]*2.0*(eBx-1.0)*eBx*x]) + return res + + def test_explicit(self): + explicit_mod = Model( + self.explicit_fcn, + fjacb=self.explicit_fjb, + fjacd=self.explicit_fjd, + meta=dict(name='Sample Explicit Model', + ref='ODRPACK UG, pg. 39'), + ) + explicit_dat = Data([0.,0.,5.,7.,7.5,10.,16.,26.,30.,34.,34.5,100.], + [1265.,1263.6,1258.,1254.,1253.,1249.8,1237.,1218.,1220.6, + 1213.8,1215.5,1212.]) + explicit_odr = ODR(explicit_dat, explicit_mod, beta0=[1500.0, -50.0, -0.1], + ifixx=[0,0,1,1,1,1,1,1,1,1,1,0]) + explicit_odr.set_job(deriv=2) + explicit_odr.set_iprint(init=0, iter=0, final=0) + + out = explicit_odr.run() + assert_array_almost_equal( + out.beta, + np.array([1.2646548050648876e+03, -5.4018409956678255e+01, + -8.7849712165253724e-02]), + ) + assert_array_almost_equal( + out.sd_beta, + np.array([1.0349270280543437, 1.583997785262061, 0.0063321988657267]), + ) + assert_array_almost_equal( + out.cov_beta, + np.array([[4.4949592379003039e-01, -3.7421976890364739e-01, + -8.0978217468468912e-04], + [-3.7421976890364739e-01, 1.0529686462751804e+00, + -1.9453521827942002e-03], + [-8.0978217468468912e-04, -1.9453521827942002e-03, + 1.6827336938454476e-05]]), + ) + + # Implicit Example + + def implicit_fcn(self, B, x): + return (B[2]*np.power(x[0]-B[0], 2) + + 2.0*B[3]*(x[0]-B[0])*(x[1]-B[1]) + + B[4]*np.power(x[1]-B[1], 2) - 1.0) + + def test_implicit(self): + implicit_mod = Model( + self.implicit_fcn, + implicit=1, + meta=dict(name='Sample Implicit Model', + ref='ODRPACK UG, pg. 49'), + ) + implicit_dat = Data([ + [0.5,1.2,1.6,1.86,2.12,2.36,2.44,2.36,2.06,1.74,1.34,0.9,-0.28, + -0.78,-1.36,-1.9,-2.5,-2.88,-3.18,-3.44], + [-0.12,-0.6,-1.,-1.4,-2.54,-3.36,-4.,-4.75,-5.25,-5.64,-5.97,-6.32, + -6.44,-6.44,-6.41,-6.25,-5.88,-5.5,-5.24,-4.86]], + 1, + ) + implicit_odr = ODR(implicit_dat, implicit_mod, + beta0=[-1.0, -3.0, 0.09, 0.02, 0.08]) + + out = implicit_odr.run() + assert_array_almost_equal( + out.beta, + np.array([-0.9993809167281279, -2.9310484652026476, 0.0875730502693354, + 0.0162299708984738, 0.0797537982976416]), + ) + assert_array_almost_equal( + out.sd_beta, + np.array([0.1113840353364371, 0.1097673310686467, 0.0041060738314314, + 0.0027500347539902, 0.0034962501532468]), + ) + assert_allclose( + out.cov_beta, + np.array([[2.1089274602333052e+00, -1.9437686411979040e+00, + 7.0263550868344446e-02, -4.7175267373474862e-02, + 5.2515575927380355e-02], + [-1.9437686411979040e+00, 2.0481509222414456e+00, + -6.1600515853057307e-02, 4.6268827806232933e-02, + -5.8822307501391467e-02], + [7.0263550868344446e-02, -6.1600515853057307e-02, + 2.8659542561579308e-03, -1.4628662260014491e-03, + 1.4528860663055824e-03], + [-4.7175267373474862e-02, 4.6268827806232933e-02, + -1.4628662260014491e-03, 1.2855592885514335e-03, + -1.2692942951415293e-03], + [5.2515575927380355e-02, -5.8822307501391467e-02, + 1.4528860663055824e-03, -1.2692942951415293e-03, + 2.0778813389755596e-03]]), + rtol=1e-6, atol=2e-6, + ) + + # Multi-variable Example + + def multi_fcn(self, B, x): + if (x < 0.0).any(): + raise OdrStop + theta = pi*B[3]/2. + ctheta = np.cos(theta) + stheta = np.sin(theta) + omega = np.power(2.*pi*x*np.exp(-B[2]), B[3]) + phi = np.arctan2((omega*stheta), (1.0 + omega*ctheta)) + r = (B[0] - B[1]) * np.power(np.sqrt(np.power(1.0 + omega*ctheta, 2) + + np.power(omega*stheta, 2)), -B[4]) + ret = np.vstack([B[1] + r*np.cos(B[4]*phi), + r*np.sin(B[4]*phi)]) + return ret + + def test_multi(self): + multi_mod = Model( + self.multi_fcn, + meta=dict(name='Sample Multi-Response Model', + ref='ODRPACK UG, pg. 56'), + ) + + multi_x = np.array([30.0, 50.0, 70.0, 100.0, 150.0, 200.0, 300.0, 500.0, + 700.0, 1000.0, 1500.0, 2000.0, 3000.0, 5000.0, 7000.0, 10000.0, + 15000.0, 20000.0, 30000.0, 50000.0, 70000.0, 100000.0, 150000.0]) + multi_y = np.array([ + [4.22, 4.167, 4.132, 4.038, 4.019, 3.956, 3.884, 3.784, 3.713, + 3.633, 3.54, 3.433, 3.358, 3.258, 3.193, 3.128, 3.059, 2.984, + 2.934, 2.876, 2.838, 2.798, 2.759], + [0.136, 0.167, 0.188, 0.212, 0.236, 0.257, 0.276, 0.297, 0.309, + 0.311, 0.314, 0.311, 0.305, 0.289, 0.277, 0.255, 0.24, 0.218, + 0.202, 0.182, 0.168, 0.153, 0.139], + ]) + n = len(multi_x) + multi_we = np.zeros((2, 2, n), dtype=float) + multi_ifixx = np.ones(n, dtype=int) + multi_delta = np.zeros(n, dtype=float) + + multi_we[0,0,:] = 559.6 + multi_we[1,0,:] = multi_we[0,1,:] = -1634.0 + multi_we[1,1,:] = 8397.0 + + for i in range(n): + if multi_x[i] < 100.0: + multi_ifixx[i] = 0 + elif multi_x[i] <= 150.0: + pass # defaults are fine + elif multi_x[i] <= 1000.0: + multi_delta[i] = 25.0 + elif multi_x[i] <= 10000.0: + multi_delta[i] = 560.0 + elif multi_x[i] <= 100000.0: + multi_delta[i] = 9500.0 + else: + multi_delta[i] = 144000.0 + if multi_x[i] == 100.0 or multi_x[i] == 150.0: + multi_we[:,:,i] = 0.0 + + multi_dat = Data(multi_x, multi_y, wd=1e-4/np.power(multi_x, 2), + we=multi_we) + multi_odr = ODR(multi_dat, multi_mod, beta0=[4.,2.,7.,.4,.5], + delta0=multi_delta, ifixx=multi_ifixx) + multi_odr.set_job(deriv=1, del_init=1) + + out = multi_odr.run() + assert_array_almost_equal( + out.beta, + np.array([4.3799880305938963, 2.4333057577497703, 8.0028845899503978, + 0.5101147161764654, 0.5173902330489161]), + ) + assert_array_almost_equal( + out.sd_beta, + np.array([0.0130625231081944, 0.0130499785273277, 0.1167085962217757, + 0.0132642749596149, 0.0288529201353984]), + ) + assert_array_almost_equal( + out.cov_beta, + np.array([[0.0064918418231375, 0.0036159705923791, 0.0438637051470406, + -0.0058700836512467, 0.011281212888768], + [0.0036159705923791, 0.0064793789429006, 0.0517610978353126, + -0.0051181304940204, 0.0130726943624117], + [0.0438637051470406, 0.0517610978353126, 0.5182263323095322, + -0.0563083340093696, 0.1269490939468611], + [-0.0058700836512467, -0.0051181304940204, -0.0563083340093696, + 0.0066939246261263, -0.0140184391377962], + [0.011281212888768, 0.0130726943624117, 0.1269490939468611, + -0.0140184391377962, 0.0316733013820852]]), + ) + + # Pearson's Data + # K. Pearson, Philosophical Magazine, 2, 559 (1901) + + def pearson_fcn(self, B, x): + return B[0] + B[1]*x + + def test_pearson(self): + p_x = np.array([0.,.9,1.8,2.6,3.3,4.4,5.2,6.1,6.5,7.4]) + p_y = np.array([5.9,5.4,4.4,4.6,3.5,3.7,2.8,2.8,2.4,1.5]) + p_sx = np.array([.03,.03,.04,.035,.07,.11,.13,.22,.74,1.]) + p_sy = np.array([1.,.74,.5,.35,.22,.22,.12,.12,.1,.04]) + + p_dat = RealData(p_x, p_y, sx=p_sx, sy=p_sy) + + # Reverse the data to test invariance of results + pr_dat = RealData(p_y, p_x, sx=p_sy, sy=p_sx) + + p_mod = Model(self.pearson_fcn, meta=dict(name='Uni-linear Fit')) + + p_odr = ODR(p_dat, p_mod, beta0=[1.,1.]) + pr_odr = ODR(pr_dat, p_mod, beta0=[1.,1.]) + + out = p_odr.run() + assert_array_almost_equal( + out.beta, + np.array([5.4767400299231674, -0.4796082367610305]), + ) + assert_array_almost_equal( + out.sd_beta, + np.array([0.3590121690702467, 0.0706291186037444]), + ) + assert_array_almost_equal( + out.cov_beta, + np.array([[0.0854275622946333, -0.0161807025443155], + [-0.0161807025443155, 0.003306337993922]]), + ) + + rout = pr_odr.run() + assert_array_almost_equal( + rout.beta, + np.array([11.4192022410781231, -2.0850374506165474]), + ) + assert_array_almost_equal( + rout.sd_beta, + np.array([0.9820231665657161, 0.3070515616198911]), + ) + assert_array_almost_equal( + rout.cov_beta, + np.array([[0.6391799462548782, -0.1955657291119177], + [-0.1955657291119177, 0.0624888159223392]]), + ) + + # Lorentz Peak + # The data is taken from one of the undergraduate physics labs I performed. + + def lorentz(self, beta, x): + return (beta[0]*beta[1]*beta[2] / np.sqrt(np.power(x*x - + beta[2]*beta[2], 2.0) + np.power(beta[1]*x, 2.0))) + + def test_lorentz(self): + l_sy = np.array([.29]*18) + l_sx = np.array([.000972971,.000948268,.000707632,.000706679, + .000706074, .000703918,.000698955,.000456856, + .000455207,.000662717,.000654619,.000652694, + .000000859202,.00106589,.00106378,.00125483, .00140818,.00241839]) + + l_dat = RealData( + [3.9094, 3.85945, 3.84976, 3.84716, 3.84551, 3.83964, 3.82608, + 3.78847, 3.78163, 3.72558, 3.70274, 3.6973, 3.67373, 3.65982, + 3.6562, 3.62498, 3.55525, 3.41886], + [652, 910.5, 984, 1000, 1007.5, 1053, 1160.5, 1409.5, 1430, 1122, + 957.5, 920, 777.5, 709.5, 698, 578.5, 418.5, 275.5], + sx=l_sx, + sy=l_sy, + ) + l_mod = Model(self.lorentz, meta=dict(name='Lorentz Peak')) + l_odr = ODR(l_dat, l_mod, beta0=(1000., .1, 3.8)) + + out = l_odr.run() + assert_array_almost_equal( + out.beta, + np.array([1.4306780846149925e+03, 1.3390509034538309e-01, + 3.7798193600109009e+00]), + ) + assert_array_almost_equal( + out.sd_beta, + np.array([7.3621186811330963e-01, 3.5068899941471650e-04, + 2.4451209281408992e-04]), + ) + assert_array_almost_equal( + out.cov_beta, + np.array([[2.4714409064597873e-01, -6.9067261911110836e-05, + -3.1236953270424990e-05], + [-6.9067261911110836e-05, 5.6077531517333009e-08, + 3.6133261832722601e-08], + [-3.1236953270424990e-05, 3.6133261832722601e-08, + 2.7261220025171730e-08]]), + ) + + def test_ticket_1253(self): + def linear(c, x): + return c[0]*x+c[1] + + c = [2.0, 3.0] + x = np.linspace(0, 10) + y = linear(c, x) + + model = Model(linear) + data = Data(x, y, wd=1.0, we=1.0) + job = ODR(data, model, beta0=[1.0, 1.0]) + result = job.run() + assert_equal(result.info, 2) + + # Verify fix for gh-9140 + + def test_ifixx(self): + x1 = [-2.01, -0.99, -0.001, 1.02, 1.98] + x2 = [3.98, 1.01, 0.001, 0.998, 4.01] + fix = np.vstack((np.zeros_like(x1, dtype=int), np.ones_like(x2, dtype=int))) + data = Data(np.vstack((x1, x2)), y=1, fix=fix) + model = Model(lambda beta, x: x[1, :] - beta[0] * x[0, :]**2., implicit=True) + + odr1 = ODR(data, model, beta0=np.array([1.])) + sol1 = odr1.run() + odr2 = ODR(data, model, beta0=np.array([1.]), ifixx=fix) + sol2 = odr2.run() + assert_equal(sol1.beta, sol2.beta) + + # verify bugfix for #11800 in #11802 + def test_ticket_11800(self): + # parameters + beta_true = np.array([1.0, 2.3, 1.1, -1.0, 1.3, 0.5]) + nr_measurements = 10 + + std_dev_x = 0.01 + x_error = np.array([[0.00063445, 0.00515731, 0.00162719, 0.01022866, + -0.01624845, 0.00482652, 0.00275988, -0.00714734, -0.00929201, -0.00687301], + [-0.00831623, -0.00821211, -0.00203459, 0.00938266, -0.00701829, + 0.0032169, 0.00259194, -0.00581017, -0.0030283, 0.01014164]]) + + std_dev_y = 0.05 + y_error = np.array([[0.05275304, 0.04519563, -0.07524086, 0.03575642, + 0.04745194, 0.03806645, 0.07061601, -0.00753604, -0.02592543, -0.02394929], + [0.03632366, 0.06642266, 0.08373122, 0.03988822, -0.0092536, + -0.03750469, -0.03198903, 0.01642066, 0.01293648, -0.05627085]]) + + beta_solution = np.array([ + 2.62920235756665876536e+00, -1.26608484996299608838e+02, + 1.29703572775403074502e+02, -1.88560985401185465804e+00, + 7.83834160771274923718e+01, -7.64124076838087091801e+01]) + + # model's function and Jacobians + def func(beta, x): + y0 = beta[0] + beta[1] * x[0, :] + beta[2] * x[1, :] + y1 = beta[3] + beta[4] * x[0, :] + beta[5] * x[1, :] + + return np.vstack((y0, y1)) + + def df_dbeta_odr(beta, x): + nr_meas = np.shape(x)[1] + zeros = np.zeros(nr_meas) + ones = np.ones(nr_meas) + + dy0 = np.array([ones, x[0, :], x[1, :], zeros, zeros, zeros]) + dy1 = np.array([zeros, zeros, zeros, ones, x[0, :], x[1, :]]) + + return np.stack((dy0, dy1)) + + def df_dx_odr(beta, x): + nr_meas = np.shape(x)[1] + ones = np.ones(nr_meas) + + dy0 = np.array([beta[1] * ones, beta[2] * ones]) + dy1 = np.array([beta[4] * ones, beta[5] * ones]) + return np.stack((dy0, dy1)) + + # do measurements with errors in independent and dependent variables + x0_true = np.linspace(1, 10, nr_measurements) + x1_true = np.linspace(1, 10, nr_measurements) + x_true = np.array([x0_true, x1_true]) + + y_true = func(beta_true, x_true) + + x_meas = x_true + x_error + y_meas = y_true + y_error + + # estimate model's parameters + model_f = Model(func, fjacb=df_dbeta_odr, fjacd=df_dx_odr) + + data = RealData(x_meas, y_meas, sx=std_dev_x, sy=std_dev_y) + + odr_obj = ODR(data, model_f, beta0=0.9 * beta_true, maxit=100) + #odr_obj.set_iprint(init=2, iter=0, iter_step=1, final=1) + odr_obj.set_job(deriv=3) + + odr_out = odr_obj.run() + + # check results + assert_equal(odr_out.info, 1) + assert_array_almost_equal(odr_out.beta, beta_solution) + + def test_multilinear_model(self): + x = np.linspace(0.0, 5.0) + y = 10.0 + 5.0 * x + data = Data(x, y) + odr_obj = ODR(data, multilinear) + output = odr_obj.run() + assert_array_almost_equal(output.beta, [10.0, 5.0]) + + def test_exponential_model(self): + x = np.linspace(0.0, 5.0) + y = -10.0 + np.exp(0.5*x) + data = Data(x, y) + odr_obj = ODR(data, exponential) + output = odr_obj.run() + assert_array_almost_equal(output.beta, [-10.0, 0.5]) + + def test_polynomial_model(self): + x = np.linspace(0.0, 5.0) + y = 1.0 + 2.0 * x + 3.0 * x ** 2 + 4.0 * x ** 3 + poly_model = polynomial(3) + data = Data(x, y) + odr_obj = ODR(data, poly_model) + output = odr_obj.run() + assert_array_almost_equal(output.beta, [1.0, 2.0, 3.0, 4.0]) + + def test_unilinear_model(self): + x = np.linspace(0.0, 5.0) + y = 1.0 * x + 2.0 + data = Data(x, y) + odr_obj = ODR(data, unilinear) + output = odr_obj.run() + assert_array_almost_equal(output.beta, [1.0, 2.0]) + + def test_quadratic_model(self): + x = np.linspace(0.0, 5.0) + y = 1.0 * x ** 2 + 2.0 * x + 3.0 + data = Data(x, y) + odr_obj = ODR(data, quadratic) + output = odr_obj.run() + assert_array_almost_equal(output.beta, [1.0, 2.0, 3.0]) + + def test_work_ind(self): + + def func(par, x): + b0, b1 = par + return b0 + b1 * x + + # generate some data + n_data = 4 + x = np.arange(n_data) + y = np.where(x % 2, x + 0.1, x - 0.1) + x_err = np.full(n_data, 0.1) + y_err = np.full(n_data, 0.1) + + # do the fitting + linear_model = Model(func) + real_data = RealData(x, y, sx=x_err, sy=y_err) + odr_obj = ODR(real_data, linear_model, beta0=[0.4, 0.4]) + odr_obj.set_job(fit_type=0) + out = odr_obj.run() + + sd_ind = out.work_ind['sd'] + assert_array_almost_equal(out.sd_beta, + out.work[sd_ind:sd_ind + len(out.sd_beta)]) + + @pytest.mark.skipif(True, reason="Fortran I/O prone to crashing so better " + "not to run this test, see gh-13127") + def test_output_file_overwrite(self): + """ + Verify fix for gh-1892 + """ + def func(b, x): + return b[0] + b[1] * x + + p = Model(func) + data = Data(np.arange(10), 12 * np.arange(10)) + tmp_dir = tempfile.mkdtemp() + error_file_path = os.path.join(tmp_dir, "error.dat") + report_file_path = os.path.join(tmp_dir, "report.dat") + try: + ODR(data, p, beta0=[0.1, 13], errfile=error_file_path, + rptfile=report_file_path).run() + ODR(data, p, beta0=[0.1, 13], errfile=error_file_path, + rptfile=report_file_path, overwrite=True).run() + finally: + # remove output files for clean up + shutil.rmtree(tmp_dir) + + def test_odr_model_default_meta(self): + def func(b, x): + return b[0] + b[1] * x + + p = Model(func) + p.set_meta(name='Sample Model Meta', ref='ODRPACK') + assert_equal(p.meta, {'name': 'Sample Model Meta', 'ref': 'ODRPACK'}) + + def test_work_array_del_init(self): + """ + Verify fix for gh-18739 where del_init=1 fails. + """ + def func(b, x): + return b[0] + b[1] * x + + # generate some data + n_data = 4 + x = np.arange(n_data) + y = np.where(x % 2, x + 0.1, x - 0.1) + x_err = np.full(n_data, 0.1) + y_err = np.full(n_data, 0.1) + + linear_model = Model(func) + # Try various shapes of the `we` array from various `sy` and `covy` + rd0 = RealData(x, y, sx=x_err, sy=y_err) + rd1 = RealData(x, y, sx=x_err, sy=0.1) + rd2 = RealData(x, y, sx=x_err, sy=[0.1]) + rd3 = RealData(x, y, sx=x_err, sy=np.full((1, n_data), 0.1)) + rd4 = RealData(x, y, sx=x_err, covy=[[0.01]]) + rd5 = RealData(x, y, sx=x_err, covy=np.full((1, 1, n_data), 0.01)) + for rd in [rd0, rd1, rd2, rd3, rd4, rd5]: + odr_obj = ODR(rd, linear_model, beta0=[0.4, 0.4], + delta0=np.full(n_data, -0.1)) + odr_obj.set_job(fit_type=0, del_init=1) + # Just make sure that it runs without raising an exception. + odr_obj.run() + + def test_pickling_data(self): + x = np.linspace(0.0, 5.0) + y = 1.0 * x + 2.0 + data = Data(x, y) + + obj_pickle = pickle.dumps(data) + del data + pickle.loads(obj_pickle) + + def test_pickling_real_data(self): + x = np.linspace(0.0, 5.0) + y = 1.0 * x + 2.0 + data = RealData(x, y) + + obj_pickle = pickle.dumps(data) + del data + pickle.loads(obj_pickle) + + def test_pickling_model(self): + obj_pickle = pickle.dumps(unilinear) + pickle.loads(obj_pickle) + + def test_pickling_odr(self): + x = np.linspace(0.0, 5.0) + y = 1.0 * x + 2.0 + odr_obj = ODR(Data(x, y), unilinear) + + obj_pickle = pickle.dumps(odr_obj) + del odr_obj + pickle.loads(obj_pickle) + + def test_pickling_output(self): + x = np.linspace(0.0, 5.0) + y = 1.0 * x + 2.0 + output = ODR(Data(x, y), unilinear).run + + obj_pickle = pickle.dumps(output) + del output + pickle.loads(obj_pickle) + + def test_explicit_model_with_implicit_job(self): + """ + Verify fix for gh-23763 that ODR doesn't segfault + """ + x = np.linspace(0, 10, 10) + y = 2.0 + 3.0 * x + + data = Data(x, y) + model = unilinear # this is an explicit model + + # job=1 is implicit, should raise on explicit model + with assert_raises(OdrError): + odr = ODR(data, model, job=1) + odr.run() diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..abdbf1c915223b0b1301f06e5afde12db82763f3 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_arraytools.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_arraytools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ed36ec357eb156b55ac35c8b97ca6fae0657799b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_arraytools.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_czt.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_czt.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c80d7f226719825df79def7dcf1823a8aec74b0f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_czt.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_delegators.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_delegators.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..05dc04ab7b04b0f2c2916fdbb847cff83d4ea9e8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_delegators.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_fir_filter_design.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_fir_filter_design.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07e5e6452604d12489962112fb3563edab088cd2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_fir_filter_design.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_lti_conversion.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_lti_conversion.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4cabfa4a8fd93df46c926aa1ee905a3c3c2213e6 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_lti_conversion.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_max_len_seq.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_max_len_seq.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f4ec868f55e5dcc5f3dd70f4e4eca1b3a48165e2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_max_len_seq.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_peak_finding.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_peak_finding.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e03aa4dc3a9fe4ccff53318ff5b90c3eeee65055 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_peak_finding.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_polyutils.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_polyutils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aabdac863e62d59b6ff7f1c44c96004a32d05b6e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_polyutils.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_savitzky_golay.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_savitzky_golay.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2ca21b08fd8c262ae8b24e9169e1c23d34729be5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_savitzky_golay.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_signal_api.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_signal_api.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5fb39d05ec9eeb83a89f02afa5cf11fa1eefc2f4 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_signal_api.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_spline_filters.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_spline_filters.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..10ccb6e2a7af2c5f10d355811de05be4c57a6183 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_spline_filters.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_support_alternative_backends.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_support_alternative_backends.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9c0dd637c49510116411db25b5a9fbc2631ef9ad Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_support_alternative_backends.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_upfirdn.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_upfirdn.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..072304b441ff86d4d521e61f42154ee4520b52d3 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_upfirdn.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_waveforms.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_waveforms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d3af96b139c5949e0ff041d6d4a1ab6e5991d53 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_waveforms.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_wavelets.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_wavelets.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b4a6a914c1969a94c3b7892bcc6a075b274dc6a7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/_wavelets.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/bsplines.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/bsplines.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..67fd77a581e7ad8a424a897547a51b7b3706ca55 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/bsplines.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/filter_design.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/filter_design.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d709c282e6a02ea5cfa3e791154ceb44b5a97de4 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/filter_design.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/fir_filter_design.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/fir_filter_design.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..76b4b77b847fb2b286925167ce754150b8a646fa Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/fir_filter_design.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/lti_conversion.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/lti_conversion.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2de4dbc1d5d33168c869d24d8d595235776ba113 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/lti_conversion.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/ltisys.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/ltisys.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a40d4de6c3041faa3288b50d7a45112473708b5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/ltisys.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/signaltools.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/signaltools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c522b5a5e1aec2d55e28657c35135b3d800f816f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/signaltools.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/spectral.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/spectral.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8085af5b249d30e3f72e88df1376d27dcdc3ec67 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/spectral.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/spline.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/spline.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fca53f87b2c1e5902b13094e56e24d8935267670 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/spline.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/waveforms.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/waveforms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..61c5aa6559a2f0d28f034fce5589ff1178f4ed8d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/waveforms.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/wavelets.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/wavelets.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9e487574285b8bb60c68b3923caa94b8b554358d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/__pycache__/wavelets.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4ebc7c28913eb9c40b2675fe1cc3e245fd79f085 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/_scipy_spectral_test_shim.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/_scipy_spectral_test_shim.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab936ab8fe4bf100a3b26313fbed5854d9a07b2b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/_scipy_spectral_test_shim.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/mpsig.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/mpsig.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fec56fafe27570e815b0918cb06a3a25d3b162f3 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/mpsig.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_array_tools.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_array_tools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..463836ac779465561891bb6dc44413d54e63dcd4 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_array_tools.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_bsplines.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_bsplines.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8fbc8b4a47b0db730f71ac5f3747545f8e67bc95 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_bsplines.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_cont2discrete.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_cont2discrete.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62a1fc36d6def655226633b653901110ec65a9f1 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_cont2discrete.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_czt.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_czt.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..69dee85aeb4fd44accd8a576b1de6e0867578b51 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_czt.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_dltisys.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_dltisys.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7796ba3a82b288c5893649ab70edc36fb2606a8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_dltisys.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_fir_filter_design.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_fir_filter_design.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..29f7e3a4d5ece37ac8fa2b27aa0e646510a796f0 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_fir_filter_design.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_ltisys.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_ltisys.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6b9a06620591602767c1effaa9ffa7bc2a22336d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_ltisys.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_max_len_seq.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_max_len_seq.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..452c5250864870fd2f4999fcdf06446cfa5279a6 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_max_len_seq.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_peak_finding.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_peak_finding.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c6b73ea0c172e9995d4d035477e2707f0b8c770f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_peak_finding.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_result_type.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_result_type.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9b3a83148501e47d49e0be4f9cf6e81942fc91bc Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_result_type.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_savitzky_golay.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_savitzky_golay.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6a42251a1afe66fd2094639543c6b25d4718cede Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_savitzky_golay.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_short_time_fft.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_short_time_fft.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ffd857f3e2c00d28254ea75e6b9c86278d12bed6 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_short_time_fft.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_splines.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_splines.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4cb24b831c1a973b11a22ddedd829e230276b8f7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_splines.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_upfirdn.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_upfirdn.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1ddd316b841ae7c8b3eb5cace6f52ac67ed218da Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_upfirdn.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_waveforms.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_waveforms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..816b1b00f02644b4605d8c657d19b74cdf8fe031 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_waveforms.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_wavelets.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_wavelets.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ba42db38a74964af819ca8c9804f88729d514dc4 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_wavelets.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_windows.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_windows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd0687adff0d07d4842573877f908a10a48dafd5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/__pycache__/test_windows.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/_scipy_spectral_test_shim.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/_scipy_spectral_test_shim.py new file mode 100644 index 0000000000000000000000000000000000000000..6003f68c0bce4ad33a110fe1379caabe14c2b1e7 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/_scipy_spectral_test_shim.py @@ -0,0 +1,311 @@ +"""Helpers to utilize existing stft / istft tests for testing `ShortTimeFFT`. + +This module provides the functions stft_compare() and istft_compare(), which, +compares the output between the existing (i)stft() and the shortTimeFFT based +_(i)stft_wrapper() implementations in this module. + +For testing add the following imports to the file ``tests/test_spectral.py``:: + + from ._scipy_spectral_test_shim import stft_compare as stft + from ._scipy_spectral_test_shim import istft_compare as istft + +and remove the existing imports of stft and istft. + +The idea of these wrappers is not to provide a backward-compatible interface +but to demonstrate that the ShortTimeFFT implementation is at least as capable +as the existing one and delivers comparable results. Furthermore, the +wrappers highlight the different philosophies of the implementations, +especially in the border handling. +""" +import platform +from typing import cast, Literal + +import numpy as np +from numpy.testing import assert_allclose + +from scipy.signal import ShortTimeFFT +from scipy.signal import get_window, stft, istft +from scipy.signal._arraytools import const_ext, even_ext, odd_ext, zero_ext +from scipy.signal._short_time_fft import FFT_MODE_TYPE +from scipy.signal._spectral_py import _triage_segments + + +def _stft_wrapper(x, fs=1.0, window='hann', nperseg=256, noverlap=None, + nfft=None, detrend=False, return_onesided=True, + boundary='zeros', padded=True, axis=-1, scaling='spectrum'): + """Wrapper for the SciPy `stft()` function based on `ShortTimeFFT` for + unit testing. + + Handling the boundary and padding is where `ShortTimeFFT` and `stft()` + differ in behavior. Parts of `_spectral_helper()` were copied to mimic + the` stft()` behavior. + + This function is meant to be solely used by `stft_compare()`. + """ + if scaling not in ('psd', 'spectrum'): # same errors as in original stft: + raise ValueError(f"Parameter {scaling=} not in ['spectrum', 'psd']!") + + # The following lines are taken from the original _spectral_helper(): + boundary_funcs = {'even': even_ext, + 'odd': odd_ext, + 'constant': const_ext, + 'zeros': zero_ext, + None: None} + + if boundary not in boundary_funcs: + raise ValueError(f"Unknown boundary option '{boundary}', must be one" + + f" of: {list(boundary_funcs.keys())}") + if x.size == 0: + return np.empty(x.shape), np.empty(x.shape), np.empty(x.shape) + + if nperseg is not None: # if specified by user + nperseg = int(nperseg) + if nperseg < 1: + raise ValueError('nperseg must be a positive integer') + + # parse window; if array like, then set nperseg = win.shape + win, nperseg = _triage_segments(window, nperseg, + input_length=x.shape[axis]) + + if nfft is None: + nfft = nperseg + elif nfft < nperseg: + raise ValueError('nfft must be greater than or equal to nperseg.') + else: + nfft = int(nfft) + + if noverlap is None: + noverlap = nperseg//2 + else: + noverlap = int(noverlap) + if noverlap >= nperseg: + raise ValueError('noverlap must be less than nperseg.') + nstep = nperseg - noverlap + n = x.shape[axis] + + # Padding occurs after boundary extension, so that the extended signal ends + # in zeros, instead of introducing an impulse at the end. + # I.e. if x = [..., 3, 2] + # extend then pad -> [..., 3, 2, 2, 3, 0, 0, 0] + # pad then extend -> [..., 3, 2, 0, 0, 0, 2, 3] + + if boundary is not None: + ext_func = boundary_funcs[boundary] + # Extend by nperseg//2 in front and back: + x = ext_func(x, nperseg//2, axis=axis) + + if padded: + # Pad to integer number of windowed segments + # I.e make x.shape[-1] = nperseg + (nseg-1)*nstep, with integer nseg + x = np.moveaxis(x, axis, -1) + + # This is an edge case where shortTimeFFT returns one more time slice + # than the Scipy stft() shorten to remove last time slice: + if n % 2 == 1 and nperseg % 2 == 1 and noverlap % 2 == 1: + x = x[..., : -1] + + nadd = (-(x.shape[-1]-nperseg) % nstep) % nperseg + zeros_shape = list(x.shape[:-1]) + [nadd] + x = np.concatenate((x, np.zeros(zeros_shape)), axis=-1) + x = np.moveaxis(x, -1, axis) + + # ... end original _spectral_helper() code. + scale_to = {'spectrum': 'magnitude', 'psd': 'psd'}[scaling] + + if np.iscomplexobj(x) and return_onesided: + return_onesided = False + # using cast() to make mypy happy: + fft_mode = cast(FFT_MODE_TYPE, 'onesided' if return_onesided else 'twosided') + + ST = ShortTimeFFT(win, nstep, fs, fft_mode=fft_mode, mfft=nfft, + scale_to=scale_to, phase_shift=None) + + k_off = nperseg // 2 + p0 = 0 # ST.lower_border_end[1] + 1 + nn = x.shape[axis] if padded else n+k_off+1 + # number of frames akin to legacy stft computation + p1 = (x.shape[axis] - nperseg) // nstep + 1 + + detr = None if detrend is False else detrend + Sxx = ST.stft_detrend(x, detr, p0, p1, k_offset=k_off, axis=axis) + t = ST.t(nn, 0, p1 - p0, k_offset=0 if boundary is not None else k_off) + if x.dtype in (np.float32, np.complex64): + Sxx = Sxx.astype(np.complex64) + + return ST.f, t, Sxx + + +def _istft_wrapper(Zxx, fs=1.0, window='hann', nperseg=None, noverlap=None, + nfft=None, input_onesided=True, boundary=True, time_axis=-1, + freq_axis=-2, scaling='spectrum') -> \ + tuple[np.ndarray, np.ndarray, tuple[int, int]]: + """Wrapper for the SciPy `istft()` function based on `ShortTimeFFT` for + unit testing. + + Note that only option handling is implemented as far as to handle the unit + tests. E.g., the case ``nperseg=None`` is not handled. + + This function is meant to be solely used by `istft_compare()`. + """ + # *** Lines are taken from _spectral_py.istft() ***: + if Zxx.ndim < 2: + raise ValueError('Input stft must be at least 2d!') + + if freq_axis == time_axis: + raise ValueError('Must specify differing time and frequency axes!') + + nseg = Zxx.shape[time_axis] + + if input_onesided: + # Assume even segment length + n_default = 2*(Zxx.shape[freq_axis] - 1) + else: + n_default = Zxx.shape[freq_axis] + + # Check windowing parameters + if nperseg is None: + nperseg = n_default + else: + nperseg = int(nperseg) + if nperseg < 1: + raise ValueError('nperseg must be a positive integer') + + if nfft is None: + if input_onesided and (nperseg == n_default + 1): + # Odd nperseg, no FFT padding + nfft = nperseg + else: + nfft = n_default + elif nfft < nperseg: + raise ValueError('nfft must be greater than or equal to nperseg.') + else: + nfft = int(nfft) + + if noverlap is None: + noverlap = nperseg//2 + else: + noverlap = int(noverlap) + if noverlap >= nperseg: + raise ValueError('noverlap must be less than nperseg.') + nstep = nperseg - noverlap + + # Get window as array + if isinstance(window, str) or type(window) is tuple: + win = get_window(window, nperseg) + else: + win = np.asarray(window) + if len(win.shape) != 1: + raise ValueError('window must be 1-D') + if win.shape[0] != nperseg: + raise ValueError(f'window must have length of {nperseg}') + + outputlength = nperseg + (nseg-1)*nstep + # *** End block of: Taken from _spectral_py.istft() *** + + # Using cast() to make mypy happy: + fft_mode = cast(FFT_MODE_TYPE, 'onesided' if input_onesided else 'twosided') + scale_to = cast(Literal['magnitude', 'psd'], + {'spectrum': 'magnitude', 'psd': 'psd'}[scaling]) + + ST = ShortTimeFFT(win, nstep, fs, fft_mode=fft_mode, mfft=nfft, + scale_to=scale_to, phase_shift=None) + + if boundary: + j = nperseg if nperseg % 2 == 0 else nperseg - 1 + k0 = ST.k_min + nperseg // 2 + k1 = outputlength - j + k0 + else: + raise NotImplementedError("boundary=False does not make sense with" + + "ShortTimeFFT.istft()!") + + x = ST.istft(Zxx, k0=k0, k1=k1, f_axis=freq_axis, t_axis=time_axis) + t = np.arange(k1 - k0) * ST.T + k_hi = ST.upper_border_begin(k1 - k0)[0] + # using cast() to make mypy happy: + return t, x, (ST.lower_border_end[0], k_hi) + + +def stft_compare(x, fs=1.0, window='hann', nperseg=256, noverlap=None, + nfft=None, detrend=False, return_onesided=True, + boundary='zeros', padded=True, axis=-1, scaling='spectrum'): + """Assert that the results from the existing `stft()` and `_stft_wrapper()` + are close to each other. + + For comparing the STFT values an absolute tolerance of the floating point + resolution was added to circumvent problems with the following tests: + * For float32 the tolerances are much higher in + TestSTFT.test_roundtrip_float32()). + * The TestSTFT.test_roundtrip_scaling() has a high relative deviation. + Interestingly this did not appear in Scipy 1.9.1 but only in the current + development version. + """ + kw = dict(x=x, fs=fs, window=window, nperseg=nperseg, noverlap=noverlap, + nfft=nfft, detrend=detrend, return_onesided=return_onesided, + boundary=boundary, padded=padded, axis=axis, scaling=scaling) + f, t, Zxx = stft(**kw) + f_wrapper, t_wrapper, Zxx_wrapper = _stft_wrapper(**kw) + + e_msg_part = " of `stft_wrapper()` differ from `stft()`." + assert_allclose(f_wrapper, f, err_msg=f"Frequencies {e_msg_part}") + assert_allclose(t_wrapper, t, err_msg=f"Time slices {e_msg_part}") + + # Adapted tolerances to account for: + atol = np.finfo(Zxx.dtype).resolution * 2 + assert_allclose(Zxx_wrapper, Zxx, atol=atol, + err_msg=f"STFT values {e_msg_part}") + return f, t, Zxx + + +def istft_compare(Zxx, fs=1.0, window='hann', nperseg=None, noverlap=None, + nfft=None, input_onesided=True, boundary=True, time_axis=-1, + freq_axis=-2, scaling='spectrum'): + """Assert that the results from the existing `istft()` and + `_istft_wrapper()` are close to each other. + + Quirks: + * If ``boundary=False`` the comparison is skipped, since it does not + make sense with ShortTimeFFT.istft(). Only used in test + TestSTFT.test_roundtrip_boundary_extension(). + * If ShortTimeFFT.istft() decides the STFT is not invertible, the + comparison is skipped, since istft() only emits a warning and does not + return a correct result. Only used in + ShortTimeFFT.test_roundtrip_not_nola(). + * For comparing the signals an absolute tolerance of the floating point + resolution was added to account for the low accuracy of float32 (Occurs + only in TestSTFT.test_roundtrip_float32()). + """ + kw = dict(Zxx=Zxx, fs=fs, window=window, nperseg=nperseg, + noverlap=noverlap, nfft=nfft, input_onesided=input_onesided, + boundary=boundary, time_axis=time_axis, freq_axis=freq_axis, + scaling=scaling) + + t, x = istft(**kw) + if not boundary: # skip test_roundtrip_boundary_extension(): + return t, x # _istft_wrapper does() not implement this case + try: # if inversion fails, istft() only emits a warning: + t_wrapper, x_wrapper, (k_lo, k_hi) = _istft_wrapper(**kw) + except ValueError as v: # Do nothing if inversion fails: + if v.args[0] == "Short-time Fourier Transform not invertible!": + return t, x + raise v + + e_msg_part = " of `istft_wrapper()` differ from `istft()`" + assert_allclose(t, t_wrapper, err_msg=f"Sample times {e_msg_part}") + + # Adapted tolerances to account for resolution loss: + atol = np.finfo(x.dtype).resolution*2 # instead of default atol = 0 + rtol = 1e-7 # default for np.allclose() + + # Relax atol on 32-Bit platforms a bit to pass CI tests. + # - Not clear why there are discrepancies (in the FFT maybe?) + # - Not sure what changed on 'i686' since earlier on those test passed + if x.dtype == np.float32 and platform.machine() == 'i686': + # float32 gets only used by TestSTFT.test_roundtrip_float32() so + # we are using the tolerances from there to circumvent CI problems + atol, rtol = 1e-4, 1e-5 + elif platform.machine() in ('aarch64', 'i386', 'i686'): + atol = max(atol, 1e-12) # 2e-15 seems too tight for 32-Bit platforms + + assert_allclose(x_wrapper[k_lo:k_hi], x[k_lo:k_hi], atol=atol, rtol=rtol, + err_msg=f"Signal values {e_msg_part}") + return t, x diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/mpsig.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/mpsig.py new file mode 100644 index 0000000000000000000000000000000000000000..d129de74e5df00c22bc0b82c7d3f7b52483941f9 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/mpsig.py @@ -0,0 +1,122 @@ +""" +Some signal functions implemented using mpmath. +""" + +try: + import mpmath +except ImportError: + mpmath = None + + +def _prod(seq): + """Returns the product of the elements in the sequence `seq`.""" + p = 1 + for elem in seq: + p *= elem + return p + + +def _relative_degree(z, p): + """ + Return relative degree of transfer function from zeros and poles. + + This is simply len(p) - len(z), which must be nonnegative. + A ValueError is raised if len(p) < len(z). + """ + degree = len(p) - len(z) + if degree < 0: + raise ValueError("Improper transfer function. " + "Must have at least as many poles as zeros.") + return degree + + +def _zpkbilinear(z, p, k, fs): + """Bilinear transformation to convert a filter from analog to digital.""" + + degree = _relative_degree(z, p) + + fs2 = 2*fs + + # Bilinear transform the poles and zeros + z_z = [(fs2 + z1) / (fs2 - z1) for z1 in z] + p_z = [(fs2 + p1) / (fs2 - p1) for p1 in p] + + # Any zeros that were at infinity get moved to the Nyquist frequency + z_z.extend([-1] * degree) + + # Compensate for gain change + numer = _prod(fs2 - z1 for z1 in z) + denom = _prod(fs2 - p1 for p1 in p) + k_z = k * numer / denom + + return z_z, p_z, k_z.real + + +def _zpklp2lp(z, p, k, wo=1): + """Transform a lowpass filter to a different cutoff frequency.""" + + degree = _relative_degree(z, p) + + # Scale all points radially from origin to shift cutoff frequency + z_lp = [wo * z1 for z1 in z] + p_lp = [wo * p1 for p1 in p] + + # Each shifted pole decreases gain by wo, each shifted zero increases it. + # Cancel out the net change to keep overall gain the same + k_lp = k * wo**degree + + return z_lp, p_lp, k_lp + + +def _butter_analog_poles(n): + """ + Poles of an analog Butterworth lowpass filter. + + This is the same calculation as scipy.signal.buttap(n) or + scipy.signal.butter(n, 1, analog=True, output='zpk'), but mpmath is used, + and only the poles are returned. + """ + poles = [-mpmath.exp(1j*mpmath.pi*k/(2*n)) for k in range(-n+1, n, 2)] + return poles + + +def butter_lp(n, Wn): + """ + Lowpass Butterworth digital filter design. + + This computes the same result as scipy.signal.butter(n, Wn, output='zpk'), + but it uses mpmath, and the results are returned in lists instead of NumPy + arrays. + """ + zeros = [] + poles = _butter_analog_poles(n) + k = 1 + fs = 2 + warped = 2 * fs * mpmath.tan(mpmath.pi * Wn / fs) + z, p, k = _zpklp2lp(zeros, poles, k, wo=warped) + z, p, k = _zpkbilinear(z, p, k, fs=fs) + return z, p, k + + +def zpkfreqz(z, p, k, worN=None): + """ + Frequency response of a filter in zpk format, using mpmath. + + This is the same calculation as scipy.signal.freqz, but the input is in + zpk format, the calculation is performed using mpath, and the results are + returned in lists instead of NumPy arrays. + """ + if worN is None or isinstance(worN, int): + N = worN or 512 + ws = [mpmath.pi * mpmath.mpf(j) / N for j in range(N)] + else: + ws = worN + + h = [] + for wk in ws: + zm1 = mpmath.exp(1j * wk) + numer = _prod([zm1 - t for t in z]) + denom = _prod([zm1 - t for t in p]) + hk = k * numer / denom + h.append(hk) + return ws, h diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_array_tools.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_array_tools.py new file mode 100644 index 0000000000000000000000000000000000000000..4bda9716e0bc4b6ad3ed0c3954147043b74c421a --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_array_tools.py @@ -0,0 +1,111 @@ +import numpy as np + +from scipy._lib._array_api import xp_assert_equal +from pytest import raises as assert_raises + +from scipy.signal._arraytools import (axis_slice, axis_reverse, + odd_ext, even_ext, const_ext, zero_ext) + + +class TestArrayTools: + + def test_axis_slice(self): + a = np.arange(12).reshape(3, 4) + + s = axis_slice(a, start=0, stop=1, axis=0) + xp_assert_equal(s, a[0:1, :]) + + s = axis_slice(a, start=-1, axis=0) + xp_assert_equal(s, a[-1:, :]) + + s = axis_slice(a, start=0, stop=1, axis=1) + xp_assert_equal(s, a[:, 0:1]) + + s = axis_slice(a, start=-1, axis=1) + xp_assert_equal(s, a[:, -1:]) + + s = axis_slice(a, start=0, step=2, axis=0) + xp_assert_equal(s, a[::2, :]) + + s = axis_slice(a, start=0, step=2, axis=1) + xp_assert_equal(s, a[:, ::2]) + + def test_axis_reverse(self): + a = np.arange(12).reshape(3, 4) + + r = axis_reverse(a, axis=0) + xp_assert_equal(r, a[::-1, :]) + + r = axis_reverse(a, axis=1) + xp_assert_equal(r, a[:, ::-1]) + + def test_odd_ext(self): + a = np.array([[1, 2, 3, 4, 5], + [9, 8, 7, 6, 5]]) + + odd = odd_ext(a, 2, axis=1) + expected = np.array([[-1, 0, 1, 2, 3, 4, 5, 6, 7], + [11, 10, 9, 8, 7, 6, 5, 4, 3]]) + xp_assert_equal(odd, expected) + + odd = odd_ext(a, 1, axis=0) + expected = np.array([[-7, -4, -1, 2, 5], + [1, 2, 3, 4, 5], + [9, 8, 7, 6, 5], + [17, 14, 11, 8, 5]]) + xp_assert_equal(odd, expected) + + assert_raises(ValueError, odd_ext, a, 2, axis=0) + assert_raises(ValueError, odd_ext, a, 5, axis=1) + + def test_even_ext(self): + a = np.array([[1, 2, 3, 4, 5], + [9, 8, 7, 6, 5]]) + + even = even_ext(a, 2, axis=1) + expected = np.array([[3, 2, 1, 2, 3, 4, 5, 4, 3], + [7, 8, 9, 8, 7, 6, 5, 6, 7]]) + xp_assert_equal(even, expected) + + even = even_ext(a, 1, axis=0) + expected = np.array([[9, 8, 7, 6, 5], + [1, 2, 3, 4, 5], + [9, 8, 7, 6, 5], + [1, 2, 3, 4, 5]]) + xp_assert_equal(even, expected) + + assert_raises(ValueError, even_ext, a, 2, axis=0) + assert_raises(ValueError, even_ext, a, 5, axis=1) + + def test_const_ext(self): + a = np.array([[1, 2, 3, 4, 5], + [9, 8, 7, 6, 5]]) + + const = const_ext(a, 2, axis=1) + expected = np.array([[1, 1, 1, 2, 3, 4, 5, 5, 5], + [9, 9, 9, 8, 7, 6, 5, 5, 5]]) + xp_assert_equal(const, expected) + + const = const_ext(a, 1, axis=0) + expected = np.array([[1, 2, 3, 4, 5], + [1, 2, 3, 4, 5], + [9, 8, 7, 6, 5], + [9, 8, 7, 6, 5]]) + xp_assert_equal(const, expected) + + def test_zero_ext(self): + a = np.array([[1, 2, 3, 4, 5], + [9, 8, 7, 6, 5]]) + + zero = zero_ext(a, 2, axis=1) + expected = np.array([[0, 0, 1, 2, 3, 4, 5, 0, 0], + [0, 0, 9, 8, 7, 6, 5, 0, 0]]) + xp_assert_equal(zero, expected) + + zero = zero_ext(a, 1, axis=0) + expected = np.array([[0, 0, 0, 0, 0], + [1, 2, 3, 4, 5], + [9, 8, 7, 6, 5], + [0, 0, 0, 0, 0]]) + xp_assert_equal(zero, expected) + diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_bsplines.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_bsplines.py new file mode 100644 index 0000000000000000000000000000000000000000..a4d3ffe88b79b0147cc52b51e0d89fa3a61ceb34 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_bsplines.py @@ -0,0 +1,391 @@ +# pylint: disable=missing-docstring +import math +import numpy as np + +from scipy._lib._array_api import ( + assert_almost_equal, xp_assert_close, xp_assert_equal, make_xp_test_case, + xp_default_dtype, array_namespace, _xp_copy_to_numpy +) +import pytest +from pytest import raises + +from scipy import signal + +skip_xp_backends = pytest.mark.skip_xp_backends +xfail_xp_backends = pytest.mark.xfail_xp_backends + +lazy_xp_modules = [signal] + + +class TestBSplines: + """Test behaviors of B-splines. Some of the values tested against were + returned as of SciPy 1.1.0 and are included for regression testing + purposes. Others (at integer points) are compared to theoretical + expressions (cf. Unser, Aldroubi, Eden, IEEE TSP 1993, Table 1).""" + + @make_xp_test_case(signal.spline_filter) + def test_spline_filter(self, xp): + rng = np.random.RandomState(12457) + # Test the type-error branch + raises(TypeError, signal.spline_filter, xp.asarray([0]), 0) + # Test the real branch + data_array_real = rng.rand(12, 12) + # make the magnitude exceed 1, and make some negative + data_array_real = 10*(1-2*data_array_real) + data_array_real = xp.asarray(data_array_real) + result_array_real = xp.asarray( + [[-.463312621, 8.33391222, .697290949, 5.28390836, + 5.92066474, 6.59452137, 9.84406950, -8.78324188, + 7.20675750, -8.17222994, -4.38633345, 9.89917069], + [2.67755154, 6.24192170, -3.15730578, 9.87658581, + -9.96930425, 3.17194115, -4.50919947, 5.75423446, + 9.65979824, -8.29066885, .971416087, -2.38331897], + [-7.08868346, 4.89887705, -1.37062289, 7.70705838, + 2.51526461, 3.65885497, 5.16786604, -8.77715342e-03, + 4.10533325, 9.04761993, -.577960351, 9.86382519], + [-4.71444301, -1.68038985, 2.84695116, 1.14315938, + -3.17127091, 1.91830461, 7.13779687, -5.35737482, + -9.66586425, -9.87717456, 9.93160672, 4.71948144], + [9.49551194, -1.92958436, 6.25427993, -9.05582911, + 3.97562282, 7.68232426, -1.04514824, -5.86021443, + -8.43007451, 5.47528997, 2.06330736, -8.65968112], + [-8.91720100, 8.87065356, 3.76879937, 2.56222894, + -.828387146, 8.72288903, 6.42474741, -6.84576083, + 9.94724115, 6.90665380, -6.61084494, -9.44907391], + [9.25196790, -.774032030, 7.05371046, -2.73505725, + 2.53953305, -1.82889155, 2.95454824, -1.66362046, + 5.72478916, -3.10287679, 1.54017123, -7.87759020], + [-3.98464539, -2.44316992, -1.12708657, 1.01725672, + -8.89294671, -5.42145629, -6.16370321, 2.91775492, + 9.64132208, .702499998, -2.02622392, 1.56308431], + [-2.22050773, 7.89951554, 5.98970713, -7.35861835, + 5.45459283, -7.76427957, 3.67280490, -4.05521315, + 4.51967507, -3.22738749, -3.65080177, 3.05630155], + [-6.21240584, -.296796126, -8.34800163, 9.21564563, + -3.61958784, -4.77120006, -3.99454057, 1.05021988e-03, + -6.95982829, 6.04380797, 8.43181250, -2.71653339], + [1.19638037, 6.99718842e-02, 6.72020394, -2.13963198, + 3.75309875, -5.70076744, 5.92143551, -7.22150575, + -3.77114594, -1.11903194, -5.39151466, 3.06620093], + [9.86326886, 1.05134482, -7.75950607, -3.64429655, + 7.81848957, -9.02270373, 3.73399754, -4.71962549, + -7.71144306, 3.78263161, 6.46034818, -4.43444731]], dtype=xp.float64) + xp_assert_close(signal.spline_filter(data_array_real, 0), + result_array_real) + + @make_xp_test_case(signal.spline_filter) + def test_spline_filter_complex(self, xp): + rng = np.random.RandomState(12457) + data_array_complex = rng.rand(7, 7) + rng.rand(7, 7)*1j + # make the magnitude exceed 1, and make some negative + data_array_complex = 10*(1+1j-2*data_array_complex) + data_array_complex = xp.asarray(data_array_complex) + + result_array_complex = xp.asarray( + [[-4.61489230e-01-1.92994022j, 8.33332443+6.25519943j, + 6.96300745e-01-9.05576038j, 5.28294849+3.97541356j, + 5.92165565+7.68240595j, 6.59493160-1.04542804j, + 9.84503460-5.85946894j], + [-8.78262329-8.4295969j, 7.20675516+5.47528982j, + -8.17223072+2.06330729j, -4.38633347-8.65968037j, + 9.89916801-8.91720295j, 2.67755103+8.8706522j, + 6.24192142+3.76879835j], + [-3.15627527+2.56303072j, 9.87658501-0.82838702j, + -9.96930313+8.72288895j, 3.17193985+6.42474651j, + -4.50919819-6.84576082j, 5.75423431+9.94723988j, + 9.65979767+6.90665293j], + [-8.28993416-6.61064005j, 9.71416473e-01-9.44907284j, + -2.38331890+9.25196648j, -7.08868170-0.77403212j, + 4.89887714+7.05371094j, -1.37062311-2.73505688j, + 7.70705748+2.5395329j], + [2.51528406-1.82964492j, 3.65885472+2.95454836j, + 5.16786575-1.66362023j, -8.77737999e-03+5.72478867j, + 4.10533333-3.10287571j, 9.04761887+1.54017115j, + -5.77960968e-01-7.87758923j], + [9.86398506-3.98528528j, -4.71444130-2.44316983j, + -1.68038976-1.12708664j, 2.84695053+1.01725709j, + 1.14315915-8.89294529j, -3.17127085-5.42145538j, + 1.91830420-6.16370344j], + [7.13875294+2.91851187j, -5.35737514+9.64132309j, + -9.66586399+0.70250005j, -9.87717438-2.0262239j, + 9.93160629+1.5630846j, 4.71948051-2.22050714j, + 9.49550819+7.8995142j]], dtype=xp.complex128) + # FIXME: for complex types, the computations are done in + # single precision (reason unclear). When this is changed, + # this test needs updating. + xp_assert_close(signal.spline_filter(data_array_complex, 0), + result_array_complex, rtol=1e-6) + + @make_xp_test_case(signal.gauss_spline) + def test_gauss_spline(self, xp): + assert math.isclose(signal.gauss_spline(0, 0), 1.381976597885342) + + xp_assert_close(signal.gauss_spline(xp.asarray([1.]), 1), + xp.asarray([0.04865217]), atol=1e-9 + ) + + @skip_xp_backends(np_only=True, reason="deliberate: array-likes are accepted") + @make_xp_test_case(signal.gauss_spline) + def test_gauss_spline_list(self, xp): + # regression test for gh-12152 (accept array_like) + knots = [-1.0, 0.0, -1.0] + assert_almost_equal(signal.gauss_spline(knots, 3), + np.asarray([0.15418033, 0.6909883, 0.15418033]) + ) + + @make_xp_test_case(signal.cspline1d) + def test_cspline1d(self, xp): + xp_assert_equal(signal.cspline1d(xp.asarray([0])), + xp.asarray([0.], dtype=xp.float64)) + c1d = xp.asarray([1.21037185, 1.86293902, 2.98834059, 4.11660378, + 4.78893826], dtype=xp.float64) + # test lamda != 0 + xp_assert_close(signal.cspline1d(xp.asarray([1., 2, 3, 4, 5]), 1), c1d) + c1d0 = xp.asarray([0.78683946, 2.05333735, 2.99981113, 3.94741812, + 5.21051638], dtype=xp.float64) + xp_assert_close(signal.cspline1d(xp.asarray([1., 2, 3, 4, 5])), c1d0) + + @make_xp_test_case(signal.qspline1d) + def test_qspline1d(self, xp): + xp_assert_equal(signal.qspline1d(xp.asarray([0])), + xp.asarray([0.], dtype=xp.float64)) + # test lamda != 0 + raises(ValueError, signal.qspline1d, xp.asarray([1., 2, 3, 4, 5]), 1.) + raises(ValueError, signal.qspline1d, xp.asarray([1., 2, 3, 4, 5]), -1.) + q1d0 = xp.asarray([0.85350007, 2.02441743, 2.99999534, 3.97561055, + 5.14634135], dtype=xp.float64) + xp_assert_close( + signal.qspline1d(xp.asarray([1., 2, 3, 4, 5], dtype=xp.float64)), q1d0 + ) + + @xfail_xp_backends("cupy", reason="https://github.com/cupy/cupy/pull/9484") + @make_xp_test_case(signal.cspline1d_eval) + def test_cspline1d_eval(self, xp): + r = signal.cspline1d_eval(xp.asarray([0., 0], dtype=xp.float64), + xp.asarray([0.], dtype=xp.float64)) + xp_assert_close(r, xp.asarray([0.], dtype=xp.float64)) + + r = signal.cspline1d_eval(xp.asarray([1., 0, 1], dtype=xp.float64), + xp.asarray([], dtype=xp.float64)) + xp_assert_equal(r, xp.asarray([], dtype=xp.float64)) + + # Test case for newx that gets filtered down to empty + r = signal.cspline1d_eval(xp.asarray([1.0, 0, 1], dtype=xp.float64), + xp.asarray([-1.0], dtype=xp.float64)) + xp_assert_close(r, xp.asarray([0.33333333], dtype=xp.float64)) + + x = [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6] + dx = x[1] - x[0] + newx = [-6., -5.5, -5., -4.5, -4., -3.5, -3., -2.5, -2., -1.5, -1., + -0.5, 0., 0.5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5., 5.5, 6., + 6.5, 7., 7.5, 8., 8.5, 9., 9.5, 10., 10.5, 11., 11.5, 12., + 12.5] + y = xp.asarray([4.216, 6.864, 3.514, 6.203, 6.759, 7.433, 7.874, 5.879, + 1.396, 4.094]) + cj = xp.asarray(signal.cspline1d(_xp_copy_to_numpy(y))) + newy = xp.asarray([6.203, 4.41570658, 3.514, 5.16924703, 6.864, 6.04643068, + 4.21600281, 6.04643068, 6.864, 5.16924703, 3.514, + 4.41570658, 6.203, 6.80717667, 6.759, 6.98971173, 7.433, + 7.79560142, 7.874, 7.41525761, 5.879, 3.18686814, 1.396, + 2.24889482, 4.094, 2.24889482, 1.396, 3.18686814, 5.879, + 7.41525761, 7.874, 7.79560142, 7.433, 6.98971173, 6.759, + 6.80717667, 6.203, 4.41570658], dtype=xp.float64) + xp_assert_close( + signal.cspline1d_eval(cj, xp.asarray(newx), dx=dx, x0=x[0]), newy + ) + + with pytest.raises(ValueError, + match="Spline coefficients 'cj' must not be empty."): + signal.cspline1d_eval(xp.asarray([], dtype=xp.float64), + xp.asarray([0.0], dtype=xp.float64)) + + @xfail_xp_backends("cupy", reason="https://github.com/cupy/cupy/pull/9484") + @make_xp_test_case(signal.qspline1d_eval) + def test_qspline1d_eval(self, xp): + xp_assert_close(signal.qspline1d_eval(xp.asarray([0., 0]), xp.asarray([0.])), + xp.asarray([0.]) + ) + xp_assert_equal(signal.qspline1d_eval(xp.asarray([1., 0, 1]), xp.asarray([])), + xp.asarray([]) + ) + + # Test case for newx that gets filtered down to empty + r = signal.qspline1d_eval(xp.asarray([1.0, 0, 1], dtype=xp.float64), + xp.asarray([-1.0], dtype=xp.float64)) + xp_assert_equal(r, xp.asarray([0.25], dtype=xp.float64)) + + x = [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6] + dx = x[1] - x[0] + newx = [-6., -5.5, -5., -4.5, -4., -3.5, -3., -2.5, -2., -1.5, -1., + -0.5, 0., 0.5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5, 5., 5.5, 6., + 6.5, 7., 7.5, 8., 8.5, 9., 9.5, 10., 10.5, 11., 11.5, 12., + 12.5] + y = xp.asarray([4.216, 6.864, 3.514, 6.203, 6.759, 7.433, 7.874, 5.879, + 1.396, 4.094]) + cj = signal.qspline1d(y) + newy = xp.asarray([6.203, 4.49418159, 3.514, 5.18390821, 6.864, 5.91436915, + 4.21600002, 5.91436915, 6.864, 5.18390821, 3.514, + 4.49418159, 6.203, 6.71900226, 6.759, 7.03980488, 7.433, + 7.81016848, 7.874, 7.32718426, 5.879, 3.23872593, 1.396, + 2.34046013, 4.094, 2.34046013, 1.396, 3.23872593, 5.879, + 7.32718426, 7.874, 7.81016848, 7.433, 7.03980488, 6.759, + 6.71900226, 6.203, 4.49418159], dtype=xp.float64) + r = signal.qspline1d_eval( + cj, xp.asarray(newx, dtype=xp.float64), dx=dx, x0=x[0] + ) + xp_assert_close(r, newy) + + with pytest.raises(ValueError, + match="Spline coefficients 'cj' must not be empty."): + signal.qspline1d_eval(xp.asarray([], dtype=xp.float64), + xp.asarray([0.0], dtype=xp.float64)) + + +# i/o dtypes with scipy 1.9.1, likely fixed by backwards compat +sepfir_dtype_map = {np.uint8: np.float32, int: np.float64, + np.float32: np.float32, float: float, + np.complex64: np.complex64, complex: complex} + + +@skip_xp_backends(np_only=True) +class TestSepfir2d: + def test_sepfir2d_invalid_filter(self, xp): + filt = xp.asarray([1.0, 2.0, 4.0, 2.0, 1.0]) + image = np.random.rand(7, 9) + image = xp.asarray(image) + # No error for odd lengths + signal.sepfir2d(image, filt, filt[2:]) + + # Row or column filter must be odd + with pytest.raises(ValueError, match="odd length"): + signal.sepfir2d(image, filt, filt[1:]) + with pytest.raises(ValueError, match="odd length"): + signal.sepfir2d(image, filt[1:], filt) + + # Filters must be 1-dimensional + with pytest.raises(ValueError, match="object too deep"): + signal.sepfir2d(image, xp.reshape(filt, (1, -1)), filt) + with pytest.raises(ValueError, match="object too deep"): + signal.sepfir2d(image, filt, xp.reshape(filt, (1, -1))) + + def test_sepfir2d_invalid_image(self, xp): + filt = xp.asarray([1.0, 2.0, 4.0, 2.0, 1.0]) + image = np.random.rand(8, 8) + image = xp.asarray(image) + + # Image must be 2 dimensional + with pytest.raises(ValueError, match="object too deep"): + signal.sepfir2d(xp.reshape(image, (4, 4, 4)), filt, filt) + + with pytest.raises(ValueError, match="object of too small depth"): + signal.sepfir2d(image[0, :], filt, filt) + + @pytest.mark.parametrize('dtyp', + [np.uint8, int, np.float32, float, np.complex64, complex] + ) + def test_simple(self, dtyp, xp): + # test values on a paper-and-pencil example + a = np.array([[1, 2, 3, 3, 2, 1], + [1, 2, 3, 3, 2, 1], + [1, 2, 3, 3, 2, 1], + [1, 2, 3, 3, 2, 1]], dtype=dtyp) + h1 = [0.5, 1, 0.5] + h2 = [1] + result = signal.sepfir2d(a, h1, h2) + dt = sepfir_dtype_map[dtyp] + expected = np.asarray([[2.5, 4. , 5.5, 5.5, 4. , 2.5], + [2.5, 4. , 5.5, 5.5, 4. , 2.5], + [2.5, 4. , 5.5, 5.5, 4. , 2.5], + [2.5, 4. , 5.5, 5.5, 4. , 2.5]], dtype=dt) + xp_assert_close(result, expected, atol=1e-16) + + result = signal.sepfir2d(a, h2, h1) + expected = np.asarray([[2., 4., 6., 6., 4., 2.], + [2., 4., 6., 6., 4., 2.], + [2., 4., 6., 6., 4., 2.], + [2., 4., 6., 6., 4., 2.]], dtype=dt) + xp_assert_close(result, expected, atol=1e-16) + + @skip_xp_backends(np_only=True, reason="TODO: convert this test") + @pytest.mark.parametrize('dtyp', + [np.uint8, int, np.float32, float, np.complex64, complex] + ) + def test_strided(self, dtyp, xp): + a = np.array([[1, 2, 3, 3, 2, 1, 1, 2, 3], + [1, 2, 3, 3, 2, 1, 1, 2, 3], + [1, 2, 3, 3, 2, 1, 1, 2, 3], + [1, 2, 3, 3, 2, 1, 1, 2, 3]]) + h1, h2 = [0.5, 1, 0.5], [1] + result_strided = signal.sepfir2d(a[:, ::2], h1, h2) + result_contig = signal.sepfir2d(a[:, ::2].copy(), h1, h2) + xp_assert_close(result_strided, result_contig, atol=1e-15) + assert result_strided.dtype == result_contig.dtype + + @skip_xp_backends(np_only=True, reason="TODO: convert this test") + @pytest.mark.xfail(reason="XXX: filt.size > image.shape: flaky") + def test_sepfir2d_strided_2(self, xp): + # XXX: this test is flaky: fails on some reruns, with + # result[0, 1] and result[1, 1] being ~1e+224. + filt = np.array([1.0, 2.0, 4.0, 2.0, 1.0, 3.0, 2.0]) + image = np.random.rand(4, 4) + + expected = np.asarray([[36.018162, 30.239061, 38.71187 , 43.878183], + [38.180999, 35.824583, 43.525247, 43.874945], + [43.269533, 40.834018, 46.757772, 44.276423], + [49.120928, 39.681844, 43.596067, 45.085854]]) + xp_assert_close(signal.sepfir2d(image, filt, filt[::3]), expected) + + @skip_xp_backends(np_only=True, reason="TODO: convert this test") + @pytest.mark.xfail(reason="XXX: flaky. pointers OOB on some platforms") + @pytest.mark.fail_asan + @pytest.mark.parametrize('dtyp', + [np.uint8, int, np.float32, float, np.complex64, complex] + ) + def test_sepfir2d_strided_3(self, dtyp, xp): + # NB: 'image' and 'filt' dtypes match here. Otherwise we can run into + # unsafe casting errors for many combinations. Historically, dtype handling + # in `sepfir2d` is a tad baroque; fixing it is an enhancement. + filt = np.array([1, 2, 4, 2, 1, 3, 2], dtype=dtyp) + image = np.asarray([[0, 3, 0, 1, 2], + [2, 2, 3, 3, 3], + [0, 1, 3, 0, 3], + [2, 3, 0, 1, 3], + [3, 3, 2, 1, 2]], dtype=dtyp) + + expected = [[123., 101., 91., 136., 127.], + [133., 125., 126., 152., 160.], + [136., 137., 150., 162., 177.], + [133., 124., 132., 148., 147.], + [173., 158., 152., 164., 141.]] + expected = np.asarray(expected) + result = signal.sepfir2d(image, filt, filt[::3]) + xp_assert_close(result, expected, atol=1e-15) + assert result.dtype == sepfir_dtype_map[dtyp] + + expected = [[22., 35., 41., 31., 47.], + [27., 39., 48., 47., 55.], + [33., 42., 49., 53., 59.], + [39., 44., 41., 36., 48.], + [67., 62., 47., 34., 46.]] + expected = np.asarray(expected) + result = signal.sepfir2d(image, filt[::3], filt[::3]) + xp_assert_close(result, expected, atol=1e-15) + assert result.dtype == sepfir_dtype_map[dtyp] + + +@make_xp_test_case(signal.cspline2d) +def test_cspline2d(xp): + rng = np.random.RandomState(181819142) + image = rng.rand(71, 73) + image = xp.asarray(image, dtype=xp_default_dtype(xp)) + result = signal.cspline2d(image, 8.0) + assert array_namespace(result) == xp + + +@make_xp_test_case(signal.qspline2d) +def test_qspline2d(xp): + rng = np.random.RandomState(181819143) + image = rng.rand(71, 73) + image = xp.asarray(image, dtype=xp_default_dtype(xp)) + result = signal.qspline2d(image) + assert array_namespace(result) == xp diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_cont2discrete.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_cont2discrete.py new file mode 100644 index 0000000000000000000000000000000000000000..c01ddab40da1793e72c06d7964757480f7a58fc7 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_cont2discrete.py @@ -0,0 +1,438 @@ +import math +import numpy as np +from scipy._lib._array_api import ( + assert_array_almost_equal, xp_assert_close, + make_xp_test_case +) + +import pytest +from scipy.signal import cont2discrete as c2d +from scipy.signal import dlsim, ss2tf, ss2zpk, lsim, lti +from scipy.signal import tf2ss, impulse, dimpulse, step, dstep + +# Author: Jeffrey Armstrong +# March 29, 2011 + +skip_xp_backends = pytest.mark.skip_xp_backends + + +@make_xp_test_case(c2d) +class TestC2D: + def test_zoh(self, xp): + ac = xp.eye(2, dtype=xp.float64) + bc = xp.full((2, 1), 0.5, dtype=xp.float64) + cc = xp.asarray([[0.75, 1.0], [1.0, 1.0], [1.0, 0.25]]) + dc = xp.asarray([[0.0], [0.0], [-0.33]]) + + ad_truth = 1.648721270700128 * xp.eye(2) + bd_truth = xp.full((2, 1), 0.324360635350064) + # c and d in discrete should be equal to their continuous counterparts + dt_requested = 0.5 + + ad, bd, cd, dd, dt = c2d((ac, bc, cc, dc), dt_requested, method='zoh') + + assert_array_almost_equal(ad_truth, ad) + assert_array_almost_equal(bd_truth, bd) + assert_array_almost_equal(cc, cd) + assert_array_almost_equal(dc, dd) + assert math.isclose(dt, dt_requested, abs_tol=1e-14) + + def test_foh(self, xp): + ac = xp.eye(2) + bc = xp.full((2, 1), 0.5) + cc = xp.asarray([[0.75, 1.0], [1.0, 1.0], [1.0, 0.25]]) + dc = xp.asarray([[0.0], [0.0], [-0.33]]) + + # True values are verified with Matlab + ad_truth = 1.648721270700128 * xp.eye(2) + bd_truth = xp.full((2, 1), 0.420839287058789) + cd_truth = cc + dd_truth = xp.asarray([[0.260262223725224], + [0.297442541400256], + [-0.144098411624840]]) + dt_requested = 0.5 + + ad, bd, cd, dd, dt = c2d((ac, bc, cc, dc), dt_requested, method='foh') + + assert_array_almost_equal(ad_truth, ad) + assert_array_almost_equal(bd_truth, bd) + assert_array_almost_equal(cd_truth, cd) + assert_array_almost_equal(dd_truth, dd) + assert math.isclose(dt, dt_requested, abs_tol=1e-14) + + def test_impulse(self, xp): + ac = xp.eye(2) + bc = xp.full((2, 1), 0.5) + cc = xp.asarray([[0.75, 1.0], [1.0, 1.0], [1.0, 0.25]]) + dc = xp.asarray([[0.0], [0.0], [0.0]]) + + # True values are verified with Matlab + ad_truth = 1.648721270700128 * xp.eye(2) + bd_truth = xp.full((2, 1), 0.412180317675032) + cd_truth = cc + dd_truth = xp.asarray([[0.4375], [0.5], [0.3125]]) + dt_requested = 0.5 + + ad, bd, cd, dd, dt = c2d((ac, bc, cc, dc), dt_requested, + method='impulse') + + assert_array_almost_equal(ad_truth, ad) + assert_array_almost_equal(bd_truth, bd) + assert_array_almost_equal(cd_truth, cd) + assert_array_almost_equal(dd_truth, dd) + assert math.isclose(dt, dt_requested, abs_tol=1e-14) + + def test_gbt(self, xp): + ac = xp.eye(2) + bc = xp.full((2, 1), 0.5) + cc = xp.asarray([[0.75, 1.0], [1.0, 1.0], [1.0, 0.25]]) + dc = xp.asarray([[0.0], [0.0], [-0.33]]) + + dt_requested = 0.5 + alpha = 1.0 / 3.0 + + ad_truth = 1.6 * xp.eye(2) + bd_truth = xp.full((2, 1), 0.3) + cd_truth = xp.asarray([[0.9, 1.2], + [1.2, 1.2], + [1.2, 0.3]]) + dd_truth = xp.asarray([[0.175], + [0.2], + [-0.205]]) + + ad, bd, cd, dd, dt = c2d((ac, bc, cc, dc), dt_requested, + method='gbt', alpha=alpha) + + assert_array_almost_equal(ad_truth, ad) + assert_array_almost_equal(bd_truth, bd) + assert_array_almost_equal(cd_truth, cd) + assert_array_almost_equal(dd_truth, dd) + + def test_euler(self, xp): + ac = xp.eye(2) + bc = xp.full((2, 1), 0.5) + cc = xp.asarray([[0.75, 1.0], [1.0, 1.0], [1.0, 0.25]]) + dc = xp.asarray([[0.0], [0.0], [-0.33]]) + + dt_requested = 0.5 + + ad_truth = 1.5 * xp.eye(2) + bd_truth = xp.full((2, 1), 0.25) + cd_truth = xp.asarray([[0.75, 1.0], + [1.0, 1.0], + [1.0, 0.25]]) + dd_truth = dc + + ad, bd, cd, dd, dt = c2d((ac, bc, cc, dc), dt_requested, + method='euler') + + assert_array_almost_equal(ad_truth, ad) + assert_array_almost_equal(bd_truth, bd) + assert_array_almost_equal(cd_truth, cd) + assert_array_almost_equal(dd_truth, dd) + assert math.isclose(dt, dt_requested, abs_tol=1e-14) + + def test_backward_diff(self, xp): + ac = xp.eye(2) + bc = xp.full((2, 1), 0.5) + cc = xp.asarray([[0.75, 1.0], [1.0, 1.0], [1.0, 0.25]]) + dc = xp.asarray([[0.0], [0.0], [-0.33]]) + + dt_requested = 0.5 + + ad_truth = 2.0 * xp.eye(2) + bd_truth = xp.full((2, 1), 0.5) + cd_truth = xp.asarray([[1.5, 2.0], + [2.0, 2.0], + [2.0, 0.5]]) + dd_truth = xp.asarray([[0.875], + [1.0], + [0.295]]) + + ad, bd, cd, dd, dt = c2d((ac, bc, cc, dc), dt_requested, + method='backward_diff') + + assert_array_almost_equal(ad_truth, ad) + assert_array_almost_equal(bd_truth, bd) + assert_array_almost_equal(cd_truth, cd) + assert_array_almost_equal(dd_truth, dd) + + def test_bilinear(self, xp): + ac = xp.eye(2) + bc = xp.full((2, 1), 0.5) + cc = xp.asarray([[0.75, 1.0], [1.0, 1.0], [1.0, 0.25]]) + dc = xp.asarray([[0.0], [0.0], [-0.33]]) + + dt_requested = 0.5 + + ad_truth = (5.0 / 3.0) * xp.eye(2) + bd_truth = xp.full((2, 1), 1.0 / 3.0) + cd_truth = xp.asarray([[1.0, 4.0 / 3.0], + [4.0 / 3.0, 4.0 / 3.0], + [4.0 / 3.0, 1.0 / 3.0]]) + dd_truth = xp.asarray([[0.291666666666667], + [1.0 / 3.0], + [-0.121666666666667]]) + + ad, bd, cd, dd, dt = c2d((ac, bc, cc, dc), dt_requested, + method='bilinear') + + assert_array_almost_equal(ad_truth, ad) + assert_array_almost_equal(bd_truth, bd) + assert_array_almost_equal(cd_truth, cd) + assert_array_almost_equal(dd_truth, dd) + assert math.isclose(dt, dt_requested, abs_tol=1e-14) + + # Same continuous system again, but change sampling rate + + ad_truth = 1.4 * xp.eye(2) + bd_truth = xp.full((2, 1), 0.2) + cd_truth = xp.asarray([[0.9, 1.2], [1.2, 1.2], [1.2, 0.3]]) + dd_truth = xp.asarray([[0.175], [0.2], [-0.205]]) + + dt_requested = 1.0 / 3.0 + + ad, bd, cd, dd, dt = c2d((ac, bc, cc, dc), dt_requested, + method='bilinear') + + assert_array_almost_equal(ad_truth, ad) + assert_array_almost_equal(bd_truth, bd) + assert_array_almost_equal(cd_truth, cd) + assert_array_almost_equal(dd_truth, dd) + assert math.isclose(dt_requested, dt) + + def test_transferfunction(self, xp): + numc = xp.asarray([0.25, 0.25, 0.5]) + denc = xp.asarray([0.75, 0.75, 1.0]) + + numd = xp.asarray([[1.0 / 3.0, -0.427419169438754, 0.221654141101125]]) + dend = xp.asarray([1.0, -1.351394049721225, 0.606530659712634]) + + dt_requested = 0.5 + + num, den, dt = c2d((numc, denc), dt_requested, method='zoh') + + assert_array_almost_equal(numd, num) + assert_array_almost_equal(dend, den) + assert math.isclose(dt_requested, dt) + + def test_zerospolesgain(self, xp): + zeros_c = xp.array([0.5, -0.5]) + poles_c = xp.array([1.j / xp.sqrt(2), -1.j / xp.sqrt(2)]) + k_c = 1.0 + + zeros_d = xp.asarray([1.23371727305860, 0.735356894461267]) + polls_d = xp.asarray([0.938148335039729 + 0.346233593780536j, + 0.938148335039729 - 0.346233593780536j]) + k_d = 1.0 + + dt_requested = 0.5 + + zeros, poles, k, dt = c2d((zeros_c, poles_c, k_c), dt_requested, + method='zoh') + + assert_array_almost_equal(zeros_d, zeros) + assert_array_almost_equal(polls_d, poles) + assert math.isclose(k_d, k) + assert math.isclose(dt_requested, dt) + + @skip_xp_backends(np_only=True) + def test_gbt_with_sio_tf_and_zpk(self, xp): + """Test method='gbt' with alpha=0.25 for tf and zpk cases.""" + # State space coefficients for the continuous SIO system. + A = -1.0 + B = 1.0 + C = 1.0 + D = 0.5 + + # The continuous transfer function coefficients. + cnum, cden = ss2tf(A, B, C, D) + + # Continuous zpk representation + cz, cp, ck = ss2zpk(A, B, C, D) + + h = 1.0 + alpha = 0.25 + + # Explicit formulas, in the scalar case. + Ad = (1 + (1 - alpha) * h * A) / (1 - alpha * h * A) + Bd = h * B / (1 - alpha * h * A) + Cd = C / (1 - alpha * h * A) + Dd = D + alpha * C * Bd + + # Convert the explicit solution to tf + dnum, dden = ss2tf(Ad, Bd, Cd, Dd) + + # Compute the discrete tf using cont2discrete. + c2dnum, c2dden, dt = c2d((cnum, cden), h, method='gbt', alpha=alpha) + + xp_assert_close(dnum, c2dnum) + xp_assert_close(dden, c2dden) + + # Convert explicit solution to zpk. + dz, dp, dk = ss2zpk(Ad, Bd, Cd, Dd) + + # Compute the discrete zpk using cont2discrete. + c2dz, c2dp, c2dk, dt = c2d((cz, cp, ck), h, method='gbt', alpha=alpha) + + xp_assert_close(dz, c2dz) + xp_assert_close(dp, c2dp) + xp_assert_close(dk, c2dk) + + def test_discrete_approx(self, xp): + """ + Test that the solution to the discrete approximation of a continuous + system actually approximates the solution to the continuous system. + This is an indirect test of the correctness of the implementation + of cont2discrete. + """ + + def u(t): + return xp.sin(2.5 * t) + + a = xp.asarray([[-0.01]]) + b = xp.asarray([[1.0]]) + c = xp.asarray([[1.0]]) + d = xp.asarray([[0.2]]) + x0 = 1.0 + + t = xp.linspace(0, 10.0, 101) + dt = t[1] - t[0] + u1 = u(t) + + # Use lsim to compute the solution to the continuous system. + t, yout, xout = lsim((a, b, c, d), T=t, U=u1, X0=x0) + + # Convert the continuous system to a discrete approximation. + dsys = c2d((a, b, c, d), dt, method='bilinear') + + # Use dlsim with the pairwise averaged input to compute the output + # of the discrete system. + u2 = 0.5 * (u1[:-1] + u1[1:]) + t2 = t[:-1] + td2, yd2, xd2 = dlsim(dsys, u=u2.reshape(-1, 1), t=t2, x0=x0) + + # ymid is the average of consecutive terms of the "exact" output + # computed by lsim2. This is what the discrete approximation + # actually approximates. + ymid = 0.5 * (yout[:-1] + yout[1:]) + + xp_assert_close(yd2.ravel(), ymid, rtol=1e-4) + + @skip_xp_backends(np_only=True) + def test_simo_tf(self): + # See gh-5753 + tf = ([[1, 0], [1, 1]], [1, 1]) + num, den, dt = c2d(tf, 0.01) + + assert dt == 0.01 # sanity check + xp_assert_close(den, [1, -0.990404983], rtol=1e-3) + xp_assert_close(num, [[1, -1], [1, -0.99004983]], rtol=1e-3) + + @skip_xp_backends(np_only=True) + def test_multioutput(self): + ts = 0.01 # time step + + tf = ([[1, -3], [1, 5]], [1, 1]) + num, den, dt = c2d(tf, ts) + + tf1 = (tf[0][0], tf[1]) + num1, den1, dt1 = c2d(tf1, ts) + + tf2 = (tf[0][1], tf[1]) + num2, den2, dt2 = c2d(tf2, ts) + + # Sanity checks + assert dt == dt1 + assert dt == dt2 + + # Check that we get the same results + xp_assert_close(num, np.vstack((num1, num2)), rtol=1e-13) + + # Single input, so the denominator should + # not be multidimensional like the numerator + xp_assert_close(den, den1, rtol=1e-13) + xp_assert_close(den, den2, rtol=1e-13) + +@skip_xp_backends(np_only=True, reason="lti currently not supported") +class TestC2dLti: + def test_c2d_ss(self, xp): + # StateSpace + A = np.array([[-0.3, 0.1], [0.2, -0.7]]) + B = np.array([[0], [1]]) + C = np.array([[1, 0]]) + D = 0 + dt = 0.05 + + A_res = np.array([[0.985136404135682, 0.004876671474795], + [0.009753342949590, 0.965629718236502]]) + B_res = np.array([[0.000122937599964], [0.049135527547844]]) + + sys_ssc = lti(A, B, C, D) + sys_ssd = sys_ssc.to_discrete(dt=dt) + + xp_assert_close(sys_ssd.A, A_res) + xp_assert_close(sys_ssd.B, B_res) + xp_assert_close(sys_ssd.C, C) + xp_assert_close(sys_ssd.D, np.zeros_like(sys_ssd.D)) + + sys_ssd2 = c2d(sys_ssc, dt=dt) + + xp_assert_close(sys_ssd2.A, A_res) + xp_assert_close(sys_ssd2.B, B_res) + xp_assert_close(sys_ssd2.C, C) + xp_assert_close(sys_ssd2.D, np.zeros_like(sys_ssd2.D)) + + def test_c2d_tf(self, xp): + + sys = lti([0.5, 0.3], [1.0, 0.4]) + sys = sys.to_discrete(0.005) + + # Matlab results + num_res = np.array([0.5, -0.485149004980066]) + den_res = np.array([1.0, -0.980198673306755]) + + # Somehow a lot of numerical errors + xp_assert_close(sys.den, den_res, atol=0.02) + xp_assert_close(sys.num, num_res, atol=0.02) + + +@make_xp_test_case(c2d) +class TestC2dInvariants: + # Some test cases for checking the invariances. + # Array of triplets: (system, sample time, number of samples) + cases = [ + (tf2ss([1, 1], [1, 1.5, 1]), 0.25, 10), + (tf2ss([1, 2], [1, 1.5, 3, 1]), 0.5, 10), + (tf2ss(0.1, [1, 1, 2, 1]), 0.5, 10), + ] + + # Check that systems discretized with the impulse-invariant + # method really hold the invariant + @make_xp_test_case(impulse, dimpulse) + @pytest.mark.parametrize("sys,sample_time,samples_number", cases) + def test_impulse_invariant(self, xp, sys, sample_time, samples_number): + sys = tuple(map(xp.asarray, sys)) + time = xp.arange(samples_number) * sample_time + _, yout_cont = impulse(sys, T=time) + _, yout_disc = dimpulse(c2d(sys, sample_time, method='impulse'), + n=len(time)) + xp_assert_close(sample_time * yout_cont.ravel(), yout_disc[0].ravel()) + + # Step invariant should hold for ZOH discretized systems + @pytest.mark.parametrize("sys,sample_time,samples_number", cases) + def test_step_invariant(self, xp, sys, sample_time, samples_number): + sys = tuple(map(xp.asarray, sys)) + time = xp.arange(samples_number) * sample_time + _, yout_cont = step(sys, T=time) + _, yout_disc = dstep(c2d(sys, sample_time, method='zoh'), n=len(time)) + xp_assert_close(yout_cont.ravel(), yout_disc[0].ravel()) + + # Linear invariant should hold for FOH discretized systems + @pytest.mark.parametrize("sys,sample_time,samples_number", cases) + def test_linear_invariant(self, xp, sys, sample_time, samples_number): + sys = tuple(map(xp.asarray, sys)) + time = xp.arange(samples_number) * sample_time + _, yout_cont, _ = lsim(sys, T=time, U=time) + _, yout_disc, _ = dlsim(c2d(sys, sample_time, method='foh'), u=time) + xp_assert_close(yout_cont.ravel(), yout_disc.ravel()) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_czt.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_czt.py new file mode 100644 index 0000000000000000000000000000000000000000..35087d99fec5057131f0735d43e0faa33a74ef82 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_czt.py @@ -0,0 +1,221 @@ +# This program is public domain +# Authors: Paul Kienzle, Nadav Horesh +''' +A unit test module for czt.py +''' +import pytest +from scipy._lib._array_api import xp_assert_close +from scipy.fft import fft +from scipy.signal import (czt, zoom_fft, czt_points, CZT, ZoomFFT) +import numpy as np + + +def check_czt(x): + # Check that czt is the equivalent of normal fft + y = fft(x) + y1 = czt(x) + xp_assert_close(y1, y, rtol=1e-13) + + # Check that interpolated czt is the equivalent of normal fft + y = fft(x, 100*len(x)) + y1 = czt(x, 100*len(x)) + xp_assert_close(y1, y, rtol=1e-12) + + +def check_zoom_fft(x): + # Check that zoom_fft is the equivalent of normal fft + y = fft(x) + y1 = zoom_fft(x, [0, 2-2./len(y)], endpoint=True) + xp_assert_close(y1, y, rtol=1e-11, atol=1e-14) + y1 = zoom_fft(x, [0, 2]) + xp_assert_close(y1, y, rtol=1e-11, atol=1e-14) + + # Test fn scalar + y1 = zoom_fft(x, 2-2./len(y), endpoint=True) + xp_assert_close(y1, y, rtol=1e-11, atol=1e-14) + y1 = zoom_fft(x, 2) + xp_assert_close(y1, y, rtol=1e-11, atol=1e-14) + + # Check that zoom_fft with oversampling is equivalent to zero padding + over = 10 + yover = fft(x, over*len(x)) + y2 = zoom_fft(x, [0, 2-2./len(yover)], m=len(yover), endpoint=True) + xp_assert_close(y2, yover, rtol=1e-12, atol=1e-10) + y2 = zoom_fft(x, [0, 2], m=len(yover)) + xp_assert_close(y2, yover, rtol=1e-12, atol=1e-10) + + # Check that zoom_fft works on a subrange + w = np.linspace(0, 2-2./len(x), len(x)) + f1, f2 = w[3], w[6] + y3 = zoom_fft(x, [f1, f2], m=3*over+1, endpoint=True) + idx3 = slice(3*over, 6*over+1) + xp_assert_close(y3, yover[idx3], rtol=1e-13) + + +def test_1D(): + # Test of 1D version of the transforms + + rng = np.random.RandomState(0) # Deterministic randomness + + # Random signals + lengths = rng.randint(8, 200, 20) + np.append(lengths, 1) + for length in lengths: + x = rng.random(length) + check_zoom_fft(x) + check_czt(x) + + # Gauss + t = np.linspace(-2, 2, 128) + x = np.exp(-t**2/0.01) + check_zoom_fft(x) + + # Linear + x = [1, 2, 3, 4, 5, 6, 7] + check_zoom_fft(x) + + # Check near powers of two + check_zoom_fft(range(126-31)) + check_zoom_fft(range(127-31)) + check_zoom_fft(range(128-31)) + check_zoom_fft(range(129-31)) + check_zoom_fft(range(130-31)) + + # Check transform on n-D array input + x = np.reshape(np.arange(3*2*28), (3, 2, 28)) + y1 = zoom_fft(x, [0, 2-2./28]) + y2 = zoom_fft(x[2, 0, :], [0, 2-2./28]) + xp_assert_close(y1[2, 0], y2, rtol=1e-13, atol=1e-12) + + y1 = zoom_fft(x, [0, 2], endpoint=False) + y2 = zoom_fft(x[2, 0, :], [0, 2], endpoint=False) + xp_assert_close(y1[2, 0], y2, rtol=1e-13, atol=1e-12) + + # Random (not a test condition) + x = rng.rand(101) + check_zoom_fft(x) + + # Spikes + t = np.linspace(0, 1, 128) + x = np.sin(2*np.pi*t*5)+np.sin(2*np.pi*t*13) + check_zoom_fft(x) + + # Sines + x = np.zeros(100, dtype=complex) + x[[1, 5, 21]] = 1 + check_zoom_fft(x) + + # Sines plus complex component + x += 1j*np.linspace(0, 0.5, x.shape[0]) + check_zoom_fft(x) + + +def test_large_prime_lengths(): + rng = np.random.RandomState(0) # Deterministic randomness + for N in (101, 1009, 10007): + x = rng.rand(N) + y = fft(x) + y1 = czt(x) + xp_assert_close(y, y1, rtol=1e-12) + + +@pytest.mark.slow +def test_czt_vs_fft(): + rng = np.random.RandomState(123) # Deterministic randomness + random_lengths = rng.exponential(100000, size=10).astype('int') + for n in random_lengths: + a = rng.randn(n) + xp_assert_close(czt(a), fft(a), rtol=1e-11) + + +def test_empty_input(): + with pytest.raises(ValueError, match='Invalid number of CZT'): + czt([]) + with pytest.raises(ValueError, match='Invalid number of CZT'): + zoom_fft([], 0.5) + + +def test_0_rank_input(): + with pytest.raises(IndexError, match='tuple index out of range'): + czt(5) + with pytest.raises(IndexError, match='tuple index out of range'): + zoom_fft(5, 0.5) + + +@pytest.mark.parametrize('impulse', ([0, 0, 1], [0, 0, 1, 0, 0], + np.concatenate((np.array([0, 0, 1]), + np.zeros(100))))) +@pytest.mark.parametrize('m', (1, 3, 5, 8, 101, 1021)) +@pytest.mark.parametrize('a', (1, 2, 0.5, 1.1)) +# Step that tests away from the unit circle, but not so far it explodes from +# numerical error +@pytest.mark.parametrize('w', (None, 0.98534 + 0.17055j)) +def test_czt_math(impulse, m, w, a): + # z-transform of an impulse is 1 everywhere + xp_assert_close(czt(impulse[2:], m=m, w=w, a=a), + np.ones(m, dtype=np.complex128), rtol=1e-10) + + # z-transform of a delayed impulse is z**-1 + xp_assert_close(czt(impulse[1:], m=m, w=w, a=a), + czt_points(m=m, w=w, a=a)**-1, rtol=1e-10) + + # z-transform of a 2-delayed impulse is z**-2 + xp_assert_close(czt(impulse, m=m, w=w, a=a), + czt_points(m=m, w=w, a=a)**-2, rtol=1e-10) + + +def test_int_args(): + # Integer argument `a` was producing all 0s + xp_assert_close(abs(czt([0, 1], m=10, a=2)), 0.5*np.ones(10), rtol=1e-15) + xp_assert_close(czt_points(11, w=2), + 1/(2**np.arange(11, dtype=np.complex128)), rtol=1e-30) + + +def test_czt_points(): + for N in (1, 2, 3, 8, 11, 100, 101, 10007): + xp_assert_close(czt_points(N), np.exp(2j*np.pi*np.arange(N)/N), + rtol=1e-30) + + xp_assert_close(czt_points(7, w=1), np.ones(7, dtype=np.complex128), rtol=1e-30) + xp_assert_close(czt_points(11, w=2.), + 1/(2**np.arange(11, dtype=np.complex128)), rtol=1e-30) + + func = CZT(12, m=11, w=2., a=1) + xp_assert_close(func.points(), 1/(2**np.arange(11)), rtol=1e-30) + + +@pytest.mark.parametrize('cls, args', [(CZT, (100,)), (ZoomFFT, (100, 0.2))]) +def test_CZT_size_mismatch(cls, args): + # Data size doesn't match function's expected size + myfunc = cls(*args) + with pytest.raises(ValueError, match='CZT defined for'): + myfunc(np.arange(5)) + + +def test_invalid_range(): + with pytest.raises(ValueError, match='2-length sequence'): + ZoomFFT(100, [1, 2, 3]) + + +@pytest.mark.parametrize('m', [0, -11, 5.5, 4.0]) +def test_czt_points_errors(m): + # Invalid number of points + with pytest.raises(ValueError, match='Invalid number of CZT'): + czt_points(m) + + +@pytest.mark.parametrize('size', [0, -5, 3.5, 4.0]) +def test_nonsense_size(size): + # Numpy and Scipy fft() give ValueError for 0 output size, so we do, too + with pytest.raises(ValueError, match='Invalid number of CZT'): + CZT(size, 3) + with pytest.raises(ValueError, match='Invalid number of CZT'): + ZoomFFT(size, 0.2, 3) + with pytest.raises(ValueError, match='Invalid number of CZT'): + CZT(3, size) + with pytest.raises(ValueError, match='Invalid number of CZT'): + ZoomFFT(3, 0.2, size) + with pytest.raises(ValueError, match='Invalid number of CZT'): + czt([1, 2, 3], size) + with pytest.raises(ValueError, match='Invalid number of CZT'): + zoom_fft([1, 2, 3], 0.2, size) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_dltisys.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_dltisys.py new file mode 100644 index 0000000000000000000000000000000000000000..d18313c34b6a261fd688fa913971f94667c7f5cb --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_dltisys.py @@ -0,0 +1,601 @@ +# Author: Jeffrey Armstrong +# April 4, 2011 +import warnings + +import numpy as np +from pytest import raises as assert_raises +from scipy._lib._array_api import ( + assert_array_almost_equal, assert_almost_equal, xp_assert_close, xp_assert_equal, +) + +from scipy.signal import (dlsim, dstep, dimpulse, tf2zpk, lti, dlti, + StateSpace, TransferFunction, ZerosPolesGain, + dfreqresp, dbode, BadCoefficients) + + +class TestDLTI: + + def test_dlsim(self): + + a = np.asarray([[0.9, 0.1], [-0.2, 0.9]]) + b = np.asarray([[0.4, 0.1, -0.1], [0.0, 0.05, 0.0]]) + c = np.asarray([[0.1, 0.3]]) + d = np.asarray([[0.0, -0.1, 0.0]]) + dt = 0.5 + + # Create an input matrix with inputs down the columns (3 cols) and its + # respective time input vector + u = np.hstack((np.linspace(0, 4.0, num=5)[:, np.newaxis], + np.full((5, 1), 0.01), + np.full((5, 1), -0.002))) + t_in = np.linspace(0, 2.0, num=5) + + # Define the known result + yout_truth = np.array([[-0.001, + -0.00073, + 0.039446, + 0.0915387, + 0.13195948]]).T + xout_truth = np.asarray([[0, 0], + [0.0012, 0.0005], + [0.40233, 0.00071], + [1.163368, -0.079327], + [2.2402985, -0.3035679]]) + + tout, yout, xout = dlsim((a, b, c, d, dt), u, t_in) + + assert_array_almost_equal(yout_truth, yout) + assert_array_almost_equal(xout_truth, xout) + assert_array_almost_equal(t_in, tout) + + # Make sure input with single-dimension doesn't raise error + dlsim((1, 2, 3), 4) + + # Interpolated control - inputs should have different time steps + # than the discrete model uses internally + u_sparse = u[[0, 4], :] + t_sparse = np.asarray([0.0, 2.0]) + + tout, yout, xout = dlsim((a, b, c, d, dt), u_sparse, t_sparse) + + assert_array_almost_equal(yout_truth, yout) + assert_array_almost_equal(xout_truth, xout) + assert len(tout) == len(yout) + + # Transfer functions (assume dt = 0.5) + num = np.asarray([1.0, -0.1]) + den = np.asarray([0.3, 1.0, 0.2]) + yout_truth = np.array([[0.0, + 0.0, + 3.33333333333333, + -4.77777777777778, + 23.0370370370370]]).T + + # Assume use of the first column of the control input built earlier + tout, yout = dlsim((num, den, 0.5), u[:, 0], t_in) + + assert_array_almost_equal(yout, yout_truth) + assert_array_almost_equal(t_in, tout) + + # Retest the same with a 1-D input vector + uflat = np.asarray(u[:, 0]) + uflat = uflat.reshape((5,)) + tout, yout = dlsim((num, den, 0.5), uflat, t_in) + + assert_array_almost_equal(yout, yout_truth) + assert_array_almost_equal(t_in, tout) + + # zeros-poles-gain representation + zd = np.array([0.5, -0.5]) + pd = np.array([1.j / np.sqrt(2), -1.j / np.sqrt(2)]) + k = 1.0 + yout_truth = np.array([[0.0, 1.0, 2.0, 2.25, 2.5]]).T + + tout, yout = dlsim((zd, pd, k, 0.5), u[:, 0], t_in) + + assert_array_almost_equal(yout, yout_truth) + assert_array_almost_equal(t_in, tout) + + # Raise an error for continuous-time systems + system = lti([1], [1, 1]) + assert_raises(AttributeError, dlsim, system, u) + + def test_dstep(self): + + a = np.asarray([[0.9, 0.1], [-0.2, 0.9]]) + b = np.asarray([[0.4, 0.1, -0.1], [0.0, 0.05, 0.0]]) + c = np.asarray([[0.1, 0.3]]) + d = np.asarray([[0.0, -0.1, 0.0]]) + dt = 0.5 + + # Because b.shape[1] == 3, dstep should result in a tuple of three + # result vectors + yout_step_truth = (np.asarray([0.0, 0.04, 0.052, 0.0404, 0.00956, + -0.036324, -0.093318, -0.15782348, + -0.226628324, -0.2969374948]), + np.asarray([-0.1, -0.075, -0.058, -0.04815, + -0.04453, -0.0461895, -0.0521812, + -0.061588875, -0.073549579, + -0.08727047595]), + np.asarray([0.0, -0.01, -0.013, -0.0101, -0.00239, + 0.009081, 0.0233295, 0.03945587, + 0.056657081, 0.0742343737])) + + tout, yout = dstep((a, b, c, d, dt), n=10) + + assert len(yout) == 3 + + for i in range(0, len(yout)): + assert yout[i].shape[0] == 10 + assert_array_almost_equal(yout[i].flatten(), yout_step_truth[i]) + + # Check that the other two inputs (tf, zpk) will work as well + tfin = ([1.0], [1.0, 1.0], 0.5) + yout_tfstep = np.asarray([0.0, 1.0, 0.0]) + tout, yout = dstep(tfin, n=3) + assert len(yout) == 1 + assert_array_almost_equal(yout[0].flatten(), yout_tfstep) + + zpkin = tf2zpk(tfin[0], tfin[1]) + (0.5,) + tout, yout = dstep(zpkin, n=3) + assert len(yout) == 1 + assert_array_almost_equal(yout[0].flatten(), yout_tfstep) + + # Raise an error for continuous-time systems + system = lti([1], [1, 1]) + assert_raises(AttributeError, dstep, system) + + def test_dimpulse(self): + + a = np.asarray([[0.9, 0.1], [-0.2, 0.9]]) + b = np.asarray([[0.4, 0.1, -0.1], [0.0, 0.05, 0.0]]) + c = np.asarray([[0.1, 0.3]]) + d = np.asarray([[0.0, -0.1, 0.0]]) + dt = 0.5 + + # Because b.shape[1] == 3, dimpulse should result in a tuple of three + # result vectors + yout_imp_truth = (np.asarray([0.0, 0.04, 0.012, -0.0116, -0.03084, + -0.045884, -0.056994, -0.06450548, + -0.068804844, -0.0703091708]), + np.asarray([-0.1, 0.025, 0.017, 0.00985, 0.00362, + -0.0016595, -0.0059917, -0.009407675, + -0.011960704, -0.01372089695]), + np.asarray([0.0, -0.01, -0.003, 0.0029, 0.00771, + 0.011471, 0.0142485, 0.01612637, + 0.017201211, 0.0175772927])) + + tout, yout = dimpulse((a, b, c, d, dt), n=10) + + assert len(yout) == 3 + + for i in range(0, len(yout)): + assert yout[i].shape[0] == 10 + assert_array_almost_equal(yout[i].flatten(), yout_imp_truth[i]) + + # Check that the other two inputs (tf, zpk) will work as well + tfin = ([1.0], [1.0, 1.0], 0.5) + yout_tfimpulse = np.asarray([0.0, 1.0, -1.0]) + tout, yout = dimpulse(tfin, n=3) + assert len(yout) == 1 + assert_array_almost_equal(yout[0].flatten(), yout_tfimpulse) + + zpkin = tf2zpk(tfin[0], tfin[1]) + (0.5,) + tout, yout = dimpulse(zpkin, n=3) + assert len(yout) == 1 + assert_array_almost_equal(yout[0].flatten(), yout_tfimpulse) + + # Raise an error for continuous-time systems + system = lti([1], [1, 1]) + assert_raises(AttributeError, dimpulse, system) + + def test_dlsim_trivial(self): + a = np.array([[0.0]]) + b = np.array([[0.0]]) + c = np.array([[0.0]]) + d = np.array([[0.0]]) + n = 5 + u = np.zeros(n).reshape(-1, 1) + tout, yout, xout = dlsim((a, b, c, d, 1), u) + xp_assert_equal(tout, np.arange(float(n))) + xp_assert_equal(yout, np.zeros((n, 1))) + xp_assert_equal(xout, np.zeros((n, 1))) + + def test_dlsim_simple1d(self): + a = np.array([[0.5]]) + b = np.array([[0.0]]) + c = np.array([[1.0]]) + d = np.array([[0.0]]) + n = 5 + u = np.zeros(n).reshape(-1, 1) + tout, yout, xout = dlsim((a, b, c, d, 1), u, x0=1) + xp_assert_equal(tout, np.arange(float(n))) + expected = (0.5 ** np.arange(float(n))).reshape(-1, 1) + xp_assert_equal(yout, expected) + xp_assert_equal(xout, expected) + + def test_dlsim_simple2d(self): + lambda1 = 0.5 + lambda2 = 0.25 + a = np.array([[lambda1, 0.0], + [0.0, lambda2]]) + b = np.array([[0.0], + [0.0]]) + c = np.array([[1.0, 0.0], + [0.0, 1.0]]) + d = np.array([[0.0], + [0.0]]) + n = 5 + u = np.zeros(n).reshape(-1, 1) + tout, yout, xout = dlsim((a, b, c, d, 1), u, x0=1) + xp_assert_equal(tout, np.arange(float(n))) + # The analytical solution: + expected = (np.array([lambda1, lambda2]) ** + np.arange(float(n)).reshape(-1, 1)) + xp_assert_equal(yout, expected) + xp_assert_equal(xout, expected) + + def test_more_step_and_impulse(self): + lambda1 = 0.5 + lambda2 = 0.75 + a = np.array([[lambda1, 0.0], + [0.0, lambda2]]) + b = np.array([[1.0, 0.0], + [0.0, 1.0]]) + c = np.array([[1.0, 1.0]]) + d = np.array([[0.0, 0.0]]) + + n = 10 + + # Check a step response. + ts, ys = dstep((a, b, c, d, 1), n=n) + + # Create the exact step response. + stp0 = (1.0 / (1 - lambda1)) * (1.0 - lambda1 ** np.arange(n)) + stp1 = (1.0 / (1 - lambda2)) * (1.0 - lambda2 ** np.arange(n)) + + xp_assert_close(ys[0][:, 0], stp0) + xp_assert_close(ys[1][:, 0], stp1) + + # Check an impulse response with an initial condition. + x0 = np.array([1.0, 1.0]) + ti, yi = dimpulse((a, b, c, d, 1), n=n, x0=x0) + + # Create the exact impulse response. + imp = (np.array([lambda1, lambda2]) ** + np.arange(-1, n + 1).reshape(-1, 1)) + imp[0, :] = 0.0 + # Analytical solution to impulse response + y0 = imp[:n, 0] + np.dot(imp[1:n + 1, :], x0) + y1 = imp[:n, 1] + np.dot(imp[1:n + 1, :], x0) + + xp_assert_close(yi[0][:, 0], y0) + xp_assert_close(yi[1][:, 0], y1) + + # Check that dt=0.1, n=3 gives 3 time values. + system = ([1.0], [1.0, -0.5], 0.1) + t, (y,) = dstep(system, n=3) + xp_assert_close(t, [0, 0.1, 0.2]) + xp_assert_equal(y.T, [[0, 1.0, 1.5]]) + t, (y,) = dimpulse(system, n=3) + xp_assert_close(t, [0, 0.1, 0.2]) + xp_assert_equal(y.T, [[0, 1, 0.5]]) + + +class TestDlti: + def test_dlti_instantiation(self): + # Test that lti can be instantiated. + + dt = 0.05 + # TransferFunction + s = dlti([1], [-1], dt=dt) + assert isinstance(s, TransferFunction) + assert isinstance(s, dlti) + assert not isinstance(s, lti) + assert s.dt == dt + + # ZerosPolesGain + s = dlti(np.array([]), np.array([-1]), 1, dt=dt) + assert isinstance(s, ZerosPolesGain) + assert isinstance(s, dlti) + assert not isinstance(s, lti) + assert s.dt == dt + + # StateSpace + s = dlti([1], [-1], 1, 3, dt=dt) + assert isinstance(s, StateSpace) + assert isinstance(s, dlti) + assert not isinstance(s, lti) + assert s.dt == dt + + # Number of inputs + assert_raises(ValueError, dlti, 1) + assert_raises(ValueError, dlti, 1, 1, 1, 1, 1) + + +class TestStateSpaceDisc: + def test_initialization(self): + # Check that all initializations work + dt = 0.05 + StateSpace(1, 1, 1, 1, dt=dt) + StateSpace([1], [2], [3], [4], dt=dt) + StateSpace(np.array([[1, 2], [3, 4]]), np.array([[1], [2]]), + np.array([[1, 0]]), np.array([[0]]), dt=dt) + StateSpace(1, 1, 1, 1, dt=True) + + def test_conversion(self): + # Check the conversion functions + s = StateSpace(1, 2, 3, 4, dt=0.05) + assert isinstance(s.to_ss(), StateSpace) + assert isinstance(s.to_tf(), TransferFunction) + assert isinstance(s.to_zpk(), ZerosPolesGain) + + # Make sure copies work + assert StateSpace(s) is not s + assert s.to_ss() is not s + + def test_properties(self): + # Test setters/getters for cross class properties. + # This implicitly tests to_tf() and to_zpk() + + # Getters + s = StateSpace(1, 1, 1, 1, dt=0.05) + xp_assert_equal(s.poles, [1.]) + xp_assert_equal(s.zeros, [0.]) + + +class TestTransferFunction: + def test_initialization(self): + # Check that all initializations work + dt = 0.05 + TransferFunction(1, 1, dt=dt) + TransferFunction([1], [2], dt=dt) + TransferFunction(np.array([1]), np.array([2]), dt=dt) + TransferFunction(1, 1, dt=True) + + def test_conversion(self): + # Check the conversion functions + s = TransferFunction([1, 0], [1, -1], dt=0.05) + assert isinstance(s.to_ss(), StateSpace) + assert isinstance(s.to_tf(), TransferFunction) + assert isinstance(s.to_zpk(), ZerosPolesGain) + + # Make sure copies work + assert TransferFunction(s) is not s + assert s.to_tf() is not s + + def test_properties(self): + # Test setters/getters for cross class properties. + # This implicitly tests to_ss() and to_zpk() + + # Getters + s = TransferFunction([1, 0], [1, -1], dt=0.05) + xp_assert_equal(s.poles, [1.]) + xp_assert_equal(s.zeros, [0.]) + + +class TestZerosPolesGain: + def test_initialization(self): + # Check that all initializations work + dt = 0.05 + ZerosPolesGain(1, 1, 1, dt=dt) + ZerosPolesGain([1], [2], 1, dt=dt) + ZerosPolesGain(np.array([1]), np.array([2]), 1, dt=dt) + ZerosPolesGain(1, 1, 1, dt=True) + + def test_conversion(self): + # Check the conversion functions + s = ZerosPolesGain(1, 2, 3, dt=0.05) + assert isinstance(s.to_ss(), StateSpace) + assert isinstance(s.to_tf(), TransferFunction) + assert isinstance(s.to_zpk(), ZerosPolesGain) + + # Make sure copies work + assert ZerosPolesGain(s) is not s + assert s.to_zpk() is not s + + +class Test_dfreqresp: + + def test_manual(self): + # Test dfreqresp() real part calculation (manual sanity check). + # 1st order low-pass filter: H(z) = 1 / (z - 0.2), + system = TransferFunction(1, [1, -0.2], dt=0.1) + w = [0.1, 1, 10] + w, H = dfreqresp(system, w=w) + + # test real + expected_re = [1.2383, 0.4130, -0.7553] + assert_almost_equal(H.real, expected_re, decimal=4) + + # test imag + expected_im = [-0.1555, -1.0214, 0.3955] + assert_almost_equal(H.imag, expected_im, decimal=4) + + def test_auto(self): + # Test dfreqresp() real part calculation. + # 1st order low-pass filter: H(z) = 1 / (z - 0.2), + system = TransferFunction(1, [1, -0.2], dt=0.1) + w = [0.1, 1, 10, 100] + w, H = dfreqresp(system, w=w) + jw = np.exp(w * 1j) + y = np.polyval(system.num, jw) / np.polyval(system.den, jw) + + # test real + expected_re = y.real + assert_almost_equal(H.real, expected_re) + + # test imag + expected_im = y.imag + assert_almost_equal(H.imag, expected_im) + + def test_freq_range(self): + # Test that freqresp() finds a reasonable frequency range. + # 1st order low-pass filter: H(z) = 1 / (z - 0.2), + # Expected range is from 0.01 to 10. + system = TransferFunction(1, [1, -0.2], dt=0.1) + n = 10 + expected_w = np.linspace(0, np.pi, 10, endpoint=False) + w, H = dfreqresp(system, n=n) + assert_almost_equal(w, expected_w) + + def test_pole_one(self): + # Test that freqresp() doesn't fail on a system with a pole at 0. + # integrator, pole at zero: H(s) = 1 / s + system = TransferFunction([1], [1, -1], dt=0.1) + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", "divide by zero", RuntimeWarning) + warnings.filterwarnings( + "ignore", "invalid value encountered", RuntimeWarning) + w, H = dfreqresp(system, n=2) + assert w[0] == 0. # a fail would give not-a-number + + def test_error(self): + # Raise an error for continuous-time systems + system = lti([1], [1, 1]) + assert_raises(AttributeError, dfreqresp, system) + + def test_from_state_space(self): + # H(z) = 2 / z^3 - 0.5 * z^2 + + system_TF = dlti([2], [1, -0.5, 0, 0]) + + A = np.array([[0.5, 0, 0], + [1, 0, 0], + [0, 1, 0]]) + B = np.array([[1, 0, 0]]).T + C = np.array([[0, 0, 2]]) + D = 0 + + system_SS = dlti(A, B, C, D) + w = 10.0**np.arange(-3,0,.5) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", BadCoefficients) + w1, H1 = dfreqresp(system_TF, w=w) + w2, H2 = dfreqresp(system_SS, w=w) + + assert_almost_equal(H1, H2) + + def test_from_zpk(self): + # 1st order low-pass filter: H(s) = 0.3 / (z - 0.2), + system_ZPK = dlti([],[0.2],0.3) + system_TF = dlti(0.3, [1, -0.2]) + w = [0.1, 1, 10, 100] + w1, H1 = dfreqresp(system_ZPK, w=w) + w2, H2 = dfreqresp(system_TF, w=w) + assert_almost_equal(H1, H2) + + +class Test_bode: + + def test_manual(self): + # Test bode() magnitude calculation (manual sanity check). + # 1st order low-pass filter: H(s) = 0.3 / (z - 0.2), + dt = 0.1 + system = TransferFunction(0.3, [1, -0.2], dt=dt) + w = [0.1, 0.5, 1, np.pi] + w2, mag, phase = dbode(system, w=w) + + # Test mag + expected_mag = [-8.5329, -8.8396, -9.6162, -12.0412] + assert_almost_equal(mag, expected_mag, decimal=4) + + # Test phase + expected_phase = [-7.1575, -35.2814, -67.9809, -180.0000] + assert_almost_equal(phase, expected_phase, decimal=4) + + # Test frequency + xp_assert_equal(np.array(w) / dt, w2) + + def test_auto(self): + # Test bode() magnitude calculation. + # 1st order low-pass filter: H(s) = 0.3 / (z - 0.2), + system = TransferFunction(0.3, [1, -0.2], dt=0.1) + w = np.array([0.1, 0.5, 1, np.pi]) + w2, mag, phase = dbode(system, w=w) + jw = np.exp(w * 1j) + y = np.polyval(system.num, jw) / np.polyval(system.den, jw) + + # Test mag + expected_mag = 20.0 * np.log10(abs(y)) + assert_almost_equal(mag, expected_mag) + + # Test phase + expected_phase = np.rad2deg(np.angle(y)) + assert_almost_equal(phase, expected_phase) + + def test_range(self): + # Test that bode() finds a reasonable frequency range. + # 1st order low-pass filter: H(s) = 0.3 / (z - 0.2), + dt = 0.1 + system = TransferFunction(0.3, [1, -0.2], dt=0.1) + n = 10 + # Expected range is from 0.01 to 10. + expected_w = np.linspace(0, np.pi, n, endpoint=False) / dt + w, mag, phase = dbode(system, n=n) + assert_almost_equal(w, expected_w) + + def test_pole_one(self): + # Test that freqresp() doesn't fail on a system with a pole at 0. + # integrator, pole at zero: H(s) = 1 / s + system = TransferFunction([1], [1, -1], dt=0.1) + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", "divide by zero", RuntimeWarning) + warnings.filterwarnings( + "ignore", "invalid value encountered", RuntimeWarning) + w, mag, phase = dbode(system, n=2) + assert w[0] == 0. # a fail would give not-a-number + + def test_imaginary(self): + # bode() should not fail on a system with pure imaginary poles. + # The test passes if bode doesn't raise an exception. + system = TransferFunction([1], [1, 0, 100], dt=0.1) + dbode(system, n=2) + + def test_error(self): + # Raise an error for continuous-time systems + system = lti([1], [1, 1]) + assert_raises(AttributeError, dbode, system) + + +class TestTransferFunctionZConversion: + """Test private conversions between 'z' and 'z**-1' polynomials.""" + + def test_full(self): + # Numerator and denominator same order + num = np.asarray([2.0, 3, 4]) + den = np.asarray([5.0, 6, 7]) + num2, den2 = TransferFunction._z_to_zinv(num, den) + xp_assert_equal(num, num2) + xp_assert_equal(den, den2) + + num2, den2 = TransferFunction._zinv_to_z(num, den) + xp_assert_equal(num, num2) + xp_assert_equal(den, den2) + + def test_numerator(self): + # Numerator lower order than denominator + num = np.asarray([2.0, 3]) + den = np.asarray([50, 6, 7]) + num2, den2 = TransferFunction._z_to_zinv(num, den) + xp_assert_equal([0.0, 2, 3], num2) + xp_assert_equal(den, den2) + + num2, den2 = TransferFunction._zinv_to_z(num, den) + xp_assert_equal([2.0, 3, 0], num2) + xp_assert_equal(den, den2) + + def test_denominator(self): + # Numerator higher order than denominator + num = np.asarray([2., 3, 4]) + den = np.asarray([5.0, 6]) + num2, den2 = TransferFunction._z_to_zinv(num, den) + xp_assert_equal(num, num2) + xp_assert_equal([0.0, 5, 6], den2) + + num2, den2 = TransferFunction._zinv_to_z(num, den) + xp_assert_equal(num, num2) + xp_assert_equal([5.0, 6, 0], den2) + diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_filter_design.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_filter_design.py new file mode 100644 index 0000000000000000000000000000000000000000..d1ea9d9f0150fc49ce0daebb8668747481633bdd --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_filter_design.py @@ -0,0 +1,5129 @@ +import math +import cmath +import warnings +import os + +from itertools import product + +from scipy._lib import _pep440 +import numpy as np +import pytest +from pytest import raises as assert_raises +from scipy._lib._array_api import ( + xp_assert_close, xp_assert_equal, array_namespace, + assert_array_almost_equal, xp_size, xp_default_dtype, is_numpy, + make_xp_test_case, make_xp_pytest_param, is_cupy, is_torch, scipy_namespace_for, + _xp_copy_to_numpy, xp_assert_close_nulp +) +import scipy._lib.array_api_extra as xpx + +from numpy import array, spacing, sin, pi +from scipy.signal import (argrelextrema, BadCoefficients, bessel, besselap, bilinear, + buttap, butter, buttord, cheb1ap, cheb1ord, cheb2ap, + cheb2ord, cheby1, cheby2, ellip, ellipap, ellipord, + firwin, freqs_zpk, freqs, freqz, freqz_zpk, + gammatone, group_delay, iircomb, iirdesign, iirfilter, + iirnotch, iirpeak, lp2bp, lp2bs, lp2hp, lp2lp, normalize, + sos2tf, sos2zpk, sosfreqz, freqz_sos, tf2sos, tf2zpk, zpk2sos, + zpk2tf, bilinear_zpk, lp2lp_zpk, lp2hp_zpk, lp2bp_zpk, + lp2bs_zpk) +from scipy.signal._filter_design import (_cplxreal, _cplxpair, _norm_factor, + _bessel_poly, _bessel_zeros) +from scipy.signal._filter_design import _logspace +from scipy.signal import _polyutils as _pu +from scipy.signal._polyutils import _sort_cmplx + +skip_xp_backends = pytest.mark.skip_xp_backends +xfail_xp_backends = pytest.mark.xfail_xp_backends + + +DEFAULT_F32 = os.getenv('SCIPY_DEFAULT_DTYPE', default='float64') == 'float32' + +try: + import mpmath +except ImportError: + mpmath = None + + +def mpmath_check(min_ver): + return pytest.mark.skipif( + mpmath is None + or _pep440.parse(mpmath.__version__) < _pep440.Version(min_ver), + reason=f"mpmath version >= {min_ver} required", + ) + + +class TestCplxPair: + + def test_trivial_input(self): + assert _cplxpair([]).size == 0 + assert _cplxpair(1) == 1 + + def test_output_order(self): + xp_assert_close(_cplxpair([1+1j, 1-1j]), [1-1j, 1+1j]) + + a = [1+1j, 1+1j, 1, 1-1j, 1-1j, 2] + b = [1-1j, 1+1j, 1-1j, 1+1j, 1, 2] + xp_assert_close(_cplxpair(a), b) + + # points spaced around the unit circle + z = np.exp(2j*pi*array([4, 3, 5, 2, 6, 1, 0])/7) + z1 = np.copy(z) + np.random.shuffle(z) + xp_assert_close(_cplxpair(z), z1) + np.random.shuffle(z) + xp_assert_close(_cplxpair(z), z1) + np.random.shuffle(z) + xp_assert_close(_cplxpair(z), z1) + + # Should be able to pair up all the conjugates + x = np.random.rand(10000) + 1j * np.random.rand(10000) + y = x.conj() + z = np.random.rand(10000) + x = np.concatenate((x, y, z)) + np.random.shuffle(x) + c = _cplxpair(x) + + # Every other element of head should be conjugates: + xp_assert_close(c[0:20000:2], np.conj(c[1:20000:2])) + # Real parts of head should be in sorted order: + xp_assert_close(c[0:20000:2].real, np.sort(c[0:20000:2].real)) + # Tail should be sorted real numbers: + xp_assert_close(c[20000:], np.sort(c[20000:])) + + def test_real_integer_input(self): + xp_assert_equal(_cplxpair([2, 0, 1]), [0, 1, 2]) + + def test_tolerances(self): + eps = spacing(1) + xp_assert_close(_cplxpair([1j, -1j, 1+1j*eps], tol=2*eps), + [-1j, 1j, 1+1j*eps]) + + # sorting close to 0 + xp_assert_close(_cplxpair([-eps+1j, +eps-1j]), [-1j, +1j]) + xp_assert_close(_cplxpair([+eps+1j, -eps-1j]), [-1j, +1j]) + xp_assert_close(_cplxpair([+1j, -1j]), [-1j, +1j]) + + def test_unmatched_conjugates(self): + # 1+2j is unmatched + assert_raises(ValueError, _cplxpair, [1+3j, 1-3j, 1+2j]) + + # 1+2j and 1-3j are unmatched + assert_raises(ValueError, _cplxpair, [1+3j, 1-3j, 1+2j, 1-3j]) + + # 1+3j is unmatched + assert_raises(ValueError, _cplxpair, [1+3j, 1-3j, 1+3j]) + + # Not conjugates + assert_raises(ValueError, _cplxpair, [4+5j, 4+5j]) + assert_raises(ValueError, _cplxpair, [1-7j, 1-7j]) + + # No pairs + assert_raises(ValueError, _cplxpair, [1+3j]) + assert_raises(ValueError, _cplxpair, [1-3j]) + + +class TestCplxReal: + + def test_trivial_input(self): + assert all(x.size == 0 for x in _cplxreal([])) + + x = _cplxreal(1) + assert x[0].size == 0 + xp_assert_equal(x[1], np.asarray([1])) + + + def test_output_order(self): + zc, zr = _cplxreal(np.roots(array([1, 0, 0, 1]))) + xp_assert_close(np.append(zc, zr), [1/2 + 1j*sin(pi/3), -1]) + + eps = spacing(1) + + a = [0+1j, 0-1j, eps + 1j, eps - 1j, -eps + 1j, -eps - 1j, + 1, 4, 2, 3, 0, 0, + 2+3j, 2-3j, + 1-eps + 1j, 1+2j, 1-2j, 1+eps - 1j, # sorts out of order + 3+1j, 3+1j, 3+1j, 3-1j, 3-1j, 3-1j, + 2-3j, 2+3j] + zc, zr = _cplxreal(a) + xp_assert_close(zc, [1j, 1j, 1j, 1+1j, 1+2j, 2+3j, 2+3j, 3+1j, 3+1j, + 3+1j]) + xp_assert_close(zr, [0.0, 0, 1, 2, 3, 4]) + + z = array([1-eps + 1j, 1+2j, 1-2j, 1+eps - 1j, 1+eps+3j, 1-2*eps-3j, + 0+1j, 0-1j, 2+4j, 2-4j, 2+3j, 2-3j, 3+7j, 3-7j, 4-eps+1j, + 4+eps-2j, 4-1j, 4-eps+2j]) + + zc, zr = _cplxreal(z) + xp_assert_close(zc, [1j, 1+1j, 1+2j, 1+3j, 2+3j, 2+4j, 3+7j, 4+1j, + 4+2j]) + xp_assert_equal(zr, np.asarray([])) + + def test_unmatched_conjugates(self): + # 1+2j is unmatched + assert_raises(ValueError, _cplxreal, [1+3j, 1-3j, 1+2j]) + + # 1+2j and 1-3j are unmatched + assert_raises(ValueError, _cplxreal, [1+3j, 1-3j, 1+2j, 1-3j]) + + # 1+3j is unmatched + assert_raises(ValueError, _cplxreal, [1+3j, 1-3j, 1+3j]) + + # No pairs + assert_raises(ValueError, _cplxreal, [1+3j]) + assert_raises(ValueError, _cplxreal, [1-3j]) + + def test_real_integer_input(self): + zc, zr = _cplxreal([2, 0, 1, 4]) + xp_assert_equal(zc, np.asarray([])) + xp_assert_equal(zr, [0, 1, 2, 4]) + + +@make_xp_test_case(tf2zpk) +class TestTf2zpk: + + @skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") + @pytest.mark.parametrize('dt', ('float64', 'complex128')) + def test_simple(self, dt, xp): + dtyp = getattr(xp, dt) + + z_r = xp.asarray([0.5, -0.5]) + p_r = xp.asarray([1.j / math.sqrt(2), -1.j / math.sqrt(2)]) + # Sort the zeros/poles so that we don't fail the test if the order + # changes + z_r = _sort_cmplx(z_r, xp=xp) + p_r = _sort_cmplx(p_r, xp=xp) + + b = xp.astype(_pu.poly(z_r, xp=xp), dtyp) + a = xp.astype(_pu.poly(p_r, xp=xp), dtyp) + + z, p, k = tf2zpk(b, a) + z = _sort_cmplx(z, xp=xp) + # The real part of `p` is ~0.0, so sort by imaginary part + p = p[xp.argsort(xp.imag(p))] + + assert_array_almost_equal(z, z_r) + assert_array_almost_equal(p, p_r) + assert math.isclose(xp.real(k), 1.) + assert k.dtype == dtyp + + def test_bad_filter(self): + # Regression test for #651: better handling of badly conditioned + # filter coefficients. + with warnings.catch_warnings(): + warnings.simplefilter("error", BadCoefficients) + assert_raises(BadCoefficients, tf2zpk, [1e-15], [1.0, 1.0]) + + +@make_xp_test_case(zpk2tf) +class TestZpk2Tf: + + def test_identity(self, xp): + """Test the identity transfer function.""" + z = xp.asarray([]) + p = xp.asarray([]) + k = 1. + b, a = zpk2tf(z, p, k) + b_r = xp.asarray([1.]) # desired result + a_r = xp.asarray([1.]) # desired result + # The test for the *type* of the return values is a regression + # test for ticket #1095. In the case p=[], zpk2tf used to + # return the scalar 1.0 instead of array([1.0]). + xp_assert_equal(b, b_r) + xp_assert_equal(a, a_r) + if is_numpy(xp): + assert isinstance(b, np.ndarray) + assert isinstance(a, np.ndarray) + + @skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") + def test_conj_pair(self, xp): + # conjugate pairs give real-coeff num & den + z = xp.asarray([1j, -1j, 2j, -2j]) + z_np = _xp_copy_to_numpy(z) + # shouldn't need elements of pairs to be adjacent + p = xp.asarray([1+1j, 3-100j, 3+100j, 1-1j]) + p_np = _xp_copy_to_numpy(p) + + k = 23 + + # np.poly should do the right thing, but be explicit about + # taking real part + b_np = k * np.poly(z_np).real + a_np = np.poly(p_np).real + b, a = map(xp.asarray, (b_np, a_np)) + + bp, ap = zpk2tf(z, p, k) + + atol = 5e-13 if is_cupy(xp) else 0.0 + xp_assert_close(b, bp, atol=atol) + xp_assert_close(a, ap) + + assert xp.isdtype(bp.dtype, 'real floating') + assert xp.isdtype(ap.dtype, 'real floating') + + @skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") + def test_complexk(self, xp): + # regression: z, p real, k complex k gave real b, a + b, a = xp.asarray([1j, 1j]), xp.asarray([1.0, 2]) + b_np, a_np = map(_xp_copy_to_numpy, (b, a)) + z_np, p_np, k_np = tf2zpk(b_np, a_np) + z, p, k = map(xp.asarray, (z_np, p_np, k_np)) + xp_assert_close(k, xp.asarray(1j), check_0d=False) + bp, ap = zpk2tf(z, p, k) + xp_assert_close(b, bp) + xp_assert_close(a, ap) + + @skip_xp_backends("jax.numpy", + reason="zpk2tf not compatible with jax yet on multi-dim arrays") + @skip_xp_backends("cupy", + reason="multi-dim arrays not supported yet on cupy") + def test_zpk2tf_with_multi_dimensional_array(self, xp): + z = xp.asarray([[1, 2], [3, 4]]) # Multi-dimensional input + p = xp.asarray([1, 2]) + k = 1 + b, a = zpk2tf(z, p, k) + b_ref = xp.asarray([[1, -3, 2], [1, -7, 12]]) + a_ref = xp.asarray([1, -3, 2]) + xp_assert_close(b, b_ref, check_dtype=False) + xp_assert_close(a, a_ref, check_dtype=False) + + @skip_xp_backends("cupy", + reason="multi-dim arrays not supported yet on cupy") + def test_zpk2tf_int_truncation(self, xp): + # regression test for gh-24382 + z = xp.asarray([[ 1, 2.], [ 0., -1.]], dtype=xp.float64) + p = xp.asarray([3., 4.], dtype=xp.float64) + k = 2.5 + + b, a = zpk2tf(z, p, k) + + # reference values from scipy 1.15.3 + b_ref = xp.asarray([[ 2.5, -7.5, 5. ], [ 2.5, 2.5, 0. ]], dtype=xp.float64) + a_ref = xp.asarray([ 1., -7., 12.], dtype=xp.float64) + + xp_assert_close(b, b_ref, atol=1e-14) + xp_assert_close(a, a_ref, atol=1e-14) + + +@make_xp_test_case(sos2zpk) +class TestSos2Zpk: + + @skip_xp_backends("dask.array", reason="it https://github.com/dask/dask/issues/11883") + @xfail_xp_backends("jax.numpy", reason="inaccurate with jax") + def test_basic(self, xp): + sos = [[1, 0, 1, 1, 0, -0.81], + [1, 0, 0, 1, 0, +0.49]] + sos = xp.asarray(sos) + z, p, k = sos2zpk(sos) + z2 = xp.asarray([1j, -1j, 0, 0]) + p2 = xp.asarray([0.9, -0.9, 0.7j, -0.7j]) + k2 = 1. + assert_array_almost_equal(_sort_cmplx(z, xp), _sort_cmplx(z2, xp), decimal=4) + assert_array_almost_equal(_sort_cmplx(p, xp), _sort_cmplx(p2, xp), decimal=4) + assert math.isclose(k, k2) + + sos = [[1.00000, +0.61803, 1.0000, 1.00000, +0.60515, 0.95873], + [1.00000, -1.61803, 1.0000, 1.00000, -1.58430, 0.95873], + [1.00000, +1.00000, 0.0000, 1.00000, +0.97915, 0.00000]] + sos = xp.asarray(sos) + z, p, k = sos2zpk(sos) + z2 = [-0.3090 + 0.9511j, -0.3090 - 0.9511j, 0.8090 + 0.5878j, + 0.8090 - 0.5878j, -1.0000 + 0.0000j, 0] + p2 = [-0.3026 + 0.9312j, -0.3026 - 0.9312j, 0.7922 + 0.5755j, + 0.7922 - 0.5755j, -0.9791 + 0.0000j, 0] + z2 = xp.asarray(z2) + p2 = xp.asarray(p2) + k2 = 1 + assert_array_almost_equal(_sort_cmplx(z, xp), _sort_cmplx(z2, xp), decimal=4) + assert_array_almost_equal(_sort_cmplx(p, xp), _sort_cmplx(p2, xp), decimal=4) + + sos = array([[1, 2, 3, 1, 0.2, 0.3], + [4, 5, 6, 1, 0.4, 0.5]]) + z = array([-1 - 1.41421356237310j, -1 + 1.41421356237310j, + -0.625 - 1.05326872164704j, -0.625 + 1.05326872164704j]) + p = array([-0.2 - 0.678232998312527j, -0.2 + 0.678232998312527j, + -0.1 - 0.538516480713450j, -0.1 + 0.538516480713450j]) + sos, z, p = map(xp.asarray, (sos, z, p)) + k = 4 + z2, p2, k2 = sos2zpk(sos) + + xp_assert_close(_sort_cmplx(z2, xp=xp), _sort_cmplx(z, xp=xp)) + xp_assert_close(_sort_cmplx(p2, xp=xp), _sort_cmplx(p, xp=xp)) + assert k2 == k + + def test_fewer_zeros(self, xp): + """Test not the expected number of p/z (effectively at origin).""" + sos = butter(3, 0.1, output='sos') + z, p, k = sos2zpk(xp.asarray(sos)) + assert z.shape[0] == 4 + assert p.shape[0] == 4 + + sos = butter(12, [5., 30.], 'bandpass', fs=1200., analog=False, output='sos') + e = BadCoefficients + if is_cupy(xp): + e = scipy_namespace_for(xp).signal.BadCoefficients + with pytest.warns(e, match='Badly conditioned'): + z, p, k = sos2zpk(xp.asarray(sos)) + assert z.shape[0] == 24 + assert p.shape[0] == 24 + + +@make_xp_test_case(sos2tf) +class TestSos2Tf: + + def test_basic(self, xp): + sos = [[1.0, 1, 1, 1, 0, -1], + [-2, 3, 1, 1, 10, 1]] + sos = xp.asarray(sos) + b, a = sos2tf(sos) + assert_array_almost_equal(b, xp.asarray([-2.0, 1, 2, 4, 1])) + assert_array_almost_equal(a, xp.asarray([1.0, 10, 0, -10, -1])) + + +@make_xp_test_case(tf2sos) +class TestTf2Sos: + + def test_basic(self, xp): + num = xp.asarray([2., 16, 44, 56, 32]) + den = xp.asarray([3., 3, -15, 18, -12]) + sos = tf2sos(num, den) + sos2 = [[0.6667, 4.0000, 5.3333, 1.0000, +2.0000, -4.0000], + [1.0000, 2.0000, 2.0000, 1.0000, -1.0000, +1.0000]] + sos2 = xp.asarray(sos2) + assert_array_almost_equal(sos, sos2, decimal=4) + + b = xp.asarray([1.0, -3, 11, -27, 18]) + a = xp.asarray([16.0, 12, 2, -4, -1]) + sos = tf2sos(b, a) + sos2 = [[0.0625, -0.1875, 0.1250, 1.0000, -0.2500, -0.1250], + [1.0000, +0.0000, 9.0000, 1.0000, +1.0000, +0.5000]] + sos2 = xp.asarray(sos2) + #assert_array_almost_equal(sos, sos2, decimal=4) + + @pytest.mark.parametrize('b, a, analog, sos', + [([1.0], [1.0], False, [[1., 0., 0., 1., 0., 0.]]), + ([1.0], [1.0], True, [[0., 0., 1., 0., 0., 1.]]), + ([1.0], [1., 0., -1.01, 0, 0.01], False, + [[1., 0., 0., 1., 0., -0.01], + [1., 0., 0., 1., 0., -1]]), + ([1.0], [1., 0., -1.01, 0, 0.01], True, + [[0., 0., 1., 1., 0., -1], + [0., 0., 1., 1., 0., -0.01]])]) + @skip_xp_backends("cupy", reason="https://github.com/cupy/cupy/issues/9376") + def test_analog(self, b, a, analog, sos, xp): + b, a, sos = map(xp.asarray, (b, a, sos)) + sos2 = tf2sos(b, a, analog=analog) + assert_array_almost_equal(sos, sos2, decimal=4) + + +@make_xp_test_case(zpk2sos) +class TestZpk2Sos: + +# @pytest.mark.parametrize('dt', 'fdgFDG') + # XXX: quietly remove float128 and complex256 + @pytest.mark.parametrize('dt', ['float32', 'float64', 'complex64', 'complex128']) + @pytest.mark.parametrize('pairing, analog', + [('nearest', False), + ('keep_odd', False), + ('minimal', False), + ('minimal', True)]) + def test_dtypes(self, dt, pairing, analog, xp): + dtype = getattr(xp, dt) + # the poles have to be complex + cdtype = (1j*xp.empty(0, dtype=dtype)).dtype + + z = xp.asarray([-1, -1], dtype=dtype) + p = xp.asarray([0.57149 + 0.29360j, 0.57149 - 0.29360j], dtype=cdtype) + k = xp.asarray(1, dtype=dtype) + sos = zpk2sos(z, p, k, pairing=pairing, analog=analog) + # octave & MATLAB + sos2 = xp.asarray([[1, 2, 1, 1, -1.14298, 0.41280]], dtype=dtype) + assert_array_almost_equal(sos, sos2, decimal=4) + + def test_basic(self, xp): + for pairing in ('nearest', 'keep_odd'): + # + # Cases that match octave + # + + z = xp.asarray([-1.0, -1.0]) + p = xp.asarray([0.57149 + 0.29360j, 0.57149 - 0.29360j]) + k = 1 + sos = zpk2sos(z, p, k, pairing=pairing) + sos2 = xp.asarray([[1, 2, 1, 1, -1.14298, 0.41280]]) # octave & MATLAB + assert_array_almost_equal(sos, sos2, decimal=4) + + z = xp.asarray([1j, -1j]) + p = xp.asarray([0.9, -0.9, 0.7j, -0.7j]) + k = 1 + sos = zpk2sos(z, p, k, pairing=pairing) + sos2 = [[1, 0, 1, 1, 0, +0.49], + [1, 0, 0, 1, 0, -0.81]] # octave + sos2 = xp.asarray(sos2) + # sos2 = [[0, 0, 1, 1, -0.9, 0], + # [1, 0, 1, 1, 0.9, 0]] # MATLAB + assert_array_almost_equal(sos, sos2, decimal=4) + + z = xp.asarray([]) + p = xp.asarray([0.8, -0.5+0.25j, -0.5-0.25j]) + k = 1. + sos = zpk2sos(z, p, k, pairing=pairing) + sos2 = [[1., 0., 0., 1., 1., 0.3125], + [1., 0., 0., 1., -0.8, 0.]] # octave, MATLAB fails + sos2 = xp.asarray(sos2) + assert_array_almost_equal(sos, sos2, decimal=4) + + z = xp.asarray([1., 1., 0.9j, -0.9j]) + p = xp.asarray([0.99+0.01j, 0.99-0.01j, 0.1+0.9j, 0.1-0.9j]) + k = 1 + sos = zpk2sos(z, p, k, pairing=pairing) + sos2 = [[1, 0, 0.81, 1, -0.2, 0.82], + [1, -2, 1, 1, -1.98, 0.9802]] # octave + sos2 = xp.asarray(sos2) + # sos2 = [[1, -2, 1, 1, -0.2, 0.82], + # [1, 0, 0.81, 1, -1.98, 0.9802]] # MATLAB + assert_array_almost_equal(sos, sos2, decimal=4) + + z = xp.asarray([0.9+0.1j, 0.9-0.1j, -0.9]) + p = xp.asarray([0.75+0.25j, 0.75-0.25j, 0.9]) + k = 1 + sos = zpk2sos(z, p, k, pairing=pairing) + if pairing == 'keep_odd': + sos2 = [[1, -1.8, 0.82, 1, -1.5, 0.625], + [1, 0.9, 0, 1, -0.9, 0]] # octave; MATLAB fails + sos2 = xp.asarray(sos2) + assert_array_almost_equal(sos, sos2, decimal=4) + else: # pairing == 'nearest' + sos2 = [[1, 0.9, 0, 1, -1.5, 0.625], + [1, -1.8, 0.82, 1, -0.9, 0]] # our algorithm + sos2 = xp.asarray(sos2) + assert_array_almost_equal(sos, sos2, decimal=4) + + # + # Cases that differ from octave: + # + + z = [-0.3090 + 0.9511j, -0.3090 - 0.9511j, 0.8090 + 0.5878j, + +0.8090 - 0.5878j, -1.0000 + 0.0000j] + p = [-0.3026 + 0.9312j, -0.3026 - 0.9312j, 0.7922 + 0.5755j, + +0.7922 - 0.5755j, -0.9791 + 0.0000j] + z = xp.asarray(z) + p = xp.asarray(p) + k = 1 + sos = zpk2sos(z, p, k, pairing=pairing) + # sos2 = [[1, 0.618, 1, 1, 0.6052, 0.95870], + # [1, -1.618, 1, 1, -1.5844, 0.95878], + # [1, 1, 0, 1, 0.9791, 0]] # octave, MATLAB fails + sos2 = [[1, 1, 0, 1, +0.97915, 0], + [1, 0.61803, 1, 1, +0.60515, 0.95873], + [1, -1.61803, 1, 1, -1.58430, 0.95873]] + sos2 = xp.asarray(sos2) + assert_array_almost_equal(sos, sos2, decimal=4) + + z = [-1 - 1.4142j, -1 + 1.4142j, + -0.625 - 1.0533j, -0.625 + 1.0533j] + p = [-0.2 - 0.6782j, -0.2 + 0.6782j, + -0.1 - 0.5385j, -0.1 + 0.5385j] + z = xp.asarray(z) + p = xp.asarray(p) + k = 4 + sos = zpk2sos(z, p, k, pairing=pairing) + sos2 = [[4, 8, 12, 1, 0.2, 0.3], + [1, 1.25, 1.5, 1, 0.4, 0.5]] # MATLAB + sos2 = xp.asarray(sos2, dtype=xp.float64) + # sos2 = [[4, 8, 12, 1, 0.4, 0.5], + # [1, 1.25, 1.5, 1, 0.2, 0.3]] # octave + xp_assert_close(sos, sos2, rtol=1e-4, atol=1e-4) + + z = xp.asarray([]) + p = xp.asarray([0.2, -0.5+0.25j, -0.5-0.25j]) + k = 1. + sos = zpk2sos(z, p, k, pairing=pairing) + sos2 = [[1., 0., 0., 1., -0.2, 0.], + [1., 0., 0., 1., 1., 0.3125]] + sos2 = xp.asarray(sos2) + # sos2 = [[1., 0., 0., 1., 1., 0.3125], + # [1., 0., 0., 1., -0.2, 0]] # octave, MATLAB fails + assert_array_almost_equal(sos, sos2, decimal=4) + + # The next two examples are adapted from Leland B. Jackson, + # "Digital Filters and Signal Processing (1995) p.400: + # http://books.google.com/books?id=VZ8uabI1pNMC&lpg=PA400&ots=gRD9pi8Jua&dq=Pole%2Fzero%20pairing%20for%20minimum%20roundoff%20noise%20in%20BSF.&pg=PA400#v=onepage&q=Pole%2Fzero%20pairing%20for%20minimum%20roundoff%20noise%20in%20BSF.&f=false + + deg2rad = xp.pi / 180. + k = 1. + + # first example + thetas = xp.asarray([22.5, 45, 77.5]) + mags = xp.asarray([0.8, 0.6, 0.9]) + z = xp.exp(1j * deg2rad * thetas) + z = xp.concat((z, xp.conj(z))) + p = xp.exp(1j * deg2rad * thetas) * mags + p = xp.concat((p, xp.conj(p))) + sos = zpk2sos(z, p, k) + # sos2 = [[1, -0.43288, 1, 1, -0.38959, 0.81], # octave, + # [1, -1.41421, 1, 1, -0.84853, 0.36], # MATLAB fails + # [1, -1.84776, 1, 1, -1.47821, 0.64]] + # Note that pole-zero pairing matches, but ordering is different + sos2 = [[1, -1.41421, 1, 1, -0.84853, 0.36], + [1, -1.84776, 1, 1, -1.47821, 0.64], + [1, -0.43288, 1, 1, -0.38959, 0.81]] + sos2 = xp.asarray(sos2) + assert_array_almost_equal(sos, sos2, decimal=4) + + # second example + thetas = xp.asarray([85., 10.]) + z = xp.exp(1j * deg2rad * thetas) + z = xp.concat((z, xp.conj(z), xp.asarray([1.0, -1.0]))) + sos = zpk2sos(z, p, k) + + # sos2 = [[1, -0.17431, 1, 1, -0.38959, 0.81], # octave "wrong", + # [1, -1.96962, 1, 1, -0.84853, 0.36], # MATLAB fails + # [1, 0, -1, 1, -1.47821, 0.64000]] + # Our pole-zero pairing matches the text, Octave does not + sos2 = [[1, 0, -1, 1, -0.84853, 0.36], + [1, -1.96962, 1, 1, -1.47821, 0.64], + [1, -0.17431, 1, 1, -0.38959, 0.81]] + sos2 = xp.asarray(sos2) + assert_array_almost_equal(sos, sos2, decimal=4) + + # these examples are taken from the doc string, and show the + # effect of the 'pairing' argument + @pytest.mark.parametrize('pairing, sos', + [('nearest', + np.array([[1., 1., 0.5, 1., -0.75, 0.], + [1., 1., 0., 1., -1.6, 0.65]])), + ('keep_odd', + np.array([[1., 1., 0, 1., -0.75, 0.], + [1., 1., 0.5, 1., -1.6, 0.65]])), + ('minimal', + np.array([[0., 1., 1., 0., 1., -0.75], + [1., 1., 0.5, 1., -1.6, 0.65]]))]) + def test_pairing(self, pairing, sos, xp): + sos = xp.asarray(sos) + z1 = xp.asarray([-1, -0.5-0.5j, -0.5+0.5j]) + p1 = xp.asarray([0.75, 0.8+0.1j, 0.8-0.1j]) + sos2 = zpk2sos(z1, p1, 1, pairing=pairing) + assert_array_almost_equal(sos, sos2, decimal=4) + + @pytest.mark.parametrize('p, sos_dt', + [([-1, 1, -0.1, 0.1], + [[0., 0., 1., 1., 0., -0.01], + [0., 0., 1., 1., 0., -1]]), + ([-0.7071+0.7071j, -0.7071-0.7071j, -0.1j, 0.1j], + [[0., 0., 1., 1., 0., 0.01], + [0., 0., 1., 1., 1.4142, 1.]])]) + def test_analog(self, p, sos_dt, xp): + # test `analog` argument + # for discrete time, poles closest to unit circle should appear last + # for cont. time, poles closest to imaginary axis should appear last + z, p = xp.asarray([]), xp.asarray(p) + sos_dt = xp.asarray(sos_dt) + sos2_dt = zpk2sos(z, p, 1, pairing='minimal', analog=False) + sos2_ct = zpk2sos(z, p, 1, pairing='minimal', analog=True) + assert_array_almost_equal(sos_dt, sos2_dt, decimal=4) + assert_array_almost_equal(xp.flip(sos_dt, axis=0), sos2_ct, decimal=4) + + def test_bad_args(self): + with pytest.raises(ValueError, match=r'pairing must be one of'): + zpk2sos([1], [2], 1, pairing='no_such_pairing') + + with pytest.raises(ValueError, match=r'.*pairing must be "minimal"'): + zpk2sos([1], [2], 1, pairing='keep_odd', analog=True) + + with pytest.raises(ValueError, + match=r'.*must have len\(p\)>=len\(z\)'): + zpk2sos([1, 1], [2], 1, analog=True) + + with pytest.raises(ValueError, match=r'k must be real'): + zpk2sos([1], [2], k=1j) + + +@make_xp_test_case(freqs) +class TestFreqs: + + def test_basic(self, xp): + _, h = freqs(xp.asarray([1.0]), xp.asarray([1.0]), worN=8) + assert_array_almost_equal(h, xp.ones(8)) + + def test_output(self, xp): + # 1st order low-pass filter: H(s) = 1 / (s + 1) + w = xp.asarray([0.1, 1, 10, 100]) + num = xp.asarray([1.]) + den = xp.asarray([1, 1.]) + w, H = freqs(num, den, worN=w) + s = w * 1j + expected = 1 / (s + 1) + assert_array_almost_equal(xp.real(H), xp.real(expected)) + assert_array_almost_equal(xp.imag(H), xp.imag(expected)) + + def test_freq_range(self, xp): + # Test that freqresp() finds a reasonable frequency range. + # 1st order low-pass filter: H(s) = 1 / (s + 1) + # Expected range is from 0.01 to 10. + num = xp.asarray([1.]) + den = xp.asarray([1, 1.]) + n = 10 + expected_w = _logspace(-2, 1, n, xp=xp) + w, H = freqs(num, den, worN=n) + assert_array_almost_equal(w, expected_w) + + def test_plot(self, xp): + + def plot(w, h): + assert_array_almost_equal(h, xp.ones(8)) + + with assert_raises(ZeroDivisionError): + freqs([1.0], [1.0], worN=8, plot=lambda w, h: 1 / 0) + + freqs(xp.asarray([1.0]), xp.asarray([1.0]), worN=8, plot=plot) + + def test_backward_compat(self, xp): + # For backward compatibility, test if None act as a wrapper for default + w1, h1 = freqs(xp.asarray([1.0]), xp.asarray([1.0])) + w2, h2 = freqs(xp.asarray([1.0]), xp.asarray([1.0]), None) + assert_array_almost_equal(w1, w2) + assert_array_almost_equal(h1, h2) + + def test_w_or_N_types(self): + # Measure at 8 equally-spaced points + for N in (8, np.int8(8), np.int16(8), np.int32(8), np.int64(8), + np.array(8)): + w, h = freqs([1.0], [1.0], worN=N) + assert len(w) == 8 + assert_array_almost_equal(h, np.ones(8)) + + # Measure at frequency 8 rad/sec + for w in (8.0, 8.0+0j): + w_out, h = freqs([1.0], [1.0], worN=w) + assert_array_almost_equal(w_out, [8]) + assert_array_almost_equal(h, [1]) + + +@make_xp_test_case(freqs_zpk) +class TestFreqs_zpk: + + def test_basic(self, xp): + _, h = freqs_zpk( + xp.asarray([1.0]), xp.asarray([1.0]), xp.asarray([1.0]), worN=8 + ) + assert_array_almost_equal(h, xp.ones(8)) + + def test_output(self, xp): + # 1st order low-pass filter: H(s) = 1 / (s + 1) + w = xp.asarray([0.1, 1, 10, 100]) + z = xp.asarray([]) + p = xp.asarray([-1.0]) + k = 1 + w, H = freqs_zpk(z, p, k, worN=w) + s = w * 1j + expected = 1 / (s + 1) + assert_array_almost_equal(xp.real(H), xp.real(expected)) + assert_array_almost_equal(xp.imag(H), xp.imag(expected)) + + def test_freq_range(self, xp): + # Test that freqresp() finds a reasonable frequency range. + # 1st order low-pass filter: H(s) = 1 / (s + 1) + # Expected range is from 0.01 to 10. + z = xp.asarray([]) + p = xp.asarray([-1.]) + k = 1 + n = 10 + expected_w = _logspace(-2, 1, n, xp=xp) + w, H = freqs_zpk(z, p, k, worN=n) + assert_array_almost_equal(w, expected_w) + + def test_vs_freqs(self, xp): + b, a = cheby1(4, 5, 100., analog=True, output='ba') + z, p, k = cheby1(4, 5, 100., analog=True, output='zpk') + + w1, h1 = map(xp.asarray, freqs(b, a)) + z, p, k = map(xp.asarray, (z, p, k)) + w2, h2 = freqs_zpk(z, p, k) + xp_assert_close(w1, w2) + xp_assert_close(h1, h2, rtol=1e-6) + + def test_backward_compat(self, xp): + # For backward compatibility, test if None act as a wrapper for default + # Also, keep testing `k` a length-one list: it is documented as a scalar, + # but the implementation was allowing for a one-element array-likes + w1, h1 = freqs_zpk(xp.asarray([1.0]), xp.asarray([1.0]), [1.0]) + w2, h2 = freqs_zpk(xp.asarray([1.0]), xp.asarray([1.0]), [1.0], None) + assert_array_almost_equal(w1, w2) + assert_array_almost_equal(h1, h2) + + def test_w_or_N_types(self): + # Measure at 8 equally-spaced points + for N in (8, np.int8(8), np.int16(8), np.int32(8), np.int64(8), + np.array(8)): + w, h = freqs_zpk([], [], 1, worN=N) + assert len(w) == 8 + assert_array_almost_equal(h, np.ones(8)) + + # Measure at frequency 8 rad/sec + for w in (8.0, 8.0+0j): + w_out, h = freqs_zpk([], [], 1, worN=w) + assert_array_almost_equal(w_out, [8]) + assert_array_almost_equal(h, [1]) + + +@make_xp_test_case(freqz) +class TestFreqz: + + def test_ticket1441(self, xp): + """Regression test for ticket 1441.""" + # Because freqz previously used arange instead of linspace, + # when N was large, it would return one more point than + # requested. + N = 100000 + w, h = freqz(xp.asarray([1.0]), worN=N) + assert w.shape == (N,) + + def test_gh_22886(self, xp): + w, h = freqz(xp.asarray([1.]), worN=xp.asarray([0., 0.1])) + xp_assert_equal(w, xp.asarray([0. , 0.1])) + xp_assert_equal(h, xp.asarray([1.+0.j, 1.+0.j])) + + def test_basic(self, xp): + w, h = freqz(xp.asarray([1.0]), worN=8) + assert_array_almost_equal(w, xp.pi * xp.arange(8, dtype=w.dtype) / 8.) + assert_array_almost_equal(h, xp.ones(8)) + w, h = freqz(xp.asarray([1.0]), worN=9) + assert_array_almost_equal(w, xp.pi * xp.arange(9, dtype=w.dtype) / 9.) + assert_array_almost_equal(h, xp.ones(9)) + + for a in [1, xp.ones(2)]: + w, h = freqz(xp.ones(2), a, worN=0) + assert w.shape == (0,) + assert h.shape == (0,) + hdt = xp.complex128 if xp_default_dtype(xp) == xp.float64 else xp.complex64 + assert h.dtype == hdt + + def test_basic2(self, xp): + t = xp.linspace(0, 1, 4, endpoint=False) + for b, a, h_whole in zip( + (xp.asarray([1., 0, 0, 0]), xp.sin(2 * xp.pi * t)), + (xp.asarray([1., 0, 0, 0]), xp.asarray([0.5, 0, 0, 0])), + (xp.asarray([1., 1., 1., 1.]), xp.asarray([0, -4j, 0, 4j])) + ): + + w, h = freqz(b, a, worN=4, whole=True) + expected_w = xp.linspace(0, 2 * xp.pi, 4, endpoint=False) + assert_array_almost_equal(w, expected_w) + assert_array_almost_equal(h, h_whole) + + if is_numpy(xp): + # simultaneously check int-like support + w, h = freqz(b, a, worN=np.int32(4), whole=True) + assert_array_almost_equal(w, expected_w) + assert_array_almost_equal(h, h_whole) + + w, h = freqz(b, a, worN=w, whole=True) + assert_array_almost_equal(w, expected_w) + assert_array_almost_equal(h, h_whole) + + def test_basic3(self): + t = np.linspace(0, 1, 4, endpoint=False) + expected_w = np.linspace(0, 2 * np.pi, 4, endpoint=False) + for b, a, h_whole in zip( + (np.asarray([1., 0, 0, 0]), np.sin(2 * np.pi * t)), + (np.asarray([1., 0, 0, 0]), np.asarray([0.5, 0, 0, 0])), + (np.asarray([1., 1., 1., 1.]), np.asarray([0, -4j, 0, 4j])) + ): + + w, h = freqz(b, a, worN=np.int32(4), whole=True) + assert_array_almost_equal(w, expected_w) + assert_array_almost_equal(h, h_whole) + + w, h = freqz(b, a, worN=w, whole=True) + assert_array_almost_equal(w, expected_w) + assert_array_almost_equal(h, h_whole) + + def test_basic_whole(self, xp): + w, h = freqz(xp.asarray([1.0]), worN=8, whole=True) + assert_array_almost_equal(w, 2 * xp.pi * xp.arange(8.0) / 8) + assert_array_almost_equal(h, xp.ones(8)) + + def test_plot(self, xp): + + def plot(w, h): + assert_array_almost_equal(w, xp.pi * xp.arange(8.0) / 8) + assert_array_almost_equal(h, xp.ones(8)) + + with assert_raises(ZeroDivisionError): + freqz(xp.asarray([1.0]), worN=8, plot=lambda w, h: 1 / 0) + + freqz(xp.asarray([1.0]), worN=8, plot=plot) + + def test_fft_wrapping(self, xp): + # Some simple real FIR filters + bs = list() # filters + as_ = list() + hs_whole = list() + hs_half = list() + # 3 taps + t = xp.linspace(0, 1, 3, endpoint=False) + bs.append(xp.sin(2 * xp.pi * t)) + as_.append(3.) + hs_whole.append(xp.asarray([0, -0.5j, 0.5j])) + hs_half.append(xp.asarray([0, math.sqrt(1./12.), -0.5j])) + # 4 taps + t = xp.linspace(0, 1, 4, endpoint=False) + bs.append(xp.sin(2 * xp.pi * t)) + as_.append(0.5) + hs_whole.append(xp.asarray([0, -4j, 0, 4j])) + hs_half.append(xp.asarray([0, math.sqrt(8), -4j, -math.sqrt(8)])) + del t + for ii, b in enumerate(bs): + # whole + a = as_[ii] + expected_w = xp.linspace(0, 2 * xp.pi, b.shape[0], endpoint=False) + w, h = freqz(b, a, worN=expected_w, whole=True) # polyval + err_msg = f'b = {b}, a={a}' + assert_array_almost_equal(w, expected_w, err_msg=err_msg) + assert_array_almost_equal(h, hs_whole[ii], err_msg=err_msg) + + w, h = freqz(b, a, worN=b.shape[0], whole=True) # FFT + assert_array_almost_equal(w, expected_w, err_msg=err_msg) + assert_array_almost_equal(h, hs_whole[ii], err_msg=err_msg) + + # non-whole + expected_w = xp.linspace(0, xp.pi, b.shape[0], endpoint=False) + w, h = freqz(b, a, worN=expected_w, whole=False) # polyval + assert_array_almost_equal(w, expected_w, err_msg=err_msg) + assert_array_almost_equal(h, hs_half[ii], err_msg=err_msg) + + w, h = freqz(b, a, worN=b.shape[0], whole=False) # FFT + assert_array_almost_equal(w, expected_w, err_msg=err_msg) + assert_array_almost_equal(h, hs_half[ii], err_msg=err_msg) + + # some random FIR filters (real + complex) + # assume polyval is accurate + rng = np.random.RandomState(0) + for ii in range(2, 10): # number of taps + b = xp.asarray(rng.randn(ii)) + for kk in range(2): + a = xp.asarray(rng.randn(1) if kk == 0 else rng.randn(3)) + for jj in range(2): + if jj == 1: + b = b + xp.asarray(rng.randn(ii)) * 1j + + # whole + expected_w = xp.linspace(0, 2 * xp.pi, ii, endpoint=False) + w, expected_h = freqz(b, a, worN=expected_w, whole=True) + assert_array_almost_equal(w, expected_w) + w, h = freqz(b, a, worN=ii, whole=True) + assert_array_almost_equal(w, expected_w) + assert_array_almost_equal(h, expected_h, decimal=4) + + # half + expected_w = xp.linspace(0, xp.pi, ii, endpoint=False) + w, expected_h = freqz(b, a, worN=expected_w, whole=False) + assert_array_almost_equal(w, expected_w) + w, h = freqz(b, a, worN=ii, whole=False) + assert_array_almost_equal(w, expected_w) + assert_array_almost_equal(h, expected_h, decimal=4) + + def test_broadcasting1(self, xp): + # Test broadcasting with worN an integer or a 1-D array, + # b and a are n-dimensional arrays. + np.random.seed(123) + b = np.random.rand(3, 5, 1) + a = np.random.rand(2, 1) + b, a = map(xp.asarray, (b, a)) + + for whole in [False, True]: + # Test with worN being integers (one fast for FFT and one not), + # a 1-D array, and an empty array. + for worN in [16, 17, xp.linspace(0, 1, 10), xp.asarray([])]: + w, h = freqz(b, a, worN=worN, whole=whole) + for k in range(b.shape[1]): + bk = b[:, k, 0] + ak = a[:, 0] + ww, hh = freqz(bk, ak, worN=worN, whole=whole) + xp_assert_close(ww, w) + xp_assert_close(hh, h[k, ...]) + + def test_broadcasting2(self, xp): + # Test broadcasting with worN an integer or a 1-D array, + # b is an n-dimensional array, and a is left at the default value. + np.random.seed(123) + b = np.random.rand(3, 5, 1) + b = xp.asarray(b) + for whole in [False, True]: + for worN in [16, 17, xp.linspace(0, 1, 10)]: + w, h = freqz(b, worN=worN, whole=whole) + for k in range(b.shape[1]): + bk = b[:, k, 0] + ww, hh = freqz(bk, worN=worN, whole=whole) + xp_assert_close(ww, w) + xp_assert_close(hh, h[k, :]) + + def test_broadcasting3(self, xp): + # Test broadcasting where b.shape[-1] is the same length + # as worN, and a is left at the default value. + np.random.seed(123) + N = 16 + b = np.random.rand(3, N) + b = xp.asarray(b) + for whole in [False, True]: + for worN in [N, xp.linspace(0, 1, N)]: + w, h = freqz(b, worN=worN, whole=whole) + assert xp_size(w) == N + for k in range(N): + bk = b[:, k] + ww, hh = freqz(bk, worN=w[k], whole=whole) + xp_assert_close(ww, xp.asarray(w[k])[None]) + xp_assert_close(hh, xp.asarray(h[k])[None]) + + def test_broadcasting4(self, xp): + # Test broadcasting with worN a 2-D array. + np.random.seed(123) + b = np.random.rand(4, 2, 1, 1) + a = np.random.rand(5, 2, 1, 1) + b, a = map(xp.asarray, (b, a)) + + for whole in [False, True]: + for worN in [np.random.rand(6, 7), np.empty((6, 0))]: + worN = xp.asarray(worN) + w, h = freqz(b, a, worN=worN, whole=whole) + xp_assert_close(w, worN, rtol=1e-14) + assert h.shape == (2,) + worN.shape + for k in range(2): + ww, hh = freqz(b[:, k, 0, 0], a[:, k, 0, 0], + worN=xp.reshape(worN, (-1,)), + whole=whole) + xp_assert_close(ww, xp.reshape(worN, (-1,)), rtol=1e-14) + xp_assert_close(hh, xp.reshape(h[k, :, :], (-1,))) + + def test_backward_compat(self): + # For backward compatibility, test if None act as a wrapper for default + w1, h1 = freqz([1.0], 1) + w2, h2 = freqz([1.0], 1, None) + assert_array_almost_equal(w1, w2) + assert_array_almost_equal(h1, h2) + + def test_fs_param(self, xp): + fs = 900 + b = xp.asarray([0.039479155677484369, 0.11843746703245311, 0.11843746703245311, + 0.039479155677484369]) + a = xp.asarray([1.0, -1.3199152021838287, 0.80341991081938424, + -0.16767146321568049]) + + # N = None, whole=False + w1, h1 = freqz(b, a, fs=fs) + w2, h2 = freqz(b, a) + xp_assert_close(h1, h2) + xp_assert_close(w1, xp.linspace(0, fs/2, 512, endpoint=False)) + + # N = None, whole=True + w1, h1 = freqz(b, a, whole=True, fs=fs) + w2, h2 = freqz(b, a, whole=True) + xp_assert_close(h1, h2) + xp_assert_close(w1, xp.linspace(0, fs, 512, endpoint=False)) + + # N = 5, whole=False + w1, h1 = freqz(b, a, 5, fs=fs) + w2, h2 = freqz(b, a, 5) + xp_assert_close(h1, h2) + xp_assert_close(w1, xp.linspace(0, fs/2, 5, endpoint=False)) + + # N = 5, whole=True + w1, h1 = freqz(b, a, 5, whole=True, fs=fs) + w2, h2 = freqz(b, a, 5, whole=True) + xp_assert_close(h1, h2) + xp_assert_close(w1, xp.linspace(0, fs, 5, endpoint=False)) + + if is_numpy(xp): + # w is an array_like + for w in ([123], (123,), xp.asarray([123]), (50, 123, 230), + xp.asarray([50, 123, 230])): + w1, h1 = freqz(b, a, w, fs=fs) + w2, h2 = freqz(b, a, 2*pi*xp.asarray(w, dtype=xp.float64)/ fs) + xp_assert_close(h1, h2) + xp_assert_close(w1, xp.asarray(w), check_dtype=False) + + def test_w_or_N_types(self): + # Measure at 7 (polyval) or 8 (fft) equally-spaced points + for N in (7, np.int8(7), np.int16(7), np.int32(7), np.int64(7), + np.array(7), + 8, np.int8(8), np.int16(8), np.int32(8), np.int64(8), + np.array(8)): + + w, h = freqz([1.0], worN=N) + assert_array_almost_equal(w, np.pi * np.arange(N) / N) + assert_array_almost_equal(h, np.ones(N)) + + w, h = freqz([1.0], worN=N, fs=100) + assert_array_almost_equal(w, np.linspace(0, 50, N, endpoint=False)) + assert_array_almost_equal(h, np.ones(N)) + + # Measure at frequency 8 Hz + for w in (8.0, 8.0+0j): + # Only makes sense when fs is specified + w_out, h = freqz(np.asarray([1.0]), worN=w, fs=100) + assert_array_almost_equal(w_out, np.asarray([8])) + assert_array_almost_equal(h, np.asarray(1.), check_0d=False) + + def test_nyquist(self, xp): + w, h = freqz(xp.asarray([1.0]), worN=8, include_nyquist=True) + assert_array_almost_equal(w, xp.pi * xp.arange(8, dtype=w.dtype) / 7.) + assert_array_almost_equal(h, xp.ones(8)) + w, h = freqz(xp.asarray([1.0]), worN=9, include_nyquist=True) + assert_array_almost_equal(w, xp.pi * xp.arange(9, dtype=w.dtype) / 8.) + assert_array_almost_equal(h, xp.ones(9)) + + for a in [1, xp.ones(2)]: + w, h = freqz(xp.ones(2), a, worN=0, include_nyquist=True) + assert w.shape == (0,) + assert h.shape == (0,) + hdt = xp.complex128 if xp_default_dtype(xp) == xp.float64 else xp.complex64 + assert h.dtype == hdt + + w1, h1 = freqz(xp.asarray([1.0]), worN=8, whole = True, include_nyquist=True) + w2, h2 = freqz(xp.asarray([1.0]), worN=8, whole = True, include_nyquist=False) + assert_array_almost_equal(w1, w2) + assert_array_almost_equal(h1, h2) + + # https://github.com/scipy/scipy/issues/17289 + # https://github.com/scipy/scipy/issues/15273 + @pytest.mark.parametrize('whole,nyquist,worN', + [(False, False, 32), + (False, True, 32), + (True, False, 32), + (True, True, 32), + (False, False, 257), + (False, True, 257), + (True, False, 257), + (True, True, 257)]) + + @xfail_xp_backends("cupy", reason="XXX: CuPy's version suspect") + def test_17289(self, whole, nyquist, worN, xp): + d = xp.asarray([0.0, 1.0]) + w, Drfft = freqz(d, worN=32, whole=whole, include_nyquist=nyquist) + _, Dpoly = freqz(d, worN=w) + xp_assert_close(Drfft, Dpoly) + + def test_fs_validation(self): + with pytest.raises(ValueError, match="Sampling.*single scalar"): + freqz([1.0], fs=np.array([10, 20])) + + with pytest.raises(ValueError, match="Sampling.*be none."): + freqz([1.0], fs=None) + + + +@make_xp_test_case(freqz_sos) +class TestFreqz_sos: + + def test_freqz_sos_basic(self, xp): + # Compare the results of freqz and freqz_sos for a low order + # Butterworth filter. + + N = 500 + + b, a = butter(4, 0.2) + sos = butter(4, 0.2, output='sos') + w, h = freqz(b, a, worN=N) + + w, h, sos = map(xp.asarray, (w, h, sos)) + w2, h2 = freqz_sos(sos, worN=N) + xp_assert_close(w2, w, rtol=1e-15) + xp_assert_close(h2, h, rtol=1e-10, atol=1e-14) + + b, a = ellip(3, 1, 30, (0.2, 0.3), btype='bandpass') + sos = ellip(3, 1, 30, (0.2, 0.3), btype='bandpass', output='sos') + w, h = freqz(b, a, worN=N) + + w, h, sos = map(xp.asarray, (w, h, sos)) + w2, h2 = freqz_sos(sos, worN=N) + xp_assert_close(w2, w, rtol=1e-15) + xp_assert_close(h2, h, rtol=1e-10, atol=1e-14) + + # must have at least one section + with assert_raises(ValueError): + freqz_sos(sos[:0, ...]) + + def test_backward_compat(self, xp): + # For backward compatibility, test if None act as a wrapper for default + N = 500 + + sos = butter(4, 0.2, output='sos') + w2, h2 = sosfreqz(sos, worN=N) + sos, w2, h2 = map(xp.asarray, (sos, w2, h2)) + w1, h1 = freqz_sos(sos, worN=N) + assert_array_almost_equal(w1, w2) + assert_array_almost_equal(h1, h2) + + @skip_xp_backends("dask.array", reason="float cannot be interpreted as an integer") + def test_freqz_sos_design(self, xp): + # Compare freqz_sos output against expected values for different + # filter types + # TODO: split into multiple tests, or parameterize across filter types + # in some way. + + # from cheb2ord + N, Wn = cheb2ord([0.1, 0.6], [0.2, 0.5], 3, 60) + sos = cheby2(N, 60, Wn, 'stop', output='sos') + sos = xp.asarray(sos) # XXX + zero = xp.asarray(0., dtype=xp.float64) + + w, h = freqz_sos(sos) + h = xp.abs(h) + w = w / xp.pi + xp_assert_close(20 * xp.log10(h[w <= 0.1]), + zero, atol=3.01, + check_shape=False) + xp_assert_close(20 * xp.log10(h[w >= 0.6]), + zero, atol=3.01, + check_shape=False) + xp_assert_close(h[(w >= 0.2) & (w <= 0.5)], + zero, atol=1e-3, + check_shape=False) # <= -60 dB + + N, Wn = cheb2ord([0.1, 0.6], [0.2, 0.5], 3, 150) + sos = cheby2(N, 150, Wn, 'stop', output='sos') + sos = xp.asarray(sos) + + w, h = freqz_sos(sos) + dB = 20*xp.log10(xp.abs(h)) + w = w / xp.pi + xp_assert_close(dB[w <= 0.1], zero, atol=3.01, check_shape=False) + xp_assert_close(dB[w >= 0.6], zero, atol=3.01, check_shape=False) + assert xp.all(dB[(w >= 0.2) & (w <= 0.5)] < -149.9) + + # from cheb1ord + N, Wn = cheb1ord(0.2, 0.3, 3, 40) + sos = cheby1(N, 3, Wn, 'low', output='sos') + sos = xp.asarray(sos) + + w, h = freqz_sos(sos) + h = xp.abs(h) + w = w / xp.pi + xp_assert_close(20 * xp.log10(h[w <= 0.2]), zero, atol=3.01, + check_shape=False) + xp_assert_close(h[w >= 0.3], zero, atol=1e-2, + check_shape=False) # <= -40 dB + + N, Wn = cheb1ord(0.2, 0.3, 1, 150) + sos = cheby1(N, 1, Wn, 'low', output='sos') + sos = xp.asarray(sos) + + w, h = freqz_sos(sos) + dB = 20*xp.log10(xp.abs(h)) + w /= np.pi + xp_assert_close(dB[w <= 0.2], zero, atol=1.01, check_shape=False) + assert xp.all(dB[w >= 0.3] < -149.9) + + # adapted from ellipord + N, Wn = ellipord(0.3, 0.2, 3, 60) + sos = ellip(N, 0.3, 60, Wn, 'high', output='sos') + sos = xp.asarray(sos) + + w, h = freqz_sos(sos) + h = xp.abs(h) + w = w / xp.pi + xp_assert_close(20 * xp.log10(h[w >= 0.3]), zero, atol=3.01, + check_shape=False) + xp_assert_close(h[w <= 0.1], zero, atol=1.5e-3, + check_shape=False) # <= -60 dB (approx) + + # adapted from buttord + N, Wn = buttord([0.2, 0.5], [0.14, 0.6], 3, 40) + sos = butter(N, Wn, 'band', output='sos') + sos = xp.asarray(sos) + + w, h = freqz_sos(sos) + h = xp.abs(h) + w = w / xp.pi + + h014 = h[w <= 0.14] + xp_assert_close(h014, xp.zeros_like(h014), atol=1e-2) # <= -40 dB + h06 = h[w >= 0.6] + xp_assert_close(h06, xp.zeros_like(h06), atol=1e-2) # <= -40 dB + h0205 = 20 * xp.log10(h[(w >= 0.2) & (w <= 0.5)]) + xp_assert_close(h0205, xp.zeros_like(h0205), atol=3.01) + + N, Wn = buttord([0.2, 0.5], [0.14, 0.6], 3, 100) + sos = butter(N, Wn, 'band', output='sos') + sos = xp.asarray(sos) + + w, h = freqz_sos(sos) + dB = 20*xp.log10(xp.maximum(xp.abs(h), xp.asarray(1e-10))) + w = w / xp.pi + + assert xp.all(dB[(w > 0) & (w <= 0.14)] < -99.9) + assert xp.all(dB[w >= 0.6] < -99.9) + db0205 = dB[(w >= 0.2) & (w <= 0.5)] + xp_assert_close(db0205, xp.zeros_like(db0205), atol=3.01) + + def test_freqz_sos_design_ellip(self, xp): + N, Wn = ellipord(0.3, 0.1, 3, 60) + sos = ellip(N, 0.3, 60, Wn, 'high', output='sos') + sos = xp.asarray(sos) + + w, h = freqz_sos(sos) + h = xp.abs(h) + w = w / xp.pi + + h03 = 20 * xp.log10(h[w >= 0.3]) + xp_assert_close(h03, xp.zeros_like(h03), atol=3.01) + h01 = h[w <= 0.1] + xp_assert_close(h01, xp.zeros_like(h01), atol=1.5e-3) # <= -60 dB (approx) + + N, Wn = ellipord(0.3, 0.2, .5, 150) + sos = ellip(N, .5, 150, Wn, 'high', output='sos') + sos = xp.asarray(sos) + + w, h = freqz_sos(sos) + dB = 20*xp.log10(xp.maximum(xp.abs(h), xp.asarray(1e-10))) + w = w / xp.pi + + db03 = dB[w >= 0.3] + xp_assert_close(db03, xp.zeros_like(db03), atol=.55) + # Allow some numerical slop in the upper bound -150, so this is + # a check that dB[w <= 0.2] is less than or almost equal to -150. + assert xp.max(dB[w <= 0.2]) < -150*(1 - 1e-12) + + @pytest.mark.thread_unsafe( + reason=("mpmath gmpy2 backend is not thread-safe, " + "see https://github.com/mpmath/mpmath/issues/974")) + @mpmath_check("0.10") + def test_freqz_sos_against_mp(self, xp): + # Compare the result of freqz_sos applied to a high order Butterworth + # filter against the result computed using mpmath. (signal.freqz fails + # miserably with such high order filters.) + from . import mpsig + N = 500 + order = 25 + Wn = 0.15 + with mpmath.workdps(80): + z_mp, p_mp, k_mp = mpsig.butter_lp(order, Wn) + w_mp, h_mp = mpsig.zpkfreqz(z_mp, p_mp, k_mp, N) + w_mp = xp.asarray([float(x) for x in w_mp], dtype=xp.float64) + h_mp = xp.asarray([complex(x) for x in h_mp], dtype=xp.complex128) + + sos = butter(order, Wn, output='sos') + sos = xp.asarray(sos, dtype=xp.float64) + w, h = freqz_sos(sos, worN=N) + xp_assert_close(w, w_mp, rtol=1e-12, atol=1e-14) + xp_assert_close(h, h_mp, rtol=1e-12, atol=1e-14) + + def test_fs_param(self, xp): + fs = 900 + sos = xp.asarray( + [[0.03934683014103762, 0.07869366028207524, 0.03934683014103762, + 1.0, -0.37256600288916636, 0.0], + [1.0, 1.0, 0.0, 1.0, -0.9495739996946778, 0.45125966317124144]] + ) + + # N = None, whole=False + w1, h1 = freqz_sos(sos, fs=fs) + w2, h2 = freqz_sos(sos) + xp_assert_close(h1, h2) + xp_assert_close(w1, xp.linspace(0, fs/2, 512, endpoint=False)) + + # N = None, whole=True + w1, h1 = freqz_sos(sos, whole=True, fs=fs) + w2, h2 = freqz_sos(sos, whole=True) + xp_assert_close(h1, h2, atol=1e-27) + xp_assert_close(w1, xp.linspace(0, fs, 512, endpoint=False)) + + # N = 5, whole=False + w1, h1 = freqz_sos(sos, 5, fs=fs) + w2, h2 = freqz_sos(sos, 5) + xp_assert_close(h1, h2) + xp_assert_close(w1, xp.linspace(0, fs/2, 5, endpoint=False)) + + # N = 5, whole=True + w1, h1 = freqz_sos(sos, 5, whole=True, fs=fs) + w2, h2 = freqz_sos(sos, 5, whole=True) + xp_assert_close(h1, h2) + xp_assert_close(w1, xp.linspace(0, fs, 5, endpoint=False)) + + @skip_xp_backends(np_only=True, reason="array-likes") + def test_fs_param2(self, xp): + fs = 900 + sos = xp.asarray( + [[0.03934683014103762, 0.07869366028207524, 0.03934683014103762, + 1.0, -0.37256600288916636, 0.0], + [1.0, 1.0, 0.0, 1.0, -0.9495739996946778, 0.45125966317124144]] + ) + + # w is an array_like + for w in ([123], (123,), xp.asarray([123]), (50, 123, 230), + xp.asarray([50, 123, 230])): + w1, h1 = freqz_sos(sos, w, fs=fs) + w1, h1 = map(xp.asarray, (w1, h1)) + + w2, h2 = freqz_sos(sos, 2*pi*xp.asarray(w, dtype=sos.dtype)/fs) + xp_assert_close(h1, h2) + xp_assert_close(w, w1, check_dtype=False) + + def test_w_or_N_types(self): + # Measure at 7 (polyval) or 8 (fft) equally-spaced points + for N in (7, np.int8(7), np.int16(7), np.int32(7), np.int64(7), + np.array(7), + 8, np.int8(8), np.int16(8), np.int32(8), np.int64(8), + np.array(8)): + + w, h = freqz_sos([1, 0, 0, 1, 0, 0], worN=N) + assert_array_almost_equal(w, np.pi * np.arange(N) / N) + assert_array_almost_equal(h, np.ones(N)) + + w, h = freqz_sos([1, 0, 0, 1, 0, 0], worN=N, fs=100) + assert_array_almost_equal(w, np.linspace(0, 50, N, endpoint=False)) + assert_array_almost_equal(h, np.ones(N)) + + # Measure at frequency 8 Hz + for w in (8.0, 8.0+0j): + # Only makes sense when fs is specified + w_out, h = freqz_sos([1, 0, 0, 1, 0, 0], worN=w, fs=100) + assert_array_almost_equal(w_out, [8]) + assert_array_almost_equal(h, [1]) + + def test_fs_validation(self): + sos = butter(4, 0.2, output='sos') + with pytest.raises(ValueError, match="Sampling.*single scalar"): + freqz_sos(sos, fs=np.array([10, 20])) + + +@make_xp_test_case(freqz_zpk) +class TestFreqz_zpk: + + def test_ticket1441(self, xp): + """Regression test for ticket 1441.""" + # Because freqz previously used arange instead of linspace, + # when N was large, it would return one more point than + # requested. + N = 100000 + w, h = freqz_zpk(xp.asarray([0.5]), xp.asarray([0.5]), 1.0, worN=N) + assert w.shape == (N,) + + def test_basic(self, xp): + w, h = freqz_zpk(xp.asarray([0.5]), xp.asarray([0.5]), 1.0, worN=8) + assert_array_almost_equal(w, xp.pi * xp.arange(8.0) / 8) + assert_array_almost_equal(h, xp.ones(8)) + + def test_basic_whole(self, xp): + w, h = freqz_zpk(xp.asarray([0.5]), xp.asarray([0.5]), 1.0, worN=8, whole=True) + assert_array_almost_equal(w, 2 * xp.pi * xp.arange(8.0) / 8) + assert_array_almost_equal(h, xp.ones(8)) + + @pytest.mark.xfail(DEFAULT_F32, reason="wrong answer with torch/float32") + def test_vs_freqz(self, xp): + b, a = cheby1(4, 5, 0.5, analog=False, output='ba') + z, p, k = cheby1(4, 5, 0.5, analog=False, output='zpk') + + w1, h1 = freqz(b, a) + z, p, k, w1, h1 = map(xp.asarray, (z, p, k, w1, h1)) + w2, h2 = freqz_zpk(z, p, k) + xp_assert_close(w1, w2) + xp_assert_close(h1, h2, rtol=1.3e-6) + + def test_backward_compat(self, xp): + # For backward compatibility, test if None act as a wrapper for default + w1, h1 = freqz_zpk(xp.asarray([0.5]), xp.asarray([0.5]), 1.0) + w2, h2 = freqz_zpk(xp.asarray([0.5]), xp.asarray([0.5]), 1.0, None) + assert_array_almost_equal(w1, w2) + assert_array_almost_equal(h1, h2) + + def test_fs_param(self, xp): + fs = 900 + z = xp.asarray([-1, -1, -1.0]) + p = xp.asarray( + [0.4747869998473389 + 0.4752230717749344j, + 0.37256600288916636, + 0.4747869998473389 - 0.4752230717749344j] + ) + k = 0.03934683014103762 + + # N = None, whole=False + w1, h1 = freqz_zpk(z, p, k, whole=False, fs=fs) + w2, h2 = freqz_zpk(z, p, k, whole=False) + xp_assert_close(h1, h2) + xp_assert_close(w1, xp.linspace(0, fs/2, 512, endpoint=False)) + + # N = None, whole=True + w1, h1 = freqz_zpk(z, p, k, whole=True, fs=fs) + w2, h2 = freqz_zpk(z, p, k, whole=True) + xp_assert_close(h1, h2) + xp_assert_close(w1, xp.linspace(0, fs, 512, endpoint=False)) + + # N = 5, whole=False + w1, h1 = freqz_zpk(z, p, k, 5, fs=fs) + w2, h2 = freqz_zpk(z, p, k, 5) + xp_assert_close(h1, h2) + xp_assert_close(w1, xp.linspace(0, fs/2, 5, endpoint=False)) + + # N = 5, whole=True + w1, h1 = freqz_zpk(z, p, k, 5, whole=True, fs=fs) + w2, h2 = freqz_zpk(z, p, k, 5, whole=True) + xp_assert_close(h1, h2) + xp_assert_close(w1, xp.linspace(0, fs, 5, endpoint=False)) + + @skip_xp_backends(np_only=True, reason="array_likes") + def test_fs_param2(self, xp): + fs = 900 + z = xp.asarray([-1, -1, -1.0]) + p = xp.asarray( + [0.4747869998473389 + 0.4752230717749344j, + 0.37256600288916636, + 0.4747869998473389 - 0.4752230717749344j] + ) + k = 0.03934683014103762 + + # w is an array_like + for w in ([123], (123,), xp.asarray([123]), (50, 123, 230), + xp.asarray([50, 123, 230])): + w1, h1 = freqz_zpk(z, p, k, w, fs=fs) + w2, h2 = freqz_zpk(z, p, k, 2*pi*xp.asarray(w)/fs) + xp_assert_close(h1, h2) + xp_assert_close(w, w1, check_dtype=False) + + def test_w_or_N_types(self): + # Measure at 8 equally-spaced points + for N in (8, np.int8(8), np.int16(8), np.int32(8), np.int64(8), + np.array(8)): + + w, h = freqz_zpk([], [], 1, worN=N) + assert_array_almost_equal(w, np.pi * np.arange(8) / 8.) + assert_array_almost_equal(h, np.ones(8)) + + w, h = freqz_zpk([], [], 1, worN=N, fs=100) + assert_array_almost_equal(w, np.linspace(0, 50, 8, endpoint=False)) + assert_array_almost_equal(h, np.ones(8)) + + # Measure at frequency 8 Hz + for w in (8.0, 8.0+0j): + # Only makes sense when fs is specified + w_out, h = freqz_zpk([], [], 1, worN=w, fs=100) + assert_array_almost_equal(w_out, [8]) + assert_array_almost_equal(h, [1]) + + def test_fs_validation(self): + with pytest.raises(ValueError, match="Sampling.*single scalar"): + freqz_zpk([1.0], [1.0], [1.0], fs=np.array([10., 20])) + + with pytest.raises(ValueError, match="Sampling.*be none."): + freqz_zpk([1.0], [1.0], [1.0], fs=None) + + +@make_xp_test_case(normalize) +class TestNormalize: + + def test_allclose(self, xp): + """Test for false positive on allclose in normalize() in + filter_design.py""" + # Test to make sure the allclose call within signal.normalize does not + # choose false positives. Then check against a known output from MATLAB + # to make sure the fix doesn't break anything. + + # These are the coefficients returned from + # `[b,a] = cheby1(8, 0.5, 0.048)' + # in MATLAB. There are at least 15 significant figures in each + # coefficient, so it makes sense to test for errors on the order of + # 1e-13 (this can always be relaxed if different platforms have + # different rounding errors) + b_matlab = xp.asarray([2.150733144728282e-11, 1.720586515782626e-10, + 6.022052805239190e-10, 1.204410561047838e-09, + 1.505513201309798e-09, 1.204410561047838e-09, + 6.022052805239190e-10, 1.720586515782626e-10, + 2.150733144728282e-11]) + a_matlab = xp.asarray([1.000000000000000e+00, -7.782402035027959e+00, + 2.654354569747454e+01, -5.182182531666387e+01, + 6.334127355102684e+01, -4.963358186631157e+01, + 2.434862182949389e+01, -6.836925348604676e+00, + 8.412934944449140e-01]) + + # This is the input to signal.normalize after passing through the + # equivalent steps in signal.iirfilter as was done for MATLAB + b_norm_in = xp.asarray([1.5543135865293012e-06, 1.2434508692234413e-05, + 4.3520780422820447e-05, 8.7041560845640893e-05, + 1.0880195105705122e-04, 8.7041560845640975e-05, + 4.3520780422820447e-05, 1.2434508692234413e-05, + 1.5543135865293012e-06]) + a_norm_in = xp.asarray([7.2269025909127173e+04, -5.6242661430467968e+05, + 1.9182761917308895e+06, -3.7451128364682454e+06, + 4.5776121393762771e+06, -3.5869706138592605e+06, + 1.7596511818472347e+06, -4.9409793515707983e+05, + 6.0799461347219651e+04]) + + b_output, a_output = normalize(b_norm_in, a_norm_in) + + # The test on b works for decimal=14 but the one for a does not. For + # the sake of consistency, both of these are decimal=13. If something + # breaks on another platform, it is probably fine to relax this lower. + decimal = 13 if xp_default_dtype(xp) == xp.float64 else 5 + assert_array_almost_equal(b_matlab, b_output, decimal=decimal) + assert_array_almost_equal(a_matlab, a_output, decimal=decimal) + + def test_errors(self): + """Test the error cases.""" + # all zero denominator + assert_raises(ValueError, normalize, [1, 2], 0) + + # denominator not 1 dimensional + assert_raises(ValueError, normalize, [1, 2], [[1]]) + + # numerator too many dimensions + assert_raises(ValueError, normalize, [[[1, 2]]], 1) + + +@make_xp_test_case(lp2lp) +class TestLp2lp: + + def test_basic(self, xp): + b = xp.asarray([1]) + a = xp.asarray([1, math.sqrt(2), 1]) + b_lp, a_lp = lp2lp(b, a, 0.38574256627112119) + assert_array_almost_equal(b_lp, xp.asarray([0.1488]), decimal=4) + assert_array_almost_equal(a_lp, xp.asarray([1, 0.5455, 0.1488]), decimal=4) + + +@make_xp_test_case(lp2hp) +class TestLp2hp: + + def test_basic(self, xp): + b = xp.asarray([0.25059432325190018]) + a = xp.asarray( + [1, 0.59724041654134863, 0.92834805757524175, 0.25059432325190018] + ) + b_hp, a_hp = lp2hp(b, a, 2*math.pi*5000) + xp_assert_close(b_hp, xp.asarray([1.0, 0, 0, 0])) + xp_assert_close( + a_hp, xp.asarray([1, 1.1638e5, 2.3522e9, 1.2373e14]), rtol=1e-4 + ) + + +@make_xp_test_case(lp2bp) +class TestLp2bp: + + def test_basic(self, xp): + b = xp.asarray([1]) + a = xp.asarray([1, 2, 2, 1]) + b_bp, a_bp = lp2bp(b, a, 2*math.pi*4000, 2*math.pi*2000) + xp_assert_close(b_bp, xp.asarray([1.9844e12, 0, 0, 0]), rtol=1e-6) + xp_assert_close( + a_bp, + xp.asarray([1, 2.5133e4, 2.2108e9, 3.3735e13, + 1.3965e18, 1.0028e22, 2.5202e26]), rtol=1e-4 + ) + + +@make_xp_test_case(lp2bs) +class TestLp2bs: + + def test_basic(self, xp): + b = xp.asarray([1]) + a = xp.asarray([1, 1]) + b_bs, a_bs = lp2bs(b, a, 0.41722257286366754, 0.18460575326152251) + assert_array_almost_equal(b_bs, xp.asarray([1, 0, 0.17407]), decimal=5) + assert_array_almost_equal(a_bs, xp.asarray([1, 0.18461, 0.17407]), decimal=5) + + +@make_xp_test_case(bilinear) +class TestBilinear: + """Tests for function `signal.bilinear`. """ + + def test_exceptions(self): + """Raise all exceptions in `bilinear()`. """ + with pytest.raises(ValueError, match="Parameter a is not .*"): + bilinear(1., np.array([[1, 2, 3]])) + with pytest.raises(ValueError, match="Parameter b is not .*"): + bilinear(np.ones((2,3)), 1. ) + + @pytest.mark.xfail(DEFAULT_F32, reason="wrong answer with torch/float32") + def test_basic(self, xp): + # reference output values computed with sympy + b = [0.14879732743343033] + a = [1, 0.54552236880522209, 0.14879732743343033] + b, a = map(xp.asarray, (b, a)) + + b_zref = xp.asarray( + [0.08782128175913713, 0.17564256351827426, 0.08782128175913713] + ) + a_zref = xp.asarray( + [1.0, -1.0047722097030667, 0.3560573367396151] + ) + + b_z, a_z = bilinear(b, a, 0.5) + + xp_assert_close_nulp(b_z, b_zref) + xp_assert_close_nulp(a_z, a_zref) + + b = xp.asarray([1, 0, 0.17407467530697837]) + a = xp.asarray([1, 0.18460575326152251, 0.17407467530697837]) + + b_zref = xp.asarray( + [0.8641286432189045, -1.2157757001964216, 0.8641286432189045] + ) + a_zref = xp.asarray([1.0, -1.2157757001964216, 0.7282572864378091]) + + b_z, a_z = bilinear(b, a, 0.5) + + xp_assert_close_nulp(b_z, xp.asarray(b_zref)) + xp_assert_close_nulp(a_z, xp.asarray(a_zref)) + + @pytest.mark.xfail(DEFAULT_F32, reason="wrong answer with torch/float32") + @xfail_xp_backends("cupy", reason="https://github.com/cupy/cupy/issues/9404") + def test_ignore_leading_zeros(self, xp): + # regression for gh-6606 + # results shouldn't change when leading zeros are added to + # input numerator or denominator + b = [0.14879732743343033] + a = [1, 0.54552236880522209, 0.14879732743343033] + b, a = map(xp.asarray, (b, a)) + + b_zref = xp.asarray( + [0.08782128175913713, 0.17564256351827426, 0.08782128175913713] + ) + a_zref = xp.asarray([1.0, -1.0047722097030667, 0.3560573367396151]) + + for lzn, lzd in product(range(4), range(4)): + b_z, a_z = bilinear(xpx.pad(b, (lzn, 0), xp=xp), + xpx.pad(a, (lzd, 0), xp=xp), + 0.5) + xp_assert_close_nulp(b_z, b_zref) + xp_assert_close_nulp(a_z, a_zref) + + @pytest.mark.xfail(DEFAULT_F32, reason="wrong answer with torch/float32") + @xfail_xp_backends("cupy", reason="complex inputs not supported") + def test_complex(self, xp): + # reference output values computed with sympy + # this is an elliptical filter, 5Hz width, centered at +50Hz: + # z, p, k = signal.ellip(2, 0.5, 20, 2*np.pi*5/2, output='zpk', analog=True) + # z = z.astype(complex) + 2j * np.pi * 50 + # p = p.astype(complex) + 2j * np.pi * 50 + # b, a = signal.zpk2tf(z, p, k) + b = [(0.09999999999999991+0j), + -62.831853071795805j, + (-9505.857007071314+0j)] + a = [(1+0j), + (21.09511000343942-628.3185307179587j), + (-98310.74322875646-6627.2242613473845j)] + b, a = map(xp.asarray, (b, a)) + + # sample frequency + fs = 1000 + b_zref = [(0.09905575106715676-0.00013441423112828688j), + (-0.18834281923181084-0.06032810039049478j), + (0.08054306669414343+0.05766172295523972j)] + a_zref = [(1+0j), + (-1.8839476369292854-0.606808151331815j), + (0.7954687330018285+0.5717459398142481j)] + + b_zref, a_zref = map(xp.asarray, (b_zref, a_zref)) + + b_z, a_z = bilinear(b, a, fs) + + # the 3 ulp difference determined from testing + xp_assert_close_nulp(b_z, b_zref, nulp=3) + xp_assert_close_nulp(a_z, a_zref, nulp=3) + + def test_fs_validation(self): + b = [0.14879732743343033] + a = [1, 0.54552236880522209, 0.14879732743343033] + with pytest.raises(ValueError, match="Sampling.*single scalar"): + bilinear(b, a, fs=np.array([10, 20])) + + with pytest.raises(ValueError, match="Sampling.*be none"): + bilinear(b, a, fs=None) + + +@make_xp_test_case(lp2lp_zpk) +class TestLp2lp_zpk: + + @xfail_xp_backends( + 'dask.array', reason='https://github.com/dask/dask/issues/11883' + ) + def test_basic(self, xp): + z = xp.asarray([]) + p = xp.asarray([(-1+1j) / math.sqrt(2), (-1-1j) / math.sqrt(2)]) + k = 1 + z_lp, p_lp, k_lp = lp2lp_zpk(z, p, k, 5) + xp_assert_equal(z_lp, xp.asarray([])) + xp_assert_close(_sort_cmplx(p_lp, xp=xp), _sort_cmplx(p, xp=xp) * 5) + assert k_lp == 25. + + # Pseudo-Chebyshev with both poles and zeros + z = xp.asarray([-2j, +2j]) + p = xp.asarray([-0.75, -0.5-0.5j, -0.5+0.5j]) + k = 3 + z_lp, p_lp, k_lp = lp2lp_zpk(z, p, k, 20) + xp_assert_close( + _sort_cmplx(z_lp, xp=xp), _sort_cmplx([-40j, +40j], xp=xp) + ) + xp_assert_close( + _sort_cmplx(p_lp, xp=xp), _sort_cmplx([-15, -10-10j, -10+10j], xp=xp) + ) + assert k_lp == 60. + + def test_fs_validation(self): + z = [-2j, +2j] + p = [-0.75, -0.5 - 0.5j, -0.5 + 0.5j] + k = 3 + + with pytest.raises(ValueError, match="Sampling.*single scalar"): + bilinear_zpk(z, p, k, fs=np.array([10, 20])) + + with pytest.raises(ValueError, match="Sampling.*be none"): + bilinear_zpk(z, p, k, fs=None) + + +@make_xp_test_case(lp2hp_zpk) +class TestLp2hp_zpk: + + @xfail_xp_backends( + 'dask.array', reason='https://github.com/dask/dask/issues/11883' + ) + def test_basic(self, xp): + z = xp.asarray([]) + p = xp.asarray([(-1+1j) / math.sqrt(2), (-1-1j) / math.sqrt(2)]) + k = 1 + + z_hp, p_hp, k_hp = lp2hp_zpk(z, p, k, 5) + xp_assert_equal(z_hp, xp.asarray([0.0, 0.0], dtype=z_hp.dtype)) + xp_assert_close(_sort_cmplx(p_hp, xp=xp), _sort_cmplx(p, xp=xp) * 5) + assert math.isclose(k_hp, 1.0, rel_tol=4e-7) + + z = xp.asarray([-2j, +2j]) + p = xp.asarray([-0.75, -0.5-0.5j, -0.5+0.5j]) + k = 3 + z_hp, p_hp, k_hp = lp2hp_zpk(z, p, k, 6) + xp_assert_close( + _sort_cmplx(z_hp, xp=xp), _sort_cmplx([-3j, 0, +3j], xp=xp) + ) + xp_assert_close( + _sort_cmplx(p_hp, xp=xp), _sort_cmplx([-8, -6-6j, -6+6j], xp=xp) + ) + assert k_hp == 32.0 + + +@make_xp_test_case(lp2bp_zpk) +class TestLp2bp_zpk: + + @xfail_xp_backends( + 'dask.array', reason='https://github.com/dask/dask/issues/11883' + ) + def test_basic(self, xp): + z = xp.asarray([-2j, +2j]) + p = xp.asarray([-0.75, -0.5-0.5j, -0.5+0.5j]) + k = 3 + z_bp, p_bp, k_bp = lp2bp_zpk(z, p, k, 15, 8) + xp_assert_close( + _sort_cmplx(z_bp, xp=xp), + _sort_cmplx([-25j, -9j, 0, +9j, +25j], xp=xp), check_dtype=False + ) + xp_assert_close( + _sort_cmplx(p_bp, xp=xp), + _sort_cmplx( + [-3 + 6j*math.sqrt(6), -3 - 6j*math.sqrt(6), + +2j + cmath.sqrt(-8j - 225) - 2, -2j + cmath.sqrt(+8j - 225) - 2, + +2j - cmath.sqrt(-8j - 225) - 2, -2j - cmath.sqrt(+8j - 225) - 2 + ], xp=xp + ), check_dtype=False + ) + assert math.isclose(k_bp, 24.0) + + +@make_xp_test_case(lp2bs_zpk) +class TestLp2bs_zpk: + + @xfail_xp_backends( + 'dask.array', reason='https://github.com/dask/dask/issues/11883' + ) + def test_basic(self, xp): + z = xp.asarray([-2j, +2j]) + p = xp.asarray([-0.75, -0.5-0.5j, -0.5+0.5j]) + k = 3 + + z_bs, p_bs, k_bs = lp2bs_zpk(z, p, k, 35, 12) + + xp_assert_close( + _sort_cmplx(z_bs, xp=xp), + _sort_cmplx([+35j, -35j, + +3j + math.sqrt(1234)*1j, + -3j + math.sqrt(1234)*1j, + +3j - math.sqrt(1234)*1j, + -3j - math.sqrt(1234)*1j], xp=xp), check_dtype=False + ) + xp_assert_close( + _sort_cmplx(p_bs, xp=xp), + _sort_cmplx([+3j*math.sqrt(129) - 8, + -3j*math.sqrt(129) - 8, + (-6 + 6j) - cmath.sqrt(-1225 - 72j), + (-6 - 6j) - cmath.sqrt(-1225 + 72j), + (-6 + 6j) + cmath.sqrt(-1225 - 72j), + (-6 - 6j) + cmath.sqrt(-1225 + 72j), ], xp=xp), + check_dtype=False + ) + assert math.isclose(k_bs, 32.0) + + +@make_xp_test_case(bilinear_zpk) +class TestBilinear_zpk: + + @xfail_xp_backends( + 'dask.array', reason='https://github.com/dask/dask/issues/11883' + ) + def test_basic(self, xp): + z = xp.asarray([-2j, +2j]) + p = xp.asarray([-0.75, -0.5-0.5j, -0.5+0.5j]) + k = 3 + + z_d, p_d, k_d = bilinear_zpk(z, p, k, 10) + + xp_assert_close( + _sort_cmplx(z_d, xp=xp), + _sort_cmplx([(20-2j) / (20+2j), (20+2j) / (20-2j), -1], xp=xp) + ) + xp_assert_close( + _sort_cmplx(p_d, xp=xp), + _sort_cmplx( + [77/83, (1j/2 + 39/2) / (41/2 - 1j/2), (39/2 - 1j/2) / (1j/2 + 41/2)], + xp=xp + ) + ) + assert math.isclose(k_d, 9696/69803, rel_tol=4e-7) + + +class TestPrototypeType: + + def test_output_type(self): + # Prototypes should consistently output arrays, not lists + # https://github.com/scipy/scipy/pull/441 + for func in (buttap, + besselap, + lambda N: cheb1ap(N, 1), + lambda N: cheb2ap(N, 20), + lambda N: ellipap(N, 1, 20)): + for N in range(7): + z, p, k = func(N) + assert isinstance(z, np.ndarray) + assert isinstance(p, np.ndarray) + + @pytest.mark.parametrize( + 'base_func,func', [ + make_xp_pytest_param(buttap, buttap), + make_xp_pytest_param(besselap, besselap), + make_xp_pytest_param(cheb1ap, lambda N, xp: cheb1ap(N, 1, xp=xp)), + make_xp_pytest_param(cheb2ap, lambda N, xp: cheb2ap(N, 20, xp=xp)), + make_xp_pytest_param(ellipap, lambda N, xp: ellipap(N, 1, 20, xp=xp)), + ], + ids=['butter', 'bessel', 'cheb1', 'cheb2', 'ellip'] + ) + def test_with_xp(self, base_func, func, xp): + func(7, xp=xp) + + +def dB(x): + # Return magnitude in decibels, avoiding divide-by-zero warnings + # (and deal with some "not less-ordered" errors when -inf shows up) + xp = array_namespace(x) + tiny = xp.asarray(np.finfo(np.float64).tiny) + return 20 * xp.log10(xp.maximum(xp.abs(x), tiny)) + + +@make_xp_test_case(buttord) +@pytest.mark.skipif(DEFAULT_F32, reason="XXX needs figuring out") +@skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") +class TestButtord: + + def test_lowpass(self, xp): + wp = 0.2 + ws = 0.3 + rp = 3 + rs = 60 + N, Wn = buttord(xp.asarray(wp), ws, rp, rs, False) + b, a = butter(N, _xp_copy_to_numpy(Wn), 'lowpass', False) + w, h = freqz(b, a) + w /= np.pi + assert np.all(-rp < dB(h[w <= wp])) + assert np.all(dB(h[ws <= w]) < -rs) + + assert N == 16 + xp_assert_close(Wn, + xp.asarray(2.0002776782743284e-01), rtol=1e-15, check_0d=False) + + def test_highpass(self, xp): + wp = 0.3 + ws = 0.2 + rp = 3 + rs = 70 + N, Wn = buttord(xp.asarray(wp), ws, rp, rs, False) + b, a = butter(N, _xp_copy_to_numpy(Wn), 'highpass', False) + w, h = freqz(b, a) + w /= np.pi + assert np.all(-rp < dB(h[wp <= w])) + assert np.all(dB(h[w <= ws]) < -rs) + + assert N == 18 + xp_assert_close(Wn, + xp.asarray(2.9996603079132672e-01), rtol=1e-15, check_0d=False) + + def test_bandpass(self, xp): + wp = [0.2, 0.5] + ws = [0.1, 0.6] + rp = 3 + rs = 80 + N, Wn = buttord(xp.asarray(wp), xp.asarray(ws), rp, rs, False) + b, a = butter(N, _xp_copy_to_numpy(Wn), 'bandpass', False) + w, h = freqz(b, a) + w /= np.pi + + assert np.all((-rp - 0.1) < dB(h[np.logical_and(wp[0] <= w, w <= wp[1])])) + + assert np.all(dB(h[np.logical_or(w <= ws[0], ws[1] <= w)]) < (-rs + 0.1)) + + assert N == 18 + xp_assert_close( + Wn, xp.asarray([1.9998742411409134e-01, 5.0002139595676276e-01]), + rtol=1e-15, + ) + + @skip_xp_backends( + cpu_only=True, exceptions=["cupy"], reason="optimize.fminbound" + ) + def test_bandstop(self, xp): + wp = [0.1, 0.6] + ws = [0.2, 0.5] + rp = 3 + rs = 90 + N, Wn = buttord(xp.asarray(wp), xp.asarray(ws), rp, rs, False) + b, a = butter(N, _xp_copy_to_numpy(Wn), 'bandstop', False) + w, h = freqz(b, a) + w /= np.pi + + assert np.all(-rp < dB(h[np.logical_or(w <= wp[0], wp[1] <= w)])) + assert np.all(dB(h[np.logical_and(ws[0] <= w, w <= ws[1])]) < -rs) + + assert N == 20 + xp_assert_close( + Wn, xp.asarray([1.4759432329294042e-01, 5.9997365985276407e-01]), + rtol=1e-6 + ) + + def test_analog(self, xp): + wp = 200. + ws = 600. + rp = 3 + rs = 60 + N, Wn = buttord(xp.asarray(wp), ws, rp, rs, True) + b, a = butter(N, _xp_copy_to_numpy(Wn), 'lowpass', True) + w, h = freqs(b, a) + assert np.all(-rp < dB(h[w <= wp])) + assert np.all(dB(h[ws <= w]) < -rs) + + assert N == 7 + xp_assert_close( + Wn, xp.asarray(2.0006785355671877e+02), rtol=1e-15, check_0d=False + ) + + n, Wn = buttord(1., xp.asarray(550/450), 1, 26, analog=True) + assert n == 19 + xp_assert_close( + Wn, xp.asarray(1.0361980524629517), rtol=1e-15, check_0d=False + ) + + assert buttord(1, xp.asarray(1.2), 1, 80, analog=True)[0] == 55 + + def test_fs_param(self, xp): + wp = [4410, 11025] + ws = [2205, 13230] + rp = 3 + rs = 80 + fs = 44100 + N, Wn = buttord(xp.asarray(wp), xp.asarray(ws), rp, rs, False, fs=fs) + b, a = butter(N, _xp_copy_to_numpy(Wn), 'bandpass', False, fs=fs) + w, h = freqz(b, a, fs=fs) + + assert np.all(-rp - 0.1 < dB(h[np.logical_and(wp[0] <= w, w <= wp[1])])) + assert np.all(dB(h[np.logical_or(w <= ws[0], ws[1] <= w)]) < -rs + 0.1) + + assert N == 18 + xp_assert_close(Wn, xp.asarray([4409.722701715714, 11025.47178084662]), + rtol=1e-15) + + def test_invalid_input(self): + with pytest.raises(ValueError) as exc_info: + buttord([20, 50], [14, 60], 3, 2) + assert "gpass should be smaller than gstop" in str(exc_info.value) + + with pytest.raises(ValueError) as exc_info: + buttord([20, 50], [14, 60], -1, 2) + assert "gpass should be larger than 0.0" in str(exc_info.value) + + with pytest.raises(ValueError) as exc_info: + buttord([20, 50], [14, 60], 1, -2) + assert "gstop should be larger than 0.0" in str(exc_info.value) + + def test_runtime_warnings(self): + msg = "Order is zero.*|divide by zero encountered" + with pytest.warns(RuntimeWarning, match=msg): + buttord(0.0, 1.0, 3, 60) + + def test_ellip_butter(self): + # The purpose of the test is to compare to some known output from past + # scipy versions. The values to compare to are generated with scipy + # 1.9.1 (there is nothing special about this particular version though) + n, wn = buttord([0.1, 0.6], [0.2, 0.5], 3, 60) + assert n == 14 + + def test_fs_validation(self): + wp = 0.2 + ws = 0.3 + rp = 3 + rs = 60 + + with pytest.raises(ValueError, match="Sampling.*single scalar"): + buttord(wp, ws, rp, rs, False, fs=np.array([10, 20])) + + +@make_xp_test_case(cheb1ord) +@skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") +class TestCheb1ord: + + @xfail_xp_backends("torch", reason="accuracy is bad") + def test_lowpass(self, xp): + wp = 0.2 + ws = 0.3 + rp = 3 + rs = 60 + N, Wn = cheb1ord(xp.asarray(wp), ws, rp, rs, False) + b, a = cheby1(N, rp, _xp_copy_to_numpy(Wn), 'low', False) + w, h = freqz(b, a) + w /= np.pi + assert np.all(-rp - 0.1 < dB(h[w <= wp])) + assert np.all(dB(h[ws <= w]) < -rs + 0.1) + + assert N == 8 + xp_assert_close(Wn, xp.asarray(0.2), rtol=1e-15, check_0d=False) + + @xfail_xp_backends("torch", reason="accuracy is bad") + def test_highpass(self, xp): + wp = 0.3 + ws = 0.2 + rp = 3 + rs = 70 + N, Wn = cheb1ord(xp.asarray(wp), ws, rp, rs, False) + b, a = cheby1(N, rp, _xp_copy_to_numpy(Wn), 'high', False) + w, h = freqz(b, a) + w /= np.pi + assert np.all(-rp - 0.1 < dB(h[wp <= w])) + assert np.all(dB(h[w <= ws]) < -rs + 0.1) + + assert N == 9 + xp_assert_close(Wn, xp.asarray(0.3), rtol=1e-15, check_0d=False) + + def test_bandpass(self, xp): + wp = [0.2, 0.5] + ws = [0.1, 0.6] + rp = 3 + rs = 80 + N, Wn = cheb1ord(xp.asarray(wp), xp.asarray(ws), rp, rs, False) + b, a = cheby1(N, rp, _xp_copy_to_numpy(Wn), 'band', False) + w, h = freqz(b, a) + w /= np.pi + assert np.all(-rp - 0.1 < dB(h[np.logical_and(wp[0] <= w, w <= wp[1])])) + assert np.all(dB(h[np.logical_or(w <= ws[0], ws[1] <= w)]) < -rs + 0.1) + + assert N == 9 + xp_assert_close(Wn, xp.asarray([0.2, 0.5]), rtol=1e-15) + + @skip_xp_backends( + cpu_only=True, exceptions=["cupy"], reason="optimize.fminbound" + ) + def test_bandstop(self, xp): + wp = [0.1, 0.6] + ws = [0.2, 0.5] + rp = 3 + rs = 90 + N, Wn = cheb1ord(xp.asarray(wp), xp.asarray(ws), rp, rs, False) + b, a = cheby1(N, rp, _xp_copy_to_numpy(Wn), 'stop', False) + w, h = freqz(b, a) + w /= np.pi + assert np.all(-rp - 0.1 < dB(h[np.logical_or(w <= wp[0], wp[1] <= w)])) + assert np.all(dB(h[np.logical_and(ws[0] <= w, w <= ws[1])]) < -rs + 0.1) + + assert N == 10 + xp_assert_close(Wn, xp.asarray([0.14758232569947785, 0.6]), rtol=1e-5) + + def test_analog(self, xp): + wp = 700 + ws = 100. + rp = 3 + rs = 70 + N, Wn = cheb1ord(wp, xp.asarray(ws), rp, rs, True) + b, a = cheby1(N, rp, _xp_copy_to_numpy(Wn), 'high', True) + w, h = freqs(b, a) + assert np.all(-rp - 0.1 < dB(h[wp <= w])) + assert np.all(dB(h[w <= ws]) < -rs + 0.1) + + assert N == 4 + assert math.isclose(Wn, 700.0, rel_tol=1e-15) + assert array_namespace(Wn) == xp + assert cheb1ord(xp.asarray(1), 1.2, 1, 80, analog=True)[0] == 17 + + @xfail_xp_backends("torch", reason="accuracy issues") + def test_fs_param(self, xp): + wp = 4800 + ws = 7200. + rp = 3 + rs = 60 + fs = 48000 + N, Wn = cheb1ord(wp, xp.asarray(ws), rp, rs, False, fs=fs) + b, a = cheby1(N, rp, _xp_copy_to_numpy(Wn), 'low', False, fs=fs) + w, h = freqz(b, a, fs=fs) + assert np.all(-rp - 0.1 < dB(h[w <= wp])) + assert np.all(dB(h[ws <= w]) < -rs + 0.1) + + assert N == 8 + assert math.isclose(Wn, 4800.0, rel_tol=1e-15) + assert array_namespace(Wn) == xp + + def test_invalid_input(self): + with pytest.raises(ValueError) as exc_info: + cheb1ord(0.2, 0.3, 3, 2) + assert "gpass should be smaller than gstop" in str(exc_info.value) + + with pytest.raises(ValueError) as exc_info: + cheb1ord(0.2, 0.3, -1, 2) + assert "gpass should be larger than 0.0" in str(exc_info.value) + + with pytest.raises(ValueError) as exc_info: + cheb1ord(0.2, 0.3, 1, -2) + assert "gstop should be larger than 0.0" in str(exc_info.value) + + def test_ellip_cheb1(self): + # The purpose of the test is to compare to some known output from past + # scipy versions. The values to compare to are generated with scipy + # 1.9.1 (there is nothing special about this particular version though) + n, wn = cheb1ord([0.1, 0.6], [0.2, 0.5], 3, 60) + assert n == 7 + + n2, w2 = cheb2ord([0.1, 0.6], [0.2, 0.5], 3, 60) + assert not (wn == w2).all() + + def test_fs_validation(self): + wp = 0.2 + ws = 0.3 + rp = 3 + rs = 60 + + with pytest.raises(ValueError, match="Sampling.*single scalar"): + cheb1ord(wp, ws, rp, rs, False, fs=np.array([10, 20])) + + +@make_xp_test_case(cheb2ord) +@pytest.mark.skipif(DEFAULT_F32, reason="XXX needs figuring out") +@skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") +class TestCheb2ord: + + def test_lowpass(self, xp): + wp = 0.2 + ws = 0.3 + rp = 3 + rs = 60 + N, Wn = cheb2ord(wp, xp.asarray(ws), rp, rs, False) + b, a = cheby2(N, rs, _xp_copy_to_numpy(Wn), 'lp', False) + w, h = freqz(b, a) + w /= np.pi + assert np.all(-rp - 0.1 < dB(h[w <= wp])) + assert np.all(dB(h[ws <= w]) < -rs + 0.1) + + assert N == 8 + xp_assert_close(Wn, xp.asarray(0.28647639976553163), rtol=1e-15, check_0d=False) + + def test_highpass(self, xp): + wp = 0.3 + ws = 0.2 + rp = 3 + rs = 70 + N, Wn = cheb2ord(wp, xp.asarray(ws), rp, rs, False) + b, a = cheby2(N, rs, _xp_copy_to_numpy(Wn), 'hp', False) + w, h = freqz(b, a) + w /= np.pi + assert np.all(-rp - 0.1 < dB(h[wp <= w])) + assert np.all(dB(h[w <= ws]) < -rs + 0.1) + + assert N == 9 + xp_assert_close(Wn, xp.asarray(0.20697492182903282), rtol=1e-15, check_0d=False) + + def test_bandpass(self, xp): + wp = [0.2, 0.5] + ws = [0.1, 0.6] + rp = 3 + rs = 80 + N, Wn = cheb2ord(xp.asarray(wp), xp.asarray(ws), rp, rs, False) + b, a = cheby2(N, rs, _xp_copy_to_numpy(Wn), 'bp', False) + w, h = freqz(b, a) + w /= np.pi + assert np.all(-rp - 0.1 < dB(h[np.logical_and(wp[0] <= w, w <= wp[1])])) + assert np.all(dB(h[np.logical_or(w <= ws[0], ws[1] <= w)]) < -rs + 0.1) + + assert N == 9 + xp_assert_close(Wn, xp.asarray([0.14876937565923479, 0.59748447842351482]), + rtol=1e-15) + + @skip_xp_backends( + cpu_only=True, exceptions=["cupy"], reason="optimize.fminbound" + ) + def test_bandstop(self, xp): + wp = [0.1, 0.6] + ws = [0.2, 0.5] + rp = 3 + rs = 90 + N, Wn = cheb2ord(xp.asarray(wp), xp.asarray(ws), rp, rs, False) + b, a = cheby2(N, rs, _xp_copy_to_numpy(Wn), 'bs', False) + w, h = freqz(b, a) + w /= np.pi + assert np.all(-rp - 0.1 < dB(h[np.logical_or(w <= wp[0], wp[1] <= w)])) + assert np.all(dB(h[np.logical_and(ws[0] <= w, w <= ws[1])]) < -rs + 0.1) + + assert N == 10 + xp_assert_close(Wn, xp.asarray([0.19926249974781743, 0.50125246585567362]), + rtol=1e-6) + + def test_analog(self, xp): + wp = [20., 50] + ws = [10., 60] + rp = 3 + rs = 80 + N, Wn = cheb2ord(xp.asarray(wp), xp.asarray(ws), rp, rs, True) + b, a = cheby2(N, rs, _xp_copy_to_numpy(Wn), 'bp', True) + w, h = freqs(b, a) + assert np.all(-rp - 0.1 < dB(h[np.logical_and(wp[0] <= w, w <= wp[1])])) + assert np.all(dB(h[np.logical_or(w <= ws[0], ws[1] <= w)]) < -rs + 0.1) + + assert N == 11 + xp_assert_close(Wn, xp.asarray([1.673740595370124e+01, 5.974641487254268e+01]), + rtol=1e-15) + + def test_fs_param(self, xp): + wp = 150 + ws = 100. + rp = 3 + rs = 70 + fs = 1000 + N, Wn = cheb2ord(wp, xp.asarray(ws), rp, rs, False, fs=fs) + b, a = cheby2(N, rs, _xp_copy_to_numpy(Wn), 'hp', False, fs=fs) + w, h = freqz(b, a, fs=fs) + assert np.all(-rp - 0.1 < dB(h[wp <= w])) + assert np.all(dB(h[w <= ws]) < -rs + 0.1) + + assert N == 9 + assert math.isclose(Wn, 103.4874609145164, rel_tol=1e-15) + assert array_namespace(Wn) == xp + + def test_invalid_input(self): + with pytest.raises(ValueError) as exc_info: + cheb2ord([0.1, 0.6], [0.2, 0.5], 3, 2) + assert "gpass should be smaller than gstop" in str(exc_info.value) + + with pytest.raises(ValueError) as exc_info: + cheb2ord([0.1, 0.6], [0.2, 0.5], -1, 2) + assert "gpass should be larger than 0.0" in str(exc_info.value) + + with pytest.raises(ValueError) as exc_info: + cheb2ord([0.1, 0.6], [0.2, 0.5], 1, -2) + assert "gstop should be larger than 0.0" in str(exc_info.value) + + def test_ellip_cheb2(self): + # The purpose of the test is to compare to some known output from past + # scipy versions. The values to compare to are generated with scipy + # 1.9.1 (there is nothing special about this particular version though) + n, wn = cheb2ord([0.1, 0.6], [0.2, 0.5], 3, 60) + assert n == 7 + + n1, w1 = cheb1ord([0.1, 0.6], [0.2, 0.5], 3, 60) + assert not (wn == w1).all() + + def test_fs_validation(self): + wp = 0.2 + ws = 0.3 + rp = 3 + rs = 60 + + with pytest.raises(ValueError, match="Sampling.*single scalar"): + cheb2ord(wp, ws, rp, rs, False, fs=np.array([10, 20])) + + +@make_xp_test_case(ellipord) +@pytest.mark.skipif(DEFAULT_F32, reason="XXX needs figuring out") +@skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") +class TestEllipord: + + def test_lowpass(self, xp): + wp = 0.2 + ws = 0.3 + rp = 3 + rs = 60 + N, Wn = ellipord(wp, xp.asarray(ws), rp, rs, False) + b, a = ellip(N, rp, rs, _xp_copy_to_numpy(Wn), 'lp', False) + w, h = freqz(b, a) + w /= np.pi + assert np.all(-rp - 0.1 < dB(h[w <= wp])) + assert np.all(dB(h[ws <= w]) < -rs + 0.1) + + assert N == 5 + xp_assert_close(Wn, xp.asarray(0.2), rtol=1e-15, check_0d=False) + + def test_lowpass_1000dB(self, xp): + # failed when ellipkm1 wasn't used in ellipord and ellipap + wp = 0.2 + ws = 0.3 + rp = 3 + rs = 1000 + N, Wn = ellipord(wp, xp.asarray(ws), rp, rs, False) + sos = ellip(N, rp, rs, _xp_copy_to_numpy(Wn), 'lp', False, output='sos') + w, h = freqz_sos(sos) + w /= np.pi + assert np.all(-rp - 0.1 < dB(h[w <= wp])) + assert np.all(dB(h[ws <= w]) < -rs + 0.1) + assert array_namespace(Wn) == xp + + def test_highpass(self, xp): + wp = 0.3 + ws = 0.2 + rp = 3 + rs = 70 + N, Wn = ellipord(wp, xp.asarray(ws), rp, rs, False) + b, a = ellip(N, rp, rs, _xp_copy_to_numpy(Wn), 'hp', False) + w, h = freqz(b, a) + w /= np.pi + assert np.all(-rp - 0.1 < dB(h[wp <= w])) + assert np.all(dB(h[w <= ws]) < -rs + 0.1) + + assert N == 6 + xp_assert_close(Wn, xp.asarray(0.3), rtol=1e-15, check_0d=False) + assert array_namespace(Wn) == xp + + def test_bandpass(self, xp): + wp = [0.2, 0.5] + ws = [0.1, 0.6] + rp = 3 + rs = 80 + N, Wn = ellipord(xp.asarray(wp), xp.asarray(ws), rp, rs, False) + b, a = ellip(N, rp, rs, _xp_copy_to_numpy(Wn), 'bp', False) + w, h = freqz(b, a) + w /= np.pi + assert np.all(-rp - 0.1 < dB(h[np.logical_and(wp[0] <= w, w <= wp[1])])) + assert np.all(dB(h[np.logical_or(w <= ws[0], ws[1] <= w)]) < -rs + 0.1) + + assert N == 6 + xp_assert_close(Wn, xp.asarray([0.2, 0.5]), rtol=1e-15) + + @skip_xp_backends( + cpu_only=True, exceptions=["cupy"], reason="optimize.fminbound" + ) + def test_bandstop(self, xp): + wp = [0.1, 0.6] + ws = [0.2, 0.5] + rp = 3 + rs = 90 + N, Wn = ellipord(xp.asarray(wp), xp.asarray(ws), rp, rs, False) + b, a = ellip(N, rp, rs, _xp_copy_to_numpy(Wn), 'bs', False) + w, h = freqz(b, a) + w /= np.pi + assert np.all(-rp - 0.1 < dB(h[np.logical_or(w <= wp[0], wp[1] <= w)])) + assert np.all(dB(h[np.logical_and(ws[0] <= w, w <= ws[1])]) < -rs + 0.1) + + assert N == 7 + xp_assert_close(Wn, xp.asarray([0.14758232794342988, 0.6]), rtol=1e-5) + + def test_analog(self, xp): + wp = [1000.0, 6000] + ws = [2000.0, 5000] + rp = 3 + rs = 90 + N, Wn = ellipord(xp.asarray(wp), xp.asarray(ws), rp, rs, True) + b, a = ellip(N, rp, rs, _xp_copy_to_numpy(Wn), 'bs', True) + w, h = freqs(b, a) + assert np.all(-rp - 0.1 < dB(h[np.logical_or(w <= wp[0], wp[1] <= w)])) + assert np.all(dB(h[np.logical_and(ws[0] <= w, w <= ws[1])]) < -rs + 0.1) + + assert N == 8 + xp_assert_close(Wn, xp.asarray([1666.6666, 6000])) + + assert ellipord(xp.asarray(1), 1.2, 1, 80, analog=True)[0] == 9 + + def test_fs_param(self, xp): + wp = [400.0, 2400] + ws = [800.0, 2000] + rp = 3 + rs = 90 + fs = 8000 + N, Wn = ellipord(xp.asarray(wp), xp.asarray(ws), rp, rs, False, fs=fs) + b, a = ellip(N, rp, rs, _xp_copy_to_numpy(Wn), 'bs', False, fs=fs) + w, h = freqz(b, a, fs=fs) + assert np.all(-rp - 0.1 < dB(h[np.logical_or(w <= wp[0], wp[1] <= w)])) + assert np.all(dB(h[np.logical_and(ws[0] <= w, w <= ws[1])]) < -rs + 0.1) + + assert N == 7 + xp_assert_close(Wn, xp.asarray([590.3293117737195, 2400]), rtol=1e-5) + + def test_invalid_input(self): + with pytest.raises(ValueError) as exc_info: + ellipord(0.2, 0.5, 3, 2) + assert "gpass should be smaller than gstop" in str(exc_info.value) + + with pytest.raises(ValueError) as exc_info: + ellipord(0.2, 0.5, -1, 2) + assert "gpass should be larger than 0.0" in str(exc_info.value) + + with pytest.raises(ValueError) as exc_info: + ellipord(0.2, 0.5, 1, -2) + assert "gstop should be larger than 0.0" in str(exc_info.value) + + def test_ellip_butter(self, xp): + # The purpose of the test is to compare to some known output from past + # scipy versions. The values to compare to are generated with scipy + # 1.9.1 (there is nothing special about this particular version though) + n, Wn = ellipord(xp.asarray([0.1, 0.6]), xp.asarray([0.2, 0.5]), 3, 60) + assert array_namespace(Wn) == xp + assert n == 5 + + def test_fs_validation(self): + wp = 0.2 + ws = 0.3 + rp = 3 + rs = 60 + + with pytest.raises(ValueError, match="Sampling.*single scalar"): + ellipord(wp, ws, rp, rs, False, fs=np.array([10, 20])) + + +# Currently the filter functions tested below (bessel, butter, cheby1, cheby2, +# and ellip) all return float64 (or complex128) output regardless of input +# dtype. Therefore reference arrays in these tests are all given an explicit 64 +# bit dtype, because the output will not match the xp_default_dtype when the +# default dtype is float32. Although the output arrays and all internal +# calculations are in 64 bit precision, tolerances are still loosened for the +# float32 case when results are impacted by reduced precision in the inputs. + + +@skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") +@make_xp_test_case(bessel) +class TestBessel: + + def test_degenerate(self, xp): + for norm in ('delay', 'phase', 'mag'): + # 0-order filter is just a passthrough + b, a = bessel(0, xp.asarray(1), analog=True, norm=norm) + xp_assert_equal(b, xp.asarray([1.0], dtype=xp.float64)) + xp_assert_equal(a, xp.asarray([1.0], dtype=xp.float64)) + + # 1-order filter is same for all types + b, a = bessel(1, xp.asarray(1.), analog=True, norm=norm) + + xp_assert_close(b, xp.asarray([1.0], dtype=xp.float64), rtol=1e-15) + xp_assert_close(a, xp.asarray([1.0, 1], dtype=xp.float64), rtol=1e-15) + + z, p, k = bessel(1, xp.asarray(0.3), analog=True, output='zpk', norm=norm) + xp_assert_equal(z, xp.asarray([], dtype=xp.float64)) + xp_assert_close( + p, xp.asarray([-0.3+0j], dtype=xp.complex128), + rtol=1e-14 if not DEFAULT_F32 else 1e-7 + ) + assert math.isclose( + k, 0.3, rel_tol=1e-14 if not DEFAULT_F32 else 1e-6 + ) + + @pytest.mark.xfail(reason="Failing in mypy workflow - see gh-23902") + def test_high_order(self, xp): + # high even order, 'phase' + z, p, k = bessel(24, xp.asarray(100), analog=True, output='zpk') + z2 = xp.asarray([], dtype=xp.float64) + p2 = [ + -9.055312334014323e+01 + 4.844005815403969e+00j, + -8.983105162681878e+01 + 1.454056170018573e+01j, + -8.837357994162065e+01 + 2.426335240122282e+01j, + -8.615278316179575e+01 + 3.403202098404543e+01j, + -8.312326467067703e+01 + 4.386985940217900e+01j, + -7.921695461084202e+01 + 5.380628489700191e+01j, + -7.433392285433246e+01 + 6.388084216250878e+01j, + -6.832565803501586e+01 + 7.415032695116071e+01j, + -6.096221567378025e+01 + 8.470292433074425e+01j, + -5.185914574820616e+01 + 9.569048385258847e+01j, + -4.027853855197555e+01 + 1.074195196518679e+02j, + -2.433481337524861e+01 + 1.207298683731973e+02j, + ] + + p2 = np.union1d(p2, np.conj(p2)) + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 9.999999999999989e+47 + xp_assert_equal(z, z2) + xp_assert_close(_sort_cmplx(p, xp=xp), + _sort_cmplx(p2, xp=xp)) + assert math.isclose(k, k2, rel_tol=1e-14) + + # high odd order, 'phase' + z, p, k = bessel(23, xp.asarray(1000.), analog=True, output='zpk') + z2 = xp.asarray([], dtype=xp.float64) + p2 = [ + -2.497697202208956e+02 + 1.202813187870698e+03j, + -4.126986617510172e+02 + 1.065328794475509e+03j, + -5.304922463809596e+02 + 9.439760364018479e+02j, + -9.027564978975828e+02 + 1.010534334242318e+02j, + -8.909283244406079e+02 + 2.023024699647598e+02j, + -8.709469394347836e+02 + 3.039581994804637e+02j, + -8.423805948131370e+02 + 4.062657947488952e+02j, + -8.045561642249877e+02 + 5.095305912401127e+02j, + -7.564660146766259e+02 + 6.141594859516342e+02j, + -6.965966033906477e+02 + 7.207341374730186e+02j, + -6.225903228776276e+02 + 8.301558302815096e+02j, + -9.066732476324988e+02] + p2 = np.union1d(p2, np.conj(p2)) + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 9.999999999999983e+68 + xp_assert_equal(z, z2) + xp_assert_close(_sort_cmplx(p, xp=xp), + _sort_cmplx(p2, xp=xp)) + assert math.isclose(k, k2, rel_tol=1e-14) + + # high even order, 'delay' (Orchard 1965 "The Roots of the + # Maximally Flat-Delay Polynomials" Table 1) + z, p, k = bessel(31, xp.asarray(1.), analog=True, output='zpk', norm='delay') + p2 = [-20.876706, + -20.826543 + 1.735732j, + -20.675502 + 3.473320j, + -20.421895 + 5.214702j, + -20.062802 + 6.961982j, + -19.593895 + 8.717546j, + -19.009148 + 10.484195j, + -18.300400 + 12.265351j, + -17.456663 + 14.065350j, + -16.463032 + 15.889910j, + -15.298849 + 17.746914j, + -13.934466 + 19.647827j, + -12.324914 + 21.610519j, + -10.395893 + 23.665701j, + - 8.005600 + 25.875019j, + - 4.792045 + 28.406037j, + ] + p2 = np.union1d(p2, np.conj(p2)) + p2 = xp.asarray(p2, dtype=xp.complex128) + xp_assert_close(_sort_cmplx(p, xp=xp), + _sort_cmplx(p2, xp=xp)) + + # high odd order, 'delay' + z, p, k = bessel(30, xp.asarray(1.), analog=True, output='zpk', norm='delay') + p2 = [-20.201029 + 0.867750j, + -20.097257 + 2.604235j, + -19.888485 + 4.343721j, + -19.572188 + 6.088363j, + -19.144380 + 7.840570j, + -18.599342 + 9.603147j, + -17.929195 + 11.379494j, + -17.123228 + 13.173901j, + -16.166808 + 14.992008j, + -15.039580 + 16.841580j, + -13.712245 + 18.733902j, + -12.140295 + 20.686563j, + -10.250119 + 22.729808j, + - 7.901170 + 24.924391j, + - 4.734679 + 27.435615j, + ] + p2 = np.union1d(p2, np.conj(p2)) + p2 = xp.asarray(p2, dtype=xp.complex128) + xp_assert_close(_sort_cmplx(p, xp=xp), + _sort_cmplx(p2, xp=xp)) + + def test_refs(self, xp): + # Compare to http://www.crbond.com/papers/bsf2.pdf + # "Delay Normalized Bessel Polynomial Coefficients" + bond_b = xp.asarray([10395.0], dtype=xp.float64) + bond_a = xp.asarray([1.0, 21, 210, 1260, 4725, 10395, 10395], dtype=xp.float64) + b, a = bessel(6, xp.asarray(1.0), norm='delay', analog=True) + xp_assert_close(b, bond_b) + xp_assert_close(a, bond_a) + + # "Delay Normalized Bessel Pole Locations" + bond_poles = { + 1: [-1.0000000000], + 2: [-1.5000000000 + 0.8660254038j], + 3: [-1.8389073227 + 1.7543809598j, -2.3221853546], + 4: [-2.1037893972 + 2.6574180419j, -2.8962106028 + 0.8672341289j], + 5: [-2.3246743032 + 3.5710229203j, -3.3519563992 + 1.7426614162j, + -3.6467385953], + 6: [-2.5159322478 + 4.4926729537j, -3.7357083563 + 2.6262723114j, + -4.2483593959 + 0.8675096732j], + 7: [-2.6856768789 + 5.4206941307j, -4.0701391636 + 3.5171740477j, + -4.7582905282 + 1.7392860611j, -4.9717868585], + 8: [-2.8389839489 + 6.3539112986j, -4.3682892172 + 4.4144425005j, + -5.2048407906 + 2.6161751526j, -5.5878860433 + 0.8676144454j], + 9: [-2.9792607982 + 7.2914636883j, -4.6384398872 + 5.3172716754j, + -5.6044218195 + 3.4981569179j, -6.1293679043 + 1.7378483835j, + -6.2970191817], + 10: [-3.1089162336 + 8.2326994591j, -4.8862195669 + 6.2249854825j, + -5.9675283286 + 4.3849471889j, -6.6152909655 + 2.6115679208j, + -6.9220449054 + 0.8676651955j] + } + + for N in range(1, 11): + p1 = np.sort(bond_poles[N]) + z, p, k = besselap(N, 'delay', xp=xp) + assert array_namespace(z) == array_namespace(p) == xp + p2 = np.sort(np.concatenate(_cplxreal(_xp_copy_to_numpy(p)))) + assert_array_almost_equal(xp.asarray(p2), xp.asarray(p1), decimal=10) + + # "Frequency Normalized Bessel Pole Locations" + bond_poles = { + 1: [-1.0000000000], + 2: [-1.1016013306 + 0.6360098248j], + 3: [-1.0474091610 + 0.9992644363j, -1.3226757999], + 4: [-0.9952087644 + 1.2571057395j, -1.3700678306 + 0.4102497175j], + 5: [-0.9576765486 + 1.4711243207j, -1.3808773259 + 0.7179095876j, + -1.5023162714], + 6: [-0.9306565229 + 1.6618632689j, -1.3818580976 + 0.9714718907j, + -1.5714904036 + 0.3208963742j], + 7: [-0.9098677806 + 1.8364513530j, -1.3789032168 + 1.1915667778j, + -1.6120387662 + 0.5892445069j, -1.6843681793], + 8: [-0.8928697188 + 1.9983258436j, -1.3738412176 + 1.3883565759j, + -1.6369394181 + 0.8227956251j, -1.7574084004 + 0.2728675751j], + 9: [-0.8783992762 + 2.1498005243j, -1.3675883098 + 1.5677337122j, + -1.6523964846 + 1.0313895670j, -1.8071705350 + 0.5123837306j, + -1.8566005012], + 10: [-0.8657569017 + 2.2926048310j, -1.3606922784 + 1.7335057427j, + -1.6618102414 + 1.2211002186j, -1.8421962445 + 0.7272575978j, + -1.9276196914 + 0.2416234710j] + } + + for N in range(1, 11): + p1 = np.sort(bond_poles[N]) + z, p, k = besselap(N, 'mag', xp=xp) + assert array_namespace(z) == array_namespace(p) == xp + p2 = np.sort(np.concatenate(_cplxreal(_xp_copy_to_numpy(p)))) + assert_array_almost_equal(xp.asarray(p2), xp.asarray(p1), decimal=10) + + # Compare to https://www.ranecommercial.com/legacy/note147.html + # "Table 1 - Bessel Crossovers of Second, Third, and Fourth-Order" + a = xp.asarray([1, 1, 1/3], dtype=xp.float64) + b2, a2 = bessel(2, xp.asarray(1.), norm='delay', analog=True) + xp_assert_close(a2/b2, xp.flip(a)) + + a = xp.asarray([1, 1, 2/5, 1/15], dtype=xp.float64) + b2, a2 = bessel(3, xp.asarray(1.), norm='delay', analog=True) + xp_assert_close(a2/b2, xp.flip(a)) + + a = xp.asarray([1, 1, 9/21, 2/21, 1/105], dtype=xp.float64) + b2, a2 = bessel(4, xp.asarray(1.), norm='delay', analog=True) + xp_assert_close(a2/b2, xp.flip(a)) + + a = xp.asarray([1, math.sqrt(3), 1], dtype=xp.float64) + b2, a2 = bessel(2, xp.asarray(1.), norm='phase', analog=True) + xp_assert_close(a2/b2, xp.flip(a)) + + # TODO: Why so inaccurate? Is reference flawed? + a = xp.asarray([1, 2.481, 2.463, 1.018], dtype=xp.float64) + b2, a2 = bessel(3, xp.asarray(1.), norm='phase', analog=True) + assert_array_almost_equal(a2/b2, xp.flip(a), decimal=1) + + # TODO: Why so inaccurate? Is reference flawed? + a = xp.asarray([1, 3.240, 4.5, 3.240, 1.050], dtype=xp.float64) + b2, a2 = bessel(4, xp.asarray(1.), norm='phase', analog=True) + assert_array_almost_equal(a2/b2, xp.flip(a), decimal=1) + + # Table of -3 dB factors: + N, scale = 2, xp.asarray([1.272, 1.272], dtype=xp.complex128) + scale2 = besselap(N, 'mag', xp=xp)[1] / besselap(N, 'phase', xp=xp)[1] + assert_array_almost_equal(scale2, scale, decimal=3) + + # TODO: Why so inaccurate? Is reference flawed? + N, scale = 3, xp.asarray([1.413, 1.413, 1.413], dtype=xp.complex128) + scale2 = besselap(N, 'mag', xp=xp)[1] / besselap(N, 'phase', xp=xp)[1] + assert_array_almost_equal(scale2, scale, decimal=2) + + # TODO: Why so inaccurate? Is reference flawed? + N, scale = 4, xp.asarray([1.533]*4, dtype=xp.complex128) + scale2 = besselap(N, 'mag', xp=xp)[1] / besselap(N, 'phase', xp=xp)[1] + assert_array_almost_equal(scale2, scale, decimal=1) + + @pytest.mark.xfail(reason="Failing in mypy workflow - see gh-23902") + def test_hardcoded(self, xp): + # Compare to values from original hardcoded implementation + originals = { + 0: [], + 1: [-1], + 2: [-.8660254037844386467637229 + .4999999999999999999999996j], + 3: [-.9416000265332067855971980, + -.7456403858480766441810907 + .7113666249728352680992154j], + 4: [-.6572111716718829545787788 + .8301614350048733772399715j, + -.9047587967882449459642624 + .2709187330038746636700926j], + 5: [-.9264420773877602247196260, + -.8515536193688395541722677 + .4427174639443327209850002j, + -.5905759446119191779319432 + .9072067564574549539291747j], + 6: [-.9093906830472271808050953 + .1856964396793046769246397j, + -.7996541858328288520243325 + .5621717346937317988594118j, + -.5385526816693109683073792 + .9616876881954277199245657j], + 7: [-.9194871556490290014311619, + -.8800029341523374639772340 + .3216652762307739398381830j, + -.7527355434093214462291616 + .6504696305522550699212995j, + -.4966917256672316755024763 + 1.002508508454420401230220j], + 8: [-.9096831546652910216327629 + .1412437976671422927888150j, + -.8473250802359334320103023 + .4259017538272934994996429j, + -.7111381808485399250796172 + .7186517314108401705762571j, + -.4621740412532122027072175 + 1.034388681126901058116589j], + 9: [-.9154957797499037686769223, + -.8911217017079759323183848 + .2526580934582164192308115j, + -.8148021112269012975514135 + .5085815689631499483745341j, + -.6743622686854761980403401 + .7730546212691183706919682j, + -.4331415561553618854685942 + 1.060073670135929666774323j], + 10: [-.9091347320900502436826431 + .1139583137335511169927714j, + -.8688459641284764527921864 + .3430008233766309973110589j, + -.7837694413101441082655890 + .5759147538499947070009852j, + -.6417513866988316136190854 + .8175836167191017226233947j, + -.4083220732868861566219785 + 1.081274842819124562037210j], + 11: [-.9129067244518981934637318, + -.8963656705721166099815744 + .2080480375071031919692341j, + -.8453044014712962954184557 + .4178696917801248292797448j, + -.7546938934722303128102142 + .6319150050721846494520941j, + -.6126871554915194054182909 + .8547813893314764631518509j, + -.3868149510055090879155425 + 1.099117466763120928733632j], + 12: [-.9084478234140682638817772 + 95506365213450398415258360e-27j, + -.8802534342016826507901575 + .2871779503524226723615457j, + -.8217296939939077285792834 + .4810212115100676440620548j, + -.7276681615395159454547013 + .6792961178764694160048987j, + -.5866369321861477207528215 + .8863772751320727026622149j, + -.3679640085526312839425808 + 1.114373575641546257595657j], + 13: [-.9110914665984182781070663, + -.8991314665475196220910718 + .1768342956161043620980863j, + -.8625094198260548711573628 + .3547413731172988997754038j, + -.7987460692470972510394686 + .5350752120696801938272504j, + -.7026234675721275653944062 + .7199611890171304131266374j, + -.5631559842430199266325818 + .9135900338325109684927731j, + -.3512792323389821669401925 + 1.127591548317705678613239j], + 14: [-.9077932138396487614720659 + 82196399419401501888968130e-27j, + -.8869506674916445312089167 + .2470079178765333183201435j, + -.8441199160909851197897667 + .4131653825102692595237260j, + -.7766591387063623897344648 + .5819170677377608590492434j, + -.6794256425119233117869491 + .7552857305042033418417492j, + -.5418766775112297376541293 + .9373043683516919569183099j, + -.3363868224902037330610040 + 1.139172297839859991370924j], + 15: [-.9097482363849064167228581, + -.9006981694176978324932918 + .1537681197278439351298882j, + -.8731264620834984978337843 + .3082352470564267657715883j, + -.8256631452587146506294553 + .4642348752734325631275134j, + -.7556027168970728127850416 + .6229396358758267198938604j, + -.6579196593110998676999362 + .7862895503722515897065645j, + -.5224954069658330616875186 + .9581787261092526478889345j, + -.3229963059766444287113517 + 1.149416154583629539665297j], + 16: [-.9072099595087001356491337 + 72142113041117326028823950e-27j, + -.8911723070323647674780132 + .2167089659900576449410059j, + -.8584264231521330481755780 + .3621697271802065647661080j, + -.8074790293236003885306146 + .5092933751171800179676218j, + -.7356166304713115980927279 + .6591950877860393745845254j, + -.6379502514039066715773828 + .8137453537108761895522580j, + -.5047606444424766743309967 + .9767137477799090692947061j, + -.3108782755645387813283867 + 1.158552841199330479412225j], + 17: [-.9087141161336397432860029, + -.9016273850787285964692844 + .1360267995173024591237303j, + -.8801100704438627158492165 + .2725347156478803885651973j, + -.8433414495836129204455491 + .4100759282910021624185986j, + -.7897644147799708220288138 + .5493724405281088674296232j, + -.7166893842372349049842743 + .6914936286393609433305754j, + -.6193710717342144521602448 + .8382497252826992979368621j, + -.4884629337672704194973683 + .9932971956316781632345466j, + -.2998489459990082015466971 + 1.166761272925668786676672j], + 18: [-.9067004324162775554189031 + 64279241063930693839360680e-27j, + -.8939764278132455733032155 + .1930374640894758606940586j, + -.8681095503628830078317207 + .3224204925163257604931634j, + -.8281885016242836608829018 + .4529385697815916950149364j, + -.7726285030739558780127746 + .5852778162086640620016316j, + -.6987821445005273020051878 + .7204696509726630531663123j, + -.6020482668090644386627299 + .8602708961893664447167418j, + -.4734268069916151511140032 + 1.008234300314801077034158j, + -.2897592029880489845789953 + 1.174183010600059128532230j], + 19: [-.9078934217899404528985092, + -.9021937639390660668922536 + .1219568381872026517578164j, + -.8849290585034385274001112 + .2442590757549818229026280j, + -.8555768765618421591093993 + .3672925896399872304734923j, + -.8131725551578197705476160 + .4915365035562459055630005j, + -.7561260971541629355231897 + .6176483917970178919174173j, + -.6818424412912442033411634 + .7466272357947761283262338j, + -.5858613321217832644813602 + .8801817131014566284786759j, + -.4595043449730988600785456 + 1.021768776912671221830298j, + -.2804866851439370027628724 + 1.180931628453291873626003j], + 20: [-.9062570115576771146523497 + 57961780277849516990208850e-27j, + -.8959150941925768608568248 + .1740317175918705058595844j, + -.8749560316673332850673214 + .2905559296567908031706902j, + -.8427907479956670633544106 + .4078917326291934082132821j, + -.7984251191290606875799876 + .5264942388817132427317659j, + -.7402780309646768991232610 + .6469975237605228320268752j, + -.6658120544829934193890626 + .7703721701100763015154510j, + -.5707026806915714094398061 + .8982829066468255593407161j, + -.4465700698205149555701841 + 1.034097702560842962315411j, + -.2719299580251652601727704 + 1.187099379810885886139638j], + 21: [-.9072262653142957028884077, + -.9025428073192696303995083 + .1105252572789856480992275j, + -.8883808106664449854431605 + .2213069215084350419975358j, + -.8643915813643204553970169 + .3326258512522187083009453j, + -.8299435470674444100273463 + .4448177739407956609694059j, + -.7840287980408341576100581 + .5583186348022854707564856j, + -.7250839687106612822281339 + .6737426063024382240549898j, + -.6506315378609463397807996 + .7920349342629491368548074j, + -.5564766488918562465935297 + .9148198405846724121600860j, + -.4345168906815271799687308 + 1.045382255856986531461592j, + -.2640041595834031147954813 + 1.192762031948052470183960j], + 22: [-.9058702269930872551848625 + 52774908289999045189007100e-27j, + -.8972983138153530955952835 + .1584351912289865608659759j, + -.8799661455640176154025352 + .2644363039201535049656450j, + -.8534754036851687233084587 + .3710389319482319823405321j, + -.8171682088462720394344996 + .4785619492202780899653575j, + -.7700332930556816872932937 + .5874255426351153211965601j, + -.7105305456418785989070935 + .6982266265924524000098548j, + -.6362427683267827226840153 + .8118875040246347267248508j, + -.5430983056306302779658129 + .9299947824439872998916657j, + -.4232528745642628461715044 + 1.055755605227545931204656j, + -.2566376987939318038016012 + 1.197982433555213008346532j], + 23: [-.9066732476324988168207439, + -.9027564979912504609412993 + .1010534335314045013252480j, + -.8909283242471251458653994 + .2023024699381223418195228j, + -.8709469395587416239596874 + .3039581993950041588888925j, + -.8423805948021127057054288 + .4062657948237602726779246j, + -.8045561642053176205623187 + .5095305912227258268309528j, + -.7564660146829880581478138 + .6141594859476032127216463j, + -.6965966033912705387505040 + .7207341374753046970247055j, + -.6225903228771341778273152 + .8301558302812980678845563j, + -.5304922463810191698502226 + .9439760364018300083750242j, + -.4126986617510148836149955 + 1.065328794475513585531053j, + -.2497697202208956030229911 + 1.202813187870697831365338j], + 24: [-.9055312363372773709269407 + 48440066540478700874836350e-27j, + -.8983105104397872954053307 + .1454056133873610120105857j, + -.8837358034555706623131950 + .2426335234401383076544239j, + -.8615278304016353651120610 + .3403202112618624773397257j, + -.8312326466813240652679563 + .4386985933597305434577492j, + -.7921695462343492518845446 + .5380628490968016700338001j, + -.7433392285088529449175873 + .6388084216222567930378296j, + -.6832565803536521302816011 + .7415032695091650806797753j, + -.6096221567378335562589532 + .8470292433077202380020454j, + -.5185914574820317343536707 + .9569048385259054576937721j, + -.4027853855197518014786978 + 1.074195196518674765143729j, + -.2433481337524869675825448 + 1.207298683731972524975429j], + 25: [-.9062073871811708652496104, + -.9028833390228020537142561 + 93077131185102967450643820e-27j, + -.8928551459883548836774529 + .1863068969804300712287138j, + -.8759497989677857803656239 + .2798521321771408719327250j, + -.8518616886554019782346493 + .3738977875907595009446142j, + -.8201226043936880253962552 + .4686668574656966589020580j, + -.7800496278186497225905443 + .5644441210349710332887354j, + -.7306549271849967721596735 + .6616149647357748681460822j, + -.6704827128029559528610523 + .7607348858167839877987008j, + -.5972898661335557242320528 + .8626676330388028512598538j, + -.5073362861078468845461362 + .9689006305344868494672405j, + -.3934529878191079606023847 + 1.082433927173831581956863j, + -.2373280669322028974199184 + 1.211476658382565356579418j], + } + for N in originals: + p1 = xp.asarray( + np.union1d(originals[N], np.conj(originals[N])), + dtype=xp.complex128 + ) + p2 = besselap(N, xp=xp)[1] + xp_assert_close(_sort_cmplx(p2, xp=xp), + _sort_cmplx(p1, xp=xp), rtol=1e-14) + + def test_norm_phase(self, xp): + # Test some orders and frequencies and see that they have the right + # phase at w0 + if is_torch(xp) and DEFAULT_F32: + pytest.xfail(reason="inaccurate on torch with float32") + for N in (1, 2, 3, 4, 5, 51, 72): + for w0 in (1, 100): + b, a = bessel(N, xp.asarray(w0), analog=True, norm='phase') + assert array_namespace(b) == array_namespace(a) == xp + w = np.linspace(0, w0, 100) + w, h = freqs(_xp_copy_to_numpy(b), _xp_copy_to_numpy(a), w) + phase = np.unwrap(np.angle(h)) + xp_assert_close( + xp.asarray(phase[[0, -1]], dtype=xp.float64), + xp.asarray([0, -N*xp.pi/4], dtype=xp.float64), rtol=1e-1 + ) + + def test_norm_mag(self, xp): + # Test some orders and frequencies and see that they have the right + # mag at w0 + if DEFAULT_F32 and is_torch(xp): + pytest.skip(reason="overflow occurs with float32 on torch") + for N in (1, 2, 3, 4, 5, 51, 72): + for w0 in (1, 100): + b, a = bessel(N, xp.asarray(w0), analog=True, norm='mag') + assert array_namespace(b) == array_namespace(a) == xp + w = [0.0, w0] + w, h = freqs(_xp_copy_to_numpy(b), _xp_copy_to_numpy(a), w) + mag = np.abs(h) + xp_assert_close( + xp.asarray(mag), xp.asarray([1, 1/math.sqrt(2)], dtype=xp.float64) + ) + + def test_norm_delay(self, xp): + # Test some orders and frequencies and see that they have the right + # delay at DC + if DEFAULT_F32 and is_torch(xp): + pytest.skip(reason="overflow occurs with float32 on torch") + for N in (1, 2, 3, 4, 5, 51, 72): + for w0 in (1, 100): + b, a = bessel(N, xp.asarray(w0), analog=True, norm='delay') + w = np.linspace(0, 10*w0, 1000) + w, h = freqs(_xp_copy_to_numpy(b), _xp_copy_to_numpy(a), w) + unwr_h = np.unwrap(np.angle(h)) + delay = -np.diff(unwr_h) / np.diff(w) + assert math.isclose(delay[0], 1/w0, rel_tol=1e-4) + + def test_norm_factor(self): + mpmath_values = { + 1: 1.0, 2: 1.361654128716130520, 3: 1.755672368681210649, + 4: 2.113917674904215843, 5: 2.427410702152628137, + 6: 2.703395061202921876, 7: 2.951722147038722771, + 8: 3.179617237510651330, 9: 3.391693138911660101, + 10: 3.590980594569163482, 11: 3.779607416439620092, + 12: 3.959150821144285315, 13: 4.130825499383535980, + 14: 4.295593409533637564, 15: 4.454233021624377494, + 16: 4.607385465472647917, 17: 4.755586548961147727, + 18: 4.899289677284488007, 19: 5.038882681488207605, + 20: 5.174700441742707423, 21: 5.307034531360917274, + 22: 5.436140703250035999, 23: 5.562244783787878196, + 24: 5.685547371295963521, 25: 5.806227623775418541, + 50: 8.268963160013226298, 51: 8.352374541546012058, + } + for N in mpmath_values: + z, p, k = besselap(N, 'delay') + xp_assert_close(_norm_factor(p, k), mpmath_values[N], rtol=1e-13) + + def test_bessel_poly(self): + xp_assert_equal(_bessel_poly(5), [945, 945, 420, 105, 15, 1]) + xp_assert_equal(_bessel_poly(4, True), [1, 10, 45, 105, 105]) + + def test_bessel_zeros(self): + xp_assert_equal(_bessel_zeros(0), []) + + def test_invalid(self): + assert_raises(ValueError, besselap, 5, 'nonsense') + assert_raises(ValueError, besselap, -5) + assert_raises(ValueError, besselap, 3.2) + assert_raises(ValueError, _bessel_poly, -3) + assert_raises(ValueError, _bessel_poly, 3.3) + + @pytest.mark.fail_slow(10) + def test_fs_param(self): + for norm in ('phase', 'mag', 'delay'): + for fs in (900, 900.1, 1234.567): + for N in (0, 1, 2, 3, 10): + for fc in (100, 100.1, 432.12345): + for btype in ('lp', 'hp'): + ba1 = bessel(N, fc, btype, norm=norm, fs=fs) + ba2 = bessel(N, fc/(fs/2), btype, norm=norm) + for ba1_, ba2_ in zip(ba1, ba2): + xp_assert_close(ba1_, ba2_) + for fc in ((100, 200), (100.1, 200.2), (321.123, 432.123)): + for btype in ('bp', 'bs'): + ba1 = bessel(N, fc, btype, norm=norm, fs=fs) + for seq in (list, tuple, array): + fcnorm = seq([f/(fs/2) for f in fc]) + ba2 = bessel(N, fcnorm, btype, norm=norm) + for ba1_, ba2_ in zip(ba1, ba2): + xp_assert_close(ba1_, ba2_) + + +@skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") +@make_xp_test_case(butter) +class TestButter: + + def test_degenerate(self, xp): + # 0-order filter is just a passthrough + b, a = butter(0, xp.asarray(1), analog=True) + xp_assert_equal(b, xp.asarray([1.0], dtype=xp.float64)) + xp_assert_equal(a, xp.asarray([1.0], dtype=xp.float64)) + + # 1-order filter is same for all types + b, a = butter(1, xp.asarray(1), analog=True) + assert_array_almost_equal(b, xp.asarray([1.0], dtype=xp.float64)) + assert_array_almost_equal(a, xp.asarray([1.0, 1.0], dtype=xp.float64)) + + z, p, k = butter(1, xp.asarray(0.3), output='zpk') + xp_assert_equal(z, xp.asarray([-1.0], dtype=xp.float64)) + xp_assert_close( + p, + xp.asarray([3.249196962329063e-01 + 0j], dtype=xp.complex128), + rtol=1e-14 if not DEFAULT_F32 else 1e-7 + ) + assert math.isclose( + k, 3.375401518835469e-01, rel_tol=1e-14 if not DEFAULT_F32 else 1e-7 + ) + + def test_basic(self, xp): + # analog s-plane + for N in range(25): + wn = 0.01 + z, p, k = butter(N, xp.asarray(wn), 'low', analog=True, output='zpk') + assert_array_almost_equal(z, xp.asarray([], dtype=xp.float64)) + assert p.shape[0] == N + # All poles should be at distance wn from origin + assert_array_almost_equal(xp.abs(p), xp.asarray(wn, dtype=xp.float64)) + assert all(xp.real(p) <= 0) # No poles in right half of S-plane + assert math.isclose(k, wn**N, rel_tol=1e-9 if not DEFAULT_F32 else 1e-6) + + # digital z-plane + for N in range(25): + wn = 0.01 + z, p, k = butter(N, xp.asarray(wn), 'high', analog=False, output='zpk') + xp_assert_equal(z, xp.ones(N, dtype=xp.float64)) # All zeros exactly at DC + assert xp.all(xp.abs(p) <= 1) # No poles outside unit circle + + b1, a1 = butter(2, xp.asarray(1), analog=True) + assert_array_almost_equal(b1, xp.asarray([1.0], dtype=xp.float64)) + assert_array_almost_equal( + a1, xp.asarray([1, math.sqrt(2), 1], dtype=xp.float64) + ) + + b2, a2 = butter(5, xp.asarray(1.), analog=True) + assert_array_almost_equal(b2, xp.asarray([1], dtype=xp.float64)) + assert_array_almost_equal( + a2, xp.asarray([1, 3.2361, 5.2361, + 5.2361, 3.2361, 1], dtype=xp.float64), + decimal=4 + ) + + b3, a3 = butter(10, xp.asarray(1.0), analog=True) + assert_array_almost_equal(b3, xp.asarray([1.0], dtype=xp.float64)) + assert_array_almost_equal( + a3, xp.asarray([1, 6.3925, 20.4317, 42.8021, 64.8824, + 74.2334, 64.8824, 42.8021, 20.4317, + 6.3925, 1], dtype=xp.float64), + decimal=4 + ) + + b2, a2 = butter(19, xp.asarray(1.0441379169150726), analog=True) + assert_array_almost_equal( + b2, xp.asarray([2.2720], dtype=xp.float64), decimal=4 + ) + assert_array_almost_equal( + a2, 1.0e+004 * xp.asarray([ + 0.0001, 0.0013, 0.0080, 0.0335, 0.1045, 0.2570, + 0.5164, 0.8669, 1.2338, 1.5010, 1.5672, 1.4044, + 1.0759, 0.6986, 0.3791, 0.1681, 0.0588, 0.0153, + 0.0026, 0.0002], dtype=xp.float64), + decimal=0 + ) + + b, a = butter(5, xp.asarray(0.4)) + assert_array_almost_equal( + b, xp.asarray([0.0219, 0.1097, 0.2194, + 0.2194, 0.1097, 0.0219], dtype=xp.float64), + decimal=4 + ) + assert_array_almost_equal( + a, xp.asarray([1.0000, -0.9853, 0.9738, + -0.3864, 0.1112, -0.0113], dtype=xp.float64), + decimal=4 + ) + + def test_highpass(self, xp): + # highpass, high even order + z, p, k = butter(28, xp.asarray(0.43), 'high', output='zpk') + z2 = xp.ones(28, dtype=xp.float64) + p2 = [ + 2.068257195514592e-01 + 9.238294351481734e-01j, + 2.068257195514592e-01 - 9.238294351481734e-01j, + 1.874933103892023e-01 + 8.269455076775277e-01j, + 1.874933103892023e-01 - 8.269455076775277e-01j, + 1.717435567330153e-01 + 7.383078571194629e-01j, + 1.717435567330153e-01 - 7.383078571194629e-01j, + 1.588266870755982e-01 + 6.564623730651094e-01j, + 1.588266870755982e-01 - 6.564623730651094e-01j, + 1.481881532502603e-01 + 5.802343458081779e-01j, + 1.481881532502603e-01 - 5.802343458081779e-01j, + 1.394122576319697e-01 + 5.086609000582009e-01j, + 1.394122576319697e-01 - 5.086609000582009e-01j, + 1.321840881809715e-01 + 4.409411734716436e-01j, + 1.321840881809715e-01 - 4.409411734716436e-01j, + 1.262633413354405e-01 + 3.763990035551881e-01j, + 1.262633413354405e-01 - 3.763990035551881e-01j, + 1.214660449478046e-01 + 3.144545234797277e-01j, + 1.214660449478046e-01 - 3.144545234797277e-01j, + 1.104868766650320e-01 + 2.771505404367791e-02j, + 1.104868766650320e-01 - 2.771505404367791e-02j, + 1.111768629525075e-01 + 8.331369153155753e-02j, + 1.111768629525075e-01 - 8.331369153155753e-02j, + 1.125740630842972e-01 + 1.394219509611784e-01j, + 1.125740630842972e-01 - 1.394219509611784e-01j, + 1.147138487992747e-01 + 1.963932363793666e-01j, + 1.147138487992747e-01 - 1.963932363793666e-01j, + 1.176516491045901e-01 + 2.546021573417188e-01j, + 1.176516491045901e-01 - 2.546021573417188e-01j, + ] + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 1.446671081817286e-06 + xp_assert_equal(z, z2) + xp_assert_close(_sort_cmplx(p, xp), _sort_cmplx(p2, xp), rtol=1e-7) + assert math.isclose(k, k2, rel_tol=1e-10 if not DEFAULT_F32 else 1e-6) + + # highpass, high odd order + z, p, k = butter(27, xp.asarray(0.56), 'high', output='zpk') + z2 = xp.ones(27, dtype=xp.float64) + p2 = [ + -1.772572785680147e-01 + 9.276431102995948e-01j, + -1.772572785680147e-01 - 9.276431102995948e-01j, + -1.600766565322114e-01 + 8.264026279893268e-01j, + -1.600766565322114e-01 - 8.264026279893268e-01j, + -1.461948419016121e-01 + 7.341841939120078e-01j, + -1.461948419016121e-01 - 7.341841939120078e-01j, + -1.348975284762046e-01 + 6.493235066053785e-01j, + -1.348975284762046e-01 - 6.493235066053785e-01j, + -1.256628210712206e-01 + 5.704921366889227e-01j, + -1.256628210712206e-01 - 5.704921366889227e-01j, + -1.181038235962314e-01 + 4.966120551231630e-01j, + -1.181038235962314e-01 - 4.966120551231630e-01j, + -1.119304913239356e-01 + 4.267938916403775e-01j, + -1.119304913239356e-01 - 4.267938916403775e-01j, + -1.069237739782691e-01 + 3.602914879527338e-01j, + -1.069237739782691e-01 - 3.602914879527338e-01j, + -1.029178030691416e-01 + 2.964677964142126e-01j, + -1.029178030691416e-01 - 2.964677964142126e-01j, + -9.978747500816100e-02 + 2.347687643085738e-01j, + -9.978747500816100e-02 - 2.347687643085738e-01j, + -9.743974496324025e-02 + 1.747028739092479e-01j, + -9.743974496324025e-02 - 1.747028739092479e-01j, + -9.580754551625957e-02 + 1.158246860771989e-01j, + -9.580754551625957e-02 - 1.158246860771989e-01j, + -9.484562207782568e-02 + 5.772118357151691e-02j, + -9.484562207782568e-02 - 5.772118357151691e-02j, + -9.452783117928215e-02 + ] + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 9.585686688851069e-09 + xp_assert_equal(z, z2) + xp_assert_close( + _sort_cmplx(p, xp), _sort_cmplx(p2, xp), + rtol=1e-8 if not DEFAULT_F32 else 1e-6 + ) + assert math.isclose(k, k2, abs_tol=1e-13) + + def test_bandpass(self, xp): + z, p, k = butter(8, xp.asarray([0.25, 0.33]), 'band', output='zpk') + z2 = [1 + 0j, 1, 1, 1, 1, 1, 1, 1, + -1, -1, -1, -1, -1, -1, -1, -1] + p2 = [ + 4.979909925436156e-01 + 8.367609424799387e-01j, + 4.979909925436156e-01 - 8.367609424799387e-01j, + 4.913338722555539e-01 + 7.866774509868817e-01j, + 4.913338722555539e-01 - 7.866774509868817e-01j, + 5.035229361778706e-01 + 7.401147376726750e-01j, + 5.035229361778706e-01 - 7.401147376726750e-01j, + 5.307617160406101e-01 + 7.029184459442954e-01j, + 5.307617160406101e-01 - 7.029184459442954e-01j, + 5.680556159453138e-01 + 6.788228792952775e-01j, + 5.680556159453138e-01 - 6.788228792952775e-01j, + 6.100962560818854e-01 + 6.693849403338664e-01j, + 6.100962560818854e-01 - 6.693849403338664e-01j, + 6.904694312740631e-01 + 6.930501690145245e-01j, + 6.904694312740631e-01 - 6.930501690145245e-01j, + 6.521767004237027e-01 + 6.744414640183752e-01j, + 6.521767004237027e-01 - 6.744414640183752e-01j, + ] + z2 = xp.asarray(z2, dtype=xp.complex128) + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 3.398854055800844e-08 + xp_assert_equal(z, z2, check_dtype=False) + xp_assert_close( + _sort_cmplx(p, xp), _sort_cmplx(p2, xp), + rtol=1e-13 if not DEFAULT_F32 else 1e-7 + ) + assert math.isclose(k, k2, rel_tol=1e-13 if not DEFAULT_F32 else 1e-5) + + # bandpass analog + z, p, k = butter(4, xp.asarray([90.5, 110.5]), 'bp', analog=True, output='zpk') + z2 = xp.zeros(4, dtype=xp.complex128) + p2 = [ + -4.179137760733086e+00 + 1.095935899082837e+02j, + -4.179137760733086e+00 - 1.095935899082837e+02j, + -9.593598668443835e+00 + 1.034745398029734e+02j, + -9.593598668443835e+00 - 1.034745398029734e+02j, + -8.883991981781929e+00 + 9.582087115567160e+01j, + -8.883991981781929e+00 - 9.582087115567160e+01j, + -3.474530886568715e+00 + 9.111599925805801e+01j, + -3.474530886568715e+00 - 9.111599925805801e+01j, + ] + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 1.600000000000001e+05 + xp_assert_equal(z, z2) + xp_assert_close(_sort_cmplx(p, xp), _sort_cmplx(p2, xp)) + assert math.isclose(k, k2, rel_tol=1e-15) + + def test_bandstop(self, xp): + z, p, k = butter(7, xp.asarray([0.45, 0.56]), 'stop', output='zpk') + z2 = [-1.594474531383421e-02 + 9.998728744679880e-01j, + -1.594474531383421e-02 - 9.998728744679880e-01j, + -1.594474531383421e-02 + 9.998728744679880e-01j, + -1.594474531383421e-02 - 9.998728744679880e-01j, + -1.594474531383421e-02 + 9.998728744679880e-01j, + -1.594474531383421e-02 - 9.998728744679880e-01j, + -1.594474531383421e-02 + 9.998728744679880e-01j, + -1.594474531383421e-02 - 9.998728744679880e-01j, + -1.594474531383421e-02 + 9.998728744679880e-01j, + -1.594474531383421e-02 - 9.998728744679880e-01j, + -1.594474531383421e-02 + 9.998728744679880e-01j, + -1.594474531383421e-02 - 9.998728744679880e-01j, + -1.594474531383421e-02 + 9.998728744679880e-01j, + -1.594474531383421e-02 - 9.998728744679880e-01j] + p2 = [-1.766850742887729e-01 + 9.466951258673900e-01j, + -1.766850742887729e-01 - 9.466951258673900e-01j, + 1.467897662432886e-01 + 9.515917126462422e-01j, + 1.467897662432886e-01 - 9.515917126462422e-01j, + -1.370083529426906e-01 + 8.880376681273993e-01j, + -1.370083529426906e-01 - 8.880376681273993e-01j, + 1.086774544701390e-01 + 8.915240810704319e-01j, + 1.086774544701390e-01 - 8.915240810704319e-01j, + -7.982704457700891e-02 + 8.506056315273435e-01j, + -7.982704457700891e-02 - 8.506056315273435e-01j, + 5.238812787110331e-02 + 8.524011102699969e-01j, + 5.238812787110331e-02 - 8.524011102699969e-01j, + -1.357545000491310e-02 + 8.382287744986582e-01j, + -1.357545000491310e-02 - 8.382287744986582e-01j] + z2 = xp.asarray(z2, dtype=xp.complex128) + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 4.577122512960063e-01 + xp_assert_close(_sort_cmplx(z, xp), _sort_cmplx(z2, xp)) + xp_assert_close(_sort_cmplx(p, xp), _sort_cmplx(p2, xp)) + assert math.isclose(k, k2, rel_tol=1e-14 if not DEFAULT_F32 else 1e-6) + + @xfail_xp_backends("cupy", reason="inaccurate on CuPy") + def test_ba_output(self, xp): + b, a = butter(4, xp.asarray([100, 300]), 'bandpass', analog=True) + b2 = [1.6e+09, 0, 0, 0, 0] + a2 = [1.000000000000000e+00, 5.226251859505511e+02, + 2.565685424949238e+05, 6.794127417357160e+07, + 1.519411254969542e+10, 2.038238225207147e+12, + 2.309116882454312e+14, 1.411088002066486e+16, + 8.099999999999991e+17] + b2 = xp.asarray(b2, dtype=xp.float64) + a2 = xp.asarray(a2, dtype=xp.float64) + xp_assert_close(b, b2, rtol=1e-14) + xp_assert_close(a, a2, rtol=1e-14) + + def test_fs_param(self): + for fs in (900, 900.1, 1234.567): + for N in (0, 1, 2, 3, 10): + for fc in (100, 100.1, 432.12345): + for btype in ('lp', 'hp'): + ba1 = butter(N, fc, btype, fs=fs) + ba2 = butter(N, fc/(fs/2), btype) + for ba1_, ba2_ in zip(ba1, ba2): + xp_assert_close(ba1_, ba2_) + for fc in ((100, 200), (100.1, 200.2), (321.123, 432.123)): + for btype in ('bp', 'bs'): + ba1 = butter(N, fc, btype, fs=fs) + for seq in (list, tuple, array): + fcnorm = seq([f/(fs/2) for f in fc]) + ba2 = butter(N, fcnorm, btype) + for ba1_, ba2_ in zip(ba1, ba2): + xp_assert_close(ba1_, ba2_) + + +@skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") +@make_xp_test_case(cheby1) +class TestCheby1: + + def test_degenerate(self, xp): + # 0-order filter is just a passthrough + # Even-order filters have DC gain of -rp dB + b, a = cheby1(0, 10*math.log10(2), xp.asarray(1), analog=True) + assert_array_almost_equal( + b, xp.asarray([1 / math.sqrt(2)], dtype=xp.float64) + ) + xp_assert_equal(a, xp.asarray([1.0], dtype=xp.float64)) + + # 1-order filter is same for all types + b, a = cheby1(1, 10*math.log10(2), xp.asarray(1), analog=True) + assert_array_almost_equal(b, xp.asarray([1.], dtype=xp.float64)) + assert_array_almost_equal(a, xp.asarray([1., 1], dtype=xp.float64)) + + z, p, k = cheby1(1, 0.1, xp.asarray(0.3), output='zpk') + xp_assert_equal(z, xp.asarray([-1.0], dtype=xp.float64)) + xp_assert_close( + p, xp.asarray([-5.390126972799615e-01 + 0j], dtype=xp.complex128), + rtol=1e-14 if not DEFAULT_F32 else 1e-7 + ) + assert math.isclose( + k, 7.695063486399808e-01, rel_tol=1e-14 if not DEFAULT_F32 else 1e-7 + ) + + def test_basic(self, xp): + for N in range(25): + wn = xp.asarray(0.01) + z, p, k = cheby1(N, 1, wn, 'low', analog=True, output='zpk') + assert_array_almost_equal(z, xp.asarray([], dtype=xp.float64)) + assert p.shape[0] == N + assert xp.all(xp.real(p) <= 0) # No poles in right half of S-plane + + for N in range(25): + wn = xp.asarray(0.01) + z, p, k = cheby1(N, 1, wn, 'high', analog=False, output='zpk') + xp_assert_equal(z, xp.ones(N, dtype=xp.float64)) # All zeros exactly at DC + assert xp.all(xp.abs(p) <= 1) # No poles outside unit circle + + # Same test as TestNormalize + b, a = cheby1(8, 0.5, xp.asarray(0.048)) + xp_assert_close( + b, xp.asarray([2.150733144728282e-11, 1.720586515782626e-10, + 6.022052805239190e-10, 1.204410561047838e-09, + 1.505513201309798e-09, 1.204410561047838e-09, + 6.022052805239190e-10, 1.720586515782626e-10, + 2.150733144728282e-11], dtype=xp.float64), + rtol=0, atol=1.5e-14 + ) + xp_assert_close( + a, xp.asarray([1.000000000000000e+00, -7.782402035027959e+00, + 2.654354569747454e+01, -5.182182531666387e+01, + 6.334127355102684e+01, -4.963358186631157e+01, + 2.434862182949389e+01, -6.836925348604676e+00, + 8.412934944449140e-01], dtype=xp.float64), + rtol=0, atol=5e-14 if not DEFAULT_F32 else 1e-7 + ) + + b, a = cheby1(4, 1, xp.asarray([0.4, 0.7]), btype='band') + assert_array_almost_equal( + b, xp.asarray([0.0084, 0, -0.0335, 0, 0.0502, 0, + -0.0335, 0, 0.0084], dtype=xp.float64), + decimal=4 + ) + assert_array_almost_equal( + a, xp.asarray([1.0, 1.1191, 2.862, 2.2986, 3.4137, + 1.8653, 1.8982, 0.5676, 0.4103], dtype=xp.float64), + decimal=4 + ) + + b2, a2 = cheby1(5, 3, xp.asarray(1), analog=True) + assert_array_almost_equal( + b2, xp.asarray([0.0626], dtype=xp.float64), decimal=4 + ) + assert_array_almost_equal( + a2, xp.asarray([1, 0.5745, 1.4150, 0.5489, 0.4080, + 0.0626], dtype=xp.float64), + decimal=4) + + b, a = cheby1(8, 0.5, xp.asarray(0.1)) + assert_array_almost_equal( + b, + 1.0e-006 * xp.asarray( + [0.00703924326028, 0.05631394608227, 0.19709881128793, + 0.39419762257586, 0.49274702821983, 0.39419762257586, + 0.19709881128793, 0.05631394608227, 0.00703924326028 + ], dtype=xp.float64 + ), + decimal=13 + ) + assert_array_almost_equal( + a, xp.asarray( + [1.00000000000000, -7.44912258934158, 24.46749067762108, + -46.27560200466141, 55.11160187999928, -42.31640010161038, + 20.45543300484147, -5.69110270561444, 0.69770374759022 + ], dtype=xp.float64 + ), + decimal=13 if not DEFAULT_F32 else 6 + ) + + b, a = cheby1(8, 0.5, xp.asarray(0.25)) + assert_array_almost_equal( + b, + 1.0e-003 * xp.asarray( + [0.00895261138923, 0.07162089111382, 0.25067311889837, + 0.50134623779673, 0.62668279724591, 0.50134623779673, + 0.25067311889837, 0.07162089111382, 0.00895261138923 + ], dtype=xp.float64 + ), + decimal=13) + assert_array_almost_equal( + a, + xp.asarray( + [1.00000000000000, -5.97529229188545, + 16.58122329202101, -27.71423273542923, + 30.39509758355313, -22.34729670426879, + 10.74509800434910, -3.08924633697497, + 0.40707685889802 + ], dtype=xp.float64 + ), decimal=13) + + def test_highpass(self, xp): + # high even order + z, p, k = cheby1(24, 0.7, xp.asarray(0.2), 'high', output='zpk') + z2 = xp.ones(24, dtype=xp.float64) + p2 = [-6.136558509657073e-01 + 2.700091504942893e-01j, + -6.136558509657073e-01 - 2.700091504942893e-01j, + -3.303348340927516e-01 + 6.659400861114254e-01j, + -3.303348340927516e-01 - 6.659400861114254e-01j, + 8.779713780557169e-03 + 8.223108447483040e-01j, + 8.779713780557169e-03 - 8.223108447483040e-01j, + 2.742361123006911e-01 + 8.356666951611864e-01j, + 2.742361123006911e-01 - 8.356666951611864e-01j, + 4.562984557158206e-01 + 7.954276912303594e-01j, + 4.562984557158206e-01 - 7.954276912303594e-01j, + 5.777335494123628e-01 + 7.435821817961783e-01j, + 5.777335494123628e-01 - 7.435821817961783e-01j, + 6.593260977749194e-01 + 6.955390907990932e-01j, + 6.593260977749194e-01 - 6.955390907990932e-01j, + 7.149590948466562e-01 + 6.559437858502012e-01j, + 7.149590948466562e-01 - 6.559437858502012e-01j, + 7.532432388188739e-01 + 6.256158042292060e-01j, + 7.532432388188739e-01 - 6.256158042292060e-01j, + 7.794365244268271e-01 + 6.042099234813333e-01j, + 7.794365244268271e-01 - 6.042099234813333e-01j, + 7.967253874772997e-01 + 5.911966597313203e-01j, + 7.967253874772997e-01 - 5.911966597313203e-01j, + 8.069756417293870e-01 + 5.862214589217275e-01j, + 8.069756417293870e-01 - 5.862214589217275e-01j] + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 6.190427617192018e-04 + xp_assert_equal(z, z2) + xp_assert_close( + _sort_cmplx(p, xp=xp), _sort_cmplx(p2, xp=xp), + rtol=1e-10 if not DEFAULT_F32 else 1e-7 + ) + assert math.isclose(k, k2, rel_tol=1e-10 if not DEFAULT_F32 else 1e-6) + + # high odd order + z, p, k = cheby1(23, 0.8, xp.asarray(0.3), 'high', output='zpk') + z2 = xp.ones(23, dtype=xp.float64) + p2 = [-7.676400532011010e-01, + -6.754621070166477e-01 + 3.970502605619561e-01j, + -6.754621070166477e-01 - 3.970502605619561e-01j, + -4.528880018446727e-01 + 6.844061483786332e-01j, + -4.528880018446727e-01 - 6.844061483786332e-01j, + -1.986009130216447e-01 + 8.382285942941594e-01j, + -1.986009130216447e-01 - 8.382285942941594e-01j, + 2.504673931532608e-02 + 8.958137635794080e-01j, + 2.504673931532608e-02 - 8.958137635794080e-01j, + 2.001089429976469e-01 + 9.010678290791480e-01j, + 2.001089429976469e-01 - 9.010678290791480e-01j, + 3.302410157191755e-01 + 8.835444665962544e-01j, + 3.302410157191755e-01 - 8.835444665962544e-01j, + 4.246662537333661e-01 + 8.594054226449009e-01j, + 4.246662537333661e-01 - 8.594054226449009e-01j, + 4.919620928120296e-01 + 8.366772762965786e-01j, + 4.919620928120296e-01 - 8.366772762965786e-01j, + 5.385746917494749e-01 + 8.191616180796720e-01j, + 5.385746917494749e-01 - 8.191616180796720e-01j, + 5.855636993537203e-01 + 8.060680937701062e-01j, + 5.855636993537203e-01 - 8.060680937701062e-01j, + 5.688812849391721e-01 + 8.086497795114683e-01j, + 5.688812849391721e-01 - 8.086497795114683e-01j] + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 1.941697029206324e-05 + xp_assert_equal(z, z2) + xp_assert_close( + _sort_cmplx(p, xp=xp), _sort_cmplx(p2, xp=xp), + rtol=1e-10 if not DEFAULT_F32 else 1e-7 + ) + assert math.isclose( + k, k2, rel_tol=1e-10 if not DEFAULT_F32 else 1e-6 + ) + + z, p, k = cheby1(10, 1, xp.asarray(1000), 'high', analog=True, output='zpk') + z2 = xp.zeros(10, dtype=xp.float64) + p2 = [-3.144743169501551e+03 + 3.511680029092744e+03j, + -3.144743169501551e+03 - 3.511680029092744e+03j, + -5.633065604514602e+02 + 2.023615191183945e+03j, + -5.633065604514602e+02 - 2.023615191183945e+03j, + -1.946412183352025e+02 + 1.372309454274755e+03j, + -1.946412183352025e+02 - 1.372309454274755e+03j, + -7.987162953085479e+01 + 1.105207708045358e+03j, + -7.987162953085479e+01 - 1.105207708045358e+03j, + -2.250315039031946e+01 + 1.001723931471477e+03j, + -2.250315039031946e+01 - 1.001723931471477e+03j] + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 8.912509381337453e-01 + xp_assert_equal(z, z2) + xp_assert_close(_sort_cmplx(p, xp=xp), _sort_cmplx(p2, xp=xp), rtol=1e-13) + assert math.isclose(k, k2, rel_tol=1e-15) + + def test_bandpass(self, xp): + z, p, k = cheby1(8, 1, xp.asarray([0.3, 0.4]), 'bp', output='zpk') + z2 = [1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1] + p2 = [3.077784854851463e-01 + 9.453307017592942e-01j, + 3.077784854851463e-01 - 9.453307017592942e-01j, + 3.280567400654425e-01 + 9.272377218689016e-01j, + 3.280567400654425e-01 - 9.272377218689016e-01j, + 3.677912763284301e-01 + 9.038008865279966e-01j, + 3.677912763284301e-01 - 9.038008865279966e-01j, + 4.194425632520948e-01 + 8.769407159656157e-01j, + 4.194425632520948e-01 - 8.769407159656157e-01j, + 4.740921994669189e-01 + 8.496508528630974e-01j, + 4.740921994669189e-01 - 8.496508528630974e-01j, + 5.234866481897429e-01 + 8.259608422808477e-01j, + 5.234866481897429e-01 - 8.259608422808477e-01j, + 5.844717632289875e-01 + 8.052901363500210e-01j, + 5.844717632289875e-01 - 8.052901363500210e-01j, + 5.615189063336070e-01 + 8.100667803850766e-01j, + 5.615189063336070e-01 - 8.100667803850766e-01j] + z2 = xp.asarray(z2, dtype=xp.float64) + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 5.007028718074307e-09 + xp_assert_equal(z, z2, check_dtype=False) + xp_assert_close( + _sort_cmplx(p, xp=xp), _sort_cmplx(p2, xp=xp), + rtol=1e-13 if not DEFAULT_F32 else 1e-7 + ) + assert math.isclose(k, k2, rel_tol=1e-13 if not DEFAULT_F32 else 1e-6) + + def test_bandstop(self, xp): + z, p, k = cheby1(7, 1, xp.asarray([0.5, 0.6]), 'stop', output='zpk') + z2 = [-1.583844403245361e-01 + 9.873775210440450e-01j, + -1.583844403245361e-01 - 9.873775210440450e-01j, + -1.583844403245361e-01 + 9.873775210440450e-01j, + -1.583844403245361e-01 - 9.873775210440450e-01j, + -1.583844403245361e-01 + 9.873775210440450e-01j, + -1.583844403245361e-01 - 9.873775210440450e-01j, + -1.583844403245361e-01 + 9.873775210440450e-01j, + -1.583844403245361e-01 - 9.873775210440450e-01j, + -1.583844403245361e-01 + 9.873775210440450e-01j, + -1.583844403245361e-01 - 9.873775210440450e-01j, + -1.583844403245361e-01 + 9.873775210440450e-01j, + -1.583844403245361e-01 - 9.873775210440450e-01j, + -1.583844403245361e-01 + 9.873775210440450e-01j, + -1.583844403245361e-01 - 9.873775210440450e-01j] + p2 = [-8.942974551472813e-02 + 3.482480481185926e-01j, + -8.942974551472813e-02 - 3.482480481185926e-01j, + 1.293775154041798e-01 + 8.753499858081858e-01j, + 1.293775154041798e-01 - 8.753499858081858e-01j, + 3.399741945062013e-02 + 9.690316022705607e-01j, + 3.399741945062013e-02 - 9.690316022705607e-01j, + 4.167225522796539e-04 + 9.927338161087488e-01j, + 4.167225522796539e-04 - 9.927338161087488e-01j, + -3.912966549550960e-01 + 8.046122859255742e-01j, + -3.912966549550960e-01 - 8.046122859255742e-01j, + -3.307805547127368e-01 + 9.133455018206508e-01j, + -3.307805547127368e-01 - 9.133455018206508e-01j, + -3.072658345097743e-01 + 9.443589759799366e-01j, + -3.072658345097743e-01 - 9.443589759799366e-01j] + z2 = xp.asarray(z2, dtype=xp.complex128) + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 3.619438310405028e-01 + xp_assert_close( + _sort_cmplx(z, xp=xp), _sort_cmplx(z2, xp=xp), + rtol=1e-13 if not DEFAULT_F32 else 1e-6 + ) + xp_assert_close( + _sort_cmplx(p, xp=xp), _sort_cmplx(p2, xp=xp), + rtol=1e-13 if not DEFAULT_F32 else 1e-6 + ) + assert math.isclose( + k, k2, rel_tol=0, abs_tol=5e-16 if not DEFAULT_F32 else 1e-7 + ) + + @xfail_xp_backends("cupy", reason="inaccurate on CuPy") + def test_ba_output(self, xp): + # with transfer function conversion, without digital conversion + b, a = cheby1(5, 0.9, xp.asarray([210, 310.0]), 'stop', analog=True) + b2 = [1.000000000000006e+00, 0, + 3.255000000000020e+05, 0, + 4.238010000000026e+10, 0, + 2.758944510000017e+15, 0, + 8.980364380050052e+19, 0, + 1.169243442282517e+24 + ] + a2 = [1.000000000000000e+00, 4.630555945694342e+02, + 4.039266454794788e+05, 1.338060988610237e+08, + 5.844333551294591e+10, 1.357346371637638e+13, + 3.804661141892782e+15, 5.670715850340080e+17, + 1.114411200988328e+20, 8.316815934908471e+21, + 1.169243442282517e+24 + ] + b2, a2 = map(lambda t: xp.asarray(t, dtype=xp.float64), (b2, a2)) + xp_assert_close(b, b2, rtol=1e-14 if not DEFAULT_F32 else 1e-7) + xp_assert_close(a, a2, rtol=1e-14 if not DEFAULT_F32 else 1e-7) + + def test_fs_param(self): + for fs in (900, 900.1, 1234.567): + for N in (0, 1, 2, 3, 10): + for fc in (100, 100.1, 432.12345): + for btype in ('lp', 'hp'): + ba1 = cheby1(N, 1, fc, btype, fs=fs) + ba2 = cheby1(N, 1, fc/(fs/2), btype) + for ba1_, ba2_ in zip(ba1, ba2): + xp_assert_close(ba1_, ba2_) + for fc in ((100, 200), (100.1, 200.2), (321.123, 432.123)): + for btype in ('bp', 'bs'): + ba1 = cheby1(N, 1, fc, btype, fs=fs) + for seq in (list, tuple, array): + fcnorm = seq([f/(fs/2) for f in fc]) + ba2 = cheby1(N, 1, fcnorm, btype) + for ba1_, ba2_ in zip(ba1, ba2): + xp_assert_close(ba1_, ba2_) + + +@skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") +@make_xp_test_case(cheby2) +class TestCheby2: + + def test_degenerate(self, xp): + # 0-order filter is just a passthrough + # Stopband ripple factor doesn't matter + b, a = cheby2(0, 123.456, xp.asarray(1), analog=True) + xp_assert_equal(b, xp.asarray([1.0], dtype=xp.float64)) + xp_assert_equal(a, xp.asarray([1.0], dtype=xp.float64)) + + # 1-order filter is same for all types + b, a = cheby2(1, 10*math.log10(2), xp.asarray(1.), analog=True) + assert_array_almost_equal(b, xp.asarray([1], dtype=xp.float64)) + assert_array_almost_equal(a, xp.asarray([1, 1], dtype=xp.float64)) + + z, p, k = cheby2(1, 50, xp.asarray(0.3), output='zpk') + xp_assert_equal(z, xp.asarray([-1], dtype=xp.complex128)) + xp_assert_close( + p, xp.asarray([9.967826460175649e-01 + 0j], dtype=xp.complex128), + rtol=1e-14 if not DEFAULT_F32 else 1e-7 + ) + assert math.isclose( + k, 1.608676991217512e-03, rel_tol=1e-14 if not DEFAULT_F32 else 1e-6 + ) + + def test_basic(self, xp): + for N in range(25): + wn = xp.asarray(0.01) + z, p, k = cheby2(N, 40, wn, 'low', analog=True, output='zpk') + assert p.shape[0] == N + assert all(xp.real(p) <= 0) # No poles in right half of S-plane + + for N in range(25): + wn = xp.asarray(0.01) + z, p, k = cheby2(N, 40, wn, 'high', analog=False, output='zpk') + assert all(xp.abs(p) <= 1) # No poles outside unit circle + + B, A = cheby2(18, 100, xp.asarray(0.5)) + assert_array_almost_equal( + B, xp.asarray([ + 0.00167583914216, 0.01249479541868, 0.05282702120282, + 0.15939804265706, 0.37690207631117, 0.73227013789108, + 1.20191856962356, 1.69522872823393, 2.07598674519837, + 2.21972389625291, 2.07598674519838, 1.69522872823395, + 1.20191856962359, 0.73227013789110, 0.37690207631118, + 0.15939804265707, 0.05282702120282, 0.01249479541868, + 0.00167583914216], dtype=xp.float64), + decimal=13 if not DEFAULT_F32 else 6 + ) + assert_array_almost_equal( + A, xp.asarray([ + 1.00000000000000, -0.27631970006174, 3.19751214254060, + -0.15685969461355, 4.13926117356269, 0.60689917820044, + 2.95082770636540, 0.89016501910416, 1.32135245849798, + 0.51502467236824, 0.38906643866660, 0.15367372690642, + 0.07255803834919, 0.02422454070134, 0.00756108751837, + 0.00179848550988, 0.00033713574499, 0.00004258794833, + 0.00000281030149], dtype=xp.float64), + decimal=13 if not DEFAULT_F32 else 6 + ) + + def test_highpass(self, xp): + # high even order + z, p, k = cheby2(26, 60, xp.asarray(0.3), 'high', output='zpk') + z2 = [9.981088955489852e-01 + 6.147058341984388e-02j, + 9.981088955489852e-01 - 6.147058341984388e-02j, + 9.832702870387426e-01 + 1.821525257215483e-01j, + 9.832702870387426e-01 - 1.821525257215483e-01j, + 9.550760158089112e-01 + 2.963609353922882e-01j, + 9.550760158089112e-01 - 2.963609353922882e-01j, + 9.162054748821922e-01 + 4.007087817803773e-01j, + 9.162054748821922e-01 - 4.007087817803773e-01j, + 8.700619897368064e-01 + 4.929423232136168e-01j, + 8.700619897368064e-01 - 4.929423232136168e-01j, + 5.889791753434985e-01 + 8.081482110427953e-01j, + 5.889791753434985e-01 - 8.081482110427953e-01j, + 5.984900456570295e-01 + 8.011302423760501e-01j, + 5.984900456570295e-01 - 8.011302423760501e-01j, + 6.172880888914629e-01 + 7.867371958365343e-01j, + 6.172880888914629e-01 - 7.867371958365343e-01j, + 6.448899971038180e-01 + 7.642754030030161e-01j, + 6.448899971038180e-01 - 7.642754030030161e-01j, + 6.804845629637927e-01 + 7.327624168637228e-01j, + 6.804845629637927e-01 - 7.327624168637228e-01j, + 8.202619107108660e-01 + 5.719881098737678e-01j, + 8.202619107108660e-01 - 5.719881098737678e-01j, + 7.228410452536148e-01 + 6.910143437705678e-01j, + 7.228410452536148e-01 - 6.910143437705678e-01j, + 7.702121399578629e-01 + 6.377877856007792e-01j, + 7.702121399578629e-01 - 6.377877856007792e-01j] + p2 = [7.365546198286450e-01 + 4.842085129329526e-02j, + 7.365546198286450e-01 - 4.842085129329526e-02j, + 7.292038510962885e-01 + 1.442201672097581e-01j, + 7.292038510962885e-01 - 1.442201672097581e-01j, + 7.151293788040354e-01 + 2.369925800458584e-01j, + 7.151293788040354e-01 - 2.369925800458584e-01j, + 6.955051820787286e-01 + 3.250341363856910e-01j, + 6.955051820787286e-01 - 3.250341363856910e-01j, + 6.719122956045220e-01 + 4.070475750638047e-01j, + 6.719122956045220e-01 - 4.070475750638047e-01j, + 6.461722130611300e-01 + 4.821965916689270e-01j, + 6.461722130611300e-01 - 4.821965916689270e-01j, + 5.528045062872224e-01 + 8.162920513838372e-01j, + 5.528045062872224e-01 - 8.162920513838372e-01j, + 5.464847782492791e-01 + 7.869899955967304e-01j, + 5.464847782492791e-01 - 7.869899955967304e-01j, + 5.488033111260949e-01 + 7.520442354055579e-01j, + 5.488033111260949e-01 - 7.520442354055579e-01j, + 6.201874719022955e-01 + 5.500894392527353e-01j, + 6.201874719022955e-01 - 5.500894392527353e-01j, + 5.586478152536709e-01 + 7.112676877332921e-01j, + 5.586478152536709e-01 - 7.112676877332921e-01j, + 5.958145844148228e-01 + 6.107074340842115e-01j, + 5.958145844148228e-01 - 6.107074340842115e-01j, + 5.747812938519067e-01 + 6.643001536914696e-01j, + 5.747812938519067e-01 - 6.643001536914696e-01j] + z2 = xp.asarray(z2, dtype=xp.complex128) + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 6.190427617192018e-04 + k2 = 9.932997786497189e-02 + xp_assert_close( + _sort_cmplx(z, xp=xp), _sort_cmplx(z2, xp=xp), + rtol=1e-13 if not DEFAULT_F32 else 1e-6 + ) + xp_assert_close( + _sort_cmplx(p, xp=xp), _sort_cmplx(p2, xp=xp), + rtol=1e-12 if not DEFAULT_F32 else 1e-6 + ) + assert math.isclose( + k, k2, rel_tol=1e-11 if not DEFAULT_F32 else 1e-6 + ) + + # high odd order + z, p, k = cheby2(25, 80, xp.asarray(0.5), 'high', output='zpk') + z2 = [9.690690376586687e-01 + 2.467897896011971e-01j, + 9.690690376586687e-01 - 2.467897896011971e-01j, + 9.999999999999492e-01, + 8.835111277191199e-01 + 4.684101698261429e-01j, + 8.835111277191199e-01 - 4.684101698261429e-01j, + 7.613142857900539e-01 + 6.483830335935022e-01j, + 7.613142857900539e-01 - 6.483830335935022e-01j, + 6.232625173626231e-01 + 7.820126817709752e-01j, + 6.232625173626231e-01 - 7.820126817709752e-01j, + 4.864456563413621e-01 + 8.737108351316745e-01j, + 4.864456563413621e-01 - 8.737108351316745e-01j, + 3.618368136816749e-01 + 9.322414495530347e-01j, + 3.618368136816749e-01 - 9.322414495530347e-01j, + 2.549486883466794e-01 + 9.669545833752675e-01j, + 2.549486883466794e-01 - 9.669545833752675e-01j, + 1.676175432109457e-01 + 9.858520980390212e-01j, + 1.676175432109457e-01 - 9.858520980390212e-01j, + 1.975218468277521e-03 + 9.999980492540941e-01j, + 1.975218468277521e-03 - 9.999980492540941e-01j, + 1.786959496651858e-02 + 9.998403260399917e-01j, + 1.786959496651858e-02 - 9.998403260399917e-01j, + 9.967933660557139e-02 + 9.950196127985684e-01j, + 9.967933660557139e-02 - 9.950196127985684e-01j, + 5.013970951219547e-02 + 9.987422137518890e-01j, + 5.013970951219547e-02 - 9.987422137518890e-01j] + p2 = [4.218866331906864e-01, + 4.120110200127552e-01 + 1.361290593621978e-01j, + 4.120110200127552e-01 - 1.361290593621978e-01j, + 3.835890113632530e-01 + 2.664910809911026e-01j, + 3.835890113632530e-01 - 2.664910809911026e-01j, + 3.399195570456499e-01 + 3.863983538639875e-01j, + 3.399195570456499e-01 - 3.863983538639875e-01j, + 2.855977834508353e-01 + 4.929444399540688e-01j, + 2.855977834508353e-01 - 4.929444399540688e-01j, + 2.255765441339322e-01 + 5.851631870205766e-01j, + 2.255765441339322e-01 - 5.851631870205766e-01j, + 1.644087535815792e-01 + 6.637356937277153e-01j, + 1.644087535815792e-01 - 6.637356937277153e-01j, + -7.293633845273095e-02 + 9.739218252516307e-01j, + -7.293633845273095e-02 - 9.739218252516307e-01j, + 1.058259206358626e-01 + 7.304739464862978e-01j, + 1.058259206358626e-01 - 7.304739464862978e-01j, + -5.703971947785402e-02 + 9.291057542169088e-01j, + -5.703971947785402e-02 - 9.291057542169088e-01j, + 5.263875132656864e-02 + 7.877974334424453e-01j, + 5.263875132656864e-02 - 7.877974334424453e-01j, + -3.007943405982616e-02 + 8.846331716180016e-01j, + -3.007943405982616e-02 - 8.846331716180016e-01j, + 6.857277464483946e-03 + 8.383275456264492e-01j, + 6.857277464483946e-03 - 8.383275456264492e-01j] + z2 = xp.asarray(z2, dtype=xp.complex128) + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 6.507068761705037e-03 + xp_assert_close( + _sort_cmplx(z, xp=xp), _sort_cmplx(z2, xp=xp), + rtol=1e-13 if not DEFAULT_F32 else 1e-6 + ) + xp_assert_close( + _sort_cmplx(p, xp=xp), _sort_cmplx(p2, xp=xp), + rtol=1e-12 if not DEFAULT_F32 else 1e-6 + ) + assert math.isclose(k, k2, rel_tol=1e-11 if not DEFAULT_F32 else 1e-6) + + def test_bandpass(self, xp): + z, p, k = cheby2(9, 40, xp.asarray([0.07, 0.2]), 'pass', output='zpk') + z2 = [-9.999999999999999e-01, + 3.676588029658514e-01 + 9.299607543341383e-01j, + 3.676588029658514e-01 - 9.299607543341383e-01j, + 7.009689684982283e-01 + 7.131917730894889e-01j, + 7.009689684982283e-01 - 7.131917730894889e-01j, + 7.815697973765858e-01 + 6.238178033919218e-01j, + 7.815697973765858e-01 - 6.238178033919218e-01j, + 8.063793628819866e-01 + 5.913986160941200e-01j, + 8.063793628819866e-01 - 5.913986160941200e-01j, + 1.000000000000001e+00, + 9.944493019920448e-01 + 1.052168511576739e-01j, + 9.944493019920448e-01 - 1.052168511576739e-01j, + 9.854674703367308e-01 + 1.698642543566085e-01j, + 9.854674703367308e-01 - 1.698642543566085e-01j, + 9.762751735919308e-01 + 2.165335665157851e-01j, + 9.762751735919308e-01 - 2.165335665157851e-01j, + 9.792277171575134e-01 + 2.027636011479496e-01j, + 9.792277171575134e-01 - 2.027636011479496e-01j] + p2 = [8.143803410489621e-01 + 5.411056063397541e-01j, + 8.143803410489621e-01 - 5.411056063397541e-01j, + 7.650769827887418e-01 + 5.195412242095543e-01j, + 7.650769827887418e-01 - 5.195412242095543e-01j, + 6.096241204063443e-01 + 3.568440484659796e-01j, + 6.096241204063443e-01 - 3.568440484659796e-01j, + 6.918192770246239e-01 + 4.770463577106911e-01j, + 6.918192770246239e-01 - 4.770463577106911e-01j, + 6.986241085779207e-01 + 1.146512226180060e-01j, + 6.986241085779207e-01 - 1.146512226180060e-01j, + 8.654645923909734e-01 + 1.604208797063147e-01j, + 8.654645923909734e-01 - 1.604208797063147e-01j, + 9.164831670444591e-01 + 1.969181049384918e-01j, + 9.164831670444591e-01 - 1.969181049384918e-01j, + 9.630425777594550e-01 + 2.317513360702271e-01j, + 9.630425777594550e-01 - 2.317513360702271e-01j, + 9.438104703725529e-01 + 2.193509900269860e-01j, + 9.438104703725529e-01 - 2.193509900269860e-01j] + z2 = xp.asarray(z2, dtype=xp.complex128) + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 9.345352824659604e-03 + xp_assert_close( + _sort_cmplx(z, xp=xp), _sort_cmplx(z2, xp=xp), + rtol=1e-13 if not DEFAULT_F32 else 1e-6 + ) + xp_assert_close( + _sort_cmplx(p, xp=xp), _sort_cmplx(p2, xp=xp), + rtol=1e-13 if not DEFAULT_F32 else 1e-6 + ) + assert math.isclose(k, k2, rel_tol=1e-11 if not DEFAULT_F32 else 1e-6) + + def test_bandstop(self, xp): + z, p, k = cheby2(6, 55, xp.asarray([0.1, 0.9]), 'stop', output='zpk') + z2 = [6.230544895101009e-01 + 7.821784343111114e-01j, + 6.230544895101009e-01 - 7.821784343111114e-01j, + 9.086608545660115e-01 + 4.175349702471991e-01j, + 9.086608545660115e-01 - 4.175349702471991e-01j, + 9.478129721465802e-01 + 3.188268649763867e-01j, + 9.478129721465802e-01 - 3.188268649763867e-01j, + -6.230544895100982e-01 + 7.821784343111109e-01j, + -6.230544895100982e-01 - 7.821784343111109e-01j, + -9.086608545660116e-01 + 4.175349702472088e-01j, + -9.086608545660116e-01 - 4.175349702472088e-01j, + -9.478129721465784e-01 + 3.188268649763897e-01j, + -9.478129721465784e-01 - 3.188268649763897e-01j] + p2 = [-9.464094036167638e-01 + 1.720048695084344e-01j, + -9.464094036167638e-01 - 1.720048695084344e-01j, + -8.715844103386737e-01 + 1.370665039509297e-01j, + -8.715844103386737e-01 - 1.370665039509297e-01j, + -8.078751204586425e-01 + 5.729329866682983e-02j, + -8.078751204586425e-01 - 5.729329866682983e-02j, + 9.464094036167665e-01 + 1.720048695084332e-01j, + 9.464094036167665e-01 - 1.720048695084332e-01j, + 8.078751204586447e-01 + 5.729329866683007e-02j, + 8.078751204586447e-01 - 5.729329866683007e-02j, + 8.715844103386721e-01 + 1.370665039509331e-01j, + 8.715844103386721e-01 - 1.370665039509331e-01j] + z2 = xp.asarray(z2, dtype=xp.complex128) + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 2.917823332763358e-03 + xp_assert_close( + _sort_cmplx(z, xp=xp), _sort_cmplx(z2, xp=xp), + rtol=1e-13 if not DEFAULT_F32 else 1e-6 + ) + xp_assert_close( + _sort_cmplx(p, xp=xp), _sort_cmplx(p2, xp=xp), + rtol=1e-13 if not DEFAULT_F32 else 1e-6 + ) + assert math.isclose(k, k2, rel_tol=1e-11 if not DEFAULT_F32 else 1e-6) + + @xfail_xp_backends("cupy", reason="inaccurate on CuPy") + def test_ba_output(self, xp): + # with transfer function conversion, without digital conversion + b, a = cheby2(5, 20, xp.asarray([2010, 2100]), 'stop', True) + b2 = [1.000000000000000e+00, 0, # Matlab: 6.683253076978249e-12, + 2.111512500000000e+07, 0, # Matlab: 1.134325604589552e-04, + 1.782966433781250e+14, 0, # Matlab: 7.216787944356781e+02, + 7.525901316990656e+20, 0, # Matlab: 2.039829265789886e+09, + 1.587960565565748e+27, 0, # Matlab: 2.161236218626134e+15, + 1.339913493808585e+33] + a2 = [1.000000000000000e+00, 1.849550755473371e+02, + 2.113222918998538e+07, 3.125114149732283e+09, + 1.785133457155609e+14, 1.979158697776348e+16, + 7.535048322653831e+20, 5.567966191263037e+22, + 1.589246884221346e+27, 5.871210648525566e+28, + 1.339913493808590e+33] + b2 = xp.asarray(b2, dtype=xp.float64) + a2 = xp.asarray(a2, dtype=xp.float64) + xp_assert_close(b, b2, rtol=5e-14 if not DEFAULT_F32 else 1e-7) + xp_assert_close(a, a2, rtol=5e-14 if not DEFAULT_F32 else 1e-7) + + def test_fs_param(self): + for fs in (900, 900.1, 1234.567): + for N in (0, 1, 2, 3, 10): + for fc in (100, 100.1, 432.12345): + for btype in ('lp', 'hp'): + ba1 = cheby2(N, 20, fc, btype, fs=fs) + ba2 = cheby2(N, 20, fc/(fs/2), btype) + for ba1_, ba2_ in zip(ba1, ba2): + xp_assert_close(ba1_, ba2_) + for fc in ((100, 200), (100.1, 200.2), (321.123, 432.123)): + for btype in ('bp', 'bs'): + ba1 = cheby2(N, 20, fc, btype, fs=fs) + for seq in (list, tuple, array): + fcnorm = seq([f/(fs/2) for f in fc]) + ba2 = cheby2(N, 20, fcnorm, btype) + for ba1_, ba2_ in zip(ba1, ba2): + xp_assert_close(ba1_, ba2_) + + +@skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") +@make_xp_test_case(ellip) +class TestEllip: + + @xfail_xp_backends("cupy", reason="dtypes do not match") + def test_degenerate(self, xp): + # 0-order filter is just a passthrough + # Even-order filters have DC gain of -rp dB + # Stopband ripple factor doesn't matter + b, a = ellip(0, 10*math.log10(2), 123.456, xp.asarray(1.), analog=True) + assert_array_almost_equal(b, xp.asarray([1/math.sqrt(2)], dtype=xp.float64)) + xp_assert_equal(a, xp.asarray([1.0], dtype=xp.float64)) + + # 1-order filter is same for all types + b, a = ellip(1, 10*math.log10(2), 1, xp.asarray(1.), analog=True) + assert_array_almost_equal(b, xp.asarray([1.], dtype=xp.float64)) + assert_array_almost_equal(a, xp.asarray([1., 1], dtype=xp.float64)) + + z, p, k = ellip(1, 1, 55, xp.asarray(0.3), output='zpk') + xp_assert_close( + z, xp.asarray([-9.999999999999998e-01 + 0j], dtype=xp.complex128), + rtol=1e-14 + ) + xp_assert_close( + p, xp.asarray([-6.660721153525525e-04 + 0j], dtype=xp.complex128), + rtol=1e-10 if not DEFAULT_F32 else 5e-5 + ) + assert math.isclose( + k, 5.003330360576763e-01, rel_tol=1e-14 if not DEFAULT_F32 else 1e-7 + ) + + def test_basic(self, xp): + for N in range(25): + wn = xp.asarray(0.01) + z, p, k = ellip(N, 1, 40, wn, 'low', analog=True, output='zpk') + assert p.shape[0] == N + assert xp.all(xp.real(p) <= 0) # No poles in right half of S-plane + + for N in range(25): + wn = xp.asarray(0.01) + z, p, k = ellip(N, 1, 40, wn, 'high', analog=False, output='zpk') + assert xp.all(xp.abs(p) <= 1) # No poles outside unit circle + + b3, a3 = ellip(5, 3, 26, xp.asarray(1.), analog=True) + assert_array_almost_equal( + b3, xp.asarray([0.1420, 0, 0.3764, 0, 0.2409], dtype=xp.float64), + decimal=4 + ) + assert_array_almost_equal( + a3, + xp.asarray([1, 0.5686, 1.8061, 0.8017, 0.8012, 0.2409], dtype=xp.float64), + decimal=4 + ) + + b, a = ellip(3, 1, 60, xp.asarray([0.4, 0.7]), 'stop') + assert_array_almost_equal( + b, xp.asarray([0.3310, 0.3469, 1.1042, 0.7044, 1.1042, + 0.3469, 0.3310], dtype=xp.float64), + decimal=4 + ) + assert_array_almost_equal( + a, xp.asarray([1.0000, 0.6973, 1.1441, 0.5878, 0.7323, + 0.1131, -0.0060], dtype=xp.float64), + decimal=4 + ) + + def test_highpass(self, xp): + # high even order + z, p, k = ellip(24, 1, 80, xp.asarray(0.3), 'high', output='zpk') + z2 = [9.761875332501075e-01 + 2.169283290099910e-01j, + 9.761875332501075e-01 - 2.169283290099910e-01j, + 8.413503353963494e-01 + 5.404901600661900e-01j, + 8.413503353963494e-01 - 5.404901600661900e-01j, + 7.160082576305009e-01 + 6.980918098681732e-01j, + 7.160082576305009e-01 - 6.980918098681732e-01j, + 6.456533638965329e-01 + 7.636306264739803e-01j, + 6.456533638965329e-01 - 7.636306264739803e-01j, + 6.127321820971366e-01 + 7.902906256703928e-01j, + 6.127321820971366e-01 - 7.902906256703928e-01j, + 5.983607817490196e-01 + 8.012267936512676e-01j, + 5.983607817490196e-01 - 8.012267936512676e-01j, + 5.922577552594799e-01 + 8.057485658286990e-01j, + 5.922577552594799e-01 - 8.057485658286990e-01j, + 5.896952092563588e-01 + 8.076258788449631e-01j, + 5.896952092563588e-01 - 8.076258788449631e-01j, + 5.886248765538837e-01 + 8.084063054565607e-01j, + 5.886248765538837e-01 - 8.084063054565607e-01j, + 5.881802711123132e-01 + 8.087298490066037e-01j, + 5.881802711123132e-01 - 8.087298490066037e-01j, + 5.879995719101164e-01 + 8.088612386766461e-01j, + 5.879995719101164e-01 - 8.088612386766461e-01j, + 5.879354086709576e-01 + 8.089078780868164e-01j, + 5.879354086709576e-01 - 8.089078780868164e-01j] + p2 = [-3.184805259081650e-01 + 4.206951906775851e-01j, + -3.184805259081650e-01 - 4.206951906775851e-01j, + 1.417279173459985e-01 + 7.903955262836452e-01j, + 1.417279173459985e-01 - 7.903955262836452e-01j, + 4.042881216964651e-01 + 8.309042239116594e-01j, + 4.042881216964651e-01 - 8.309042239116594e-01j, + 5.128964442789670e-01 + 8.229563236799665e-01j, + 5.128964442789670e-01 - 8.229563236799665e-01j, + 5.569614712822724e-01 + 8.155957702908510e-01j, + 5.569614712822724e-01 - 8.155957702908510e-01j, + 5.750478870161392e-01 + 8.118633973883931e-01j, + 5.750478870161392e-01 - 8.118633973883931e-01j, + 5.825314018170804e-01 + 8.101960910679270e-01j, + 5.825314018170804e-01 - 8.101960910679270e-01j, + 5.856397379751872e-01 + 8.094825218722543e-01j, + 5.856397379751872e-01 - 8.094825218722543e-01j, + 5.869326035251949e-01 + 8.091827531557583e-01j, + 5.869326035251949e-01 - 8.091827531557583e-01j, + 5.874697218855733e-01 + 8.090593298213502e-01j, + 5.874697218855733e-01 - 8.090593298213502e-01j, + 5.876904783532237e-01 + 8.090127161018823e-01j, + 5.876904783532237e-01 - 8.090127161018823e-01j, + 5.877753105317594e-01 + 8.090050577978136e-01j, + 5.877753105317594e-01 - 8.090050577978136e-01j] + z2 = xp.asarray(z2, dtype=xp.complex128) + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 4.918081266957108e-02 + xp_assert_close(_sort_cmplx(z, xp=xp), + _sort_cmplx(z2, xp=xp), rtol=1e-4) + xp_assert_close(_sort_cmplx(p, xp=xp), + _sort_cmplx(p2, xp=xp), rtol=1e-4) + assert math.isclose(k, k2, rel_tol=1e-3) + + # high odd order + z, p, k = ellip(23, 1, 70, xp.asarray(0.5), 'high', output='zpk') + z2 = [9.999999999998661e-01, + 6.603717261750994e-01 + 7.509388678638675e-01j, + 6.603717261750994e-01 - 7.509388678638675e-01j, + 2.788635267510325e-01 + 9.603307416968041e-01j, + 2.788635267510325e-01 - 9.603307416968041e-01j, + 1.070215532544218e-01 + 9.942567008268131e-01j, + 1.070215532544218e-01 - 9.942567008268131e-01j, + 4.049427369978163e-02 + 9.991797705105507e-01j, + 4.049427369978163e-02 - 9.991797705105507e-01j, + 1.531059368627931e-02 + 9.998827859909265e-01j, + 1.531059368627931e-02 - 9.998827859909265e-01j, + 5.808061438534933e-03 + 9.999831330689181e-01j, + 5.808061438534933e-03 - 9.999831330689181e-01j, + 2.224277847754599e-03 + 9.999975262909676e-01j, + 2.224277847754599e-03 - 9.999975262909676e-01j, + 8.731857107534554e-04 + 9.999996187732845e-01j, + 8.731857107534554e-04 - 9.999996187732845e-01j, + 3.649057346914968e-04 + 9.999999334218996e-01j, + 3.649057346914968e-04 - 9.999999334218996e-01j, + 1.765538109802615e-04 + 9.999999844143768e-01j, + 1.765538109802615e-04 - 9.999999844143768e-01j, + 1.143655290967426e-04 + 9.999999934602630e-01j, + 1.143655290967426e-04 - 9.999999934602630e-01j] + p2 = [-6.322017026545028e-01, + -4.648423756662754e-01 + 5.852407464440732e-01j, + -4.648423756662754e-01 - 5.852407464440732e-01j, + -2.249233374627773e-01 + 8.577853017985717e-01j, + -2.249233374627773e-01 - 8.577853017985717e-01j, + -9.234137570557621e-02 + 9.506548198678851e-01j, + -9.234137570557621e-02 - 9.506548198678851e-01j, + -3.585663561241373e-02 + 9.821494736043981e-01j, + -3.585663561241373e-02 - 9.821494736043981e-01j, + -1.363917242312723e-02 + 9.933844128330656e-01j, + -1.363917242312723e-02 - 9.933844128330656e-01j, + -5.131505238923029e-03 + 9.975221173308673e-01j, + -5.131505238923029e-03 - 9.975221173308673e-01j, + -1.904937999259502e-03 + 9.990680819857982e-01j, + -1.904937999259502e-03 - 9.990680819857982e-01j, + -6.859439885466834e-04 + 9.996492201426826e-01j, + -6.859439885466834e-04 - 9.996492201426826e-01j, + -2.269936267937089e-04 + 9.998686250679161e-01j, + -2.269936267937089e-04 - 9.998686250679161e-01j, + -5.687071588789117e-05 + 9.999527573294513e-01j, + -5.687071588789117e-05 - 9.999527573294513e-01j, + -6.948417068525226e-07 + 9.999882737700173e-01j, + -6.948417068525226e-07 - 9.999882737700173e-01j] + z2 = xp.asarray(z2, dtype=xp.complex128) + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 1.220910020289434e-02 + xp_assert_close(_sort_cmplx(z, xp=xp), + _sort_cmplx(z2, xp=xp), rtol=1e-4) + xp_assert_close(_sort_cmplx(p, xp=xp), + _sort_cmplx(p2, xp=xp), rtol=1e-4) + assert math.isclose(k, k2, rel_tol=1e-3) + + def test_bandpass(self, xp): + z, p, k = ellip(7, 1, 40, [0.07, 0.2], 'pass', output='zpk') + z2 = [-9.999999999999991e-01, + 6.856610961780020e-01 + 7.279209168501619e-01j, + 6.856610961780020e-01 - 7.279209168501619e-01j, + 7.850346167691289e-01 + 6.194518952058737e-01j, + 7.850346167691289e-01 - 6.194518952058737e-01j, + 7.999038743173071e-01 + 6.001281461922627e-01j, + 7.999038743173071e-01 - 6.001281461922627e-01j, + 9.999999999999999e-01, + 9.862938983554124e-01 + 1.649980183725925e-01j, + 9.862938983554124e-01 - 1.649980183725925e-01j, + 9.788558330548762e-01 + 2.045513580850601e-01j, + 9.788558330548762e-01 - 2.045513580850601e-01j, + 9.771155231720003e-01 + 2.127093189691258e-01j, + 9.771155231720003e-01 - 2.127093189691258e-01j] + p2 = [8.063992755498643e-01 + 5.858071374778874e-01j, + 8.063992755498643e-01 - 5.858071374778874e-01j, + 8.050395347071724e-01 + 5.639097428109795e-01j, + 8.050395347071724e-01 - 5.639097428109795e-01j, + 8.113124936559144e-01 + 4.855241143973142e-01j, + 8.113124936559144e-01 - 4.855241143973142e-01j, + 8.665595314082394e-01 + 3.334049560919331e-01j, + 8.665595314082394e-01 - 3.334049560919331e-01j, + 9.412369011968871e-01 + 2.457616651325908e-01j, + 9.412369011968871e-01 - 2.457616651325908e-01j, + 9.679465190411238e-01 + 2.228772501848216e-01j, + 9.679465190411238e-01 - 2.228772501848216e-01j, + 9.747235066273385e-01 + 2.178937926146544e-01j, + 9.747235066273385e-01 - 2.178937926146544e-01j] + z2 = xp.asarray(z2, dtype=xp.complex128) + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 8.354782670263239e-03 + xp_assert_close(_sort_cmplx(z, xp=xp), + _sort_cmplx(z2, xp=xp), rtol=1e-4) + xp_assert_close(_sort_cmplx(p, xp=xp), + _sort_cmplx(p2, xp=xp), rtol=1e-4) + assert math.isclose(k, k2, rel_tol=1e-3) + + z, p, k = ellip(5, 1, 75, [90.5, 110.5], 'pass', True, 'zpk') + z2 = [-5.583607317695175e-14 + 1.433755965989225e+02j, + -5.583607317695175e-14 - 1.433755965989225e+02j, + 5.740106416459296e-14 + 1.261678754570291e+02j, + 5.740106416459296e-14 - 1.261678754570291e+02j, + -2.199676239638652e-14 + 6.974861996895196e+01j, + -2.199676239638652e-14 - 6.974861996895196e+01j, + -3.372595657044283e-14 + 7.926145989044531e+01j, + -3.372595657044283e-14 - 7.926145989044531e+01j, + 0] + p2 = [-8.814960004852743e-01 + 1.104124501436066e+02j, + -8.814960004852743e-01 - 1.104124501436066e+02j, + -2.477372459140184e+00 + 1.065638954516534e+02j, + -2.477372459140184e+00 - 1.065638954516534e+02j, + -3.072156842945799e+00 + 9.995404870405324e+01j, + -3.072156842945799e+00 - 9.995404870405324e+01j, + -2.180456023925693e+00 + 9.379206865455268e+01j, + -2.180456023925693e+00 - 9.379206865455268e+01j, + -7.230484977485752e-01 + 9.056598800801140e+01j, + -7.230484977485752e-01 - 9.056598800801140e+01j] + z2 = xp.asarray(z2, dtype=xp.complex128) + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 3.774571622827070e-02 + xp_assert_close(_sort_cmplx(z, xp=xp), + _sort_cmplx(z2, xp=xp), rtol=1e-4) + xp_assert_close(_sort_cmplx(p, xp=xp), + _sort_cmplx(p2, xp=xp), rtol=1e-6) + assert math.isclose(k, k2, rel_tol=1e-3) + + def test_bandstop(self, xp): + z, p, k = ellip(8, 1, 65, [0.2, 0.4], 'stop', output='zpk') + z2 = [3.528578094286510e-01 + 9.356769561794296e-01j, + 3.528578094286510e-01 - 9.356769561794296e-01j, + 3.769716042264783e-01 + 9.262248159096587e-01j, + 3.769716042264783e-01 - 9.262248159096587e-01j, + 4.406101783111199e-01 + 8.976985411420985e-01j, + 4.406101783111199e-01 - 8.976985411420985e-01j, + 5.539386470258847e-01 + 8.325574907062760e-01j, + 5.539386470258847e-01 - 8.325574907062760e-01j, + 6.748464963023645e-01 + 7.379581332490555e-01j, + 6.748464963023645e-01 - 7.379581332490555e-01j, + 7.489887970285254e-01 + 6.625826604475596e-01j, + 7.489887970285254e-01 - 6.625826604475596e-01j, + 7.913118471618432e-01 + 6.114127579150699e-01j, + 7.913118471618432e-01 - 6.114127579150699e-01j, + 7.806804740916381e-01 + 6.249303940216475e-01j, + 7.806804740916381e-01 - 6.249303940216475e-01j] + + p2 = [-1.025299146693730e-01 + 5.662682444754943e-01j, + -1.025299146693730e-01 - 5.662682444754943e-01j, + 1.698463595163031e-01 + 8.926678667070186e-01j, + 1.698463595163031e-01 - 8.926678667070186e-01j, + 2.750532687820631e-01 + 9.351020170094005e-01j, + 2.750532687820631e-01 - 9.351020170094005e-01j, + 3.070095178909486e-01 + 9.457373499553291e-01j, + 3.070095178909486e-01 - 9.457373499553291e-01j, + 7.695332312152288e-01 + 2.792567212705257e-01j, + 7.695332312152288e-01 - 2.792567212705257e-01j, + 8.083818999225620e-01 + 4.990723496863960e-01j, + 8.083818999225620e-01 - 4.990723496863960e-01j, + 8.066158014414928e-01 + 5.649811440393374e-01j, + 8.066158014414928e-01 - 5.649811440393374e-01j, + 8.062787978834571e-01 + 5.855780880424964e-01j, + 8.062787978834571e-01 - 5.855780880424964e-01j] + z2 = xp.asarray(z2, dtype=xp.complex128) + p2 = xp.asarray(p2, dtype=xp.complex128) + k2 = 2.068622545291259e-01 + xp_assert_close(_sort_cmplx(z, xp=xp), + _sort_cmplx(z2, xp=xp), rtol=1e-6) + xp_assert_close(_sort_cmplx(p, xp=xp), + _sort_cmplx(p2, xp=xp), rtol=1e-5) + assert math.isclose(k, k2, rel_tol=1e-5) + + @xfail_xp_backends("cupy", reason="inaccurate on CuPy") + def test_ba_output(self, xp): + # with transfer function conversion, without digital conversion + b, a = ellip(5, 1, 40, xp.asarray([201, 240]), 'stop', True) + b2 = [ + 1.000000000000000e+00, 0, # Matlab: 1.743506051190569e-13, + 2.426561778314366e+05, 0, # Matlab: 3.459426536825722e-08, + 2.348218683400168e+10, 0, # Matlab: 2.559179747299313e-03, + 1.132780692872241e+15, 0, # Matlab: 8.363229375535731e+01, + 2.724038554089566e+19, 0, # Matlab: 1.018700994113120e+06, + 2.612380874940186e+23 + ] + a2 = [ + 1.000000000000000e+00, 1.337266601804649e+02, + 2.486725353510667e+05, 2.628059713728125e+07, + 2.436169536928770e+10, 1.913554568577315e+12, + 1.175208184614438e+15, 6.115751452473410e+16, + 2.791577695211466e+19, 7.241811142725384e+20, + 2.612380874940182e+23 + ] + b2 = xp.asarray(b2, dtype=xp.float64) + a2 = xp.asarray(a2, dtype=xp.float64) + xp_assert_close(b, b2, rtol=1e-6) + xp_assert_close(a, a2, rtol=1e-4) + + def test_fs_param(self): + for fs in (900, 900.1, 1234.567): + for N in (0, 1, 2, 3, 10): + for fc in (100, 100.1, 432.12345): + for btype in ('lp', 'hp'): + ba1 = ellip(N, 1, 20, fc, btype, fs=fs) + ba2 = ellip(N, 1, 20, fc/(fs/2), btype) + for ba1_, ba2_ in zip(ba1, ba2): + xp_assert_close(ba1_, ba2_) + for fc in ((100, 200), (100.1, 200.2), (321.123, 432.123)): + for btype in ('bp', 'bs'): + ba1 = ellip(N, 1, 20, fc, btype, fs=fs) + for seq in (list, tuple, array): + fcnorm = seq([f/(fs/2) for f in fc]) + ba2 = ellip(N, 1, 20, fcnorm, btype) + for ba1_, ba2_ in zip(ba1, ba2): + xp_assert_close(ba1_, ba2_) + + def test_fs_validation(self): + with pytest.raises(ValueError, match="Sampling.*single scalar"): + iirnotch(0.06, 30, fs=np.array([10, 20])) + + with pytest.raises(ValueError, match="Sampling.*be none"): + iirnotch(0.06, 30, fs=None) + + +def test_sos_consistency(): + # Consistency checks of output='sos' for the specialized IIR filter + # design functions. + design_funcs = [(bessel, (0.1,)), + (butter, (0.1,)), + (cheby1, (45.0, 0.1)), + (cheby2, (0.087, 0.1)), + (ellip, (0.087, 45, 0.1))] + for func, args in design_funcs: + name = func.__name__ + + b, a = func(2, *args, output='ba') + sos = func(2, *args, output='sos') + xp_assert_close(sos, [np.hstack((b, a))], err_msg=f"{name}(2,...)") + + zpk = func(3, *args, output='zpk') + sos = func(3, *args, output='sos') + xp_assert_close(sos, zpk2sos(*zpk), err_msg=f"{name}(3,...)") + + zpk = func(4, *args, output='zpk') + sos = func(4, *args, output='sos') + xp_assert_close(sos, zpk2sos(*zpk), err_msg=f"{name}(4,...)") + + +@make_xp_test_case(iirnotch) +class TestIIRNotch: + + def test_ba_output(self, xp): + # Compare coefficients with Matlab ones + # for the equivalent input: + b, a = iirnotch(0.06, 30, xp=xp) + b2 = xp.asarray([ + 9.9686824e-01, -1.9584219e+00, + 9.9686824e-01 + ]) + a2 = xp.asarray([ + 1.0000000e+00, -1.9584219e+00, + 9.9373647e-01 + ]) + + xp_assert_close(b, b2, rtol=1e-8) + xp_assert_close(a, a2, rtol=1e-8) + + @pytest.mark.xfail(DEFAULT_F32, reason="wrong answer with torch/float32") + @skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") + def test_frequency_response(self, xp): + # Get filter coefficients + b, a = iirnotch(0.3, 30, xp=xp) + + # Get frequency response + w, h = freqz(b, a, 1000) + + # Pick 5 point + p = [200, # w0 = 0.200 + 295, # w0 = 0.295 + 300, # w0 = 0.300 + 305, # w0 = 0.305 + 400] # w0 = 0.400 + + # Get frequency response correspondent to each of those points + hp = h[xp.asarray(p)] + + # Check if the frequency response fulfill the specifications: + # hp[0] and hp[4] correspond to frequencies distant from + # w0 = 0.3 and should be close to 1 + assert math.isclose(xp.abs(hp[0]), 1., rel_tol=1e-2) + assert math.isclose(xp.abs(hp[4]), 1., rel_tol=1e-2) + + # hp[1] and hp[3] correspond to frequencies approximately + # on the edges of the passband and should be close to -3dB + assert math.isclose(xp.abs(hp[1]), 1 / math.sqrt(2), rel_tol=1e-2) + assert math.isclose(xp.abs(hp[3]), 1 / math.sqrt(2), rel_tol=1e-2) + + # hp[2] correspond to the frequency that should be removed + # the frequency response should be very close to 0 + assert math.isclose(xp.abs(hp[2]), 0.0, abs_tol=1e-10) + + def test_errors(self): + # Exception should be raised if w0 > 1 or w0 <0 + assert_raises(ValueError, iirnotch, w0=2, Q=30) + assert_raises(ValueError, iirnotch, w0=-1, Q=30) + + # Exception should be raised if any of the parameters + # are not float (or cannot be converted to one) + assert_raises(ValueError, iirnotch, w0="blabla", Q=30) + assert_raises(TypeError, iirnotch, w0=-1, Q=[1, 2, 3]) + + @pytest.mark.xfail(DEFAULT_F32, reason="wrong answer with torch/float32") + @skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") + def test_fs_param(self, xp): + # Get filter coefficients + b, a = iirnotch(1500, 30, fs=10000, xp=xp) + + # Get frequency response + w, h = freqz(b, a, 1000, fs=10000) + + # Pick 5 point + p = [200, # w0 = 1000 + 295, # w0 = 1475 + 300, # w0 = 1500 + 305, # w0 = 1525 + 400] # w0 = 2000 + + # Get frequency response correspondent to each of those points + hp = h[xp.asarray(p)] + + # Check if the frequency response fulfill the specifications: + # hp[0] and hp[4] correspond to frequencies distant from + # w0 = 1500 and should be close to 1 + assert math.isclose(xp.abs(hp[0]), 1.0, rel_tol=1e-2) + assert math.isclose(xp.abs(hp[4]), 1.0, rel_tol=1e-2) + + # hp[1] and hp[3] correspond to frequencies approximately + # on the edges of the passband and should be close to -3dB + assert math.isclose(xp.abs(hp[1]), 1 / math.sqrt(2), rel_tol=1e-2) + assert math.isclose(xp.abs(hp[3]), 1 / math.sqrt(2), rel_tol=1e-2) + + # hp[2] correspond to the frequency that should be removed + # the frequency response should be very close to 0 + assert math.isclose(xp.abs(hp[2]), 0.0, abs_tol=1e-10) + + +@make_xp_test_case(iirpeak) +class TestIIRPeak: + + def test_ba_output(self, xp): + # Compare coefficients with Matlab ones + # for the equivalent input: + b, a = iirpeak(0.06, 30, xp=xp) + b2 = xp.asarray([ + 3.131764229e-03, 0, + -3.131764229e-03 + ]) + a2 = xp.asarray([ + 1.0000000e+00, -1.958421917e+00, + 9.9373647e-01 + ]) + xp_assert_close(b, b2, rtol=1e-8) + xp_assert_close(a, a2, rtol=1e-8) + + @pytest.mark.xfail(DEFAULT_F32, reason="wrong answer with torch/float32") + @skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") + def test_frequency_response(self, xp): + # Get filter coefficients + b, a = iirpeak(0.3, 30, xp=xp) + + # Get frequency response + w, h = freqz(b, a, 1000) + + # Pick 5 point + p = [30, # w0 = 0.030 + 295, # w0 = 0.295 + 300, # w0 = 0.300 + 305, # w0 = 0.305 + 800] # w0 = 0.800 + + # Get frequency response correspondent to each of those points + hp = h[xp.asarray(p)] + + # Check if the frequency response fulfill the specifications: + # hp[0] and hp[4] correspond to frequencies distant from + # w0 = 0.3 and should be close to 0 + assert math.isclose(xp.abs(hp[0]), 0., abs_tol=1e-2) + assert math.isclose(xp.abs(hp[4]), 0., abs_tol=1e-2) + + # hp[1] and hp[3] correspond to frequencies approximately + # on the edges of the passband and should be close to 10**(-3/20) + assert math.isclose(xp.abs(hp[1]), 1 / math.sqrt(2), rel_tol=1e-2) + assert math.isclose(xp.abs(hp[3]), 1 / math.sqrt(2), rel_tol=1e-2) + + # hp[2] correspond to the frequency that should be retained and + # the frequency response should be very close to 1 + assert math.isclose(xp.abs(hp[2]), 1.0, rel_tol=1e-10) + + @skip_xp_backends(np_only=True) + def test_errors(self): + # Exception should be raised if w0 > 1 or w0 <0 + assert_raises(ValueError, iirpeak, w0=2, Q=30) + assert_raises(ValueError, iirpeak, w0=-1, Q=30) + + # Exception should be raised if any of the parameters + # are not float (or cannot be converted to one) + assert_raises(ValueError, iirpeak, w0="blabla", Q=30) + assert_raises(TypeError, iirpeak, w0=-1, Q=[1, 2, 3]) + + @pytest.mark.xfail(DEFAULT_F32, reason="wrong answer with torch/float32") + @skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") + def test_fs_param(self, xp): + # Get filter coefficients + b, a = iirpeak(1200, 30, fs=8000, xp=xp) + + # Get frequency response + w, h = freqz(b, a, 1000, fs=8000) + + # Pick 5 point + p = [30, # w0 = 120 + 295, # w0 = 1180 + 300, # w0 = 1200 + 305, # w0 = 1220 + 800] # w0 = 3200 + + # Get frequency response correspondent to each of those points + hp = h[xp.asarray(p)] + + # Check if the frequency response fulfill the specifications: + # hp[0] and hp[4] correspond to frequencies distant from + # w0 = 1200 and should be close to 0 + assert math.isclose(abs(hp[0]), 0.0, abs_tol=1e-2) + assert math.isclose(abs(hp[4]), 0.0, abs_tol=1e-2) + + # hp[1] and hp[3] correspond to frequencies approximately + # on the edges of the passband and should be close to 10**(-3/20) + assert math.isclose(abs(hp[1]), 1 / math.sqrt(2), rel_tol=1e-2) + assert math.isclose(abs(hp[3]), 1 / math.sqrt(2), rel_tol=1e-2) + + # hp[2] correspond to the frequency that should be retained and + # the frequency response should be very close to 1 + assert math.isclose(abs(hp[2]), 1.0, rel_tol=1e-10) + + +@pytest.mark.xfail(DEFAULT_F32, reason="wrong answers with torch/float32") +@skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") +@make_xp_test_case(iircomb) +class TestIIRComb: + # Test erroneous input cases + @skip_xp_backends(np_only=True) + def test_invalid_input(self): + # w0 is <= 0 or >= fs / 2 + fs = 1000 + for args in [(-fs, 30), (0, 35), (fs / 2, 40), (fs, 35)]: + with pytest.raises(ValueError, match='w0 must be between '): + iircomb(*args, fs=fs) + + # fs is not divisible by w0 + for args in [(120, 30), (157, 35)]: + with pytest.raises(ValueError, match='fs must be divisible '): + iircomb(*args, fs=fs) + + # https://github.com/scipy/scipy/issues/14043#issuecomment-1107349140 + # Previously, fs=44100, w0=49.999 was rejected, but fs=2, + # w0=49.999/int(44100/2) was accepted. Now it is rejected, too. + with pytest.raises(ValueError, match='fs must be divisible '): + iircomb(w0=49.999/int(44100/2), Q=30) + + with pytest.raises(ValueError, match='fs must be divisible '): + iircomb(w0=49.999, Q=30, fs=44100) + + # Filter type is not notch or peak + for args in [(0.2, 30, 'natch'), (0.5, 35, 'comb')]: + with pytest.raises(ValueError, match='ftype must be '): + iircomb(*args) + + # Verify that the filter's frequency response contains a + # notch at the cutoff frequency + @pytest.mark.parametrize('ftype', ('notch', 'peak')) + def test_frequency_response(self, ftype, xp): + # Create a notching or peaking comb filter at 1000 Hz + b, a = iircomb(1000, 30, ftype=ftype, fs=10000, xp=xp) + + # Compute the frequency response + freqs, response = freqz(b, a, 1000, fs=10000) + + # Find the notch using argrelextrema + comb_points = argrelextrema(abs(_xp_copy_to_numpy(response)), np.less)[0] + comb_points = xp.asarray(comb_points) + + # Verify that the first notch sits at 1000 Hz + comb1 = comb_points[0] + xp_assert_close(freqs[comb1], xp.asarray(1000.), check_0d=False) + + # Verify pass_zero parameter + @pytest.mark.parametrize('ftype,pass_zero,peak,notch', + [('peak', True, 123.45, 61.725), + ('peak', False, 61.725, 123.45), + ('peak', None, 61.725, 123.45), + ('notch', None, 61.725, 123.45), + ('notch', True, 123.45, 61.725), + ('notch', False, 61.725, 123.45)]) + def test_pass_zero(self, ftype, pass_zero, peak, notch, xp): + # Create a notching or peaking comb filter + b, a = iircomb(123.45, 30, ftype=ftype, fs=1234.5, pass_zero=pass_zero, xp=xp) + + # Compute the frequency response + freqs, response = freqz(b, a, xp.asarray([peak, notch]), fs=1234.5) + + # Verify that expected notches are notches and peaks are peaks + assert xp.abs(response[0]) > 0.99 + assert xp.abs(response[1]) < 1e-10 + + # All built-in IIR filters are real, so should have perfectly + # symmetrical poles and zeros. Then ba representation (using + # numpy.poly) will be purely real instead of having negligible + # imaginary parts. + def test_iir_symmetry(self, xp): + b, a = iircomb(400, 30, fs=24000, xp=xp) + z, p, k = tf2zpk(b, a) + xp_assert_equal(_sort_cmplx(z, xp=xp), _sort_cmplx(xp.conj(z), xp=xp)) + xp_assert_equal(_sort_cmplx(p, xp=xp), _sort_cmplx(xp.conj(p), xp=xp)) + xp_assert_equal(k, xp.real(k)) + + isdtype = array_namespace(b).isdtype + assert isdtype(b.dtype, ('real floating', 'complex floating')) + assert isdtype(a.dtype, ('real floating', 'complex floating')) + + # Verify filter coefficients with MATLAB's iircomb function + def test_ba_output(self, xp): + b_notch, a_notch = iircomb(60, 35, ftype='notch', fs=600, xp=xp) + b_notch2 = [0.957020174408697, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, -0.957020174408697] + a_notch2 = [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, -0.914040348817395] + b_notch2 = xp.asarray(b_notch2) + a_notch2 = xp.asarray(a_notch2) + xp_assert_close(b_notch, b_notch2) + xp_assert_close(a_notch, a_notch2) + + b_peak, a_peak = iircomb(60, 35, ftype='peak', fs=600, xp=xp) + b_peak2 = [0.0429798255913026, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, -0.0429798255913026] + a_peak2 = [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.914040348817395] + b_peak2 = xp.asarray(b_peak2) + a_peak2 = xp.asarray(a_peak2) + xp_assert_close(b_peak, b_peak2) + xp_assert_close(a_peak, a_peak2) + + # Verify that https://github.com/scipy/scipy/issues/14043 is fixed + def test_nearest_divisor(self, xp): + # Create a notching comb filter + b, a = iircomb(50/int(44100/2), 50.0, ftype='notch', xp=xp) + + # Compute the frequency response at an upper harmonic of 50 + freqs, response = freqz(b, a, xp.asarray([22000]), fs=44100) + + # Before bug fix, this would produce N = 881, so that 22 kHz was ~0 dB. + # Now N = 882 correctly and 22 kHz should be a notch <-220 dB + assert xp.abs(response[0]) < 1e-10 + + def test_fs_validation(self): + with pytest.raises(ValueError, match="Sampling.*single scalar"): + iircomb(1000, 30, fs=np.array([10, 20])) + + with pytest.raises(ValueError, match="Sampling.*be none"): + iircomb(1000, 30, fs=None) + + +class TestIIRDesign: + + def test_exceptions(self): + with pytest.raises(ValueError, match="the same shape"): + iirdesign(0.2, [0.1, 0.3], 1, 40) + with pytest.raises(ValueError, match="the same shape"): + iirdesign(np.array([[0.3, 0.6], [0.3, 0.6]]), + np.array([[0.4, 0.5], [0.4, 0.5]]), 1, 40) + + # discrete filter with non-positive frequency + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign(0, 0.5, 1, 40) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign(-0.1, 0.5, 1, 40) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign(0.1, 0, 1, 40) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign(0.1, -0.5, 1, 40) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign([0, 0.3], [0.1, 0.5], 1, 40) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign([-0.1, 0.3], [0.1, 0.5], 1, 40) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign([0.1, 0], [0.1, 0.5], 1, 40) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign([0.1, -0.3], [0.1, 0.5], 1, 40) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign([0.1, 0.3], [0, 0.5], 1, 40) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign([0.1, 0.3], [-0.1, 0.5], 1, 40) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign([0.1, 0.3], [0.1, 0], 1, 40) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign([0.1, 0.3], [0.1, -0.5], 1, 40) + + # analog filter with negative frequency + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign(-0.1, 0.5, 1, 40, analog=True) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign(0.1, -0.5, 1, 40, analog=True) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign([-0.1, 0.3], [0.1, 0.5], 1, 40, analog=True) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign([0.1, -0.3], [0.1, 0.5], 1, 40, analog=True) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign([0.1, 0.3], [-0.1, 0.5], 1, 40, analog=True) + with pytest.raises(ValueError, match="must be greater than 0"): + iirdesign([0.1, 0.3], [0.1, -0.5], 1, 40, analog=True) + + # discrete filter with fs=None, freq > 1 + with pytest.raises(ValueError, match="must be less than 1"): + iirdesign(1, 0.5, 1, 40) + with pytest.raises(ValueError, match="must be less than 1"): + iirdesign(1.1, 0.5, 1, 40) + with pytest.raises(ValueError, match="must be less than 1"): + iirdesign(0.1, 1, 1, 40) + with pytest.raises(ValueError, match="must be less than 1"): + iirdesign(0.1, 1.5, 1, 40) + with pytest.raises(ValueError, match="must be less than 1"): + iirdesign([1, 0.3], [0.1, 0.5], 1, 40) + with pytest.raises(ValueError, match="must be less than 1"): + iirdesign([1.1, 0.3], [0.1, 0.5], 1, 40) + with pytest.raises(ValueError, match="must be less than 1"): + iirdesign([0.1, 1], [0.1, 0.5], 1, 40) + with pytest.raises(ValueError, match="must be less than 1"): + iirdesign([0.1, 1.1], [0.1, 0.5], 1, 40) + with pytest.raises(ValueError, match="must be less than 1"): + iirdesign([0.1, 0.3], [1, 0.5], 1, 40) + with pytest.raises(ValueError, match="must be less than 1"): + iirdesign([0.1, 0.3], [1.1, 0.5], 1, 40) + with pytest.raises(ValueError, match="must be less than 1"): + iirdesign([0.1, 0.3], [0.1, 1], 1, 40) + with pytest.raises(ValueError, match="must be less than 1"): + iirdesign([0.1, 0.3], [0.1, 1.5], 1, 40) + + # discrete filter with fs>2, wp, ws < fs/2 must pass + iirdesign(100, 500, 1, 40, fs=2000) + iirdesign(500, 100, 1, 40, fs=2000) + iirdesign([200, 400], [100, 500], 1, 40, fs=2000) + iirdesign([100, 500], [200, 400], 1, 40, fs=2000) + + # discrete filter with fs>2, freq > fs/2: this must raise + with pytest.raises(ValueError, match="must be less than fs/2"): + iirdesign(1000, 400, 1, 40, fs=2000) + with pytest.raises(ValueError, match="must be less than fs/2"): + iirdesign(1100, 500, 1, 40, fs=2000) + with pytest.raises(ValueError, match="must be less than fs/2"): + iirdesign(100, 1000, 1, 40, fs=2000) + with pytest.raises(ValueError, match="must be less than fs/2"): + iirdesign(100, 1100, 1, 40, fs=2000) + with pytest.raises(ValueError, match="must be less than fs/2"): + iirdesign([1000, 400], [100, 500], 1, 40, fs=2000) + with pytest.raises(ValueError, match="must be less than fs/2"): + iirdesign([1100, 400], [100, 500], 1, 40, fs=2000) + with pytest.raises(ValueError, match="must be less than fs/2"): + iirdesign([200, 1000], [100, 500], 1, 40, fs=2000) + with pytest.raises(ValueError, match="must be less than fs/2"): + iirdesign([200, 1100], [100, 500], 1, 40, fs=2000) + with pytest.raises(ValueError, match="must be less than fs/2"): + iirdesign([200, 400], [1000, 500], 1, 40, fs=2000) + with pytest.raises(ValueError, match="must be less than fs/2"): + iirdesign([200, 400], [1100, 500], 1, 40, fs=2000) + with pytest.raises(ValueError, match="must be less than fs/2"): + iirdesign([200, 400], [100, 1000], 1, 40, fs=2000) + with pytest.raises(ValueError, match="must be less than fs/2"): + iirdesign([200, 400], [100, 1100], 1, 40, fs=2000) + + with pytest.raises(ValueError, match="strictly inside stopband"): + iirdesign([0.1, 0.4], [0.5, 0.6], 1, 40) + with pytest.raises(ValueError, match="strictly inside stopband"): + iirdesign([0.5, 0.6], [0.1, 0.4], 1, 40) + with pytest.raises(ValueError, match="strictly inside stopband"): + iirdesign([0.3, 0.6], [0.4, 0.7], 1, 40) + with pytest.raises(ValueError, match="strictly inside stopband"): + iirdesign([0.4, 0.7], [0.3, 0.6], 1, 40) + + def test_fs_validation(self): + with pytest.raises(ValueError, match="Sampling.*single scalar"): + iirfilter(1, 1, btype="low", fs=np.array([10, 20])) + + +@skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") +@make_xp_test_case(iirfilter) +class TestIIRFilter: + + @pytest.mark.parametrize( + "func,ftype", + [ + make_xp_pytest_param(butter, "butter"), + make_xp_pytest_param(bessel, "bessel"), + make_xp_pytest_param(cheby1, "cheby1"), + make_xp_pytest_param(cheby2, "cheby2"), + make_xp_pytest_param(ellip, "ellip"), + ] + ) + def test_symmetry(self, func, ftype, xp): + # All built-in IIR filters are real, so should have perfectly + # symmetrical poles and zeros. Then ba representation (using + # numpy.poly) will be purely real instead of having negligible + # imaginary parts. + for N in range(1, 26): + z, p, k = iirfilter(N, xp.asarray(1.1), 1, 20, 'low', analog=True, + ftype=ftype, output='zpk') + xp_assert_close(_sort_cmplx(z, xp=xp), _sort_cmplx(xp.conj(z), xp=xp)) + xp_assert_close(_sort_cmplx(p, xp=xp), _sort_cmplx(xp.conj(p), xp=xp)) + assert complex(k).imag == 0 + + b, a = iirfilter(N, xp.asarray(1.1), 1, 20, 'low', analog=True, + ftype=ftype, output='ba') + + isdtype = array_namespace(b).isdtype + assert isdtype(b.dtype, ('real floating', 'complex floating')) + assert isdtype(a.dtype, ('real floating', 'complex floating')) + + @make_xp_test_case(bessel) + def test_int_inputs(self, xp): + # Using integer frequency arguments and large N should not produce + # numpy integers that wraparound to negative numbers + k = iirfilter(24, xp.asarray(100), btype='low', analog=True, ftype='bessel', + output='zpk')[2] + k2 = 9.999999999999989e+47 + assert math.isclose(k, k2) + # if fs is specified then the normalization of Wn to have + # 0 <= Wn <= 1 should not cause an integer overflow + # the following line should not raise an exception + iirfilter(20, xp.asarray([1000000000, 1100000000]), btype='bp', + analog=False, fs=6250000000) + + def test_invalid_wn_size(self): + # low and high have 1 Wn, band and stop have 2 Wn + assert_raises(ValueError, iirfilter, 1, [0.1, 0.9], btype='low') + assert_raises(ValueError, iirfilter, 1, [0.2, 0.5], btype='high') + assert_raises(ValueError, iirfilter, 1, 0.2, btype='bp') + assert_raises(ValueError, iirfilter, 1, 400, btype='bs', analog=True) + + def test_invalid_wn_range(self): + # For digital filters, 0 <= Wn <= 1 + assert_raises(ValueError, iirfilter, 1, 2, btype='low') + assert_raises(ValueError, iirfilter, 1, [0.5, 1], btype='band') + assert_raises(ValueError, iirfilter, 1, [0., 0.5], btype='band') + assert_raises(ValueError, iirfilter, 1, -1, btype='high') + assert_raises(ValueError, iirfilter, 1, [1, 2], btype='band') + assert_raises(ValueError, iirfilter, 1, [10, 20], btype='stop') + + # analog=True with non-positive critical frequencies + with pytest.raises(ValueError, match="must be greater than 0"): + iirfilter(2, 0, btype='low', analog=True) + with pytest.raises(ValueError, match="must be greater than 0"): + iirfilter(2, -1, btype='low', analog=True) + with pytest.raises(ValueError, match="must be greater than 0"): + iirfilter(2, [0, 100], analog=True) + with pytest.raises(ValueError, match="must be greater than 0"): + iirfilter(2, [-1, 100], analog=True) + with pytest.raises(ValueError, match="must be greater than 0"): + iirfilter(2, [10, 0], analog=True) + with pytest.raises(ValueError, match="must be greater than 0"): + iirfilter(2, [10, -1], analog=True) + + @make_xp_test_case(butter) + def test_analog_sos(self, xp): + # first order Butterworth filter with Wn = 1 has tf 1/(s+1) + sos = xp.asarray([[0., 0., 1., 0., 1., 1.]]) + sos2 = iirfilter(N=1, Wn=xp.asarray(1), btype='low', analog=True, output='sos') + assert_array_almost_equal(sos, sos2) + + def test_wn1_ge_wn0(self): + # gh-15773: should raise error if Wn[0] >= Wn[1] + with pytest.raises(ValueError, + match=r"Wn\[0\] must be less than Wn\[1\]"): + iirfilter(2, [0.5, 0.5]) + with pytest.raises(ValueError, + match=r"Wn\[0\] must be less than Wn\[1\]"): + iirfilter(2, [0.6, 0.5]) + + +@skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") +@make_xp_test_case(group_delay) +class TestGroupDelay: + def test_identity_filter(self, xp): + w, gd = group_delay((1, xp.asarray(1))) + assert_array_almost_equal(w, xp.pi * xp.arange(512, dtype=w.dtype) / 512) + assert_array_almost_equal(gd, xp.zeros(512)) + + w, gd = group_delay((1, xp.asarray(1)), whole=True) + assert_array_almost_equal(w, 2 * xp.pi * xp.arange(512, dtype=w.dtype) / 512) + assert_array_almost_equal(gd, xp.zeros(512)) + + @xfail_xp_backends("cupy", reason="slightly inaccurate") + @pytest.mark.xfail(DEFAULT_F32, reason="wrong answer with torch/float32") + def test_fir(self, xp): + # Let's design linear phase FIR and check that the group delay + # is constant. + N = 100 + b = firwin(N + 1, 0.1) + b = xp.asarray(b) + w, gd = group_delay((b, 1)) + xp_assert_close(gd, xp.ones_like(gd)*(0.5 * N), rtol=5e-7) + + @pytest.mark.xfail(DEFAULT_F32, reason="wrong answer with torch/float32") + def test_iir(self, xp): + # Let's design Butterworth filter and test the group delay at + # some points against MATLAB answer. + b, a = butter(4, 0.1) + b, a = map(xp.asarray, (b, a)) + w = xp.linspace(0, xp.pi, num=10, endpoint=False) + w, gd = group_delay((b, a), w=w) + matlab_gd = xp.asarray([8.249313898506037, 11.958947880907104, + 2.452325615326005, 1.048918665702008, + 0.611382575635897, 0.418293269460578, + 0.317932917836572, 0.261371844762525, + 0.229038045801298, 0.212185774208521]) + assert_array_almost_equal(gd, matlab_gd) + + @xfail_xp_backends("cupy", reason="does not warn") + @xfail_xp_backends("torch", reason="does not warn") + def test_singular(self, xp): + # Let's create a filter with zeros and poles on the unit circle and + # check if warnings are raised at those frequencies. + z1 = np.exp(1j * 0.1 * pi) + z2 = np.exp(1j * 0.25 * pi) + p1 = np.exp(1j * 0.5 * pi) + p2 = np.exp(1j * 0.8 * pi) + + b = np.convolve([1, -z1], [1, -z2]) + a = np.convolve([1, -p1], [1, -p2]) + b, a = map(xp.asarray, (b, a)) + + w = xp.asarray([0.1 * xp.pi, 0.25 * xp.pi, -0.5 * xp.pi, -0.8 * xp.pi]) + + with pytest.warns(UserWarning): + w, gd = group_delay((b, a), w=w) + + def test_backward_compat(self, xp): + # For backward compatibility, test if None act as a wrapper for default + w1, gd1 = group_delay((1, xp.asarray(1))) + w2, gd2 = group_delay((1, xp.asarray(1)), None) + assert_array_almost_equal(w1, w2) + assert_array_almost_equal(gd1, gd2) + + @pytest.mark.xfail(DEFAULT_F32, reason="wrong answer with torch/float32") + def test_fs_param(self, xp): + # Let's design Butterworth filter and test the group delay at + # some points against the normalized frequency answer. + b, a = butter(4, 4800, fs=96000) + b, a = map(xp.asarray, (b, a)) + w = xp.linspace(0, 96000/2, num=10, endpoint=False) + w, gd = group_delay((b, a), w=w, fs=96000) + norm_gd = xp.asarray([8.249313898506037, 11.958947880907104, + 2.452325615326005, 1.048918665702008, + 0.611382575635897, 0.418293269460578, + 0.317932917836572, 0.261371844762525, + 0.229038045801298, 0.212185774208521]) + assert_array_almost_equal(gd, norm_gd) + + @skip_xp_backends(np_only=True, reason='numpy scalars') + def test_w_or_N_types(self, xp): + # Measure at 8 equally-spaced points + for N in (8, np.int8(8), np.int16(8), np.int32(8), np.int64(8), + np.array(8)): + w, gd = group_delay((1, 1), N) + assert_array_almost_equal(w, pi * np.arange(8) / 8) + assert_array_almost_equal(gd, np.zeros(8)) + + # Measure at frequency 8 rad/sec + for w in (8.0, 8.0+0j): + w_out, gd = group_delay((1, 1), w) + assert_array_almost_equal(w_out, [8]) + assert_array_almost_equal(gd, [0]) + + @pytest.mark.xfail(DEFAULT_F32, reason="with torch/float32, the rtol is ~1e-7") + @xfail_xp_backends("cupy", reason="inaccurate") + def test_complex_coef(self, xp): + # gh-19586: handle complex coef TFs + # + # for g(z) = (alpha*z+1)/(1+conjugate(alpha)), group delay is + # given by function below. + # + # def gd_expr(w, alpha): + # num = 1j*(abs(alpha)**2-1)*np.exp(1j*w) + # den = (alpha*np.exp(1j*w)+1)*(np.exp(1j*w)+np.conj(alpha)) + # return -np.imag(num/den) + + # arbitrary non-real alpha + alpha = -0.6143077933232609 + 0.3355978770229421j + # 8 points from from -pi to pi + wref = xp.asarray([-3.141592653589793 , + -2.356194490192345 , + -1.5707963267948966, + -0.7853981633974483, + 0. , + 0.7853981633974483, + 1.5707963267948966, + 2.356194490192345 ]) + gdref = xp.asarray([0.18759548150354619, + 0.17999770352712252, + 0.23598047471879877, + 0.46539443069907194, + 1.9511492420564165 , + 3.478129975138865 , + 0.6228594960517333 , + 0.27067831839471224]) + b = xp.asarray([alpha, 1]) + a = xp.asarray([1, alpha.conjugate()]) + gdtest = group_delay((b, a), wref)[1] + # need nulp=14 for macOS arm64 wheel builds; added 2 for some + # robustness on other platforms. + xp_assert_close_nulp(gdtest, gdref, nulp=16) + + def test_fs_validation(self): + with pytest.raises(ValueError, match="Sampling.*single scalar"): + group_delay((1, 1), fs=np.array([10, 20])) + + with pytest.raises(ValueError, match="Sampling.*be none"): + group_delay((1, 1), fs=None) + + +@skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/11883") +@make_xp_test_case(gammatone) +class TestGammatone: + # Test erroneous input cases. + @skip_xp_backends(np_only=True) + def test_invalid_input(self, xp): + # Cutoff frequency is <= 0 or >= fs / 2. + fs = 16000 + for args in [(-fs, 'iir'), (0, 'fir'), (fs / 2, 'iir'), (fs, 'fir')]: + with pytest.raises(ValueError, match='The frequency must be ' + 'between '): + gammatone(*args, fs=fs) + + # Filter type is not fir or iir + for args in [(440, 'fie'), (220, 'it')]: + with pytest.raises(ValueError, match='ftype must be '): + gammatone(*args, fs=fs) + + # Order is <= 0 or > 24 for FIR filter. + for args in [(440, 'fir', -50), (220, 'fir', 0), (110, 'fir', 25), + (55, 'fir', 50)]: + with pytest.raises(ValueError, match='Invalid order: '): + gammatone(*args, numtaps=None, fs=fs) + + # Verify that the filter's frequency response is approximately + # 1 at the cutoff frequency. + @pytest.mark.xfail(DEFAULT_F32, reason="wrong answer with torch/float32") + @xfail_xp_backends("cupy", reason="inaccurate") + def test_frequency_response(self, xp): + fs = 16000 + ftypes = ['fir', 'iir'] + for ftype in ftypes: + # Create a gammatone filter centered at 1000 Hz. + b, a = gammatone(1000, ftype, fs=fs, xp=xp) + + # Calculate the frequency response. + freqs, response = freqz(_xp_copy_to_numpy(b), _xp_copy_to_numpy(a)) + + # Determine peak magnitude of the response + # and corresponding frequency. + response_max = np.max(np.abs(response)) + freq_hz = freqs[np.argmax(np.abs(response))] / ((2 * np.pi) / fs) + response_max, freq_hz = map(xp.asarray, (response_max, freq_hz)) + + # Check that the peak magnitude is 1 and the frequency is 1000 Hz. + xp_assert_close(response_max, + xp.ones_like(response_max), rtol=1e-2, check_0d=False) + xp_assert_close(freq_hz, + 1000*xp.ones_like(freq_hz), rtol=1e-2, check_0d=False) + + # All built-in IIR filters are real, so should have perfectly + # symmetrical poles and zeros. Then ba representation (using + # numpy.poly) will be purely real instead of having negligible + # imaginary parts. + def test_iir_symmetry(self, xp): + b, a = gammatone(440, 'iir', fs=24000, xp=xp) + z, p, k = tf2zpk(_xp_copy_to_numpy(b), _xp_copy_to_numpy(a)) + z, p, k = map(xp.asarray, (z, p, k)) + xp_assert_equal(_sort_cmplx(z, xp=xp), _sort_cmplx(xp.conj(z), xp=xp)) + xp_assert_equal(_sort_cmplx(p, xp=xp), _sort_cmplx(xp.conj(p), xp=xp)) + xp_assert_equal(k, xp.real(k)) + + isdtype = array_namespace(b).isdtype + assert isdtype(b.dtype, ('real floating', 'complex floating')) + assert isdtype(a.dtype, ('real floating', 'complex floating')) + + # Verify FIR filter coefficients with the paper's + # Mathematica implementation + def test_fir_ba_output(self, xp): + b, _ = gammatone(15, 'fir', fs=1000, xp=xp) + b2 = [0.0, 2.2608075649884e-04, + 1.5077903981357e-03, 4.2033687753998e-03, + 8.1508962726503e-03, 1.2890059089154e-02, + 1.7833890391666e-02, 2.2392613558564e-02, + 2.6055195863104e-02, 2.8435872863284e-02, + 2.9293319149544e-02, 2.852976858014e-02, + 2.6176557156294e-02, 2.2371510270395e-02, + 1.7332485267759e-02] + b2 = xp.asarray(b2) + xp_assert_close(b, b2) + + # Verify IIR filter coefficients with the paper's MATLAB implementation + def test_iir_ba_output(self, xp): + b, a = gammatone(440, 'iir', fs=16000, xp=xp) + b2 = [1.31494461367464e-06, -5.03391196645395e-06, + 7.00649426000897e-06, -4.18951968419854e-06, + 9.02614910412011e-07] + a2 = [1.0, -7.65646235454218, + 25.7584699322366, -49.7319214483238, + 60.2667361289181, -46.9399590980486, + 22.9474798808461, -6.43799381299034, + 0.793651554625368] + b2, a2 = map(xp.asarray, (b2, a2)) + xp_assert_close(b, b2, atol=1e-10, rtol=5e-5) + xp_assert_close(a, a2, atol=1e-10, rtol=5e-5) + + def test_fs_validation(self): + with pytest.raises(ValueError, match="Sampling.*single scalar"): + gammatone(440, 'iir', fs=np.asarray([10, 20])) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_fir_filter_design.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_fir_filter_design.py new file mode 100644 index 0000000000000000000000000000000000000000..293361b6526b148ff3ec072d1d4e28e49ae07436 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_fir_filter_design.py @@ -0,0 +1,868 @@ +import math +import numpy as np + +from pytest import raises as assert_raises, warns as assert_warns +import pytest + +import scipy._lib.array_api_extra as xpx +import scipy.signal as signal +from scipy._lib._array_api import ( + xp_assert_close, xp_assert_equal, assert_almost_equal, assert_array_almost_equal, + array_namespace, xp_default_dtype, make_xp_test_case, _xp_copy_to_numpy +) +from scipy.fft import fft, fft2 +from scipy.signal import (kaiser_beta, kaiser_atten, kaiserord, + firwin, firwin2, freqz, remez, firls, minimum_phase, convolve2d, firwin_2d +) + +skip_xp_backends = pytest.mark.skip_xp_backends +xfail_xp_backends = pytest.mark.xfail_xp_backends + +lazy_xp_modules = [signal] + + +def test_kaiser_beta(): + b = kaiser_beta(58.7) + assert_almost_equal(b, 0.1102 * 50.0) + b = kaiser_beta(22.0) + assert_almost_equal(b, 0.5842 + 0.07886) + b = kaiser_beta(21.0) + assert b == 0.0 + b = kaiser_beta(10.0) + assert b == 0.0 + + +def test_kaiser_atten(): + a = kaiser_atten(1, 1.0) + assert a == 7.95 + a = kaiser_atten(2, 1/np.pi) + assert a == 2.285 + 7.95 + + +def test_kaiserord(): + assert_raises(ValueError, kaiserord, 1.0, 1.0) + numtaps, beta = kaiserord(2.285 + 7.95 - 0.001, 1/np.pi) + assert (numtaps, beta) == (2, 0.0) + + +@make_xp_test_case(firwin) +class TestFirwin: + + def check_response(self, h, expected_response, tol=.05): + xp = array_namespace(h) + N = h.shape[0] + alpha = 0.5 * (N-1) + m = xp.arange(0, N, dtype=xp_default_dtype(xp)) - alpha # time indices of taps + for freq, expected in expected_response: + actual = abs(xp.sum(h * xp.exp(-1j * xp.pi * m * freq))) + mse = abs(actual - expected)**2 + assert mse < tol, f'response not as expected, mse={mse:g} > {tol:g}' + + def test_response(self, xp): + N = 51 + f = xp.asarray(.5) + + # increase length just to try even/odd + h = firwin(N, f) # low-pass from 0 to f + self.check_response(h, [(.25,1), (.75,0)]) + + h = firwin(N+1, f, window='nuttall') # specific window + self.check_response(h, [(.25,1), (.75,0)]) + + h = firwin(N+2, f, pass_zero=False) # stop from 0 to f --> high-pass + self.check_response(h, [(.25,0), (.75,1)]) + + f1, f2, f3, f4 = .2, .4, .6, .8 + h = firwin(N+3, [f1, f2], pass_zero=False) # band-pass filter + self.check_response(h, [(.1,0), (.3,1), (.5,0)]) + + h = firwin(N+4, [f1, f2]) # band-stop filter + self.check_response(h, [(.1,1), (.3,0), (.5,1)]) + + h = firwin(N+5, [f1, f2, f3, f4], pass_zero=False, scale=False) + self.check_response(h, [(.1,0), (.3,1), (.5,0), (.7,1), (.9,0)]) + + h = firwin(N+6, [f1, f2, f3, f4]) # multiband filter + self.check_response(h, [(.1,1), (.3,0), (.5,1), (.7,0), (.9,1)]) + + h = firwin(N+7, 0.1, width=.03) # low-pass + self.check_response(h, [(.05,1), (.75,0)]) + + h = firwin(N+8, 0.1, pass_zero=False) # high-pass + self.check_response(h, [(.05,0), (.75,1)]) + + def mse(self, h, bands): + """Compute mean squared error versus ideal response across frequency + band. + h -- coefficients + bands -- list of (left, right) tuples relative to 1==Nyquist of + passbands + """ + xp = array_namespace(h) + h_np = _xp_copy_to_numpy(h) + w, H = freqz(h_np, worN=1024) + w, H = map(xp.asarray, (w, H)) + f = w/xp.pi + passIndicator = xp.zeros(w.shape[0], dtype=xp.bool) + for left, right in bands: + passIndicator |= (f >= left) & (f < right) + Hideal = xp.where(passIndicator, xp.ones_like(passIndicator), + xp.zeros_like(passIndicator)) + Hideal = xp.astype(Hideal, H.dtype) + mse = xp.mean(abs(abs(H)-Hideal)**2) + return mse + + @pytest.mark.parametrize( + "cutoff,pass_zero,expected_response", + [ + ([0.5], True, (0, 1)), + ([0.2, .6], False, (.4, 1)), + ([.5], False, (1, 1)), + ] + ) + def test_scaling(self, cutoff, pass_zero, expected_response, xp): + """ + For one lowpass, bandpass, and highpass example filter, this test + checks two things: + - the mean squared error over the frequency domain of the unscaled + filter is smaller than the scaled filter (true for rectangular + window) + - the response of the scaled filter is exactly unity at the center + of the first passband + """ + N = 11 + cutoff = xp.asarray(cutoff) + h = firwin(N, cutoff, scale=False, pass_zero=pass_zero, window='ones') + hs = firwin(N, cutoff, scale=True, pass_zero=pass_zero, window='ones') + if cutoff.shape[0] == 1: + if pass_zero: + cutoff = xp.concat([xp.asarray([0], dtype=cutoff.dtype), cutoff]) + else: + cutoff = xp.concat([cutoff, xp.asarray([1], dtype=cutoff.dtype)]) + msg = 'least squares violation' + assert self.mse(h, [cutoff]) < self.mse(hs, [cutoff]), msg + self.check_response(hs, [expected_response], 1e-12) + + def test_fs_validation(self): + with pytest.raises(ValueError, match="Sampling.*single scalar"): + firwin(51, .5, fs=np.array([10, 20])) + + +@make_xp_test_case(firwin) +class TestFirWinMore: + """Different author, different style, different tests...""" + + def test_lowpass(self, xp): + width = 0.04 + ntaps, beta = kaiserord(120, width) + cutoff = xp.asarray(0.5) + kwargs = dict(cutoff=cutoff, window=('kaiser', beta), scale=False) + taps = firwin(ntaps, **kwargs) + + # Check the symmetry of taps. + assert_array_almost_equal(taps[:ntaps//2], xp.flip(taps)[:ntaps//2]) + + # Check the gain at a few samples where + # we know it should be approximately 0 or 1. + freq_samples = xp.asarray([0.0, 0.25, 0.5-width/2, 0.5+width/2, 0.75, 1.0]) + freq_samples = _xp_copy_to_numpy(freq_samples) + freqs, response = freqz(_xp_copy_to_numpy(taps), worN=np.pi*freq_samples) + + assert_array_almost_equal( + xp.abs(xp.asarray(response)), + xp.asarray([1.0, 1.0, 1.0, 0.0, 0.0, 0.0]), decimal=5 + ) + + taps_str = firwin(ntaps, pass_zero='lowpass', **kwargs) + xp_assert_close(taps, taps_str) + + def test_highpass(self, xp): + width = 0.04 + ntaps, beta = kaiserord(120, width) + + # Ensure that ntaps is odd. + ntaps |= 1 + + cutoff = xp.asarray(0.5) + kwargs = dict(cutoff=cutoff, window=('kaiser', beta), scale=False) + taps = firwin(ntaps, pass_zero=False, **kwargs) + + # Check the symmetry of taps. + assert_array_almost_equal(taps[:ntaps//2], xp.flip(taps)[:ntaps//2]) + + # Check the gain at a few samples where + # we know it should be approximately 0 or 1. + freq_samples = xp.asarray([0.0, 0.25, 0.5 - width/2, 0.5 + width/2, 0.75, 1.0]) + freq_samples = _xp_copy_to_numpy(freq_samples) + freqs, response = freqz(_xp_copy_to_numpy(taps), worN=np.pi*freq_samples) + + assert_array_almost_equal(xp.abs(xp.asarray(response)), + xp.asarray([0.0, 0.0, 0.0, 1.0, 1.0, 1.0]), decimal=5) + + taps_str = firwin(ntaps, pass_zero='highpass', **kwargs) + xp_assert_close(taps, taps_str) + + def test_bandpass(self, xp): + width = 0.04 + ntaps, beta = kaiserord(120, width) + kwargs = dict( + cutoff=xp.asarray([0.3, 0.7]), window=('kaiser', beta), scale=False + ) + taps = firwin(ntaps, pass_zero=False, **kwargs) + + # Check the symmetry of taps. + assert_array_almost_equal(taps[:ntaps//2], xp.flip(taps)[:ntaps//2]) + + # Check the gain at a few samples where + # we know it should be approximately 0 or 1. + freq_samples = xp.asarray([0.0, 0.2, 0.3 - width/2, 0.3 + width/2, 0.5, + 0.7 - width/2, 0.7 + width/2, 0.8, 1.0]) + freq_samples = _xp_copy_to_numpy(freq_samples) + freqs, response = freqz(_xp_copy_to_numpy(taps), worN=np.pi*freq_samples) + + assert_array_almost_equal(xp.abs(xp.asarray(response)), + xp.asarray([0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0]), decimal=5) + + taps_str = firwin(ntaps, pass_zero='bandpass', **kwargs) + xp_assert_close(taps, taps_str) + + def test_bandstop_multi(self, xp): + width = 0.04 + ntaps, beta = kaiserord(120, width) + kwargs = dict(cutoff=xp.asarray([0.2, 0.5, 0.8]), window=('kaiser', beta), + scale=False) + taps = firwin(ntaps, **kwargs) + + # Check the symmetry of taps. + assert_array_almost_equal(taps[:ntaps//2], xp.flip(taps)[:ntaps//2]) + + # Check the gain at a few samples where + # we know it should be approximately 0 or 1. + freq_samples = xp.asarray([0.0, 0.1, 0.2 - width/2, 0.2 + width/2, 0.35, + 0.5 - width/2, 0.5 + width/2, 0.65, + 0.8 - width/2, 0.8 + width/2, 0.9, 1.0]) + freq_samples = _xp_copy_to_numpy(freq_samples) + freqs, response = freqz(_xp_copy_to_numpy(taps), worN=np.pi*freq_samples) + + assert_array_almost_equal( + xp.abs(xp.asarray(response)), + xp.asarray([1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0]), + decimal=5 + ) + + taps_str = firwin(ntaps, pass_zero='bandstop', **kwargs) + xp_assert_close(taps, taps_str) + + def test_fs_nyq(self, xp): + """Test the fs and nyq keywords.""" + nyquist = 1000 + width = 40.0 + relative_width = width/nyquist + ntaps, beta = kaiserord(120, relative_width) + taps = firwin(ntaps, cutoff=xp.asarray([300, 700]), window=('kaiser', beta), + pass_zero=False, scale=False, fs=2*nyquist) + + # Check the symmetry of taps. + assert_array_almost_equal(taps[:ntaps//2], xp.flip(taps)[:ntaps//2]) + + # Check the gain at a few samples where + # we know it should be approximately 0 or 1. + freq_samples = xp.asarray([0.0, 200, 300 - width/2, 300 + width/2, 500, + 700 - width/2, 700 + width/2, 800, 1000]) + freq_samples = _xp_copy_to_numpy(freq_samples) + freqs, response = freqz( + _xp_copy_to_numpy(taps), worN=np.pi*freq_samples/nyquist + ) + + assert_array_almost_equal(xp.abs(xp.asarray(response)), + xp.asarray([0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0]), decimal=5) + + def test_array_cutoff(self, xp): + taps = firwin(3, xp.asarray([.1, .2])) + # smoke test against the value computed by scipy==1.5.2 + xp_assert_close( + taps, xp.asarray([-0.00801395, 1.0160279, -0.00801395]), atol=1e-8 + ) + + def test_bad_cutoff(self): + """Test that invalid cutoff argument raises ValueError.""" + # cutoff values must be greater than 0 and less than 1. + assert_raises(ValueError, firwin, 99, -0.5) + assert_raises(ValueError, firwin, 99, 1.5) + # Don't allow 0 or 1 in cutoff. + assert_raises(ValueError, firwin, 99, [0, 0.5]) + assert_raises(ValueError, firwin, 99, [0.5, 1]) + # cutoff values must be strictly increasing. + assert_raises(ValueError, firwin, 99, [0.1, 0.5, 0.2]) + assert_raises(ValueError, firwin, 99, [0.1, 0.5, 0.5]) + # Must have at least one cutoff value. + assert_raises(ValueError, firwin, 99, []) + # 2D array not allowed. + assert_raises(ValueError, firwin, 99, [[0.1, 0.2],[0.3, 0.4]]) + # cutoff values must be less than nyq. + assert_raises(ValueError, firwin, 99, 50.0, fs=80) + assert_raises(ValueError, firwin, 99, [10, 20, 30], fs=50) + + def test_even_highpass_raises_value_error(self): + """Test that attempt to create a highpass filter with an even number + of taps raises a ValueError exception.""" + assert_raises(ValueError, firwin, 40, 0.5, pass_zero=False) + assert_raises(ValueError, firwin, 40, [.25, 0.5]) + + def test_bad_pass_zero(self): + """Test degenerate pass_zero cases.""" + with assert_raises(ValueError, match="^Parameter pass_zero='foo' not in "): + firwin(41, 0.5, pass_zero='foo') + with assert_raises(ValueError, match="^Parameter pass_zero=1.0 not in "): + firwin(41, 0.5, pass_zero=1.) + for pass_zero in ('lowpass', 'highpass'): + with assert_raises(ValueError, match='cutoff must have one'): + firwin(41, [0.5, 0.6], pass_zero=pass_zero) + for pass_zero in ('bandpass', 'bandstop'): + with assert_raises(ValueError, match='must have at least two'): + firwin(41, [0.5], pass_zero=pass_zero) + + def test_fs_validation(self): + with pytest.raises(ValueError, match="Sampling.*single scalar"): + firwin2(51, .5, 1, fs=np.array([10, 20])) + + +@make_xp_test_case(firwin2) +class TestFirwin2: + + def test_invalid_args(self): + # `freq` and `gain` have different lengths. + with assert_raises(ValueError, match='must be of same length'): + firwin2(50, [0, 0.5, 1], [0.0, 1.0]) + # `nfreqs` is less than `ntaps`. + with assert_raises(ValueError, match='ntaps must be less than nfreqs'): + firwin2(50, [0, 0.5, 1], [0.0, 1.0, 1.0], nfreqs=33) + # Decreasing value in `freq` + with assert_raises(ValueError, match='must be nondecreasing'): + firwin2(50, [0, 0.5, 0.4, 1.0], [0, .25, .5, 1.0]) + # Value in `freq` repeated more than once. + with assert_raises(ValueError, match='must not occur more than twice'): + firwin2(50, [0, .1, .1, .1, 1.0], [0.0, 0.5, 0.75, 1.0, 1.0]) + # `freq` does not start at 0.0. + with assert_raises(ValueError, match='start with 0'): + firwin2(50, [0.5, 1.0], [0.0, 1.0]) + # `freq` does not end at fs/2. + with assert_raises(ValueError, match='end with fs/2'): + firwin2(50, [0.0, 0.5], [0.0, 1.0]) + # Value 0 is repeated in `freq` + with assert_raises(ValueError, match='0 must not be repeated'): + firwin2(50, [0.0, 0.0, 0.5, 1.0], [1.0, 1.0, 0.0, 0.0]) + # Value fs/2 is repeated in `freq` + with assert_raises(ValueError, match='fs/2 must not be repeated'): + firwin2(50, [0.0, 0.5, 1.0, 1.0], [1.0, 1.0, 0.0, 0.0]) + # Value in `freq` that is too close to a repeated number + with assert_raises(ValueError, match='cannot contain numbers ' + 'that are too close'): + firwin2(50, [0.0, 0.5 - np.finfo(float).eps * 0.5, 0.5, 0.5, 1.0], + [1.0, 1.0, 1.0, 0.0, 0.0]) + + # Type II filter, but the gain at nyquist frequency is not zero. + with assert_raises(ValueError, match='Type II filter'): + firwin2(16, [0.0, 0.5, 1.0], [0.0, 1.0, 1.0]) + + # Type III filter, but the gains at nyquist and zero rate are not zero. + with assert_raises(ValueError, match='Type III filter'): + firwin2(17, [0.0, 0.5, 1.0], [0.0, 1.0, 1.0], antisymmetric=True) + with assert_raises(ValueError, match='Type III filter'): + firwin2(17, [0.0, 0.5, 1.0], [1.0, 1.0, 0.0], antisymmetric=True) + with assert_raises(ValueError, match='Type III filter'): + firwin2(17, [0.0, 0.5, 1.0], [1.0, 1.0, 1.0], antisymmetric=True) + + # Type IV filter, but the gain at zero rate is not zero. + with assert_raises(ValueError, match='Type IV filter'): + firwin2(16, [0.0, 0.5, 1.0], [1.0, 1.0, 0.0], antisymmetric=True) + + def test01(self, xp): + width = 0.04 + beta = 12.0 + ntaps = 400 + # Filter is 1 from w=0 to w=0.5, then decreases linearly from 1 to 0 as w + # increases from w=0.5 to w=1 (w=1 is the Nyquist frequency). + freq = xp.asarray([0.0, 0.5, 1.0]) + gain = xp.asarray([1.0, 1.0, 0.0]) + taps = firwin2(ntaps, freq, gain, window=('kaiser', beta)) + freq_samples = xp.asarray([0.0, 0.25, 0.5 - width/2, 0.5 + width/2, + 0.75, 1.0 - width/2]) + freq_samples = _xp_copy_to_numpy(freq_samples) + freqs, response = freqz(_xp_copy_to_numpy(taps), worN=np.pi*freq_samples) + assert_array_almost_equal( + xp.abs(xp.asarray(response)), + xp.asarray([1.0, 1.0, 1.0, 1.0 - width, 0.5, width]), decimal=5 + ) + + @skip_xp_backends("jax.numpy", reason="immutable arrays") + def test02(self, xp): + width = 0.04 + beta = 12.0 + # ntaps must be odd for positive gain at Nyquist. + ntaps = 401 + # An ideal highpass filter. + freq = xp.asarray([0.0, 0.5, 0.5, 1.0]) + gain = xp.asarray([0.0, 0.0, 1.0, 1.0]) + taps = firwin2(ntaps, freq, gain, window=('kaiser', beta)) + freq_samples = xp.asarray([0.0, 0.25, 0.5 - width, 0.5 + width, 0.75, 1.0]) + freq_samples = _xp_copy_to_numpy(freq_samples) + freqs, response = freqz(_xp_copy_to_numpy(taps), worN=np.pi*freq_samples) + assert_array_almost_equal( + xp.abs(xp.asarray(response)), + xp.asarray([0.0, 0.0, 0.0, 1.0, 1.0, 1.0]), decimal=5 + ) + + @skip_xp_backends("jax.numpy", reason="immutable arrays") + def test03(self, xp): + width = 0.02 + ntaps, beta = kaiserord(120, width) + # ntaps must be odd for positive gain at Nyquist. + ntaps = int(ntaps) | 1 + freq = xp.asarray([0.0, 0.4, 0.4, 0.5, 0.5, 1.0]) + gain = xp.asarray([1.0, 1.0, 0.0, 0.0, 1.0, 1.0]) + taps = firwin2(ntaps, freq, gain, window=('kaiser', beta)) + freq_samples = np.array([0.0, 0.4 - width, 0.4 + width, 0.45, + 0.5 - width, 0.5 + width, 0.75, 1.0]) + freqs, response = freqz(_xp_copy_to_numpy(taps), worN=np.pi*freq_samples) + assert_array_almost_equal( + xp.abs(xp.asarray(response)), + xp.asarray([1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0]), decimal=5 + ) + + @skip_xp_backends("jax.numpy", reason="immutable arrays") + def test04(self, xp): + """Test firwin2 when window=None.""" + ntaps = 5 + # Ideal lowpass: gain is 1 on [0,0.5], and 0 on [0.5, 1.0] + freq = xp.asarray([0.0, 0.5, 0.5, 1.0]) + gain = xp.asarray([1.0, 1.0, 0.0, 0.0]) + + taps = firwin2(ntaps, freq, gain, window=None, nfreqs=8193) + alpha = 0.5 * (ntaps - 1) + m = xp.arange(0, ntaps, dtype=freq.dtype) - alpha + h = 0.5 * xpx.sinc(0.5 * m) + assert_array_almost_equal(h, taps) + + def test05(self, xp): + """Test firwin2 for calculating Type IV filters""" + ntaps = 1500 + + freq = xp.asarray([0.0, 1.0]) + gain = xp.asarray([0.0, 1.0]) + taps = firwin2(ntaps, freq, gain, window=None, antisymmetric=True) + + flip = array_namespace(freq).flip + dec = {'decimal': 4.5} if xp_default_dtype(xp) == xp.float32 else {} + assert_array_almost_equal(taps[: ntaps // 2], flip(-taps[ntaps // 2:]), **dec) + + freqs, response = freqz(_xp_copy_to_numpy(taps), worN=2048) + freqs, response = map(xp.asarray, (freqs, response)) + assert_array_almost_equal(xp.abs(response), freqs / xp.pi, decimal=4) + + @skip_xp_backends("jax.numpy", reason="immutable arrays") + def test06(self, xp): + """Test firwin2 for calculating Type III filters""" + ntaps = 1501 + + freq = xp.asarray([0.0, 0.5, 0.55, 1.0]) + gain = xp.asarray([0.0, 0.5, 0.0, 0.0]) + taps = firwin2(ntaps, freq, gain, window=None, antisymmetric=True) + assert taps[ntaps // 2] == 0.0 + + flip = array_namespace(freq).flip + dec = {'decimal': 4.5} if xp_default_dtype(xp) == xp.float32 else {} + assert_array_almost_equal(taps[: ntaps // 2], + flip(-taps[ntaps // 2 + 1:]), **dec + ) + + freqs, response1 = freqz(_xp_copy_to_numpy(taps), worN=2048) + response2 = xp.asarray( + np.interp(freqs / np.pi, _xp_copy_to_numpy(freq), _xp_copy_to_numpy(gain)) + ) + assert_array_almost_equal(xp.abs(xp.asarray(response1)), response2, decimal=3) + + def test_fs_nyq(self, xp): + taps1 = firwin2(80, xp.asarray([0.0, 0.5, 1.0]), xp.asarray([1.0, 1.0, 0.0])) + taps2 = firwin2(80, xp.asarray([0.0, 30.0, 60.0]), xp.asarray([1.0, 1.0, 0.0]), + fs=120.0) + assert_array_almost_equal(taps1, taps2) + + def test_tuple(self): + taps1 = firwin2(150, (0.0, 0.5, 0.5, 1.0), (1.0, 1.0, 0.0, 0.0)) + taps2 = firwin2(150, [0.0, 0.5, 0.5, 1.0], [1.0, 1.0, 0.0, 0.0]) + assert_array_almost_equal(taps1, taps2) + + @skip_xp_backends("jax.numpy", reason="immutable arrays") + def test_input_modyfication(self, xp): + freq1 = xp.asarray([0.0, 0.5, 0.5, 1.0]) + freq2 = xp.asarray(freq1) + firwin2(80, freq1, xp.asarray([1.0, 1.0, 0.0, 0.0])) + xp_assert_equal(freq1, freq2) + + +@make_xp_test_case(remez) +class TestRemez: + + def test_bad_args(self): + assert_raises(ValueError, remez, 11, [0.1, 0.4], [1], type='pooka') + + def test_hilbert(self): + N = 11 # number of taps in the filter + a = 0.1 # width of the transition band + + # design an unity gain hilbert bandpass filter from w to 0.5-w + h = remez(11, [a, 0.5-a], [1], type='hilbert') + + # make sure the filter has correct # of taps + assert len(h) == N, "Number of Taps" + + # make sure it is type III (anti-symmetric tap coefficients) + assert_array_almost_equal(h[:(N-1)//2], -h[:-(N-1)//2-1:-1]) + + # Since the requested response is symmetric, all even coefficients + # should be zero (or in this case really small) + assert (abs(h[1::2]) < 1e-15).all(), "Even Coefficients Equal Zero" + + # now check the frequency response + w, H = freqz(h, 1) + f = w/2/np.pi + Hmag = abs(H) + + # should have a zero at 0 and pi (in this case close to zero) + assert (Hmag[[0, -1]] < 0.02).all(), "Zero at zero and pi" + + # check that the pass band is close to unity + idx = np.logical_and(f > a, f < 0.5-a) + assert (abs(Hmag[idx] - 1) < 0.015).all(), "Pass Band Close To Unity" + + def test_compare(self, xp): + # test comparison to MATLAB + k = [0.024590270518440, -0.041314581814658, -0.075943803756711, + -0.003530911231040, 0.193140296954975, 0.373400753484939, + 0.373400753484939, 0.193140296954975, -0.003530911231040, + -0.075943803756711, -0.041314581814658, 0.024590270518440] + h = remez(12, xp.asarray([0, 0.3, 0.5, 1]), xp.asarray([1, 0]), fs=2.) + atol_arg = {'atol': 1e-8} if xp_default_dtype(xp) == xp.float32 else {} + xp_assert_close(h, xp.asarray(k, dtype=xp.float64), **atol_arg) + + h = [-0.038976016082299, 0.018704846485491, -0.014644062687875, + 0.002879152556419, 0.016849978528150, -0.043276706138248, + 0.073641298245579, -0.103908158578635, 0.129770906801075, + -0.147163447297124, 0.153302248456347, -0.147163447297124, + 0.129770906801075, -0.103908158578635, 0.073641298245579, + -0.043276706138248, 0.016849978528150, 0.002879152556419, + -0.014644062687875, 0.018704846485491, -0.038976016082299] + atol_arg = {'atol': 3e-8} if xp_default_dtype(xp) == xp.float32 else {} + xp_assert_close( + remez(21, xp.asarray([0, 0.8, 0.9, 1]), xp.asarray([0, 1]), fs=2.), + xp.asarray(h, dtype=xp.float64), **atol_arg + ) + + def test_fs_validation(self): + with pytest.raises(ValueError, match="Sampling.*single scalar"): + remez(11, .1, 1, fs=np.array([10, 20])) + + def test_gh_23266(self, xp): + bands = xp.asarray([0.0, 0.2, 0.3, 0.5]) + desired = xp.asarray([1.0, 0.0]) + weight = xp.asarray([1.0, 2.0]) + remez(21, bands, desired, weight=weight) + + +@make_xp_test_case(firls) +class TestFirls: + + def test_bad_args(self): + # even numtaps + assert_raises(ValueError, firls, 10, [0.1, 0.2], [0, 0]) + # odd bands + assert_raises(ValueError, firls, 11, [0.1, 0.2, 0.4], [0, 0, 0]) + # len(bands) != len(desired) + assert_raises(ValueError, firls, 11, [0.1, 0.2, 0.3, 0.4], [0, 0, 0]) + # non-monotonic bands + assert_raises(ValueError, firls, 11, [0.2, 0.1], [0, 0]) + assert_raises(ValueError, firls, 11, [0.1, 0.2, 0.3, 0.3], [0] * 4) + assert_raises(ValueError, firls, 11, [0.3, 0.4, 0.1, 0.2], [0] * 4) + assert_raises(ValueError, firls, 11, [0.1, 0.3, 0.2, 0.4], [0] * 4) + # negative desired + assert_raises(ValueError, firls, 11, [0.1, 0.2], [-1, 1]) + # len(weight) != len(pairs) + assert_raises(ValueError, firls, 11, [0.1, 0.2], [0, 0], weight=[1, 2]) + # negative weight + assert_raises(ValueError, firls, 11, [0.1, 0.2], [0, 0], weight=[-1]) + + @skip_xp_backends("dask.array", reason="dask fancy indexing shape=(nan,)") + def test_firls(self, xp): + N = 11 # number of taps in the filter + a = 0.1 # width of the transition band + + # design a halfband symmetric low-pass filter + h = firls(11, xp.asarray([0, a, 0.5 - a, 0.5]), xp.asarray([1, 1, 0, 0]), + fs=1.0) + + # make sure the filter has correct # of taps + assert h.shape[0] == N + + # make sure it is symmetric + midx = (N-1) // 2 + flip = array_namespace(h).flip + assert_array_almost_equal(h[:midx], flip(h[midx+1:])) # h[:-midx-1:-1]) + + # make sure the center tap is 0.5 + assert math.isclose(h[midx], 0.5, abs_tol=1e-8) + + # For halfband symmetric, odd coefficients (except the center) + # should be zero (really small) + hodd = xp.stack((h[1:midx:2], h[-midx+1::2])) + assert_array_almost_equal(hodd, xp.zeros_like(hodd)) + + # now check the frequency response + w, H = freqz(_xp_copy_to_numpy(h), 1) + w, H = xp.asarray(w), xp.asarray(H) + f = w/2/xp.pi + Hmag = xp.abs(H) + + # check that the pass band is close to unity + idx = xp.logical_and(f > 0, f < a) + assert_array_almost_equal(Hmag[idx], xp.ones_like(Hmag[idx]), decimal=3) + + # check that the stop band is close to zero + idx = xp.logical_and(f > 0.5 - a, f < 0.5) + assert_array_almost_equal(Hmag[idx], xp.zeros_like(Hmag[idx]), decimal=3) + + def test_compare(self, xp): + # compare to OCTAVE output + taps = firls(9, xp.asarray([0, 0.5, 0.55, 1]), + xp.asarray([1, 1, 0, 0]), weight=xp.asarray([1, 2])) + # >> taps = firls(8, [0 0.5 0.55 1], [1 1 0 0], [1, 2]); + known_taps = [-6.26930101730182e-04, -1.03354450635036e-01, + -9.81576747564301e-03, 3.17271686090449e-01, + 5.11409425599933e-01, 3.17271686090449e-01, + -9.81576747564301e-03, -1.03354450635036e-01, + -6.26930101730182e-04] + atol_arg = {'atol': 5e-8} if xp_default_dtype(xp) == xp.float32 else {} + known_taps = xp.asarray(known_taps, dtype=xp.float64) + xp_assert_close(taps, known_taps, **atol_arg) + + # compare to MATLAB output + taps = firls(11, xp.asarray([0, 0.5, 0.5, 1]), + xp.asarray([1, 1, 0, 0]), weight=xp.asarray([1, 2])) + # >> taps = firls(10, [0 0.5 0.5 1], [1 1 0 0], [1, 2]); + known_taps = [ + 0.058545300496815, -0.014233383714318, -0.104688258464392, + 0.012403323025279, 0.317930861136062, 0.488047220029700, + 0.317930861136062, 0.012403323025279, -0.104688258464392, + -0.014233383714318, 0.058545300496815] + known_taps = xp.asarray(known_taps, dtype=xp.float64) + atol_arg = {'atol': 3e-8} if xp_default_dtype(xp) == xp.float32 else {} + xp_assert_close(taps, known_taps, **atol_arg) + + # With linear changes: + taps = firls(7, xp.asarray((0, 1, 2, 3, 4, 5)), + xp.asarray([1, 0, 0, 1, 1, 0]), fs=20) + # >> taps = firls(6, [0, 0.1, 0.2, 0.3, 0.4, 0.5], [1, 0, 0, 1, 1, 0]) + known_taps = [ + 1.156090832768218, -4.1385894727395849, 7.5288619164321826, + -8.5530572592947856, 7.5288619164321826, -4.1385894727395849, + 1.156090832768218] + known_taps = xp.asarray(known_taps, dtype=xp.float64) + xp_assert_close(taps, known_taps) + + def test_rank_deficient(self, xp): + # solve() runs but warns (only sometimes, so here we don't use match) + x = firls(21, xp.asarray([0, 0.1, 0.9, 1]), xp.asarray([1, 1, 0, 0])) + w, h = freqz(_xp_copy_to_numpy(x), fs=2.) + w, h = map(xp.asarray, (w, h)) + absh2 = xp.abs(h[:2]) + xp_assert_close(absh2, xp.ones_like(absh2), atol=1e-5) + absh2 = xp.abs(h[-2:]) + xp_assert_close(absh2, xp.zeros_like(absh2), atol=1e-6, rtol=1e-7) + # switch to pinvh (tolerances could be higher with longer + # filters, but using shorter ones is faster computationally and + # the idea is the same) + x = firls(101, xp.asarray([0, 0.01, 0.99, 1]), xp.asarray([1, 1, 0, 0])) + w, h = freqz(_xp_copy_to_numpy(x), fs=2.) + w, h = map(xp.asarray, (w, h)) + mask = xp.asarray(w < 0.01) + h = xp.asarray(h) + assert xp.sum(xp.astype(mask, xp.int64)) > 3 + habs = xp.abs(h[mask]) + xp_assert_close(habs, xp.ones_like(habs), atol=1e-4) + mask = xp.asarray(w > 0.99) + assert xp.sum(xp.astype(mask, xp.int64)) > 3 + habs = xp.abs(h[mask]) + xp_assert_close(habs, xp.zeros_like(habs), atol=1e-4) + + def test_fs_validation(self): + with pytest.raises(ValueError, match="Sampling.*single scalar"): + firls(11, .1, 1, fs=np.array([10, 20])) + +@make_xp_test_case(minimum_phase) +class TestMinimumPhase: + + def test_bad_args(self): + # not enough taps + assert_raises(ValueError, minimum_phase, [1.]) + assert_raises(ValueError, minimum_phase, [1., 1.]) + assert_raises(ValueError, minimum_phase, np.full(10, 1j)) + assert_raises((ValueError, TypeError), minimum_phase, 'foo') + assert_raises(ValueError, minimum_phase, np.ones(10), n_fft=8) + assert_raises(ValueError, minimum_phase, np.ones(10), method='foo') + assert_warns(RuntimeWarning, minimum_phase, np.arange(3)) + with pytest.raises(ValueError, match="is only supported when"): + minimum_phase(np.ones(3), method='hilbert', half=False) + + def test_homomorphic(self): + # check that it can recover frequency responses of arbitrary + # linear-phase filters + + # for some cases we can get the actual filter back + h = [1, -1] + h_new = minimum_phase(np.convolve(h, h[::-1])) + xp_assert_close(h_new, np.asarray(h, dtype=np.float64), rtol=0.05) + + # but in general we only guarantee we get the magnitude back + rng = np.random.RandomState(0) + for n in (2, 3, 10, 11, 15, 16, 17, 20, 21, 100, 101): + h = rng.randn(n) + h_linear = np.convolve(h, h[::-1]) + h_new = minimum_phase(h_linear) + xp_assert_close(np.abs(fft(h_new)), np.abs(fft(h)), rtol=1e-4) + h_new = minimum_phase(h_linear, half=False) + assert len(h_linear) == len(h_new) + xp_assert_close(np.abs(fft(h_new)), np.abs(fft(h_linear)), rtol=1e-4) + + @skip_xp_backends("dask.array", reason="too slow") + @make_xp_test_case(signal.hilbert) + def test_hilbert(self, xp): + # compare to MATLAB output of reference implementation + + # f=[0 0.3 0.5 1]; + # a=[1 1 0 0]; + # h=remez(11,f,a); + h = remez(12, [0, 0.3, 0.5, 1], [1, 0], fs=2.) + k = [0.349585548646686, 0.373552164395447, 0.326082685363438, + 0.077152207480935, -0.129943946349364, -0.059355880509749] + h = xp.asarray(h) + k = xp.asarray(k, dtype=xp.float64) + m = minimum_phase(h, 'hilbert') + xp_assert_close(m, k, rtol=5e-3) + + # f=[0 0.8 0.9 1]; + # a=[0 0 1 1]; + # h=remez(20,f,a); + h = remez(21, [0, 0.8, 0.9, 1], [0, 1], fs=2.) + k = [0.232486803906329, -0.133551833687071, 0.151871456867244, + -0.157957283165866, 0.151739294892963, -0.129293146705090, + 0.100787844523204, -0.065832656741252, 0.035361328741024, + -0.014977068692269, -0.158416139047557] + h = xp.asarray(h) + k = xp.asarray(k, dtype=xp.float64) + m = minimum_phase(h, 'hilbert', n_fft=2**19) + xp_assert_close(m, k, rtol=2e-3) + + +class Testfirwin_2d: + def test_invalid_args(self): + with pytest.raises(ValueError, + match="hsize must be a 2-element tuple or list"): + firwin_2d((50,), window=(("kaiser", 5.0), "boxcar"), fc=0.4) + + with pytest.raises(ValueError, + match="window must be a 2-element tuple or list"): + firwin_2d((51, 51), window=("hamming",), fc=0.5) + + with pytest.raises(ValueError, + match="window must be a 2-element tuple or list"): + firwin_2d((51, 51), window="invalid_window", fc=0.5) + + def test_filter_design(self): + hsize = (51, 51) + window = (("kaiser", 8.0), ("kaiser", 8.0)) + fc = 0.4 + taps_kaiser = firwin_2d(hsize, window, fc=fc) + assert taps_kaiser.shape == (51, 51) + + window = ("hamming", "hamming") + taps_hamming = firwin_2d(hsize, window, fc=fc) + assert taps_hamming.shape == (51, 51) + + def test_impulse_response(self): + hsize = (31, 31) + window = ("hamming", "hamming") + fc = 0.4 + taps = firwin_2d(hsize, window, fc=fc) + + impulse = np.zeros((63, 63)) + impulse[31, 31] = 1 + + response = convolve2d(impulse, taps, mode='same') + + expected_response = taps + xp_assert_close(response[16:47, 16:47], expected_response, rtol=1e-5) + + def test_frequency_response(self): + """Compare 1d and 2d frequency response. """ + hsize = (31, 31) + windows = ("hamming", "hamming") + fc = 0.4 + taps_1d = firwin(numtaps=hsize[0], cutoff=fc, window=windows[0]) + taps_2d = firwin_2d(hsize, windows, fc=fc) + + f_resp_1d = fft(taps_1d) + f_resp_2d = fft2(taps_2d) + + xp_assert_close(f_resp_2d[0, :], f_resp_1d, + err_msg='DC Gain at (0, f1) is not unity!') + xp_assert_close(f_resp_2d[:, 0], f_resp_1d, + err_msg='DC Gain at (f0, 0) is not unity!') + xp_assert_close(f_resp_2d, np.outer(f_resp_1d, f_resp_1d), + atol=np.finfo(f_resp_2d.dtype).resolution, + err_msg='2d frequency response is not product of 1d responses') + + def test_symmetry(self): + hsize = (51, 51) + window = ("hamming", "hamming") + fc = 0.4 + taps = firwin_2d(hsize, window, fc=fc) + xp_assert_close(taps, np.flip(taps), rtol=1e-5) + + def test_circular_symmetry(self): + hsize = (51, 51) + window = "hamming" + taps = firwin_2d(hsize, window, circular=True, fc=0.5) + center = hsize[0] // 2 + for i in range(hsize[0]): + for j in range(hsize[1]): + xp_assert_close(taps[i, j], + taps[center - (i - center), center - (j - center)], + rtol=1e-5) + + def test_edge_case_circular(self): + hsize = (3, 3) + window = "hamming" + taps_small = firwin_2d(hsize, window, circular=True, fc=0.5) + assert taps_small.shape == (3, 3) + + hsize = (101, 101) + taps_large = firwin_2d(hsize, window, circular=True, fc=0.5) + assert taps_large.shape == (101, 101) + + def test_known_result(self): + hsize = (5, 5) + window = ('kaiser', 8.0) + fc = 0.1 + fs = 2 + + row_filter = firwin(hsize[0], cutoff=fc, window=window, fs=fs) + col_filter = firwin(hsize[1], cutoff=fc, window=window, fs=fs) + known_result = np.outer(row_filter, col_filter) + + taps = firwin_2d(hsize, (window, window), fc=fc) + assert taps.shape == known_result.shape, ( + f"Shape mismatch: {taps.shape} vs {known_result.shape}" + ) + assert np.allclose(taps, known_result, rtol=1e-1), ( + f"Filter shape mismatch: {taps} vs {known_result}" + ) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_ltisys.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_ltisys.py new file mode 100644 index 0000000000000000000000000000000000000000..d8c4cde919d51ecc998405999a270a6733803377 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_ltisys.py @@ -0,0 +1,1245 @@ +import warnings +from types import GenericAlias + +import numpy as np +import pytest +from pytest import raises as assert_raises +from scipy._lib._array_api import( + assert_almost_equal, xp_assert_equal, xp_assert_close, make_xp_test_case +) + +from scipy.signal import (ss2tf, tf2ss, lti, + dlti, bode, freqresp, lsim, impulse, step, + abcd_normalize, place_poles, + TransferFunction, StateSpace, ZerosPolesGain) +from scipy.signal._filter_design import BadCoefficients +import scipy.linalg as linalg + + +def _assert_poles_close(P1,P2, rtol=1e-8, atol=1e-8): + """ + Check each pole in P1 is close to a pole in P2 with a 1e-8 + relative tolerance or 1e-8 absolute tolerance (useful for zero poles). + These tolerances are very strict but the systems tested are known to + accept these poles so we should not be far from what is requested. + """ + P2 = P2.copy() + for p1 in P1: + found = False + for p2_idx in range(P2.shape[0]): + if np.allclose([np.real(p1), np.imag(p1)], + [np.real(P2[p2_idx]), np.imag(P2[p2_idx])], + rtol, atol): + found = True + np.delete(P2, p2_idx) + break + if not found: + raise ValueError("Can't find pole " + str(p1) + " in " + str(P2)) + + +class TestPlacePoles: + + def _check(self, A, B, P, **kwargs): + """ + Perform the most common tests on the poles computed by place_poles + and return the Bunch object for further specific tests + """ + fsf = place_poles(A, B, P, **kwargs) + expected, _ = np.linalg.eig(A - np.dot(B, fsf.gain_matrix)) + _assert_poles_close(expected, fsf.requested_poles) + _assert_poles_close(expected, fsf.computed_poles) + _assert_poles_close(P,fsf.requested_poles) + return fsf + + def test_real(self): + # Test real pole placement using KNV and YT0 algorithm and example 1 in + # section 4 of the reference publication (see place_poles docstring) + A = np.array([1.380, -0.2077, 6.715, -5.676, -0.5814, -4.290, 0, + 0.6750, 1.067, 4.273, -6.654, 5.893, 0.0480, 4.273, + 1.343, -2.104]).reshape(4, 4) + B = np.array([0, 5.679, 1.136, 1.136, 0, 0, -3.146,0]).reshape(4, 2) + P = np.array([-0.2, -0.5, -5.0566, -8.6659]) + + # Check that both KNV and YT compute correct K matrix + self._check(A, B, P, method='KNV0') + self._check(A, B, P, method='YT') + + # Try to reach the specific case in _YT_real where two singular + # values are almost equal. This is to improve code coverage but I + # have no way to be sure this code is really reached + + # on some architectures this can lead to a RuntimeWarning invalid + # value in divide (see gh-7590), so suppress it for now + with np.errstate(invalid='ignore'): + self._check(A, B, (2,2,3,3)) + + def test_complex(self): + # Test complex pole placement on a linearized car model, taken from L. + # Jaulin, Automatique pour la robotique, Cours et Exercices, iSTE + # editions p 184/185 + A = np.array([[0, 7, 0, 0], + [0, 0, 0, 7/3.], + [0, 0, 0, 0], + [0, 0, 0, 0]]) + B = np.array([[0, 0], + [0, 0], + [1, 0], + [0, 1]]) + # Test complex poles on YT + P = np.array([-3, -1, -2-1j, -2+1j]) + # on macOS arm64 this can lead to a RuntimeWarning invalid + # value in divide, so suppress it for now + with np.errstate(divide='ignore', invalid='ignore'): + self._check(A, B, P) + + # Try to reach the specific case in _YT_complex where two singular + # values are almost equal. This is to improve code coverage but I + # have no way to be sure this code is really reached + + P = [0-1e-6j,0+1e-6j,-10,10] + with np.errstate(divide='ignore', invalid='ignore'): + self._check(A, B, P, maxiter=1000) + + # Try to reach the specific case in _YT_complex where the rank two + # update yields two null vectors. This test was found via Monte Carlo. + + A = np.array( + [-2148,-2902, -2267, -598, -1722, -1829, -165, -283, -2546, + -167, -754, -2285, -543, -1700, -584, -2978, -925, -1300, + -1583, -984, -386, -2650, -764, -897, -517, -1598, 2, -1709, + -291, -338, -153, -1804, -1106, -1168, -867, -2297] + ).reshape(6,6) + + B = np.array( + [-108, -374, -524, -1285, -1232, -161, -1204, -672, -637, + -15, -483, -23, -931, -780, -1245, -1129, -1290, -1502, + -952, -1374, -62, -964, -930, -939, -792, -756, -1437, + -491, -1543, -686] + ).reshape(6,5) + P = [-25.-29.j, -25.+29.j, 31.-42.j, 31.+42.j, 33.-41.j, 33.+41.j] + self._check(A, B, P) + + # Use a lot of poles to go through all cases for update_order + # in _YT_loop + + big_A = np.ones((11,11))-np.eye(11) + big_B = np.ones((11,10))-np.diag([1]*10,1)[:,1:] + big_A[:6,:6] = A + big_B[:6,:5] = B + + P = [-10,-20,-30,40,50,60,70,-20-5j,-20+5j,5+3j,5-3j] + with np.errstate(divide='ignore', invalid='ignore'): + self._check(big_A, big_B, P) + + #check with only complex poles and only real poles + P = [-10,-20,-30,-40,-50,-60,-70,-80,-90,-100] + self._check(big_A[:-1,:-1], big_B[:-1,:-1], P) + P = [-10+10j,-20+20j,-30+30j,-40+40j,-50+50j, + -10-10j,-20-20j,-30-30j,-40-40j,-50-50j] + self._check(big_A[:-1,:-1], big_B[:-1,:-1], P) + + # need a 5x5 array to ensure YT handles properly when there + # is only one real pole and several complex + A = np.array([0,7,0,0,0,0,0,7/3.,0,0,0,0,0,0,0,0, + 0,0,0,5,0,0,0,0,9]).reshape(5,5) + B = np.array([0,0,0,0,1,0,0,1,2,3]).reshape(5,2) + P = np.array([-2, -3+1j, -3-1j, -1+1j, -1-1j]) + with np.errstate(divide='ignore', invalid='ignore'): + place_poles(A, B, P) + + # same test with an odd number of real poles > 1 + # this is another specific case of YT + P = np.array([-2, -3, -4, -1+1j, -1-1j]) + with np.errstate(divide='ignore', invalid='ignore'): + self._check(A, B, P) + + def test_tricky_B(self): + # check we handle as we should the 1 column B matrices and + # n column B matrices (with n such as shape(A)=(n, n)) + A = np.array([1.380, -0.2077, 6.715, -5.676, -0.5814, -4.290, 0, + 0.6750, 1.067, 4.273, -6.654, 5.893, 0.0480, 4.273, + 1.343, -2.104]).reshape(4, 4) + B = np.array([0, 5.679, 1.136, 1.136, 0, 0, -3.146, 0, 1, 2, 3, 4, + 5, 6, 7, 8]).reshape(4, 4) + + # KNV or YT are not called here, it's a specific case with only + # one unique solution + P = np.array([-0.2, -0.5, -5.0566, -8.6659]) + fsf = self._check(A, B, P) + # rtol and nb_iter should be set to np.nan as the identity can be + # used as transfer matrix + assert np.isnan(fsf.rtol) + assert np.isnan(fsf.nb_iter) + + # check with complex poles too as they trigger a specific case in + # the specific case :-) + P = np.array((-2+1j,-2-1j,-3,-2)) + fsf = self._check(A, B, P) + assert np.isnan(fsf.rtol) + assert np.isnan(fsf.nb_iter) + + #now test with a B matrix with only one column (no optimisation) + B = B[:,0].reshape(4,1) + P = np.array((-2+1j,-2-1j,-3,-2)) + fsf = self._check(A, B, P) + + # we can't optimize anything, check they are set to 0 as expected + assert fsf.rtol == 0 + assert fsf.nb_iter == 0 + + def test_errors(self): + # Test input mistakes from user + A = np.array([0,7,0,0,0,0,0,7/3.,0,0,0,0,0,0,0,0]).reshape(4,4) + B = np.array([0,0,0,0,1,0,0,1]).reshape(4,2) + + #should fail as the method keyword is invalid + assert_raises(ValueError, place_poles, A, B, (-2.1,-2.2,-2.3,-2.4), + method="foo") + + #should fail as poles are not 1D array + assert_raises(ValueError, place_poles, A, B, + np.array((-2.1,-2.2,-2.3,-2.4)).reshape(4,1)) + + #should fail as A is not a 2D array + assert_raises(ValueError, place_poles, A[:,:,np.newaxis], B, + (-2.1,-2.2,-2.3,-2.4)) + + #should fail as B is not a 2D array + assert_raises(ValueError, place_poles, A, B[:,:,np.newaxis], + (-2.1,-2.2,-2.3,-2.4)) + + #should fail as there are too many poles + assert_raises(ValueError, place_poles, A, B, (-2.1,-2.2,-2.3,-2.4,-3)) + + #should fail as there are not enough poles + assert_raises(ValueError, place_poles, A, B, (-2.1,-2.2,-2.3)) + + #should fail as the rtol is greater than 1 + assert_raises(ValueError, place_poles, A, B, (-2.1,-2.2,-2.3,-2.4), + rtol=42) + + #should fail as maxiter is smaller than 1 + assert_raises(ValueError, place_poles, A, B, (-2.1,-2.2,-2.3,-2.4), + maxiter=-42) + + # should fail as ndim(B) is two + assert_raises(ValueError, place_poles, A, B, (-2,-2,-2,-2)) + + # uncontrollable system + assert_raises(ValueError, place_poles, np.ones((4,4)), + np.ones((4,2)), (1,2,3,4)) + + # Should not raise ValueError as the poles can be placed but should + # raise a warning as the convergence is not reached + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + fsf = place_poles(A, B, (-1,-2,-3,-4), rtol=1e-16, maxiter=42) + assert len(w) == 1 + assert issubclass(w[-1].category, UserWarning) + assert ("Convergence was not reached after maxiter iterations" + in str(w[-1].message)) + assert fsf.nb_iter == 42 + + # should fail as a complex misses its conjugate + assert_raises(ValueError, place_poles, A, B, (-2+1j,-2-1j,-2+3j,-2)) + + # should fail as A is not square + assert_raises(ValueError, place_poles, A[:,:3], B, (-2,-3,-4,-5)) + + # should fail as B has not the same number of lines as A + assert_raises(ValueError, place_poles, A, B[:3,:], (-2,-3,-4,-5)) + + # should fail as KNV0 does not support complex poles + assert_raises(ValueError, place_poles, A, B, + (-2+1j,-2-1j,-2+3j,-2-3j), method="KNV0") + + +class TestSS2TF: + + def check_matrix_shapes(self, p, q, r): + ss2tf(np.zeros((p, p)), + np.zeros((p, q)), + np.zeros((r, p)), + np.zeros((r, q)), 0) + + def test_shapes(self): + # Each tuple holds: + # number of states, number of inputs, number of outputs + for p, q, r in [(3, 3, 3), (1, 3, 3), (1, 1, 1)]: + self.check_matrix_shapes(p, q, r) + + def test_basic(self): + # Test a round trip through tf2ss and ss2tf. + b = np.array([1.0, 3.0, 5.0]) + a = np.array([1.0, 2.0, 3.0]) + + A, B, C, D = tf2ss(b, a) + xp_assert_close(A, [[-2., -3], [1, 0]], rtol=1e-13) + xp_assert_close(B, [[1.], [0]], rtol=1e-13) + xp_assert_close(C, [[1., 2]], rtol=1e-13) + xp_assert_close(D, [[1.]], rtol=1e-14) + + bb, aa = ss2tf(A, B, C, D) + xp_assert_close(bb[0], b, rtol=1e-13) + xp_assert_close(aa, a, rtol=1e-13) + + def test_zero_order_round_trip(self): + # See gh-5760 + tf = (2, 1) + A, B, C, D = tf2ss(*tf) + xp_assert_close(A, [[0.]], rtol=1e-13) + xp_assert_close(B, [[0.]], rtol=1e-13) + xp_assert_close(C, [[0.]], rtol=1e-13) + xp_assert_close(D, [[2.]], rtol=1e-13) + + num, den = ss2tf(A, B, C, D) + xp_assert_close(num, [[2., 0]], rtol=1e-13) + xp_assert_close(den, [1., 0], rtol=1e-13) + + tf = ([[5], [2]], 1) + A, B, C, D = tf2ss(*tf) + xp_assert_close(A, [[0.]], rtol=1e-13) + xp_assert_close(B, [[0.]], rtol=1e-13) + xp_assert_close(C, [[0.], [0]], rtol=1e-13) + xp_assert_close(D, [[5.], [2]], rtol=1e-13) + + num, den = ss2tf(A, B, C, D) + xp_assert_close(num, [[5., 0], [2, 0]], rtol=1e-13) + xp_assert_close(den, [1., 0], rtol=1e-13) + + def test_simo_round_trip(self): + # See gh-5753 + tf = ([[1, 2], [1, 1]], [1, 2]) + A, B, C, D = tf2ss(*tf) + xp_assert_close(A, [[-2.]], rtol=1e-13) + xp_assert_close(B, [[1.]], rtol=1e-13) + xp_assert_close(C, [[0.], [-1.]], rtol=1e-13) + xp_assert_close(D, [[1.], [1.]], rtol=1e-13) + + num, den = ss2tf(A, B, C, D) + xp_assert_close(num, [[1., 2.], [1., 1.]], rtol=1e-13) + xp_assert_close(den, [1., 2.], rtol=1e-13) + + tf = ([[1, 0, 1], [1, 1, 1]], [1, 1, 1]) + A, B, C, D = tf2ss(*tf) + xp_assert_close(A, [[-1., -1.], [1., 0.]], rtol=1e-13) + xp_assert_close(B, [[1.], [0.]], rtol=1e-13) + xp_assert_close(C, [[-1., 0.], [0., 0.]], rtol=1e-13) + xp_assert_close(D, [[1.], [1.]], rtol=1e-13) + + num, den = ss2tf(A, B, C, D) + xp_assert_close(num, [[1., 0., 1.], [1., 1., 1.]], rtol=1e-13) + xp_assert_close(den, [1., 1., 1.], rtol=1e-13) + + tf = ([[1, 2, 3], [1, 2, 3]], [1, 2, 3, 4]) + A, B, C, D = tf2ss(*tf) + xp_assert_close(A, [[-2., -3, -4], [1, 0, 0], [0, 1, 0]], rtol=1e-13) + xp_assert_close(B, [[1.], [0], [0]], rtol=1e-13) + xp_assert_close(C, [[1., 2, 3], [1, 2, 3]], rtol=1e-13) + xp_assert_close(D, [[0.], [0]], rtol=1e-13) + + num, den = ss2tf(A, B, C, D) + xp_assert_close(num, [[0., 1, 2, 3], [0, 1, 2, 3]], rtol=1e-13) + xp_assert_close(den, [1., 2, 3, 4], rtol=1e-13) + + tf = (np.array([1, [2, 3]], dtype=object), [1, 6]) + A, B, C, D = tf2ss(*tf) + xp_assert_close(A, [[-6.]], rtol=1e-31) + xp_assert_close(B, [[1.]], rtol=1e-31) + xp_assert_close(C, [[1.], [-9]], rtol=1e-31) + xp_assert_close(D, [[0.], [2]], rtol=1e-31) + + num, den = ss2tf(A, B, C, D) + xp_assert_close(num, [[0., 1], [2, 3]], rtol=1e-13) + xp_assert_close(den, [1., 6], rtol=1e-13) + + tf = (np.array([[1, -3], [1, 2, 3]], dtype=object), [1, 6, 5]) + A, B, C, D = tf2ss(*tf) + xp_assert_close(A, [[-6., -5], [1, 0]], rtol=1e-13) + xp_assert_close(B, [[1.], [0]], rtol=1e-13) + xp_assert_close(C, [[1., -3], [-4, -2]], rtol=1e-13) + xp_assert_close(D, [[0.], [1]], rtol=1e-13) + + num, den = ss2tf(A, B, C, D) + xp_assert_close(num, [[0., 1, -3], [1, 2, 3]], rtol=1e-13) + xp_assert_close(den, [1., 6, 5], rtol=1e-13) + + def test_all_int_arrays(self): + A = [[0, 1, 0], [0, 0, 1], [-3, -4, -2]] + B = [[0], [0], [1]] + C = [[5, 1, 0]] + D = [[0]] + num, den = ss2tf(A, B, C, D) + xp_assert_close(num, [[0.0, 0.0, 1.0, 5.0]], rtol=1e-13, atol=1e-14) + xp_assert_close(den, [1.0, 2.0, 4.0, 3.0], rtol=1e-13) + + def test_multioutput(self): + # Regression test for gh-2669. + + # 4 states + A = np.array([[-1.0, 0.0, 1.0, 0.0], + [-1.0, 0.0, 2.0, 0.0], + [-4.0, 0.0, 3.0, 0.0], + [-8.0, 8.0, 0.0, 4.0]]) + + # 1 input + B = np.array([[0.3], + [0.0], + [7.0], + [0.0]]) + + # 3 outputs + C = np.array([[0.0, 1.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 1.0], + [8.0, 8.0, 0.0, 0.0]]) + + D = np.array([[0.0], + [0.0], + [1.0]]) + + # Get the transfer functions for all the outputs in one call. + b_all, a = ss2tf(A, B, C, D) + + # Get the transfer functions for each output separately. + b0, a0 = ss2tf(A, B, C[0], D[0]) + b1, a1 = ss2tf(A, B, C[1], D[1]) + b2, a2 = ss2tf(A, B, C[2], D[2]) + + # Check that we got the same results. + xp_assert_close(a0, a, rtol=1e-13) + xp_assert_close(a1, a, rtol=1e-13) + xp_assert_close(a2, a, rtol=1e-13) + xp_assert_close(b_all, np.vstack((b0, b1, b2)), rtol=1e-13, atol=1e-14) + + +class TestLsim: + digits_accuracy = 7 + + def lti_nowarn(self, *args): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", BadCoefficients) + system = lti(*args) + return system + + def test_first_order(self): + # y' = -y + # exact solution is y(t) = exp(-t) + system = self.lti_nowarn(-1.,1.,1.,0.) + t = np.linspace(0,5) + u = np.zeros_like(t) + tout, y, x = lsim(system, u, t, X0=[1.0]) + expected_x = np.exp(-tout) + assert_almost_equal(x, expected_x) + assert_almost_equal(y, expected_x) + + def test_second_order(self): + t = np.linspace(0, 10, 1001) + u = np.zeros_like(t) + # Second order system with a repeated root: x''(t) + 2*x(t) + x(t) = 0. + # With initial conditions x(0)=1.0 and x'(t)=0.0, the exact solution + # is (1-t)*exp(-t). + system = self.lti_nowarn([1.0], [1.0, 2.0, 1.0]) + tout, y, x = lsim(system, u, t, X0=[1.0, 0.0]) + expected_x = (1.0 - tout) * np.exp(-tout) + assert_almost_equal(x[:, 0], expected_x) + + def test_integrator(self): + # integrator: y' = u + system = self.lti_nowarn(0., 1., 1., 0.) + t = np.linspace(0,5) + u = t + tout, y, x = lsim(system, u, t) + expected_x = 0.5 * tout**2 + assert_almost_equal(x, expected_x, decimal=self.digits_accuracy) + assert_almost_equal(y, expected_x, decimal=self.digits_accuracy) + + def test_two_states(self): + # A system with two state variables, two inputs, and one output. + A = np.array([[-1.0, 0.0], [0.0, -2.0]]) + B = np.array([[1.0, 0.0], [0.0, 1.0]]) + C = np.array([1.0, 0.0]) + D = np.zeros((1, 2)) + + system = self.lti_nowarn(A, B, C, D) + + t = np.linspace(0, 10.0, 21) + u = np.zeros((len(t), 2)) + tout, y, x = lsim(system, U=u, T=t, X0=[1.0, 1.0]) + expected_y = np.exp(-tout) + expected_x0 = np.exp(-tout) + expected_x1 = np.exp(-2.0 * tout) + assert_almost_equal(y, expected_y) + assert_almost_equal(x[:, 0], expected_x0) + assert_almost_equal(x[:, 1], expected_x1) + + def test_double_integrator(self): + # double integrator: y'' = 2u + A = np.array([[0., 1.], [0., 0.]]) + B = np.array([[0.], [1.]]) + C = np.array([[2., 0.]]) + system = self.lti_nowarn(A, B, C, 0.) + t = np.linspace(0,5) + u = np.ones_like(t) + tout, y, x = lsim(system, u, t) + expected_x = np.transpose(np.array([0.5 * tout**2, tout])) + expected_y = tout**2 + assert_almost_equal(x, expected_x, decimal=self.digits_accuracy) + assert_almost_equal(y, expected_y, decimal=self.digits_accuracy) + + def test_jordan_block(self): + # Non-diagonalizable A matrix + # x1' + x1 = x2 + # x2' + x2 = u + # y = x1 + # Exact solution with u = 0 is y(t) = t exp(-t) + A = np.array([[-1., 1.], [0., -1.]]) + B = np.array([[0.], [1.]]) + C = np.array([[1., 0.]]) + system = self.lti_nowarn(A, B, C, 0.) + t = np.linspace(0,5) + u = np.zeros_like(t) + tout, y, x = lsim(system, u, t, X0=[0.0, 1.0]) + expected_y = tout * np.exp(-tout) + assert_almost_equal(y, expected_y) + + def test_miso(self): + # A system with two state variables, two inputs, and one output. + A = np.array([[-1.0, 0.0], [0.0, -2.0]]) + B = np.array([[1.0, 0.0], [0.0, 1.0]]) + C = np.array([1.0, 0.0]) + D = np.zeros((1,2)) + system = self.lti_nowarn(A, B, C, D) + + t = np.linspace(0, 5.0, 101) + u = np.zeros((len(t), 2)) + tout, y, x = lsim(system, u, t, X0=[1.0, 1.0]) + expected_y = np.exp(-tout) + expected_x0 = np.exp(-tout) + expected_x1 = np.exp(-2.0*tout) + assert_almost_equal(y, expected_y) + assert_almost_equal(x[:,0], expected_x0) + assert_almost_equal(x[:,1], expected_x1) + + def test_nonzero_initial_time(self): + system = self.lti_nowarn(-1.,1.,1.,0.) + t = np.linspace(1,2) + u = np.zeros_like(t) + tout, y, x = lsim(system, u, t, X0=[1.0]) + expected_y = np.exp(-tout) + assert_almost_equal(y, expected_y) + + def test_nonequal_timesteps(self): + t = np.array([0.0, 1.0, 1.0, 3.0]) + u = np.array([0.0, 0.0, 1.0, 1.0]) + # Simple integrator: x'(t) = u(t) + system = ([1.0], [1.0, 0.0]) + with assert_raises(ValueError, + match="Time steps are not equally spaced."): + tout, y, x = lsim(system, u, t, X0=[1.0]) + + +class TestImpulse: + def test_first_order(self): + # First order system: x'(t) + x(t) = u(t) + # Exact impulse response is x(t) = exp(-t). + system = ([1.0], [1.0,1.0]) + tout, y = impulse(system) + expected_y = np.exp(-tout) + assert_almost_equal(y, expected_y) + + def test_first_order_fixed_time(self): + # Specify the desired time values for the output. + + # First order system: x'(t) + x(t) = u(t) + # Exact impulse response is x(t) = exp(-t). + system = ([1.0], [1.0,1.0]) + n = 21 + t = np.linspace(0, 2.0, n) + tout, y = impulse(system, T=t) + assert tout.shape == (n,) + assert_almost_equal(tout, t) + expected_y = np.exp(-t) + assert_almost_equal(y, expected_y) + + def test_first_order_initial(self): + # Specify an initial condition as a scalar. + + # First order system: x'(t) + x(t) = u(t), x(0)=3.0 + # Exact impulse response is x(t) = 4*exp(-t). + system = ([1.0], [1.0,1.0]) + tout, y = impulse(system, X0=3.0) + expected_y = 4.0 * np.exp(-tout) + assert_almost_equal(y, expected_y) + + def test_first_order_initial_list(self): + # Specify an initial condition as a list. + + # First order system: x'(t) + x(t) = u(t), x(0)=3.0 + # Exact impulse response is x(t) = 4*exp(-t). + system = ([1.0], [1.0,1.0]) + tout, y = impulse(system, X0=[3.0]) + expected_y = 4.0 * np.exp(-tout) + assert_almost_equal(y, expected_y) + + def test_integrator(self): + # Simple integrator: x'(t) = u(t) + system = ([1.0], [1.0,0.0]) + tout, y = impulse(system) + expected_y = np.ones_like(tout) + assert_almost_equal(y, expected_y) + + def test_second_order(self): + # Second order system with a repeated root: + # x''(t) + 2*x(t) + x(t) = u(t) + # The exact impulse response is t*exp(-t). + system = ([1.0], [1.0, 2.0, 1.0]) + tout, y = impulse(system) + expected_y = tout * np.exp(-tout) + assert_almost_equal(y, expected_y) + + def test_array_like(self): + # Test that function can accept sequences, scalars. + system = ([1.0], [1.0, 2.0, 1.0]) + # TODO: add meaningful test where X0 is a list + tout, y = impulse(system, X0=[3], T=[5, 6]) + tout, y = impulse(system, X0=[3], T=[5]) + + def test_array_like2(self): + system = ([1.0], [1.0, 2.0, 1.0]) + tout, y = impulse(system, X0=3, T=5) + + +class TestStep: + def test_first_order(self): + # First order system: x'(t) + x(t) = u(t) + # Exact step response is x(t) = 1 - exp(-t). + system = ([1.0], [1.0,1.0]) + tout, y = step(system) + expected_y = 1.0 - np.exp(-tout) + assert_almost_equal(y, expected_y) + + def test_first_order_fixed_time(self): + # Specify the desired time values for the output. + + # First order system: x'(t) + x(t) = u(t) + # Exact step response is x(t) = 1 - exp(-t). + system = ([1.0], [1.0,1.0]) + n = 21 + t = np.linspace(0, 2.0, n) + tout, y = step(system, T=t) + assert tout.shape == (n,) + assert_almost_equal(tout, t) + expected_y = 1 - np.exp(-t) + assert_almost_equal(y, expected_y) + + def test_first_order_initial(self): + # Specify an initial condition as a scalar. + + # First order system: x'(t) + x(t) = u(t), x(0)=3.0 + # Exact step response is x(t) = 1 + 2*exp(-t). + system = ([1.0], [1.0,1.0]) + tout, y = step(system, X0=3.0) + expected_y = 1 + 2.0*np.exp(-tout) + assert_almost_equal(y, expected_y) + + def test_first_order_initial_list(self): + # Specify an initial condition as a list. + + # First order system: x'(t) + x(t) = u(t), x(0)=3.0 + # Exact step response is x(t) = 1 + 2*exp(-t). + system = ([1.0], [1.0,1.0]) + tout, y = step(system, X0=[3.0]) + expected_y = 1 + 2.0*np.exp(-tout) + assert_almost_equal(y, expected_y) + + def test_integrator(self): + # Simple integrator: x'(t) = u(t) + # Exact step response is x(t) = t. + system = ([1.0],[1.0,0.0]) + tout, y = step(system) + expected_y = tout + assert_almost_equal(y, expected_y) + + def test_second_order(self): + # Second order system with a repeated root: + # x''(t) + 2*x(t) + x(t) = u(t) + # The exact step response is 1 - (1 + t)*exp(-t). + system = ([1.0], [1.0, 2.0, 1.0]) + tout, y = step(system) + expected_y = 1 - (1 + tout) * np.exp(-tout) + assert_almost_equal(y, expected_y) + + def test_array_like(self): + # Test that function can accept sequences, scalars. + system = ([1.0], [1.0, 2.0, 1.0]) + # TODO: add meaningful test where X0 is a list + tout, y = step(system, T=[5, 6]) + + def test_complex_input(self): + # Test that complex input doesn't raise an error. + # `step` doesn't seem to have been designed for complex input, but this + # works and may be used, so add regression test. See gh-2654. + step(([], [-1], 1+0j)) + + +class TestLti: + def test_lti_instantiation(self): + # Test that lti can be instantiated with sequences, scalars. + # See PR-225. + + # TransferFunction + s = lti([1], [-1]) + assert isinstance(s, TransferFunction) + assert isinstance(s, lti) + assert not isinstance(s, dlti) + assert s.dt is None + + # ZerosPolesGain + s = lti(np.array([]), np.array([-1]), 1) + assert isinstance(s, ZerosPolesGain) + assert isinstance(s, lti) + assert not isinstance(s, dlti) + assert s.dt is None + + # StateSpace + s = lti([], [-1], 1) + s = lti([1], [-1], 1, 3) + assert isinstance(s, StateSpace) + assert isinstance(s, lti) + assert not isinstance(s, dlti) + assert s.dt is None + + +class TestStateSpace: + def test_initialization(self): + # Check that all initializations work + StateSpace(1, 1, 1, 1) + StateSpace([1], [2], [3], [4]) + StateSpace(np.array([[1, 2], [3, 4]]), np.array([[1], [2]]), + np.array([[1, 0]]), np.array([[0]])) + + def test_conversion(self): + # Check the conversion functions + s = StateSpace(1, 2, 3, 4) + assert isinstance(s.to_ss(), StateSpace) + assert isinstance(s.to_tf(), TransferFunction) + assert isinstance(s.to_zpk(), ZerosPolesGain) + + # Make sure copies work + assert StateSpace(s) is not s + assert s.to_ss() is not s + + def test_properties(self): + # Test setters/getters for cross class properties. + # This implicitly tests to_tf() and to_zpk() + + # Getters + s = StateSpace(1, 1, 1, 1) + xp_assert_equal(s.poles, [1.]) + xp_assert_equal(s.zeros, [0.]) + assert s.dt is None + + def test_operators(self): + # Test +/-/* operators on systems + + class BadType: + pass + + s1 = StateSpace(np.array([[-0.5, 0.7], [0.3, -0.8]]), + np.array([[1], [0]]), + np.array([[1, 0]]), + np.array([[0]]), + ) + + s2 = StateSpace(np.array([[-0.2, -0.1], [0.4, -0.1]]), + np.array([[1], [0]]), + np.array([[1, 0]]), + np.array([[0]]) + ) + + s_discrete = s1.to_discrete(0.1) + s2_discrete = s2.to_discrete(0.2) + s3_discrete = s2.to_discrete(0.1) + + # Impulse response + t = np.linspace(0, 1, 100) + u = np.zeros_like(t) + u[0] = 1 + + # Test multiplication + for typ in (int, float, complex, np.float32, np.complex128, np.array): + xp_assert_close(lsim(typ(2) * s1, U=u, T=t)[1], + typ(2) * lsim(s1, U=u, T=t)[1]) + + xp_assert_close(lsim(s1 * typ(2), U=u, T=t)[1], + lsim(s1, U=u, T=t)[1] * typ(2)) + + xp_assert_close(lsim(s1 / typ(2), U=u, T=t)[1], + lsim(s1, U=u, T=t)[1] / typ(2)) + + with assert_raises(TypeError): + typ(2) / s1 + + xp_assert_close(lsim(s1 * 2, U=u, T=t)[1], + lsim(s1, U=2 * u, T=t)[1]) + + xp_assert_close(lsim(s1 * s2, U=u, T=t)[1], + lsim(s1, U=lsim(s2, U=u, T=t)[1], T=t)[1], + atol=1e-5) + + with assert_raises(TypeError): + s1 / s1 + + with assert_raises(TypeError): + s1 * s_discrete + + with assert_raises(TypeError): + # Check different discretization constants + s_discrete * s2_discrete + + with assert_raises(TypeError): + s1 * BadType() + + with assert_raises(TypeError): + BadType() * s1 + + with assert_raises(TypeError): + s1 / BadType() + + with assert_raises(TypeError): + BadType() / s1 + + # Test addition + xp_assert_close(lsim(s1 + 2, U=u, T=t)[1], + 2 * u + lsim(s1, U=u, T=t)[1]) + + # Check for dimension mismatch + with assert_raises(ValueError): + s1 + np.array([1, 2]) + + with assert_raises(ValueError): + np.array([1, 2]) + s1 + + with assert_raises(TypeError): + s1 + s_discrete + + with assert_raises(ValueError): + s1 / np.array([[1, 2], [3, 4]]) + + with assert_raises(TypeError): + # Check different discretization constants + s_discrete + s2_discrete + + with assert_raises(TypeError): + s1 + BadType() + + with assert_raises(TypeError): + BadType() + s1 + + xp_assert_close(lsim(s1 + s2, U=u, T=t)[1], + lsim(s1, U=u, T=t)[1] + lsim(s2, U=u, T=t)[1]) + + # Test subtraction + xp_assert_close(lsim(s1 - 2, U=u, T=t)[1], + -2 * u + lsim(s1, U=u, T=t)[1]) + + xp_assert_close(lsim(2 - s1, U=u, T=t)[1], + 2 * u + lsim(-s1, U=u, T=t)[1]) + + xp_assert_close(lsim(s1 - s2, U=u, T=t)[1], + lsim(s1, U=u, T=t)[1] - lsim(s2, U=u, T=t)[1]) + + with assert_raises(TypeError): + s1 - BadType() + + with assert_raises(TypeError): + BadType() - s1 + + s = s_discrete + s3_discrete + assert s.dt == 0.1 + + s = s_discrete * s3_discrete + assert s.dt == 0.1 + + s = 3 * s_discrete + assert s.dt == 0.1 + + s = -s_discrete + assert s.dt == 0.1 + +class TestTransferFunction: + def test_initialization(self): + # Check that all initializations work + TransferFunction(1, 1) + TransferFunction([1], [2]) + TransferFunction(np.array([1]), np.array([2])) + + def test_conversion(self): + # Check the conversion functions + s = TransferFunction([1, 0], [1, -1]) + assert isinstance(s.to_ss(), StateSpace) + assert isinstance(s.to_tf(), TransferFunction) + assert isinstance(s.to_zpk(), ZerosPolesGain) + + # Make sure copies work + assert TransferFunction(s) is not s + assert s.to_tf() is not s + + def test_properties(self): + # Test setters/getters for cross class properties. + # This implicitly tests to_ss() and to_zpk() + + # Getters + s = TransferFunction([1, 0], [1, -1]) + xp_assert_equal(s.poles, [1.]) + xp_assert_equal(s.zeros, [0.]) + + +class TestZerosPolesGain: + def test_initialization(self): + # Check that all initializations work + ZerosPolesGain(1, 1, 1) + ZerosPolesGain([1], [2], 1) + ZerosPolesGain(np.array([1]), np.array([2]), 1) + + def test_conversion(self): + #Check the conversion functions + s = ZerosPolesGain(1, 2, 3) + assert isinstance(s.to_ss(), StateSpace) + assert isinstance(s.to_tf(), TransferFunction) + assert isinstance(s.to_zpk(), ZerosPolesGain) + + # Make sure copies work + assert ZerosPolesGain(s) is not s + assert s.to_zpk() is not s + + +@make_xp_test_case(abcd_normalize) +class Test_abcd_normalize: + A = [[1.0, 2.0], [3.0, 4.0]] + B = [[-1.0], [5.0]] + C = [[4.0, 5.0]] + D = [[2.5]] + + def test_no_matrix_fails(self): + assert_raises(ValueError, abcd_normalize) + + def test_A_nosquare_fails(self, xp): + assert_raises(ValueError, abcd_normalize, xp.asarray([1, -1]), + xp.asarray(self.B), xp.asarray(self.C), xp.asarray(self.D)) + + def test_AB_mismatch_fails(self, xp): + assert_raises(ValueError, abcd_normalize, xp.asarray(self.A), + xp.asarray([-1, 5]), xp.asarray(self.C), xp.asarray(self.D)) + + def test_AC_mismatch_fails(self, xp): + assert_raises(ValueError, abcd_normalize, xp.asarray(self.A), + xp.asarray(self.B), xp.asarray([[4.0], [5.0]]), + xp.asarray(self.D)) + + def test_CD_mismatch_fails(self, xp): + assert_raises(ValueError, abcd_normalize, xp.asarray(self.A), + xp.asarray(self.B), xp.asarray(self.C), xp.asarray([2.5, 0])) + + def test_BD_mismatch_fails(self, xp): + assert_raises(ValueError, abcd_normalize, xp.asarray(self.A), + xp.asarray([-1, 5]), xp.asarray(self.C), xp.asarray(self.D)) + + def test_normalized_matrices_unchanged(self, xp): + A_, B_, C_, D_ = map(xp.asarray, (self.A, self.B, self.C, self.D)) + A, B, C, D = abcd_normalize(A=A_, B=B_, C=C_, D=D_) + xp_assert_equal(A, A_) + xp_assert_equal(B, B_) + xp_assert_equal(C, C_) + xp_assert_equal(D, D_) + + def test_shapes(self, xp): + A, B, C, D = abcd_normalize(xp.asarray(self.A), xp.asarray(self.B), + xp.asarray([1, 0]), xp.asarray(0)) + assert A.shape[0] == A.shape[1] + assert A.shape[0] == B.shape[0] + assert A.shape[0] == C.shape[1] + assert C.shape[0] == D.shape[0] + assert B.shape[1] == D.shape[1] + + def test_zero_dimension_is_not_none1(self, xp): + A_ = xp.asarray(self.A) + B_ = xp.zeros((2, 0)) + D_ = xp.zeros((0, 0)) + A, B, C, D = abcd_normalize(A=A_, B=B_, D=D_) + xp_assert_equal(A, A_) + xp_assert_equal(B, B_) + xp_assert_equal(D, D_) + assert C.shape[0] == D_.shape[0] + assert C.shape[1] == A_.shape[0] + + def test_zero_dimension_is_not_none2(self, xp): + A_ = xp.asarray(self.A) + B_ = xp.zeros((2, 0)) + C_ = xp.zeros((0, 2)) + A, B, C, D = abcd_normalize(A=A_, B=B_, C=C_) + xp_assert_equal(A, A_) + xp_assert_equal(B, B_) + xp_assert_equal(C, C_) + assert D.shape[0] == C_.shape[0] + assert D.shape[1] == B_.shape[1] + + def test_missing_A(self, xp): + B_, C_, D_ = map(xp.asarray, (self.B, self.C, self.D)) + A, B, C, D = abcd_normalize(B=B_, C=C_, D=D_) + assert A.shape[0] == A.shape[1] + assert A.shape[0] == B.shape[0] + assert A.shape == (B_.shape[0], B_.shape[0]) + + def test_missing_B(self, xp): + A_, C_, D_ = map(xp.asarray, (self.A, self.C, self.D)) + A, B, C, D = abcd_normalize(A=A_, C=C_, D=D_) + assert B.shape[0] == A.shape[0] + assert B.shape[1] == D.shape[1] + assert B.shape == (A_.shape[0], D_.shape[1]) + + def test_missing_C(self, xp): + A_, B_, D_ = map(xp.asarray, (self.A, self.B, self.D)) + A, B, C, D = abcd_normalize(A=A_, B=B_, D=D_) + assert C.shape[0] == D.shape[0] + assert C.shape[1] == A.shape[0] + assert C.shape == (D_.shape[0], A_.shape[0]) + + def test_missing_D(self, xp): + A_, B_, C_ = map(xp.asarray, (self.A, self.B, self.C)) + A, B, C, D = abcd_normalize(A=A_, B=B_, C=C_) + assert D.shape[0] == C.shape[0] + assert D.shape[1] == B.shape[1] + assert D.shape == (C_.shape[0], B_.shape[1]) + + def test_missing_AB(self, xp): + C_, D_ = map(xp.asarray, (self.C, self.D)) + A, B, C, D = abcd_normalize(C=C_, D=D_) + assert A.shape[0] == A.shape[1] + assert A.shape[0] == B.shape[0] + assert B.shape[1] == D.shape[1] + assert A.shape == (C_.shape[1], C_.shape[1]) + assert B.shape == (C_.shape[1], D_.shape[1]) + + def test_missing_AC(self, xp): + B_, D_ = map(xp.asarray, (self.B, self.D)) + A, B, C, D = abcd_normalize(B=B_, D=D_) + assert A.shape[0] == A.shape[1] + assert A.shape[0] == B.shape[0] + assert C.shape[0] == D.shape[0] + assert C.shape[1] == A.shape[0] + assert A.shape == (B_.shape[0], B_.shape[0]) + assert C.shape == (D_.shape[0], B_.shape[0]) + + def test_missing_AD(self, xp): + B_, C_ = map(xp.asarray, (self.B, self.C)) + A, B, C, D = abcd_normalize(B=B_, C=C_) + assert A.shape[0] == A.shape[1] + assert A.shape[0] == B.shape[0] + assert D.shape[0] == C.shape[0] + assert D.shape[1] == B.shape[1] + assert A.shape == (B_.shape[0], B_.shape[0]) + assert D.shape == (C_.shape[0], B_.shape[1]) + + def test_missing_BC(self, xp): + A_, D_ = map(xp.asarray, (self.A, self.D)) + A, B, C, D = abcd_normalize(A=A_, D=D_) + assert B.shape[0] == A.shape[0] + assert B.shape[1] == D.shape[1] + assert C.shape[0] == D.shape[0] + assert C.shape[1] == A.shape[0] + assert B.shape == (A_.shape[0], D_.shape[1]) + assert C.shape == (D_.shape[0], A_.shape[0]) + + def test_missing_ABC_fails(self, xp): + assert_raises(ValueError, abcd_normalize, D=xp.asarray(self.D)) + + def test_missing_BD_fails(self, xp): + assert_raises(ValueError, abcd_normalize, A=xp.asarray(self.A), + C=xp.asarray(self.C)) + + def test_missing_CD_fails(self, xp): + assert_raises(ValueError, abcd_normalize, A=xp.asarray(self.A), + B=xp.asarray(self.B)) + + +class Test_bode: + + def test_01(self): + # Test bode() magnitude calculation (manual sanity check). + # 1st order low-pass filter: H(s) = 1 / (s + 1), + # cutoff: 1 rad/s, slope: -20 dB/decade + # H(s=0.1) ~= 0 dB + # H(s=1) ~= -3 dB + # H(s=10) ~= -20 dB + # H(s=100) ~= -40 dB + system = lti([1], [1, 1]) + w = [0.1, 1, 10, 100] + w, mag, phase = bode(system, w=w) + expected_mag = [0, -3, -20, -40] + assert_almost_equal(mag, expected_mag, decimal=1) + + def test_02(self): + # Test bode() phase calculation (manual sanity check). + # 1st order low-pass filter: H(s) = 1 / (s + 1), + # angle(H(s=0.1)) ~= -5.7 deg + # angle(H(s=1)) ~= -45 deg + # angle(H(s=10)) ~= -84.3 deg + system = lti([1], [1, 1]) + w = [0.1, 1, 10] + w, mag, phase = bode(system, w=w) + expected_phase = [-5.7, -45, -84.3] + assert_almost_equal(phase, expected_phase, decimal=1) + + def test_03(self): + # Test bode() magnitude calculation. + # 1st order low-pass filter: H(s) = 1 / (s + 1) + system = lti([1], [1, 1]) + w = [0.1, 1, 10, 100] + w, mag, phase = bode(system, w=w) + jw = w * 1j + y = np.polyval(system.num, jw) / np.polyval(system.den, jw) + expected_mag = 20.0 * np.log10(abs(y)) + assert_almost_equal(mag, expected_mag) + + def test_04(self): + # Test bode() phase calculation. + # 1st order low-pass filter: H(s) = 1 / (s + 1) + system = lti([1], [1, 1]) + w = [0.1, 1, 10, 100] + w, mag, phase = bode(system, w=w) + jw = w * 1j + y = np.polyval(system.num, jw) / np.polyval(system.den, jw) + expected_phase = np.arctan2(y.imag, y.real) * 180.0 / np.pi + assert_almost_equal(phase, expected_phase) + + def test_05(self): + # Test that bode() finds a reasonable frequency range. + # 1st order low-pass filter: H(s) = 1 / (s + 1) + system = lti([1], [1, 1]) + n = 10 + # Expected range is from 0.01 to 10. + expected_w = np.logspace(-2, 1, n) + w, mag, phase = bode(system, n=n) + assert_almost_equal(w, expected_w) + + def test_06(self): + # Test that bode() doesn't fail on a system with a pole at 0. + # integrator, pole at zero: H(s) = 1 / s + system = lti([1], [1, 0]) + w, mag, phase = bode(system, n=2) + assert w[0] == 0.01 # a fail would give not-a-number + + def test_07(self): + # bode() should not fail on a system with pure imaginary poles. + # The test passes if bode doesn't raise an exception. + system = lti([1], [1, 0, 100]) + w, mag, phase = bode(system, n=2) + + def test_08(self): + # Test that bode() return continuous phase, issues/2331. + system = lti([], [-10, -30, -40, -60, -70], 1) + w, mag, phase = system.bode(w=np.logspace(-3, 40, 100)) + assert_almost_equal(min(phase), -450, decimal=15) + + def test_from_state_space(self): + # Ensure that bode works with a system that was created from the + # state space representation matrices A, B, C, D. In this case, + # system.num will be a 2-D array with shape (1, n+1), where (n,n) + # is the shape of A. + # A Butterworth lowpass filter is used, so we know the exact + # frequency response. + a = np.array([1.0, 2.0, 2.0, 1.0]) + A = linalg.companion(a).T + B = np.array([[0.0], [0.0], [1.0]]) + C = np.array([[1.0, 0.0, 0.0]]) + D = np.array([[0.0]]) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", BadCoefficients) + system = lti(A, B, C, D) + w, mag, phase = bode(system, n=100) + + expected_magnitude = 20 * np.log10(np.sqrt(1.0 / (1.0 + w**6))) + assert_almost_equal(mag, expected_magnitude) + + +class Test_freqresp: + + def test_output_manual(self): + # Test freqresp() output calculation (manual sanity check). + # 1st order low-pass filter: H(s) = 1 / (s + 1), + # re(H(s=0.1)) ~= 0.99 + # re(H(s=1)) ~= 0.5 + # re(H(s=10)) ~= 0.0099 + system = lti([1], [1, 1]) + w = [0.1, 1, 10] + w, H = freqresp(system, w=w) + expected_re = [0.99, 0.5, 0.0099] + expected_im = [-0.099, -0.5, -0.099] + assert_almost_equal(H.real, expected_re, decimal=1) + assert_almost_equal(H.imag, expected_im, decimal=1) + + def test_output(self): + # Test freqresp() output calculation. + # 1st order low-pass filter: H(s) = 1 / (s + 1) + system = lti([1], [1, 1]) + w = [0.1, 1, 10, 100] + w, H = freqresp(system, w=w) + s = w * 1j + expected = np.polyval(system.num, s) / np.polyval(system.den, s) + assert_almost_equal(H.real, expected.real) + assert_almost_equal(H.imag, expected.imag) + + def test_freq_range(self): + # Test that freqresp() finds a reasonable frequency range. + # 1st order low-pass filter: H(s) = 1 / (s + 1) + # Expected range is from 0.01 to 10. + system = lti([1], [1, 1]) + n = 10 + expected_w = np.logspace(-2, 1, n) + w, H = freqresp(system, n=n) + assert_almost_equal(w, expected_w) + + def test_pole_zero(self): + # Test that freqresp() doesn't fail on a system with a pole at 0. + # integrator, pole at zero: H(s) = 1 / s + system = lti([1], [1, 0]) + w, H = freqresp(system, n=2) + assert w[0] == 0.01 # a fail would give not-a-number + + def test_from_state_space(self): + # Ensure that freqresp works with a system that was created from the + # state space representation matrices A, B, C, D. In this case, + # system.num will be a 2-D array with shape (1, n+1), where (n,n) is + # the shape of A. + # A Butterworth lowpass filter is used, so we know the exact + # frequency response. + a = np.array([1.0, 2.0, 2.0, 1.0]) + A = linalg.companion(a).T + B = np.array([[0.0],[0.0],[1.0]]) + C = np.array([[1.0, 0.0, 0.0]]) + D = np.array([[0.0]]) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", BadCoefficients) + system = lti(A, B, C, D) + w, H = freqresp(system, n=100) + s = w * 1j + expected = (1.0 / (1.0 + 2*s + 2*s**2 + s**3)) + assert_almost_equal(H.real, expected.real) + assert_almost_equal(H.imag, expected.imag) + + def test_from_zpk(self): + # 4th order low-pass filter: H(s) = 1 / (s + 1) + system = lti([],[-1]*4,[1]) + w = [0.1, 1, 10, 100] + w, H = freqresp(system, w=w) + s = w * 1j + expected = 1 / (s + 1)**4 + assert_almost_equal(H.real, expected.real) + assert_almost_equal(H.imag, expected.imag) + +@pytest.mark.parametrize( + "cls", [StateSpace, TransferFunction, ZerosPolesGain, lti, dlti] +) +def test_subscriptable_generic_types(cls): + assert isinstance(cls[np.float64], GenericAlias) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_max_len_seq.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_max_len_seq.py new file mode 100644 index 0000000000000000000000000000000000000000..7610b3f898571d10d75a64f00d900168c7142fbe --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_max_len_seq.py @@ -0,0 +1,71 @@ +import numpy as np +from pytest import raises as assert_raises +from scipy._lib._array_api import xp_assert_close, xp_assert_equal + +from numpy.fft import fft, ifft + +from scipy.signal import max_len_seq + + +class TestMLS: + + def test_mls_inputs(self): + # can't all be zero state + assert_raises(ValueError, max_len_seq, + 10, state=np.zeros(10)) + # wrong size state + assert_raises(ValueError, max_len_seq, 10, + state=np.ones(3)) + # wrong length + assert_raises(ValueError, max_len_seq, 10, length=-1) + xp_assert_equal(max_len_seq(10, length=0)[0], + np.asarray([], dtype=np.int8) + ) + # unknown taps + assert_raises(ValueError, max_len_seq, 64) + # bad taps + assert_raises(ValueError, max_len_seq, 10, taps=[-1, 1]) + + def test_mls_output(self): + # define some alternate working taps + alt_taps = {2: [1], 3: [2], 4: [3], 5: [4, 3, 2], 6: [5, 4, 1], 7: [4], + 8: [7, 5, 3]} + # assume the other bit levels work, too slow to test higher orders... + for nbits in range(2, 8): + for state in [None, np.round(np.random.rand(nbits))]: + for taps in [None, alt_taps[nbits]]: + if state is not None and np.all(state == 0): + state[0] = 1 # they can't all be zero + orig_m = max_len_seq(nbits, state=state, + taps=taps)[0] + m = 2. * orig_m - 1. # convert to +/- 1 representation + # First, make sure we got all 1's or -1 + err_msg = "mls had non binary terms" + xp_assert_equal(np.abs(m), np.ones_like(m), + err_msg=err_msg) + # Test via circular cross-correlation, which is just mult. + # in the frequency domain with one signal conjugated + tester = np.real(ifft(fft(m) * np.conj(fft(m)))) + out_len = 2**nbits - 1 + # impulse amplitude == test_len + err_msg = "mls impulse has incorrect value" + xp_assert_close(tester[0], + float(out_len), + err_msg=err_msg + ) + # steady-state is -1 + err_msg = "mls steady-state has incorrect value" + xp_assert_close(tester[1:], + np.full(out_len - 1, -1, dtype=tester.dtype), + err_msg=err_msg) + # let's do the split thing using a couple options + for n in (1, 2**(nbits - 1)): + m1, s1 = max_len_seq(nbits, state=state, taps=taps, + length=n) + m2, s2 = max_len_seq(nbits, state=s1, taps=taps, + length=1) + m3, s3 = max_len_seq(nbits, state=s2, taps=taps, + length=out_len - n - 1) + new_m = np.concatenate((m1, m2, m3)) + xp_assert_equal(orig_m, new_m) + diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_peak_finding.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_peak_finding.py new file mode 100644 index 0000000000000000000000000000000000000000..8118c505e83f51417fa895056fcd799011cd98df --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_peak_finding.py @@ -0,0 +1,913 @@ +import copy + +import numpy as np +import pytest +from pytest import raises, warns +from scipy._lib._array_api import xp_assert_close, xp_assert_equal + +from scipy.signal._peak_finding import ( + argrelmax, + argrelmin, + peak_prominences, + peak_widths, + _unpack_condition_args, + find_peaks, + find_peaks_cwt, + _identify_ridge_lines +) +from scipy.signal.windows import gaussian +from scipy.signal._peak_finding_utils import _local_maxima_1d, PeakPropertyWarning + + +def _gen_gaussians(center_locs, sigmas, total_length): + xdata = np.arange(0, total_length).astype(float) + out_data = np.zeros(total_length, dtype=float) + for ind, sigma in enumerate(sigmas): + tmp = (xdata - center_locs[ind]) / sigma + out_data += np.exp(-(tmp**2)) + return out_data + + +def _gen_gaussians_even(sigmas, total_length): + num_peaks = len(sigmas) + delta = total_length / (num_peaks + 1) + center_locs = np.linspace(delta, total_length - delta, num=num_peaks).astype(int) + out_data = _gen_gaussians(center_locs, sigmas, total_length) + return out_data, center_locs + + +def _gen_ridge_line(start_locs, max_locs, length, distances, gaps): + """ + Generate coordinates for a ridge line. + + Will be a series of coordinates, starting a start_loc (length 2). + The maximum distance between any adjacent columns will be + `max_distance`, the max distance between adjacent rows + will be `map_gap'. + + `max_locs` should be the size of the intended matrix. The + ending coordinates are guaranteed to be less than `max_locs`, + although they may not approach `max_locs` at all. + """ + + def keep_bounds(num, max_val): + out = max(num, 0) + out = min(out, max_val) + return out + + gaps = copy.deepcopy(gaps) + distances = copy.deepcopy(distances) + + locs = np.zeros([length, 2], dtype=int) + locs[0, :] = start_locs + total_length = max_locs[0] - start_locs[0] - sum(gaps) + if total_length < length: + raise ValueError('Cannot generate ridge line according to constraints') + dist_int = length / len(distances) - 1 + gap_int = length / len(gaps) - 1 + for ind in range(1, length): + nextcol = locs[ind - 1, 1] + nextrow = locs[ind - 1, 0] + 1 + if (ind % dist_int == 0) and (len(distances) > 0): + nextcol += ((-1)**ind)*distances.pop() + if (ind % gap_int == 0) and (len(gaps) > 0): + nextrow += gaps.pop() + nextrow = keep_bounds(nextrow, max_locs[0]) + nextcol = keep_bounds(nextcol, max_locs[1]) + locs[ind, :] = [nextrow, nextcol] + + return [locs[:, 0], locs[:, 1]] + + +class TestLocalMaxima1d: + + def test_empty(self): + """Test with empty signal.""" + x = np.array([], dtype=np.float64) + for array in _local_maxima_1d(x): + xp_assert_equal(array, np.array([]), check_dtype=False) + assert array.base is None + + def test_linear(self): + """Test with linear signal.""" + x = np.linspace(0, 100) + for array in _local_maxima_1d(x): + xp_assert_equal(array, np.array([], dtype=np.intp)) + assert array.base is None + + def test_simple(self): + """Test with simple signal.""" + x = np.linspace(-10, 10, 50) + x[2::3] += 1 + expected = np.arange(2, 50, 3, dtype=np.intp) + for array in _local_maxima_1d(x): + # For plateaus of size 1, the edges are identical with the + # midpoints + xp_assert_equal(array, expected, check_dtype=False) + assert array.base is None + + def test_flat_maxima(self): + """Test if flat maxima are detected correctly.""" + x = np.array([-1.3, 0, 1, 0, 2, 2, 0, 3, 3, 3, 2.99, 4, 4, 4, 4, -10, + -5, -5, -5, -5, -5, -10]) + midpoints, left_edges, right_edges = _local_maxima_1d(x) + xp_assert_equal(midpoints, np.array([2, 4, 8, 12, 18]), check_dtype=False) + xp_assert_equal(left_edges, np.array([2, 4, 7, 11, 16]), check_dtype=False) + xp_assert_equal(right_edges, np.array([2, 5, 9, 14, 20]), check_dtype=False) + + @pytest.mark.parametrize('x', [ + np.array([1., 0, 2]), + np.array([3., 3, 0, 4, 4]), + np.array([5., 5, 5, 0, 6, 6, 6]), + ]) + def test_signal_edges(self, x): + """Test if behavior on signal edges is correct.""" + for array in _local_maxima_1d(x): + xp_assert_equal(array, np.array([], dtype=np.intp)) + assert array.base is None + + def test_exceptions(self): + """Test input validation and raised exceptions.""" + with raises(ValueError, match="wrong number of dimensions"): + _local_maxima_1d(np.ones((1, 1))) + with raises(ValueError, match="expected 'const float64_t'"): + _local_maxima_1d(np.ones(1, dtype=int)) + with raises(TypeError, match="list"): + _local_maxima_1d([1., 2.]) + with raises(TypeError, match="'x' must not be None"): + _local_maxima_1d(None) + + +class TestRidgeLines: + + def test_empty(self): + test_matr = np.zeros([20, 100]) + lines = _identify_ridge_lines(test_matr, np.full(20, 2), 1) + assert len(lines) == 0 + + def test_minimal(self): + test_matr = np.zeros([20, 100]) + test_matr[0, 10] = 1 + lines = _identify_ridge_lines(test_matr, np.full(20, 2), 1) + assert len(lines) == 1 + + test_matr = np.zeros([20, 100]) + test_matr[0:2, 10] = 1 + lines = _identify_ridge_lines(test_matr, np.full(20, 2), 1) + assert len(lines) == 1 + + def test_single_pass(self): + distances = [0, 1, 2, 5] + gaps = [0, 1, 2, 0, 1] + test_matr = np.zeros([20, 50]) + 1e-12 + length = 12 + line = _gen_ridge_line([0, 25], test_matr.shape, length, distances, gaps) + test_matr[line[0], line[1]] = 1 + max_distances = np.full(20, max(distances)) + identified_lines = _identify_ridge_lines(test_matr, + max_distances, + max(gaps) + 1) + assert len(identified_lines) == 1 + for iline_, line_ in zip(identified_lines[0], line): + xp_assert_equal(iline_, line_, check_dtype=False) + + def test_single_bigdist(self): + distances = [0, 1, 2, 5] + gaps = [0, 1, 2, 4] + test_matr = np.zeros([20, 50]) + length = 12 + line = _gen_ridge_line([0, 25], test_matr.shape, length, distances, gaps) + test_matr[line[0], line[1]] = 1 + max_dist = 3 + max_distances = np.full(20, max_dist) + #This should get 2 lines, since the distance is too large + identified_lines = _identify_ridge_lines(test_matr, + max_distances, + max(gaps) + 1) + assert len(identified_lines) == 2 + + for iline in identified_lines: + adists = np.diff(iline[1]) + np.testing.assert_array_less(np.abs(adists), max_dist) + + agaps = np.diff(iline[0]) + np.testing.assert_array_less(np.abs(agaps), max(gaps) + 0.1) + + def test_single_biggap(self): + distances = [0, 1, 2, 5] + max_gap = 3 + gaps = [0, 4, 2, 1] + test_matr = np.zeros([20, 50]) + length = 12 + line = _gen_ridge_line([0, 25], test_matr.shape, length, distances, gaps) + test_matr[line[0], line[1]] = 1 + max_dist = 6 + max_distances = np.full(20, max_dist) + #This should get 2 lines, since the gap is too large + identified_lines = _identify_ridge_lines(test_matr, max_distances, max_gap) + assert len(identified_lines) == 2 + + for iline in identified_lines: + adists = np.diff(iline[1]) + np.testing.assert_array_less(np.abs(adists), max_dist) + + agaps = np.diff(iline[0]) + np.testing.assert_array_less(np.abs(agaps), max(gaps) + 0.1) + + def test_single_biggaps(self): + distances = [0] + max_gap = 1 + gaps = [3, 6] + test_matr = np.zeros([50, 50]) + length = 30 + line = _gen_ridge_line([0, 25], test_matr.shape, length, distances, gaps) + test_matr[line[0], line[1]] = 1 + max_dist = 1 + max_distances = np.full(50, max_dist) + #This should get 3 lines, since the gaps are too large + identified_lines = _identify_ridge_lines(test_matr, max_distances, max_gap) + assert len(identified_lines) == 3 + + for iline in identified_lines: + adists = np.diff(iline[1]) + np.testing.assert_array_less(np.abs(adists), max_dist) + + agaps = np.diff(iline[0]) + np.testing.assert_array_less(np.abs(agaps), max(gaps) + 0.1) + + +class TestArgrel: + + def test_empty(self): + # Regression test for gh-2832. + # When there are no relative extrema, make sure that + # the number of empty arrays returned matches the + # dimension of the input. + + empty_array = np.array([], dtype=int) + + z1 = np.zeros(5) + + i = argrelmin(z1) + xp_assert_equal(len(i), 1) + xp_assert_equal(i[0], empty_array, check_dtype=False) + + z2 = np.zeros((3, 5)) + + row, col = argrelmin(z2, axis=0) + xp_assert_equal(row, empty_array, check_dtype=False) + xp_assert_equal(col, empty_array, check_dtype=False) + + row, col = argrelmin(z2, axis=1) + xp_assert_equal(row, empty_array, check_dtype=False) + xp_assert_equal(col, empty_array, check_dtype=False) + + def test_basic(self): + # Note: the docstrings for the argrel{min,max,extrema} functions + # do not give a guarantee of the order of the indices, so we'll + # sort them before testing. + + x = np.array([[1, 2, 2, 3, 2], + [2, 1, 2, 2, 3], + [3, 2, 1, 2, 2], + [2, 3, 2, 1, 2], + [1, 2, 3, 2, 1]]) + + row, col = argrelmax(x, axis=0) + order = np.argsort(row) + xp_assert_equal(row[order], [1, 2, 3], check_dtype=False) + xp_assert_equal(col[order], [4, 0, 1], check_dtype=False) + + row, col = argrelmax(x, axis=1) + order = np.argsort(row) + xp_assert_equal(row[order], [0, 3, 4], check_dtype=False) + xp_assert_equal(col[order], [3, 1, 2], check_dtype=False) + + row, col = argrelmin(x, axis=0) + order = np.argsort(row) + xp_assert_equal(row[order], [1, 2, 3], check_dtype=False) + xp_assert_equal(col[order], [1, 2, 3], check_dtype=False) + + row, col = argrelmin(x, axis=1) + order = np.argsort(row) + xp_assert_equal(row[order], [1, 2, 3], check_dtype=False) + xp_assert_equal(col[order], [1, 2, 3], check_dtype=False) + + def test_highorder(self): + order = 2 + sigmas = [1.0, 2.0, 10.0, 5.0, 15.0] + test_data, act_locs = _gen_gaussians_even(sigmas, 500) + test_data[act_locs + order] = test_data[act_locs]*0.99999 + test_data[act_locs - order] = test_data[act_locs]*0.99999 + rel_max_locs = argrelmax(test_data, order=order, mode='clip')[0] + + assert len(rel_max_locs) == len(act_locs) + assert (rel_max_locs == act_locs).all() + + def test_2d_gaussians(self): + sigmas = [1.0, 2.0, 10.0] + test_data, act_locs = _gen_gaussians_even(sigmas, 100) + rot_factor = 20 + rot_range = np.arange(0, len(test_data)) - rot_factor + test_data_2 = np.vstack([test_data, test_data[rot_range]]) + rel_max_rows, rel_max_cols = argrelmax(test_data_2, axis=1, order=1) + + for rw in range(0, test_data_2.shape[0]): + inds = (rel_max_rows == rw) + + assert len(rel_max_cols[inds]) == len(act_locs) + assert (act_locs == (rel_max_cols[inds] - rot_factor*rw)).all() + + +class TestPeakProminences: + + def test_empty(self): + """ + Test if an empty array is returned if no peaks are provided. + """ + out = peak_prominences([1, 2, 3], []) + for arr, dtype in zip(out, [np.float64, np.intp, np.intp]): + assert arr.size == 0 + assert arr.dtype == dtype + + out = peak_prominences([], []) + for arr, dtype in zip(out, [np.float64, np.intp, np.intp]): + assert arr.size == 0 + assert arr.dtype == dtype + + def test_basic(self): + """ + Test if height of prominences is correctly calculated in signal with + rising baseline (peak widths are 1 sample). + """ + # Prepare basic signal + x = np.array([-1, 1.2, 1.2, 1, 3.2, 1.3, 2.88, 2.1]) + peaks = np.array([1, 2, 4, 6]) + lbases = np.array([0, 0, 0, 5]) + rbases = np.array([3, 3, 5, 7]) + proms = x[peaks] - np.max([x[lbases], x[rbases]], axis=0) + # Test if calculation matches handcrafted result + out = peak_prominences(x, peaks) + xp_assert_equal(out[0], proms, check_dtype=False) + xp_assert_equal(out[1], lbases, check_dtype=False) + xp_assert_equal(out[2], rbases, check_dtype=False) + + def test_edge_cases(self): + """ + Test edge cases. + """ + # Peaks have same height, prominence and bases + x = [0, 2, 1, 2, 1, 2, 0] + peaks = [1, 3, 5] + proms, lbases, rbases = peak_prominences(x, peaks) + xp_assert_equal(proms, np.asarray([2.0, 2, 2]), check_dtype=False) + xp_assert_equal(lbases, [0, 0, 0], check_dtype=False) + xp_assert_equal(rbases, [6, 6, 6], check_dtype=False) + + # Peaks have same height & prominence but different bases + x = [0, 1, 0, 1, 0, 1, 0] + peaks = np.array([1, 3, 5]) + proms, lbases, rbases = peak_prominences(x, peaks) + xp_assert_equal(proms, np.asarray([1.0, 1, 1])) + xp_assert_equal(lbases, peaks - 1, check_dtype=False) + xp_assert_equal(rbases, peaks + 1, check_dtype=False) + + def test_non_contiguous(self): + """ + Test with non-C-contiguous input arrays. + """ + x = np.repeat([-9, 9, 9, 0, 3, 1], 2) + peaks = np.repeat([1, 2, 4], 2) + proms, lbases, rbases = peak_prominences(x[::2], peaks[::2]) + xp_assert_equal(proms, np.asarray([9.0, 9, 2])) + xp_assert_equal(lbases, [0, 0, 3], check_dtype=False) + xp_assert_equal(rbases, [3, 3, 5], check_dtype=False) + + def test_wlen(self): + """ + Test if wlen actually shrinks the evaluation range correctly. + """ + x = [0, 1, 2, 3, 1, 0, -1] + peak = [3] + # Test rounding behavior of wlen + proms = peak_prominences(x, peak) + for prom, val in zip(proms, [3.0, 0, 6]): + assert prom == val + + for wlen, i in [(8, 0), (7, 0), (6, 0), (5, 1), (3.2, 1), (3, 2), (1.1, 2)]: + proms = peak_prominences(x, peak, wlen) + for prom, val in zip(proms, [3. - i, 0 + i, 6 - i]): + assert prom == val + + def test_exceptions(self): + """ + Verify that exceptions and warnings are raised. + """ + # x with dimension > 1 + with raises(ValueError, match='1-D array'): + peak_prominences([[0, 1, 1, 0]], [1, 2]) + # peaks with dimension > 1 + with raises(ValueError, match='1-D array'): + peak_prominences([0, 1, 1, 0], [[1, 2]]) + # x with dimension < 1 + with raises(ValueError, match='1-D array'): + peak_prominences(3, [0,]) + + # empty x with supplied + with raises(ValueError, match='not a valid index'): + peak_prominences([], [0]) + # invalid indices with non-empty x + for p in [-100, -1, 3, 1000]: + with raises(ValueError, match='not a valid index'): + peak_prominences([1, 0, 2], [p]) + + # peaks is not cast-able to np.intp + with raises(TypeError, match='cannot safely cast'): + peak_prominences([0, 1, 1, 0], [1.1, 2.3]) + + # wlen < 3 + with raises(ValueError, match='wlen'): + peak_prominences(np.arange(10), [3, 5], wlen=1) + + def test_warnings(self): + """ + Verify that appropriate warnings are raised. + """ + msg = "some peaks have a prominence of 0" + for p in [0, 1, 2]: + with warns(PeakPropertyWarning, match=msg): + peak_prominences([1, 0, 2], [p,]) + with warns(PeakPropertyWarning, match=msg): + peak_prominences([0, 1, 1, 1, 0], [2], wlen=2) + + +class TestPeakWidths: + + def test_empty(self): + """ + Test if an empty array is returned if no peaks are provided. + """ + widths = peak_widths([], [])[0] + assert isinstance(widths, np.ndarray) + assert widths.size == 0 + widths = peak_widths([1, 2, 3], [])[0] + assert isinstance(widths, np.ndarray) + assert widths.size == 0 + out = peak_widths([], []) + for arr in out: + assert isinstance(arr, np.ndarray) + assert arr.size == 0 + + @pytest.mark.filterwarnings("ignore:some peaks have a width of 0") + def test_basic(self): + """ + Test a simple use case with easy to verify results at different relative + heights. + """ + x = np.array([1, 0, 1, 2, 1, 0, -1]) + prominence = 2 + for rel_height, width_true, lip_true, rip_true in [ + (0., 0., 3., 3.), # raises warning + (0.25, 1., 2.5, 3.5), + (0.5, 2., 2., 4.), + (0.75, 3., 1.5, 4.5), + (1., 4., 1., 5.), + (2., 5., 1., 6.), + (3., 5., 1., 6.) + ]: + width_calc, height, lip_calc, rip_calc = peak_widths( + x, [3], rel_height) + xp_assert_close(width_calc, np.asarray([width_true])) + xp_assert_close(height, np.asarray([2 - rel_height * prominence])) + xp_assert_close(lip_calc, np.asarray([lip_true])) + xp_assert_close(rip_calc, np.asarray([rip_true])) + + def test_non_contiguous(self): + """ + Test with non-C-contiguous input arrays. + """ + x = np.repeat([0, 100, 50], 4) + peaks = np.repeat([1], 3) + result = peak_widths(x[::4], peaks[::3]) + xp_assert_equal(result, + np.asarray([[0.75], [75], [0.75], [1.5]]) + ) + + def test_exceptions(self): + """ + Verify that argument validation works as intended. + """ + with raises(ValueError, match='1-D array'): + # x with dimension > 1 + peak_widths(np.zeros((3, 4)), np.ones(3)) + with raises(ValueError, match='1-D array'): + # x with dimension < 1 + peak_widths(3, [0]) + with raises(ValueError, match='1-D array'): + # peaks with dimension > 1 + peak_widths(np.arange(10), np.ones((3, 2), dtype=np.intp)) + with raises(ValueError, match='1-D array'): + # peaks with dimension < 1 + peak_widths(np.arange(10), 3) + with raises(ValueError, match='not a valid index'): + # peak pos exceeds x.size + peak_widths(np.arange(10), [8, 11]) + with raises(ValueError, match='not a valid index'): + # empty x with peaks supplied + peak_widths([], [1, 2]) + with raises(TypeError, match='cannot safely cast'): + # peak cannot be safely cast to intp + peak_widths(np.arange(10), [1.1, 2.3]) + with raises(ValueError, match='rel_height'): + # rel_height is < 0 + peak_widths([0, 1, 0, 1, 0], [1, 3], rel_height=-1) + with raises(TypeError, match='None'): + # prominence data contains None + peak_widths([1, 2, 1], [1], prominence_data=(None, None, None)) + + def test_warnings(self): + """ + Verify that appropriate warnings are raised. + """ + msg = "some peaks have a width of 0" + with warns(PeakPropertyWarning, match=msg): + # Case: rel_height is 0 + peak_widths([0, 1, 0], [1], rel_height=0) + with warns(PeakPropertyWarning, match=msg): + # Case: prominence is 0 and bases are identical + peak_widths( + [0, 1, 1, 1, 0], [2], + prominence_data=(np.array([0.], np.float64), + np.array([2], np.intp), + np.array([2], np.intp)) + ) + + def test_mismatching_prominence_data(self): + """Test with mismatching peak and / or prominence data.""" + x = [0, 1, 0] + peak = [1] + for i, (prominences, left_bases, right_bases) in enumerate([ + ((1.,), (-1,), (2,)), # left base not in x + ((1.,), (0,), (3,)), # right base not in x + ((1.,), (2,), (0,)), # swapped bases same as peak + ((1., 1.), (0, 0), (2, 2)), # array shapes don't match peaks + ((1., 1.), (0,), (2,)), # arrays with different shapes + ((1.,), (0, 0), (2,)), # arrays with different shapes + ((1.,), (0,), (2, 2)) # arrays with different shapes + ]): + # Make sure input is matches output of signal.peak_prominences + prominence_data = (np.array(prominences, dtype=np.float64), + np.array(left_bases, dtype=np.intp), + np.array(right_bases, dtype=np.intp)) + # Test for correct exception + if i < 3: + match = "prominence data is invalid for peak" + else: + match = "arrays in `prominence_data` must have the same shape" + with raises(ValueError, match=match): + peak_widths(x, peak, prominence_data=prominence_data) + + @pytest.mark.filterwarnings("ignore:some peaks have a width of 0") + def test_intersection_rules(self): + """Test if x == eval_height counts as an intersection.""" + # Flatt peak with two possible intersection points if evaluated at 1 + x = [0, 1, 2, 1, 3, 3, 3, 1, 2, 1, 0] + # relative height is 0 -> width is 0 as well, raises warning + xp_assert_close(peak_widths(x, peaks=[5], rel_height=0), + [(0.,), (3.,), (5.,), (5.,)]) + # width_height == x counts as intersection -> nearest 1 is chosen + xp_assert_close(peak_widths(x, peaks=[5], rel_height=2/3), + [(4.,), (1.,), (3.,), (7.,)]) + + +def test_unpack_condition_args(): + """ + Verify parsing of condition arguments for `scipy.signal.find_peaks` function. + """ + x = np.arange(10) + amin_true = x + amax_true = amin_true + 10 + peaks = amin_true[1::2] + + # Test unpacking with None or interval + assert (None, None) == _unpack_condition_args((None, None), x, peaks) + assert (1, None) == _unpack_condition_args(1, x, peaks) + assert (1, None) == _unpack_condition_args((1, None), x, peaks) + assert (None, 2) == _unpack_condition_args((None, 2), x, peaks) + assert (3., 4.5) == _unpack_condition_args((3., 4.5), x, peaks) + + # Test if borders are correctly reduced with `peaks` + amin_calc, amax_calc = _unpack_condition_args((amin_true, amax_true), x, peaks) + xp_assert_equal(amin_calc, amin_true[peaks]) + xp_assert_equal(amax_calc, amax_true[peaks]) + + # Test raises if array borders don't match x + with raises(ValueError, match="array size of lower"): + _unpack_condition_args(amin_true, np.arange(11), peaks) + with raises(ValueError, match="array size of upper"): + _unpack_condition_args((None, amin_true), np.arange(11), peaks) + + +class TestFindPeaks: + + # Keys of optionally returned properties + property_keys = {'peak_heights', 'left_thresholds', 'right_thresholds', + 'prominences', 'left_bases', 'right_bases', 'widths', + 'width_heights', 'left_ips', 'right_ips'} + + def test_constant(self): + """ + Test behavior for signal without local maxima. + """ + open_interval = (None, None) + peaks, props = find_peaks(np.ones(10), + height=open_interval, threshold=open_interval, + prominence=open_interval, width=open_interval) + assert peaks.size == 0 + for key in self.property_keys: + assert props[key].size == 0 + + def test_plateau_size(self): + """ + Test plateau size condition for peaks. + """ + # Prepare signal with peaks with peak_height == plateau_size + plateau_sizes = np.array([1, 2, 3, 4, 8, 20, 111]) + x = np.zeros(plateau_sizes.size * 2 + 1) + x[1::2] = plateau_sizes + repeats = np.ones(x.size, dtype=int) + repeats[1::2] = x[1::2] + x = np.repeat(x, repeats) + + # Test full output + peaks, props = find_peaks(x, plateau_size=(None, None)) + xp_assert_equal(peaks, [1, 3, 7, 11, 18, 33, 100], check_dtype=False) + xp_assert_equal(props["plateau_sizes"], plateau_sizes, check_dtype=False) + xp_assert_equal(props["left_edges"], peaks - (plateau_sizes - 1) // 2, + check_dtype=False) + xp_assert_equal(props["right_edges"], peaks + plateau_sizes // 2, + check_dtype=False) + + # Test conditions + xp_assert_equal(find_peaks(x, plateau_size=4)[0], [11, 18, 33, 100], + check_dtype=False) + xp_assert_equal(find_peaks(x, plateau_size=(None, 3.5))[0], [1, 3, 7], + check_dtype=False) + xp_assert_equal(find_peaks(x, plateau_size=(5, 50))[0], [18, 33], + check_dtype=False) + + def test_height_condition(self): + """ + Test height condition for peaks. + """ + x = (0., 1/3, 0., 2.5, 0, 4., 0) + peaks, props = find_peaks(x, height=(None, None)) + xp_assert_equal(peaks, np.array([1, 3, 5]), check_dtype=False) + xp_assert_equal(props['peak_heights'], np.array([1/3, 2.5, 4.]), + check_dtype=False) + xp_assert_equal(find_peaks(x, height=0.5)[0], np.array([3, 5]), + check_dtype=False) + xp_assert_equal(find_peaks(x, height=(None, 3))[0], np.array([1, 3]), + check_dtype=False) + xp_assert_equal(find_peaks(x, height=(2, 3))[0], np.array([3]), + check_dtype=False) + + def test_threshold_condition(self): + """ + Test threshold condition for peaks. + """ + x = (0, 2, 1, 4, -1) + peaks, props = find_peaks(x, threshold=(None, None)) + xp_assert_equal(peaks, np.array([1, 3]), check_dtype=False) + xp_assert_equal(props['left_thresholds'], np.array([2.0, 3.0])) + xp_assert_equal(props['right_thresholds'], np.array([1.0, 5.0])) + xp_assert_equal(find_peaks(x, threshold=2)[0], np.array([3]), + check_dtype=False) + xp_assert_equal(find_peaks(x, threshold=3.5)[0], np.array([], dtype=int), + check_dtype=False) + xp_assert_equal(find_peaks(x, threshold=(None, 5))[0], np.array([1, 3]), + check_dtype=False) + xp_assert_equal(find_peaks(x, threshold=(None, 4))[0], np.array([1]), + check_dtype=False) + xp_assert_equal(find_peaks(x, threshold=(2, 4))[0], np.array([], dtype=int), + check_dtype=False) + + def test_distance_condition(self): + """ + Test distance condition for peaks. + """ + # Peaks of different height with constant distance 3 + peaks_all = np.arange(1, 21, 3) + x = np.zeros(21) + x[peaks_all] += np.linspace(1, 2, peaks_all.size) + + # Test if peaks with "minimal" distance are still selected (distance = 3) + xp_assert_equal(find_peaks(x, distance=3)[0], peaks_all, check_dtype=False) + + # Select every second peak (distance > 3) + peaks_subset = find_peaks(x, distance=3.0001)[0] + # Test if peaks_subset is subset of peaks_all + assert np.setdiff1d(peaks_subset, peaks_all, assume_unique=True).size == 0 + + # Test if every second peak was removed + dfs = np.diff(peaks_subset) + xp_assert_equal(dfs, 6*np.ones_like(dfs)) + + # Test priority of peak removal + x = [-2, 1, -1, 0, -3] + peaks_subset = find_peaks(x, distance=10)[0] # use distance > x size + assert peaks_subset.size == 1 and peaks_subset[0] == 1 + + def test_prominence_condition(self): + """ + Test prominence condition for peaks. + """ + x = np.linspace(0, 10, 100) + peaks_true = np.arange(1, 99, 2) + offset = np.linspace(1, 10, peaks_true.size) + x[peaks_true] += offset + prominences = x[peaks_true] - x[peaks_true + 1] + interval = (3, 9) + keep = np.nonzero( + (interval[0] <= prominences) & (prominences <= interval[1])) + + peaks_calc, properties = find_peaks(x, prominence=interval) + xp_assert_equal(peaks_calc, peaks_true[keep], check_dtype=False) + xp_assert_equal(properties['prominences'], prominences[keep], check_dtype=False) + xp_assert_equal(properties['left_bases'], + np.zeros_like(properties['left_bases'])) + xp_assert_equal(properties['right_bases'], peaks_true[keep] + 1, + check_dtype=False) + + def test_width_condition(self): + """ + Test width condition for peaks. + """ + x = np.array([1, 0, 1, 2, 1, 0, -1, 4, 0]) + peaks, props = find_peaks(x, width=(None, 2), rel_height=0.75) + assert peaks.size == 1 + xp_assert_equal(peaks, 7*np.ones_like(peaks)) + xp_assert_close(props['widths'], np.asarray([1.35])) + xp_assert_close(props['width_heights'], np.asarray([1.])) + xp_assert_close(props['left_ips'], np.asarray([6.4])) + xp_assert_close(props['right_ips'], np.asarray([7.75])) + + def test_properties(self): + """ + Test returned properties. + """ + open_interval = (None, None) + x = [0, 1, 0, 2, 1.5, 0, 3, 0, 5, 9] + peaks, props = find_peaks(x, + height=open_interval, threshold=open_interval, + prominence=open_interval, width=open_interval) + assert len(props) == len(self.property_keys) + for key in self.property_keys: + assert peaks.size == props[key].size + + def test_raises(self): + """ + Test exceptions raised by function. + """ + with raises(ValueError, match="1-D array"): + find_peaks(np.array(1)) + with raises(ValueError, match="1-D array"): + find_peaks(np.ones((2, 2))) + with raises(ValueError, match="distance"): + find_peaks(np.arange(10), distance=-1) + + @pytest.mark.filterwarnings("ignore:some peaks have a prominence of 0", + "ignore:some peaks have a width of 0") + def test_wlen_smaller_plateau(self): + """ + Test behavior of prominence and width calculation if the given window + length is smaller than a peak's plateau size. + + Regression test for gh-9110. + """ + peaks, props = find_peaks([0, 1, 1, 1, 0], prominence=(None, None), + width=(None, None), wlen=2) + xp_assert_equal(peaks, 2 * np.ones_like(peaks)) + xp_assert_equal(props["prominences"], np.zeros_like(props["prominences"])) + xp_assert_equal(props["widths"], np.zeros_like(props["widths"])) + xp_assert_equal(props["width_heights"], np.ones_like(props["width_heights"])) + for key in ("left_bases", "right_bases", "left_ips", "right_ips"): + xp_assert_equal(props[key], peaks, check_dtype=False) + + @pytest.mark.parametrize("kwargs", [ + {}, + {"distance": 3.0}, + {"prominence": (None, None)}, + {"width": (None, 2)}, + + ]) + def test_readonly_array(self, kwargs): + """ + Test readonly arrays are accepted. + """ + x = np.linspace(0, 10, 15) + x_readonly = x.copy() + x_readonly.flags.writeable = False + + peaks, _ = find_peaks(x) + peaks_readonly, _ = find_peaks(x_readonly, **kwargs) + + xp_assert_close(peaks, peaks_readonly) + + +class TestFindPeaksCwt: + + def test_find_peaks_exact(self): + """ + Generate a series of gaussians and attempt to find the peak locations. + """ + sigmas = [5.0, 3.0, 10.0, 20.0, 10.0, 50.0] + num_points = 500 + test_data, act_locs = _gen_gaussians_even(sigmas, num_points) + widths = np.arange(0.1, max(sigmas)) + found_locs = find_peaks_cwt(test_data, widths, gap_thresh=2, min_snr=0, + min_length=None) + xp_assert_equal(found_locs, act_locs, + check_dtype=False, + err_msg="Found maximum locations did not equal those expected" + ) + + def test_find_peaks_withnoise(self): + """ + Verify that peak locations are (approximately) found + for a series of gaussians with added noise. + """ + sigmas = [5.0, 3.0, 10.0, 20.0, 10.0, 50.0] + num_points = 500 + test_data, act_locs = _gen_gaussians_even(sigmas, num_points) + widths = np.arange(0.1, max(sigmas)) + noise_amp = 0.07 + rng = np.random.default_rng(18181911) + test_data += (rng.random(num_points) - 0.5)*(2*noise_amp) + found_locs = find_peaks_cwt(test_data, widths, min_length=15, + gap_thresh=1, min_snr=noise_amp / 5) + + err_msg ='Different number of peaks found than expected' + assert len(found_locs) == len(act_locs), err_msg + diffs = np.abs(found_locs - act_locs) + max_diffs = np.array(sigmas) / 5 + np.testing.assert_array_less(diffs, max_diffs, 'Maximum location differed' + + f'by more than {max_diffs}') + + def test_find_peaks_nopeak(self): + """ + Verify that no peak is found in + data that's just noise. + """ + noise_amp = 1.0 + num_points = 100 + rng = np.random.RandomState(181819141) + test_data = (rng.rand(num_points) - 0.5)*(2*noise_amp) + widths = np.arange(10, 50) + found_locs = find_peaks_cwt(test_data, widths, min_snr=5, noise_perc=30) + assert len(found_locs) == 0 + + def test_find_peaks_with_non_default_wavelets(self): + x = gaussian(200, 2) + widths = np.array([1, 2, 3, 4]) + a = find_peaks_cwt(x, widths, wavelet=gaussian) + + xp_assert_equal(a, np.asarray([100]), check_dtype=False) + + def test_find_peaks_window_size(self): + """ + Verify that window_size is passed correctly to private function and + affects the result. + """ + sigmas = [2.0, 2.0] + num_points = 1000 + test_data, act_locs = _gen_gaussians_even(sigmas, num_points) + widths = np.arange(0.1, max(sigmas), 0.2) + noise_amp = 0.05 + rng = np.random.RandomState(18181911) + test_data += (rng.rand(num_points) - 0.5)*(2*noise_amp) + + # Possibly contrived negative region to throw off peak finding + # when window_size is too large + test_data[250:320] -= 1 + + found_locs = find_peaks_cwt(test_data, widths, gap_thresh=2, min_snr=3, + min_length=None, window_size=None) + with pytest.raises(AssertionError): + assert found_locs.size == act_locs.size + + found_locs = find_peaks_cwt(test_data, widths, gap_thresh=2, min_snr=3, + min_length=None, window_size=20) + assert found_locs.size == act_locs.size + + def test_find_peaks_with_one_width(self): + """ + Verify that the `width` argument + in `find_peaks_cwt` can be a float + """ + xs = np.arange(0, np.pi, 0.05) + test_data = np.sin(xs) + widths = 1 + found_locs = find_peaks_cwt(test_data, widths) + + np.testing.assert_equal(found_locs, 32) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_result_type.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_result_type.py new file mode 100644 index 0000000000000000000000000000000000000000..a2cadd325a7e36c877df8532ba957712831c2dad --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_result_type.py @@ -0,0 +1,51 @@ +# Regressions tests on result types of some signal functions + +import numpy as np + +from scipy.signal import (decimate, + lfilter_zi, + lfiltic, + sos2tf, + sosfilt_zi) + + +def test_decimate(): + ones_f32 = np.ones(32, dtype=np.float32) + assert decimate(ones_f32, 2).dtype == np.float32 + + ones_i64 = np.ones(32, dtype=np.int64) + assert decimate(ones_i64, 2).dtype == np.float64 + + +def test_lfilter_zi(): + b_f32 = np.array([1, 2, 3], dtype=np.float32) + a_f32 = np.array([4, 5, 6], dtype=np.float32) + assert lfilter_zi(b_f32, a_f32).dtype == np.float32 + + +def test_lfiltic(): + # this would return f32 when given a mix of f32 / f64 args + b_f32 = np.array([1, 2, 3], dtype=np.float32) + a_f32 = np.array([4, 5, 6], dtype=np.float32) + x_f32 = np.ones(32, dtype=np.float32) + + b_f64 = b_f32.astype(np.float64) + a_f64 = a_f32.astype(np.float64) + x_f64 = x_f32.astype(np.float64) + + assert lfiltic(b_f64, a_f32, x_f32).dtype == np.float64 + assert lfiltic(b_f32, a_f64, x_f32).dtype == np.float64 + assert lfiltic(b_f32, a_f32, x_f64).dtype == np.float64 + assert lfiltic(b_f32, a_f32, x_f32, x_f64).dtype == np.float64 + + +def test_sos2tf(): + sos_f32 = np.array([[4, 5, 6, 1, 2, 3]], dtype=np.float32) + b, a = sos2tf(sos_f32) + assert b.dtype == np.float32 + assert a.dtype == np.float32 + + +def test_sosfilt_zi(): + sos_f32 = np.array([[4, 5, 6, 1, 2, 3]], dtype=np.float32) + assert sosfilt_zi(sos_f32).dtype == np.float32 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_savitzky_golay.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_savitzky_golay.py new file mode 100644 index 0000000000000000000000000000000000000000..f819910c3dbea4e83e4dbb3d1db2189cf3fa1cc0 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_savitzky_golay.py @@ -0,0 +1,396 @@ +import pytest +import numpy as np + +from scipy._lib._array_api import ( + xp_assert_close, xp_assert_equal, xp_swapaxes, is_torch, make_xp_test_case, + _xp_copy_to_numpy +) + +from scipy.ndimage import convolve1d # type: ignore[attr-defined] + +from scipy.signal import savgol_coeffs, savgol_filter +from scipy.signal._savitzky_golay import _polyder + +skip_xp_backends = pytest.mark.skip_xp_backends +xfail_xp_backends = pytest.mark.xfail_xp_backends + +pytestmark = pytest.mark.skip_xp_backends( + "dask.array", reason="linalg.lstsq is missing rcond" +) + + +def check_polyder(p, m, expected, xp): + dp = _polyder(p, m, xp=xp) + xp_assert_equal(dp, expected) + + +def test_polyder(xp): + cases = [ + ([5], 0, [5]), + ([5], 1, [0]), + ([3, 2, 1], 0, [3, 2, 1]), + ([3, 2, 1], 1, [6, 2]), + ([3, 2, 1], 2, [6]), + ([3, 2, 1], 3, [0]), + ([[3, 2, 1], [5, 6, 7]], 0, [[3, 2, 1], [5, 6, 7]]), + ([[3, 2, 1], [5, 6, 7]], 1, [[6, 2], [10, 6]]), + ([[3, 2, 1], [5, 6, 7]], 2, [[6], [10]]), + ([[3, 2, 1], [5, 6, 7]], 3, [[0], [0]]), + ] + for p, m, expected in cases: + pp = xp.asarray(p) + ee = xp.asarray(expected) + check_polyder( + pp.T if pp.ndim == 2 else pp, + m, + ee.T if ee.ndim ==2 else ee, + xp + ) + + +#-------------------------------------------------------------------- +# savgol_coeffs tests +#-------------------------------------------------------------------- + +def alt_sg_coeffs(window_length, polyorder, pos, xp): + """This is an alternative implementation of the SG coefficients. + + It uses numpy.polyfit and numpy.polyval. The results should be + equivalent to those of savgol_coeffs(), but this implementation + is slower. + + window_length should be odd. + + """ + if pos is None: + pos = window_length // 2 + t = np.arange(window_length) + unit = (t == pos).astype(int) + h = np.polyval(np.polyfit(t, unit, polyorder), t) + return xp.asarray(h) + + +@make_xp_test_case(savgol_coeffs) +def test_sg_coeffs_trivial(xp): + # Test a trivial case of savgol_coeffs: polyorder = window_length - 1 + h = savgol_coeffs(1, 0, xp=xp) + xp_assert_close(h, xp.asarray([1.0], dtype=xp.float64)) + + h = savgol_coeffs(3, 2, xp=xp) + xp_assert_close(h, xp.asarray([0.0, 1, 0], dtype=xp.float64), atol=1e-10) + + h = savgol_coeffs(5, 4, xp=xp) + xp_assert_close(h, xp.asarray([0.0, 0, 1, 0, 0], dtype=xp.float64), atol=1e-10) + + h = savgol_coeffs(5, 4, pos=1, xp=xp) + xp_assert_close(h, xp.asarray([0.0, 0, 0, 1, 0], dtype=xp.float64), atol=1e-10) + + h = savgol_coeffs(5, 4, pos=1, use='dot', xp=xp) + xp_assert_close(h, xp.asarray([0.0, 1, 0, 0, 0], dtype=xp.float64), atol=1e-10) + + +def compare_coeffs_to_alt(window_length, order, xp): + # For the given window_length and order, compare the results + # of savgol_coeffs and alt_sg_coeffs for pos from 0 to window_length - 1. + # Also include pos=None. + for pos in [None] + list(range(window_length)): + h1 = savgol_coeffs(window_length, order, pos=pos, use='dot', xp=xp) + h2 = alt_sg_coeffs(window_length, order, pos=pos, xp=xp) + xp_assert_close( + h1, h2, atol=2e-10, + err_msg=f"window_length = {window_length}, order = {order}, pos = {pos}" + ) + + +@make_xp_test_case(savgol_coeffs) +def test_sg_coeffs_compare(xp): + # Compare savgol_coeffs() to alt_sg_coeffs(). + for window_length in range(1, 8, 2): + for order in range(window_length): + compare_coeffs_to_alt(window_length, order, xp=xp) + + +@make_xp_test_case(savgol_coeffs) +def test_sg_coeffs_exact(xp): + polyorder = 4 + window_length = 9 + halflen = window_length // 2 + + x = xp.linspace(0, 21, 43) + delta = x[1] - x[0] + + # The data is a cubic polynomial. We'll use an order 4 + # SG filter, so the filtered values should equal the input data + # (except within half window_length of the edges). + y = 0.5 * x ** 3 - x + h = savgol_coeffs(window_length, polyorder, xp=xp) + y0 = xp.asarray(convolve1d(_xp_copy_to_numpy(y), _xp_copy_to_numpy(h))) + xp_assert_close(y0[halflen:-halflen], y[halflen:-halflen]) + + # Check the same input, but use deriv=1. dy is the exact result. + dy = 1.5 * x ** 2 - 1 + h = savgol_coeffs(window_length, polyorder, deriv=1, delta=delta, xp=xp) + y1 = xp.asarray(convolve1d(_xp_copy_to_numpy(y), _xp_copy_to_numpy(h))) + xp_assert_close(y1[halflen:-halflen], dy[halflen:-halflen]) + + # Check the same input, but use deriv=2. d2y is the exact result. + d2y = 3.0 * x + h = savgol_coeffs(window_length, polyorder, deriv=2, delta=delta, xp=xp) + y2 = xp.asarray(convolve1d(_xp_copy_to_numpy(y), _xp_copy_to_numpy(h))) + xp_assert_close(y2[halflen:-halflen], d2y[halflen:-halflen]) + + +@make_xp_test_case(savgol_coeffs) +def test_sg_coeffs_deriv(xp): + # The data in `x` is a sampled parabola, so using savgol_coeffs with an + # order 2 or higher polynomial should give exact results. + i = xp.asarray([-2.0, 0.0, 2.0, 4.0, 6.0], dtype=xp.float64) + x = i ** 2 / 4 + dx = i / 2 + d2x = xp.full_like(i, 0.5) + for pos in range(x.shape[0]): + coeffs0 = savgol_coeffs(5, 3, pos=pos, delta=2.0, use='dot', xp=xp) + xp_assert_close(coeffs0 @ x, x[pos], atol=1e-10) + coeffs1 = savgol_coeffs(5, 3, pos=pos, delta=2.0, use='dot', deriv=1, xp=xp) + xp_assert_close(coeffs1 @ x, dx[pos], atol=1e-10) + coeffs2 = savgol_coeffs(5, 3, pos=pos, delta=2.0, use='dot', deriv=2, xp=xp) + xp_assert_close(coeffs2 @ x , d2x[pos], atol=1e-10) + + +@make_xp_test_case(savgol_coeffs) +def test_sg_coeffs_deriv_gt_polyorder(xp): + """ + If deriv > polyorder, the coefficients should be all 0. + This is a regression test for a bug where, e.g., + savgol_coeffs(5, polyorder=1, deriv=2) + raised an error. + """ + coeffs = savgol_coeffs(5, polyorder=1, deriv=2, xp=xp) + xp_assert_equal(coeffs, xp.zeros(5, dtype=xp.float64)) + coeffs = savgol_coeffs(7, polyorder=4, deriv=6, xp=xp) + xp_assert_equal(coeffs, xp.zeros(7, dtype=xp.float64)) + + +@xfail_xp_backends( + "torch", reason="torch loses precision (worse with f32 default dtype)" +) +@make_xp_test_case(savgol_coeffs) +def test_sg_coeffs_large(xp): + # Test that for large values of window_length and polyorder the array of + # coefficients returned is symmetric. The aim is to ensure that + # no potential numeric overflow occurs. + coeffs0 = savgol_coeffs(31, 9, xp=xp) + xp_assert_close( + coeffs0, xp.flip(coeffs0), atol=5e-4 if is_torch(xp) else 1.5e-6 + ) + + coeffs1 = savgol_coeffs(31, 9, deriv=1, xp=xp) + xp_assert_close( + coeffs1, -xp.flip(coeffs1), atol=1.2e-2 if is_torch(xp) else 1.5e-6 + ) + +# -------------------------------------------------------------------- +# savgol_coeffs tests for even window length +# -------------------------------------------------------------------- + +@make_xp_test_case(savgol_coeffs) +def test_sg_coeffs_even_window_length(xp): + # Simple case - deriv=0, polyorder=0, 1 + window_lengths = [4, 6, 8, 10, 12, 14, 16] + for length in window_lengths: + h_p_d = savgol_coeffs(length, 0, 0, xp=xp) + xp_assert_close(h_p_d, xp.ones_like(h_p_d) / length) + + # Verify with closed forms + # deriv=1, polyorder=1, 2 + def h_p_d_closed_form_1(k, m): + return 6*(k - 0.5)/((2*m + 1)*m*(2*m - 1)) + + # deriv=2, polyorder=2 + def h_p_d_closed_form_2(k, m): + numer = 15*(-4*m**2 + 1 + 12*(k - 0.5)**2) + denom = 4*(2*m + 1)*(m + 1)*m*(m - 1)*(2*m - 1) + return numer/denom + + for length in window_lengths: + m = length//2 + expected_output = [h_p_d_closed_form_1(k, m) + for k in range(-m + 1, m + 1)][::-1] + expected_output = xp.asarray(expected_output, dtype=xp.float64) + actual_output = savgol_coeffs(length, 1, 1, xp=xp) + xp_assert_close(actual_output, expected_output) + actual_output = savgol_coeffs(length, 2, 1, xp=xp) + xp_assert_close(actual_output, expected_output) + + expected_output = [h_p_d_closed_form_2(k, m) + for k in range(-m + 1, m + 1)][::-1] + expected_output = xp.asarray(expected_output, dtype=xp.float64) + actual_output = savgol_coeffs(length, 2, 2, xp=xp) + xp_assert_close(actual_output, expected_output) + actual_output = savgol_coeffs(length, 3, 2, xp=xp) + xp_assert_close(actual_output, expected_output) + +#-------------------------------------------------------------------- +# savgol_filter tests +#-------------------------------------------------------------------- + +@make_xp_test_case(savgol_filter) +def test_sg_filter_trivial(xp): + """ Test some trivial edge cases for savgol_filter().""" + x = xp.asarray([1.0]) + y = savgol_filter(x, 1, 0) + xp_assert_equal(y, xp.asarray([1.0])) + + # Input is a single value. With a window length of 3 and polyorder 1, + # the value in y is from the straight-line fit of (-1,0), (0,3) and + # (1, 0) at 0. This is just the average of the three values, hence 1.0. + x = xp.asarray([3.0]) + y = savgol_filter(x, 3, 1, mode='constant') + xp_assert_close(y, xp.asarray([1.0]), atol=1.5e-15) + + x = xp.asarray([3.0]) + y = savgol_filter(x, 3, 1, mode='nearest') + xp_assert_close(y, xp.asarray([3.0]), atol=1.5e-15) + + x = xp.asarray([1.0] * 3) + y = savgol_filter(x, 3, 1, mode='wrap') + xp_assert_close(y, xp.asarray([1.0, 1.0, 1.0]), atol=1.5e-15) + + +@make_xp_test_case(savgol_filter) +def test_sg_filter_basic(xp): + # Some basic test cases for savgol_filter(). + x = xp.asarray([1.0, 2.0, 1.0]) + y = savgol_filter(x, 3, 1, mode='constant') + xp_assert_close(y, xp.asarray([1.0, 4.0 / 3, 1.0])) + + y = savgol_filter(x, 3, 1, mode='mirror') + xp_assert_close(y, xp.asarray([5.0 / 3, 4.0 / 3, 5.0 / 3])) + + y = savgol_filter(x, 3, 1, mode='wrap') + xp_assert_close(y, xp.asarray([4.0 / 3, 4.0 / 3, 4.0 / 3])) + + +@make_xp_test_case(savgol_filter) +def test_sg_filter_2d(xp): + x = xp.asarray([[1.0, 2.0, 1.0], + [2.0, 4.0, 2.0]]) + expected = xp.asarray([[1.0, 4.0 / 3, 1.0], + [2.0, 8.0 / 3, 2.0]]) + y = savgol_filter(x, 3, 1, mode='constant') + xp_assert_close(y, expected) + + y = savgol_filter(x.T, 3, 1, mode='constant', axis=0) + xp_assert_close(y, expected.T) + + +@make_xp_test_case(savgol_filter) +def test_sg_filter_interp_edges(xp): + # Another test with low degree polynomial data, for which we can easily + # give the exact results. In this test, we use mode='interp', so + # savgol_filter should match the exact solution for the entire data set, + # including the edges. + t = xp.linspace(-5, 5, 21, dtype=xp.float64) + delta = t[1] - t[0] + # Polynomial test data. + x = xp.stack([t, + 3 * t ** 2, + t ** 3 - t]) + dx = xp.stack([xp.ones_like(t), + 6 * t, + 3 * t ** 2 - 1.0]) + d2x = xp.stack([xp.zeros_like(t), + xp.full_like(t, 6), + 6 * t]) + + window_length = 7 + + y = savgol_filter(x, window_length, 3, axis=-1, mode='interp') + xp_assert_close(y, x, atol=1e-12) + + y1 = savgol_filter(x, window_length, 3, axis=-1, mode='interp', + deriv=1, delta=delta) + xp_assert_close(y1, dx, atol=1e-12) + + y2 = savgol_filter(x, window_length, 3, axis=-1, mode='interp', + deriv=2, delta=delta) + xp_assert_close(y2, d2x, atol=1e-12) + + # Transpose everything, and test again with axis=0. + + x = x.T + dx = dx.T + d2x = d2x.T + + y = savgol_filter(x, window_length, 3, axis=0, mode='interp') + xp_assert_close(y, x, atol=1e-12) + + y1 = savgol_filter(x, window_length, 3, axis=0, mode='interp', + deriv=1, delta=delta) + xp_assert_close(y1, dx, atol=1e-12) + + y2 = savgol_filter(x, window_length, 3, axis=0, mode='interp', + deriv=2, delta=delta) + xp_assert_close(y2, d2x, atol=1e-12) + + +@make_xp_test_case(savgol_filter) +def test_sg_filter_interp_edges_3d(xp): + # Test mode='interp' with a 3-D array. + t = xp.linspace(-5, 5, 21) + delta = t[1] - t[0] + x1 = xp.stack([t, -t]) + x2 = xp.stack([t ** 2, 3 * t ** 2 + 5]) + x3 = xp.stack([t ** 3, 2 * t ** 3 + t ** 2 - 0.5 * t]) + dx1 = xp.stack([xp.ones_like(t), -xp.ones_like(t)]) + dx2 = xp.stack([2 * t, 6 * t]) + dx3 = xp.stack([3 * t ** 2, 6 * t ** 2 + 2 * t - 0.5]) + + # z has shape (3, 2, 21) + z = xp.stack([x1, x2, x3]) + dz = xp.stack([dx1, dx2, dx3]) + + y = savgol_filter(z, 7, 3, axis=-1, mode='interp', delta=delta) + xp_assert_close(y, z, atol=1e-10) + + dy = savgol_filter(z, 7, 3, axis=-1, mode='interp', deriv=1, delta=delta) + xp_assert_close(dy, dz, atol=1e-10) + + # z has shape (3, 21, 2) + z = xp.stack([x1.T, x2.T, x3.T]) + dz = xp.stack([dx1.T, dx2.T, dx3.T]) + + y = savgol_filter(z, 7, 3, axis=1, mode='interp', delta=delta) + xp_assert_close(y, z, atol=1e-10) + + dy = savgol_filter(z, 7, 3, axis=1, mode='interp', deriv=1, delta=delta) + xp_assert_close(dy, dz, atol=1e-10) + + # z has shape (21, 3, 2) + z = xp.asarray(xp_swapaxes(z, 0, 1, xp=xp), copy=True) + dz = xp.asarray(xp_swapaxes(dz, 0, 1, xp=xp), copy=True) + + y = savgol_filter(z, 7, 3, axis=0, mode='interp', delta=delta) + xp_assert_close(y, z, atol=1e-10) + + dy = savgol_filter(z, 7, 3, axis=0, mode='interp', deriv=1, delta=delta) + xp_assert_close(dy, dz, atol=1e-10) + + +@make_xp_test_case(savgol_filter) +def test_sg_filter_valid_window_length_3d(xp): + """Tests that the window_length check is using the correct axis.""" + + x = xp.ones((10, 20, 30)) + + savgol_filter(x, window_length=29, polyorder=3, mode='interp') + + with pytest.raises(ValueError, match='window_length must be less than'): + # window_length is more than x.shape[-1]. + savgol_filter(x, window_length=31, polyorder=3, mode='interp') + + savgol_filter(x, window_length=9, polyorder=3, axis=0, mode='interp') + + with pytest.raises(ValueError, match='window_length must be less than'): + # window_length is more than x.shape[0]. + savgol_filter(x, window_length=11, polyorder=3, axis=0, mode='interp') diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_short_time_fft.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_short_time_fft.py new file mode 100644 index 0000000000000000000000000000000000000000..063f44f66d896e7c714d487abcc32654ee11d4b7 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_short_time_fft.py @@ -0,0 +1,1116 @@ +"""Unit tests for module `_short_time_fft`. + +This file's structure loosely groups the tests into the following sequential +categories: + +1. Test function `_calc_dual_canonical_window`. +2. Test for invalid parameters and exceptions in `ShortTimeFFT` (until the + `test_from_window` function). +3. Test algorithmic properties of STFT/ISTFT. Some tests were ported from + ``test_spectral.py``. + +Notes +----- +* Mypy 0.990 does interpret the line:: + + from scipy.stats import norm as normal_distribution + + incorrectly (but the code works), hence a ``type: ignore`` was appended. +""" +import math +from itertools import product +from types import GenericAlias +from typing import cast, get_args, Literal + +import numpy as np +import pytest +from scipy._lib._array_api import xp_assert_close, xp_assert_equal +from scipy.fft import fftshift +from scipy.stats import norm as normal_distribution # type: ignore +from scipy.signal import check_COLA, get_window, welch, stft, istft, spectrogram + +from scipy.signal._short_time_fft import FFT_MODE_TYPE, \ + _calc_dual_canonical_window, closest_STFT_dual_window, ShortTimeFFT, PAD_TYPE +from scipy.signal.windows import blackman, gaussian, hamming, nuttall, triang + + +def test__calc_dual_canonical_window_roundtrip(): + """Test dual window calculation with a round trip to verify duality. + + Note that this works only for canonical window pairs (having minimal + energy) like a Gaussian. + + The window is the same as in the example of `from ShortTimeFFT.from_dual`. + """ + win = gaussian(51, std=10, sym=True) + d_win = _calc_dual_canonical_window(win, 10) + win2 = _calc_dual_canonical_window(d_win, 10) + xp_assert_close(win2, win) + + +def test__calc_dual_canonical_window_exceptions(): + """Raise all exceptions in `_calc_dual_canonical_window`.""" + # Verify that calculation can fail: + with pytest.raises(ValueError, match="hop=5 is larger than window len.*"): + _calc_dual_canonical_window(np.ones(4), 5) + with pytest.raises(ValueError, match=".* Transform not invertible!"): + _calc_dual_canonical_window(np.array([.1, .2, .3, 0]), 4) + + # Verify that parameter `win` may not be integers: + with pytest.raises(ValueError, match="Parameter 'win' cannot be of int.*"): + _calc_dual_canonical_window(np.ones(4, dtype=int), 1) + +def test_closest_STFT_dual_window_exceptions(): + """Raise all exceptions in `closest_STFT_dual_window`.""" + with pytest.raises(ValueError, match="Parameters `win` and `desired_dual` are.*"): + closest_STFT_dual_window(np.ones(4), 2, np.ones(5)) + with pytest.raises(ValueError, match="Parameters `win` and `desired_dual` are.*"): + closest_STFT_dual_window(np.ones((4, 1)), 2, np.ones(4)) + with pytest.raises(ValueError, match="Parameter win must have finite entries!"): + closest_STFT_dual_window(np.ones(4)*np.nan, 2, np.ones(4)) + with pytest.raises(ValueError, match="Parameter desired_dual must have finite.*"): + closest_STFT_dual_window(np.ones(4), 2, np.ones(4)*np.nan) + with pytest.raises(ValueError, match="Parameter hop=20 is not an integer.*"): + closest_STFT_dual_window(np.ones(4), 20, np.ones(4)) + with pytest.raises(ValueError, match="Parameter hop=2.0 is not an integer.*"): + # noinspection PyTypeChecker + closest_STFT_dual_window(np.ones(4), 2., np.ones(4)) + + with pytest.raises(ValueError, match="Unable to calculate scaled closest dual.*"): + closest_STFT_dual_window(np.ones(4), 2, np.zeros(4), scaled=True) + + +@pytest.mark.parametrize("scaled", (True, False)) +@pytest.mark.parametrize('sym_win', (False, True)) +@pytest.mark.parametrize('hop', (8, 9)) +@pytest.mark.parametrize('m', (16, 17)) +@pytest.mark.parametrize('win_name', ('hann', 'hamming')) +def test_closest_STFT_dual_window_roundtrip(win_name, m, hop, sym_win, scaled): + """Do roundtrip, i.e., compare dual of dual windows. + + The default for parameter `desired_dual` is also verified. + """ + win = get_window(win_name, m, not sym_win) + d1, s1 = closest_STFT_dual_window(win, hop, np.ones_like(win), scaled=scaled) + d2, s2 = closest_STFT_dual_window(win, hop, scaled=scaled) # equals d1, s1 + d3, s3 = closest_STFT_dual_window(d1, hop, win * s1, scaled=True) # roundtrip + + # (d1, s1) == (d2, s2) should hold, but the BLAS backend used to calculate the inner + # product in `closest_STFT_dual_window` does not guarantee exact reproducibility + # due to indeterministic summation order during parallel execution. Hence, only + # approximate equality is verified. Consult NumPy 29873 issue for discussion. + res = np.finfo(win.dtype).resolution # 1e-15 for float64 + err_msg = "Default for parameter `desired_dual` is not ok!" + xp_assert_close(d2, d1, atol=res, err_msg=err_msg) + xp_assert_close(s2, s1, atol=res, err_msg=err_msg) + + xp_assert_close(s1*s3, 1., atol=res*5, err_msg="Invalid Scale factors") + xp_assert_close(d3, win, atol=res*5, err_msg="Roundtrip failed!") + + if scaled: # check that scaling factor is correct: + d3, _ = closest_STFT_dual_window(win, hop, np.ones(m) * s1, scaled=False) + xp_assert_close(d3, d1, atol=res, err_msg="Roundtrip failed!") + + +@pytest.mark.parametrize('scaled', (False, True)) +def test_closest_STFT_dual_window_STFT_roundtrip(scaled): + """STFT Roundtrip correctness of closest dual window. """ + np.random.seed(5613830) + n, m_num, hop = 15, 7, 3 + w, desires_dual = hamming(m_num), triang(m_num) + d, _ = closest_STFT_dual_window(w, hop, desires_dual, scaled=scaled) + + SFT = ShortTimeFFT(w, hop=hop, dual_win=d, fs=1, scale_to=None, phase_shift=None) + x = 10 * np.random.randn(n) + Sx = SFT.stft(x) + y = SFT.istft(Sx, 0, n) + + atol = np.finfo(w.dtype).resolution * 10 + xp_assert_close(y, x, atol=atol, err_msg="Invalid closest window") + + +@pytest.mark.parametrize('scaled', (False, True)) +def test_closest_STFT_dual_window_STFT_roundtrip_complex(scaled): + """STFT Roundtrip correctness of closest dual window with complex values. """ + np.random.seed(34905436) + n, m_num, hop = 15, 7, 3 + win = 1j*hamming(m_num) + nuttall(m_num) + desires_dual = 1j*triang(m_num) + blackman(m_num) + dual, s = closest_STFT_dual_window(win, hop, desires_dual, scaled=scaled) + + SFT = ShortTimeFFT(win, hop=hop, dual_win=dual, fs=1, fft_mode='twosided', + scale_to=None, phase_shift=None) + x = 10 * np.random.randn(n) + 10j * np.random.randn(n) + Sx = SFT.stft(x) + y = SFT.istft(Sx, 0, n) + + atol = np.finfo(win.dtype).resolution * 10 + xp_assert_close(y, x, atol=atol, err_msg=f"Invalid complex closest window ({s=})") + + +@pytest.mark.parametrize("win_name, nperseg, noverlap, scale_fac", ([ + ('boxcar', 16, 8, 1/2), + ('boxcar', 18, 12, 1/3), + ('boxcar', 16, 12, 1/4), + ('bartlett', 16, 8, 1.), + ('bartlett', 16, 12, 1/2), + ('bartlett', 30, 25, 1/3), + ('hann', 16, 8, 1.), + ('hann', 18, 12, 2/3), + ('hann', 16, 12, 1/2), + ('blackman', 9, 6, 50/63), + ('boxcar', 8, 7, 1/8)])) # hop = 1 +def test_closest_STFT_dual_window_cola(win_name, nperseg, noverlap, scale_fac): + """Test if `closest_STFT_dual_window` generalizes `check_COLA`. + + The parameters were taken from the `check_COLA` documentation. + Note that `check_COLA` only guarantees the existence of a dual window with constant + values but not that those values are unity (which is clear, when investigating the + 'boxcar' examples). The values for `scale_fac` were determined empirically. + """ + desired_dual = get_window(win_name, nperseg, fftbins=True) + assert check_COLA(desired_dual, nperseg, noverlap), "COLA cond. violated!" + + win = np.ones(nperseg) # check scaled window: + d_s, s = closest_STFT_dual_window(win, nperseg-noverlap, desired_dual, scaled=True) + + res = np.finfo(desired_dual.dtype).resolution + rel_tol_d = max(abs(d_s))*res*3 + xp_assert_close(s, scale_fac, atol=res*10, + err_msg=f"Scale factor off by {s/scale_fac}") + xp_assert_close(d_s, desired_dual*scale_fac, atol=res*10, rtol=rel_tol_d, + err_msg="Calculated incorrect scaled window!") + + # check unscaled window: + d_u, u = closest_STFT_dual_window(win * scale_fac, nperseg - noverlap, + desired_dual, scaled=False) + + # this should be hard-coded not computed, so no need for allclose + assert u == 1., "Scaling factor not 1 for parameter `scaled=True`!" + xp_assert_close(d_u, desired_dual, atol=res*10, rtol=rel_tol_d, + err_msg="Calculated incorrect unscaled window!") + + +def test_invalid_initializer_parameters(): + """Verify that exceptions get raised on invalid parameters when + instantiating ShortTimeFFT. """ + with pytest.raises(ValueError, match=r"Parameter win must be 1d, " + + r"but win.shape=\(2, 2\)!"): + ShortTimeFFT(np.ones((2, 2)), hop=4, fs=1) + with pytest.raises(ValueError, match="Parameter win must have " + + "finite entries"): + ShortTimeFFT(np.array([1, np.inf, 2, 3]), hop=4, fs=1) + with pytest.raises(ValueError, match="Parameter hop=0 is not " + + "an integer >= 1!"): + ShortTimeFFT(np.ones(4), hop=0, fs=1) + with pytest.raises(ValueError, match="Parameter hop=2.0 is not " + + "an integer >= 1!"): + # noinspection PyTypeChecker + ShortTimeFFT(np.ones(4), hop=2.0, fs=1) + with pytest.raises(ValueError, match=r"dual_win.shape=\(5,\) must equal " + + r"win.shape=\(4,\)!"): + ShortTimeFFT(np.ones(4), hop=2, fs=1, dual_win=np.ones(5)) + with pytest.raises(ValueError, match="Parameter dual_win must be " + + "a finite array!"): + ShortTimeFFT(np.ones(3), hop=2, fs=1, + dual_win=np.array([np.nan, 2, 3])) + + +def test_exceptions_properties_methods(): + """Verify that exceptions get raised when setting properties or calling + method of ShortTimeFFT to/with invalid values.""" + SFT = ShortTimeFFT(np.ones(8), hop=4, fs=1) + with pytest.raises(ValueError, match="Sampling interval T=-1 must be " + + "positive!"): + SFT.T = -1 + with pytest.raises(ValueError, match="Sampling frequency fs=-1 must be " + + "positive!"): + SFT.fs = -1 + with pytest.raises(ValueError, match="fft_mode='invalid_typ' not in " + + r"\('twosided', 'centered', " + + r"'onesided', 'onesided2X'\)!"): + SFT.fft_mode = 'invalid_typ' + with pytest.raises(ValueError, match="For scaling is None, " + + "fft_mode='onesided2X' is invalid.*"): + SFT.fft_mode = 'onesided2X' + with pytest.raises(ValueError, match="Attribute mfft=7 needs to be " + + "at least the window length.*"): + SFT.mfft = 7 + with pytest.raises(ValueError, match="scaling='invalid' not in.*"): + # noinspection PyTypeChecker + SFT.scale_to('invalid') + with pytest.raises(ValueError, match="phase_shift=3.0 has the unit .*"): + SFT.phase_shift = 3.0 + with pytest.raises(ValueError, match="-mfft < phase_shift < mfft " + + "does not hold.*"): + SFT.phase_shift = 2*SFT.mfft + with pytest.raises(ValueError, match="Parameter padding='invalid' not.*"): + # noinspection PyTypeChecker + g = SFT._x_slices(np.zeros(16), k_off=0, p0=0, p1=1, padding='invalid') + next(g) # execute generator + with pytest.raises(ValueError, match="Trend type must be 'linear' " + + "or 'constant'"): + # noinspection PyTypeChecker + SFT.stft_detrend(np.zeros(16), detr='invalid') + with pytest.raises(ValueError, match="Parameter detr=nan is not a str, " + + "function or None!"): + # noinspection PyTypeChecker + SFT.stft_detrend(np.zeros(16), detr=np.nan) + with pytest.raises(ValueError, match="Invalid Parameter p0=0, p1=200.*"): + SFT.p_range(100, 0, 200) + + with pytest.raises(ValueError, match="f_axis=0 may not be equal to " + + "t_axis=0!"): + SFT.istft(np.zeros((SFT.f_pts, 2)), t_axis=0, f_axis=0) + with pytest.raises(ValueError, match=r"S.shape\[f_axis\]=2 must be equal" + + " to self.f_pts=5.*"): + SFT.istft(np.zeros((2, 2))) + with pytest.raises(ValueError, match=r"S.shape\[t_axis\]=1 needs to have" + + " at least 2 slices.*"): + SFT.istft(np.zeros((SFT.f_pts, 1))) + with pytest.raises(ValueError, match=r".*\(k1=100\) <= \(k_max=12\) " + + "is false!$"): + SFT.istft(np.zeros((SFT.f_pts, 3)), k1=100) + with pytest.raises(ValueError, match=r"\(k1=1\) - \(k0=0\) = 1 has to " + + "be at least.* length 4!"): + SFT.istft(np.zeros((SFT.f_pts, 3)), k0=0, k1=1) + + with pytest.raises(ValueError, match=r"Parameter axes_seq='invalid' " + + r"not in \['tf', 'ft'\]!"): + # noinspection PyTypeChecker + SFT.extent(n=100, axes_seq='invalid') + with pytest.raises(ValueError, match="Attribute fft_mode=twosided must.*"): + SFT.fft_mode = 'twosided' + SFT.extent(n=100) + + +@pytest.mark.parametrize('m', ('onesided', 'onesided2X')) +def test_exceptions_fft_mode_complex_win(m: FFT_MODE_TYPE): + """Verify that one-sided spectra are not allowed with complex-valued + windows or with complex-valued signals. + + The reason being, the `rfft` function only accepts real-valued input. + """ + with pytest.raises(ValueError, + match=f"One-sided spectra, i.e., fft_mode='{m}'.*"): + ShortTimeFFT(np.ones(8)*1j, hop=4, fs=1, fft_mode=m) + + SFT = ShortTimeFFT(np.ones(8)*1j, hop=4, fs=1, fft_mode='twosided') + with pytest.raises(ValueError, + match=f"One-sided spectra, i.e., fft_mode='{m}'.*"): + SFT.fft_mode = m + + SFT = ShortTimeFFT(np.ones(8), hop=4, fs=1, scale_to='psd', fft_mode='onesided') + with pytest.raises(ValueError, match="Complex-valued `x` not allowed for self.*"): + SFT.stft(np.ones(8)*1j) + SFT.fft_mode = 'onesided2X' + with pytest.raises(ValueError, match="Complex-valued `x` not allowed for self.*"): + SFT.stft(np.ones(8)*1j) + + +def test_invalid_fft_mode_RuntimeError(): + """Ensure exception gets raised when property `fft_mode` is invalid. """ + SFT = ShortTimeFFT(np.ones(8), hop=4, fs=1) + # noinspection PyTypeChecker + SFT._fft_mode = 'invalid_typ' + + with pytest.raises(RuntimeError): + _ = SFT.f + with pytest.raises(RuntimeError): + SFT._fft_func(np.ones(8)) + with pytest.raises(RuntimeError): + SFT._ifft_func(np.ones(8)) + + +@pytest.mark.parametrize('win_params, Nx', [(('gaussian', 2.), 9), # in docstr + ('triang', 7), + (('kaiser', 4.0), 9), + (('exponential', None, 1.), 9), + (4.0, 9)]) +def test_from_window(win_params, Nx: int): + """Verify that `from_window()` handles parameters correctly. + + The window parameterizations are documented in the `get_window` docstring. + """ + w_sym, fs = get_window(win_params, Nx, fftbins=False), 16. + w_per = get_window(win_params, Nx, fftbins=True) + SFT0 = ShortTimeFFT(w_sym, hop=3, fs=fs, fft_mode='twosided', + scale_to='psd', phase_shift=1) + nperseg = len(w_sym) + noverlap = nperseg - SFT0.hop + SFT1 = ShortTimeFFT.from_window(win_params, fs, nperseg, noverlap, + symmetric_win=True, fft_mode='twosided', + scale_to='psd', phase_shift=1) + # periodic window: + SFT2 = ShortTimeFFT.from_window(win_params, fs, nperseg, noverlap, + symmetric_win=False, fft_mode='twosided', + scale_to='psd', phase_shift=1) + # Be informative when comparing instances: + xp_assert_equal(SFT1.win, SFT0.win) + xp_assert_close(SFT2.win, w_per / np.sqrt(sum(w_per**2) * fs)) + for n_ in ('hop', 'T', 'fft_mode', 'mfft', 'scaling', 'phase_shift'): + v0, v1, v2 = (getattr(SFT_, n_) for SFT_ in (SFT0, SFT1, SFT2)) + assert v1 == v0, f"SFT1.{n_}={v1} does not equal SFT0.{n_}={v0}" + assert v2 == v0, f"SFT2.{n_}={v2} does not equal SFT0.{n_}={v0}" + + +def test_from_win_equals_dual_exceptions(): + """Raise all occurring exceptions in `ShortTimeFFT.from_closest_win_equals_dual`. + """ + with pytest.raises(ValueError, match="Parameter desired_win is not 1d, but.*"): + ShortTimeFFT.from_win_equals_dual(np.ones((3, 4)), hop=1, fs=1) + with pytest.raises(ValueError, match="Parameter desired_win cannot be of int.*"): + ShortTimeFFT.from_win_equals_dual(np.ones(4, dtype=int), hop=1, fs=1) + with pytest.raises(ValueError, match="Parameter desired_win is not 1d, but.*"): + ShortTimeFFT.from_win_equals_dual(np.array([]), hop=1, fs=1) + with pytest.raises(ValueError, match="Parameter desired_win must have finite.*"): + ShortTimeFFT.from_win_equals_dual(np.ones(3) * np.inf, hop=1, fs=1) + with pytest.raises(ValueError, match="Parameter hop=0 is not an integer .*"): + ShortTimeFFT.from_win_equals_dual(np.ones(4), hop=0, fs=1) + with pytest.raises(ValueError, match="Parameter hop=5 is not an integer .*"): + ShortTimeFFT.from_win_equals_dual(np.ones(4), hop=5, fs=1) + + with pytest.raises(ValueError, match="P.+ desired_win does not have valid.*"): + w = np.array([1, 0, 1, 0, 1], dtype=float) + ShortTimeFFT.from_win_equals_dual(w, hop=2, fs=1) + with pytest.raises(ValueError, match="Parameter scale_to='invalid' not in.*"): + # noinspection PyTypeChecker + ShortTimeFFT.from_win_equals_dual(w, hop=2, fs=1, scale_to='invalid') + +@pytest.mark.parametrize('fft_bins', (True, False)) +@pytest.mark.parametrize('m, hop', [(16, 8), (16, 7), (17, 8), (17, 9), (16, 16)]) +def test_from_win_equals_dual_params(m, hop, fft_bins): + """Test windows parameterizations for `ShortTimeFFT.from_closest_win_equals_dual`. + + The flattop window is used since it also has negative values. + """ + desired_win = get_window('flattop', m, fftbins=fft_bins) + SFT0 = ShortTimeFFT.from_win_equals_dual(desired_win, hop, fs=1) + xp_assert_close(SFT0.dual_win, SFT0.win, err_msg="win must equals dual window!") + + SFT1 = ShortTimeFFT(SFT0.win, hop, fs=1) + xp_assert_close(SFT1.dual_win, SFT0.win, err_msg="dual win isn't canonical win!") + + +@pytest.mark.parametrize('fft_bins', (True, False)) +@pytest.mark.parametrize('m, hop', [(16, 8), (16, 7), (17, 8), (17, 9), (16, 16)]) +@pytest.mark.parametrize('scale_to', (None, 'unitary')) +def test_from_win_equals_dual_roundtrip(m, hop, fft_bins, scale_to): + """Testing roundtrip verifies that the dual window is correct. + """ + desired_win = get_window('flattop', m, fftbins=fft_bins) + SFT0 = ShortTimeFFT.from_win_equals_dual(desired_win, hop, fs=1) + + x = np.cos(np.arange(2*m)**2) + x1 = SFT0.istft(SFT0.stft(x), 0, len(x)) + xp_assert_close(x1, x, err_msg="Roundtrip for win equaling its dual failed!") + + +def test_from_win_equals_dual_unitary(): + """Check that STFT can be unitary mapping. """ + m, hop = 8, 4 + des_win = get_window('hann', m) + SFT = ShortTimeFFT.from_win_equals_dual(des_win, hop, 1, fft_mode='twosided', + scale_to='unitary') + # Orthogonal signals: + x, y = np.tile([-1, -1, 1, 1], 4), np.tile([1, -1, -1, 1], 4) + Sxx, Sxy = SFT.spectrogram(x), SFT.spectrogram(x, y) + + atol = np.finfo(Sxx.dtype).resolution + assert sum(x * y) == 0 + xp_assert_close(np.sum(Sxx), np.sum(x ** 2, dtype=Sxx.dtype), atol=atol, + err_msg="Energies do not match!") + xp_assert_close(np.sum(Sxy), 0.0j, atol=atol, + err_msg="STFT scalar product of Sx and Sy not 0!") + xp_assert_close(SFT.dual_win, SFT.win*SFT.m_num, atol=atol, + err_msg="Wrong factor for dual_win/win!") + + +def test_dual_win_roundtrip(): + """Verify the duality of `win` and `dual_win`. + + Note that this test does not work for arbitrary windows, since dual windows + are not unique. It always works for invertible STFTs if the windows do not + overlap. + """ + # Non-standard values for keyword arguments (except for `scale_to`): + kw = dict(hop=4, fs=1, fft_mode='twosided', mfft=8, scale_to=None, + phase_shift=2) + SFT0 = ShortTimeFFT(np.ones(4), **kw) + SFT1 = ShortTimeFFT.from_dual(SFT0.dual_win, **kw) + xp_assert_close(SFT1.dual_win, SFT0.win) + + +@pytest.mark.parametrize('scale_to, fac_psd, fac_mag', + [(None, 0.25, 0.125), + ('magnitude', 2.0, 1), + ('psd', 1, 0.5)]) +def test_scaling(scale_to: Literal['magnitude', 'psd'], fac_psd, fac_mag): + """Verify scaling calculations. + + * Verify passing `scale_to`parameter to ``__init__(). + * Roundtrip while changing scaling factor. + """ + SFT = ShortTimeFFT(np.ones(4) * 2, hop=4, fs=1, scale_to=scale_to) + assert SFT.fac_psd == fac_psd + assert SFT.fac_magnitude == fac_mag + # increase coverage by accessing properties twice: + assert SFT.fac_psd == fac_psd + assert SFT.fac_magnitude == fac_mag + + x = np.fft.irfft([0, 0, 7, 0, 0, 0, 0]) # periodic signal + Sx = SFT.stft(x) + Sx_mag, Sx_psd = Sx * SFT.fac_magnitude, Sx * SFT.fac_psd + + SFT.scale_to('magnitude') + x_mag = SFT.istft(Sx_mag, k1=len(x)) + xp_assert_close(x_mag, x) + + SFT.scale_to('psd') + x_psd = SFT.istft(Sx_psd, k1=len(x)) + xp_assert_close(x_psd, x) + + +def test_scale_to(): + """Verify `scale_to()` method.""" + SFT = ShortTimeFFT(np.ones(4) * 2, hop=4, fs=1, scale_to=None) + + SFT.scale_to('magnitude') + assert SFT.scaling == 'magnitude' + assert SFT.fac_psd == 2.0 + assert SFT.fac_magnitude == 1 + + SFT.scale_to('psd') + assert SFT.scaling == 'psd' + assert SFT.fac_psd == 1 + assert SFT.fac_magnitude == 0.5 + + SFT.scale_to('psd') # needed for coverage + + for scale, s_fac in zip(('magnitude', 'psd'), (8, 4)): + SFT = ShortTimeFFT(np.ones(4) * 2, hop=4, fs=1, scale_to=None) + dual_win = SFT.dual_win.copy() + + SFT.scale_to(cast(Literal['magnitude', 'psd'], scale)) + xp_assert_close(SFT.dual_win, dual_win * s_fac) + + +def test_x_slices_padding(): + """Verify padding. + + The reference arrays were taken from the docstrings of `zero_ext`, + `const_ext`, `odd_ext()`, and `even_ext()` from the _array_tools module. + """ + SFT = ShortTimeFFT(np.ones(5), hop=4, fs=1) + x = np.array([[1, 2, 3, 4, 5], [0, 1, 4, 9, 16]], dtype=float) + d = {'zeros': [[[0, 0, 1, 2, 3], [0, 0, 0, 1, 4]], + [[3, 4, 5, 0, 0], [4, 9, 16, 0, 0]]], + 'edge': [[[1, 1, 1, 2, 3], [0, 0, 0, 1, 4]], + [[3, 4, 5, 5, 5], [4, 9, 16, 16, 16]]], + 'even': [[[3, 2, 1, 2, 3], [4, 1, 0, 1, 4]], + [[3, 4, 5, 4, 3], [4, 9, 16, 9, 4]]], + 'odd': [[[-1, 0, 1, 2, 3], [-4, -1, 0, 1, 4]], + [[3, 4, 5, 6, 7], [4, 9, 16, 23, 28]]]} + for p_, xx in d.items(): + gen = SFT._x_slices(np.array(x), 0, 0, 2, padding=cast(PAD_TYPE, p_)) + yy = np.array([y_.copy() for y_ in gen]) # due to inplace copying + xx = np.asarray(xx, dtype=np.float64) + xp_assert_equal(yy, xx, err_msg=f"Failed '{p_}' padding.") + + +def test_invertible(): + """Verify `invertible` property. """ + SFT = ShortTimeFFT(np.ones(8), hop=4, fs=1) + assert SFT.invertible + SFT = ShortTimeFFT(np.ones(8), hop=9, fs=1) + assert not SFT.invertible + + +def test_border_values(): + """Ensure that minimum and maximum values of slices are correct.""" + SFT = ShortTimeFFT(np.ones(8), hop=4, fs=1) + assert SFT.p_min == 0 + assert SFT.k_min == -4 + assert SFT.lower_border_end == (4, 1) + assert SFT.lower_border_end == (4, 1) # needed to test caching + assert SFT.p_max(10) == 4 + assert SFT.k_max(10) == 16 + assert SFT.upper_border_begin(10) == (4, 2) + assert SFT.upper_border_begin(10) == (4, 2) # needed to test caching + # Raise exceptions: + with pytest.raises(ValueError, match="^Parameter n must be"): + SFT.upper_border_begin(3) + with pytest.raises(ValueError, match="^Parameter n must be"): + SFT._post_padding(3) + with pytest.raises(RuntimeError): + SFT._hop = -1 # illegal hop interval + SFT.upper_border_begin(8) + +def test_border_values_exotic(): + """Ensure that the border calculations are correct for windows with + zeros. """ + w = np.array([0, 0, 0, 0, 0, 0, 0, 1.]) + SFT = ShortTimeFFT(w, hop=1, fs=1) + assert SFT.lower_border_end == (0, 0) + + SFT = ShortTimeFFT(np.flip(w), hop=20, fs=1) + assert SFT.upper_border_begin(4) == (16, 1) + assert SFT.upper_border_begin(5) == (16, 1) + assert SFT.upper_border_begin(23) == (36, 2) + assert SFT.upper_border_begin(24) == (36, 2) + assert SFT.upper_border_begin(25) == (36, 2) + + SFT._hop = -1 # provoke unreachable line + with pytest.raises(RuntimeError): + _ = SFT.k_max(4) + with pytest.raises(RuntimeError): + _ = SFT.k_min + + +def test_t(): + """Verify that the times of the slices are correct. """ + SFT = ShortTimeFFT(np.ones(8), hop=4, fs=2) + assert SFT.T == 1/2 + assert SFT.fs == 2. + assert SFT.delta_t == 4 * 1/2 + t_stft = np.arange(0, SFT.p_max(10)) * SFT.delta_t + xp_assert_equal(SFT.t(10), t_stft) + xp_assert_equal(SFT.t(10, 1, 3), t_stft[1:3]) + SFT.T = 1/4 + assert SFT.T == 1/4 + assert SFT.fs == 4 + SFT.fs = 1/8 + assert SFT.fs == 1/8 + assert SFT.T == 8 + with pytest.raises(ValueError): + # noinspection PyTypeChecker + SFT.t(1.5) # only integers allowed + with pytest.raises(ValueError): + SFT.t(-1) # only positive `n` allowed + + +@pytest.mark.parametrize('fft_mode, f', + [('onesided', [0., 1., 2.]), + ('onesided2X', [0., 1., 2.]), + ('twosided', [0., 1., 2., -2., -1.]), + ('centered', [-2., -1., 0., 1., 2.])]) +def test_f(fft_mode: FFT_MODE_TYPE, f): + """Verify the frequency values property `f`.""" + SFT = ShortTimeFFT(np.ones(5), hop=4, fs=5, fft_mode=fft_mode, + scale_to='psd') + xp_assert_equal(SFT.f, f) + + +@pytest.mark.parametrize('n', [20, 21]) +@pytest.mark.parametrize('m', [5, 6]) +@pytest.mark.parametrize('fft_mode', ['onesided', 'centered']) +def test_extent(n, m, fft_mode: FFT_MODE_TYPE): + """Ensure that the `extent()` method is correct. """ + SFT = ShortTimeFFT(np.ones(m), hop=m, fs=m, fft_mode=fft_mode) + + t0 = SFT.t(n)[0] # first timestamp + t1 = SFT.t(n)[-1] + SFT.delta_t # last timestamp + 1 + t0c, t1c = t0 - SFT.delta_t / 2, t1 - SFT.delta_t / 2 # centered timestamps + + f0 = SFT.f[0] # first frequency + f1 = SFT.f[-1] + SFT.delta_f # last frequency + 1 + f0c, f1c = f0 - SFT.delta_f / 2, f1 - SFT.delta_f / 2 # centered frequencies + + assert SFT.extent(n, 'tf', False) == (t0, t1, f0, f1) + assert SFT.extent(n, 'ft', False) == (f0, f1, t0, t1) + assert SFT.extent(n, 'tf', True) == (t0c, t1c, f0c, f1c) + assert SFT.extent(n, 'ft', True) == (f0c, f1c, t0c, t1c) + + +def test_spectrogram(): + """Verify spectrogram and cross-spectrogram methods. """ + SFT = ShortTimeFFT(np.ones(8), hop=4, fs=1) + x, y = np.ones(10), np.arange(10) + X, Y = SFT.stft(x), SFT.stft(y) + xp_assert_close(SFT.spectrogram(x), X.real**2+X.imag**2) + xp_assert_close(SFT.spectrogram(x, y), X * Y.conj()) + + +@pytest.mark.parametrize('n', [8, 9]) +def test_fft_func_roundtrip(n: int): + """Test roundtrip `ifft_func(fft_func(x)) == x` for all permutations of + relevant parameters. """ + np.random.seed(2394795) + x0 = np.random.rand(n) + w, h_n = np.ones(n), 4 + + pp = dict( + fft_mode=get_args(FFT_MODE_TYPE), + mfft=[None, n, n+1, n+2], + scaling=[None, 'magnitude', 'psd'], + phase_shift=[None, -n+1, 0, n // 2, n-1]) + for f_typ, mfft, scaling, phase_shift in product(*pp.values()): + if f_typ == 'onesided2X' and scaling is None: + continue # this combination is forbidden + SFT = ShortTimeFFT(w, h_n, fs=n, fft_mode=f_typ, mfft=mfft, + scale_to=scaling, phase_shift=phase_shift) + X0 = SFT._fft_func(x0) + x1 = SFT._ifft_func(X0) + xp_assert_close(x0.astype(x1.dtype), x1, + err_msg="_fft_func() roundtrip failed for " + + f"{f_typ=}, {mfft=}, {scaling=}, {phase_shift=}") + + SFT = ShortTimeFFT(w, h_n, fs=1) + SFT._fft_mode = 'invalid_fft' # type: ignore + with pytest.raises(RuntimeError): + SFT._fft_func(x0) + with pytest.raises(RuntimeError): + SFT._ifft_func(x0) + + +@pytest.mark.parametrize('i', range(19)) +def test_impulse_roundtrip(i): + """Roundtrip for an impulse being at different positions `i`.""" + n = 19 + w, h_n = np.ones(8), 3 + x = np.zeros(n) + x[i] = 1 + + SFT = ShortTimeFFT(w, hop=h_n, fs=1, scale_to=None, phase_shift=None) + Sx = SFT.stft(x) + # test slicing the input signal into two parts: + n_q = SFT.nearest_k_p(n // 2) + Sx0 = SFT.stft(x[:n_q], padding='zeros') + Sx1 = SFT.stft(x[n_q:], padding='zeros') + q0_ub = SFT.upper_border_begin(n_q)[1] - SFT.p_min + q1_le = SFT.lower_border_end[1] - SFT.p_min + xp_assert_close(Sx0[:, :q0_ub], Sx[:, :q0_ub], err_msg=f"{i=}") + xp_assert_close(Sx1[:, q1_le:], Sx[:, q1_le-Sx1.shape[1]:], + err_msg=f"{i=}") + + Sx01 = np.hstack((Sx0[:, :q0_ub], + Sx0[:, q0_ub:] + Sx1[:, :q1_le], + Sx1[:, q1_le:])) + xp_assert_close(Sx, Sx01, atol=1e-8, err_msg=f"{i=}") + + y = SFT.istft(Sx, 0, n) + xp_assert_close(y, x, atol=1e-8, err_msg=f"{i=}") + y0 = SFT.istft(Sx, 0, n//2) + xp_assert_close(x[:n//2], y0, atol=1e-8, err_msg=f"{i=}") + y1 = SFT.istft(Sx, n // 2, n) + xp_assert_close(x[n // 2:], y1, atol=1e-8, err_msg=f"{i=}") + + +@pytest.mark.parametrize('hop', [1, 7, 8]) +def test_asymmetric_window_roundtrip(hop: int): + """An asymmetric window could uncover indexing problems. """ + np.random.seed(23371) + + w = np.arange(16) / 8 # must be of type float + w[len(w)//2:] = 1 + SFT = ShortTimeFFT(w, hop, fs=1) + + x = 10 * np.random.randn(64) + Sx = SFT.stft(x) + x1 = SFT.istft(Sx, k1=len(x)) + xp_assert_close(x1, x1, err_msg="Roundtrip for asymmetric window with " + + f" {hop=} failed!") + + +@pytest.mark.parametrize('m_num', [6, 7]) +def test_minimal_length_signal(m_num): + """Verify that the shortest allowed signal works. """ + SFT = ShortTimeFFT(np.ones(m_num), m_num//2, fs=1) + n = math.ceil(m_num/2) + x = np.ones(n) + Sx = SFT.stft(x) + x1 = SFT.istft(Sx, k1=n) + xp_assert_close(x1, x, err_msg=f"Roundtrip minimal length signal ({n=})" + + f" for {m_num} sample window failed!") + with pytest.raises(ValueError, match=rf"len\(x\)={n-1} must be >= ceil.*"): + SFT.stft(x[:-1]) + with pytest.raises(ValueError, match=rf"S.shape\[t_axis\]={Sx.shape[1]-1}" + f" needs to have at least {Sx.shape[1]} slices"): + SFT.istft(Sx[:, :-1], k1=n) + + +def test_compare_stft_detrend(): + """Test the detrending in `ShortTimeFFT.stft_detrend()`. """ + SFT = ShortTimeFFT(np.ones(4), 4, fs=1) + x0 = np.zeros(4) # signal without trend + x1 = x0 + 3 # signal with constant trend + x2 = x0 + np.arange(len(x0)) # signal with linear trend + + kw = dict(k_offset=2, p1=1) # we want only one slice + Sx0 = SFT.stft(x0, **kw) # no trend + Sx1 = SFT.stft_detrend(x1, detr='constant', **kw) + Sx2 = SFT.stft_detrend(x2, detr='linear', **kw) + Sx3 = SFT.stft_detrend(x1, detr=lambda x: x - np.mean(x), **kw) + + atol = np.finfo(Sx0.dtype).resolution * 5 # needed to compare with array of zeros + xp_assert_close(Sx1, Sx0, atol=atol, err_msg="Constant detrending failed!") + xp_assert_close(Sx0, Sx2, atol=atol, err_msg="Linear detrending failed!") + xp_assert_close(Sx0, Sx3, atol=atol, err_msg="Detrending using a function failed!") + + +def test_tutorial_stft_sliding_win(): + """Verify example in "Sliding Windows" subsection from the "User Guide". + + In :ref:`tutorial_stft_sliding_win` (file ``signal.rst``) of the + :ref:`user_guide` the behavior the border behavior of + ``ShortTimeFFT(np.ones(6), 2, fs=1)`` with a 50 sample signal is discussed. + This test verifies the presented indexes. + """ + SFT = ShortTimeFFT(np.ones(6), 2, fs=1) + + # Lower border: + assert SFT.m_num_mid == 3, f"Slice middle is not 3 but {SFT.m_num_mid=}" + assert SFT.p_min == -1, f"Lowest slice {SFT.p_min=} is not -1" + assert SFT.k_min == -5, f"Lowest slice sample {SFT.p_min=} is not -5" + k_lb, p_lb = SFT.lower_border_end + assert p_lb == 2, f"First unaffected slice {p_lb=} is not 2" + assert k_lb == 5, f"First unaffected sample {k_lb=} is not 5" + + n = 50 # upper signal border + assert (p_max := SFT.p_max(n)) == 27, f"Last slice {p_max=} must be 27" + assert (k_max := SFT.k_max(n)) == 55, f"Last sample {k_max=} must be 55" + k_ub, p_ub = SFT.upper_border_begin(n) + assert p_ub == 24, f"First upper border slice {p_ub=} must be 24" + assert k_ub == 45, f"First upper border slice {k_ub=} must be 45" + + +def test_tutorial_stft_legacy_stft(): + """Verify STFT example in "Comparison with Legacy Implementation" from the + "User Guide". + + In :ref:`tutorial_stft_legacy_stft` (file ``signal.rst``) of the + :ref:`user_guide` the legacy and the new implementation are compared. + """ + fs, N = 200, 1001 # # 200 Hz sampling rate for 5 s signal + t_z = np.arange(N) / fs # time indexes for signal + z = np.exp(2j*np.pi * 70 * (t_z - 0.2 * t_z ** 2)) # complex-valued chirp + + nperseg, noverlap = 50, 40 + win = ('gaussian', 1e-2 * fs) # Gaussian with 0.01 s standard deviation + + # Legacy STFT: + f0_u, t0, Sz0_u = stft(z, fs, win, nperseg, noverlap, + return_onesided=False, scaling='spectrum') + Sz0 = fftshift(Sz0_u, axes=0) + + # New STFT: + SFT = ShortTimeFFT.from_window(win, fs, nperseg, noverlap, + fft_mode='centered', + scale_to='magnitude', phase_shift=None) + Sz1 = SFT.stft(z) + + xp_assert_close(Sz0, Sz1[:, 2:-1]) + + xp_assert_close((abs(Sz1[:, 1]).min(), abs(Sz1[:, 1]).max()), + (6.925060911593139e-07, 8.00271269218721e-07)) + + t0_r, z0_r = istft(Sz0_u, fs, win, nperseg, noverlap, input_onesided=False, + scaling='spectrum') + z1_r = SFT.istft(Sz1, k1=N) + assert len(z0_r) == N + 9 + xp_assert_close(z0_r[:N], z) + xp_assert_close(z1_r, z) + + # Spectrogram is just the absolute square of th STFT: + xp_assert_close(SFT.spectrogram(z), abs(Sz1) ** 2) + + +def test_tutorial_stft_legacy_spectrogram(): + """Verify spectrogram example in "Comparison with Legacy Implementation" + from the "User Guide". + + In :ref:`tutorial_stft_legacy_stft` (file ``signal.rst``) of the + :ref:`user_guide` the legacy and the new implementation are compared. + """ + fs, N = 200, 1001 # 200 Hz sampling rate for almost 5 s signal + t_z = np.arange(N) / fs # time indexes for signal + z = np.exp(2j*np.pi*70 * (t_z - 0.2*t_z**2)) # complex-valued sweep + + nperseg, noverlap = 50, 40 + win = ('gaussian', 1e-2 * fs) # Gaussian with 0.01 s standard dev. + + # Legacy spectrogram: + f2_u, t2, Sz2_u = spectrogram(z, fs, win, nperseg, noverlap, detrend=None, + return_onesided=False, scaling='spectrum', + mode='complex') + + f2, Sz2 = fftshift(f2_u), fftshift(Sz2_u, axes=0) + + # New STFT: + SFT = ShortTimeFFT.from_window(win, fs, nperseg, noverlap, + fft_mode='centered', scale_to='magnitude', + phase_shift=None) + Sz3 = SFT.stft(z, p0=0, p1=(N-noverlap) // SFT.hop, k_offset=nperseg // 2) + t3 = SFT.t(N, p0=0, p1=(N-noverlap) // SFT.hop, k_offset=nperseg // 2) + + xp_assert_close(t2, t3) + xp_assert_close(f2, SFT.f) + xp_assert_close(Sz2, Sz3) + + +def test_permute_axes(): + """Verify correctness of four-dimensional signal by permuting its + shape. """ + n = 25 + SFT = ShortTimeFFT(np.ones(8)/8, hop=3, fs=n) + x0 = np.arange(n, dtype=np.float64) + Sx0 = SFT.stft(x0) + Sx0 = Sx0.reshape((Sx0.shape[0], 1, 1, 1, Sx0.shape[-1])) + SxT = np.moveaxis(Sx0, (0, -1), (-1, 0)) + + atol = 2 * np.finfo(SFT.win.dtype).resolution + for i in range(4): + y = np.reshape(x0, np.roll((n, 1, 1, 1), i)) + Sy = SFT.stft(y, axis=i) + xp_assert_close(Sy, np.moveaxis(Sx0, 0, i)) + + yb0 = SFT.istft(Sy, k1=n, f_axis=i) + xp_assert_close(yb0, y, atol=atol) + # explicit t-axis parameter (for coverage): + yb1 = SFT.istft(Sy, k1=n, f_axis=i, t_axis=Sy.ndim-1) + xp_assert_close(yb1, y, atol=atol) + + SyT = np.moveaxis(Sy, (i, -1), (-1, i)) + xp_assert_close(SyT, np.moveaxis(SxT, 0, i)) + + ybT = SFT.istft(SyT, k1=n, t_axis=i, f_axis=-1) + xp_assert_close(ybT, y, atol=atol) + + +@pytest.mark.parametrize("fft_mode", + ('twosided', 'centered', 'onesided', 'onesided2X')) +def test_roundtrip_multidimensional(fft_mode: FFT_MODE_TYPE): + """Test roundtrip of a multidimensional input signal versus its components. + + This test can uncover potential problems with `fftshift()`. + """ + n = 9 + x = np.arange(4*n*2, dtype=np.float64).reshape(4, n, 2) + SFT = ShortTimeFFT(get_window('hann', 4), hop=2, fs=1, + scale_to='magnitude', fft_mode=fft_mode) + Sx = SFT.stft(x, axis=1) + y = SFT.istft(Sx, k1=n, f_axis=1, t_axis=-1) + xp_assert_close(y, x.astype(y.dtype), err_msg='Multidim. roundtrip failed!') + + for i, j in product(range(x.shape[0]), range(x.shape[2])): + y_ = SFT.istft(Sx[i, :, j, :], k1=n) + xp_assert_close(y_, x[i, :, j].astype(y_.dtype), + err_msg="Multidim. roundtrip for component " + + f"x[{i}, :, {j}] and {fft_mode=} failed!") + +@pytest.mark.parametrize("phase_shift", (0, 4, None)) +def test_roundtrip_two_dimensional(phase_shift: int|None): + """Test roundtrip of a 2 channel input signal with `mfft` set with different + values for `phase_shift` + + Tests for Issue https://github.com/scipy/scipy/issues/21671 + """ + n = 21 + SFT = ShortTimeFFT.from_window('hann', fs=1, nperseg=13, noverlap=7, + mfft=16, phase_shift=phase_shift) + x = np.arange(2*n, dtype=float).reshape(2, n) + Sx = SFT.stft(x) + y = SFT.istft(Sx, k1=n) + xp_assert_close(y, x, atol=2 * np.finfo(SFT.win.dtype).resolution, + err_msg='2-dim. roundtrip failed!') + + +@pytest.mark.parametrize('window, n, nperseg, noverlap', + [('boxcar', 100, 10, 0), # Test no overlap + ('boxcar', 100, 10, 9), # Test high overlap + ('bartlett', 101, 51, 26), # Test odd nperseg + ('hann', 1024, 256, 128), # Test defaults + (('tukey', 0.5), 1152, 256, 64), # Test Tukey + ('hann', 1024, 256, 255), # Test overlapped hann + ('boxcar', 100, 10, 3), # NOLA True, COLA False + ('bartlett', 101, 51, 37), # NOLA True, COLA False + ('hann', 1024, 256, 127), # NOLA True, COLA False + # NOLA True, COLA False: + (('tukey', 0.5), 1152, 256, 14), + ('hann', 1024, 256, 5)]) # NOLA True, COLA False +def test_roundtrip_windows(window, n: int, nperseg: int, noverlap: int): + """Roundtrip test adapted from `test_spectral.TestSTFT`. + + The parameters are taken from the methods test_roundtrip_real(), + test_roundtrip_nola_not_cola(), test_roundtrip_float32(), + test_roundtrip_complex(). + """ + np.random.seed(2394655) + + w = get_window(window, nperseg) + SFT = ShortTimeFFT(w, nperseg - noverlap, fs=1, fft_mode='twosided', + phase_shift=None) + + z = 10 * np.random.randn(n) + 10j * np.random.randn(n) + Sz = SFT.stft(z) + z1 = SFT.istft(Sz, k1=len(z)) + xp_assert_close(z, z1, err_msg="Roundtrip for complex values failed") + + x = 10 * np.random.randn(n) + Sx = SFT.stft(x) + x1 = SFT.istft(Sx, k1=len(z)) + xp_assert_close(x.astype(np.complex128), x1, + err_msg="Roundtrip for float values failed") + + x32 = x.astype(np.float32) + Sx32 = SFT.stft(x32) + x32_1 = SFT.istft(Sx32, k1=len(x32)) + x32_1_r = x32_1.real + xp_assert_close(x32, x32_1_r.astype(np.float32), + err_msg="Roundtrip for 32 Bit float values failed") + xp_assert_close(x32.imag, np.zeros_like(x32.imag), + err_msg="Roundtrip for 32 Bit float values failed") + + +@pytest.mark.parametrize('signal_type', ('real', 'complex')) +def test_roundtrip_complex_window(signal_type): + """Test roundtrip for complex-valued window function + + The purpose of this test is to check if the dual window is calculated + correctly for complex-valued windows. + """ + np.random.seed(1354654) + win = np.exp(2j*np.linspace(0, np.pi, 8)) + SFT = ShortTimeFFT(win, 3, fs=1, fft_mode='twosided') + + z = 10 * np.random.randn(11) + if signal_type == 'complex': + z = z + 2j * z + Sz = SFT.stft(z) + z1 = SFT.istft(Sz, k1=len(z)) + xp_assert_close(z.astype(np.complex128), z1, + err_msg="Roundtrip for complex-valued window failed") + + +def test_average_all_segments(): + """Compare `welch` function with stft mean. + + Ported from `TestSpectrogram.test_average_all_segments` from file + ``test__spectral.py``. + """ + x = np.random.randn(1024) + + fs = 1.0 + window = ('tukey', 0.25) + nperseg, noverlap = 16, 2 + fw, Pw = welch(x, fs, window, nperseg, noverlap) + SFT = ShortTimeFFT.from_window(window, fs, nperseg, noverlap, + fft_mode='onesided2X', scale_to='psd', + phase_shift=None) + # `welch` positions the window differently than the STFT: + P = SFT.spectrogram(x, detr='constant', p0=0, + p1=(len(x)-noverlap)//SFT.hop, k_offset=nperseg//2) + + xp_assert_close(SFT.f, fw) + xp_assert_close(np.mean(P, axis=-1), Pw) + + +@pytest.mark.parametrize('window, N, nperseg, noverlap, mfft', + # from test_roundtrip_padded_FFT: + [('hann', 1024, 256, 128, 512), + ('hann', 1024, 256, 128, 501), + ('boxcar', 100, 10, 0, 33), + (('tukey', 0.5), 1152, 256, 64, 1024), + # from test_roundtrip_padded_signal: + ('boxcar', 101, 10, 0, None), + ('hann', 1000, 256, 128, None), + # from test_roundtrip_boundary_extension: + ('boxcar', 100, 10, 0, None), + ('boxcar', 100, 10, 9, None)]) +@pytest.mark.parametrize('padding', get_args(PAD_TYPE)) +def test_stft_padding_roundtrip(window, N: int, nperseg: int, noverlap: int, + mfft: int, padding): + """Test the parameter 'padding' of `stft` with roundtrips. + + The STFT parametrizations were taken from the methods + `test_roundtrip_padded_FFT`, `test_roundtrip_padded_signal` and + `test_roundtrip_boundary_extension` from class `TestSTFT` in file + ``test_spectral.py``. Note that the ShortTimeFFT does not need the + concept of "boundary extension". + """ + x = normal_distribution.rvs(size=N, random_state=2909) # real signal + z = x * np.exp(1j * np.pi / 4) # complex signal + + SFT = ShortTimeFFT.from_window(window, 1, nperseg, noverlap, + fft_mode='twosided', mfft=mfft) + Sx = SFT.stft(x, padding=padding) + x1 = SFT.istft(Sx, k1=N) + xp_assert_close(x1, x.astype(np.complex128), + err_msg=f"Failed real roundtrip with '{padding}' padding") + + Sz = SFT.stft(z, padding=padding) + z1 = SFT.istft(Sz, k1=N) + xp_assert_close(z1, z, err_msg="Failed complex roundtrip with " + + f" '{padding}' padding") + + +@pytest.mark.parametrize('N_x', (128, 129, 255, 256, 1337)) # signal length +@pytest.mark.parametrize('w_size', (128, 256)) # window length +@pytest.mark.parametrize('t_step', (4, 64)) # SFT time hop +@pytest.mark.parametrize('f_c', (7., 23.)) # frequency of input sine +def test_energy_conservation(N_x: int, w_size: int, t_step: int, f_c: float): + """Test if a `psd`-scaled STFT conserves the L2 norm. + + This test is adapted from MNE-Python [1]_. Besides being battle-tested, + this test has the benefit of using non-standard window including + non-positive values and a 2d input signal. + + Since `ShortTimeFFT` requires the signal length `N_x` to be at least the + window length `w_size`, the parameter `N_x` was changed from + ``(127, 128, 255, 256, 1337)`` to ``(128, 129, 255, 256, 1337)`` to be + more useful. + + .. [1] File ``test_stft.py`` of MNE-Python + https://github.com/mne-tools/mne-python/blob/main/mne/time_frequency/tests/test_stft.py + """ + window = np.sin(np.arange(.5, w_size + .5) / w_size * np.pi) + SFT = ShortTimeFFT(window, t_step, fs=1000, fft_mode='onesided2X', + scale_to='psd') + atol = 2*np.finfo(window.dtype).resolution + N_x = max(N_x, w_size) # minimal sing + # Test with low frequency signal + t = np.arange(N_x).astype(np.float64) + x = np.sin(2 * np.pi * f_c * t * SFT.T) + x = np.array([x, x + 1.]) + X = SFT.stft(x) + xp = SFT.istft(X, k1=N_x) + + max_freq = SFT.f[np.argmax(np.sum(np.abs(X[0]) ** 2, axis=1))] + + assert X.shape[1] == SFT.f_pts + assert np.all(SFT.f >= 0.) + assert np.abs(max_freq - f_c) < 1. + xp_assert_close(x, xp, atol=atol) + + # check L2-norm squared (i.e., energy) conservation: + E_x = np.sum(x**2, axis=-1) * SFT.T # numerical integration + aX2 = X.real**2 + X.imag.real**2 + E_X = np.sum(np.sum(aX2, axis=-1) * SFT.delta_t, axis=-1) * SFT.delta_f + xp_assert_close(E_X, E_x, atol=atol) + + # Test with random signal + np.random.seed(2392795) + x = np.random.randn(2, N_x) + X = SFT.stft(x) + xp = SFT.istft(X, k1=N_x) + + assert X.shape[1] == SFT.f_pts + assert np.all(SFT.f >= 0.) + assert np.abs(max_freq - f_c) < 1. + xp_assert_close(x, xp, atol=atol) + + # check L2-norm squared (i.e., energy) conservation: + E_x = np.sum(x**2, axis=-1) * SFT.T # numeric integration + aX2 = X.real ** 2 + X.imag.real ** 2 + E_X = np.sum(np.sum(aX2, axis=-1) * SFT.delta_t, axis=-1) * SFT.delta_f + xp_assert_close(E_X, E_x, atol=atol) + + # Try with empty array + x = np.zeros((0, N_x)) + X = SFT.stft(x) + xp = SFT.istft(X, k1=N_x) + assert xp.shape == x.shape + + +def test_subscriptable_generic_type(): + assert isinstance(ShortTimeFFT[np.float64], GenericAlias) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_signaltools.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_signaltools.py new file mode 100644 index 0000000000000000000000000000000000000000..fc9ea2b62687c205d792332a8e2a3ea0a79fe501 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_signaltools.py @@ -0,0 +1,4766 @@ +import sys +import math +import warnings + +from concurrent.futures import ThreadPoolExecutor, as_completed +from itertools import product +from math import gcd + +import pytest +from pytest import raises as assert_raises +import numpy as np +from numpy.exceptions import ComplexWarning + +from scipy import fft as sp_fft +from scipy.ndimage import correlate1d +from scipy.optimize import fmin, linear_sum_assignment +from scipy import signal +from scipy.signal import ( + correlate, correlate2d, correlation_lags, convolve, convolve2d, + fftconvolve, oaconvolve, choose_conv_method, envelope, + hilbert, hilbert2, lfilter, lfilter_zi, filtfilt, butter, zpk2tf, zpk2sos, + invres, invresz, vectorstrength, lfiltic, tf2sos, sosfilt, sosfiltfilt, + sosfilt_zi, tf2zpk, BadCoefficients, detrend, unique_roots, residue, + residuez) +from scipy.signal.windows import hann +from scipy.signal._signaltools import _filtfilt_gust, _compute_factors, _group_poles +from scipy.signal._upfirdn import _upfirdn_modes +from scipy._lib import _testutils + +from scipy._lib._array_api import ( + xp_assert_close, xp_assert_equal, is_numpy, is_torch, is_jax, is_cupy, + assert_array_almost_equal, assert_almost_equal, + xp_copy, xp_size, xp_default_dtype, array_namespace, make_xp_test_case, + make_xp_pytest_param, SCIPY_DEVICE, _xp_copy_to_numpy +) +skip_xp_backends = pytest.mark.skip_xp_backends +xfail_xp_backends = pytest.mark.xfail_xp_backends + +lazy_xp_modules = [signal] + + +@make_xp_test_case(convolve) +class TestConvolve: + + @skip_xp_backends("jax.numpy", + reason="jax returns floats; scipy returns ints; cf gh-6076") + def test_basic(self, xp): + a = xp.asarray([3, 4, 5, 6, 5, 4]) + b = xp.asarray([1, 2, 3]) + c = convolve(a, b) + xp_assert_equal(c, xp.asarray([3, 10, 22, 28, 32, 32, 23, 12])) + + @skip_xp_backends("jax.numpy", + reason="jax returns floats; scipy returns ints; cf gh-6076") + def test_same(self, xp): + a = xp.asarray([3, 4, 5]) + b = xp.asarray([1, 2, 3, 4]) + c = convolve(a, b, mode="same") + xp_assert_equal(c, xp.asarray([10, 22, 34])) + + @skip_xp_backends("jax.numpy", + reason="jax returns floats; scipy returns ints; cf gh-6076") + def test_same_eq(self, xp): + a = xp.asarray([3, 4, 5]) + b = xp.asarray([1, 2, 3]) + c = convolve(a, b, mode="same") + xp_assert_equal(c, xp.asarray([10, 22, 22])) + + def test_complex(self, xp): + x = xp.asarray([1 + 1j, 2 + 1j, 3 + 1j]) + y = xp.asarray([1 + 1j, 2 + 1j]) + z = convolve(x, y) + xp_assert_equal(z, xp.asarray([2j, 2 + 6j, 5 + 8j, 5 + 5j])) + + @xfail_xp_backends("jax.numpy", reason="wrong output dtype") + def test_zero_rank(self, xp): + a = xp.asarray(1289) + b = xp.asarray(4567) + c = convolve(a, b) + xp_assert_equal(c, a * b) + + @skip_xp_backends(np_only=True, reason="pure python") + def test_zero_rank_python_scalars(self, xp): + a = 1289 + b = 4567 + c = convolve(a, b) + assert c == a * b + + @xfail_xp_backends("jax.numpy", reason="disagreement between methods") + def test_broadcastable(self, xp): + a = xp.reshape(xp.arange(27), (3, 3, 3)) + b = xp.arange(3) + for i in range(3): + b_shape = [1]*3 + b_shape[i] = 3 + + x = convolve(a, xp.reshape(b, tuple(b_shape)), method='direct') + y = convolve(a, xp.reshape(b, tuple(b_shape)), method='fft') + xp_assert_close(x, y, atol=1e-14) + + @xfail_xp_backends("jax.numpy", reason="wrong output dtype") + def test_single_element(self, xp): + a = xp.asarray([4967]) + b = xp.asarray([3920]) + c = convolve(a, b) + xp_assert_equal(c, a * b) + + @skip_xp_backends("jax.numpy",) + @skip_xp_backends("cupy") + def test_2d_arrays(self, xp): + a = xp.asarray([[1, 2, 3], [3, 4, 5]]) + b = xp.asarray([[2, 3, 4], [4, 5, 6]]) + c = convolve(a, b) + d = xp.asarray([[2, 7, 16, 17, 12], + [10, 30, 62, 58, 38], + [12, 31, 58, 49, 30]]) + xp_assert_equal(c, d) + + @skip_xp_backends("torch") + @skip_xp_backends("cupy") + def test_input_swapping(self, xp): + small = xp.reshape(xp.arange(8), (2, 2, 2)) + big = 1j * xp.reshape(xp.arange(27, dtype=xp.complex128), (3, 3, 3)) + big += xp.reshape(xp.arange(27, dtype=xp.complex128)[::-1], (3, 3, 3)) + + out_array = xp.asarray( + [[[0 + 0j, 26 + 0j, 25 + 1j, 24 + 2j], + [52 + 0j, 151 + 5j, 145 + 11j, 93 + 11j], + [46 + 6j, 133 + 23j, 127 + 29j, 81 + 23j], + [40 + 12j, 98 + 32j, 93 + 37j, 54 + 24j]], + + [[104 + 0j, 247 + 13j, 237 + 23j, 135 + 21j], + [282 + 30j, 632 + 96j, 604 + 124j, 330 + 86j], + [246 + 66j, 548 + 180j, 520 + 208j, 282 + 134j], + [142 + 66j, 307 + 161j, 289 + 179j, 153 + 107j]], + + [[68 + 36j, 157 + 103j, 147 + 113j, 81 + 75j], + [174 + 138j, 380 + 348j, 352 + 376j, 186 + 230j], + [138 + 174j, 296 + 432j, 268 + 460j, 138 + 278j], + [70 + 138j, 145 + 323j, 127 + 341j, 63 + 197j]], + + [[32 + 72j, 68 + 166j, 59 + 175j, 30 + 100j], + [68 + 192j, 139 + 433j, 117 + 455j, 57 + 255j], + [38 + 222j, 73 + 499j, 51 + 521j, 21 + 291j], + [12 + 144j, 20 + 318j, 7 + 331j, 0 + 182j]]]) + + xp_assert_equal(convolve(small, big, 'full'), out_array) + xp_assert_equal(convolve(big, small, 'full'), out_array) + xp_assert_equal(convolve(small, big, 'same'), + out_array[1:3, 1:3, 1:3]) + xp_assert_equal(convolve(big, small, 'same'), + out_array[0:3, 0:3, 0:3]) + xp_assert_equal(convolve(small, big, 'valid'), + out_array[1:3, 1:3, 1:3]) + xp_assert_equal(convolve(big, small, 'valid'), + out_array[1:3, 1:3, 1:3]) + + def test_invalid_params(self, xp): + a = xp.asarray([3, 4, 5]) + b = xp.asarray([1, 2, 3]) + assert_raises(ValueError, convolve, a, b, mode='spam') + assert_raises(ValueError, convolve, a, b, mode='eggs', method='fft') + assert_raises(ValueError, convolve, a, b, mode='ham', method='direct') + assert_raises(ValueError, convolve, a, b, mode='full', method='bacon') + assert_raises(ValueError, convolve, a, b, mode='same', method='bacon') + + @skip_xp_backends("jax.numpy", reason="dtypes do not match") + def test_valid_mode2(self, xp): + # See gh-5897 + a = xp.asarray([1, 2, 3, 6, 5, 3]) + b = xp.asarray([2, 3, 4, 5, 3, 4, 2, 2, 1]) + expected = xp.asarray([70, 78, 73, 65]) + + out = convolve(a, b, 'valid') + xp_assert_equal(out, expected) + + out = convolve(b, a, 'valid') + xp_assert_equal(out, expected) + + a = xp.asarray([1 + 5j, 2 - 1j, 3 + 0j]) + b = xp.asarray([2 - 3j, 1 + 0j]) + expected = xp.asarray([2 - 3j, 8 - 10j]) + + out = convolve(a, b, 'valid') + xp_assert_equal(out, expected) + + out = convolve(b, a, 'valid') + xp_assert_equal(out, expected) + + @skip_xp_backends("jax.numpy", reason="dtypes do not match") + def test_same_mode(self, xp): + a = xp.asarray([1, 2, 3, 3, 1, 2]) + b = xp.asarray([1, 4, 3, 4, 5, 6, 7, 4, 3, 2, 1, 1, 3]) + c = convolve(a, b, 'same') + d = xp.asarray([57, 61, 63, 57, 45, 36]) + xp_assert_equal(c, d) + + @skip_xp_backends("cupy", reason="different exception") + def test_invalid_shapes(self, xp): + # By "invalid," we mean that no one + # array has dimensions that are all at + # least as large as the corresponding + # dimensions of the other array. This + # setup should throw a ValueError. + a = xp.reshape(xp.arange(1, 7), (2, 3)) + b = xp.reshape(xp.arange(-6, 0), (3, 2)) + + assert_raises(ValueError, convolve, *(a, b), **{'mode': 'valid'}) + assert_raises(ValueError, convolve, *(b, a), **{'mode': 'valid'}) + + @skip_xp_backends(np_only=True, reason="TODO: convert this test") + def test_convolve_method(self, xp, n=100): + # this types data structure was manually encoded instead of + # using custom filters on the soon-to-be-removed np.sctypes + types = {'uint16', 'uint64', 'int64', 'int32', + 'complex128', 'float64', 'float16', + 'complex64', 'float32', 'int16', + 'uint8', 'uint32', 'int8', 'bool'} + args = [(t1, t2, mode) for t1 in types for t2 in types + for mode in ['valid', 'full', 'same']] + + # These are random arrays, which means test is much stronger than + # convolving testing by convolving two np.ones arrays + rng = np.random.RandomState(42) + array_types = {'i': rng.choice([0, 1], size=n), + 'f': rng.randn(n)} + array_types['b'] = array_types['u'] = array_types['i'] + array_types['c'] = array_types['f'] + 0.5j*array_types['f'] + + for t1, t2, mode in args: + x1 = array_types[np.dtype(t1).kind].astype(t1) + x2 = array_types[np.dtype(t2).kind].astype(t2) + + results = {key: convolve(x1, x2, method=key, mode=mode) + for key in ['fft', 'direct']} + + assert results['fft'].dtype == results['direct'].dtype + + if 'bool' in t1 and 'bool' in t2: + assert choose_conv_method(x1, x2) == 'direct' + continue + + # Found by experiment. Found approx smallest value for (rtol, atol) + # threshold to have tests pass. + if any([t in {'complex64', 'float32'} for t in [t1, t2]]): + kwargs = {'rtol': 1.0e-4, 'atol': 1e-6} + elif 'float16' in [t1, t2]: + # atol is default for np.allclose + kwargs = {'rtol': 1e-3, 'atol': 1e-3} + else: + # defaults for np.allclose (different from assert_allclose) + kwargs = {'rtol': 1e-5, 'atol': 1e-8} + + xp_assert_close(results['fft'], results['direct'], **kwargs) + + @skip_xp_backends("jax.numpy", reason="dtypes do not match") + def test_convolve_method_large_input(self, xp): + # This is really a test that convolving two large integers goes to the + # direct method even if they're in the fft method. + for n in [10, 20, 50, 51, 52, 53, 54, 60, 62]: + z = xp.asarray([2**n], dtype=xp.int64) + fft = convolve(z, z, method='fft') + direct = convolve(z, z, method='direct') + + # this is the case when integer precision gets to us + # issue #6076 has more detail, hopefully more tests after resolved + # # XXX: revisit check_dtype under np 2.0: 32bit linux & windows + if n < 50: + val = xp.asarray([2**(2*n)]) + xp_assert_equal(fft, direct) + xp_assert_equal(fft, val, check_dtype=False) + xp_assert_equal(direct, val, check_dtype=False) + + @skip_xp_backends(np_only=True) + def test_mismatched_dims(self, xp): + # Input arrays should have the same number of dimensions + assert_raises(ValueError, convolve, [1], 2, method='direct') + assert_raises(ValueError, convolve, 1, [2], method='direct') + assert_raises(ValueError, convolve, [1], 2, method='fft') + assert_raises(ValueError, convolve, 1, [2], method='fft') + assert_raises(ValueError, convolve, [1], [[2]]) + assert_raises(ValueError, convolve, [3], 2) + + +@make_xp_test_case(convolve2d) +class TestConvolve2d: + + @skip_xp_backends("jax.numpy", reason="dtypes do not match") + def test_2d_arrays(self, xp): + a = xp.asarray([[1, 2, 3], [3, 4, 5]]) + b = xp.asarray([[2, 3, 4], [4, 5, 6]]) + d = xp.asarray([[2, 7, 16, 17, 12], + [10, 30, 62, 58, 38], + [12, 31, 58, 49, 30]]) + e = convolve2d(a, b) + xp_assert_equal(e, d) + + @skip_xp_backends("jax.numpy", reason="dtypes do not match") + def test_valid_mode(self, xp): + e = xp.asarray([[2, 3, 4, 5, 6, 7, 8], [4, 5, 6, 7, 8, 9, 10]]) + f = xp.asarray([[1, 2, 3], [3, 4, 5]]) + h = xp.asarray([[62, 80, 98, 116, 134]]) + + g = convolve2d(e, f, 'valid') + xp_assert_equal(g, h) + + # See gh-5897 + g = convolve2d(f, e, 'valid') + xp_assert_equal(g, h) + + @skip_xp_backends("torch", reason="dtypes do not match") + def test_valid_mode_complx(self, xp): + e = xp.asarray([[2, 3, 4, 5, 6, 7, 8], [4, 5, 6, 7, 8, 9, 10]]) + f = xp.asarray([[1, 2, 3], [3, 4, 5]], dtype=xp.complex128) + 1j + h = xp.asarray([[62.+24.j, 80.+30.j, 98.+36.j, 116.+42.j, 134.+48.j]]) + + g = convolve2d(e, f, 'valid') + xp_assert_close(g, h) + + # See gh-5897 + g = convolve2d(f, e, 'valid') + xp_assert_equal(g, h) + + @skip_xp_backends("jax.numpy", reason="jax only allows fillvalue=0") + def test_fillvalue(self, xp): + a = xp.asarray([[1, 2, 3], [3, 4, 5]]) + b = xp.asarray([[2, 3, 4], [4, 5, 6]]) + fillval = 1 + c = convolve2d(a, b, 'full', 'fill', fillval) + d = xp.asarray([[24, 26, 31, 34, 32], + [28, 40, 62, 64, 52], + [32, 46, 67, 62, 48]]) + xp_assert_equal(c, d) + + def test_fillvalue_errors(self, xp): + msg = "could not cast `fillvalue` directly to the output " + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", "Casting complex values", ComplexWarning) + with assert_raises(ValueError, match=msg): + convolve2d([[1]], [[1, 2]], fillvalue=1j) + + msg = "`fillvalue` must be scalar or an array with " + with assert_raises(ValueError, match=msg): + convolve2d([[1]], [[1, 2]], fillvalue=[1, 2]) + + def test_fillvalue_empty(self, xp): + # Check that fillvalue being empty raises an error: + assert_raises(ValueError, convolve2d, [[1]], [[1, 2]], + fillvalue=[]) + + @skip_xp_backends("jax.numpy", reason="jax only supports boundary='fill'") + def test_wrap_boundary(self, xp): + a = xp.asarray([[1, 2, 3], [3, 4, 5]]) + b = xp.asarray([[2, 3, 4], [4, 5, 6]]) + c = convolve2d(a, b, 'full', 'wrap') + d = xp.asarray([[80, 80, 74, 80, 80], + [68, 68, 62, 68, 68], + [80, 80, 74, 80, 80]]) + xp_assert_equal(c, d) + + @skip_xp_backends("jax.numpy", reason="jax only supports boundary='fill'") + def test_sym_boundary(self, xp): + a = xp.asarray([[1, 2, 3], [3, 4, 5]]) + b = xp.asarray([[2, 3, 4], [4, 5, 6]]) + c = convolve2d(a, b, 'full', 'symm') + d = xp.asarray([[34, 30, 44, 62, 66], + [52, 48, 62, 80, 84], + [82, 78, 92, 110, 114]]) + xp_assert_equal(c, d) + + @skip_xp_backends("jax.numpy", reason="jax only supports boundary='fill'") + @pytest.mark.parametrize('func', [convolve2d, correlate2d]) + @pytest.mark.parametrize('boundary, expected', + [('symm', [[37.0, 42.0, 44.0, 45.0]]), + ('wrap', [[43.0, 44.0, 42.0, 39.0]])]) + def test_same_with_boundary(self, func, boundary, expected, xp): + # Test boundary='symm' and boundary='wrap' with a "long" kernel. + # The size of the kernel requires that the values in the "image" + # be extended more than once to handle the requested boundary method. + # This is a regression test for gh-8684 and gh-8814. + image = xp.asarray([[2.0, -1.0, 3.0, 4.0]]) + kernel = xp.ones((1, 21)) + result = func(image, kernel, mode='same', boundary=boundary) + # The expected results were calculated "by hand". Because the + # kernel is all ones, the same result is expected for convolve2d + # and correlate2d. + xp_assert_equal(result, xp.asarray(expected)) + + @skip_xp_backends("jax.numpy", reason="jax only supports boundary='fill'") + def test_boundary_extension_same(self, xp): + # Regression test for gh-12686. + # Use ndimage.convolve with appropriate arguments to create the + # expected result. + import scipy.ndimage as ndi + a = xp.reshape(xp.arange(1, 10*3+1, dtype=xp.float64), (10, 3)) + b = xp.reshape(xp.arange(1, 10*10+1, dtype=xp.float64), (10, 10)) + c = convolve2d(a, b, mode='same', boundary='wrap') + xp_assert_equal(c, ndi.convolve(a, b, mode='wrap', origin=(-1, -1))) + + @skip_xp_backends("jax.numpy", reason="jax only supports boundary='fill'") + def test_boundary_extension_full(self, xp): + # Regression test for gh-12686. + # Use ndimage.convolve with appropriate arguments to create the + # expected result. + import scipy.ndimage as ndi + a = xp.reshape(xp.arange(1, 3*3+1, dtype=xp.float64), (3, 3)) + b = xp.reshape(xp.arange(1, 6*6+1, dtype=xp.float64), (6, 6)) + c = convolve2d(a, b, mode='full', boundary='wrap') + + a_np = np.arange(1, 3*3 +1, dtype=float).reshape(3, 3) + apad_np = np.pad(a_np, ((3, 3), (3, 3)), 'wrap') + apad = xp.asarray(apad_np) + xp_assert_equal(c, xp.asarray(ndi.convolve(apad, b, mode='wrap')[:-1, :-1])) + + def test_invalid_shapes(self, xp): + # By "invalid," we mean that no one + # array has dimensions that are all at + # least as large as the corresponding + # dimensions of the other array. This + # setup should throw a ValueError. + a = xp.reshape(xp.arange(1, 7), (2, 3)) + b = xp.reshape(xp.arange(-6, 0), (3, 2)) + + assert_raises(ValueError, convolve2d, *(a, b), **{'mode': 'valid'}) + assert_raises(ValueError, convolve2d, *(b, a), **{'mode': 'valid'}) + + @skip_xp_backends("jax.numpy", + reason="jax returns floats; scipy returns ints; cf gh-6076") + def test_same_mode(self, xp): + e = xp.asarray([[1, 2, 3], [3, 4, 5]]) + f = xp.asarray([[2, 3, 4, 5, 6, 7, 8], [4, 5, 6, 7, 8, 9, 10]]) + g = convolve2d(e, f, 'same') + h = xp.asarray([[22, 28, 34], + [80, 98, 116]]) + xp_assert_equal(g, h) + + @skip_xp_backends("jax.numpy", + reason="jax returns floats; scipy returns ints; cf gh-6076") + def test_valid_mode2(self, xp): + # See gh-5897 + e = xp.asarray([[1, 2, 3], [3, 4, 5]]) + f = xp.asarray([[2, 3, 4, 5, 6, 7, 8], [4, 5, 6, 7, 8, 9, 10]]) + expected = xp.asarray([[62, 80, 98, 116, 134]]) + + out = convolve2d(e, f, 'valid') + xp_assert_equal(out, expected) + + out = convolve2d(f, e, 'valid') + xp_assert_equal(out, expected) + + e = xp.asarray([[1 + 1j, 2 - 3j], [3 + 1j, 4 + 0j]]) + f = xp.asarray([[2 - 1j, 3 + 2j, 4 + 0j], [4 - 0j, 5 + 1j, 6 - 3j]]) + expected = xp.asarray([[27 - 1j, 46. + 2j]]) + + out = convolve2d(e, f, 'valid') + xp_assert_equal(out, expected) + + # See gh-5897 + out = convolve2d(f, e, 'valid') + xp_assert_equal(out, expected) + + @skip_xp_backends("torch", + reason="only integer tensors of a single element can be converted" + ) + def test_consistency_convolve_funcs(self, xp): + # Compare np.convolve, signal.convolve, signal.convolve2d + a = xp.arange(5) + b = xp.asarray([3.2, 1.4, 3]) + a_np = _xp_copy_to_numpy(a) + b_np = _xp_copy_to_numpy(b) + + for mode in ['full', 'valid', 'same']: + xp_assert_close( + xp.asarray(np.convolve(a_np, b_np, mode=mode)), + signal.convolve(a, b, mode=mode) + ) + xp_assert_close( + xp.squeeze( + signal.convolve2d(a[None, :], b[None, :], mode=mode), + axis=0 + ), + signal.convolve(a, b, mode=mode) + ) + + def test_invalid_dims(self, xp): + assert_raises(ValueError, convolve2d, 3, 4) + assert_raises(ValueError, convolve2d, [3], [4]) + assert_raises(ValueError, convolve2d, [[[3]]], [[[4]]]) + + @pytest.mark.slow + @pytest.mark.xfail_on_32bit("Can't create large array for test") + @skip_xp_backends(np_only=True, reason="stride_tricks") + def test_large_array(self, xp): + # Test indexing doesn't overflow an int (gh-10761) + n = 2**31 // (1000 * xp.int64().itemsize) + _testutils.check_free_memory(2 * n * 1001 * np.int64().itemsize / 1e6) + + # Create a chequered pattern of 1s and 0s + a = xp.zeros(1001 * n, dtype=xp.int64) + a[::2] = 1 + a = np.lib.stride_tricks.as_strided(a, shape=(n, 1000), strides=(8008, 8)) + + count = signal.convolve2d(a, [[1, 1]]) + fails = np.where(count > 1) + assert fails[0].size == 0 + + +@make_xp_test_case(fftconvolve) +class TestFFTConvolve: + + @skip_xp_backends("torch", reason="dtypes do not match") + @pytest.mark.parametrize('axes', ['', None, 0, [0], -1, [-1]]) + def test_real(self, axes, xp): + a = xp.asarray([1, 2, 3]) + expected = xp.asarray([1, 4, 10, 12, 9.]) + + if axes == '': + out = fftconvolve(a, a) + else: + if isinstance(axes, list): + axes = tuple(axes) + out = fftconvolve(a, a, axes=axes) + + xp_assert_close(out, expected, atol=1.5e-6) + + @skip_xp_backends("torch", reason="dtypes do not match") + @pytest.mark.parametrize('axes', [1, [1], -1, [-1]]) + def test_real_axes(self, axes, xp): + a = xp.asarray([1, 2, 3]) + expected = xp.asarray([1, 4, 10, 12, 9.]) + + a = xp.asarray(np.tile(a, [2, 1])) + expected = xp.asarray(np.tile(expected, [2, 1])) + + if isinstance(axes, list): + axes = tuple(axes) + + out = fftconvolve(a, a, axes=axes) + xp_assert_close(out, expected, atol=1.5e-6) + + @pytest.mark.parametrize('axes', ['', None, 0, [0], -1, [-1]]) + def test_complex(self, axes, xp): + a = xp.asarray([1 + 1j, 2 + 2j, 3 + 3j]) + expected = xp.asarray([0 + 2j, 0 + 8j, 0 + 20j, 0 + 24j, 0 + 18j]) + + if axes == '': + out = fftconvolve(a, a) + else: + if isinstance(axes, list): + axes = tuple(axes) + out = fftconvolve(a, a, axes=axes) + xp_assert_close(out, expected, atol=1.5e-6) + + @pytest.mark.parametrize('axes', [1, [1], -1, [-1]]) + def test_complex_axes(self, axes, xp): + a = xp.asarray([1 + 1j, 2 + 2j, 3 + 3j]) + expected = xp.asarray([0 + 2j, 0 + 8j, 0 + 20j, 0 + 24j, 0 + 18j]) + + a = xp.asarray(np.tile(a, [2, 1])) + expected = xp.asarray(np.tile(expected, [2, 1])) + + if isinstance(axes, list): + axes = tuple(axes) + + out = fftconvolve(a, a, axes=axes) + xp_assert_close(out, expected, atol=1.5e-6) + + @pytest.mark.parametrize('axes', ['', + None, + [0, 1], + [1, 0], + [0, -1], + [-1, 0], + [-2, 1], + [1, -2], + [-2, -1], + [-1, -2]]) + def test_2d_real_same(self, axes, xp): + a = xp.asarray([[1.0, 2, 3], + [4, 5, 6]]) + expected = xp.asarray([[1.0, 4, 10, 12, 9], + [8, 26, 56, 54, 36], + [16, 40, 73, 60, 36]]) + + if axes == '': + out = fftconvolve(a, a) + else: + if isinstance(axes, list): + axes = tuple(axes) + out = fftconvolve(a, a, axes=axes) + xp_assert_close(out, expected) + + @pytest.mark.parametrize('axes', [[1, 2], + [2, 1], + [1, -1], + [-1, 1], + [-2, 2], + [2, -2], + [-2, -1], + [-1, -2]]) + def test_2d_real_same_axes(self, axes, xp): + a = xp.asarray([[1, 2, 3], + [4, 5, 6]]) + expected = xp.asarray([[1, 4, 10, 12, 9], + [8, 26, 56, 54, 36], + [16, 40, 73, 60, 36]]) + + a = xp.asarray(np.tile(a, [2, 1, 1])) + expected = xp.asarray(np.tile(expected, [2, 1, 1])) + + if isinstance(axes, list): + axes = tuple(axes) + + out = fftconvolve(a, a, axes=axes) + xp_assert_close(out, expected, atol=1.5e-6, check_dtype=False) + + @pytest.mark.parametrize('axes', ['', + None, + [0, 1], + [1, 0], + [0, -1], + [-1, 0], + [-2, 1], + [1, -2], + [-2, -1], + [-1, -2]]) + def test_2d_complex_same(self, axes, xp): + a = xp.asarray([[1 + 2j, 3 + 4j, 5 + 6j], + [2 + 1j, 4 + 3j, 6 + 5j]]) + expected = xp.asarray([ + [-3 + 4j, -10 + 20j, -21 + 56j, -18 + 76j, -11 + 60j], + [10j, 44j, 118j, 156j, 122j], + [3 + 4j, 10 + 20j, 21 + 56j, 18 + 76j, 11 + 60j] + ]) + + if axes == '': + out = fftconvolve(a, a) + else: + if isinstance(axes, list): + axes = tuple(axes) + out = fftconvolve(a, a, axes=axes) + + xp_assert_close(out, expected, atol=1.5e-6) + + @pytest.mark.parametrize('axes', [[1, 2], + [2, 1], + [1, -1], + [-1, 1], + [-2, 2], + [2, -2], + [-2, -1], + [-1, -2]]) + def test_2d_complex_same_axes(self, axes, xp): + a = xp.asarray([[1 + 2j, 3 + 4j, 5 + 6j], + [2 + 1j, 4 + 3j, 6 + 5j]]) + expected = xp.asarray([ + [-3 + 4j, -10 + 20j, -21 + 56j, -18 + 76j, -11 + 60j], + [10j, 44j, 118j, 156j, 122j], + [3 + 4j, 10 + 20j, 21 + 56j, 18 + 76j, 11 + 60j] + ]) + + a = xp.asarray(np.tile(a, [2, 1, 1])) + expected = xp.asarray(np.tile(expected, [2, 1, 1])) + + if isinstance(axes, list): + axes = tuple(axes) + + out = fftconvolve(a, a, axes=axes) + xp_assert_close(out, expected, atol=1.5e-6) + + @skip_xp_backends("torch", reason="dtypes do not match") + @pytest.mark.parametrize('axes', ['', None, 0, [0], -1, [-1]]) + def test_real_same_mode(self, axes, xp): + a = xp.asarray([1, 2, 3]) + b = xp.asarray([3, 3, 5, 6, 8, 7, 9, 0, 1]) + expected_1 = xp.asarray([35., 41., 47.]) + expected_2 = xp.asarray([9., 20., 25., 35., 41., 47., 39., 28., 2.]) + + if axes == '': + out = fftconvolve(a, b, 'same') + else: + if isinstance(axes, list): + axes = tuple(axes) + out = fftconvolve(a, b, 'same', axes=axes) + xp_assert_close(out, expected_1) + + if axes == '': + out = fftconvolve(b, a, 'same') + else: + if isinstance(axes, list): + axes = tuple(axes) + out = fftconvolve(b, a, 'same', axes=axes) + xp_assert_close(out, expected_2, atol=1.5e-6) + + @skip_xp_backends("torch", reason="dtypes do not match") + @pytest.mark.parametrize('axes', [1, -1, [1], [-1]]) + def test_real_same_mode_axes(self, axes, xp): + a = xp.asarray([1, 2, 3]) + b = xp.asarray([3, 3, 5, 6, 8, 7, 9, 0, 1]) + expected_1 = xp.asarray([35., 41., 47.]) + expected_2 = xp.asarray([9., 20., 25., 35., 41., 47., 39., 28., 2.]) + + a = xp.asarray(np.tile(a, [2, 1])) + b = xp.asarray(np.tile(b, [2, 1])) + expected_1 = xp.asarray(np.tile(expected_1, [2, 1])) + expected_2 = xp.asarray(np.tile(expected_2, [2, 1])) + + if isinstance(axes, list): + axes = tuple(axes) + + out = fftconvolve(a, b, 'same', axes=axes) + xp_assert_close(out, expected_1, atol=1.5e-6) + + out = fftconvolve(b, a, 'same', axes=axes) + xp_assert_close(out, expected_2, atol=1.5e-6) + + @skip_xp_backends("torch", reason="dtypes do not match") + @pytest.mark.parametrize('axes', ['', None, 0, [0], -1, [-1]]) + def test_valid_mode_real(self, axes, xp): + # See gh-5897 + a = xp.asarray([3, 2, 1]) + b = xp.asarray([3, 3, 5, 6, 8, 7, 9, 0, 1]) + expected = xp.asarray([24., 31., 41., 43., 49., 25., 12.]) + + if axes == '': + out = fftconvolve(a, b, 'valid') + else: + if isinstance(axes, list): + axes = tuple(axes) + out = fftconvolve(a, b, 'valid', axes=axes) + xp_assert_close(out, expected, atol=1.5e-6) + + if axes == '': + out = fftconvolve(b, a, 'valid') + else: + if isinstance(axes, list): + axes = tuple(axes) + out = fftconvolve(b, a, 'valid', axes=axes) + xp_assert_close(out, expected, atol=1.5e-6) + + @skip_xp_backends("torch", reason="dtypes do not match") + @pytest.mark.parametrize('axes', [1, [1]]) + def test_valid_mode_real_axes(self, axes, xp): + # See gh-5897 + a = xp.asarray([3, 2, 1]) + b = xp.asarray([3, 3, 5, 6, 8, 7, 9, 0, 1]) + expected = xp.asarray([24., 31., 41., 43., 49., 25., 12.]) + + a = xp.asarray(np.tile(a, [2, 1])) + b = xp.asarray(np.tile(b, [2, 1])) + expected = xp.asarray(np.tile(expected, [2, 1])) + + if isinstance(axes, list): + axes = tuple(axes) + + out = fftconvolve(a, b, 'valid', axes=axes) + xp_assert_close(out, expected, atol=1.5e-6) + + @pytest.mark.parametrize('axes', ['', None, 0, [0], -1, [-1]]) + def test_valid_mode_complex(self, axes, xp): + a = xp.asarray([3 - 1j, 2 + 7j, 1 + 0j]) + b = xp.asarray([3 + 2j, 3 - 3j, 5 + 0j, 6 - 1j, 8 + 0j]) + expected = xp.asarray([45. + 12.j, 30. + 23.j, 48 + 32.j]) + + if axes == '': + out = fftconvolve(a, b, 'valid') + else: + if isinstance(axes, list): + axes = tuple(axes) + out = fftconvolve(a, b, 'valid', axes=axes) + xp_assert_close(out, expected, atol=1.5e-6) + + if axes == '': + out = fftconvolve(b, a, 'valid') + else: + if isinstance(axes, list): + axes = tuple(axes) + out = fftconvolve(b, a, 'valid', axes=axes) + xp_assert_close(out, expected, atol=1.5e-6) + + @pytest.mark.parametrize('axes', [1, [1], -1, [-1]]) + def test_valid_mode_complex_axes(self, axes, xp): + a = xp.asarray([3 - 1j, 2 + 7j, 1 + 0j]) + b = xp.asarray([3 + 2j, 3 - 3j, 5 + 0j, 6 - 1j, 8 + 0j]) + expected = xp.asarray([45. + 12.j, 30. + 23.j, 48 + 32.j]) + + a = xp.asarray(np.tile(a, [2, 1])) + b = xp.asarray(np.tile(b, [2, 1])) + expected = xp.asarray(np.tile(expected, [2, 1])) + + if isinstance(axes, list): + axes = tuple(axes) + + out = fftconvolve(a, b, 'valid', axes=axes) + xp_assert_close(out, expected, atol=1.5e-6) + + out = fftconvolve(b, a, 'valid', axes=axes) + xp_assert_close(out, expected, atol=1.5e-6) + + @skip_xp_backends("jax.numpy", reason="mapped axes must have same shape") + @skip_xp_backends("torch", reason="dtypes do not match") + def test_valid_mode_ignore_nonaxes(self, xp): + # See gh-5897 + a = xp.asarray([3, 2, 1]) + b = xp.asarray([3, 3, 5, 6, 8, 7, 9, 0, 1]) + expected = xp.asarray([24., 31., 41., 43., 49., 25., 12.]) + + a = xp.asarray(np.tile(a, [2, 1])) + b = xp.asarray(np.tile(b, [1, 1])) + expected = xp.asarray(np.tile(expected, [2, 1])) + + out = fftconvolve(a, b, 'valid', axes=1) + xp_assert_close(out, expected, atol=1.5e-6) + + @xfail_xp_backends("cupy", reason="dtypes do not match") + @xfail_xp_backends("jax.numpy", reason="assorted error messages") + @pytest.mark.parametrize("a,b", [([], []), ([5, 6], []), ([], [7])]) + def test_empty(self, a, b, xp): + # Regression test for #1745: crashes with 0-length input. + xp_assert_equal( + fftconvolve(xp.asarray(a), xp.asarray(b)), + xp.asarray([]), + ) + + @skip_xp_backends("jax.numpy", reason="jnp.pad: pad_width with nd=0") + def test_zero_rank(self, xp): + a = xp.asarray(4967) + b = xp.asarray(3920) + out = fftconvolve(a, b) + xp_assert_equal(out, a * b) + + def test_single_element(self, xp): + a = xp.asarray([4967]) + b = xp.asarray([3920]) + out = fftconvolve(a, b) + xp_assert_equal(out, + xp.asarray(a * b, dtype=out.dtype)) + + @pytest.mark.parametrize('axes', ['', None, 0, [0], -1, [-1]]) + def test_random_data(self, axes, xp): + rng = np.random.default_rng(1234) + a_np = np.random.rand(1233) + 1j * rng.random(1233) + b_np = np.random.rand(1321) + 1j * rng.random(1321) + expected = xp.asarray(np.convolve(a_np, b_np, 'full')) + a = xp.asarray(a_np) + b = xp.asarray(b_np) + + if axes == '': + out = fftconvolve(a, b, 'full') + else: + if isinstance(axes, list): + axes = tuple(axes) + out = fftconvolve(a, b, 'full', axes=axes) + xp_assert_close(out, expected, rtol=1e-10) + + @pytest.mark.parametrize('axes', [1, [1], -1, [-1]]) + def test_random_data_axes(self, axes, xp): + rng = np.random.default_rng(1234) + a_np = np.random.rand(1233) + 1j * rng.random(1233) + b_np = np.random.rand(1321) + 1j * rng.random(1321) + expected = np.convolve(a_np, b_np, 'full') + a_np = np.tile(a_np, [2, 1]) + b_np = np.tile(b_np, [2, 1]) + expected = xp.asarray(np.tile(expected, [2, 1])) + + a = xp.asarray(a_np) + b = xp.asarray(b_np) + + if isinstance(axes, list): + axes = tuple(axes) + + out = fftconvolve(a, b, 'full', axes=axes) + xp_assert_close(out, expected, rtol=1e-10) + + @xfail_xp_backends(np_only=True, reason="TODO: swapaxes") + @pytest.mark.parametrize('axes', [[1, 4], + [4, 1], + [1, -1], + [-1, 1], + [-4, 4], + [4, -4], + [-4, -1], + [-1, -4]]) + def test_random_data_multidim_axes(self, axes, xp): + a_shape, b_shape = (123, 22), (132, 11) + rng = np.random.default_rng(1234) + a = xp.asarray(np.random.rand(*a_shape) + 1j * rng.random(a_shape)) + b = xp.asarray(np.random.rand(*b_shape) + 1j * rng.random(b_shape)) + expected = convolve2d(a, b, 'full') + + a = a[:, :, None, None, None] + b = b[:, :, None, None, None] + expected = expected[:, :, None, None, None] + + a = xp.moveaxis(a.swapaxes(0, 2), 1, 4) + b = xp.moveaxis(b.swapaxes(0, 2), 1, 4) + expected = xp.moveaxis(expected.swapaxes(0, 2), 1, 4) + + # use 1 for dimension 2 in a and 3 in b to test broadcasting + a = xp.asarray(np.tile(a, [2, 1, 3, 1, 1])) + b = xp.asarray(np.tile(b, [2, 1, 1, 4, 1])) + expected = xp.asarray(np.tile(expected, [2, 1, 3, 4, 1])) + + out = fftconvolve(a, b, 'full', axes=axes) + xp_assert_close(out, expected, rtol=1e-10, atol=1e-10) + + @pytest.mark.slow + @pytest.mark.parametrize( + 'n', + list(range(1, 100)) + + list(range(1000, 1500)) + + np.random.RandomState(1234).randint(1001, 10000, 5).tolist()) + def test_many_sizes(self, n, xp): + a_np = np.random.rand(n) + 1j * np.random.rand(n) + b_np = np.random.rand(n) + 1j * np.random.rand(n) + expected = xp.asarray(np.convolve(a_np, b_np, 'full')) + a = xp.asarray(a_np) + b = xp.asarray(b_np) + + out = fftconvolve(a, b, 'full') + xp_assert_close(out, expected, atol=1e-10) + + out = fftconvolve(a, b, 'full', axes=(0,)) + xp_assert_close(out, expected, atol=1e-10) + + @skip_xp_backends(np_only=True) + def test_fft_nan(self, xp): + n = 1000 + rng = np.random.default_rng(43876432987) + sig_nan = xp.asarray(rng.standard_normal(n)) + + for val in [np.nan, np.inf]: + sig_nan[100] = val + coeffs = xp.asarray(signal.firwin(200, 0.2)) + + msg = "Use of fft convolution.*|invalid value encountered.*" + with pytest.warns(RuntimeWarning, match=msg): + signal.convolve(sig_nan, coeffs, mode='same', method='fft') + + +def fftconvolve_err(*args, **kwargs): + raise RuntimeError('Fell back to fftconvolve') + + +def gen_oa_shapes(sizes): + return [(a, b) for a, b in product(sizes, repeat=2) + if abs(a - b) > 3] + + +def gen_oa_shapes_2d(sizes): + shapes0 = gen_oa_shapes(sizes) + shapes1 = gen_oa_shapes(sizes) + shapes = [ishapes0+ishapes1 for ishapes0, ishapes1 in + zip(shapes0, shapes1)] + + modes = ['full', 'valid', 'same'] + return [ishapes+(imode,) for ishapes, imode in product(shapes, modes) + if imode != 'valid' or + (ishapes[0] > ishapes[1] and ishapes[2] > ishapes[3]) or + (ishapes[0] < ishapes[1] and ishapes[2] < ishapes[3])] + + +def gen_oa_shapes_eq(sizes): + return [(a, b) for a, b in product(sizes, repeat=2) + if a >= b] + + +@make_xp_test_case(oaconvolve) +class TestOAConvolve: + @pytest.mark.slow() + @pytest.mark.parametrize('shape_a_0, shape_b_0', + gen_oa_shapes_eq(list(range(1, 100, 1)) + + list(range(100, 1000, 23))) + ) + def test_real_manylens(self, shape_a_0, shape_b_0, xp): + a = np.random.rand(shape_a_0) + b = np.random.rand(shape_b_0) + expected = xp.asarray(fftconvolve(a, b)) + a = xp.asarray(a) + b = xp.asarray(b) + + out = oaconvolve(a, b) + + assert_array_almost_equal(out, expected) + + @pytest.mark.parametrize('shape_a_0, shape_b_0', + gen_oa_shapes([50, 47, 6, 4, 1])) + @pytest.mark.parametrize('is_complex', [True, False]) + @pytest.mark.parametrize('mode', ['full', 'valid', 'same']) + def test_1d_noaxes(self, shape_a_0, shape_b_0, + is_complex, mode, monkeypatch, xp): + a = np.random.rand(shape_a_0) + b = np.random.rand(shape_b_0) + if is_complex: + a = a + 1j*np.random.rand(shape_a_0) + b = b + 1j*np.random.rand(shape_b_0) + expected = xp.asarray(fftconvolve(a, b, mode=mode)) + a = xp.asarray(a) + b = xp.asarray(b) + + monkeypatch.setattr(signal._signaltools, 'fftconvolve', + fftconvolve_err) + out = oaconvolve(a, b, mode=mode) + + assert_array_almost_equal(out, expected) + + @pytest.mark.parametrize('axes', [0, 1]) + @pytest.mark.parametrize('shape_a_0, shape_b_0', + gen_oa_shapes([50, 47, 6, 4])) + @pytest.mark.parametrize('shape_a_extra', [1, 3]) + @pytest.mark.parametrize('shape_b_extra', [1, 3]) + @pytest.mark.parametrize('is_complex', [True, False]) + @pytest.mark.parametrize('mode', ['full', 'valid', 'same']) + def test_1d_axes(self, axes, shape_a_0, shape_b_0, + shape_a_extra, shape_b_extra, + is_complex, mode, monkeypatch, xp): + ax_a = [shape_a_extra]*2 + ax_b = [shape_b_extra]*2 + ax_a[axes] = shape_a_0 + ax_b[axes] = shape_b_0 + + a = np.random.rand(*ax_a) + b = np.random.rand(*ax_b) + if is_complex: + a = a + 1j*np.random.rand(*ax_a) + b = b + 1j*np.random.rand(*ax_b) + + expected = xp.asarray(fftconvolve(a, b, mode=mode, axes=axes)) + a = xp.asarray(a) + b = xp.asarray(b) + + monkeypatch.setattr(signal._signaltools, 'fftconvolve', + fftconvolve_err) + out = oaconvolve(a, b, mode=mode, axes=axes) + + assert_array_almost_equal(out, expected) + + @pytest.mark.parametrize('shape_a_0, shape_b_0, ' + 'shape_a_1, shape_b_1, mode', + gen_oa_shapes_2d([50, 47, 6, 4])) + @pytest.mark.parametrize('is_complex', [True, False]) + def test_2d_noaxes(self, shape_a_0, shape_b_0, + shape_a_1, shape_b_1, mode, + is_complex, monkeypatch, xp): + a = np.random.rand(shape_a_0, shape_a_1) + b = np.random.rand(shape_b_0, shape_b_1) + if is_complex: + a = a + 1j*np.random.rand(shape_a_0, shape_a_1) + b = b + 1j*np.random.rand(shape_b_0, shape_b_1) + + expected = xp.asarray(fftconvolve(a, b, mode=mode)) + a = xp.asarray(a) + b = xp.asarray(b) + + monkeypatch.setattr(signal._signaltools, 'fftconvolve', + fftconvolve_err) + out = oaconvolve(a, b, mode=mode) + + assert_array_almost_equal(out, expected) + + @pytest.mark.parametrize('axes', [[0, 1], [0, 2], [1, 2]]) + @pytest.mark.parametrize('shape_a_0, shape_b_0, ' + 'shape_a_1, shape_b_1, mode', + gen_oa_shapes_2d([50, 47, 6, 4])) + @pytest.mark.parametrize('shape_a_extra', [1, 3]) + @pytest.mark.parametrize('shape_b_extra', [1, 3]) + @pytest.mark.parametrize('is_complex', [True, False]) + def test_2d_axes(self, axes, shape_a_0, shape_b_0, + shape_a_1, shape_b_1, mode, + shape_a_extra, shape_b_extra, + is_complex, monkeypatch, xp): + ax_a = [shape_a_extra]*3 + ax_b = [shape_b_extra]*3 + ax_a[axes[0]] = shape_a_0 + ax_b[axes[0]] = shape_b_0 + ax_a[axes[1]] = shape_a_1 + ax_b[axes[1]] = shape_b_1 + + a = np.random.rand(*ax_a) + b = np.random.rand(*ax_b) + if is_complex: + a = a + 1j*np.random.rand(*ax_a) + b = b + 1j*np.random.rand(*ax_b) + + axes = tuple(axes) # XXX for CuPy + expected = xp.asarray(fftconvolve(a, b, mode=mode, axes=axes)) + a = xp.asarray(a) + b = xp.asarray(b) + + monkeypatch.setattr(signal._signaltools, 'fftconvolve', + fftconvolve_err) + out = oaconvolve(a, b, mode=mode, axes=axes) + + assert_array_almost_equal(out, expected) + + @xfail_xp_backends("torch", reason="ValueError: Target length must be positive") + @pytest.mark.parametrize("a,b", [([], []), ([5, 6], []), ([], [7])]) + def test_empty(self, a, b, xp): + # Regression test for #1745: crashes with 0-length input. + xp_assert_equal( + oaconvolve(xp.asarray(a), xp.asarray(b)), + xp.asarray([]), check_dtype=False + ) + + def test_zero_rank(self, xp): + a = xp.asarray(4967) + b = xp.asarray(3920) + out = oaconvolve(a, b) + xp_assert_equal(out, a * b) + + def test_single_element(self, xp): + a = xp.asarray([4967]) + b = xp.asarray([3920]) + out = oaconvolve(a, b) + xp_assert_equal(out, a * b) + + +@skip_xp_backends(np_only=True, reason="assertions may differ on backends") +@pytest.mark.parametrize('convapproach', + [make_xp_pytest_param(fftconvolve), + make_xp_pytest_param(oaconvolve)]) +class TestAllFreqConvolves: + + def test_invalid_shapes(self, convapproach, xp): + a = np.arange(1, 7).reshape((2, 3)) + b = np.arange(-6, 0).reshape((3, 2)) + with assert_raises(ValueError, + match="For 'valid' mode, one must be at least " + "as large as the other in every dimension"): + convapproach(a, b, mode='valid') + + def test_invalid_shapes_axes(self, convapproach, xp): + a = np.zeros([5, 6, 2, 1]) + b = np.zeros([5, 6, 3, 1]) + with assert_raises(ValueError, + match=r"incompatible shapes for in1 and in2:" + r" \(5L?, 6L?, 2L?, 1L?\) and" + r" \(5L?, 6L?, 3L?, 1L?\)"): + convapproach(a, b, axes=[0, 1]) + + @pytest.mark.parametrize('a,b', + [([1], 2), + (1, [2]), + ([3], [[2]])]) + def test_mismatched_dims(self, a, b, convapproach, xp): + with assert_raises(ValueError, + match="in1 and in2 should have the same" + " dimensionality"): + convapproach(a, b) + + def test_invalid_flags(self, convapproach, xp): + with assert_raises(ValueError, + match="acceptable mode flags are 'valid'," + " 'same', or 'full'"): + convapproach([1], [2], mode='chips') + + with assert_raises(ValueError, + match="when provided, axes cannot be empty"): + convapproach([1], [2], axes=[]) + + with assert_raises(ValueError, match="axes must be a scalar or " + "iterable of integers"): + convapproach([1], [2], axes=[[1, 2], [3, 4]]) + + with assert_raises(ValueError, match="axes must be a scalar or " + "iterable of integers"): + convapproach([1], [2], axes=[1., 2., 3., 4.]) + + with assert_raises(ValueError, + match="axes exceeds dimensionality of input"): + convapproach([1], [2], axes=[1]) + + with assert_raises(ValueError, + match="axes exceeds dimensionality of input"): + convapproach([1], [2], axes=[-2]) + + with assert_raises(ValueError, + match="all axes must be unique"): + convapproach([1], [2], axes=[0, 0]) + + +@skip_xp_backends(np_only=True, reason="assertions may differ on backends") +@pytest.mark.filterwarnings('ignore::DeprecationWarning') +@pytest.mark.parametrize('dtype', [np.longdouble, np.clongdouble]) +@make_xp_test_case(convolve, fftconvolve) +def test_convolve_longdtype_input(dtype, xp): + x = np.random.random((27, 27)).astype(dtype) + y = np.random.random((4, 4)).astype(dtype) + if np.iscomplexobj(dtype()): + x += .1j + y -= .1j + + res = fftconvolve(x, y) + xp_assert_close(res, convolve(x, y, method='direct')) + assert res.dtype == dtype + + +class TestMedFilt: + + IN = [[50, 50, 50, 50, 50, 92, 18, 27, 65, 46], + [50, 50, 50, 50, 50, 0, 72, 77, 68, 66], + [50, 50, 50, 50, 50, 46, 47, 19, 64, 77], + [50, 50, 50, 50, 50, 42, 15, 29, 95, 35], + [50, 50, 50, 50, 50, 46, 34, 9, 21, 66], + [70, 97, 28, 68, 78, 77, 61, 58, 71, 42], + [64, 53, 44, 29, 68, 32, 19, 68, 24, 84], + [3, 33, 53, 67, 1, 78, 74, 55, 12, 83], + [7, 11, 46, 70, 60, 47, 24, 43, 61, 26], + [32, 61, 88, 7, 39, 4, 92, 64, 45, 61]] + + OUT = [[0, 50, 50, 50, 42, 15, 15, 18, 27, 0], + [0, 50, 50, 50, 50, 42, 19, 21, 29, 0], + [50, 50, 50, 50, 50, 47, 34, 34, 46, 35], + [50, 50, 50, 50, 50, 50, 42, 47, 64, 42], + [50, 50, 50, 50, 50, 50, 46, 55, 64, 35], + [33, 50, 50, 50, 50, 47, 46, 43, 55, 26], + [32, 50, 50, 50, 50, 47, 46, 45, 55, 26], + [7, 46, 50, 50, 47, 46, 46, 43, 45, 21], + [0, 32, 33, 39, 32, 32, 43, 43, 43, 0], + [0, 7, 11, 7, 4, 4, 19, 19, 24, 0]] + + KERNEL_SIZE = [7,3] + + @make_xp_test_case(signal.medfilt, signal.medfilt2d) + def test_basic(self, xp): + + in_ = xp.asarray(self.IN) + out_ = xp.asarray(self.OUT) + kernel_size = xp.asarray(self.KERNEL_SIZE) + + d = signal.medfilt(in_, kernel_size) + e = signal.medfilt2d(xp.asarray(in_, dtype=xp.float64), kernel_size) + xp_assert_equal(d, out_) + xp_assert_equal(d, e, check_dtype=False) + + @pytest.mark.parametrize('dtype', ["uint8", "int8", "uint16", "int16", + "uint32", "int32", "uint64", "int64", + "float32", "float64"]) + @make_xp_test_case(signal.medfilt, signal.medfilt2d) + def test_types(self, dtype, xp): + # volume input and output types match + if is_torch(xp) and dtype in ["uint16", "uint32", "uint64"]: + pytest.skip("torch does not support unisigned ints") + + dtype = getattr(xp, dtype) + in_typed = xp.asarray(self.IN, dtype=dtype) + assert signal.medfilt(in_typed).dtype == dtype + assert signal.medfilt2d(in_typed).dtype == dtype + + @skip_xp_backends(np_only=True, reason="assertions may differ") + @pytest.mark.parametrize('dtype', [np.bool_, np.complex64, np.complex128, + np.clongdouble, np.float16, + "float96", "float128"]) + @make_xp_test_case(signal.medfilt, signal.medfilt2d) + def test_invalid_dtypes(self, dtype, xp): + # We can only test this on platforms that support a native type of float96 or + # float128; comparing to np.longdouble allows us to filter out non-native types + if (dtype in ["float96", "float128"] + and np.finfo(np.longdouble).dtype != dtype): + pytest.skip(f"Platform does not support {dtype}") + + in_typed = np.array(self.IN, dtype=dtype) + with pytest.raises(ValueError, match="not supported"): + signal.medfilt(in_typed) + + with pytest.raises(ValueError, match="not supported"): + signal.medfilt2d(in_typed) + + @skip_xp_backends(np_only=True, reason="object arrays") + @make_xp_test_case(signal.medfilt) + def test_none(self, xp): + # gh-1651, trac #1124. Ensure this does not segfault. + with assert_raises((ValueError, TypeError)): + signal.medfilt(None) + + @skip_xp_backends(np_only=True, reason="strides are only writeable in NumPy") + @make_xp_test_case(signal.medfilt) + def test_odd_strides(self, xp): + # Avoid a regression with possible contiguous + # numpy arrays that have odd strides. The stride value below gets + # us into wrong memory if used (but it does not need to be used) + dummy = xp.arange(10, dtype=xp.float64) + a = dummy[5:6] + a = np.lib.stride_tricks.as_strided(a, strides=(16,)) + xp_assert_close(signal.medfilt(a, 1), xp.asarray([5.])) + + @skip_xp_backends( + "jax.numpy", + reason="chunk assignment does not work on jax immutable arrays" + ) + @pytest.mark.parametrize("dtype", ["uint8", "float32", "float64"]) + @make_xp_test_case(signal.medfilt2d) + def test_medfilt2d_parallel(self, dtype, xp): + dtype = getattr(xp, dtype) + in_typed = xp.asarray(self.IN, dtype=dtype) + expected = xp.asarray(self.OUT, dtype=dtype) + + # This is used to simplify the indexing calculations. + assert in_typed.shape == expected.shape + + # We'll do the calculation in four chunks. M1 and N1 are the dimensions + # of the first output chunk. We have to extend the input by half the + # kernel size to be able to calculate the full output chunk. + M1 = expected.shape[0] // 2 + N1 = expected.shape[1] // 2 + offM = self.KERNEL_SIZE[0] // 2 + 1 + offN = self.KERNEL_SIZE[1] // 2 + 1 + + def apply(chunk): + # in = slice of in_typed to use. + # sel = slice of output to crop it to the correct region. + # out = slice of output array to store in. + M, N = chunk + if M == 0: + Min = slice(0, M1 + offM) + Msel = slice(0, -offM) + Mout = slice(0, M1) + else: + Min = slice(M1 - offM, None) + Msel = slice(offM, None) + Mout = slice(M1, None) + if N == 0: + Nin = slice(0, N1 + offN) + Nsel = slice(0, -offN) + Nout = slice(0, N1) + else: + Nin = slice(N1 - offN, None) + Nsel = slice(offN, None) + Nout = slice(N1, None) + + # Do the calculation, but do not write to the output in the threads. + chunk_data = in_typed[Min, Nin] + med = signal.medfilt2d(chunk_data, self.KERNEL_SIZE) + return med[Msel, Nsel], Mout, Nout + + # Give each chunk to a different thread. + output = xp.zeros_like(expected) + with ThreadPoolExecutor(max_workers=4) as pool: + chunks = {(0, 0), (0, 1), (1, 0), (1, 1)} + futures = {pool.submit(apply, chunk) for chunk in chunks} + + # Store each result in the output as it arrives. + for future in as_completed(futures): + data, Mslice, Nslice = future.result() + output[Mslice, Nslice] = data + + xp_assert_equal(output, expected) + + +@make_xp_test_case(signal.wiener) +class TestWiener: + + @skip_xp_backends("cupy", reason="XXX: can_cast in cupy <= 13.2") + def test_basic(self, xp): + g = xp.asarray([[5, 6, 4, 3], + [3, 5, 6, 2], + [2, 3, 5, 6], + [1, 6, 9, 7]], dtype=xp.float64) + h = xp.asarray([[2.16374269, 3.2222222222, 2.8888888889, 1.6666666667], + [2.666666667, 4.33333333333, 4.44444444444, 2.8888888888], + [2.222222222, 4.4444444444, 5.4444444444, 4.801066874837], + [1.33333333333, 3.92735042735, 6.0712560386, 5.0404040404]]) + assert_array_almost_equal(signal.wiener(g), h, decimal=6) + assert_array_almost_equal(signal.wiener(g, mysize=3), h, decimal=6) + + +padtype_options = ["mean", "median", "minimum", "maximum", "line"] +padtype_options += _upfirdn_modes + + +class TestResample: + + @make_xp_test_case(signal.resample, signal.resample_poly) + @xfail_xp_backends("cupy", reason="does not raise with non-int upsampling factor") + def test_basic(self, xp): + # Some basic tests + + # Regression test for issue #3603. + # window.shape must equal to sig.shape[0] + sig = xp.arange(128, dtype=xp.float64) + num = 256 + win = signal.get_window(('kaiser', 8.0), 160, xp=xp) + assert_raises(ValueError, signal.resample, sig, num, window=win) + assert_raises(ValueError, signal.resample, sig, num, domain='INVALID') + + # Other degenerate conditions + assert_raises(ValueError, signal.resample_poly, sig, 'yo', 1) + assert_raises(ValueError, signal.resample_poly, sig, 1, 0) + assert_raises(ValueError, signal.resample_poly, sig, 1.3, 2) + assert_raises(ValueError, signal.resample_poly, sig, 2, 1.3) + assert_raises(ValueError, signal.resample_poly, sig, 2, 1, padtype='') + assert_raises(ValueError, signal.resample_poly, sig, 2, 1, + padtype='mean', cval=10) + assert_raises(ValueError, signal.resample_poly, sig, 2, 1, window=xp.eye(2)) + + # test for issue #6505 - should not modify window.shape when axis ≠ 0 + sig2 = xp.tile(xp.arange(160, dtype=xp.float64), (2, 1)) + signal.resample(sig2, num, axis=-1, window=win) + assert win.shape == (160,) + + # Ensure coverage for parameter cval=None and cval != None: + x_ref = signal.resample_poly(sig, 2, 1) + x0 = signal.resample_poly(sig, 2, 1, padtype='constant') + x1 = signal.resample_poly(sig, 2, 1, padtype='constant', cval=0) + xp_assert_equal(x1, x_ref) + xp_assert_equal(x0, x_ref) + + @pytest.mark.parametrize('window', (None, 'hamming')) + @pytest.mark.parametrize('N', (20, 19)) + @pytest.mark.parametrize('num', (100, 101, 10, 11)) + @make_xp_test_case(signal.resample) + def test_rfft(self, N, num, window, xp): + # Make sure the speed up using rfft gives the same result as the normal + # way using fft + dt_r = xp_default_dtype(xp) + dt_c = xp.complex64 if dt_r == xp.float32 else xp.complex128 + + x = xp.linspace(0, 10, N, endpoint=False) + y = xp.cos(-x**2/6.0) + desired = signal.resample(xp.astype(y, dt_c), num, window=window) + xp_assert_close(signal.resample(y, num, window=window), + xp.real(desired)) + + y = xp.stack([xp.cos(-x**2/6.0), xp.sin(-x**2/6.0)]) + y_complex = xp.astype(y, dt_c) + resampled = signal.resample(y_complex, num, axis=1, window=window) + + atol = 1e-9 if dt_r == xp.float64 else 3e-7 + + xp_assert_close( + signal.resample(y, num, axis=1, window=window), + xp.real(resampled), + atol=atol) + + @make_xp_test_case(signal.resample) + def test_input_domain(self, xp): + # Test if both input domain modes produce the same results. + tsig = xp.astype(xp.arange(256), xp.complex128) + fsig = sp_fft.fft(tsig) + num = 256 + xp_assert_close( + signal.resample(fsig, num, domain='freq'), + signal.resample(tsig, num, domain='time'), + atol=1e-9) + + @pytest.mark.parametrize('nx', (1, 2, 3, 5, 8)) + @pytest.mark.parametrize('ny', (1, 2, 3, 5, 8)) + @pytest.mark.parametrize('dtype', ('float64', 'complex128')) + @make_xp_test_case(signal.resample) + def test_dc(self, nx, ny, dtype, xp): + dtype = getattr(xp, dtype) + x = xp.asarray([1] * nx, dtype=dtype) + y = signal.resample(x, ny) + xp_assert_close(y, xp.asarray([1] * ny, dtype=y.dtype)) + + @skip_xp_backends("cupy", reason="padtype not supported by upfirdn") + @pytest.mark.parametrize('padtype', padtype_options) + @make_xp_test_case(signal.resample_poly) + def test_mutable_window(self, padtype, xp): + # Test that a mutable window is not modified + impulse = xp.zeros(3) + window = xp.asarray(np.random.RandomState(0).randn(2)) + window_orig = xp.asarray(window, copy=True) + signal.resample_poly(impulse, 5, 1, window=window, padtype=padtype) + xp_assert_equal(window, window_orig) + + @skip_xp_backends("cupy", reason="padtype not supported by upfirdn") + @make_xp_test_case(signal.resample_poly) + @pytest.mark.parametrize('padtype', padtype_options) + def test_output_float32(self, padtype, xp): + # Test that float32 inputs yield a float32 output + x = xp.arange(10, dtype=xp.float32) + h = xp.asarray([1, 1, 1], dtype=xp.float32) + y = signal.resample_poly(x, 1, 2, window=h, padtype=padtype) + assert y.dtype == xp.float32 + + @pytest.mark.parametrize('padtype', padtype_options) + @pytest.mark.parametrize('dtype', ['float32', 'float64']) + @skip_xp_backends("cupy", reason="padtype not supported by upfirdn") + @make_xp_test_case(signal.resample_poly) + def test_output_match_dtype(self, padtype, dtype, xp): + # Test that the dtype of x is preserved per issue #14733 + dtype = getattr(xp, dtype) + x = xp.arange(10, dtype=dtype) + y = signal.resample_poly(x, 1, 2, padtype=padtype) + assert y.dtype == x.dtype + + @skip_xp_backends("cupy", reason="padtype not supported by upfirdn") + @pytest.mark.parametrize( + "method, ext, padtype", + [("fft", False, None)] + + list( + product( + ["polyphase"], [False, True], padtype_options, + ) + ), + ) + @make_xp_test_case(signal.resample, signal.resample_poly) + def test_resample_methods(self, method, ext, padtype, xp): + # Test resampling of sinusoids and random noise (1-sec) + rate = 100 + rates_to = [49, 50, 51, 99, 100, 101, 199, 200, 201] + + # Sinusoids, windowed to avoid edge artifacts + t = xp.arange(rate, dtype=xp.float64) / float(rate) + freqs = xp.asarray((1., 10., 40.))[:, xp.newaxis] + x = xp.sin(2 * xp.pi * freqs * t) * hann(rate, xp=xp) + + for rate_to in rates_to: + t_to = xp.arange(rate_to, dtype=xp.float64) / float(rate_to) + y_tos = xp.sin(2 * xp.pi * freqs * t_to) * hann(rate_to, xp=xp) + if method == 'fft': + y_resamps = signal.resample(x, rate_to, axis=-1) + else: + if ext and rate_to != rate: + # Match default window design + g = gcd(rate_to, rate) + up = rate_to // g + down = rate // g + max_rate = max(up, down) + f_c = 1. / max_rate + half_len = 10 * max_rate + window = signal.firwin(2 * half_len + 1, f_c, + window=('kaiser', 5.0)) + window = xp.asarray(window) + polyargs = {'window': window, 'padtype': padtype} + else: + polyargs = {'padtype': padtype} + + y_resamps = signal.resample_poly(x, rate_to, rate, axis=-1, + **polyargs) + + for i in range(y_tos.shape[0]): + y_to = y_tos[i, :] + y_resamp = y_resamps[i, :] + freq = float(freqs[i, 0]) + if freq >= 0.5 * rate_to: + #y_to.fill(0.) # mostly low-passed away + y_to = xp.zeros_like(y_to) # mostly low-passed away + if padtype in ['minimum', 'maximum']: + xp_assert_close(y_resamp, y_to, atol=3e-1) + else: + xp_assert_close(y_resamp, y_to, atol=1e-3) + else: + assert y_to.shape == y_resamp.shape + corr = np.corrcoef(y_to, y_resamp)[0, 1] + assert corr > 0.99, (corr, rate, rate_to) + + # Random data + rng = np.random.RandomState(0) + x = hann(rate) * np.cumsum(rng.randn(rate)) # low-pass, wind + x = xp.asarray(x) + for rate_to in rates_to: + # random data + t_to = xp.arange(rate_to, dtype=xp.float64) / float(rate_to) + y_to = np.interp(t_to, t, x) + if method == 'fft': + y_resamp = signal.resample(x, rate_to) + else: + y_resamp = signal.resample_poly(x, rate_to, rate, + padtype=padtype) + assert y_to.shape == y_resamp.shape + corr = xp.asarray(np.corrcoef(y_to, y_resamp)[0, 1]) + assert corr > 0.99, corr + + # More tests of fft method (Master 0.18.1 fails these) + if method == 'fft': + x1 = xp.asarray([1.+0.j, 0.+0.j]) + y1_test = signal.resample(x1, 4) + # upsampling a complex array + y1_true = xp.asarray([1.+0.j, 0.5+0.j, 0.+0.j, 0.5+0.j]) + xp_assert_close(y1_test, y1_true, atol=1e-12) + x2 = xp.asarray([1., 0.5, 0., 0.5]) + y2_test = signal.resample(x2, 2) # downsampling a real array + y2_true = xp.asarray([1., 0.]) + xp_assert_close(y2_test, y2_true, atol=1e-12) + + @pytest.mark.parametrize("n_in", (8, 9)) + @pytest.mark.parametrize("n_out", (3, 4)) + @make_xp_test_case(signal.resample) + def test_resample_win_func(self, n_in, n_out): + """Test callable window function. """ + x_in = np.ones(n_in) + + def win(freqs): + """Scale input by 1/2""" + return 0.5 * np.ones_like(freqs) + + y0 = signal.resample(x_in, n_out) + y1 = signal.resample(x_in, n_out, window=win) + + xp_assert_close(2*y1, y0, atol=1e-12) + + @pytest.mark.parametrize("n_in", (6, 12)) + @pytest.mark.parametrize("n_out", (3, 4)) + @make_xp_test_case(signal.resample) + def test__resample_param_t(self, n_in, n_out): + """Verify behavior for parameter `t`. + + Note that only `t[0]` and `t[1]` are utilized. + """ + t0, dt = 10, 2 + x_in = np.ones(n_in) + + y0 = signal.resample(x_in, n_out) + y1, t1 = signal.resample(x_in, n_out, t=[t0, t0+dt]) + t_ref = 10 + np.arange(len(y0)) * dt * n_in / n_out + + xp_assert_equal(y1, y0) # no influence of `t` + xp_assert_close(t1, t_ref, atol=1e-12) + + @pytest.mark.parametrize("n1", (2, 3, 7, 8)) + @pytest.mark.parametrize("n0", (2, 3, 7, 8)) + @make_xp_test_case(signal.resample) + def test_resample_nyquist(self, n0, n1): + """Test behavior at Nyquist frequency to ensure issue #14569 is fixed. """ + f_ny = min(n0, n1) // 2 + tt = (np.arange(n_) / n_ for n_ in (n0, n1)) + x0, x1 = (np.cos(2 * np.pi * f_ny * t_) for t_ in tt) + + y1_r = signal.resample(x0, n1) + y1_c = signal.resample(x0 + 0j, n1) + + xp_assert_close(y1_r, x1, atol=1e-12) + xp_assert_close(y1_c.real, x1, atol=1e-12) + + @pytest.mark.parametrize('down_factor', [2, 11, 79]) + @pytest.mark.parametrize("dtype", [int, np.float32, np.complex64, float, complex]) + @make_xp_test_case(signal.resample_poly) + def test_poly_vs_filtfilt(self, down_factor, dtype, xp): + # Check that up=1.0 gives same answer as filtfilt + slicing + random_state = np.random.RandomState(17) + size = 10000 + + x = random_state.randn(size).astype(dtype) + if dtype in (np.complex64, np.complex128): + x += 1j * random_state.randn(size) + + # resample_poly assumes zeros outside of signl, whereas filtfilt + # can only constant-pad. Make them equivalent: + x[0] = 0 + x[-1] = 0 + + h = signal.firwin(31, 1. / down_factor, window='hamming') + yf = filtfilt(h, 1.0, x, padtype='constant')[::down_factor] + + # Need to pass convolved version of filter to resample_poly, + # since filtfilt does forward and backward, but resample_poly + # only goes forward + hc = convolve(h, np.flip(h)) + + # Use yf.copy() to avoid negative strides, which are unsupported + # in torch. + x, hc, yf = map(xp.asarray, (x, hc, yf.copy())) + y = signal.resample_poly(x, 1, down_factor, window=hc) + xp_assert_close(yf, y, atol=3e-7, rtol=6e-7) + + @make_xp_test_case(signal.resample_poly) + def test_correlate1d(self, xp): + for down in [2, 4]: + for nx in range(1, 40, down): + for nweights in (32, 33): + x = np.random.random((nx,)) + weights = np.random.random((nweights,)) + y_g = correlate1d(x, np.flip(weights), mode='constant') + x, weights, y_g = map(xp.asarray, (x, weights, y_g)) + y_s = signal.resample_poly( + x, up=1, down=down, window=weights) + xp_assert_close(y_g[::down], y_s) + + @make_xp_test_case(signal.resample_poly) + @pytest.mark.parametrize('dtype', ['int32', 'float32']) + @skip_xp_backends("cupy", reason="padtype not supported by upfirdn") + def test_gh_15620(self, dtype, xp): + dtype = getattr(xp, dtype) + data = xp.asarray([0, 1, 2, 3, 2, 1, 0], dtype=dtype) + actual = signal.resample_poly(data, + up=2, + down=1, + padtype='smooth') + assert np.count_nonzero(actual) > 0 + + +@make_xp_test_case(signal.cspline1d_eval) +class TestCSpline1DEval: + + def test_basic(self, xp): + y = np.asarray([1, 2, 3, 4, 3, 2, 1, 2, 3.0]) + x = np.arange(y.shape[0]) + dx = x[1] - x[0] + cj = xp.asarray(signal.cspline1d(y)) + x2 = xp.arange(len(y) * 10.0) / 10.0 + y2 = signal.cspline1d_eval(cj, x2, dx=dx, x0=x[0]) + + # make sure interpolated values are on knot points + assert_array_almost_equal(y2[::10], xp.asarray(y), decimal=5) + + def test_complex(self, xp): + # create some smoothly varying complex signal to interpolate + x = np.arange(2.0) + y = np.zeros(x.shape, dtype=np.complex64) + T = 10.0 + f = 1.0 / T + y = np.exp(2.0J * np.pi * f * x) + + # get the cspline transform + cy = xp.asarray(signal.cspline1d(y)) + + # determine new test x value and interpolate + xnew = xp.asarray([0.5]) + ynew = signal.cspline1d_eval(cy, xnew) + + assert ynew.dtype == xp.asarray(y).dtype + + +@make_xp_test_case(signal.order_filter) +class TestOrderFilt: + + def test_basic(self, xp): + actual = signal.order_filter(xp.asarray([1, 2, 3]), xp.asarray([1, 0, 1]), 1) + expect = xp.asarray([2, 3, 2]) + xp_assert_equal(actual, expect) + + def test_doc_example(self, xp): + x = xp.reshape(xp.arange(25, dtype=xp_default_dtype(xp)), (5, 5)) + domain = xp.eye(3, dtype=xp_default_dtype(xp)) + + # minimum of elements 1,3,9 (zero-padded) on phone pad + # 7,5,3 on numpad + expected = xp.asarray( + [[0., 0., 0., 0., 0.], + [0., 0., 1., 2., 0.], + [0., 5., 6., 7., 0.], + [0., 10., 11., 12., 0.], + [0., 0., 0., 0., 0.]], + dtype=xp_default_dtype(xp) + ) + xp_assert_close(signal.order_filter(x, domain, 0), expected) + + # maximum of elements 1,3,9 (zero-padded) on phone pad + # 7,5,3 on numpad + expected = xp.asarray( + [[6., 7., 8., 9., 4.], + [11., 12., 13., 14., 9.], + [16., 17., 18., 19., 14.], + [21., 22., 23., 24., 19.], + [20., 21., 22., 23., 24.]], + ) + xp_assert_close(signal.order_filter(x, domain, 2), expected) + + # and, just to complete the set, median of zero-padded elements + expected = xp.asarray( + [[0, 1, 2, 3, 0], + [5, 6, 7, 8, 3], + [10, 11, 12, 13, 8], + [15, 16, 17, 18, 13], + [0, 15, 16, 17, 18]], + dtype=xp_default_dtype(xp) + ) + xp_assert_close(signal.order_filter(x, domain, 1), expected) + + @xfail_xp_backends('dask.array', reason='repeat requires an axis') + @xfail_xp_backends('torch', reason='array-api-compat#292') + @make_xp_test_case(signal.medfilt) + def test_medfilt_order_filter(self, xp): + x = xp.reshape(xp.arange(25), (5, 5)) + + # median of zero-padded elements 1,5,9 on phone pad + # 7,5,3 on numpad + expected = xp.asarray( + [[0, 1, 2, 3, 0], + [1, 6, 7, 8, 4], + [6, 11, 12, 13, 9], + [11, 16, 17, 18, 14], + [0, 16, 17, 18, 0]], + ) + xp_assert_close(signal.medfilt(x, 3), expected) + + xp_assert_close( + signal.order_filter(x, xp.ones((3, 3)), 4), + expected + ) + + def test_order_filter_asymmetric(self, xp): + x = xp.reshape(xp.arange(25), (5, 5)) + domain = xp.asarray( + [[1, 1, 0], + [0, 1, 0], + [0, 0, 0]], + ) + + expected = xp.asarray( + [[0, 0, 0, 0, 0], + [0, 0, 1, 2, 3], + [0, 5, 6, 7, 8], + [0, 10, 11, 12, 13], + [0, 15, 16, 17, 18]] + ) + xp_assert_close(signal.order_filter(x, domain, 0), expected) + + expected = xp.asarray( + [[0, 0, 0, 0, 0], + [0, 1, 2, 3, 4], + [5, 6, 7, 8, 9], + [10, 11, 12, 13, 14], + [15, 16, 17, 18, 19]] + ) + xp_assert_close(signal.order_filter(x, domain, 1), expected) + + +@make_xp_test_case(lfilter) +class _TestLinearFilter: + def generate(self, shape, xp): + prodshape = shape if isinstance(shape, int) else math.prod(shape) + x = xp.linspace(0, prodshape - 1, prodshape) + if not isinstance(shape, int): + x = xp.reshape(x, shape) + return self.convert_dtype(x, xp) + + def convert_dtype(self, arr, xp): + if self.dtype == np.dtype('O'): + arr = np.asarray(arr) + out = np.empty(arr.shape, self.dtype) + iter = np.nditer([arr, out], ['refs_ok','zerosize_ok'], + [['readonly'],['writeonly']]) + for x, y in iter: + y[...] = self.type(x[()]) + return out + else: + dtype = (getattr(xp, self.dtype) + if isinstance(self.dtype, str) + else self.dtype) + return xp.asarray(arr, dtype=dtype) + + @skip_xp_backends('cupy', reason='XXX https://github.com/scipy/scipy/issues/23539') + def test_invalid_params(self, xp): + """Verify all exceptions are raised. """ + b, a, x = xp.asarray([1]), xp.asarray([2]), xp.asarray([3, 4]) + with pytest.raises(ValueError, match="^Parameter b is not"): + lfilter(xp.eye(2), a, x) # b not one-dimensional + with pytest.raises(ValueError, match="^Parameter b is not"): + lfilter(xp.asarray([]), a, x) # b empty + with pytest.raises(ValueError, match="^Parameter a is not"): + lfilter(b, xp.eye(2), x) # a not one-dimensional + with pytest.raises(ValueError, match="^Parameter a is not"): + lfilter(b, xp.asarray([]), x) # a empty + with pytest.raises(NotImplementedError, match="^Parameter's dtypes produced "): + b, a, x = (xp.astype(v_, xp.uint64, copy=False) for v_ in (b, a, x)) + lfilter(b, a, x) # fails with uint64 dtype + + def test_rank_1_IIR(self, xp): + x = self.generate((6,), xp) + b = self.convert_dtype([1, -1], xp) + a = self.convert_dtype([0.5, -0.5], xp) + y_r = self.convert_dtype([0, 2, 4, 6, 8, 10.], xp) + assert_array_almost_equal(lfilter(b, a, x), y_r) + + def test_rank_1_FIR(self, xp): + x = self.generate((6,), xp) + b = self.convert_dtype([1, 1], xp) + a = self.convert_dtype([1], xp) + y_r = self.convert_dtype([0, 1, 3, 5, 7, 9.], xp) + assert_array_almost_equal(lfilter(b, a, x), y_r) + + @skip_xp_backends('cupy', reason='XXX https://github.com/cupy/cupy/pull/8677') + def test_rank_1_IIR_init_cond(self, xp): + x = self.generate((6,), xp) + b = self.convert_dtype([1, 0, -1], xp) + a = self.convert_dtype([0.5, -0.5], xp) + zi = self.convert_dtype([1, 2], xp) + y_r = self.convert_dtype([1, 5, 9, 13, 17, 21], xp) + zf_r = self.convert_dtype([13, -10], xp) + y, zf = lfilter(b, a, x, zi=zi) + assert_array_almost_equal(y, y_r) + assert_array_almost_equal(zf, zf_r) + + @skip_xp_backends('cupy', reason='XXX https://github.com/cupy/cupy/pull/8677') + def test_rank_1_FIR_init_cond(self, xp): + x = self.generate((6,), xp) + b = self.convert_dtype([1, 1, 1], xp) + a = self.convert_dtype([1], xp) + zi = self.convert_dtype([1, 1], xp) + y_r = self.convert_dtype([1, 2, 3, 6, 9, 12.], xp) + zf_r = self.convert_dtype([9, 5], xp) + y, zf = lfilter(b, a, x, zi=zi) + assert_array_almost_equal(y, y_r) + assert_array_almost_equal(zf, zf_r) + + def test_rank_2_IIR_axis_0(self, xp): + x = self.generate((4, 3), xp) + b = self.convert_dtype([1, -1], xp) + a = self.convert_dtype([0.5, 0.5], xp) + y_r2_a0 = self.convert_dtype([[0, 2, 4], [6, 4, 2], [0, 2, 4], + [6, 4, 2]], xp) + y = lfilter(b, a, x, axis=0) + assert_array_almost_equal(y_r2_a0, y) + + def test_rank_2_IIR_axis_1(self, xp): + x = self.generate((4, 3), xp) + b = self.convert_dtype([1, -1], xp) + a = self.convert_dtype([0.5, 0.5], xp) + y_r2_a1 = self.convert_dtype([[0, 2, 0], [6, -4, 6], [12, -10, 12], + [18, -16, 18]], xp) + y = lfilter(b, a, x, axis=1) + assert_array_almost_equal(y_r2_a1, y) + + @skip_xp_backends('cupy', reason='XXX https://github.com/cupy/cupy/pull/8677') + def test_rank_2_IIR_axis_0_init_cond(self, xp): + x = self.generate((4, 3), xp) + b = self.convert_dtype([1, -1], xp) + a = self.convert_dtype([0.5, 0.5], xp) + zi = self.convert_dtype(np.ones((4,1)), xp) + + y_r2_a0_1 = self.convert_dtype([[1, 1, 1], [7, -5, 7], [13, -11, 13], + [19, -17, 19]], xp) + zf_r = self.convert_dtype([-5, -17, -29, -41], xp)[:, np.newaxis] + y, zf = lfilter(b, a, x, axis=1, zi=zi) + assert_array_almost_equal(y_r2_a0_1, y) + assert_array_almost_equal(zf, zf_r) + + @skip_xp_backends('cupy', reason='XXX https://github.com/cupy/cupy/pull/8677') + def test_rank_2_IIR_axis_1_init_cond(self, xp): + x = self.generate((4, 3), xp) + b = self.convert_dtype([1, -1], xp) + a = self.convert_dtype([0.5, 0.5], xp) + zi = self.convert_dtype(np.ones((1, 3)), xp) + + y_r2_a0_0 = self.convert_dtype([[1, 3, 5], [5, 3, 1], + [1, 3, 5], [5, 3, 1]], xp) + zf_r = self.convert_dtype([[-23, -23, -23]], xp) + y, zf = lfilter(b, a, x, axis=0, zi=zi) + assert_array_almost_equal(y_r2_a0_0, y) + assert_array_almost_equal(zf, zf_r) + + def test_rank_3_IIR(self, xp): + x = self.generate((4, 3, 2), xp) + b = self.convert_dtype([1, -1], xp) + a = self.convert_dtype([0.5, 0.5], xp) + a_np, b_np, x_np = map(_xp_copy_to_numpy, (a, b, x)) + for axis in range(x.ndim): + y = lfilter(b, a, x, axis) + y_r = np.apply_along_axis(lambda w: lfilter(b_np, a_np, w), axis, x_np) + assert_array_almost_equal(y, xp.asarray(y_r)) + + @xfail_xp_backends("cupy", reason="inaccurate") + def test_rank_3_IIR_init_cond(self, xp): + x = self.generate((4, 3, 2), xp) + b = self.convert_dtype([1, -1], xp) + a = self.convert_dtype([0.5, 0.5], xp) + + for axis in range(x.ndim): + zi_shape = list(x.shape) + zi_shape[axis] = 1 + zi = self.convert_dtype(xp.ones(zi_shape), xp) + zi1 = self.convert_dtype([1], xp) + y, zf = lfilter(b, a, x, axis, zi) + b_np, a_np, zi1_np = map(_xp_copy_to_numpy, (b, a, zi1)) + def lf0(w): + return lfilter(b_np, a_np, w, zi=zi1_np)[0] + def lf1(w): + return lfilter(b_np, a_np, w, zi=zi1_np)[1] + y_r = np.apply_along_axis(lf0, axis, _xp_copy_to_numpy(x)) + zf_r = np.apply_along_axis(lf1, axis, _xp_copy_to_numpy(x)) + assert_array_almost_equal(y, xp.asarray(y_r)) + assert_array_almost_equal(zf, xp.asarray(zf_r)) + + def test_rank_3_FIR(self, xp): + x = self.generate((4, 3, 2), xp) + b = self.convert_dtype([1, 0, -1], xp) + a = self.convert_dtype([1], xp) + + a_np, b_np, x_np = map(_xp_copy_to_numpy, (a, b, x)) + for axis in range(x.ndim): + y = lfilter(b, a, x, axis) + y_r = np.apply_along_axis(lambda w: lfilter(b_np, a_np, w), axis, x_np) + assert_array_almost_equal(y, xp.asarray(y_r)) + + @xfail_xp_backends("cupy", reason="inaccurate") + def test_rank_3_FIR_init_cond(self, xp): + x = self.generate((4, 3, 2), xp) + b = self.convert_dtype([1, 0, -1], xp) + a = self.convert_dtype([1], xp) + + x_np, b_np, a_np = map(_xp_copy_to_numpy, (x, b, a)) + for axis in range(x.ndim): + zi_shape = list(x.shape) + zi_shape[axis] = 2 + zi = self.convert_dtype(xp.ones(zi_shape), xp) + zi1 = self.convert_dtype([1, 1], xp) + zi1_np = _xp_copy_to_numpy(zi1) + y, zf = lfilter(b, a, x, axis, zi) + b_np, a_np, zi1_np = map(_xp_copy_to_numpy, (b, a, zi1)) + def lf0(w): + return lfilter(b_np, a_np, w, zi=zi1_np)[0] + def lf1(w): + return lfilter(b_np, a_np, w, zi=zi1_np)[1] + y_r = np.apply_along_axis(lf0, axis, x_np) + zf_r = np.apply_along_axis(lf1, axis, x_np) + assert_array_almost_equal(y, xp.asarray(y_r)) + assert_array_almost_equal(zf, xp.asarray(zf_r)) + + @skip_xp_backends('cupy', reason='XXX https://github.com/cupy/cupy/pull/8677') + def test_zi_pseudobroadcast(self, xp): + x = self.generate((4, 5, 20), xp) + b, a = signal.butter(8, 0.2, output='ba') + b = self.convert_dtype(b, xp) + a = self.convert_dtype(a, xp) + zi_size = b.shape[0] - 1 + + # lfilter requires x.ndim == zi.ndim exactly. However, zi can have + # length 1 dimensions. + zi_full = self.convert_dtype(xp.ones((4, 5, zi_size)), xp) + zi_sing = self.convert_dtype(xp.ones((1, 1, zi_size)), xp) + + y_full, zf_full = lfilter(b, a, x, zi=zi_full) + y_sing, zf_sing = lfilter(b, a, x, zi=zi_sing) + + assert_array_almost_equal(y_sing, y_full) + assert_array_almost_equal(zf_full, zf_sing) + + # lfilter does not prepend ones + assert_raises(ValueError, lfilter, b, a, x, -1, xp.ones(zi_size)) + + @skip_xp_backends('cupy', reason='XXX https://github.com/cupy/cupy/pull/8677') + def test_scalar_a(self, xp): + # a can be a scalar. + x = self.generate(6, xp) + b = self.convert_dtype([1, 0, -1], xp) + a = self.convert_dtype([1], xp) + y_r = self.convert_dtype([0, 1, 2, 2, 2, 2], xp) + + y = lfilter(b, a[0], x) + assert_array_almost_equal(y, y_r) + + @skip_xp_backends('cupy', reason='XXX https://github.com/cupy/cupy/pull/8677') + def test_zi_some_singleton_dims(self, xp): + # lfilter doesn't really broadcast (no prepending of 1's). But does + # do singleton expansion if x and zi have the same ndim. This was + # broken only if a subset of the axes were singletons (gh-4681). + x = self.convert_dtype(xp.zeros((3, 2, 5), dtype=xp.int64), xp) + b = self.convert_dtype(xp.ones(5, dtype=xp.int64), xp) + a = self.convert_dtype(xp.asarray([1, 0, 0]), xp) + zi = np.ones((3, 1, 4), dtype=np.int64) + zi[1, :, :] *= 2 + zi[2, :, :] *= 3 + zi = xp.asarray(zi) + zi = self.convert_dtype(zi, xp) + + zf_expected = self.convert_dtype(xp.zeros((3, 2, 4), dtype=xp.int64), xp) + y_expected = np.zeros((3, 2, 5), dtype=np.int64) + y_expected[:, :, :4] = [[[1]], [[2]], [[3]]] + y_expected = xp.asarray(y_expected) + y_expected = self.convert_dtype(y_expected, xp) + + # IIR + y_iir, zf_iir = lfilter(b, a, x, -1, zi) + assert_array_almost_equal(y_iir, y_expected) + assert_array_almost_equal(zf_iir, zf_expected) + + # FIR + y_fir, zf_fir = lfilter(b, a[0], x, -1, zi) + assert_array_almost_equal(y_fir, y_expected) + assert_array_almost_equal(zf_fir, zf_expected) + + def base_bad_size_zi(self, b, a, x, axis, zi, xp): + b = self.convert_dtype(b, xp) + a = self.convert_dtype(a, xp) + x = self.convert_dtype(x, xp) + zi = self.convert_dtype(zi, xp) + assert_raises(ValueError, lfilter, b, a, x, axis, zi) + + @skip_xp_backends('cupy', reason='cupy does not raise') + def test_bad_size_zi(self, xp): + # rank 1 + x1 = xp.arange(6) + self.base_bad_size_zi([1], [1], x1, -1, [1], xp) + self.base_bad_size_zi([1, 1], [1], x1, -1, [0, 1], xp) + self.base_bad_size_zi([1, 1], [1], x1, -1, [[0]], xp) + self.base_bad_size_zi([1, 1], [1], x1, -1, [0, 1, 2], xp) + self.base_bad_size_zi([1, 1, 1], [1], x1, -1, [[0]], xp) + self.base_bad_size_zi([1, 1, 1], [1], x1, -1, [0, 1, 2], xp) + self.base_bad_size_zi([1], [1, 1], x1, -1, [0, 1], xp) + self.base_bad_size_zi([1], [1, 1], x1, -1, [[0]], xp) + self.base_bad_size_zi([1], [1, 1], x1, -1, [0, 1, 2], xp) + self.base_bad_size_zi([1, 1, 1], [1, 1], x1, -1, [0], xp) + self.base_bad_size_zi([1, 1, 1], [1, 1], x1, -1, [[0], [1]], xp) + self.base_bad_size_zi([1, 1, 1], [1, 1], x1, -1, [0, 1, 2], xp) + self.base_bad_size_zi([1, 1, 1], [1, 1], x1, -1, [0, 1, 2, 3], xp) + self.base_bad_size_zi([1, 1], [1, 1, 1], x1, -1, [0], xp) + self.base_bad_size_zi([1, 1], [1, 1, 1], x1, -1, [[0], [1]], xp) + self.base_bad_size_zi([1, 1], [1, 1, 1], x1, -1, [0, 1, 2], xp) + self.base_bad_size_zi([1, 1], [1, 1, 1], x1, -1, [0, 1, 2, 3], xp) + + # rank 2 + x2 = np.arange(12).reshape((4,3)) + x2 = xp.asarray(x2) + # for axis=0 zi.shape should == (max(len(a),len(b))-1, 3) + self.base_bad_size_zi([1], [1], x2, 0, [0], xp) + + # for each of these there are 5 cases tested (in this order): + # 1. not deep enough, right # elements + # 2. too deep, right # elements + # 3. right depth, right # elements, transposed + # 4. right depth, too few elements + # 5. right depth, too many elements + + self.base_bad_size_zi([1, 1], [1], x2, 0, [0, 1, 2], xp) + self.base_bad_size_zi([1, 1], [1], x2, 0, [[[0, 1, 2]]], xp) + self.base_bad_size_zi([1, 1], [1], x2, 0, [[0], [1], [2]], xp) + self.base_bad_size_zi([1, 1], [1], x2, 0, [[0, 1]], xp) + self.base_bad_size_zi([1, 1], [1], x2, 0, [[0, 1, 2, 3]], xp) + + self.base_bad_size_zi([1, 1, 1], [1], x2, 0, [0, 1, 2, 3, 4, 5], xp) + self.base_bad_size_zi([1, 1, 1], [1], x2, 0, [[[0, 1, 2], [3, 4, 5]]], xp) + self.base_bad_size_zi([1, 1, 1], [1], x2, 0, [[0, 1], [2, 3], [4, 5]], xp) + self.base_bad_size_zi([1, 1, 1], [1], x2, 0, [[0, 1], [2, 3]], xp) + self.base_bad_size_zi([1, 1, 1], [1], x2, 0, [[0, 1, 2, 3], [4, 5, 6, 7]], xp) + + self.base_bad_size_zi([1], [1, 1], x2, 0, [0, 1, 2], xp) + self.base_bad_size_zi([1], [1, 1], x2, 0, [[[0, 1, 2]]], xp) + self.base_bad_size_zi([1], [1, 1], x2, 0, [[0], [1], [2]], xp) + self.base_bad_size_zi([1], [1, 1], x2, 0, [[0, 1]], xp) + self.base_bad_size_zi([1], [1, 1], x2, 0, [[0, 1, 2, 3]], xp) + + self.base_bad_size_zi([1], [1, 1, 1], x2, 0, [0, 1, 2, 3, 4, 5], xp) + self.base_bad_size_zi([1], [1, 1, 1], x2, 0, [[[0, 1, 2], [3, 4, 5]]], xp) + self.base_bad_size_zi([1], [1, 1, 1], x2, 0, [[0, 1], [2, 3], [4, 5]], xp) + self.base_bad_size_zi([1], [1, 1, 1], x2, 0, [[0, 1], [2, 3]], xp) + self.base_bad_size_zi([1], [1, 1, 1], x2, 0, [[0, 1, 2, 3], [4, 5, 6, 7]], xp) + + self.base_bad_size_zi([1, 1, 1], [1, 1], x2, 0, [0, 1, 2, 3, 4, 5], xp) + self.base_bad_size_zi([1, 1, 1], [1, 1], x2, 0, [[[0, 1, 2], [3, 4, 5]]], xp) + self.base_bad_size_zi([1, 1, 1], [1, 1], x2, 0, [[0, 1], [2, 3], [4, 5]], xp) + self.base_bad_size_zi([1, 1, 1], [1, 1], x2, 0, [[0, 1], [2, 3]], xp) + self.base_bad_size_zi([1, 1, 1], [1, 1], x2, 0, + [[0, 1, 2, 3], [4, 5, 6, 7]], xp) + + # for axis=1 zi.shape should == (4, max(len(a),len(b))-1) + self.base_bad_size_zi([1], [1], x2, 1, [0], xp) + + self.base_bad_size_zi([1, 1], [1], x2, 1, [0, 1, 2, 3], xp) + self.base_bad_size_zi([1, 1], [1], x2, 1, [[[0], [1], [2], [3]]], xp) + self.base_bad_size_zi([1, 1], [1], x2, 1, [[0, 1, 2, 3]], xp) + self.base_bad_size_zi([1, 1], [1], x2, 1, [[0], [1], [2]], xp) + self.base_bad_size_zi([1, 1], [1], x2, 1, [[0], [1], [2], [3], [4]], xp) + + self.base_bad_size_zi([1, 1, 1], [1], x2, 1, [0, 1, 2, 3, 4, 5, 6, 7], xp) + self.base_bad_size_zi([1, 1, 1], [1], x2, 1, + [[[0, 1], [2, 3], [4, 5], [6, 7]]], xp) + self.base_bad_size_zi([1, 1, 1], [1], x2, 1, [[0, 1, 2, 3], [4, 5, 6, 7]], xp) + self.base_bad_size_zi([1, 1, 1], [1], x2, 1, [[0, 1], [2, 3], [4, 5]], xp) + self.base_bad_size_zi([1, 1, 1], [1], x2, 1, + [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]], xp) + + self.base_bad_size_zi([1], [1, 1], x2, 1, [0, 1, 2, 3], xp) + self.base_bad_size_zi([1], [1, 1], x2, 1, [[[0], [1], [2], [3]]], xp) + self.base_bad_size_zi([1], [1, 1], x2, 1, [[0, 1, 2, 3]], xp) + self.base_bad_size_zi([1], [1, 1], x2, 1, [[0], [1], [2]], xp) + self.base_bad_size_zi([1], [1, 1], x2, 1, [[0], [1], [2], [3], [4]], xp) + + self.base_bad_size_zi([1], [1, 1, 1], x2, 1, [0, 1, 2, 3, 4, 5, 6, 7], xp) + self.base_bad_size_zi([1], [1, 1, 1], x2, 1, + [[[0, 1], [2, 3], [4, 5], [6, 7]]], xp) + self.base_bad_size_zi([1], [1, 1, 1], x2, 1, [[0, 1, 2, 3], [4, 5, 6, 7]], xp) + self.base_bad_size_zi([1], [1, 1, 1], x2, 1, [[0, 1], [2, 3], [4, 5]], xp) + self.base_bad_size_zi([1], [1, 1, 1], x2, 1, [[0, 1], + [2, 3], [4, 5], [6, 7], [8, 9]], xp) + + self.base_bad_size_zi([1, 1, 1], [1, 1], x2, 1, [0, 1, 2, 3, 4, 5, 6, 7], xp) + self.base_bad_size_zi([1, 1, 1], [1, 1], x2, 1, + [[[0, 1], [2, 3], [4, 5], [6, 7]]], xp) + self.base_bad_size_zi([1, 1, 1], [1, 1], x2, 1, + [[0, 1, 2, 3], [4, 5, 6, 7]], xp) + self.base_bad_size_zi([1, 1, 1], [1, 1], x2, 1, [[0, 1], [2, 3], [4, 5]], xp) + self.base_bad_size_zi([1, 1, 1], [1, 1], x2, 1, + [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]], xp) + + def test_empty_zi(self, xp): + # Regression test for #880: empty array for zi crashes. + x = self.generate((5,), xp) + a = self.convert_dtype([1], xp) + b = self.convert_dtype([1], xp) + zi = self.convert_dtype([], xp) + y, zf = lfilter(b, a, x, zi=zi) + assert_array_almost_equal(y, x) + assert zf.dtype == (getattr(xp, self.dtype) + if isinstance(self.dtype, str) + else self.dtype) + assert xp_size(zf) == 0 + + @skip_xp_backends('jax.numpy', reason='jax does not support inplace ops') + @pytest.mark.parametrize('a', (1, [1], [1, .5, 1.5], 2, [2], [2, 1, 3]), + ids=str) + @make_xp_test_case(lfiltic) + def test_lfiltic(self, a, xp): + # Test for #22470: lfiltic does not handle `a[0] != 1` + # and, more in general, test that lfiltic behaves consistently with lfilter + if is_cupy(xp) and isinstance(a, int | float): + pytest.skip('cupy does not supoprt scalar filter coefficients') + x = self.generate(6, xp) # arbitrary input + b = self.convert_dtype([.5, 1., .2], xp) # arbitrary b + a = self.convert_dtype(a, xp) + N = xp_size(a) - 1 + M = xp_size(b) - 1 + K = M + N if is_cupy(xp) else max(N, M) + # compute reference initial conditions as final conditions of lfilter + y1, zi_1 = lfilter(b, a, x, zi=self.generate(K, xp)) + # copute initial conditions from lfiltic + zi_2 = lfiltic(b, a, xp.flip(y1), xp.flip(x)) + # compare lfiltic's output with reference + assert_array_almost_equal(zi_1, zi_2) + + @make_xp_test_case(lfiltic) + def test_lfiltic_bad_coeffs(xp): + # Test for invalid filter coefficients (wrong shape or zero `a[0]`) + assert_raises(ValueError, lfiltic, [1, 2], [], [0, 0], [0, 1]) + assert_raises(ValueError, lfiltic, [1, 2], [0, 2], [0, 0], [0, 1]) + assert_raises(ValueError, lfiltic, [1, 2], [[1], [2]], [0, 0], [0, 1]) + assert_raises(ValueError, lfiltic, [[1], [2]], [1], [0, 0], [0, 1]) + + @skip_xp_backends( + 'array_api_strict', reason='int64 and float64 cannot be promoted together' + ) + @skip_xp_backends('jax.numpy', reason='jax dtype defaults differ') + @make_xp_test_case(lfiltic) + def test_lfiltic_bad_zi(self, xp): + # Regression test for #3699: bad initial conditions + a = self.convert_dtype([1], xp) + b = self.convert_dtype([1], xp) + # "y" sets the datatype of zi, so it truncates if int + zi = lfiltic(b, a, xp.asarray([1., 0])) + zi_1 = lfiltic(b, a, xp.asarray([1.0, 0])) + zi_2 = lfiltic(b, a, xp.asarray([True, False])) + xp_assert_equal(zi, zi_1) + + check_dtype_arg = {} if self.dtype == object else {'check_dtype': False} + xp_assert_equal(zi, zi_2, **check_dtype_arg) + + @skip_xp_backends('cupy', reason='XXX https://github.com/cupy/cupy/pull/8677') + def test_short_x_FIR(self, xp): + # regression test for #5116 + # x shorter than b, with non None zi fails + a = self.convert_dtype([1], xp) + b = self.convert_dtype([1, 0, -1], xp) + zi = self.convert_dtype([2, 7], xp) + x = self.convert_dtype([72], xp) + ye = self.convert_dtype([74], xp) + zfe = self.convert_dtype([7, -72], xp) + y, zf = lfilter(b, a, x, zi=zi) + assert_array_almost_equal(y, ye) + assert_array_almost_equal(zf, zfe) + + @skip_xp_backends('cupy', reason='XXX https://github.com/cupy/cupy/pull/8677') + def test_short_x_IIR(self, xp): + # regression test for #5116 + # x shorter than b, with non None zi fails + a = self.convert_dtype([1, 1], xp) + b = self.convert_dtype([1, 0, -1], xp) + zi = self.convert_dtype([2, 7], xp) + x = self.convert_dtype([72], xp) + ye = self.convert_dtype([74], xp) + zfe = self.convert_dtype([-67, -72], xp) + y, zf = lfilter(b, a, x, zi=zi) + assert_array_almost_equal(y, ye) + assert_array_almost_equal(zf, zfe) + + def test_do_not_modify_a_b_IIR(self, xp): + x = self.generate((6,), xp) + b = self.convert_dtype([1, -1], xp) + b0 = xp_copy(b, xp=xp) + a = self.convert_dtype([0.5, -0.5], xp) + a0 = xp_copy(a, xp=xp) + y_r = self.convert_dtype([0, 2, 4, 6, 8, 10.], xp) + y_f = lfilter(b, a, x) + assert_array_almost_equal(y_f, y_r) + xp_assert_equal(b, b0) + xp_assert_equal(a, a0) + + def test_do_not_modify_a_b_FIR(self, xp): + x = self.generate((6,), xp) + b = self.convert_dtype([1, 0, 1], xp) + b0 = xp_copy(b, xp=xp) + a = self.convert_dtype([2], xp) + a0 = xp_copy(a, xp=xp) + y_r = self.convert_dtype([0, 0.5, 1, 2, 3, 4.], xp) + y_f = lfilter(b, a, x) + assert_array_almost_equal(y_f, y_r) + xp_assert_equal(b, b0) + xp_assert_equal(a, a0) + + @skip_xp_backends(np_only=True) + @pytest.mark.parametrize("a", [1.0, [1.0], np.array(1.0)]) + @pytest.mark.parametrize("b", [1.0, [1.0], np.array(1.0)]) + def test_scalar_input(self, a, b, xp): + data = np.random.randn(10) + data = xp.asarray(data) + xp_assert_close( + lfilter(xp.asarray([1.0]), xp.asarray([1.0]), data), + lfilter(b, a, data) + ) + + +class TestLinearFilterFloat32(_TestLinearFilter): + dtype = 'float32' + + +class TestLinearFilterFloat64(_TestLinearFilter): + dtype = 'float64' + + +@skip_xp_backends(np_only=True) +class TestLinearFilterFloatExtended(_TestLinearFilter): + dtype = np.dtype('g') + + +class TestLinearFilterComplex64(_TestLinearFilter): + dtype = 'complex64' + + +class TestLinearFilterComplex128(_TestLinearFilter): + dtype = 'complex128' + + +@skip_xp_backends(np_only=True) +class TestLinearFilterComplexExtended(_TestLinearFilter): + dtype = np.dtype('G') + + +@make_xp_test_case(lfilter) +def test_lfilter_bad_object(xp): + # lfilter: object arrays with non-numeric objects raise TypeError. + # Regression test for ticket #1452. + if hasattr(sys, 'abiflags') and 'd' in sys.abiflags: + pytest.skip('test is flaky when run with python3-dbg') + assert_raises(TypeError, lfilter, [1.0], [1.0], [1.0, None, 2.0]) + assert_raises(TypeError, lfilter, [1.0], [None], [1.0, 2.0, 3.0]) + assert_raises(TypeError, lfilter, [None], [1.0], [1.0, 2.0, 3.0]) + + +@make_xp_test_case(lfilter) +def test_lfilter_notimplemented_input(xp): + # Should not crash, gh-7991 + assert_raises(NotImplementedError, lfilter, [2,3], [4,5], [1,2,3,4,5]) + + +@pytest.mark.parametrize('dt', ["uint8", "int8", "uint16", "int16", + "uint32", "int32", + "uint64", "int64", + "float32", "float64", + ]) + +@xfail_xp_backends("jax.numpy", reason="fails all around") +@make_xp_test_case(correlate) +class TestCorrelateReal: + def _setup_rank1(self, dt, xp): + a = xp.linspace(0, 3, 4, dtype=dt) + b = xp.linspace(1, 2, 2, dtype=dt) + + y_r = xp.asarray([0, 2, 5, 8, 3], dtype=dt) + return a, b, y_r + + def equal_tolerance(self, res_dt): + # default value of keyword + decimal = 6 + try: + dt_info = np.finfo(res_dt) + if hasattr(dt_info, 'resolution'): + decimal = int(-0.5*np.log10(dt_info.resolution)) + except Exception: + pass + return decimal + + def equal_tolerance_fft(self, res_dt): + # FFT implementations convert longdouble arguments down to + # double so don't expect better precision, see gh-9520 + if res_dt == np.longdouble: + return self.equal_tolerance(np.float64) + else: + return self.equal_tolerance(res_dt) + + @skip_xp_backends(np_only=True, reason="order='F'") + def test_method(self, dt, xp): + dt = getattr(xp, dt) + + a, b, y_r = self._setup_rank3(dt, xp) + y_fft = correlate(a, b, method='fft') + y_direct = correlate(a, b, method='direct') + + assert_array_almost_equal(y_r, y_fft, + decimal=self.equal_tolerance_fft(y_fft.dtype),) + assert_array_almost_equal(y_r, y_direct, + decimal=self.equal_tolerance(y_direct.dtype),) + assert y_fft.dtype == dt + assert y_direct.dtype == dt + + def test_rank1_valid(self, dt, xp): + if is_torch(xp) and dt in ["uint16", "uint32", "uint64"]: + pytest.skip("torch does not support unsigned ints") + + dt = getattr(xp, dt) if isinstance(dt, str) else dt + a, b, y_r = self._setup_rank1(dt, xp) + y = correlate(a, b, 'valid') + assert_array_almost_equal(y, y_r[1:4]) + assert y.dtype == dt + + # See gh-5897 + y = correlate(b, a, 'valid') + assert_array_almost_equal(y, xp.flip(y_r[1:4])) + assert y.dtype == dt + + def test_rank1_same(self, dt, xp): + if is_torch(xp) and dt in ["uint16", "uint32", "uint64"]: + pytest.skip("torch does not support unsigned ints") + + dt = getattr(xp, dt) if isinstance(dt, str) else dt + + a, b, y_r = self._setup_rank1(dt, xp) + y = correlate(a, b, 'same') + assert_array_almost_equal(y, y_r[:-1]) + assert y.dtype == dt + + def test_rank1_full(self, dt, xp): + if is_torch(xp) and dt in ["uint16", "uint32", "uint64"]: + pytest.skip("torch does not support unsigned ints") + + dt = getattr(xp, dt) if isinstance(dt, str) else dt + + a, b, y_r = self._setup_rank1(dt, xp) + y = correlate(a, b, 'full') + assert_array_almost_equal(y, y_r) + assert y.dtype == dt + + def _setup_rank3(self, dt, xp): + a = np.linspace(0, 39, 40).reshape((2, 4, 5), order='F').astype( + dt) + b = np.linspace(0, 23, 24).reshape((2, 3, 4), order='F').astype( + dt) + + y_r = np.array([[[0., 184., 504., 912., 1360., 888., 472., 160.], + [46., 432., 1062., 1840., 2672., 1698., 864., 266.], + [134., 736., 1662., 2768., 3920., 2418., 1168., 314.], + [260., 952., 1932., 3056., 4208., 2580., 1240., 332.], + [202., 664., 1290., 1984., 2688., 1590., 712., 150.], + [114., 344., 642., 960., 1280., 726., 296., 38.]], + + [[23., 400., 1035., 1832., 2696., 1737., 904., 293.], + [134., 920., 2166., 3680., 5280., 3306., 1640., 474.], + [325., 1544., 3369., 5512., 7720., 4683., 2192., 535.], + [571., 1964., 3891., 6064., 8272., 4989., 2324., 565.], + [434., 1360., 2586., 3920., 5264., 3054., 1312., 230.], + [241., 700., 1281., 1888., 2496., 1383., 532., 39.]], + + [[22., 214., 528., 916., 1332., 846., 430., 132.], + [86., 484., 1098., 1832., 2600., 1602., 772., 206.], + [188., 802., 1698., 2732., 3788., 2256., 1018., 218.], + [308., 1006., 1950., 2996., 4052., 2400., 1078., 230.], + [230., 692., 1290., 1928., 2568., 1458., 596., 78.], + [126., 354., 636., 924., 1212., 654., 234., 0.]]], + dtype=np.float64).astype(dt) + + return a, b, y_r + + @skip_xp_backends(np_only=True, reason="order='F'") + def test_rank3_valid(self, dt, xp): + dt = getattr(xp, dt) if isinstance(dt, str) else dt + a, b, y_r = self._setup_rank3(dt, xp) + y = correlate(a, b, "valid") + assert_array_almost_equal(y, y_r[1:2, 2:4, 3:5]) + assert y.dtype == dt + + # See gh-5897 + y = correlate(b, a, "valid") + assert_array_almost_equal(y, y_r[1:2, 2:4, 3:5][::-1, ::-1, ::-1]) + assert y.dtype == dt + + @skip_xp_backends(np_only=True, reason="order='F'") + def test_rank3_same(self, dt, xp): + dt = getattr(xp, dt) if isinstance(dt, str) else dt + a, b, y_r = self._setup_rank3(dt, xp) + y = correlate(a, b, "same") + xp_assert_close(y, y_r[0:-1, 1:-1, 1:-2]) + assert y.dtype == dt + + @skip_xp_backends(np_only=True, reason="order='F'") + def test_rank3_all(self, dt, xp): + dt = getattr(xp, dt) if isinstance(dt, str) else dt + a, b, y_r = self._setup_rank3(dt, xp) + y = correlate(a, b) + xp_assert_close(y, y_r) + assert y.dtype == dt + + +@make_xp_test_case(correlate) +class TestCorrelate: + # Tests that don't depend on dtype + + @skip_xp_backends(np_only=True) + def test_invalid_shapes(self, xp): + # By "invalid," we mean that no one + # array has dimensions that are all at + # least as large as the corresponding + # dimensions of the other array. This + # setup should throw a ValueError. + a = np.arange(1, 7).reshape((2, 3)) + b = np.arange(-6, 0).reshape((3, 2)) + + assert_raises(ValueError, correlate, *(a, b), **{'mode': 'valid'}) + assert_raises(ValueError, correlate, *(b, a), **{'mode': 'valid'}) + + @skip_xp_backends(np_only=True) + def test_invalid_params(self, xp): + a = [3, 4, 5] + b = [1, 2, 3] + assert_raises(ValueError, correlate, a, b, mode='spam') + assert_raises(ValueError, correlate, a, b, mode='eggs', method='fft') + assert_raises(ValueError, correlate, a, b, mode='ham', method='direct') + assert_raises(ValueError, correlate, a, b, mode='full', method='bacon') + assert_raises(ValueError, correlate, a, b, mode='same', method='bacon') + + @skip_xp_backends(np_only=True) + def test_mismatched_dims(self, xp): + # Input arrays should have the same number of dimensions + assert_raises(ValueError, correlate, [1], 2, method='direct') + assert_raises(ValueError, correlate, 1, [2], method='direct') + assert_raises(ValueError, correlate, [1], 2, method='fft') + assert_raises(ValueError, correlate, 1, [2], method='fft') + assert_raises(ValueError, correlate, [1], [[2]]) + assert_raises(ValueError, correlate, [3], 2) + + @skip_xp_backends(cpu_only=True, exceptions=['cupy']) + @skip_xp_backends("jax.numpy", reason="dtype differs") + def test_numpy_fastpath(self, xp): + a = xp.asarray([1, 2, 3]) + b = xp.asarray([4, 5]) + xp_assert_close(correlate(a, b, mode='same'), xp.asarray([5, 14, 23])) + + a = xp.asarray([1, 2, 3]) + b = xp.asarray([4, 5, 6]) + xp_assert_close(correlate(a, b, mode='same'), xp.asarray([17, 32, 23])) + xp_assert_close(correlate(a, b, mode='full'), xp.asarray([6, 17, 32, 23, 12])) + xp_assert_close(correlate(a, b, mode='valid'), xp.asarray([32])) + + +@make_xp_test_case(correlation_lags) +@pytest.mark.parametrize("mode", ["valid", "same", "full"]) +@pytest.mark.parametrize("behind", [True, False]) +@pytest.mark.parametrize("input_size", [100, 101, 1000, 1001, + pytest.param(10000, marks=[pytest.mark.slow]), + pytest.param(10001, marks=[pytest.mark.slow])] +) +def test_correlation_lags(mode, behind, input_size, xp): + # generate random data + rng = np.random.RandomState(0) + in1 = rng.standard_normal(input_size) + offset = int(input_size/10) + # generate offset version of array to correlate with + if behind: + # y is behind x + in2 = np.concatenate([rng.standard_normal(offset), in1]) + expected = -offset + else: + # y is ahead of x + in2 = in1[offset:] + expected = offset + # cross correlate, returning lag information + correlation = correlate(in1, in2, mode=mode) + lags = correlation_lags(in1.size, in2.size, mode=mode) + # identify the peak + lag_index = np.argmax(correlation) + # Check as expected + xp_assert_equal(lags[lag_index], expected) + # Correlation and lags shape should match + assert lags.shape == correlation.shape + + +@make_xp_test_case(correlation_lags) +def test_correlation_lags_invalid_mode(xp): + with pytest.raises(ValueError, match="Mode asdfgh is invalid"): + correlation_lags(100, 100, mode="asdfgh") + + +@make_xp_test_case(correlate) +@pytest.mark.parametrize('dt_name', ['complex64', 'complex128']) +class TestCorrelateComplex: + # The decimal precision to be used for comparing results. + # This value will be passed as the 'decimal' keyword argument of + # assert_array_almost_equal(). + # Since correlate may chose to use FFT method which converts + # longdoubles to doubles internally don't expect better precision + # for longdouble than for double (see gh-9520). + + def decimal(self, dt, xp): + if is_numpy(xp) and dt == np.clongdouble: + dt = np.cdouble + + # emulate np.finfo(dt).precision for complex64 and complex128 + prec = {64: 15, 32: 6}[xp.finfo(dt).bits] + return int(2 * prec / 3) + + def _setup_rank1(self, dt, mode, xp): + rng = np.random.default_rng(9) + a = np.random.randn(10).astype(dt) + a += 1j * rng.standard_normal(10).astype(dt) + b = np.random.randn(8).astype(dt) + b += 1j * rng.standard_normal(8).astype(dt) + + y_r = (correlate(a.real, b.real, mode=mode) + + correlate(a.imag, b.imag, mode=mode)).astype(dt) + y_r += 1j * (-correlate(a.real, b.imag, mode=mode) + + correlate(a.imag, b.real, mode=mode)) + + a, b, y_r = xp.asarray(a), xp.asarray(b), xp.asarray(y_r) + return a, b, y_r + + def test_rank1_valid(self, dt_name, xp): + a, b, y_r = self._setup_rank1(dt_name, 'valid', xp) + dt = getattr(xp, dt_name) + y = correlate(a, b, 'valid') + assert_array_almost_equal(y, y_r, decimal=self.decimal(dt, xp)) + assert y.dtype == dt + + # See gh-5897 + y = correlate(b, a, 'valid') + assert_array_almost_equal(y, xp.conj(xp.flip(y_r)), + decimal=self.decimal(dt, xp)) + assert y.dtype == dt + + def test_rank1_same(self, dt_name, xp): + a, b, y_r = self._setup_rank1(dt_name, 'same', xp) + dt = getattr(xp, dt_name) + + y = correlate(a, b, 'same') + assert_array_almost_equal(y, y_r, decimal=self.decimal(dt, xp)) + assert y.dtype == dt + + def test_rank1_full(self, dt_name, xp): + a, b, y_r = self._setup_rank1(dt_name, 'full', xp) + dt = getattr(xp, dt_name) + y = correlate(a, b, 'full') + assert_array_almost_equal(y, y_r, decimal=self.decimal(dt, xp)) + assert y.dtype == dt + + def test_swap_full(self, dt_name, xp): + dt = getattr(xp, dt_name) + d = xp.asarray([0.+0.j, 1.+1.j, 2.+2.j], dtype=dt) + k = xp.asarray([1.+3.j, 2.+4.j, 3.+5.j, 4.+6.j], dtype=dt) + y = correlate(d, k) + xp_assert_close( + y, xp.asarray([0.+0.j, 10.-2.j, 28.-6.j, 22.-6.j, 16.-6.j, 8.-4.j]), + atol=1e-6, check_dtype=False + ) + + def test_swap_same(self, dt_name, xp): + d = xp.asarray([0.+0.j, 1.+1.j, 2.+2.j]) + k = xp.asarray([1.+3.j, 2.+4.j, 3.+5.j, 4.+6.j]) + y = correlate(d, k, mode="same") + xp_assert_close(y, xp.asarray([10.-2.j, 28.-6.j, 22.-6.j])) + + @skip_xp_backends("cupy", reason="notimplementederror") + def test_rank3(self, dt_name, xp): + if is_jax(xp) and SCIPY_DEVICE != "cpu": + pytest.xfail(reason="error tolerances exceeded with JAX on gpu") + a = np.random.randn(10, 8, 6).astype(dt_name) + a += 1j * np.random.randn(10, 8, 6).astype(dt_name) + b = np.random.randn(8, 6, 4).astype(dt_name) + b += 1j * np.random.randn(8, 6, 4).astype(dt_name) + + y_r = (correlate(a.real, b.real) + + correlate(a.imag, b.imag)).astype(dt_name) + y_r += 1j * (-correlate(a.real, b.imag) + correlate(a.imag, b.real)) + + a, b, y_r = xp.asarray(a), xp.asarray(b), xp.asarray(y_r) + dt = getattr(xp, dt_name) + + y = correlate(a, b, 'full') + assert_array_almost_equal(y, y_r, decimal=self.decimal(dt, xp) - 1) + assert y.dtype == dt + + @skip_xp_backends(np_only=True) # XXX: check 0D/scalars on backends. + def test_rank0(self, dt_name, xp): + a = np.array(np.random.randn()).astype(dt_name) + a += 1j * np.array(np.random.randn()).astype(dt_name) + b = np.array(np.random.randn()).astype(dt_name) + b += 1j * np.array(np.random.randn()).astype(dt_name) + dt = getattr(xp, dt_name) + + y_r = (correlate(a.real, b.real) + + correlate(a.imag, b.imag)).astype(dt) + y_r += 1j * np.array(-correlate(a.real, b.imag) + + correlate(a.imag, b.real)) + + a, b = xp.asarray(a), xp.asarray(b) + + y = correlate(a, b, 'full') + assert_array_almost_equal(y, y_r, decimal=self.decimal(dt, xp) - 1) + assert y.dtype == dt + + xp_assert_equal(correlate([1], [2j]), np.asarray(correlate(1, 2j)), + check_shape=False) + xp_assert_equal(correlate([2j], [3j]), np.asarray(correlate(2j, 3j)), + check_shape=False) + xp_assert_equal(correlate([3j], [4]), np.asarray(correlate(3j, 4)), + check_shape=False) + + + +class TestCorrelate2d: + + @make_xp_test_case(signal.correlate) + def test_consistency_correlate_funcs(self, xp): + # Compare np.correlate, signal.correlate, signal.correlate2d + a = np.arange(5) + b = np.array([3.2, 1.4, 3]) + for mode in ['full', 'valid', 'same']: + a_xp, b_xp = xp.asarray(a), xp.asarray(b) + np_corr_result = np.correlate(a, b, mode=mode) + assert_almost_equal(signal.correlate(a_xp, b_xp, mode=mode), + xp.asarray(np_corr_result)) + + # See gh-5897 + if mode == 'valid': + np_corr_result = np.correlate(b, a, mode=mode) + assert_almost_equal(signal.correlate(b_xp, a_xp, mode=mode), + xp.asarray(np_corr_result)) + + @skip_xp_backends(np_only=True) + @make_xp_test_case(signal.correlate2d) + def test_consistency_correlate_funcs_2(self, xp): + # Compare np.correlate, signal.correlate, signal.correlate2d + a = np.arange(5) + b = np.array([3.2, 1.4, 3]) + for mode in ['full', 'valid', 'same']: + assert_almost_equal(np.squeeze(signal.correlate2d([a], [b], + mode=mode)), + signal.correlate(a, b, mode=mode)) + + # See gh-5897 + if mode == 'valid': + assert_almost_equal(np.squeeze(signal.correlate2d([b], [a], + mode=mode)), + signal.correlate(b, a, mode=mode)) + + + @skip_xp_backends(np_only=True) + @make_xp_test_case(signal.correlate2d) + def test_invalid_shapes(self, xp): + # By "invalid," we mean that no one + # array has dimensions that are all at + # least as large as the corresponding + # dimensions of the other array. This + # setup should throw a ValueError. + a = np.arange(1, 7).reshape((2, 3)) + b = np.arange(-6, 0).reshape((3, 2)) + + assert_raises(ValueError, signal.correlate2d, *(a, b), **{'mode': 'valid'}) + assert_raises(ValueError, signal.correlate2d, *(b, a), **{'mode': 'valid'}) + + @make_xp_test_case(signal.correlate2d) + def test_complex_input(self, xp): + xp_assert_equal(signal.correlate2d(xp.asarray([[1]]), xp.asarray([[2j]])), + xp.asarray([-2j]), check_shape=False, check_dtype=False) + xp_assert_equal(signal.correlate2d(xp.asarray([[2j]]), xp.asarray([[3j]])), + xp.asarray([6+0j]), check_shape=False, check_dtype=False) + xp_assert_equal(signal.correlate2d(xp.asarray([[3j]]), xp.asarray([[4]])), + xp.asarray([12j]), check_shape=False, check_dtype=False) + + +@make_xp_test_case(lfilter_zi) +class TestLFilterZI: + + @skip_xp_backends(np_only=True, reason='list inputs are numpy specific') + def test_array_like(self, xp): + zi_expected = xp.asarray([5.0, -1.0]) + zi = lfilter_zi([1.0, 0.0, 2.0], [1.0, -1.0, 0.5]) + assert_array_almost_equal(zi, zi_expected) + + def test_basic(self, xp): + a = xp.asarray([1.0, -1.0, 0.5]) + b = xp.asarray([1.0, 0.0, 2.0]) + zi_expected = xp.asarray([5.0, -1.0]) + zi = lfilter_zi(b, a) + assert_array_almost_equal(zi, zi_expected) + + def test_scale_invariance(self, xp): + # Regression test. There was a bug in which b was not correctly + # rescaled when a[0] was nonzero. + b = xp.asarray([2.0, 8, 5]) + a = xp.asarray([1.0, 1, 8]) + zi1 = lfilter_zi(b, a) + zi2 = lfilter_zi(2*b, 2*a) + xp_assert_close(zi2, zi1, rtol=1e-12) + + @pytest.mark.parametrize('dtype', ['float32', 'float64']) + def test_types(self, dtype, xp): + dtype = getattr(xp, dtype) + b = xp.zeros((8), dtype=dtype) + a = xp.asarray([1], dtype=dtype) + assert signal.lfilter_zi(b, a).dtype == dtype + + +@make_xp_test_case(filtfilt, sosfiltfilt) +class TestFiltFilt: + filtfilt_kind = 'tf' + + def filtfilt(self, zpk, x, axis=-1, padtype='odd', padlen=None, + method='pad', irlen=None, xp=None): + if self.filtfilt_kind == 'tf': + b, a = zpk2tf(*zpk) + b, a = xp.asarray(b), xp.asarray(a) + return filtfilt(b, a, x, axis, padtype, padlen, method, irlen) + elif self.filtfilt_kind == 'sos': + sos = zpk2sos(*zpk) + sos = xp.asarray(sos) + return sosfiltfilt(sos, x, axis, padtype, padlen) + + @skip_xp_backends('torch', reason='negative strides') + def test_basic(self, xp): + if is_jax(xp) and self.filtfilt_kind == 'sos': + pytest.skip(reason='sosfilt works in-place') + + zpk = tf2zpk(xp.asarray([1., 2, 3]), xp.asarray([1., 2, 3])) + out = self.filtfilt(zpk, xp.arange(12), xp=xp) + atol= 4e-9 if is_cupy(xp) else 5.28e-11 + xp_assert_close(out, xp.arange(12, dtype=xp.float64), atol=atol) + + @skip_xp_backends('torch', reason='negative strides') + def test_sine(self, xp): + if is_jax(xp) and self.filtfilt_kind == 'sos': + pytest.skip(reason='sosfilt works in-place') + + rate = 2000 + t = xp.linspace(0, 1.0, rate + 1) + # A signal with low frequency and a high frequency. + xlow = xp.sin(5 * 2 * np.pi * t) + xhigh = xp.sin(250 * 2 * np.pi * t) + x = xlow + xhigh + + zpk = butter(8, xp.asarray(0.125), output='zpk') + # r is the magnitude of the largest pole. + r = np.abs(zpk[1]).max() + eps = 1e-5 + # n estimates the number of steps for the + # transient to decay by a factor of eps. + n = int(np.ceil(np.log(eps) / np.log(r))) + + # High order lowpass filter... + y = self.filtfilt(zpk, x, padlen=n, xp=xp) + # Result should be just xlow. + err = np.abs(y - xlow).max() + assert err < 1e-4 + + # A 2D case. + x2d = xp.asarray(np.vstack([xlow, xlow + xhigh])) + y2d = self.filtfilt(zpk, x2d, padlen=n, axis=1, xp=xp) + assert y2d.shape == x2d.shape + err = np.abs(y2d - xlow).max() + assert err < 1e-4 + + # Use the previous result to check the use of the axis keyword. + # (Regression test for ticket #1620) + y2dt = self.filtfilt(zpk, x2d.T, padlen=n, axis=0, xp=xp) + xp_assert_equal(y2d, y2dt.T) + + @skip_xp_backends('torch', reason='negative strides') + def test_axis(self, xp): + if is_jax(xp) and self.filtfilt_kind == 'sos': + pytest.skip(reason='sosfilt works in-place') + + # Test the 'axis' keyword on a 3D array. + x = np.arange(10.0 * 11.0 * 12.0).reshape(10, 11, 12) + x = xp.asarray(x) + zpk = butter(3, xp.asarray(0.125), output='zpk') + y0 = self.filtfilt(zpk, x, padlen=0, axis=0, xp=xp) + y1 = self.filtfilt( + zpk, xp.asarray(np.swapaxes(x, 0, 1)), padlen=0, axis=1, xp=xp + ) + xp_assert_equal(y0, xp.asarray(np.swapaxes(y1, 0, 1))) + y2 = self.filtfilt( + zpk, xp.asarray(np.swapaxes(x, 0, 2)), padlen=0, axis=2, xp=xp + ) + xp_assert_equal(y0, xp.asarray(np.swapaxes(y2, 0, 2))) + + @skip_xp_backends(np_only=True, + reason='python scalars in array_namespace are np-only') + def test_acoeff(self, xp): + if self.filtfilt_kind != 'tf': + return # only necessary for TF + # test for 'a' coefficient as single number + out = signal.filtfilt( + xp.asarray([.5, .5]), 1, xp.arange(10, dtype=xp.float64) + ) + xp_assert_close(out, xp.arange(10, dtype=xp.float64), rtol=1e-14, atol=1e-14) + + @skip_xp_backends(np_only=True, reason='_filtfilt_gust is np-only') + def test_gust_simple(self, xp): + if self.filtfilt_kind != 'tf': + pytest.skip('gust only implemented for TF systems') + # The input array has length 2. The exact solution for this case + # was computed "by hand". + x = xp.asarray([1.0, 2.0]) + b = xp.asarray([0.5]) + a = xp.asarray([1.0, -0.5]) + y, z1, z2 = _filtfilt_gust(b, a, x) + xp_assert_close(z1[0], 0.3*x[0] + 0.2*x[1]) + xp_assert_close(z2[0], 0.2*x[0] + 0.3*x[1]) + xp_assert_close(y, + xp.asarray([z1[0] + 0.25*z2[0] + 0.25*x[0] + 0.125*x[1], + 0.25*z1[0] + z2[0] + 0.125*x[0] + 0.25*x[1]]) + ) + + @skip_xp_backends(np_only=True, + reason='python scalars in array_namespace are np-only') + def test_gust_scalars(self, xp): + if self.filtfilt_kind != 'tf': + pytest.skip('gust only implemented for TF systems') + # The filter coefficients are both scalars, so the filter simply + # multiplies its input by b/a. When it is used in filtfilt, the + # factor is (b/a)**2. + x = xp.arange(12) + b = 3.0 + a = 2.0 + y = filtfilt(b, a, x, method="gust") + expected = (b/a)**2 * x + xp_assert_close(y, expected) + + +@make_xp_test_case(sosfiltfilt, filtfilt) +class TestSOSFiltFilt(TestFiltFilt): + filtfilt_kind = 'sos' + + @skip_xp_backends('jax.numpy', reason='sosfilt works in-place') + @skip_xp_backends('torch', reason='negative strides') + def test_equivalence(self, xp): + """Test equivalence between sosfiltfilt and filtfilt""" + x = np.random.RandomState(0).randn(1000) + x = xp.asarray(x) + for order in range(1, 6): + zpk = signal.butter(order, 0.35, output='zpk') + b, a = zpk2tf(*zpk) + sos = zpk2sos(*zpk) + + b, a, sos = map(xp.asarray, (b, a, sos)) + y = filtfilt(b, a, x) + y_sos = sosfiltfilt(sos, x) + xp_assert_close(y, y_sos, atol=1e-12, err_msg=f'order={order}') + + +def filtfilt_gust_opt(b, a, x): + """ + An alternative implementation of filtfilt with Gustafsson edges. + + This function computes the same result as + `scipy.signal._signaltools._filtfilt_gust`, but only 1-d arrays + are accepted. The problem is solved using `fmin` from `scipy.optimize`. + `_filtfilt_gust` is significantly faster than this implementation. + """ + def filtfilt_gust_opt_func(ics, b, a, x): + """Objective function used in filtfilt_gust_opt.""" + m = max(len(a), len(b)) - 1 + z0f = ics[:m] + z0b = ics[m:] + y_f = lfilter(b, a, x, zi=z0f)[0] + y_fb = lfilter(b, a, y_f[::-1], zi=z0b)[0][::-1] + + y_b = lfilter(b, a, x[::-1], zi=z0b)[0][::-1] + y_bf = lfilter(b, a, y_b, zi=z0f)[0] + value = np.sum((y_fb - y_bf)**2) + return value + + m = max(len(a), len(b)) - 1 + zi = lfilter_zi(b, a) + ics = np.concatenate((x[:m].mean()*zi, x[-m:].mean()*zi)) + result = fmin(filtfilt_gust_opt_func, ics, args=(b, a, x), + xtol=1e-10, ftol=1e-12, + maxfun=10000, maxiter=10000, + full_output=True, disp=False) + opt, fopt, niter, funcalls, warnflag = result + if warnflag > 0: + raise RuntimeError( + f"minimization failed in filtfilt_gust_opt: warnflag={warnflag}" + ) + z0f = opt[:m] + z0b = opt[m:] + + # Apply the forward-backward filter using the computed initial + # conditions. + y_b = lfilter(b, a, x[::-1], zi=z0b)[0][::-1] + y = lfilter(b, a, y_b, zi=z0f)[0] + + return y, z0f, z0b + + +def check_filtfilt_gust(b, a, shape, axis, irlen=None): + # Generate x, the data to be filtered. + rng = np.random.default_rng(123) + x = rng.standard_normal(shape) + + # Apply filtfilt to x. This is the main calculation to be checked. + y = filtfilt(b, a, x, axis=axis, method="gust", irlen=irlen) + + # Also call the private function so we can test the ICs. + yg, zg1, zg2 = _filtfilt_gust(b, a, x, axis=axis, irlen=irlen) + + # filtfilt_gust_opt is an independent implementation that gives the + # expected result, but it only handles 1-D arrays, so use some looping + # and reshaping shenanigans to create the expected output arrays. + xx = np.swapaxes(x, axis, -1) + out_shape = xx.shape[:-1] + yo = np.empty_like(xx) + m = max(len(a), len(b)) - 1 + zo1 = np.empty(out_shape + (m,)) + zo2 = np.empty(out_shape + (m,)) + for indx in product(*[range(d) for d in out_shape]): + yo[indx], zo1[indx], zo2[indx] = filtfilt_gust_opt(b, a, xx[indx]) + yo = np.swapaxes(yo, -1, axis) + zo1 = np.swapaxes(zo1, -1, axis) + zo2 = np.swapaxes(zo2, -1, axis) + + xp_assert_close(y, yo, rtol=1e-8, atol=1e-9) + xp_assert_close(yg, yo, rtol=1e-8, atol=1e-9) + xp_assert_close(zg1, zo1, rtol=1e-8, atol=1e-9) + xp_assert_close(zg2, zo2, rtol=1e-8, atol=1e-9) + + +@make_xp_test_case(choose_conv_method) +@pytest.mark.fail_slow(10) +def test_choose_conv_method(xp): + for mode in ['valid', 'same', 'full']: + for ndim in [1, 2]: + n, k, true_method = 8, 6, 'direct' + x = np.random.randn(*((n,) * ndim)) + h = np.random.randn(*((k,) * ndim)) + + method = choose_conv_method(x, h, mode=mode) + assert method == true_method + + method_try, times = choose_conv_method(x, h, mode=mode, measure=True) + assert method_try in {'fft', 'direct'} + assert isinstance(times, dict) + assert 'fft' in times.keys() and 'direct' in times.keys() + + n = 10 + for not_fft_conv_supp in ["complex256", "complex192"]: + if hasattr(np, not_fft_conv_supp): + x = np.ones(n, dtype=not_fft_conv_supp) + h = x.copy() + assert choose_conv_method(x, h, mode=mode) == 'direct' + + x = np.array([2**51], dtype=np.int64) + h = x.copy() + assert choose_conv_method(x, h, mode=mode) == 'direct' + + +@make_xp_test_case(choose_conv_method) +def test_choose_conv_method_2(xp): + for mode in ['valid', 'same', 'full']: + n = 10 + for not_fft_conv_supp in ["complex256", "complex192"]: + if hasattr(np, not_fft_conv_supp): + x = np.ones(n, dtype=not_fft_conv_supp) + h = x.copy() + assert choose_conv_method(x, h, mode=mode) == 'direct' + + +@skip_xp_backends(np_only=True) +@pytest.mark.fail_slow(10) +def test_filtfilt_gust(xp): + # Design a filter. + z, p, k = signal.ellip(3, 0.01, 120, 0.0875, output='zpk') + + # Find the approximate impulse response length of the filter. + eps = 1e-10 + r = np.max(np.abs(p)) + approx_impulse_len = int(np.ceil(np.log(eps) / np.log(r))) + + b, a = zpk2tf(z, p, k) + for irlen in [None, approx_impulse_len]: + signal_len = 5 * approx_impulse_len + + # 1-d test case + check_filtfilt_gust(b, a, (signal_len,), 0, irlen) + + # 3-d test case; test each axis. + for axis in range(3): + shape = [2, 2, 2] + shape[axis] = signal_len + check_filtfilt_gust(b, a, shape, axis, irlen) + + # Test case with length less than 2*approx_impulse_len. + # In this case, `filtfilt_gust` should behave the same as if + # `irlen=None` was given. + length = 2*approx_impulse_len - 50 + check_filtfilt_gust(b, a, (length,), 0, approx_impulse_len) + + +@make_xp_test_case(signal.decimate) +class TestDecimate: + def test_bad_args(self, xp): + x = xp.arange(12) + assert_raises(TypeError, signal.decimate, x, q=0.5, n=1) + assert_raises(TypeError, signal.decimate, x, q=2, n=0.5) + + def test_basic_IIR(self, xp): + x = xp.arange(12) + y = signal.decimate(x, 2, n=1, ftype='iir', zero_phase=False).round() + xp_assert_equal(y, x[::2].astype(float)) + + def test_basic_FIR(self, xp): + x = xp.arange(12) + y = signal.decimate(x, 2, n=1, ftype='fir', zero_phase=False).round() + xp_assert_equal(y, x[::2].astype(float)) + + def test_shape(self, xp): + # Regression test for ticket #1480. + z = xp.zeros((30, 30)) + d0 = signal.decimate(z, 2, axis=0, zero_phase=False) + assert d0.shape == (15, 30) + d1 = signal.decimate(z, 2, axis=1, zero_phase=False) + assert d1.shape == (30, 15) + + @skip_xp_backends(np_only=True, reason="test code is NumPy specific") + def test_phaseshift_FIR(self, xp): + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "Badly conditioned filter", BadCoefficients) + self._test_phaseshift(method='fir', zero_phase=False) + + @skip_xp_backends(np_only=True, reason="test code is NumPy specific") + def test_zero_phase_FIR(self, xp): + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "Badly conditioned filter", BadCoefficients) + self._test_phaseshift(method='fir', zero_phase=True) + + @skip_xp_backends(np_only=True, reason="test code is NumPy specific") + def test_phaseshift_IIR(self, xp): + self._test_phaseshift(method='iir', zero_phase=False) + + @skip_xp_backends(np_only=True, reason="test code is NumPy specific") + def test_zero_phase_IIR(self, xp): + self._test_phaseshift(method='iir', zero_phase=True) + + def _test_phaseshift(self, method, zero_phase): + # TODO. Look into making tests using this work for CuPy. + rate = 120 + rates_to = [15, 20, 30, 40] # q = 8, 6, 4, 3 + + t_tot = 100 # Need to let antialiasing filters settle + t = np.arange(rate*t_tot+1) / float(rate) + + # Sinusoids at 0.8*nyquist, windowed to avoid edge artifacts + freqs = np.array(rates_to) * 0.8 / 2 + d = (np.exp(1j * 2 * np.pi * freqs[:, np.newaxis] * t) + * signal.windows.tukey(t.size, 0.1)) + + for rate_to in rates_to: + q = rate // rate_to + t_to = np.arange(rate_to*t_tot+1) / float(rate_to) + d_tos = (np.exp(1j * 2 * np.pi * freqs[:, np.newaxis] * t_to) + * signal.windows.tukey(t_to.size, 0.1)) + + # Set up downsampling filters, match v0.17 defaults + if method == 'fir': + n = 30 + system = signal.dlti(signal.firwin(n + 1, 1. / q, + window='hamming'), 1.) + elif method == 'iir': + n = 8 + wc = 0.8*np.pi/q + system = signal.dlti(*signal.cheby1(n, 0.05, wc/np.pi)) + + # Calculate expected phase response, as unit complex vector + if zero_phase is False: + _, h_resps = signal.freqz(system.num, system.den, + freqs/rate*2*np.pi) + h_resps /= np.abs(h_resps) + else: + h_resps = np.ones_like(freqs) + + y_resamps = signal.decimate(d.real, q, n, ftype=system, + zero_phase=zero_phase) + + # Get phase from complex inner product, like CSD + h_resamps = np.sum(d_tos.conj() * y_resamps, axis=-1) + h_resamps /= np.abs(h_resamps) + subnyq = freqs < 0.5*rate_to + + # Complex vectors should be aligned, only compare below nyquist + result = np.angle(h_resps.conj()*h_resamps)[subnyq] + xp_assert_close(result, np.zeros_like(result), + atol=1e-3, rtol=1e-3) + + def test_auto_n(self, xp): + # Test that our value of n is a reasonable choice (depends on + # the downsampling factor) + sfreq = 100. + n = 1000 + t = xp.arange(n) / sfreq + # will alias for decimations (>= 15) + x = xp.asarray(xp.sqrt(2. / n) * xp.sin(2 * xp.pi * (sfreq / 30.) * t)) + # Use xp.sqrt(x.dot(x)) instead of xp.linalg.vector_norm(x) because + # linear algebra extension is not universally available. + xp_assert_close(xp.sqrt(x.dot(x)), xp.asarray(1.), rtol=1e-3, check_0d=False) + x_out = signal.decimate(x, 30, ftype='fir') + assert xp.sqrt(x_out.dot(x_out)) < 0.01 + + def test_long_float32(self, xp): + # regression: gh-15072. With 32-bit float and either lfilter + # or filtfilt, this is numerically unstable + x = signal.decimate(xp.ones(10_000, dtype=xp.float32), 10) + assert not any(xp.isnan(x)) + + def test_float16_upcast(self): + # float16 must be upcast to float64 + x = signal.decimate(np.ones(100, dtype=np.float16), 10) + assert x.dtype.type == np.float64 + + @skip_xp_backends(np_only=True, reason="dlti") + def test_complex_iir_dlti(self, xp): + # regression: gh-17845 + # centre frequency for filter [Hz] + fcentre = 50 + # filter passband width [Hz] + fwidth = 5 + # sample rate [Hz] + fs = 1e3 + + z, p, k = signal.butter(2, xp.asarray(2*xp.pi*fwidth/2), + output='zpk', fs=fs) + z = z.astype(complex) * xp.exp(xp.asarray(2j * xp.pi * fcentre/fs)) + p = p.astype(complex) * xp.exp(xp.asarray(2j * xp.pi * fcentre/fs)) + system = signal.dlti(z, p, k) + + t = xp.arange(200) / fs + + # input + u = (xp.exp(2j * xp.pi * fcentre * t) + + 0.5 * xp.exp(-2j * xp.pi * fcentre * t)) + + ynzp = signal.decimate(u, 2, ftype=system, zero_phase=False) + ynzpref = signal.lfilter(*signal.zpk2tf(z, p, k), + u)[::2] + + xp_assert_equal(ynzp, ynzpref) + + yzp = signal.decimate(u, 2, ftype=system, zero_phase=True) + yzpref = signal.filtfilt(*signal.zpk2tf(z, p, k), + u)[::2] + + xp_assert_close(yzp, yzpref, rtol=1e-10, atol=1e-13) + + @skip_xp_backends(np_only=True, reason="dlti") + def test_complex_fir_dlti(self, xp): + # centre frequency for filter [Hz] + fcentre = 50 + # filter passband width [Hz] + fwidth = 5 + # sample rate [Hz] + fs = 1e3 + numtaps = 20 + + # FIR filter about 0Hz + bbase = signal.firwin(numtaps, fwidth/2, fs=fs) + + # rotate these to desired frequency + zbase = np.roots(bbase) + zrot = zbase * np.exp(2j * np.pi * fcentre/fs) + # FIR filter about 50Hz, maintaining passband gain of 0dB + bz = bbase[0] * np.poly(zrot) + + system = signal.dlti(bz, 1) + + t = np.arange(200) / fs + + # input + u = (np.exp(2j * np.pi * fcentre * t) + + 0.5 * np.exp(-2j * np.pi * fcentre * t)) + + ynzp = signal.decimate(u, 2, ftype=system, zero_phase=False) + ynzpref = signal.upfirdn(bz, u, up=1, down=2)[:100] + + xp_assert_equal(ynzp, ynzpref) + + yzp = signal.decimate(u, 2, ftype=system, zero_phase=True) + yzpref = signal.resample_poly(u, 1, 2, window=bz) + + xp_assert_equal(yzp, yzpref) + +@make_xp_test_case(hilbert) +class TestHilbert: + + def test_bad_args(self, xp): + x = xp.asarray([1.0 + 0.0j]) + assert_raises(ValueError, hilbert, x) + x = xp.arange(8.0) + assert_raises(ValueError, hilbert, x, N=0) + + def test_hilbert_theoretical(self, xp): + # test cases by Ariel Rokem + decimal = 14 + + pi = xp.pi + t = xp.arange(0, 2 * pi, pi / 256, dtype=xp.float64) + a0 = xp.sin(t) + a1 = xp.cos(t) + a2 = xp.sin(2 * t) + a3 = xp.cos(2 * t) + a = xp.stack([a0, a1, a2, a3]) + + h = hilbert(a) + h_abs = xp.abs(h) + + h_angle = xp.atan2(xp.imag(h), xp.real(h)) # np.angle(h) + h_real = xp.real(h) + + # The real part should be equal to the original signals: + assert_almost_equal(h_real, a, decimal) + # The absolute value should be one everywhere, for this input: + assert_almost_equal(h_abs, xp.ones(a.shape), decimal) + # For the 'slow' sine - the phase should go from -pi/2 to pi/2 in + # the first 256 bins: + assert_almost_equal(h_angle[0, :256], + xp.arange(-pi / 2, pi / 2, pi / 256, dtype=xp.float64), + decimal) + # For the 'slow' cosine - the phase should go from 0 to pi in the + # same interval: + assert_almost_equal( + h_angle[1, :256], xp.arange(0, pi, pi / 256, dtype=xp.float64), decimal) + # The 'fast' sine should make this phase transition in half the time: + assert_almost_equal(h_angle[2, :128], + xp.arange(-pi / 2, pi / 2, pi / 128, dtype=xp.float64), + decimal) + # Ditto for the 'fast' cosine: + assert_almost_equal( + h_angle[3, :128], xp.arange(0, pi, pi / 128, dtype=xp.float64), decimal) + + # The imaginary part of hilbert(cos(t)) = sin(t) Wikipedia + assert_almost_equal(xp.imag(h[1, :]), a0, decimal) + + def test_hilbert_axisN(self, xp): + # tests for axis and N arguments + a = xp.reshape(xp.arange(18, dtype=xp.float64), (3, 6)) + # test axis + aa = hilbert(a, axis=-1) + xp_assert_equal(hilbert(a.T, axis=0), aa.T) + # test 1d + assert_almost_equal(hilbert(a[0, :]), aa[0, :], 14) + + # test N + aan = hilbert(a, N=20, axis=-1) + assert aan.shape == (3, 20) + assert hilbert(a.T, N=20, axis=0).shape == (20, 3) + # the next test is just a regression test, + # no idea whether numbers make sense + a0hilb = np.array([0.000000000000000e+00 - 1.72015830311905j, + 1.000000000000000e+00 - 2.047794505137069j, + 1.999999999999999e+00 - 2.244055555687583j, + 3.000000000000000e+00 - 1.262750302935009j, + 4.000000000000000e+00 - 1.066489252384493j, + 5.000000000000000e+00 + 2.918022706971047j, + 8.881784197001253e-17 + 3.845658908989067j, + -9.444121133484362e-17 + 0.985044202202061j, + -1.776356839400251e-16 + 1.332257797702019j, + -3.996802888650564e-16 + 0.501905089898885j, + 1.332267629550188e-16 + 0.668696078880782j, + -1.192678053963799e-16 + 0.235487067862679j, + -1.776356839400251e-16 + 0.286439612812121j, + 3.108624468950438e-16 + 0.031676888064907j, + 1.332267629550188e-16 - 0.019275656884536j, + -2.360035624836702e-16 - 0.1652588660287j, + 0.000000000000000e+00 - 0.332049855010597j, + 3.552713678800501e-16 - 0.403810179797771j, + 8.881784197001253e-17 - 0.751023775297729j, + 9.444121133484362e-17 - 0.79252210110103j]) + a0hilb = xp.asarray(a0hilb) + assert_almost_equal(aan[0, :], a0hilb, 14, err_msg='N regression') + + def test_hilbert_axis_3d(self, xp): + a = xp.reshape(xp.arange(3 * 5 * 7, dtype=xp.float64), (3, 5, 7)) + # test axis + aa = hilbert(a, axis=-1) + for axis in [0, 1]: + aap = hilbert(xp.moveaxis(a, -1, axis), axis=axis) + aap = xp.moveaxis(aap, axis, -1) + xp_assert_equal(aa, aap) + + @pytest.mark.parametrize('dtype', ['float32', 'float64']) + def test_hilbert_types(self, dtype, xp): + dtype = getattr(xp, dtype) + in_typed = xp.zeros(8, dtype=dtype) + assert xp.real(hilbert(in_typed)).dtype == dtype + + +@make_xp_test_case(hilbert2) +class TestHilbert2: + """Test function `signal.hilbert2`. """ + + @skip_xp_backends(np_only=True, reason='list inputs are numpy-specific') + def test_array_like(self, xp): + hilbert2([[1, 2, 3], [4, 5, 6]]) + + def test_bad_args(self, xp): + """Raise all exceptions in `hilbert2`. """ + x = xp.reshape(xp.arange(16), (4, 4)) + with pytest.raises(ValueError, match="^x must be real."): + hilbert2(xp.asarray([[1.0 + 0.0j]])) + with pytest.raises(ValueError, match="^N must be positive."): + hilbert2(x, N=-1) + with pytest.raises(ValueError, match="^When given as a tuple, N must hold"): + hilbert2(x, N=(1, 1, 1)) + with pytest.raises(ValueError, match="^When given as a tuple, N must hold"): + hilbert2(x, N=(0, 1)) + + @skip_xp_backends("cupy", reason="CuPy's hilbert2 does not have axes= argument") + def test_bad_args2(self, xp): + x = xp.reshape(xp.arange(16), (4, 4)) + with pytest.raises(ValueError, match="^axes must be a tuple of length 2"): + hilbert2(x, axes=(0, 1, 2)) + with pytest.raises(ValueError, match="^axes must contain 2 distinct axes"): + hilbert2(x, axes=(0, 0)) + + @pytest.mark.parametrize('dtype', ['float32', 'float64']) + def test_hilbert2_types(self, dtype, xp): + dtype = getattr(xp, dtype) + in_typed = xp.zeros((2, 32), dtype=dtype) + out = xp.real(signal.hilbert2(in_typed)) + assert out.dtype == dtype + + def test_1d_input(self, xp): + """Needed for 100% coverage """ + x = xp.asarray([0., 1., 1., 0., -1., -1.]) + x0a = signal.hilbert2(xp.reshape(x, (6, 1))) + x1a = signal.hilbert2(xp.reshape(x, (1, 6))) + xp_assert_close(x0a, x1a.T) + + def test_parameter_N(self, xp): + """Compare passing tuple to single int. """ + x = xp.zeros((5, 5)) + x0_a = hilbert2(x, N=4) + x1_a = hilbert2(x, N=(4, 4)) + xp_assert_equal(x1_a, x0_a) + + @pytest.mark.parametrize('shape', [(4, 5), (5, 4), (4, 4), (5, 5)]) + @skip_xp_backends("cupy", reason="Bug in cupy implementation, see cupy#9396") + def test_quadrant_values(self, shape, xp): + """Compare desired and calculated values in Fourier space. """ + x_f = xp.ones(shape, dtype=xp.complex128) # FFT of input signal + x_f[0 , 0] += 7 + x = xp.real(sp_fft.ifft2(x_f)) # x.imag is zero + + x_as = hilbert2(x) + x_as_f = sp_fft.fft2(x_as) + + # Create slices for bins with purely positive and purely negative frequencies + # (can be verified with `sp_fft.fftfreq()`): + f0_pos, f0_neg = slice(1, (shape[0] + 1) // 2), slice((shape[0] + 1) // 2, None) + f1_pos, f1_neg = slice(1, (shape[1] + 1) // 2), slice((shape[1] + 1) // 2, None) + # Verify all values: + atol = 1e-12 # for x of dtype complex128 + xp_assert_close(x_as_f[f0_pos, f1_pos], x_f[f0_pos, f1_pos] * 4, atol=atol) + xp_assert_close(x_as_f[0, f1_pos], x_f[0, f1_pos] * 2, atol=atol) + xp_assert_close(x_as_f[f0_pos, 0], x_f[f0_pos, 0] * 2, atol=atol) + xp_assert_close(x_as_f[0, 0], x_f[0, 0], atol=atol) + zz_as_f = x_as_f[f0_neg, f1_neg] # check for zeroed orthants + xp_assert_close(zz_as_f, xp.zeros_like(zz_as_f), atol=atol) + + @pytest.mark.parametrize('shape', [(4, 5), (5, 4), (4, 4), (5, 5)]) + def test_zero_analytic_signal(self, shape, xp): + """Test that a real signal with Z[-p,-q] == np.conj(Z[p,q]) + produces a zero analytic signal.""" + c0 = shape[0] // 2 + c1 = shape[1] // 2 + x_f = xp.zeros(shape) + x_f[c0 - 1, c1 + 1] = 1.0 + x_f[c0 + 1, c1 - 1] = 1.0 + x_f = sp_fft.ifftshift(x_f) + x = xp.real(sp_fft.ifft2(x_f)) + assert xp.sum(abs(x)) > 0.0 + x_as = hilbert2(x) + xp_assert_close(x_as, xp.zeros_like(x_as), atol=xp.finfo(x_as.dtype).eps*16) + + @pytest.mark.parametrize('sh0', [4, 5]) + @pytest.mark.parametrize('sh1', [6, 7]) + @pytest.mark.parametrize('sh2', [8, 9]) + @pytest.mark.parametrize('not_axis', [0, 1, 2]) + @skip_xp_backends("cupy", reason="cupy implementation does not have axes kwarg") + def test_3d_vs_slice(self, sh0, sh1, sh2, not_axis, xp): + """2d transform on 3d array is equal to 2d transform on 2d slices.""" + x = xp.reshape(xp.arange(sh0 * sh1 * sh2, dtype=xp.float64), (sh0, sh1, sh2)) + transform_axes = [0, 1, 2] + transform_axes.pop(not_axis) + x_as_3d = hilbert2(x, axes=transform_axes) + parts = xp.unstack(x, axis=not_axis) + x_as_2d = [hilbert2(p) for p in parts] + x_as_2d = xp.stack(x_as_2d, axis=not_axis) + xp_assert_close(x_as_3d, x_as_2d) + + @skip_xp_backends("cupy", reason="cupy implementation does not have axes kwarg") + def test_3d_axis_order(self, xp): + """2d transform on equal arrays with moved axis are equal.""" + x0 = xp.reshape(xp.arange(5 * 7 * 9, dtype=xp.float64), (5, 7, 9)) + x0_as = hilbert2(x0) + + x1 = xp.moveaxis(x0, 0, 1) + x1_as = hilbert2(x1, axes=(0, 2)) + x1_as = xp.moveaxis(x1_as, 1, 0) + xp_assert_close(x0_as, x1_as) + + x2 = xp.moveaxis(x0, 0, 2) + x2_as = hilbert2(x2, axes=(0, 1)) + x2_as = xp.moveaxis(x2_as, 2, 0) + xp_assert_close(x0_as, x2_as) + + +@make_xp_test_case(envelope) +class TestEnvelope: + """Unit tests for function `._signaltools.envelope()`. """ + + @staticmethod + def assert_close(actual, desired, msg, xp): + a_r_tol = ({'atol': 1e-12, 'rtol': 1e-12} + if xp_default_dtype(xp) == xp.float64 + else {'atol': 1e-5, 'rtol': 1e-5} + ) + + """Little helper to compare to arrays with proper tolerances""" + xp_assert_close(actual, desired, **a_r_tol, err_msg=msg) + + def test_envelope_invalid_parameters(self, xp): + """For `envelope()` Raise all exceptions that are used to verify function + parameters. """ + with pytest.raises(ValueError, + match=r"Invalid parameter axis=2 for z.shape=.*"): + envelope(np.ones(3), axis=2) + with pytest.raises(ValueError, + match=r"z.shape\[axis\] not > 0 for z.shape=.*"): + envelope(xp.ones((3, 0)), axis=1) + for bp_in in [(0, 1, 2), (0, 2.), (None, 2.)]: + ts = ', '.join(map(str, bp_in)) + with pytest.raises(ValueError, + match=rf"bp_in=\({ts}\) isn't a 2-tuple of.*"): + # noinspection PyTypeChecker + envelope(xp.ones(4), bp_in=bp_in) + with pytest.raises(ValueError, + match="n_out=10.0 is not a positive integer or.*"): + # noinspection PyTypeChecker + envelope(xp.ones(4), n_out=10.) + for bp_in in [(-1, 3), (1, 1), (0, 10)]: + with pytest.raises(ValueError, + match=r"`-n//2 <= bp_in\[0\] < bp_in\[1\] <=.*"): + envelope(xp.ones(4), bp_in=bp_in) + with pytest.raises(ValueError, match="residual='undefined' not in .*"): + # noinspection PyTypeChecker + envelope(xp.ones(4), residual='undefined') + + @skip_xp_backends("jax.numpy", reason="XXX: immutable arrays") + def test_envelope_verify_parameters(self, xp): + """Ensure that the various parametrizations produce compatible results. """ + dt_r = xp_default_dtype(xp) + dt_c = xp.complex64 if dt_r == xp.float32 else xp.complex128 + + Z = xp.asarray([4.0, 2, 2, 3, 0], dtype=dt_r) + Zr_a = xp.asarray([4.0, 0, 0, 6, 0, 0, 0, 0], dtype=dt_r) + z = sp_fft.irfft(Z) + n = z.shape[0] + + # the reference envelope: + ze2_0, zr_0 = xp.unstack(envelope(z, (1, 3), residual='all', squared=True)) + self.assert_close(sp_fft.rfft(ze2_0), + xp.asarray([4, 2, 0, 0, 0], dtype=dt_c), + msg="Envelope calculation error", xp=xp) + self.assert_close(sp_fft.rfft(zr_0), + xp.asarray([4, 0, 0, 3, 0], dtype=dt_c), + msg="Residual calculation error", xp=xp) + + ze_1, zr_1 = xp.unstack(envelope(z, (1, 3), residual='all', squared=False)) + self.assert_close(ze_1**2, ze2_0, + msg="Unsquared versus Squared envelope calculation error", + xp=xp) + self.assert_close(zr_1, zr_0, + msg="Unsquared versus Squared residual calculation error", + xp=xp) + + ze2_2, zr_2 = xp.unstack( + envelope(z, (1, 3), residual='all', squared=True, n_out=3*n) + ) + self.assert_close(ze2_2[::3], ze2_0, + msg="3x up-sampled envelope calculation error", xp=xp) + self.assert_close(zr_2[::3], zr_0, + msg="3x up-sampled residual calculation error", xp=xp) + + ze2_3, zr_3 = xp.unstack(envelope(z, (1, 3), residual='lowpass', squared=True)) + self.assert_close(ze2_3, ze2_0, + msg="`residual='lowpass'` envelope calculation error", xp=xp) + self.assert_close(sp_fft.rfft(zr_3), + xp.asarray([4, 0, 0, 0, 0], dtype=dt_c), + msg="`residual='lowpass'` residual calculation error", xp=xp) + + ze2_4 = envelope(z, (1, 3), residual=None, squared=True) + self.assert_close(ze2_4, ze2_0, + msg="`residual=None` envelope calculation error", xp=xp) + + # compare complex analytic signal to real version + Z_a = xp.asarray(Z, copy=True) + Z_a[1:] *= 2 + z_a = sp_fft.ifft(Z_a, n=n) # analytic signal of Z + self.assert_close(xp.real(z_a), z, + msg="Reference analytic signal error", xp=xp) + ze2_a, zr_a = xp.unstack(envelope(z_a, (1, 3), residual='all', squared=True)) + self.assert_close(ze2_a, xp.astype(ze2_0, dt_c), # dtypes must match + msg="Complex envelope calculation error", xp=xp) + self.assert_close(sp_fft.fft(zr_a), xp.asarray(Zr_a, dtype=dt_c), + msg="Complex residual calculation error", xp=xp) + + @skip_xp_backends("jax.numpy", reason="XXX: immutable arrays") + @pytest.mark.parametrize( + " Z, bp_in, Ze2_desired, Zr_desired", + [([1, 0, 2, 2, 0], (1, None), [4, 2, 0, 0, 0], [1, 0, 0, 0, 0]), + ([4, 0, 2, 0, 0], (0, None), [4, 0, 2, 0, 0], [0, 0, 0, 0, 0]), + ([4, 0, 0, 2, 0], (None, None), [4, 0, 0, 2, 0], [0, 0, 0, 0, 0]), + ([0, 0, 2, 2, 0], (1, 3), [2, 0, 0, 0, 0], [0, 0, 0, 2, 0]), + ([4, 0, 2, 2, 0], (-3, 3), [4, 0, 2, 0, 0], [0, 0, 0, 2, 0]), + ([4, 0, 3, 4, 0], (None, 1), [2, 0, 0, 0, 0], [0, 0, 3, 4, 0]), + ([4, 0, 3, 4, 0], (None, 0), [0, 0, 0, 0, 0], [4, 0, 3, 4, 0])]) + def test_envelope_real_signals(self, Z, bp_in, Ze2_desired, Zr_desired, xp): + """Test envelope calculation with real-valued test signals. + + The comparisons are performed in the Fourier space, since it makes evaluating + the bandpass filter behavior straightforward. Note that also the squared + envelope can be easily calculated by hand, if one recalls that coefficients of + a complex-valued Fourier series representing the signal can be directly + determined by an FFT and that the absolute square of a Fourier series is again + a Fourier series. + """ + Z = xp.asarray(Z, dtype=xp.float64) + Ze2_desired = xp.asarray(Ze2_desired, dtype=xp.float64) + Zr_desired = xp.asarray(Zr_desired, dtype=xp.float64) + + z = sp_fft.irfft(Z) + ze2, zr = xp.unstack(envelope(z, bp_in, residual='all', squared=True)) + ze2_lp, zr_lp = xp.unstack(envelope(z, bp_in, residual='lowpass', squared=True)) + Ze2, Zr, Ze2_lp, Zr_lp = (sp_fft.rfft(z_) for z_ in (ze2, zr, ze2_lp, zr_lp)) + + Ze2_desired = xp.asarray(Ze2_desired, dtype=xp.complex128) + Zr_desired = xp.asarray(Zr_desired, dtype=xp.complex128) + self.assert_close(Ze2, Ze2_desired, + msg="Envelope calculation error (residual='all')", xp=xp) + self.assert_close(Zr, Zr_desired, + msg="Residual calculation error (residual='all')", xp=xp) + + if bp_in[1] is not None: + Zr_desired[bp_in[1]:] = 0 + self.assert_close(Ze2_lp, Ze2_desired, + msg="Envelope calculation error (residual='lowpass')", xp=xp) + self.assert_close(Zr_lp, Zr_desired, + msg="Residual calculation error (residual='lowpass')", xp=xp) + + @skip_xp_backends("jax.numpy", reason="XXX: immutable arrays") + @pytest.mark.parametrize( + " Z, bp_in, Ze2_desired, Zr_desired", + [([0, 5, 0, 5, 0], (None, None), [5, 0, 10, 0, 5], [0, 0, 0, 0, 0]), + ([1, 5, 0, 5, 2], (-1, 2), [5, 0, 10, 0, 5], [1, 0, 0, 0, 2]), + ([1, 2, 6, 0, 6, 3], (-1, 2), [0, 6, 0, 12, 0, 6], [1, 2, 0, 0, 0, 3]) + ]) + def test_envelope_complex_signals(self, Z, bp_in, Ze2_desired, Zr_desired, xp): + """Test envelope calculation with complex-valued test signals. + + We only need to test for the complex envelope here, since the ``Nones``s in the + bandpass filter were already tested in the previous test. + """ + Z = xp.asarray(Z, dtype=xp.float64) + Ze2_desired = xp.asarray(Ze2_desired, dtype=xp.complex128) + Zr_desired = xp.asarray(Zr_desired, dtype=xp.complex128) + + z = sp_fft.ifft(sp_fft.ifftshift(Z)) + ze2, zr = xp.unstack(envelope(z, bp_in, residual='all', squared=True)) + Ze2, Zr = (sp_fft.fftshift(sp_fft.fft(z_)) for z_ in (ze2, zr)) + + self.assert_close(Ze2, Ze2_desired, + msg="Envelope calculation error", xp=xp) + self.assert_close(Zr, Zr_desired, + msg="Residual calculation error", xp=xp) + + @skip_xp_backends("jax.numpy", reason="XXX: immutable arrays") + def test_envelope_verify_axis_parameter(self, xp): + """Test for multi-channel envelope calculations. """ + dt_r = xp_default_dtype(xp) + dt_c = xp.complex64 if dt_r == xp.float32 else xp.complex128 + + z = sp_fft.irfft(xp.asarray([[1.0, 0, 2, 2, 0], [7, 0, 4, 4, 0]], dtype=dt_r)) + Ze2_desired = xp.asarray([[4, 2, 0, 0, 0], [16, 8, 0, 0, 0]], + dtype=dt_c) + Zr_desired = xp.asarray([[1, 0, 0, 0, 0], [7, 0, 0, 0, 0]], dtype=dt_c) + + ze2, zr = xp.unstack(envelope(z, squared=True, axis=1)) + ye2T, yrT = xp.unstack(envelope(z.T, squared=True, axis=0)) + Ze2, Ye2, Zr, Yr = (sp_fft.rfft(z_) for z_ in (ze2, ye2T.T, zr, yrT.T)) + + self.assert_close(Ze2, Ze2_desired, msg="2d envelope calculation error", xp=xp) + self.assert_close(Zr, Zr_desired, msg="2d residual calculation error", xp=xp) + self.assert_close( + Ye2, Ze2_desired, msg="Transposed 2d envelope calc. error", xp=xp + ) + self.assert_close( + Yr, Zr_desired, msg="Transposed 2d residual calc. error", xp=xp + ) + + @skip_xp_backends("jax.numpy", reason="XXX: immutable arrays") + def test_envelope_verify_axis_parameter_complex(self, xp): + """Test for multi-channel envelope calculations with complex values. """ + dt_r = xp_default_dtype(xp) + dt_c = xp.complex64 if dt_r == xp.float32 else xp.complex128 + inp = xp.asarray([[1.0, 5, 0, 5, 2], [1, 10, 0, 10, 2]], dtype=dt_r) + z = sp_fft.ifft(sp_fft.ifftshift(inp, axes=1)) + Ze2_des = xp.asarray([[5, 0, 10, 0, 5], [20, 0, 40, 0, 20],], dtype=dt_c) + Zr_des = xp.asarray([[1, 0, 0, 0, 2], [1, 0, 0, 0, 2]], dtype=dt_c) + + kw = dict(bp_in=(-1, 2), residual='all', squared=True) + ze2, zr = xp.unstack(envelope(z, axis=1, **kw)) + ye2T, yrT = xp.unstack(envelope(z.T, axis=0, **kw)) + Ze2, Ye2, Zr, Yr = (sp_fft.fftshift(sp_fft.fft(z_), axes=1) + for z_ in (ze2, ye2T.T, zr, yrT.T)) + + self.assert_close(Ze2, Ze2_des, msg="2d envelope calculation error", xp=xp) + self.assert_close(Zr, Zr_des, msg="2d residual calculation error", xp=xp) + self.assert_close( + Ye2, Ze2_des, msg="Transposed 2d envelope calc. error", xp=xp + ) + self.assert_close(Yr, Zr_des, msg="Transposed 2d residual calc. error", xp=xp) + + @skip_xp_backends("jax.numpy", reason="XXX: immutable arrays") + @pytest.mark.parametrize('X', [[4, 0, 0, 1, 2], [4, 0, 0, 2, 1, 2]]) + def test_compare_envelope_hilbert(self, X, xp): + """Compare output of `envelope()` and `hilbert()`. """ + X = xp.asarray(X, dtype=xp.float64) + x = sp_fft.irfft(X) + e_hil = xp.abs(hilbert(x)) + e_env = envelope(x, (None, None), residual=None) + self.assert_close(e_hil, e_env, msg="Hilbert-Envelope comparison error", xp=xp) + + def test_nyquist(self): + """Test behavior when input is a cosine at the Nyquist frequency. + + Resampling even length signals, requires accounting for unpaired bins at the + Nyquist frequency (consults the source code of `resample`). + + Since `envelope` excludes the Nyquist frequency from the envelope calculation, + only the residues need to be investigated. + """ + x4 = sp_fft.irfft([0, 0, 8]) # = [2, -2, 2, -2] + x6 = signal.resample(x4, num=6) # = [2, -1, -1, 2, -1, -1] + y6, y6_res = envelope(x4, n_out=6, residual='all') # real-valued case + z6, z6_res = envelope(x4 + 0j, n_out=6, residual='all') # complex-valued case + + xp_assert_close(y6, np.zeros(6), atol=1e-12) + xp_assert_close(y6_res, x6, atol=1e-12) + + xp_assert_close(z6, np.zeros(6, dtype=z6.dtype), atol=1e-12) + xp_assert_close(z6_res, x6.astype(z6.dtype), atol=1e-12) + + +class TestPartialFractionExpansion: + @staticmethod + def assert_rp_almost_equal(r, p, r_true, p_true, decimal=7): + xp = array_namespace(r, p) + r_true = xp.asarray(r_true) + p_true = xp.asarray(p_true) + + distance = xp.hypot(abs(p[:, None] - p_true), + abs(r[:, None] - r_true)) + + rows, cols = linear_sum_assignment(_xp_copy_to_numpy(distance)) + assert_almost_equal(p[rows], p_true[cols], decimal=decimal) + assert_almost_equal(r[rows], r_true[cols], decimal=decimal) + + @skip_xp_backends(np_only=True) + def test_compute_factors(self, xp): + factors, poly = _compute_factors([1, 2, 3], [3, 2, 1]) + assert len(factors) == 3 + assert_almost_equal(factors[0], np.poly([2, 2, 3])) + assert_almost_equal(factors[1], np.poly([1, 1, 1, 3])) + assert_almost_equal(factors[2], np.poly([1, 1, 1, 2, 2])) + assert_almost_equal(poly, np.poly([1, 1, 1, 2, 2, 3])) + + factors, poly = _compute_factors([1, 2, 3], [3, 2, 1], + include_powers=True) + assert len(factors) == 6 + assert_almost_equal(factors[0], np.poly([1, 1, 2, 2, 3])) + assert_almost_equal(factors[1], np.poly([1, 2, 2, 3])) + assert_almost_equal(factors[2], np.poly([2, 2, 3])) + assert_almost_equal(factors[3], np.poly([1, 1, 1, 2, 3])) + assert_almost_equal(factors[4], np.poly([1, 1, 1, 3])) + assert_almost_equal(factors[5], np.poly([1, 1, 1, 2, 2])) + assert_almost_equal(poly, np.poly([1, 1, 1, 2, 2, 3])) + + @skip_xp_backends(np_only=True) + def test_group_poles(self, xp): + unique, multiplicity = _group_poles( + [1.0, 1.001, 1.003, 2.0, 2.003, 3.0], 0.1, 'min') + xp_assert_close(unique, [1.0, 2.0, 3.0]) + xp_assert_close(multiplicity, [3, 2, 1]) + + @make_xp_test_case(residue) + def test_residue_general(self, xp): + # Test are taken from issue #4464, note that poles in scipy are + # in increasing by absolute value order, opposite to MATLAB. + r, p, k = residue(xp.asarray([5, 3, -2, 7]), xp.asarray([-4, 0, 8, 3])) + assert_almost_equal(r, xp.asarray([1.3320, -0.6653, -1.4167]), decimal=4) + assert_almost_equal(p, xp.asarray([-0.4093, -1.1644, 1.5737]), decimal=4) + assert_almost_equal(k, xp.asarray([-1.2500]), decimal=4) + + r, p, k = residue(xp.asarray([-4, 8]), xp.asarray([1, 6, 8])) + assert_almost_equal(r, xp.asarray([8, -12])) + assert_almost_equal(p, xp.asarray([-2, -4])) + assert k.size == 0 + + r, p, k = residue(xp.asarray([4, 1]), xp.asarray([1, -1, -2])) + assert_almost_equal(r, xp.asarray([1, 3])) + assert_almost_equal(p, xp.asarray([-1, 2])) + assert k.size == 0 + + r, p, k = residue(xp.asarray([4, 3]), + xp.asarray([2, -3.4, 1.98, -0.406])) + self.assert_rp_almost_equal( + r, p, [-18.125 - 13.125j, -18.125 + 13.125j, 36.25], + [0.5 - 0.2j, 0.5 + 0.2j, 0.7]) + assert k.size == 0 + + r, p, k = residue(xp.asarray([2, 1]), xp.asarray([1, 5, 8, 4])) + self.assert_rp_almost_equal(r, p, [-1, 1, 3], + [-1, -2, -2]) + assert k.size == 0 + + r, p, k = residue(xp.asarray([3, -1.1, 0.88, -2.396, 1.348]), + xp.asarray([1, -0.7, -0.14, 0.048])) + assert_almost_equal(r, xp.asarray([-3, 4, 1])) + assert_almost_equal(p, xp.asarray([0.2, -0.3, 0.8])) + assert_almost_equal(k, xp.asarray([3, 1])) + + r, p, k = residue(xp.asarray([1]), xp.asarray([1, 2, -3])) + assert_almost_equal(r, xp.asarray([0.25, -0.25])) + assert_almost_equal(p, xp.asarray([1, -3])) + assert k.size == 0 + + r, p, k = residue(xp.asarray([1, 0, -5]), xp.asarray([1, 0, 0, 0, -1])) + self.assert_rp_almost_equal(r, p, + [1, 1.5j, -1.5j, -1], + [-1, -1j, 1j, 1]) + assert k.size == 0 + + r, p, k = residue(xp.asarray([3, 8, 6]), xp.asarray([1, 3, 3, 1])) + self.assert_rp_almost_equal(r, p, [1, 2, 3], + [-1, -1, -1]) + assert k.size == 0 + + r, p, k = residue(xp.asarray([3, -1]), xp.asarray([1, -3, 2])) + assert_almost_equal(r, xp.asarray([-2, 5])) + assert_almost_equal(p, xp.asarray([1, 2])) + assert k.size == 0 + + r, p, k = residue(xp.asarray([2, 3, -1]), xp.asarray([1, -3, 2])) + assert_almost_equal(r, xp.asarray([-4, 13])) + assert_almost_equal(p, xp.asarray([1, 2])) + assert_almost_equal(k, xp.asarray([2])) + + r, p, k = residue(xp.asarray([7, 2, 3, -1]), xp.asarray([1, -3, 2])) + assert_almost_equal(r, xp.asarray([-11, 69])) + assert_almost_equal(p, xp.asarray([1, 2])) + assert_almost_equal(k, xp.asarray([7, 23])) + + r, p, k = residue(xp.asarray([2, 3, -1]), xp.asarray([1, -3, 4, -2])) + self.assert_rp_almost_equal(r, p, [4, -1 + 3.5j, -1 - 3.5j], + [1, 1 - 1j, 1 + 1j]) + assert k.size == 0 + + @make_xp_test_case(residue) + def test_residue_leading_zeros(self, xp): + # Leading zeros in numerator or denominator must not affect the answer. + r0, p0, k0 = residue(xp.asarray([5, 3, -2, 7]), xp.asarray([-4, 0, 8, 3])) + r1, p1, k1 = residue(xp.asarray([0, 5, 3, -2, 7]), xp.asarray([-4, 0, 8, 3])) + r2, p2, k2 = residue(xp.asarray([5, 3, -2, 7]), xp.asarray([0, -4, 0, 8, 3])) + r3, p3, k3 = residue(xp.asarray([0, 0, 5, 3, -2, 7]), + xp.asarray([0, 0, 0, -4, 0, 8, 3])) + assert_almost_equal(r0, r1) + assert_almost_equal(r0, r2) + assert_almost_equal(r0, r3) + assert_almost_equal(p0, p1) + assert_almost_equal(p0, p2) + assert_almost_equal(p0, p3) + assert_almost_equal(k0, k1) + assert_almost_equal(k0, k2) + assert_almost_equal(k0, k3) + + @make_xp_test_case(residue) + def test_residue_degenerate(self, xp): + # Several tests for zero numerator and denominator. + r, p, k = residue(xp.asarray([0, 0]), xp.asarray([1, 6, 8])) + assert_almost_equal(r, xp.asarray([0, 0])) + assert_almost_equal(p, xp.asarray([-2, -4])) + assert k.size == 0 + + r, p, k = residue(xp.asarray(0), xp.asarray(1)) + assert r.size == 0 + assert p.size == 0 + assert k.size == 0 + + with pytest.raises(ValueError, match="Denominator `a` is zero."): + residue(1, 0) + + @make_xp_test_case(residuez) + def test_residuez_general(self, xp): + r, p, k = residuez(xp.asarray([1, 6, 6, 2]), + xp.asarray([1, -(2 + 1j), (1 + 2j), -1j])) + self.assert_rp_almost_equal(r, p, [-2+2.5j, 7.5+7.5j, -4.5-12j], + [1j, 1, 1]) + assert_almost_equal(k, xp.asarray([2j])) + + r, p, k = residuez(xp.asarray([1, 2, 1]), xp.asarray([1, -1, 0.3561])) + self.assert_rp_almost_equal(r, p, + [-0.9041 - 5.9928j, -0.9041 + 5.9928j], + [0.5 + 0.3257j, 0.5 - 0.3257j], + decimal=4) + assert_almost_equal(k, xp.asarray([2.8082]), decimal=4) + + r, p, k = residuez(xp.asarray([1, -1]), xp.asarray([1, -5, 6])) + assert_almost_equal(r, xp.asarray([-1, 2])) + assert_almost_equal(p, xp.asarray([2, 3])) + assert k.size == 0 + + r, p, k = residuez(xp.asarray([2, 3, 4]), xp.asarray([1, 3, 3, 1])) + self.assert_rp_almost_equal(r, p, [4, -5, 3], [-1, -1, -1]) + assert k.size == 0 + + r, p, k = residuez(xp.asarray([1, -10, -4, 4]), xp.asarray([2, -2, -4])) + assert_almost_equal(r, xp.asarray([0.5, -1.5])) + assert_almost_equal(p, xp.asarray([-1, 2])) + assert_almost_equal(k, xp.asarray([1.5, -1])) + + r, p, k = residuez(xp.asarray([18]), xp.asarray([18, 3, -4, -1])) + self.assert_rp_almost_equal(r, p, + [0.36, 0.24, 0.4], [0.5, -1/3, -1/3]) + assert k.size == 0 + + r, p, k = residuez(xp.asarray([2, 3]), + xp.asarray(np.polymul([1, -1/2], [1, 1/4]))) + assert_almost_equal(r, xp.asarray([-10/3, 16/3])) + assert_almost_equal(p, xp.asarray([-0.25, 0.5])) + assert k.size == 0 + + r, p, k = residuez(xp.asarray([1, -2, 1]), xp.asarray([1, -1])) + assert_almost_equal(r, xp.asarray([0])) + assert_almost_equal(p, xp.asarray([1])) + assert_almost_equal(k, xp.asarray([1, -1])) + + r, p, k = residuez(xp.asarray(1), xp.asarray([1, -1j])) + assert_almost_equal(r, xp.asarray([1])) + assert_almost_equal(p, xp.asarray([1j])) + assert k.size == 0 + + r, p, k = residuez(xp.asarray(1), xp.asarray([1, -1, 0.25])) + assert_almost_equal(r, xp.asarray([0, 1])) + assert_almost_equal(p, xp.asarray([0.5, 0.5])) + assert k.size == 0 + + r, p, k = residuez(xp.asarray(1), xp.asarray([1, -0.75, .125])) + assert_almost_equal(r, xp.asarray([-1, 2])) + assert_almost_equal(p, xp.asarray([0.25, 0.5])) + assert k.size == 0 + + r, p, k = residuez(xp.asarray([1, 6, 2]), xp.asarray([1, -2, 1])) + assert_almost_equal(r, xp.asarray([-10, 9])) + assert_almost_equal(p, xp.asarray([1, 1])) + assert_almost_equal(k, xp.asarray([2])) + + r, p, k = residuez(xp.asarray([6, 2]), xp.asarray([1, -2, 1])) + assert_almost_equal(r, xp.asarray([-2, 8])) + assert_almost_equal(p, xp.asarray([1, 1])) + assert k.size == 0 + + r, p, k = residuez(xp.asarray([1, 6, 6, 2]), xp.asarray([1, -2, 1])) + assert_almost_equal(r, xp.asarray([-24, 15])) + assert_almost_equal(p, xp.asarray([1, 1])) + assert_almost_equal(k, xp.asarray([10, 2])) + + r, p, k = residuez(xp.asarray([1, 0, 1]), xp.asarray([1, 0, 0, 0, 0, -1])) + self.assert_rp_almost_equal(r, p, + [0.2618 + 0.1902j, 0.2618 - 0.1902j, + 0.4, 0.0382 - 0.1176j, 0.0382 + 0.1176j], + [-0.8090 + 0.5878j, -0.8090 - 0.5878j, + 1.0, 0.3090 + 0.9511j, 0.3090 - 0.9511j], + decimal=4) + assert k.size == 0 + + @make_xp_test_case(residuez) + def test_residuez_trailing_zeros(self, xp): + # Trailing zeros in numerator or denominator must not affect the + # answer. + r0, p0, k0 = residuez(xp.asarray([5, 3, -2, 7]), + xp.asarray([-4, 0, 8, 3])) + r1, p1, k1 = residuez(xp.asarray([5, 3, -2, 7, 0]), + xp.asarray([-4, 0, 8, 3])) + r2, p2, k2 = residuez(xp.asarray([5, 3, -2, 7]), + xp.asarray([-4, 0, 8, 3, 0])) + r3, p3, k3 = residuez(xp.asarray([5, 3, -2, 7, 0, 0]), + xp.asarray([-4, 0, 8, 3, 0, 0, 0])) + assert_almost_equal(r0, r1) + assert_almost_equal(r0, r2) + assert_almost_equal(r0, r3) + assert_almost_equal(p0, p1) + assert_almost_equal(p0, p2) + assert_almost_equal(p0, p3) + assert_almost_equal(k0, k1) + assert_almost_equal(k0, k2) + assert_almost_equal(k0, k3) + + @make_xp_test_case(residuez) + def test_residuez_degenerate(self, xp): + r, p, k = residuez(xp.asarray([0, 0]), xp.asarray([1, 6, 8])) + assert_almost_equal(r, xp.asarray([0, 0])) + assert_almost_equal(p, xp.asarray([-2, -4])) + assert k.size == 0 + + r, p, k = residuez(xp.asarray(0), xp.asarray(1)) + assert r.size == 0 + assert p.size == 0 + assert k.size == 0 + + with pytest.raises(ValueError, match="Denominator `a` is zero."): + residuez(xp.asarray(1), xp.asarray(0)) + + with pytest.raises(ValueError, + match="First coefficient of determinant `a` must " + "be non-zero."): + residuez(xp.asarray(1), xp.asarray([0, 1, 2, 3])) + + @make_xp_test_case(invres, invresz) + def test_inverse_unique_roots_different_rtypes(self, xp): + # This test was inspired by github issue 2496. + r = xp.asarray([3 / 10, -1 / 6, -2 / 15]) + p = xp.asarray([0, -2, -5]) + k = xp.asarray([]) + b_expected = xp.asarray([0.0, 1, 3]) + a_expected = xp.asarray([1, 7, 10, 0]) + + # With the default tolerance, the rtype does not matter + # for this example. + for rtype in ('avg', 'mean', 'min', 'minimum', 'max', 'maximum'): + b, a = invres(r, p, k, rtype=rtype) + xp_assert_close(b, b_expected, atol=5e-16) + xp_assert_close(a, a_expected, check_dtype=False, atol=5e-16) + + b, a = invresz(r, p, k, rtype=rtype) + xp_assert_close(b, b_expected, atol=5e-16) + xp_assert_close(a, a_expected, check_dtype=False, atol=5e-16) + + @make_xp_test_case(invres, invresz) + def test_inverse_repeated_roots_different_rtypes(self, xp): + r = xp.asarray([3 / 20, -7 / 36, -1 / 6, 2 / 45]) + p = xp.asarray([0, -2, -2, -5]) + k = xp.asarray([]) + b_expected = xp.asarray([0.0, 0, 1, 3]) + b_expected_z = xp.asarray([-1/6, -2/3, 11/6, 3]) + a_expected = xp.asarray([1, 9, 24, 20, 0]) + + for rtype in ('avg', 'mean', 'min', 'minimum', 'max', 'maximum'): + b, a = invres(r, p, k, rtype=rtype) + xp_assert_close(b, b_expected, atol=1e-14) + xp_assert_close(a, a_expected, check_dtype=False) + + b, a = invresz(r, p, k, rtype=rtype) + xp_assert_close(b, b_expected_z, atol=1e-14) + xp_assert_close(a, a_expected, check_dtype=False) + + @make_xp_test_case(invres, invresz) + def test_inverse_bad_rtype(self, xp): + r = xp.asarray([3 / 20, -7 / 36, -1 / 6, 2 / 45]) + p = xp.asarray([0, -2, -2, -5]) + k = xp.asarray([]) + with pytest.raises(ValueError, match="`rtype` must be one of"): + invres(r, p, k, rtype='median') + with pytest.raises(ValueError, match="`rtype` must be one of"): + invresz(r, p, k, rtype='median') + + @make_xp_test_case(invresz) + def test_invresz_one_coefficient_bug(self, xp): + # Regression test for issue in gh-4646. + r = xp.asarray([1]) + p = xp.asarray([2]) + k = xp.asarray([0]) + b, a = invresz(r, p, k) + xp_assert_close(b, xp.asarray([1])) + xp_assert_close(a, xp.asarray([1.0, -2.0])) + + @make_xp_test_case(invres) + def test_invres(self, xp): + b, a = invres(xp.asarray([1]), xp.asarray([1]), xp.asarray([])) + assert_almost_equal(b, xp.asarray([1])) + assert_almost_equal(a, xp.asarray([1, -1])) + + b, a = invres(xp.asarray([1 - 1j, 2, 0.5 - 3j]), + xp.asarray([1, 0.5j, 1 + 1j]), xp.asarray([])) + assert_almost_equal(b, xp.asarray([3.5 - 4j, -8.5 + 0.25j, 3.5 + 3.25j])) + assert_almost_equal(a, xp.asarray([1, -2 - 1.5j, 0.5 + 2j, 0.5 - 0.5j])) + + b, a = invres(xp.asarray([0.5, 1]), xp.asarray([1 - 1j, 2 + 2j]), + xp.asarray([1, 2, 3])) + assert_almost_equal(b, xp.asarray([1, -1 - 1j, 1 - 2j, 0.5 - 3j, 10])) + assert_almost_equal(a, xp.asarray([1, -3 - 1j, 4])) + + b, a = invres(xp.asarray([-1, 2, 1j, 3 - 1j, 4, -2]), + xp.asarray([-1, 2 - 1j, 2 - 1j, 3, 3, 3]), xp.asarray([])) + assert_almost_equal(b, + xp.asarray([4 - 1j, -28 + 16j, 40 - 62j, 100 + 24j, + -292 + 219j, 192 - 268j])) + assert_almost_equal(a, + xp.asarray([1, -12 + 2j, 53 - 20j, -96 + 68j, 27 - 72j, + 108 - 54j, -81 + 108j])) + + b, a = invres(xp.asarray([-1, 1j]), xp.asarray([1, 1]), xp.asarray([1, 2])) + assert_almost_equal(b, xp.asarray([1, 0, -4, 3 + 1j])) + assert_almost_equal(a, xp.asarray([1, -2, 1])) + + @make_xp_test_case(invresz) + def test_invresz(self, xp): + b, a = invresz(xp.asarray([1]), xp.asarray([1]), xp.asarray([])) + assert_almost_equal(b, xp.asarray([1])) + assert_almost_equal(a, xp.asarray([1, -1])) + + b, a = invresz(xp.asarray([1 - 1j, 2, 0.5 - 3j]), + xp.asarray([1, 0.5j, 1 + 1j]), xp.asarray([])) + assert_almost_equal(b, xp.asarray([3.5 - 4j, -8.5 + 0.25j, 3.5 + 3.25j])) + assert_almost_equal(a, xp.asarray([1, -2 - 1.5j, 0.5 + 2j, 0.5 - 0.5j])) + + b, a = invresz(xp.asarray([0.5, 1]), + xp.asarray([1 - 1j, 2 + 2j]), + xp.asarray([1, 2, 3])) + assert_almost_equal(b, xp.asarray([2.5, -3 - 1j, 1 - 2j, -1 - 3j, 12])) + assert_almost_equal(a, xp.asarray([1, -3 - 1j, 4])) + + b, a = invresz(xp.asarray([-1, 2, 1j, 3 - 1j, 4, -2]), + xp.asarray([-1, 2 - 1j, 2 - 1j, 3, 3, 3]), + xp.asarray([])) + assert_almost_equal(b, + xp.asarray([6, -50 + 11j, 100 - 72j, 80 + 58j, + -354 + 228j, 234 - 297j])) + assert_almost_equal(a, + xp.asarray([1, -12 + 2j, 53 - 20j, -96 + 68j, 27 - 72j, + 108 - 54j, -81 + 108j])) + + b, a = invresz(xp.asarray([-1, 1j]), + xp.asarray([1, 1]), + xp.asarray([1, 2])) + assert_almost_equal(b, xp.asarray([1j, 1, -3, 2])) + assert_almost_equal(a, xp.asarray([1, -2, 1])) + + @skip_xp_backends(np_only=True) + @make_xp_test_case(invres, invresz) + def test_inverse_scalar_arguments(self, xp): + b, a = invres(1, 1, 1) + assert_almost_equal(b, [1, 0]) + assert_almost_equal(a, [1, -1]) + + b, a = invresz(1, 1, 1) + assert_almost_equal(b, [2, -1]) + assert_almost_equal(a, [1, -1]) + + +@make_xp_test_case(vectorstrength) +class TestVectorstrength: + + def test_single_1dperiod(self, xp): + events = xp.asarray([.5]) + period = 5. + targ_strength = 1. + targ_phase = .1 + + strength, phase = vectorstrength(events, period) + + assert strength.ndim == 0 + assert phase.ndim == 0 + + assert math.isclose(strength, targ_strength, abs_tol=1.5e-7) + assert math.isclose(phase, 2 * math.pi * targ_phase, abs_tol=1.5e-7) + + @xfail_xp_backends('torch', reason="phase modulo 2*pi") + def test_single_2dperiod(self, xp): + events = xp.asarray([.5]) + period = xp.asarray([1, 2, 5.]) + targ_strength = xp.asarray([1.] * 3) + targ_phase = xp.asarray([.5, .25, .1]) + + strength, phase = vectorstrength(events, period) + + assert strength.ndim == 1 + assert phase.ndim == 1 + assert_array_almost_equal(strength, targ_strength) + assert_almost_equal(phase, 2 * xp.pi * targ_phase) + + def test_equal_1dperiod(self, xp): + events = xp.asarray([.25, .25, .25, .25, .25, .25]) + period = 2 + targ_strength = 1. + targ_phase = .125 + + strength, phase = vectorstrength(events, period) + + assert strength.ndim == 0 + assert phase.ndim == 0 + + assert math.isclose(strength, targ_strength, abs_tol=1.5e-7) + assert math.isclose(phase, 2 * math.pi * targ_phase, abs_tol=1.5e-7) + + def test_equal_2dperiod(self, xp): + events = xp.asarray([.25, .25, .25, .25, .25, .25]) + period = xp.asarray([1, 2, ]) + targ_strength = xp.asarray([1.] * 2) + targ_phase = xp.asarray([.25, .125]) + + strength, phase = vectorstrength(events, period) + + assert strength.ndim == 1 + assert phase.ndim == 1 + assert_almost_equal(strength, targ_strength) + assert_almost_equal(phase, 2 * xp.pi * targ_phase) + + def test_spaced_1dperiod(self, xp): + events = xp.asarray([.1, 1.1, 2.1, 4.1, 10.1]) + period = 1 + targ_strength = 1. + targ_phase = .1 + + strength, phase = vectorstrength(events, period) + + assert strength.ndim == 0 + assert phase.ndim == 0 + + assert math.isclose(strength, targ_strength, abs_tol=1.5e-7) + assert math.isclose(phase, 2 * math.pi * targ_phase, abs_tol=1.5e-6) + + def test_spaced_2dperiod(self, xp): + events = xp.asarray([.1, 1.1, 2.1, 4.1, 10.1]) + period = xp.asarray([1, .5]) + targ_strength = xp.asarray([1.] * 2) + targ_phase = xp.asarray([.1, .2]) + + strength, phase = vectorstrength(events, period) + + assert strength.ndim == 1 + assert phase.ndim == 1 + assert_almost_equal(strength, targ_strength) + rtol_kw = {'rtol': 2e-6} if xp_default_dtype(xp) == xp.float32 else {} + xp_assert_close(phase, 2 * xp.pi * targ_phase, **rtol_kw) + + def test_partial_1dperiod(self, xp): + events = xp.asarray([.25, .5, .75]) + period = 1 + targ_strength = 1. / 3. + targ_phase = .5 + + strength, phase = vectorstrength(events, period) + + assert strength.ndim == 0 + assert phase.ndim == 0 + + assert math.isclose(strength, targ_strength) + assert math.isclose(phase, 2 * math.pi * targ_phase) + + + @xfail_xp_backends("torch", reason="phase modulo 2*pi") + def test_partial_2dperiod(self, xp): + events = xp.asarray([.25, .5, .75]) + period = xp.asarray([1., 1., 1., 1.]) + targ_strength = xp.asarray([1. / 3.] * 4) + targ_phase = xp.asarray([.5, .5, .5, .5]) + + strength, phase = vectorstrength(events, period) + + assert strength.ndim == 1 + assert phase.ndim == 1 + assert_almost_equal(strength, targ_strength) + assert_almost_equal(phase, 2 * xp.pi * targ_phase) + + def test_opposite_1dperiod(self, xp): + events = xp.asarray([0, .25, .5, .75]) + period = 1. + targ_strength = 0 + + strength, phase = vectorstrength(events, period) + + assert strength.ndim == 0 + assert phase.ndim == 0 + assert math.isclose(strength, targ_strength, abs_tol=1.5e-7) + + def test_opposite_2dperiod(self, xp): + events = xp.asarray([0, .25, .5, .75]) + period = xp.asarray([1.] * 10) + targ_strength = xp.asarray([0.] * 10) + + strength, phase = vectorstrength(events, period) + + assert strength.ndim == 1 + assert phase.ndim == 1 + assert_almost_equal(strength, targ_strength) + + def test_2d_events_ValueError(self, xp): + events = xp.asarray([[1, 2]]) + period = 1. + assert_raises(ValueError, vectorstrength, events, period) + + def test_2d_period_ValueError(self, xp): + events = 1. + period = xp.asarray([[1]]) + assert_raises(ValueError, vectorstrength, events, period) + + def test_zero_period_ValueError(self, xp): + events = 1. + period = 0 + assert_raises(ValueError, vectorstrength, events, period) + + def test_negative_period_ValueError(self, xp): + events = 1. + period = -1 + assert_raises(ValueError, vectorstrength, events, period) + + +# XXX: restore testing on CuPy, where possible. Multiple issues in this test: +# 1. _zi functions deliberately incompatible in cupy +# (https://github.com/scipy/scipy/pull/21713#issuecomment-2417494443) +# 2. a CuPy issue to be fixed in 14.0 only +# (https://github.com/cupy/cupy/pull/8677) +# 3. an issue with CuPy's __array__ not numpy-2.0 compatible +@skip_xp_backends(cpu_only=True) +@make_xp_test_case(sosfilt) +@pytest.mark.parametrize('dt', ['float32', 'float64', 'complex64', 'complex128']) +class TestSOSFilt: + + # The test_rank* tests are pulled from _TestLinearFilter + @skip_xp_backends('jax.numpy', reason='buffer array is read-only') + def test_rank1(self, dt, xp): + dt = getattr(xp, dt) + x = xp.linspace(0, 5, 6, dtype=dt) + b = xp.asarray([1, -1], dtype=dt) + a = xp.asarray([0.5, -0.5], dtype=dt) + + # Test simple IIR + y_r = xp.asarray([0, 2, 4, 6, 8, 10.], dtype=dt) + bb, aa = map(np.asarray, (b, a)) + sos = tf2sos(bb, aa) + sos = xp.asarray(sos) # XXX while tf2sos is numpy only + assert_array_almost_equal(sosfilt(sos, x), y_r) + + # Test simple FIR + b = xp.asarray([1, 1], dtype=dt) + # NOTE: This was changed (rel. to TestLinear...) to add a pole @zero: + a = xp.asarray([1, 0], dtype=dt) + y_r = xp.asarray([0, 1, 3, 5, 7, 9.], dtype=dt) + bb, aa = map(np.asarray, (b, a)) + sos = tf2sos(bb, aa) + sos = xp.asarray(sos) # XXX while tf2sos is numpy only + assert_array_almost_equal(sosfilt(sos, x), y_r) + + b = xp.asarray([1.0, 1, 0]) + a = xp.asarray([1.0, 0, 0]) + x = xp.ones(8) + + sos = xp.concat((b, a)) + sos = xp.reshape(sos, (1, 6)) + y = sosfilt(sos, x) + xp_assert_close(y, xp.asarray([1.0, 2, 2, 2, 2, 2, 2, 2])) + + @skip_xp_backends('jax.numpy', reason='buffer array is read-only') + def test_rank2(self, dt, xp): + dt = getattr(xp, dt) + shape = (4, 3) + prodshape = math.prod(shape) + x = xp.linspace(0, prodshape - 1, prodshape, dtype=dt) + x = xp.reshape(x, shape) + + b = xp.asarray([1, -1], dtype=dt) + a = xp.asarray([0.5, 0.5], dtype=dt) + + y_r2_a0 = xp.asarray([[0, 2, 4], [6, 4, 2], [0, 2, 4], [6, 4, 2]], + dtype=dt) + + y_r2_a1 = xp.asarray([[0, 2, 0], [6, -4, 6], [12, -10, 12], + [18, -16, 18]], dtype=dt) + + bb, aa = map(np.asarray, (b, a)) + sos = tf2sos(bb, aa) + sos = xp.asarray(sos) # XXX + y = sosfilt(sos, x, axis=0) + assert_array_almost_equal(y_r2_a0, y) + + sos = tf2sos(bb, aa) + sos = xp.asarray(sos) # XXX + y = sosfilt(sos, x, axis=1) + assert_array_almost_equal(y_r2_a1, y) + + @skip_xp_backends('jax.numpy', reason='buffer array is read-only') + def test_rank3(self, dt, xp): + dt = getattr(xp, dt) + shape = (4, 3, 2) + prodshape = math.prod(shape) + x = xp.linspace(0, prodshape - 1, prodshape) + x = xp.reshape(x, shape) + + b = xp.asarray([1, -1], dtype=dt) + a = xp.asarray([0.5, 0.5], dtype=dt) + + # Test last axis + bb, aa = map(np.asarray, (b, a)) # XXX until tf2sos is array api compatible + sos = tf2sos(bb, aa) + sos = xp.asarray(sos) # XXX + y = sosfilt(sos, x) + for i in range(x.shape[0]): + for j in range(x.shape[1]): + assert_array_almost_equal(y[i, j, ...], lfilter(b, a, x[i, j, ...])) + + def _get_ab_sos(self, xp): + b1, a1 = signal.butter(2, 0.25, 'low') + b2, a2 = signal.butter(2, 0.75, 'low') + b3, a3 = signal.butter(2, 0.75, 'low') + b = np.convolve(np.convolve(b1, b2), b3) + a = np.convolve(np.convolve(a1, a2), a3) + sos = np.array((np.r_[b1, a1], np.r_[b2, a2], np.r_[b3, a3])) + + a, b, sos = map(xp.asarray, (a, b, sos)) + return a, b, sos + + @skip_xp_backends('jax.numpy', reason='item assignment') + def test_initial_conditions(self, dt, xp): + a, b, sos = self._get_ab_sos(xp) + + x = np.random.rand(50).astype(dt) + x = xp.asarray(x) + + dt = getattr(xp, dt) + + # Stopping filtering and continuing + y_true, zi = lfilter(b, a, x[:20], zi=xp.zeros(6)) + y_true = xp.concat((y_true, lfilter(b, a, x[20:], zi=zi)[0])) + xp_assert_close(y_true, lfilter(b, a, x)) + + y_sos, zi = sosfilt(sos, x[:20], zi=xp.zeros((3, 2))) + y_sos = xp.concat((y_sos, sosfilt(sos, x[20:], zi=zi)[0])) + xp_assert_close(y_true, y_sos) + + # Use a step function + zi = sosfilt_zi(sos) + x = xp.ones(8, dtype=dt) + y, zf = sosfilt(sos, x, zi=zi) + + xp_assert_close(y, xp.ones(8), check_dtype=False) + xp_assert_close(zf, zi, check_dtype=False) + + @skip_xp_backends('jax.numpy', reason='item assignment') + @skip_xp_backends('array_api_strict', reason='fancy indexing not supported') + def test_initial_conditions_2(self, dt, xp): + dt = getattr(xp, dt) + x = xp.ones(8, dtype=dt) + + _, _, sos = self._get_ab_sos(xp) + zi = sosfilt_zi(sos) + + # Initial condition shape matching + x = xp.reshape(x, (1, 1) + x.shape) # 3D + with pytest.raises(ValueError): + sosfilt(sos, x, zi=zi) + + zi_nd = xp_copy(zi, xp=xp) + zi_nd = xp.reshape(zi_nd, (zi.shape[0], 1, 1, zi.shape[-1])) + + with pytest.raises(ValueError): + sosfilt(sos, x, zi=zi_nd[:, :, :, [0, 1, 1]]) + + y, zf = sosfilt(sos, x, zi=zi_nd) + xp_assert_close(y[0, 0], xp.ones(8), check_dtype=False) + xp_assert_close(zf[:, 0, 0, :], zi, check_dtype=False) + + @skip_xp_backends('jax.numpy', reason='item assignment') + def test_initial_conditions_3d_axis1(self, dt, xp): + # Test the use of zi when sosfilt is applied to axis 1 of a 3-d input. + + # Input array is x. + x = np.random.RandomState(159).randint(0, 5, size=(2, 15, 3)) + x = x.astype(dt) + x = xp.asarray(x) + + # Design a filter in ZPK format and convert to SOS + zpk = signal.butter(6, 0.35, output='zpk') + sos = zpk2sos(*zpk) + sos = xp.asarray(sos) # XXX while zpk2sos is numpy-only + + nsections = sos.shape[0] + + # Filter along this axis. + axis = 1 + + # Initial conditions, all zeros. + shp = list(x.shape) + shp[axis] = 2 + shp = tuple([nsections] + shp) + z0 = xp.zeros(shp) + + # Apply the filter to x. + yf, zf = sosfilt(sos, x, axis=axis, zi=z0) + + # Apply the filter to x in two stages. + y1, z1 = sosfilt(sos, x[:, :5, :], axis=axis, zi=z0) + y2, z2 = sosfilt(sos, x[:, 5:, :], axis=axis, zi=z1) + + # y should equal yf, and z2 should equal zf. + y = xp.concat((y1, y2), axis=axis) + xp_assert_close(y, yf, rtol=1e-10, atol=1e-13) + xp_assert_close(z2, zf, rtol=1e-10, atol=1e-13) + + # let's try the "step" initial condition + zi = sosfilt_zi(sos) + zi = xp.reshape(zi, (nsections, 1, 2, 1)) + zi = zi * x[:, 0:1, :] + y = sosfilt(sos, x, axis=axis, zi=zi)[0] + # check it against the TF form + b, a = zpk2tf(*zpk) + b, a = xp.asarray(b), xp.asarray(a) # XXX while zpk2tf is numpy-only + + zi = lfilter_zi(b, a) + zi = xp.reshape(zi, (1, xp_size(zi), 1)) + zi = zi * x[:, 0:1, :] + y_tf = lfilter(b, a, x, axis=axis, zi=zi)[0] + xp_assert_close(y, y_tf, rtol=1e-10, atol=1e-13) + + @skip_xp_backends('torch', reason='issues a RuntimeWarning') + @skip_xp_backends('jax.numpy', reason='item assignment') + def test_bad_zi_shape(self, dt, xp): + dt = getattr(xp, dt) + # The shape of zi is checked before using any values in the + # arguments, so np.empty is fine for creating the arguments. + x = xp.empty((3, 15, 3), dtype=dt) + sos = xp.zeros((4, 6)) + zi = xp.empty((4, 3, 3, 2)) # Correct shape is (4, 3, 2, 3) + with pytest.raises(ValueError, match='should be all ones'): + sosfilt(sos, x, zi=zi, axis=1) + sos[:, 3] = 1. + with pytest.raises(ValueError, match='Invalid zi shape'): + sosfilt(sos, x, zi=zi, axis=1) + + @skip_xp_backends('jax.numpy', reason='item assignment') + def test_sosfilt_zi(self, dt, xp): + dt = getattr(xp, dt) + sos = signal.butter(6, 0.2, output='sos') + sos = xp.asarray(sos) # XXX while butter is np-only + zi = sosfilt_zi(sos) + + y, zf = sosfilt(sos, xp.ones(40, dtype=dt), zi=zi) + xp_assert_close(zf, zi, rtol=1e-13, check_dtype=False) + + # Expected steady state value of the step response of this filter: + ss = xp.prod(xp.sum(sos[:, :3], axis=-1) / xp.sum(sos[:, 3:], axis=-1)) + xp_assert_close(y, ss * xp.ones_like(y), rtol=1e-13) + + @skip_xp_backends(np_only=True) + def test_sosfilt_zi_2(self, dt, xp): + # zi as array-like + dt = getattr(xp, dt) + sos = signal.butter(6, 0.2, output='sos') + sos = xp.asarray(sos) # XXX while butter is np-only + zi = sosfilt_zi(sos) + + _, zf = sosfilt(sos, xp.ones(40, dtype=dt), zi=zi.tolist()) + xp_assert_close(zf, zi, rtol=1e-13, check_dtype=False) + + +@make_xp_test_case(signal.deconvolve) +class TestDeconvolve: + + @skip_xp_backends(np_only=True, reason="list inputs are numpy-specific") + def test_array_like(self, xp): + # From docstring example: with lists + original = [0.0, 1, 0, 0, 1, 1, 0, 0] + impulse_response = [2, 1] + recorded = xp.asarray([0.0, 2, 1, 0, 2, 3, 1, 0, 0]) + recovered, remainder = signal.deconvolve(recorded, impulse_response) + xp_assert_close(recovered, original) + + def test_basic(self, xp): + # From docstring example + original = xp.asarray([0.0, 1, 0, 0, 1, 1, 0, 0], dtype=xp.float64) + impulse_response = xp.asarray([2, 1]) + recorded = xp.asarray([0.0, 2, 1, 0, 2, 3, 1, 0, 0]) + recovered, remainder = signal.deconvolve(recorded, impulse_response) + xp_assert_close(recovered, original) + + @xfail_xp_backends("cupy", reason="different error message") + def test_n_dimensional_signal(self, xp): + recorded = xp.asarray([[0, 0], [0, 0]]) + impulse_response = xp.asarray([0, 0]) + with pytest.raises(ValueError, match="^Parameter signal must be non-empty"): + quotient, remainder = signal.deconvolve(recorded, impulse_response) + + @xfail_xp_backends("cupy", reason="different error message") + def test_n_dimensional_divisor(self, xp): + recorded = xp.asarray([0, 0]) + impulse_response = xp.asarray([[0, 0], [0, 0]]) + with pytest.raises(ValueError, match="^Parameter divisor must be non-empty"): + quotient, remainder = signal.deconvolve(recorded, impulse_response) + + def test_divisor_greater_signal(self, xp): + """Return signal as `remainder` when ``len(divisior) > len(signal)``. """ + sig, div = xp.asarray([0, 1, 2]), xp.asarray([0, 1, 2, 4, 5]) + quotient, remainder = signal.deconvolve(sig, div) + xp_assert_equal(remainder, sig) + assert xp_size(xp.asarray(quotient)) == 0 + + +@make_xp_test_case(detrend) +class TestDetrend: + + def test_basic(self, xp): + detrended = detrend(xp.asarray([1, 2, 3])) + detrended_exact = xp.asarray([0, 0, 0]) + assert_array_almost_equal(detrended, detrended_exact) + + @skip_xp_backends("jax.numpy", reason="overwrite_data not implemented") + def test_copy(self, xp): + x = xp.asarray([1, 1.2, 1.5, 1.6, 2.4]) + copy_array = detrend(x, overwrite_data=False) + inplace = detrend(x, overwrite_data=True) + assert_array_almost_equal(copy_array, inplace) + + @pytest.mark.parametrize('kind', ['linear', 'constant']) + @pytest.mark.parametrize('axis', [0, 1, 2]) + def test_axis(self, axis, kind, xp): + data = xp.reshape(xp.arange(5*6*7), (5, 6, 7)) + detrended = detrend(data, type=kind, axis=axis) + assert detrended.shape == data.shape + + def test_bp(self, xp): + data = [0, 1, 2] + [5, 0, -5, -10] + data = xp.asarray(data) + detrended = detrend(data, type='linear', bp=3) + xp_assert_close(detrended, xp.zeros_like(detrended), atol=1e-14) + + # repeat with ndim > 1 and axis + data = xp.asarray(data)[None, :, None] + + detrended = detrend(data, type="linear", bp=3, axis=1) + xp_assert_close(detrended, xp.zeros_like(detrended), atol=1e-14) + + # breakpoint index > shape[axis]: raises + with assert_raises(ValueError): + detrend(data, type="linear", bp=3) + + @pytest.mark.parametrize('bp', [np.array([0, 2]), [0, 2]]) + def test_detrend_array_bp(self, bp, xp): + # regression test for https://github.com/scipy/scipy/issues/18675 + rng = np.random.RandomState(12345) + x = rng.rand(10) + x = xp.asarray(x, dtype=xp_default_dtype(xp)) + if isinstance(bp, np.ndarray) and not is_jax(xp): + # JAX expects a static array for bp, so don't call xp.asarray + # for JAX. + bp = xp.asarray(bp) + else: + if not (is_numpy(xp) or is_jax(xp)): + pytest.skip("list bp is currently numpy and jax only") + + res = detrend(x, bp=bp) + res_scipy_191 = xp.asarray([-4.44089210e-16, -2.22044605e-16, + -1.11128506e-01, -1.69470553e-01, 1.14710683e-01, 6.35468419e-02, + 3.53533144e-01, -3.67877935e-02, -2.00417675e-02, -1.94362049e-01]) + + atol = 3e-7 if xp_default_dtype(xp) == xp.float32 else 1e-14 + xp_assert_close(res, res_scipy_191, atol=atol) + + +@make_xp_test_case(unique_roots) +class TestUniqueRoots: + def test_real_no_repeat(self, xp): + p = xp.asarray([-1.0, -0.5, 0.3, 1.2, 10.0]) + unique, multiplicity = unique_roots(p) + assert_almost_equal(unique, p, decimal=15) + xp_assert_equal(multiplicity, xp.ones(len(p), dtype=int)) + + def test_real_repeat(self, xp): + p = xp.asarray([-1.0, -0.95, -0.89, -0.8, 0.5, 1.0, 1.05]) + + unique, multiplicity = unique_roots(p, tol=1e-1, rtype='min') + assert_almost_equal(unique, xp.asarray([-1.0, -0.89, 0.5, 1.0]), decimal=15) + xp_assert_equal(multiplicity, xp.asarray([2, 2, 1, 2])) + + unique, multiplicity = unique_roots(p, tol=1e-1, rtype='max') + assert_almost_equal(unique, xp.asarray([-0.95, -0.8, 0.5, 1.05]), decimal=15) + xp_assert_equal(multiplicity, xp.asarray([2, 2, 1, 2])) + + unique, multiplicity = unique_roots(p, tol=1e-1, rtype='avg') + assert_almost_equal(unique, xp.asarray([-0.975, -0.845, 0.5, 1.025]), + decimal=15) + xp_assert_equal(multiplicity, xp.asarray([2, 2, 1, 2])) + + def test_complex_no_repeat(self, xp): + p = xp.asarray([-1.0, 1.0j, 0.5 + 0.5j, -1.0 - 1.0j, 3.0 + 2.0j]) + unique, multiplicity = unique_roots(p) + assert_almost_equal(unique, p, decimal=15) + xp_assert_equal(multiplicity, xp.ones(len(p), dtype=int)) + + def test_complex_repeat(self, xp): + p = xp.asarray([-1.0, -1.0 + 0.05j, -0.95 + 0.15j, -0.90 + 0.15j, 0.0, + 0.5 + 0.5j, 0.45 + 0.55j]) + + unique, multiplicity = unique_roots(p, tol=1e-1, rtype='min') + assert_almost_equal(unique, + xp.asarray([-1.0, -0.95 + 0.15j, 0.0, 0.45 + 0.55j]), + decimal=15) + xp_assert_equal(multiplicity, xp.asarray([2, 2, 1, 2])) + + unique, multiplicity = unique_roots(p, tol=1e-1, rtype='max') + assert_almost_equal( + unique, + xp.asarray( + [-1.0 + 0.05j, -0.90 + 0.15j, 0.0, 0.5 + 0.5j] + ), + decimal=15, + ) + xp_assert_equal(multiplicity, xp.asarray([2, 2, 1, 2])) + + unique, multiplicity = unique_roots(p, tol=1e-1, rtype='avg') + assert_almost_equal( + unique, + xp.asarray([-1.0 + 0.025j, -0.925 + 0.15j, 0.0, 0.475 + 0.525j]), + decimal=15, + ) + xp_assert_equal(multiplicity, xp.asarray([2, 2, 1, 2])) + + def test_gh_4915(self, xp): + p = xp.asarray(np.roots(np.convolve(np.ones(5), np.ones(5)))) + true_roots = xp.asarray( + [-(-1)**(1/5), (-1)**(4/5), -(-1)**(3/5), (-1)**(2/5)] + ) + + unique, multiplicity = unique_roots(p) + unique = xp.sort(unique) + + assert_almost_equal(xp.sort(unique), true_roots, decimal=7) + xp_assert_equal(multiplicity, xp.asarray([2, 2, 2, 2])) + + def test_complex_roots_extra(self, xp): + unique, multiplicity = unique_roots(xp.asarray([1.0, 1.0j, 1.0])) + assert_almost_equal(unique, xp.asarray([1.0, 1.0j]), decimal=15) + xp_assert_equal(multiplicity, xp.asarray([2, 1])) + + unique, multiplicity = unique_roots( + xp.asarray([1, 1 + 2e-9, 1e-9 + 1j]), tol=0.1 + ) + assert_almost_equal(unique, xp.asarray([1.0, 1e-9 + 1.0j]), decimal=15) + xp_assert_equal(multiplicity, xp.asarray([2, 1])) + + def test_single_unique_root(self, xp): + p = xp.asarray(np.random.rand(100) + 1j * np.random.rand(100)) + unique, multiplicity = unique_roots(p, 2) + assert_almost_equal(unique, xp.asarray([np.min(p)]), decimal=15) + xp_assert_equal(multiplicity, xp.asarray([100])) + + +def test_gh_22684(): + actual = signal.resample_poly(np.arange(2000, dtype=np.complex64), 6, 4) + assert actual.dtype == np.complex64 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_spectral.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_spectral.py new file mode 100644 index 0000000000000000000000000000000000000000..3e1c2284a98ddcf7909a2f8398d7d014cdb7c6b6 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_spectral.py @@ -0,0 +1,2188 @@ +import sys +import warnings + +import numpy as np +from numpy.testing import (assert_, + assert_allclose, assert_array_equal, assert_equal, + assert_array_almost_equal_nulp) +import pytest +from pytest import raises as assert_raises + +from scipy import signal +from scipy._lib._array_api import xp_assert_close +from scipy.fft import fftfreq, rfftfreq, fft, irfft +from scipy.integrate import trapezoid +from scipy.signal import (periodogram, welch, lombscargle, coherence, csd, + spectrogram, check_COLA, check_NOLA) +from scipy.signal.windows import hann +from scipy.signal._spectral_py import _spectral_helper + +# Compare ShortTimeFFT.stft() / ShortTimeFFT.istft() with stft() / istft(): +from scipy.signal.tests._scipy_spectral_test_shim import stft_compare as stft +from scipy.signal.tests._scipy_spectral_test_shim import istft_compare as istft + + +class TestPeriodogram: + def test_real_onesided_even(self): + x = np.zeros(16) + x[0] = 1 + f, p = periodogram(x) + assert_allclose(f, np.linspace(0, 0.5, 9)) + q = np.ones(9) + q[0] = 0 + q[-1] /= 2.0 + q /= 8 + assert_allclose(p, q) + + def test_real_onesided_odd(self): + x = np.zeros(15) + x[0] = 1 + f, p = periodogram(x) + assert_allclose(f, np.arange(8.0)/15.0) + q = np.ones(8) + q[0] = 0 + q *= 2.0/15.0 + assert_allclose(p, q, atol=1e-15) + + def test_real_twosided(self): + x = np.zeros(16) + x[0] = 1 + f, p = periodogram(x, return_onesided=False) + assert_allclose(f, fftfreq(16, 1.0)) + q = np.full(16, 1/16.0) + q[0] = 0 + assert_allclose(p, q) + + def test_real_spectrum(self): + x = np.zeros(16) + x[0] = 1 + f, p = periodogram(x, scaling='spectrum') + g, q = periodogram(x, scaling='density') + assert_allclose(f, np.linspace(0, 0.5, 9)) + assert_allclose(p, q/16.0) + + def test_integer_even(self): + x = np.zeros(16, dtype=int) + x[0] = 1 + f, p = periodogram(x) + assert_allclose(f, np.linspace(0, 0.5, 9)) + q = np.ones(9) + q[0] = 0 + q[-1] /= 2.0 + q /= 8 + assert_allclose(p, q) + + def test_integer_odd(self): + x = np.zeros(15, dtype=int) + x[0] = 1 + f, p = periodogram(x) + assert_allclose(f, np.arange(8.0)/15.0) + q = np.ones(8) + q[0] = 0 + q *= 2.0/15.0 + assert_allclose(p, q, atol=1e-15) + + def test_integer_twosided(self): + x = np.zeros(16, dtype=int) + x[0] = 1 + f, p = periodogram(x, return_onesided=False) + assert_allclose(f, fftfreq(16, 1.0)) + q = np.full(16, 1/16.0) + q[0] = 0 + assert_allclose(p, q) + + def test_complex(self): + x = np.zeros(16, np.complex128) + x[0] = 1.0 + 2.0j + f, p = periodogram(x, return_onesided=False) + assert_allclose(f, fftfreq(16, 1.0)) + q = np.full(16, 5.0/16.0) + q[0] = 0 + assert_allclose(p, q) + + def test_unk_scaling(self): + assert_raises(ValueError, periodogram, np.zeros(4, np.complex128), + scaling='foo') + + @pytest.mark.skipif( + sys.maxsize <= 2**32, + reason="On some 32-bit tolerance issue" + ) + def test_nd_axis_m1(self): + x = np.zeros(20, dtype=np.float64) + x = x.reshape((2,1,10)) + x[:,:,0] = 1.0 + f, p = periodogram(x) + assert_array_equal(p.shape, (2, 1, 6)) + assert_array_almost_equal_nulp(p[0,0,:], p[1,0,:], 60) + f0, p0 = periodogram(x[0,0,:]) + assert_array_almost_equal_nulp(p0[np.newaxis,:], p[1,:], 60) + + @pytest.mark.skipif( + sys.maxsize <= 2**32, + reason="On some 32-bit tolerance issue" + ) + def test_nd_axis_0(self): + x = np.zeros(20, dtype=np.float64) + x = x.reshape((10,2,1)) + x[0,:,:] = 1.0 + f, p = periodogram(x, axis=0) + assert_array_equal(p.shape, (6,2,1)) + assert_array_almost_equal_nulp(p[:,0,0], p[:,1,0], 60) + f0, p0 = periodogram(x[:,0,0]) + assert_array_almost_equal_nulp(p0, p[:,1,0]) + + def test_window_external(self): + x = np.zeros(16) + x[0] = 1 + f, p = periodogram(x, 10, 'hann') + win = signal.get_window('hann', 16) + fe, pe = periodogram(x, 10, win) + assert_array_almost_equal_nulp(p, pe) + assert_array_almost_equal_nulp(f, fe) + win_err = signal.get_window('hann', 32) + assert_raises(ValueError, periodogram, x, + 10, win_err) # win longer than signal + + def test_padded_fft(self): + x = np.zeros(16) + x[0] = 1 + f, p = periodogram(x) + fp, pp = periodogram(x, nfft=32) + assert_allclose(f, fp[::2]) + assert_allclose(p, pp[::2]) + assert_array_equal(pp.shape, (17,)) + + def test_empty_input(self): + f, p = periodogram([]) + assert_array_equal(f.shape, (0,)) + assert_array_equal(p.shape, (0,)) + for shape in [(0,), (3,0), (0,5,2)]: + f, p = periodogram(np.empty(shape)) + assert_array_equal(f.shape, shape) + assert_array_equal(p.shape, shape) + + def test_empty_input_other_axis(self): + for shape in [(3,0), (0,5,2)]: + f, p = periodogram(np.empty(shape), axis=1) + assert_array_equal(f.shape, shape) + assert_array_equal(p.shape, shape) + + def test_short_nfft(self): + x = np.zeros(18) + x[0] = 1 + f, p = periodogram(x, nfft=16) + assert_allclose(f, np.linspace(0, 0.5, 9)) + q = np.ones(9) + q[0] = 0 + q[-1] /= 2.0 + q /= 8 + assert_allclose(p, q) + + def test_nfft_is_xshape(self): + x = np.zeros(16) + x[0] = 1 + f, p = periodogram(x, nfft=16) + assert_allclose(f, np.linspace(0, 0.5, 9)) + q = np.ones(9) + q[0] = 0 + q[-1] /= 2.0 + q /= 8 + assert_allclose(p, q) + + def test_real_onesided_even_32(self): + x = np.zeros(16, 'f') + x[0] = 1 + f, p = periodogram(x) + assert_allclose(f, np.linspace(0, 0.5, 9)) + q = np.ones(9, 'f') + q[0] = 0 + q[-1] /= 2.0 + q /= 8 + assert_allclose(p, q) + assert_(p.dtype == q.dtype) + + def test_real_onesided_odd_32(self): + x = np.zeros(15, 'f') + x[0] = 1 + f, p = periodogram(x) + assert_allclose(f, np.arange(8.0)/15.0) + q = np.ones(8, 'f') + q[0] = 0 + q *= 2.0/15.0 + assert_allclose(p, q, atol=1e-7) + assert_(p.dtype == q.dtype) + + def test_real_twosided_32(self): + x = np.zeros(16, 'f') + x[0] = 1 + f, p = periodogram(x, return_onesided=False) + assert_allclose(f, fftfreq(16, 1.0)) + q = np.full(16, 1/16.0, 'f') + q[0] = 0 + assert_allclose(p, q) + assert_(p.dtype == q.dtype) + + def test_complex_32(self): + x = np.zeros(16, 'F') + x[0] = 1.0 + 2.0j + f, p = periodogram(x, return_onesided=False) + assert_allclose(f, fftfreq(16, 1.0)) + q = np.full(16, 5.0/16.0, 'f') + q[0] = 0 + assert_allclose(p, q) + assert_(p.dtype == q.dtype) + + def test_shorter_window_error(self): + x = np.zeros(16) + x[0] = 1 + win = signal.get_window('hann', 10) + expected_msg = ('the size of the window must be the same size ' + 'of the input on the specified axis') + with assert_raises(ValueError, match=expected_msg): + periodogram(x, window=win) + + +class TestWelch: + def test_real_onesided_even(self): + x = np.zeros(16) + x[0] = 1 + x[8] = 1 + f, p = welch(x, nperseg=8) + assert_allclose(f, np.linspace(0, 0.5, 5)) + q = np.array([0.08333333, 0.15277778, 0.22222222, 0.22222222, + 0.11111111]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_real_onesided_odd(self): + x = np.zeros(16) + x[0] = 1 + x[8] = 1 + f, p = welch(x, nperseg=9) + assert_allclose(f, np.arange(5.0)/9.0) + q = np.array([0.12477455, 0.23430933, 0.17072113, 0.17072113, + 0.17072113]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_real_twosided(self): + x = np.zeros(16) + x[0] = 1 + x[8] = 1 + f, p = welch(x, nperseg=8, return_onesided=False) + assert_allclose(f, fftfreq(8, 1.0)) + q = np.array([0.08333333, 0.07638889, 0.11111111, 0.11111111, + 0.11111111, 0.11111111, 0.11111111, 0.07638889]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_real_spectrum(self): + x = np.zeros(16) + x[0] = 1 + x[8] = 1 + f, p = welch(x, nperseg=8, scaling='spectrum') + assert_allclose(f, np.linspace(0, 0.5, 5)) + q = np.array([0.015625, 0.02864583, 0.04166667, 0.04166667, + 0.02083333]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_integer_onesided_even(self): + x = np.zeros(16, dtype=int) + x[0] = 1 + x[8] = 1 + f, p = welch(x, nperseg=8) + assert_allclose(f, np.linspace(0, 0.5, 5)) + q = np.array([0.08333333, 0.15277778, 0.22222222, 0.22222222, + 0.11111111]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_integer_onesided_odd(self): + x = np.zeros(16, dtype=int) + x[0] = 1 + x[8] = 1 + f, p = welch(x, nperseg=9) + assert_allclose(f, np.arange(5.0)/9.0) + q = np.array([0.12477455, 0.23430933, 0.17072113, 0.17072113, + 0.17072113]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_integer_twosided(self): + x = np.zeros(16, dtype=int) + x[0] = 1 + x[8] = 1 + f, p = welch(x, nperseg=8, return_onesided=False) + assert_allclose(f, fftfreq(8, 1.0)) + q = np.array([0.08333333, 0.07638889, 0.11111111, 0.11111111, + 0.11111111, 0.11111111, 0.11111111, 0.07638889]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_complex(self): + x = np.zeros(16, np.complex128) + x[0] = 1.0 + 2.0j + x[8] = 1.0 + 2.0j + f, p = welch(x, nperseg=8, return_onesided=False) + assert_allclose(f, fftfreq(8, 1.0)) + q = np.array([0.41666667, 0.38194444, 0.55555556, 0.55555556, + 0.55555556, 0.55555556, 0.55555556, 0.38194444]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_unk_scaling(self): + assert_raises(ValueError, welch, np.zeros(4, np.complex128), + scaling='foo', nperseg=4) + + def test_detrend_linear(self): + x = np.arange(10, dtype=np.float64) + 0.04 + f, p = welch(x, nperseg=10, detrend='linear') + assert_allclose(p, np.zeros_like(p), atol=1e-15) + + def test_no_detrending(self): + x = np.arange(10, dtype=np.float64) + 0.04 + f1, p1 = welch(x, nperseg=10, detrend=False) + f2, p2 = welch(x, nperseg=10, detrend=lambda x: x) + assert_allclose(f1, f2, atol=1e-15) + assert_allclose(p1, p2, atol=1e-15) + + def test_detrend_external(self): + x = np.arange(10, dtype=np.float64) + 0.04 + f, p = welch(x, nperseg=10, + detrend=lambda seg: signal.detrend(seg, type='l')) + assert_allclose(p, np.zeros_like(p), atol=1e-15) + + def test_detrend_external_nd_m1(self): + x = np.arange(40, dtype=np.float64) + 0.04 + x = x.reshape((2,2,10)) + f, p = welch(x, nperseg=10, + detrend=lambda seg: signal.detrend(seg, type='l')) + assert_allclose(p, np.zeros_like(p), atol=1e-15) + + def test_detrend_external_nd_0(self): + x = np.arange(20, dtype=np.float64) + 0.04 + x = x.reshape((2,1,10)) + x = np.moveaxis(x, 2, 0) + f, p = welch(x, nperseg=10, axis=0, + detrend=lambda seg: signal.detrend(seg, axis=0, type='l')) + assert_allclose(p, np.zeros_like(p), atol=1e-15) + + def test_nd_axis_m1(self): + x = np.arange(20, dtype=np.float64) + 0.04 + x = x.reshape((2,1,10)) + f, p = welch(x, nperseg=10) + assert_array_equal(p.shape, (2, 1, 6)) + assert_allclose(p[0,0,:], p[1,0,:], atol=1e-13, rtol=1e-13) + f0, p0 = welch(x[0,0,:], nperseg=10) + assert_allclose(p0[np.newaxis,:], p[1,:], atol=1e-13, rtol=1e-13) + + def test_nd_axis_0(self): + x = np.arange(20, dtype=np.float64) + 0.04 + x = x.reshape((10,2,1)) + f, p = welch(x, nperseg=10, axis=0) + assert_array_equal(p.shape, (6,2,1)) + assert_allclose(p[:,0,0], p[:,1,0], atol=1e-13, rtol=1e-13) + f0, p0 = welch(x[:,0,0], nperseg=10) + assert_allclose(p0, p[:,1,0], atol=1e-13, rtol=1e-13) + + def test_window_external(self): + x = np.zeros(16) + x[0] = 1 + x[8] = 1 + f, p = welch(x, 10, 'hann', nperseg=8) + win = signal.get_window('hann', 8) + fe, pe = welch(x, 10, win, nperseg=None) + assert_array_almost_equal_nulp(p, pe) + assert_array_almost_equal_nulp(f, fe) + assert_array_equal(fe.shape, (5,)) # because win length used as nperseg + assert_array_equal(pe.shape, (5,)) + assert_raises(ValueError, welch, x, + 10, win, nperseg=4) # because nperseg != win.shape[-1] + win_err = signal.get_window('hann', 32) + assert_raises(ValueError, welch, x, + 10, win_err, nperseg=None) # win longer than signal + + def test_empty_input(self): + f, p = welch([]) + assert_array_equal(f.shape, (0,)) + assert_array_equal(p.shape, (0,)) + for shape in [(0,), (3,0), (0,5,2)]: + f, p = welch(np.empty(shape)) + assert_array_equal(f.shape, shape) + assert_array_equal(p.shape, shape) + + def test_empty_input_other_axis(self): + for shape in [(3,0), (0,5,2)]: + f, p = welch(np.empty(shape), axis=1) + assert_array_equal(f.shape, shape) + assert_array_equal(p.shape, shape) + + def test_short_data(self): + x = np.zeros(8) + x[0] = 1 + #for string-like window, input signal length < nperseg value gives + #UserWarning, sets nperseg to x.shape[-1] + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "nperseg=256 is greater than signal.*", UserWarning) + f, p = welch(x,window='hann') # default nperseg + f1, p1 = welch(x,window='hann', nperseg=256) # user-specified nperseg + f2, p2 = welch(x, nperseg=8) # valid nperseg, doesn't give warning + assert_allclose(f, f2) + assert_allclose(p, p2) + assert_allclose(f1, f2) + assert_allclose(p1, p2) + + def test_window_long_or_nd(self): + assert_raises(ValueError, welch, np.zeros(4), 1, np.array([1,1,1,1,1])) + assert_raises(ValueError, welch, np.zeros(4), 1, + np.arange(6).reshape((2,3))) + + def test_nondefault_noverlap(self): + x = np.zeros(64) + x[::8] = 1 + f, p = welch(x, nperseg=16, noverlap=4) + q = np.array([0, 1./12., 1./3., 1./5., 1./3., 1./5., 1./3., 1./5., + 1./6.]) + assert_allclose(p, q, atol=1e-12) + + def test_bad_noverlap(self): + assert_raises(ValueError, welch, np.zeros(4), 1, 'hann', 2, 7) + + def test_nfft_too_short(self): + assert_raises(ValueError, welch, np.ones(12), nfft=3, nperseg=4) + + def test_real_onesided_even_32(self): + x = np.zeros(16, 'f') + x[0] = 1 + x[8] = 1 + f, p = welch(x, nperseg=8) + assert_allclose(f, np.linspace(0, 0.5, 5)) + q = np.array([0.08333333, 0.15277778, 0.22222222, 0.22222222, + 0.11111111], 'f') + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + assert_(p.dtype == q.dtype) + + def test_real_onesided_odd_32(self): + x = np.zeros(16, 'f') + x[0] = 1 + x[8] = 1 + f, p = welch(x, nperseg=9) + assert_allclose(f, np.arange(5.0)/9.0) + q = np.array([0.12477458, 0.23430935, 0.17072113, 0.17072116, + 0.17072113], 'f') + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + assert_(p.dtype == q.dtype) + + def test_real_twosided_32(self): + x = np.zeros(16, 'f') + x[0] = 1 + x[8] = 1 + f, p = welch(x, nperseg=8, return_onesided=False) + assert_allclose(f, fftfreq(8, 1.0)) + q = np.array([0.08333333, 0.07638889, 0.11111111, + 0.11111111, 0.11111111, 0.11111111, 0.11111111, + 0.07638889], 'f') + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + assert_(p.dtype == q.dtype) + + def test_complex_32(self): + x = np.zeros(16, 'F') + x[0] = 1.0 + 2.0j + x[8] = 1.0 + 2.0j + f, p = welch(x, nperseg=8, return_onesided=False) + assert_allclose(f, fftfreq(8, 1.0)) + q = np.array([0.41666666, 0.38194442, 0.55555552, 0.55555552, + 0.55555558, 0.55555552, 0.55555552, 0.38194442], 'f') + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + assert_(p.dtype == q.dtype, + f'dtype mismatch, {p.dtype}, {q.dtype}') + + def test_padded_freqs(self): + x = np.zeros(12) + + nfft = 24 + f = fftfreq(nfft, 1.0)[:nfft//2+1] + f[-1] *= -1 + fodd, _ = welch(x, nperseg=5, nfft=nfft) + feven, _ = welch(x, nperseg=6, nfft=nfft) + assert_allclose(f, fodd) + assert_allclose(f, feven) + + nfft = 25 + f = fftfreq(nfft, 1.0)[:(nfft + 1)//2] + fodd, _ = welch(x, nperseg=5, nfft=nfft) + feven, _ = welch(x, nperseg=6, nfft=nfft) + assert_allclose(f, fodd) + assert_allclose(f, feven) + + def test_window_correction(self): + A = 20 + fs = 1e4 + nperseg = int(fs//10) + fsig = 300 + ii = int(fsig*nperseg//fs) # Freq index of fsig + + tt = np.arange(fs)/fs + x = A*np.sin(2*np.pi*fsig*tt) + + for window in ['hann', 'bartlett', ('tukey', 0.1), 'flattop']: + _, p_spec = welch(x, fs=fs, nperseg=nperseg, window=window, + scaling='spectrum') + freq, p_dens = welch(x, fs=fs, nperseg=nperseg, window=window, + scaling='density') + + # Check peak height at signal frequency for 'spectrum' + assert_allclose(p_spec[ii], A**2/2.0) + # Check integrated spectrum RMS for 'density' + assert_allclose(np.sqrt(trapezoid(p_dens, freq)), A*np.sqrt(2)/2, + rtol=1e-3) + + def test_axis_rolling(self): + np.random.seed(1234) + + x_flat = np.random.randn(1024) + _, p_flat = welch(x_flat) + + for a in range(3): + newshape = [1,]*3 + newshape[a] = -1 + x = x_flat.reshape(newshape) + + _, p_plus = welch(x, axis=a) # Positive axis index + _, p_minus = welch(x, axis=a-x.ndim) # Negative axis index + + assert_equal(p_flat, p_plus.squeeze(), err_msg=a) + assert_equal(p_flat, p_minus.squeeze(), err_msg=a-x.ndim) + + def test_average(self): + x = np.zeros(16) + x[0] = 1 + x[8] = 1 + f, p = welch(x, nperseg=8, average='median') + assert_allclose(f, np.linspace(0, 0.5, 5)) + q = np.array([.1, .05, 0., 1.54074396e-33, 0.]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + assert_raises(ValueError, welch, x, nperseg=8, + average='unrecognised-average') + + def test_ratio_scale_to(self): + """Verify the factor of ``sum(abs(window)**2)*fs / abs(sum(window))**2`` + used in the `welch` and `csd` docstrs. """ + x, win, fs = np.array([1., 0, 0, 0]), np.ones(4), 12 + params = dict(fs=fs, window=win, return_onesided=False, detrend=None) + p_dens = welch(x, scaling='density', **params)[1] + p_spec = welch(x, scaling='spectrum', **params)[1] + p_fac = sum(win**2)*fs / abs(sum(win))**2 + assert_allclose(p_spec / p_dens, p_fac) + +class TestCSD: + def test_pad_shorter_x(self): + x = np.zeros(8) + y = np.zeros(12) + + f = np.linspace(0, 0.5, 7) + c = np.zeros(7,dtype=np.complex128) + f1, c1 = csd(x, y, nperseg=12) + + assert_allclose(f, f1) + assert_allclose(c, c1) + + def test_pad_shorter_y(self): + x = np.zeros(12) + y = np.zeros(8) + + f = np.linspace(0, 0.5, 7) + c = np.zeros(7,dtype=np.complex128) + f1, c1 = csd(x, y, nperseg=12) + + assert_allclose(f, f1) + assert_allclose(c, c1) + + def test_unequal_length_input_1D(self): + """Test zero-padding for input `x.shape[axis] != y.shape[axis]` for 1d arrays. + + This test ensures that issue 23036 is fixed. + """ + x = np.tile([4, 0, -4, 0], 4) + + kw = dict(fs=len(x), window='boxcar', nperseg=4) + X0 = signal.csd(x, np.copy(x), **kw)[1] # `x is x` must be False + X1 = signal.csd(x, x[:8], **kw)[1] + X2 = signal.csd(x[:8], x, **kw)[1] + xp_assert_close(X1, X0 / 2) + xp_assert_close(X2, X0 / 2) + + def test_unequal_length_input_3D(self): + """Test zero-padding for input `x.shape[axis] != y.shape[axis]` for 3d arrays. + + This test ensures that issue 23036 is fixed. + """ + n = 8 + x = np.zeros(2 * 3 * n).reshape(2, n, 3) + x[:, 0, :] = n + + kw = dict(fs=n, window='boxcar', nperseg=n, detrend=None, axis=1) + X0 = signal.csd(x, x.copy(), **kw)[1] # `x is x` must be False + X1 = signal.csd(x, x[:, :2, :], **kw)[1] + X2 = signal.csd(x[:, :2, :], x, **kw)[1] + xp_assert_close(X1, X0) + xp_assert_close(X2, X0) + + def test_real_onesided_even(self): + x = np.zeros(16) + x[0] = 1 + x[8] = 1 + f, p = csd(x, x, nperseg=8) + assert_allclose(f, np.linspace(0, 0.5, 5)) + q = np.array([0.08333333, 0.15277778, 0.22222222, 0.22222222, + 0.11111111]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_real_onesided_odd(self): + x = np.zeros(16) + x[0] = 1 + x[8] = 1 + f, p = csd(x, x, nperseg=9) + assert_allclose(f, np.arange(5.0)/9.0) + q = np.array([0.12477455, 0.23430933, 0.17072113, 0.17072113, + 0.17072113]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_real_twosided(self): + x = np.zeros(16) + x[0] = 1 + x[8] = 1 + f, p = csd(x, x, nperseg=8, return_onesided=False) + assert_allclose(f, fftfreq(8, 1.0)) + q = np.array([0.08333333, 0.07638889, 0.11111111, 0.11111111, + 0.11111111, 0.11111111, 0.11111111, 0.07638889]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_real_spectrum(self): + x = np.zeros(16) + x[0] = 1 + x[8] = 1 + f, p = csd(x, x, nperseg=8, scaling='spectrum') + assert_allclose(f, np.linspace(0, 0.5, 5)) + q = np.array([0.015625, 0.02864583, 0.04166667, 0.04166667, + 0.02083333]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_integer_onesided_even(self): + x = np.zeros(16, dtype=int) + x[0] = 1 + x[8] = 1 + f, p = csd(x, x, nperseg=8) + assert_allclose(f, np.linspace(0, 0.5, 5)) + q = np.array([0.08333333, 0.15277778, 0.22222222, 0.22222222, + 0.11111111]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_integer_onesided_odd(self): + x = np.zeros(16, dtype=int) + x[0] = 1 + x[8] = 1 + f, p = csd(x, x, nperseg=9) + assert_allclose(f, np.arange(5.0)/9.0) + q = np.array([0.12477455, 0.23430933, 0.17072113, 0.17072113, + 0.17072113]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_integer_twosided(self): + x = np.zeros(16, dtype=int) + x[0] = 1 + x[8] = 1 + f, p = csd(x, x, nperseg=8, return_onesided=False) + assert_allclose(f, fftfreq(8, 1.0)) + q = np.array([0.08333333, 0.07638889, 0.11111111, 0.11111111, + 0.11111111, 0.11111111, 0.11111111, 0.07638889]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_complex(self): + x = np.zeros(16, np.complex128) + x[0] = 1.0 + 2.0j + x[8] = 1.0 + 2.0j + f, p = csd(x, x, nperseg=8, return_onesided=False) + assert_allclose(f, fftfreq(8, 1.0)) + q = np.array([0.41666667, 0.38194444, 0.55555556, 0.55555556, + 0.55555556, 0.55555556, 0.55555556, 0.38194444]) + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + + def test_unk_scaling(self): + assert_raises(ValueError, csd, np.zeros(4, np.complex128), + np.ones(4, np.complex128), scaling='foo', nperseg=4) + + def test_detrend_linear(self): + x = np.arange(10, dtype=np.float64) + 0.04 + f, p = csd(x, x, nperseg=10, detrend='linear') + assert_allclose(p, np.zeros_like(p), atol=1e-15) + + def test_no_detrending(self): + x = np.arange(10, dtype=np.float64) + 0.04 + f1, p1 = csd(x, x, nperseg=10, detrend=False) + f2, p2 = csd(x, x, nperseg=10, detrend=lambda x: x) + assert_allclose(f1, f2, atol=1e-15) + assert_allclose(p1, p2, atol=1e-15) + + def test_detrend_external(self): + x = np.arange(10, dtype=np.float64) + 0.04 + f, p = csd(x, x, nperseg=10, + detrend=lambda seg: signal.detrend(seg, type='l')) + assert_allclose(p, np.zeros_like(p), atol=1e-15) + + def test_detrend_external_nd_m1(self): + x = np.arange(40, dtype=np.float64) + 0.04 + x = x.reshape((2,2,10)) + f, p = csd(x, x, nperseg=10, + detrend=lambda seg: signal.detrend(seg, type='l')) + assert_allclose(p, np.zeros_like(p), atol=1e-15) + + def test_detrend_external_nd_0(self): + x = np.arange(20, dtype=np.float64) + 0.04 + x = x.reshape((2,1,10)) + x = np.moveaxis(x, 2, 0) + f, p = csd(x, x, nperseg=10, axis=0, + detrend=lambda seg: signal.detrend(seg, axis=0, type='l')) + assert_allclose(p, np.zeros_like(p), atol=1e-15) + + def test_nd_axis_m1(self): + x = np.arange(20, dtype=np.float64) + 0.04 + x = x.reshape((2,1,10)) + f, p = csd(x, x, nperseg=10) + assert_array_equal(p.shape, (2, 1, 6)) + assert_allclose(p[0,0,:], p[1,0,:], atol=1e-13, rtol=1e-13) + f0, p0 = csd(x[0,0,:], x[0,0,:], nperseg=10) + assert_allclose(p0[np.newaxis,:], p[1,:], atol=1e-13, rtol=1e-13) + + def test_nd_axis_0(self): + x = np.arange(20, dtype=np.float64) + 0.04 + x = x.reshape((10,2,1)) + f, p = csd(x, x, nperseg=10, axis=0) + assert_array_equal(p.shape, (6,2,1)) + assert_allclose(p[:,0,0], p[:,1,0], atol=1e-13, rtol=1e-13) + f0, p0 = csd(x[:,0,0], x[:,0,0], nperseg=10) + assert_allclose(p0, p[:,1,0], atol=1e-13, rtol=1e-13) + + def test_window_external(self): + x = np.zeros(16) + x[0] = 1 + x[8] = 1 + f, p = csd(x, x, 10, 'hann', 8) + win = signal.get_window('hann', 8) + fe, pe = csd(x, x, 10, win, nperseg=None) + assert_array_almost_equal_nulp(p, pe) + assert_array_almost_equal_nulp(f, fe) + assert_array_equal(fe.shape, (5,)) # because win length used as nperseg + assert_array_equal(pe.shape, (5,)) + assert_raises(ValueError, csd, x, x, + 10, win, nperseg=256) # because nperseg != win.shape[-1] + win_err = signal.get_window('hann', 32) + assert_raises(ValueError, csd, x, x, + 10, win_err, nperseg=None) # because win longer than signal + with pytest.raises(ValueError, match="Parameter nperseg=0.*"): + csd(x, x, 0, nperseg=0) + + def test_empty_input(self): + f, p = csd([],np.zeros(10)) + assert_array_equal(f.shape, (0,)) + assert_array_equal(p.shape, (0,)) + + f, p = csd(np.zeros(10),[]) + assert_array_equal(f.shape, (0,)) + assert_array_equal(p.shape, (0,)) + + for shape in [(0,), (3,0), (0,5,2)]: + f, p = csd(np.empty(shape), np.empty(shape)) + assert_array_equal(f.shape, shape) + assert_array_equal(p.shape, shape) + + f, p = csd(np.ones(10), np.empty((5,0))) + assert_array_equal(f.shape, (5,0)) + assert_array_equal(p.shape, (5,0)) + + f, p = csd(np.empty((5,0)), np.ones(10)) + assert_array_equal(f.shape, (5,0)) + assert_array_equal(p.shape, (5,0)) + + def test_empty_input_other_axis(self): + for shape in [(3,0), (0,5,2)]: + f, p = csd(np.empty(shape), np.empty(shape), axis=1) + assert_array_equal(f.shape, shape) + assert_array_equal(p.shape, shape) + + f, p = csd(np.empty((10,10,3)), np.zeros((10,0,1)), axis=1) + assert_array_equal(f.shape, (10,0,3)) + assert_array_equal(p.shape, (10,0,3)) + + f, p = csd(np.empty((10,0,1)), np.zeros((10,10,3)), axis=1) + assert_array_equal(f.shape, (10,0,3)) + assert_array_equal(p.shape, (10,0,3)) + + def test_short_data(self): + x = np.zeros(8) + x[0] = 1 + + #for string-like window, input signal length < nperseg value gives + #UserWarning, sets nperseg to x.shape[-1] + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "nperseg=256 is greater than signal length.*", UserWarning) + f, p = csd(x, x, window='hann') # default nperseg + f1, p1 = csd(x, x, window='hann', nperseg=256) # user-specified nperseg + f2, p2 = csd(x, x, nperseg=8) # valid nperseg, doesn't give warning + assert_allclose(f, f2) + assert_allclose(p, p2) + assert_allclose(f1, f2) + assert_allclose(p1, p2) + + def test_window_long_or_nd(self): + assert_raises(ValueError, csd, np.zeros(4), np.ones(4), 1, + np.array([1,1,1,1,1])) + assert_raises(ValueError, csd, np.zeros(4), np.ones(4), 1, + np.arange(6).reshape((2,3))) + + def test_nondefault_noverlap(self): + x = np.zeros(64) + x[::8] = 1 + f, p = csd(x, x, nperseg=16, noverlap=4) + q = np.array([0, 1./12., 1./3., 1./5., 1./3., 1./5., 1./3., 1./5., + 1./6.]) + assert_allclose(p, q, atol=1e-12) + + def test_bad_noverlap(self): + assert_raises(ValueError, csd, np.zeros(4), np.ones(4), 1, 'hann', + 2, 7) + + def test_nfft_too_short(self): + assert_raises(ValueError, csd, np.ones(12), np.zeros(12), nfft=3, + nperseg=4) + + def test_incompatible_inputs(self): + with pytest.raises(ValueError, match='x and y cannot be broadcast.*'): + csd(np.ones((1, 8, 1)), np.ones((2, 8)), nperseg=4) + + + def test_real_onesided_even_32(self): + x = np.zeros(16, 'f') + x[0] = 1 + x[8] = 1 + f, p = csd(x, x, nperseg=8) + assert_allclose(f, np.linspace(0, 0.5, 5)) + q = np.array([0.08333333, 0.15277778, 0.22222222, 0.22222222, + 0.11111111], 'f') + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + assert_(p.dtype == q.dtype) + + def test_real_onesided_odd_32(self): + x = np.zeros(16, 'f') + x[0] = 1 + x[8] = 1 + f, p = csd(x, x, nperseg=9) + assert_allclose(f, np.arange(5.0)/9.0) + q = np.array([0.12477458, 0.23430935, 0.17072113, 0.17072116, + 0.17072113], 'f') + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + assert_(p.dtype == q.dtype) + + def test_real_twosided_32(self): + x = np.zeros(16, 'f') + x[0] = 1 + x[8] = 1 + f, p = csd(x, x, nperseg=8, return_onesided=False) + assert_allclose(f, fftfreq(8, 1.0)) + q = np.array([0.08333333, 0.07638889, 0.11111111, + 0.11111111, 0.11111111, 0.11111111, 0.11111111, + 0.07638889], 'f') + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + assert_(p.dtype == q.dtype) + + def test_complex_32(self): + x = np.zeros(16, 'F') + x[0] = 1.0 + 2.0j + x[8] = 1.0 + 2.0j + f, p = csd(x, x, nperseg=8, return_onesided=False) + assert_allclose(f, fftfreq(8, 1.0)) + q = np.array([0.41666666, 0.38194442, 0.55555552, 0.55555552, + 0.55555558, 0.55555552, 0.55555552, 0.38194442], 'f') + assert_allclose(p, q, atol=1e-7, rtol=1e-7) + assert_(p.dtype == q.dtype, + f'dtype mismatch, {p.dtype}, {q.dtype}') + + def test_padded_freqs(self): + x = np.zeros(12) + y = np.ones(12) + + nfft = 24 + f = fftfreq(nfft, 1.0)[:nfft//2+1] + f[-1] *= -1 + fodd, _ = csd(x, y, nperseg=5, nfft=nfft) + feven, _ = csd(x, y, nperseg=6, nfft=nfft) + assert_allclose(f, fodd) + assert_allclose(f, feven) + + nfft = 25 + f = fftfreq(nfft, 1.0)[:(nfft + 1)//2] + fodd, _ = csd(x, y, nperseg=5, nfft=nfft) + feven, _ = csd(x, y, nperseg=6, nfft=nfft) + assert_allclose(f, fodd) + assert_allclose(f, feven) + + def test_copied_data(self): + x = np.random.randn(64) + y = x.copy() + + _, p_same = csd(x, x, nperseg=8, average='mean', + return_onesided=False) + _, p_copied = csd(x, y, nperseg=8, average='mean', + return_onesided=False) + assert_allclose(p_same, p_copied) + + _, p_same = csd(x, x, nperseg=8, average='median', + return_onesided=False) + _, p_copied = csd(x, y, nperseg=8, average='median', + return_onesided=False) + assert_allclose(p_same, p_copied) + + +class TestCoherence: + def test_identical_input(self): + x = np.random.randn(20) + y = np.copy(x) # So `y is x` -> False + + f = np.linspace(0, 0.5, 6) + C = np.ones(6) + f1, C1 = coherence(x, y, nperseg=10) + + assert_allclose(f, f1) + assert_allclose(C, C1) + + def test_phase_shifted_input(self): + x = np.random.randn(20) + y = -x + + f = np.linspace(0, 0.5, 6) + C = np.ones(6) + f1, C1 = coherence(x, y, nperseg=10) + + assert_allclose(f, f1) + assert_allclose(C, C1) + + +class TestSpectrogram: + def test_average_all_segments(self): + x = np.random.randn(1024) + + fs = 1.0 + window = ('tukey', 0.25) + nperseg = 16 + noverlap = 2 + + f, _, P = spectrogram(x, fs, window, nperseg, noverlap) + fw, Pw = welch(x, fs, window, nperseg, noverlap) + assert_allclose(f, fw) + assert_allclose(np.mean(P, axis=-1), Pw) + + def test_window_external(self): + x = np.random.randn(1024) + + fs = 1.0 + window = ('tukey', 0.25) + nperseg = 16 + noverlap = 2 + f, _, P = spectrogram(x, fs, window, nperseg, noverlap) + + win = signal.get_window(('tukey', 0.25), 16) + fe, _, Pe = spectrogram(x, fs, win, nperseg=None, noverlap=2) + assert_array_equal(fe.shape, (9,)) # because win length used as nperseg + assert_array_equal(Pe.shape, (9,73)) + assert_raises(ValueError, spectrogram, x, + fs, win, nperseg=8) # because nperseg != win.shape[-1] + win_err = signal.get_window(('tukey', 0.25), 2048) + assert_raises(ValueError, spectrogram, x, + fs, win_err, nperseg=None) # win longer than signal + + def test_short_data(self): + x = np.random.randn(1024) + fs = 1.0 + + #for string-like window, input signal length < nperseg value gives + #UserWarning, sets nperseg to x.shape[-1] + f, _, p = spectrogram(x, fs, window=('tukey',0.25)) # default nperseg + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "nperseg = 1025 is greater than input length = 1024, " + "using nperseg = 1024", + UserWarning, + ) + f1, _, p1 = spectrogram(x, fs, window=('tukey',0.25), + nperseg=1025) # user-specified nperseg + f2, _, p2 = spectrogram(x, fs, nperseg=256) # to compare w/default + f3, _, p3 = spectrogram(x, fs, nperseg=1024) # compare w/user-spec'd + assert_allclose(f, f2) + assert_allclose(p, p2) + assert_allclose(f1, f3) + assert_allclose(p1, p3) + +class TestLombscargle: + def test_frequency(self): + """Test if frequency location of peak corresponds to frequency of + generated input signal. + """ + + # Input parameters + ampl = 2. + w = 1. + phi = 0.5 * np.pi + nin = 100 + nout = 1000 + p = 0.7 # Fraction of points to select + + # Randomly select a fraction of an array with timesteps + rng = np.random.RandomState(2353425) + r = rng.rand(nin) + t = np.linspace(0.01*np.pi, 10.*np.pi, nin)[r >= p] + + # Plot a sine wave for the selected times + y = ampl * np.sin(w*t + phi) + + # Define the array of frequencies for which to compute the periodogram + f = np.linspace(0.01, 10., nout) + + # Calculate Lomb-Scargle periodogram + P = lombscargle(t, y, f) + + # Check if difference between found frequency maximum and input + # frequency is less than accuracy + delta = f[1] - f[0] + assert(w - f[np.argmax(P)] < (delta/2.)) + + # also, check that it works with weights + P = lombscargle(t, y, f, weights=np.ones_like(t, dtype=f.dtype)) + + # Check if difference between found frequency maximum and input + # frequency is less than accuracy + delta = f[1] - f[0] + assert(w - f[np.argmax(P)] < (delta/2.)) + + def test_amplitude(self): + # Test if height of peak in unnormalized Lomb-Scargle periodogram + # corresponds to amplitude of the generated input signal. + + # Input parameters + ampl = 2. + w = 1. + phi = 0.5 * np.pi + nin = 1000 + nout = 1000 + p = 0.7 # Fraction of points to select + + # Randomly select a fraction of an array with timesteps + rng = np.random.RandomState(2353425) + r = rng.rand(nin) + t = np.linspace(0.01*np.pi, 10.*np.pi, nin)[r >= p] + + # Plot a sine wave for the selected times + y = ampl * np.sin(w*t + phi) + + # Define the array of frequencies for which to compute the periodogram + f = np.linspace(0.01, 10., nout) + + # Calculate Lomb-Scargle periodogram + pgram = lombscargle(t, y, f) + + # convert to the amplitude + pgram = np.sqrt(4.0 * pgram / t.shape[0]) + + # Check if amplitude is correct (this will not exactly match, due to + # numerical differences when data is removed) + assert_allclose(pgram[f==w], ampl, rtol=5e-2) + + @pytest.mark.filterwarnings("ignore::DeprecationWarning") + def test_precenter(self): + # Test if precenter gives the same result as manually precentering + # (for a very simple offset) + + # Input parameters + ampl = 2. + w = 1. + phi = 0.5 * np.pi + nin = 100 + nout = 1000 + p = 0.7 # Fraction of points to select + offset = 0.15 # Offset to be subtracted in pre-centering + + # Randomly select a fraction of an array with timesteps + rng = np.random.RandomState(2353425) + r = rng.rand(nin) + t = np.linspace(0.01*np.pi, 10.*np.pi, nin)[r >= p] + + # Plot a sine wave for the selected times + y = ampl * np.sin(w*t + phi) + offset + + # Define the array of frequencies for which to compute the periodogram + f = np.linspace(0.01, 10., nout) + + # Calculate Lomb-Scargle periodogram + pgram = lombscargle(t, y, f, precenter=True) + pgram2 = lombscargle(t, y - y.mean(), f, precenter=False) + + # check if centering worked + assert_allclose(pgram, pgram2) + + # do this again, but with floating_mean=True + + # Calculate Lomb-Scargle periodogram + pgram = lombscargle(t, y, f, precenter=True, floating_mean=True) + pgram2 = lombscargle(t, y - y.mean(), f, precenter=False, floating_mean=True) + + # check if centering worked + assert_allclose(pgram, pgram2) + + def test_normalize(self): + # Test normalize option of Lomb-Scarge. + + # Input parameters + ampl = 2. + w = 1. + phi = 0.5 * np.pi + nin = 100 + nout = 1000 + p = 0.7 # Fraction of points to select + + # Randomly select a fraction of an array with timesteps + rng = np.random.RandomState(2353425) + r = rng.rand(nin) + t = np.linspace(0.01*np.pi, 10.*np.pi, nin)[r >= p] + + # Plot a sine wave for the selected times + y = ampl * np.sin(w*t + phi) + + # Define the array of frequencies for which to compute the periodogram + f = np.linspace(0.01, 10., nout) + + # Calculate Lomb-Scargle periodogram + pgram = lombscargle(t, y, f) + pgram2 = lombscargle(t, y, f, normalize=True) + + # Calculate the scale to convert from unnormalized to normalized + weights = np.ones_like(t)/float(t.shape[0]) + YY_hat = (weights * y * y).sum() + YY = YY_hat # correct formula for floating_mean=False + scale_to_use = 2/(YY*t.shape[0]) + + # check if normalization works as expected + assert_allclose(pgram * scale_to_use, pgram2) + assert_allclose(np.max(pgram2), 1.0) + + def test_wrong_shape(self): + + # different length t and y + t = np.linspace(0, 1, 1) + y = np.linspace(0, 1, 2) + f = np.linspace(0, 1, 3) + 0.1 + assert_raises(ValueError, lombscargle, t, y, f) + + # t is 2D, with both axes length > 1 + t = np.repeat(np.expand_dims(np.linspace(0, 1, 2), 1), 2, axis=1) + y = np.linspace(0, 1, 2) + f = np.linspace(0, 1, 3) + 0.1 + assert_raises(ValueError, lombscargle, t, y, f) + + # y is 2D, with both axes length > 1 + t = np.linspace(0, 1, 2) + y = np.repeat(np.expand_dims(np.linspace(0, 1, 2), 1), 2, axis=1) + f = np.linspace(0, 1, 3) + 0.1 + assert_raises(ValueError, lombscargle, t, y, f) + + # f is 2D, with both axes length > 1 + t = np.linspace(0, 1, 2) + y = np.linspace(0, 1, 2) + f = np.repeat(np.expand_dims(np.linspace(0, 1, 3), 1) + 0.1, 2, axis=1) + assert_raises(ValueError, lombscargle, t, y, f) + + # weights is 2D, with both axes length > 1 + t = np.linspace(0, 1, 2) + y = np.linspace(0, 1, 2) + f = np.linspace(0, 1, 3) + 0.1 + weights = np.repeat(np.expand_dims(np.linspace(0, 1, 2), 1), 2, axis=1) + assert_raises(ValueError, lombscargle, t, y, f, weights=weights) + + def test_lombscargle_atan_vs_atan2(self): + # https://github.com/scipy/scipy/issues/3787 + # This raised a ZeroDivisionError. + t = np.linspace(0, 10, 1000, endpoint=False) + y = np.sin(4*t) + f = np.linspace(0, 50, 500, endpoint=False) + 0.1 + lombscargle(t, y, f*2*np.pi) + + def test_wrong_shape_weights(self): + # Weights must be the same shape as t + + t = np.linspace(0, 1, 1) + y = np.linspace(0, 1, 1) + f = np.linspace(0, 1, 3) + 0.1 + weights = np.linspace(1, 2, 2) + assert_raises(ValueError, lombscargle, t, y, f, weights=weights) + + def test_zero_division_weights(self): + # Weights cannot sum to 0 + + t = np.zeros(1) + y = np.zeros(1) + f = np.ones(1) + weights = np.zeros(1) + assert_raises(ValueError, lombscargle, t, y, f, weights=weights) + + def test_normalize_parameter(self): + # Test the validity of the normalize parameter input + + # Input parameters + ampl = 2. + w = 1. + phi = 0 + nin = 100 + nout = 1000 + p = 0.7 # Fraction of points to select + + # Randomly select a fraction of an array with timesteps + rng = np.random.RandomState(2353425) + r = rng.rand(nin) + t = np.linspace(0.01*np.pi, 10.*np.pi, nin)[r >= p] + + # Plot a sine wave for the selected times + y = ampl * np.sin(w*t + phi) + + # Define the array of frequencies for which to compute the periodogram + f = np.linspace(0.01, 10., nout) + + # check each of the valid inputs + pgram_false = lombscargle(t, y, f, normalize=False) + pgram_true = lombscargle(t, y, f, normalize=True) + pgram_power = lombscargle(t, y, f, normalize='power') + pgram_norm = lombscargle(t, y, f, normalize='normalize') + pgram_amp = lombscargle(t, y, f, normalize='amplitude') + + # validate the results that should be the same + assert_allclose(pgram_false, pgram_power) + assert_allclose(pgram_true, pgram_norm) + + # validate that the power and norm outputs are proper wrt each other + weights = np.ones_like(y)/float(y.shape[0]) + YY_hat = (weights * y * y).sum() + YY = YY_hat # correct formula for floating_mean=False + assert_allclose(pgram_power * 2.0 / (float(t.shape[0]) * YY), pgram_norm) + + # validate that the amp output is correct for the given input + f_i = np.where(f==w)[0][0] + assert_allclose(np.abs(pgram_amp[f_i]), ampl) + + # check invalid inputs + # 1) a string that is not allowed + assert_raises(ValueError, lombscargle, t, y, f, normalize='lomb') + # 2) something besides a bool or str + assert_raises(ValueError, lombscargle, t, y, f, normalize=2) + + def test_offset_removal(self): + # Verify that the amplitude is the same, even with an offset + # must use floating_mean=True, otherwise it will not remove an offset + + # Input parameters + ampl = 2. + w = 1. + phi = 0.5 * np.pi + nin = 100 + nout = 1000 + p = 0.7 # Fraction of points to select + offset = 2.15 # Large offset + + # Randomly select a fraction of an array with timesteps + rng = np.random.RandomState(2353425) + r = rng.rand(nin) + t = np.linspace(0.01*np.pi, 10.*np.pi, nin)[r >= p] + + # Plot a sine wave for the selected times + y = ampl * np.sin(w*t + phi) + + # Define the array of frequencies for which to compute the periodogram + f = np.linspace(0.01, 10., nout) + + # Calculate Lomb-Scargle periodogram + pgram = lombscargle(t, y, f, floating_mean=True) + pgram_offset = lombscargle(t, y + offset, f, floating_mean=True) + + # check if offset removal works as expected + assert_allclose(pgram, pgram_offset) + + def test_floating_mean_false(self): + # Verify that when disabling the floating_mean, the calculations are correct + + # Input parameters + ampl = 2. + w = 1. + phi = 0 + nin = 1000 + nout = 1000 + p = 0.7 # Fraction of points to select + offset = 2 # Large offset + + # Randomly select a fraction of an array with timesteps + rng = np.random.RandomState(2353425) + r = rng.rand(nin) + t = np.linspace(0.01*np.pi, 10.*np.pi, nin)[r >= p] + + # Plot a cos wave for the selected times + y = ampl * np.cos(w*t + phi) + + # Define the array of frequencies for which to compute the periodogram + f = np.linspace(0.01, 10., nout) + + # Calculate Lomb-Scargle periodogram + pgram = lombscargle(t, y, f, normalize=True, floating_mean=False) + pgram_offset = lombscargle(t, y + offset, f, normalize=True, + floating_mean=False) + + # check if disabling floating_mean works as expected + # nearly-zero for no offset, exact value will change based on seed + assert(pgram[0] < 0.01) + # significant value with offset, exact value will change based on seed + assert(pgram_offset[0] > 0.5) + + def test_amplitude_is_correct(self): + # Verify that the amplitude is correct (when normalize='amplitude') + + # Input parameters + ampl = 2. + w = 1. + phi = 0.12 + nin = 100 + nout = 1000 + p = 0.7 # Fraction of points to select + offset = 2.15 # Large offset + + # Randomly select a fraction of an array with timesteps + rng = np.random.RandomState(2353425) + r = rng.rand(nin) + t = np.linspace(0.01*np.pi, 10.*np.pi, nin)[r >= p] + + # Plot a sine wave for the selected times + y = ampl * np.cos(w*t + phi) + offset + + # Define the array of frequencies for which to compute the periodogram + f = np.linspace(0.01, 10., nout) + + # Get the index of where the exact result should be + f_indx = np.where(f==w)[0][0] + + # Calculate Lomb-Scargle periodogram (amplitude + phase) + pgram = lombscargle(t, y, f, normalize='amplitude', floating_mean=True) + + # Check if amplitude is correct + assert_allclose(np.abs(pgram[f_indx]), ampl) + + # Check if phase is correct + # (phase angle is the negative of the phase offset) + assert_allclose(-np.angle(pgram[f_indx]), phi) + + def test_negative_weight(self): + # Test that a negative weight produces an error + + t = np.zeros(1) + y = np.zeros(1) + f = np.ones(1) + weights = -np.ones(1) + assert_raises(ValueError, lombscargle, t, y, f, weights=weights) + + @pytest.mark.filterwarnings("ignore::DeprecationWarning") + def test_list_input(self): + # Test that input can be passsed in as lists and with a numerical issue + # https://github.com/scipy/scipy/issues/8787 + + t = [1.98201652e+09, 1.98201752e+09, 1.98201852e+09, 1.98201952e+09, + 1.98202052e+09, 1.98202152e+09, 1.98202252e+09, 1.98202352e+09, + 1.98202452e+09, 1.98202552e+09, 1.98202652e+09, 1.98202752e+09, + 1.98202852e+09, 1.98202952e+09, 1.98203052e+09, 1.98203152e+09, + 1.98203252e+09, 1.98203352e+09, 1.98203452e+09, 1.98203552e+09, + 1.98205452e+09, 1.98205552e+09, 1.98205652e+09, 1.98205752e+09, + 1.98205852e+09, 1.98205952e+09, 1.98206052e+09, 1.98206152e+09, + 1.98206252e+09, 1.98206352e+09, 1.98206452e+09, 1.98206552e+09, + 1.98206652e+09, 1.98206752e+09, 1.98206852e+09, 1.98206952e+09, + 1.98207052e+09, 1.98207152e+09, 1.98207252e+09, 1.98207352e+09, + 1.98209652e+09, 1.98209752e+09, 1.98209852e+09, 1.98209952e+09, + 1.98210052e+09, 1.98210152e+09, 1.98210252e+09, 1.98210352e+09, + 1.98210452e+09, 1.98210552e+09, 1.98210652e+09, 1.98210752e+09, + 1.98210852e+09, 1.98210952e+09, 1.98211052e+09, 1.98211152e+09, + 1.98211252e+09, 1.98211352e+09, 1.98211452e+09, 1.98211552e+09, + 1.98217252e+09, 1.98217352e+09, 1.98217452e+09, 1.98217552e+09, + 1.98217652e+09, 1.98217752e+09, 1.98217852e+09, 1.98217952e+09, + 1.98218052e+09, 1.98218152e+09, 1.98218252e+09, 1.98218352e+09, + 1.98218452e+09, 1.98218552e+09, 1.98218652e+09, 1.98218752e+09, + 1.98218852e+09, 1.98218952e+09, 1.98219052e+09, 1.98219152e+09, + 1.98219352e+09, 1.98219452e+09, 1.98219552e+09, 1.98219652e+09, + 1.98219752e+09, 1.98219852e+09, 1.98219952e+09, 1.98220052e+09, + 1.98220152e+09, 1.98220252e+09, 1.98220352e+09, 1.98220452e+09, + 1.98220552e+09, 1.98220652e+09, 1.98220752e+09, 1.98220852e+09, + 1.98220952e+09, 1.98221052e+09, 1.98221152e+09, 1.98221252e+09, + 1.98222752e+09, 1.98222852e+09, 1.98222952e+09, 1.98223052e+09, + 1.98223152e+09, 1.98223252e+09, 1.98223352e+09, 1.98223452e+09, + 1.98223552e+09, 1.98223652e+09, 1.98223752e+09, 1.98223852e+09, + 1.98223952e+09, 1.98224052e+09, 1.98224152e+09, 1.98224252e+09, + 1.98224352e+09, 1.98224452e+09, 1.98224552e+09, 1.98224652e+09, + 1.98224752e+09] + y = [2.97600000e+03, 3.18200000e+03, 3.74900000e+03, 4.53500000e+03, + 5.43300000e+03, 6.38000000e+03, 7.34000000e+03, 8.29200000e+03, + 9.21900000e+03, 1.01120000e+04, 1.09620000e+04, 1.17600000e+04, + 1.25010000e+04, 1.31790000e+04, 1.37900000e+04, 1.43290000e+04, + 1.47940000e+04, 1.51800000e+04, 1.54870000e+04, 1.57110000e+04, + 5.74200000e+03, 4.82300000e+03, 3.99100000e+03, 3.33600000e+03, + 2.99600000e+03, 3.08400000e+03, 3.56700000e+03, 4.30700000e+03, + 5.18200000e+03, 6.11900000e+03, 7.07900000e+03, 8.03400000e+03, + 8.97000000e+03, 9.87300000e+03, 1.07350000e+04, 1.15480000e+04, + 1.23050000e+04, 1.30010000e+04, 1.36300000e+04, 1.41890000e+04, + 6.00000000e+03, 5.06800000e+03, 4.20500000e+03, 3.49000000e+03, + 3.04900000e+03, 3.01600000e+03, 3.40400000e+03, 4.08800000e+03, + 4.93500000e+03, 5.86000000e+03, 6.81700000e+03, 7.77500000e+03, + 8.71800000e+03, 9.63100000e+03, 1.05050000e+04, 1.13320000e+04, + 1.21050000e+04, 1.28170000e+04, 1.34660000e+04, 1.40440000e+04, + 1.32730000e+04, 1.26040000e+04, 1.18720000e+04, 1.10820000e+04, + 1.02400000e+04, 9.35300000e+03, 8.43000000e+03, 7.48100000e+03, + 6.52100000e+03, 5.57000000e+03, 4.66200000e+03, 3.85400000e+03, + 3.24600000e+03, 2.97900000e+03, 3.14700000e+03, 3.68800000e+03, + 4.45900000e+03, 5.35000000e+03, 6.29400000e+03, 7.25400000e+03, + 9.13800000e+03, 1.00340000e+04, 1.08880000e+04, 1.16910000e+04, + 1.24370000e+04, 1.31210000e+04, 1.37380000e+04, 1.42840000e+04, + 1.47550000e+04, 1.51490000e+04, 1.54630000e+04, 1.56950000e+04, + 1.58430000e+04, 1.59070000e+04, 1.58860000e+04, 1.57800000e+04, + 1.55910000e+04, 1.53190000e+04, 1.49650000e+04, 1.45330000e+04, + 3.01000000e+03, 3.05900000e+03, 3.51200000e+03, 4.23400000e+03, + 5.10000000e+03, 6.03400000e+03, 6.99300000e+03, 7.95000000e+03, + 8.88800000e+03, 9.79400000e+03, 1.06600000e+04, 1.14770000e+04, + 1.22400000e+04, 1.29410000e+04, 1.35770000e+04, 1.41430000e+04, + 1.46350000e+04, 1.50500000e+04, 1.53850000e+04, 1.56400000e+04, + 1.58110000e+04] + + periods = np.linspace(400, 120, 1000) + angular_freq = 2 * np.pi / periods + + lombscargle(t, y, angular_freq, precenter=True, normalize=True) + + def test_zero_freq(self): + # Verify that function works when freqs includes 0 + # The value at f=0 will depend on the seed + + # Input parameters + ampl = 2. + w = 1. + phi = 0.12 + nin = 100 + nout = 1001 + p = 0.7 # Fraction of points to select + offset = 0 + + # Randomly select a fraction of an array with timesteps + rng = np.random.RandomState(2353425) + r = rng.rand(nin) + t = np.linspace(0.01*np.pi, 10.*np.pi, nin)[r >= p] + + # Plot a sine wave for the selected times + y = ampl * np.cos(w*t + phi) + offset + + # Define the array of frequencies for which to compute the periodogram + f = np.linspace(0, 10., nout) + + # Calculate Lomb-Scargle periodogram + pgram = lombscargle(t, y, f, normalize=True, floating_mean=True) + + # exact value will change based on seed + # testing to make sure it is very small + assert(pgram[0] < 1e-4) + + def test_simple_div_zero(self): + # these are bare-minimum examples that would, without the eps adjustments, + # cause division-by-zero errors + + # first, test with example that will cause first SS sum to be 0.0 + t = [t + 1 for t in range(0, 32)] + y = np.ones(len(t)) + freqs = [2.0*np.pi] * 2 # must have 2+ elements + lombscargle(t, y, freqs) + + # second, test with example that will cause first CC sum to be 0.0 + t = [t*4 + 1 for t in range(0, 32)] + y = np.ones(len(t)) + freqs = [np.pi/2.0] * 2 # must have 2+ elements + + lombscargle(t, y, freqs) + + @pytest.mark.filterwarnings("ignore::DeprecationWarning") + def test_input_mutation(self): + # this tests for mutation of the input arrays + # https://github.com/scipy/scipy/issues/23474 + + # Input parameters + ampl = 2. + w = 1. + phi = 0.5 * np.pi + nin = 100 + nout = 1000 + p = 0.7 # Fraction of points to select + + # Randomly select a fraction of an array with timesteps + rng = np.random.default_rng() + r = rng.random(nin) + t = np.linspace(0.01*np.pi, 10.*np.pi, nin)[r >= p] + + # Plot a sine wave for the selected times + y = ampl * np.sin(w*t + phi) + + # Define the array of frequencies for which to compute the periodogram + f = np.linspace(0.01, 10., nout) + + weights = np.ones_like(y) + + # create original copies before passing + t_org = t.copy() + y_org = y.copy() + f_org = f.copy() + weights_org = weights.copy() + + lombscargle(t, y, f, precenter=True, weights=weights) + + # check all 4 array inputs + assert_array_equal(t, t_org) + assert_array_equal(y, y_org) + assert_array_equal(f, f_org) + assert_array_equal(weights, weights_org) + + def test_precenter_deprecation(self): + # test that precenter deprecation warning is raised + + # Input parameters + ampl = 2. + w = 1. + phi = 0.5 * np.pi + nin = 100 + nout = 1000 + p = 0.7 # Fraction of points to select + offset = 0.15 # Offset to be subtracted in pre-centering + + # Randomly select a fraction of an array with timesteps + rng = np.random.default_rng() + r = rng.random(nin) + t = np.linspace(0.01*np.pi, 10.*np.pi, nin)[r >= p] + + # Plot a sine wave for the selected times + y = ampl * np.sin(w*t + phi) + offset + + # Define the array of frequencies for which to compute the periodogram + f = np.linspace(0.01, 10., nout) + + # Calculate Lomb-Scargle periodogram + with pytest.deprecated_call(match="leave 'precenter' unspecified"): + lombscargle(t, y, f, precenter=True) + # Should warn for explicit `False` too + with pytest.deprecated_call(match="leave 'precenter' unspecified"): + lombscargle(t, y, f, precenter=False) + + @pytest.mark.filterwarnings( + "ignore:.*leave 'precenter' unspecified.*:DeprecationWarning" + ) + def test_positional_args_deprecation(self): + with pytest.deprecated_call(match="use keyword arguments"): + one = np.asarray([1.0]) + lombscargle(one, one, one, False) + + +class TestSTFT: + def test_input_validation(self): + + def chk_VE(match): + """Assert for a ValueError matching regexp `match`. + + This little wrapper allows a more concise code layout. + """ + return pytest.raises(ValueError, match=match) + + # Checks for check_COLA(): + with chk_VE('nperseg must be a positive integer'): + check_COLA('hann', -10, 0) + with chk_VE('noverlap must be less than nperseg.'): + check_COLA('hann', 10, 20) + with chk_VE('window must be 1-D'): + check_COLA(np.ones((2, 2)), 10, 0) + with chk_VE('window must have length of nperseg'): + check_COLA(np.ones(20), 10, 0) + + # Checks for check_NOLA(): + with chk_VE('nperseg must be a positive integer'): + check_NOLA('hann', -10, 0) + with chk_VE('noverlap must be less than nperseg'): + check_NOLA('hann', 10, 20) + with chk_VE('window must be 1-D'): + check_NOLA(np.ones((2, 2)), 10, 0) + with chk_VE('window must have length of nperseg'): + check_NOLA(np.ones(20), 10, 0) + with chk_VE('noverlap must be a nonnegative integer'): + check_NOLA('hann', 64, -32) + + x = np.zeros(1024) + z = stft(x)[2] + + # Checks for stft(): + with chk_VE('window must be 1-D'): + stft(x, window=np.ones((2, 2))) + with chk_VE('value specified for nperseg is different ' + + 'from length of window'): + stft(x, window=np.ones(10), nperseg=256) + with chk_VE('nperseg must be a positive integer'): + stft(x, nperseg=-256) + with chk_VE('noverlap must be less than nperseg.'): + stft(x, nperseg=256, noverlap=1024) + with chk_VE('nfft must be greater than or equal to nperseg.'): + stft(x, nperseg=256, nfft=8) + + # Checks for istft(): + with chk_VE('Input stft must be at least 2d!'): + istft(x) + with chk_VE('window must be 1-D'): + istft(z, window=np.ones((2, 2))) + with chk_VE('window must have length of 256'): + istft(z, window=np.ones(10), nperseg=256) + with chk_VE('nperseg must be a positive integer'): + istft(z, nperseg=-256) + with chk_VE('noverlap must be less than nperseg.'): + istft(z, nperseg=256, noverlap=1024) + with chk_VE('nfft must be greater than or equal to nperseg.'): + istft(z, nperseg=256, nfft=8) + with pytest.warns(UserWarning, match="NOLA condition failed, " + + "STFT may not be invertible"): + istft(z, nperseg=256, noverlap=0, window='hann') + with chk_VE('Must specify differing time and frequency axes!'): + istft(z, time_axis=0, freq_axis=0) + + # Checks for _spectral_helper(): + with chk_VE("Unknown value for mode foo, must be one of: " + + r"\{'psd', 'stft'\}"): + _spectral_helper(x, x, mode='foo') + with chk_VE("x and y must be equal if mode is 'stft'"): + _spectral_helper(x[:512], x[512:], mode='stft') + with chk_VE("Unknown boundary option 'foo', must be one of: " + + r"\['even', 'odd', 'constant', 'zeros', None\]"): + _spectral_helper(x, x, boundary='foo') + + scaling = "not_valid" + with chk_VE(fr"Parameter {scaling=} not in \['spectrum', 'psd'\]!"): + stft(x, scaling=scaling) + with chk_VE(fr"Parameter {scaling=} not in \['spectrum', 'psd'\]!"): + istft(z, scaling=scaling) + + def test_check_COLA(self): + settings = [ + ('boxcar', 10, 0), + ('boxcar', 10, 9), + ('bartlett', 51, 26), + ('hann', 256, 128), + ('hann', 256, 192), + ('blackman', 300, 200), + (('tukey', 0.5), 256, 64), + ('hann', 256, 255), + ] + + for setting in settings: + msg = '{}, {}, {}'.format(*setting) + assert_equal(True, check_COLA(*setting), err_msg=msg) + + def test_check_NOLA(self): + settings_pass = [ + ('boxcar', 10, 0), + ('boxcar', 10, 9), + ('boxcar', 10, 7), + ('bartlett', 51, 26), + ('bartlett', 51, 10), + ('hann', 256, 128), + ('hann', 256, 192), + ('hann', 256, 37), + ('blackman', 300, 200), + ('blackman', 300, 123), + (('tukey', 0.5), 256, 64), + (('tukey', 0.5), 256, 38), + ('hann', 256, 255), + ('hann', 256, 39), + ] + for setting in settings_pass: + msg = '{}, {}, {}'.format(*setting) + assert_equal(True, check_NOLA(*setting), err_msg=msg) + + w_fail = np.ones(16) + w_fail[::2] = 0 + settings_fail = [ + (w_fail, len(w_fail), len(w_fail) // 2), + ('hann', 64, 0), + ] + for setting in settings_fail: + msg = '{}, {}, {}'.format(*setting) + assert_equal(False, check_NOLA(*setting), err_msg=msg) + + def test_average_all_segments(self): + rng = np.random.RandomState(1234) + x = rng.randn(1024) + + fs = 1.0 + window = 'hann' + nperseg = 16 + noverlap = 8 + + # Compare twosided, because onesided welch doubles non-DC terms to + # account for power at negative frequencies. stft doesn't do this, + # because it breaks invertibility. + f, _, Z = stft(x, fs, window, nperseg, noverlap, padded=False, + return_onesided=False, boundary=None) + fw, Pw = welch(x, fs, window, nperseg, noverlap, return_onesided=False, + scaling='spectrum', detrend=False) + + assert_allclose(f, fw) + assert_allclose(np.mean(np.abs(Z)**2, axis=-1), Pw) + + def test_permute_axes(self): + rng = np.random.RandomState(1234) + x = rng.randn(1024) + + fs = 1.0 + window = 'hann' + nperseg = 16 + noverlap = 8 + + f1, t1, Z1 = stft(x, fs, window, nperseg, noverlap) + f2, t2, Z2 = stft(x.reshape((-1, 1, 1)), fs, window, nperseg, noverlap, + axis=0) + + t3, x1 = istft(Z1, fs, window, nperseg, noverlap) + t4, x2 = istft(Z2.T, fs, window, nperseg, noverlap, time_axis=0, + freq_axis=-1) + + assert_allclose(f1, f2) + assert_allclose(t1, t2) + assert_allclose(t3, t4) + assert_allclose(Z1, Z2[:, 0, 0, :]) + assert_allclose(x1, x2[:, 0, 0]) + + @pytest.mark.parametrize('scaling', ['spectrum', 'psd']) + def test_roundtrip_real(self, scaling): + rng = np.random.RandomState(1234) + + settings = [ + ('boxcar', 100, 10, 0), # Test no overlap + ('boxcar', 100, 10, 9), # Test high overlap + ('bartlett', 101, 51, 26), # Test odd nperseg + ('hann', 1024, 256, 128), # Test defaults + (('tukey', 0.5), 1152, 256, 64), # Test Tukey + ('hann', 1024, 256, 255), # Test overlapped hann + ] + + for window, N, nperseg, noverlap in settings: + t = np.arange(N) + x = 10*rng.randn(t.size) + + _, _, zz = stft(x, nperseg=nperseg, noverlap=noverlap, + window=window, detrend=None, padded=False, + scaling=scaling) + + tr, xr = istft(zz, nperseg=nperseg, noverlap=noverlap, + window=window, scaling=scaling) + + msg = f'{window}, {noverlap}' + assert_allclose(t, tr, err_msg=msg) + assert_allclose(x, xr, err_msg=msg) + + def test_roundtrip_not_nola(self): + rng = np.random.RandomState(1234) + + w_fail = np.ones(16) + w_fail[::2] = 0 + settings = [ + (w_fail, 256, len(w_fail), len(w_fail) // 2), + ('hann', 256, 64, 0), + ] + + for window, N, nperseg, noverlap in settings: + msg = f'{window}, {N}, {nperseg}, {noverlap}' + assert not check_NOLA(window, nperseg, noverlap), msg + + t = np.arange(N) + x = 10 * rng.randn(t.size) + + _, _, zz = stft(x, nperseg=nperseg, noverlap=noverlap, + window=window, detrend=None, padded=True, + boundary='zeros') + with pytest.warns(UserWarning, match='NOLA'): + tr, xr = istft(zz, nperseg=nperseg, noverlap=noverlap, + window=window, boundary=True) + + assert np.allclose(t, tr[:len(t)]), msg + assert not np.allclose(x, xr[:len(x)]), msg + + def test_roundtrip_nola_not_cola(self): + rng = np.random.RandomState(1234) + + settings = [ + ('boxcar', 100, 10, 3), # NOLA True, COLA False + ('bartlett', 101, 51, 37), # NOLA True, COLA False + ('hann', 1024, 256, 127), # NOLA True, COLA False + (('tukey', 0.5), 1152, 256, 14), # NOLA True, COLA False + ('hann', 1024, 256, 5), # NOLA True, COLA False + ] + + for window, N, nperseg, noverlap in settings: + msg = f'{window}, {nperseg}, {noverlap}' + assert check_NOLA(window, nperseg, noverlap), msg + assert not check_COLA(window, nperseg, noverlap), msg + + t = np.arange(N) + x = 10 * rng.randn(t.size) + + _, _, zz = stft(x, nperseg=nperseg, noverlap=noverlap, + window=window, detrend=None, padded=True, + boundary='zeros') + + tr, xr = istft(zz, nperseg=nperseg, noverlap=noverlap, + window=window, boundary=True) + + msg = f'{window}, {noverlap}' + assert_allclose(t, tr[:len(t)], err_msg=msg) + assert_allclose(x, xr[:len(x)], err_msg=msg) + + def test_roundtrip_float32(self): + rng = np.random.RandomState(1234) + + settings = [('hann', 1024, 256, 128)] + + for window, N, nperseg, noverlap in settings: + t = np.arange(N) + x = 10*rng.randn(t.size) + x = x.astype(np.float32) + + _, _, zz = stft(x, nperseg=nperseg, noverlap=noverlap, + window=window, detrend=None, padded=False) + + tr, xr = istft(zz, nperseg=nperseg, noverlap=noverlap, + window=window) + + msg = f'{window}, {noverlap}' + assert_allclose(t, t, err_msg=msg) + assert_allclose(x, xr, err_msg=msg, rtol=1e-4, atol=1e-5) + assert_(x.dtype == xr.dtype) + + @pytest.mark.parametrize('scaling', ['spectrum', 'psd']) + def test_roundtrip_complex(self, scaling): + rng = np.random.RandomState(1234) + + settings = [ + ('boxcar', 100, 10, 0), # Test no overlap + ('boxcar', 100, 10, 9), # Test high overlap + ('bartlett', 101, 51, 26), # Test odd nperseg + ('hann', 1024, 256, 128), # Test defaults + (('tukey', 0.5), 1152, 256, 64), # Test Tukey + ('hann', 1024, 256, 255), # Test overlapped hann + ] + + for window, N, nperseg, noverlap in settings: + t = np.arange(N) + x = 10*rng.randn(t.size) + 10j*rng.randn(t.size) + + _, _, zz = stft(x, nperseg=nperseg, noverlap=noverlap, + window=window, detrend=None, padded=False, + return_onesided=False, scaling=scaling) + + tr, xr = istft(zz, nperseg=nperseg, noverlap=noverlap, + window=window, input_onesided=False, + scaling=scaling) + + msg = f'{window}, {nperseg}, {noverlap}' + assert_allclose(t, tr, err_msg=msg) + assert_allclose(x, xr, err_msg=msg) + + # Check that asking for onesided switches to twosided + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "Input data is complex, switching to return_onesided=False", + UserWarning, + ) + _, _, zz = stft(x, nperseg=nperseg, noverlap=noverlap, + window=window, detrend=None, padded=False, + return_onesided=True, scaling=scaling) + + tr, xr = istft(zz, nperseg=nperseg, noverlap=noverlap, + window=window, input_onesided=False, scaling=scaling) + + msg = f'{window}, {nperseg}, {noverlap}' + assert_allclose(t, tr, err_msg=msg) + assert_allclose(x, xr, err_msg=msg) + + def test_roundtrip_boundary_extension(self): + rng = np.random.RandomState(1234) + + # Test against boxcar, since window is all ones, and thus can be fully + # recovered with no boundary extension + + settings = [ + ('boxcar', 100, 10, 0), # Test no overlap + ('boxcar', 100, 10, 9), # Test high overlap + ] + + for window, N, nperseg, noverlap in settings: + t = np.arange(N) + x = 10*rng.randn(t.size) + + _, _, zz = stft(x, nperseg=nperseg, noverlap=noverlap, + window=window, detrend=None, padded=True, + boundary=None) + + _, xr = istft(zz, noverlap=noverlap, window=window, boundary=False) + + for boundary in ['even', 'odd', 'constant', 'zeros']: + _, _, zz_ext = stft(x, nperseg=nperseg, noverlap=noverlap, + window=window, detrend=None, padded=True, + boundary=boundary) + + _, xr_ext = istft(zz_ext, noverlap=noverlap, window=window, + boundary=True) + + msg = f'{window}, {noverlap}, {boundary}' + assert_allclose(x, xr, err_msg=msg) + assert_allclose(x, xr_ext, err_msg=msg) + + def test_roundtrip_padded_signal(self): + rng = np.random.RandomState(1234) + + settings = [ + ('boxcar', 101, 10, 0), + ('hann', 1000, 256, 128), + ] + + for window, N, nperseg, noverlap in settings: + t = np.arange(N) + x = 10*rng.randn(t.size) + + _, _, zz = stft(x, nperseg=nperseg, noverlap=noverlap, + window=window, detrend=None, padded=True) + + tr, xr = istft(zz, noverlap=noverlap, window=window) + + msg = f'{window}, {noverlap}' + # Account for possible zero-padding at the end + assert_allclose(t, tr[:t.size], err_msg=msg) + assert_allclose(x, xr[:x.size], err_msg=msg) + + def test_roundtrip_padded_FFT(self): + rng = np.random.RandomState(1234) + + settings = [ + ('hann', 1024, 256, 128, 512), + ('hann', 1024, 256, 128, 501), + ('boxcar', 100, 10, 0, 33), + (('tukey', 0.5), 1152, 256, 64, 1024), + ] + + for window, N, nperseg, noverlap, nfft in settings: + t = np.arange(N) + x = 10*rng.randn(t.size) + xc = x*np.exp(1j*np.pi/4) + + # real signal + _, _, z = stft(x, nperseg=nperseg, noverlap=noverlap, nfft=nfft, + window=window, detrend=None, padded=True) + + # complex signal + _, _, zc = stft(xc, nperseg=nperseg, noverlap=noverlap, nfft=nfft, + window=window, detrend=None, padded=True, + return_onesided=False) + + tr, xr = istft(z, nperseg=nperseg, noverlap=noverlap, nfft=nfft, + window=window) + + tr, xcr = istft(zc, nperseg=nperseg, noverlap=noverlap, nfft=nfft, + window=window, input_onesided=False) + + msg = f'{window}, {noverlap}' + assert_allclose(t, tr, err_msg=msg) + assert_allclose(x, xr, err_msg=msg) + assert_allclose(xc, xcr, err_msg=msg) + + def test_axis_rolling(self): + rng = np.random.RandomState(1234) + + x_flat = rng.randn(1024) + _, _, z_flat = stft(x_flat) + + for a in range(3): + newshape = [1,]*3 + newshape[a] = -1 + x = x_flat.reshape(newshape) + + _, _, z_plus = stft(x, axis=a) # Positive axis index + _, _, z_minus = stft(x, axis=a-x.ndim) # Negative axis index + + assert_equal(z_flat, z_plus.squeeze(), err_msg=a) + assert_equal(z_flat, z_minus.squeeze(), err_msg=a-x.ndim) + + # z_flat has shape [n_freq, n_time] + + # Test vs. transpose + _, x_transpose_m = istft(z_flat.T, time_axis=-2, freq_axis=-1) + _, x_transpose_p = istft(z_flat.T, time_axis=0, freq_axis=1) + + assert_allclose(x_flat, x_transpose_m, err_msg='istft transpose minus') + assert_allclose(x_flat, x_transpose_p, err_msg='istft transpose plus') + + def test_roundtrip_scaling(self): + """Verify behavior of scaling parameter. """ + # Create 1024 sample cosine signal with amplitude 2: + X = np.zeros(513, dtype=complex) + X[256] = 1024 + x = np.fft.irfft(X) + power_x = sum(x**2) / len(x) # power of signal x is 2 + + # Calculate magnitude-scaled STFT: + Zs = stft(x, boundary='even', scaling='spectrum')[2] + + # Test round trip: + x1 = istft(Zs, boundary=True, scaling='spectrum')[1] + assert_allclose(x1, x) + + # For a Hann-windowed 256 sample length FFT, we expect a peak at + # frequency 64 (since it is 1/4 the length of X) with a height of 1 + # (half the amplitude). A Hann window of a perfectly centered sine has + # the magnitude [..., 0, 0, 0.5, 1, 0.5, 0, 0, ...]. + # Note that in this case the 'even' padding works for the beginning + # but not for the end of the STFT. + assert_allclose(abs(Zs[63, :-1]), 0.5) + assert_allclose(abs(Zs[64, :-1]), 1) + assert_allclose(abs(Zs[65, :-1]), 0.5) + # All other values should be zero: + Zs[63:66, :-1] = 0 + # Note since 'rtol' does not have influence here, atol needs to be set: + assert_allclose(Zs[:, :-1], 0, atol=np.finfo(Zs.dtype).resolution) + + # Calculate two-sided psd-scaled STFT: + # - using 'even' padding since signal is axis symmetric - this ensures + # stationary behavior on the boundaries + # - using the two-sided transform allows determining the spectral + # power by `sum(abs(Zp[:, k])**2) / len(f)` for the k-th time slot. + Zp = stft(x, return_onesided=False, boundary='even', scaling='psd')[2] + + # Calculate spectral power of Zd by summing over the frequency axis: + psd_Zp = np.sum(Zp.real**2 + Zp.imag**2, axis=0) / Zp.shape[0] + # Spectral power of Zp should be equal to the signal's power: + assert_allclose(psd_Zp, power_x) + + # Test round trip: + x1 = istft(Zp, input_onesided=False, boundary=True, scaling='psd')[1] + assert_allclose(x1, x) + + # The power of the one-sided psd-scaled STFT can be determined + # analogously (note that the two sides are not of equal shape): + Zp0 = stft(x, return_onesided=True, boundary='even', scaling='psd')[2] + + # Since x is real, its Fourier transform is conjugate symmetric, i.e., + # the missing 'second side' can be expressed through the 'first side': + Zp1 = np.conj(Zp0[-2:0:-1, :]) # 'second side' is conjugate reversed + assert_allclose(Zp[:129, :], Zp0) + assert_allclose(Zp[129:, :], Zp1) + + # Calculate the spectral power: + s2 = (np.sum(Zp0.real ** 2 + Zp0.imag ** 2, axis=0) + + np.sum(Zp1.real ** 2 + Zp1.imag ** 2, axis=0)) + psd_Zp01 = s2 / (Zp0.shape[0] + Zp1.shape[0]) + assert_allclose(psd_Zp01, power_x) + + # Test round trip: + x1 = istft(Zp0, input_onesided=True, boundary=True, scaling='psd')[1] + assert_allclose(x1, x) + + +class TestSampledSpectralRepresentations: + """Check energy/power relations from `Spectral Analysis` section in the user guide. + + A 32 sample cosine signal is used to compare the numerical to the expected results + stated in :ref:`tutorial_SpectralAnalysis` in + file ``doc/source/tutorial/signal.rst`` + """ + n: int = 32 #: number of samples + T: float = 1/16 #: sampling interval + a_ref: float = 3 #: amplitude of reference + l_a: int = 3 #: index in fft for defining frequency of test signal + + x_ref: np.ndarray #: reference signal + X_ref: np.ndarray #: two-sided FFT of x_ref + E_ref: float #: energy of signal + P_ref: float #: power of signal + + def setup_method(self): + """Create Cosine signal with amplitude a from spectrum. """ + f = rfftfreq(self.n, self.T) + X_ref = np.zeros_like(f) + self.l_a = 3 + X_ref[self.l_a] = self.a_ref/2 * self.n # set amplitude + self.x_ref = irfft(X_ref) + self.X_ref = fft(self.x_ref) + + # Closed form expression for continuous-time signal: + self.E_ref = self.tau * self.a_ref**2 / 2 # energy of signal + self.P_ref = self.a_ref**2 / 2 # power of signal + + @property + def tau(self) -> float: + """Duration of signal. """ + return self.n * self.T + + @property + def delta_f(self) -> float: + """Bin width """ + return 1 / (self.n * self.T) + + def test_reference_signal(self): + """Test energy and power formulas. """ + # Verify that amplitude is a: + assert_allclose(2*self.a_ref, np.ptp(self.x_ref), rtol=0.1) + # Verify that energy expression for sampled signal: + assert_allclose(self.T * sum(self.x_ref ** 2), self.E_ref) + + # Verify that spectral energy and power formulas are correct: + sum_X_ref_squared = sum(self.X_ref.real**2 + self.X_ref.imag**2) + assert_allclose(self.T/self.n * sum_X_ref_squared, self.E_ref) + assert_allclose(1/self.n**2 * sum_X_ref_squared, self.P_ref) + + def test_windowed_DFT(self): + """Verify spectral representations of windowed DFT. + + Furthermore, the scalings of `periodogram` and `welch` are verified. + """ + w = hann(self.n, sym=False) + c_amp, c_rms = abs(sum(w)), np.sqrt(sum(w.real**2 + w.imag**2)) + Xw = fft(self.x_ref*w) # unnormalized windowed DFT + + # Verify that the *spectrum* peak is consistent: + assert_allclose(self.tau * Xw[self.l_a] / c_amp, self.a_ref * self.tau / 2) + # Verify that the *amplitude spectrum* peak is consistent: + assert_allclose(Xw[self.l_a] / c_amp, self.a_ref/2) + + # Verify spectral power/energy equals signal's power/energy: + X_ESD = self.tau * self.T * abs(Xw / c_rms)**2 # Energy Spectral Density + X_PSD = self.T * abs(Xw / c_rms)**2 # Power Spectral Density + assert_allclose(self.delta_f * sum(X_ESD), self.E_ref) + assert_allclose(self.delta_f * sum(X_PSD), self.P_ref) + + # Verify scalings of periodogram: + kw = dict(fs=1/self.T, window=w, detrend=False, return_onesided=False) + _, P_mag = periodogram(self.x_ref, scaling='spectrum', **kw) + _, P_psd = periodogram(self.x_ref, scaling='density', **kw) + + # Verify that periodogram calculates a squared magnitude spectrum: + float_res = np.finfo(P_mag.dtype).resolution + assert_allclose(P_mag, abs(Xw/c_amp)**2, atol=float_res*max(P_mag)) + # Verify that periodogram calculates a PSD: + assert_allclose(P_psd, X_PSD, atol=float_res*max(P_psd)) + + # Ensure that scaling of welch is the same as of periodogram: + kw = dict(nperseg=len(self.x_ref), noverlap=0, **kw) + assert_allclose(welch(self.x_ref, scaling='spectrum', **kw)[1], P_mag, + atol=float_res*max(P_mag)) + assert_allclose(welch(self.x_ref, scaling='density', **kw)[1], P_psd, + atol=float_res*max(P_psd)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_splines.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_splines.py new file mode 100644 index 0000000000000000000000000000000000000000..42e352a952eaa174cd5c6d6312e4c330a2c5dd15 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_splines.py @@ -0,0 +1,422 @@ +# pylint: disable=missing-docstring +import math +import numpy as np +import pytest +from scipy._lib._array_api import is_cupy, xp_assert_close, xp_default_dtype, concat_1d + +from scipy.signal._spline import ( + symiirorder1_ic, symiirorder2_ic_fwd, symiirorder2_ic_bwd) +from scipy.signal import symiirorder1, symiirorder2 + +skip_xp_backends = pytest.mark.skip_xp_backends +xfail_xp_backends = pytest.mark.xfail_xp_backends + + +def _compute_symiirorder2_bwd_hs(k, cs, rsq, omega): + cssq = cs * cs + k = np.abs(k) + rsupk = np.power(rsq, k / 2.0) + + c0 = (cssq * (1.0 + rsq) / (1.0 - rsq) / + (1 - 2 * rsq * np.cos(2 * omega) + rsq * rsq)) + gamma = (1.0 - rsq) / (1.0 + rsq) / np.tan(omega) + return c0 * rsupk * (np.cos(omega * k) + gamma * np.sin(omega * k)) + + +class TestSymIIR: + + @skip_xp_backends(np_only=True, reason="_ic functions are private and numpy-only") + @pytest.mark.parametrize( + 'dtype', ['float32', 'float64', 'complex64', 'complex128']) + @pytest.mark.parametrize('precision', [-1.0, 0.7, 0.5, 0.25, 0.0075]) + def test_symiir1_ic(self, dtype, precision, xp): + + dtype = getattr(xp, dtype) + + c_precision = precision + if precision <= 0.0 or precision > 1.0: + if dtype in {xp.float32, xp.complex64}: + c_precision = 1e-6 + else: + c_precision = 1e-11 + + # Symmetrical initial conditions for a IIR filter of order 1 are: + # x[0] + z1 * \sum{k = 0}^{n - 1} x[k] * z1^k + + # Check the initial condition for a low-pass filter + # with coefficient b = 0.85 on a step signal. The initial condition is + # a geometric series: 1 + b * \sum_{k = 0}^{n - 1} u[k] b^k. + + # Finding the initial condition corresponds to + # 1. Computing the index n such that b**n < precision, which + # corresponds to ceil(log(precision) / log(b)) + # 2. Computing the geometric series until n, this can be computed + # using the partial sum formula: (1 - b**n) / (1 - b) + # This holds due to the input being a step signal. + b = 0.85 + n_exp = int(math.ceil(math.log(c_precision) / math.log(b))) + expected = xp.asarray([[(1 - b ** n_exp) / (1 - b)]], dtype=dtype) + expected = 1 + b * expected + + # Create a step signal of size n + 1 + x = xp.ones(n_exp + 1, dtype=dtype) + xp_assert_close(symiirorder1_ic(x, b, precision), expected, + atol=2e-6, rtol=2e-7) + + # Check the conditions for an exponential decreasing signal with base 2. + # Same conditions hold, as the product of 0.5^n * 0.85^n is + # still a geometric series + b_d = xp.asarray(b, dtype=dtype) + expected = np.asarray( + [[(1 - (0.5 * b_d) ** n_exp) / (1 - (0.5 * b_d))]], dtype=dtype) + expected = 1 + b_d * expected + + # Create an exponential decreasing signal of size n + 1 + x = 2 ** -xp.arange(n_exp + 1, dtype=dtype) + xp_assert_close(symiirorder1_ic(x, b, precision), expected, + atol=2e-6, rtol=2e-7) + + @skip_xp_backends(np_only=True, reason="_ic functions are private and numpy-only") + def test_symiir1_ic_fails(self, xp): + # Test that symiirorder1_ic fails whenever \sum_{n = 1}^{n} b^n > eps + b = 0.85 + # Create a step signal of size 100 + x = xp.ones(100, dtype=xp.float64) + + # Compute the closed form for the geometrical series + precision = 1 / (1 - b) + pytest.raises(ValueError, symiirorder1_ic, x, b, precision) + + # Test that symiirorder1_ic fails when |z1| >= 1 + pytest.raises(ValueError, symiirorder1_ic, x, 1.0, -1) + pytest.raises(ValueError, symiirorder1_ic, x, 2.0, -1) + + @skip_xp_backends( + cpu_only=True, exceptions=["cupy"], reason="internals are numpy-only" + ) + @xfail_xp_backends("cupy", reason="sum did not converge") + @skip_xp_backends("jax.numpy", reason="item assignment in tests") + @pytest.mark.parametrize( + 'dtype', ['float32', 'float64', 'complex64', 'complex128']) + @pytest.mark.parametrize('precision', [-1.0, 0.7, 0.5, 0.25, 0.0075]) + def test_symiir1(self, dtype, precision, xp): + dtype = getattr(xp, dtype) + + c_precision = precision + if precision <= 0.0 or precision > 1.0: + if dtype in {xp.float32, xp.complex64}: + c_precision = 1e-6 + else: + c_precision = 1e-11 + + # Test for a low-pass filter with c0 = 0.15 and z1 = 0.85 + # using an unit step over 200 samples. + c0 = 0.15 + z1 = 0.85 + n = 200 + signal = xp.ones(n, dtype=dtype) + + # Find the initial condition. See test_symiir1_ic for a detailed + # explanation + n_exp = int(math.ceil(math.log(c_precision) / math.log(z1))) + initial = xp.asarray((1 - z1 ** n_exp) / (1 - z1), dtype=dtype) + initial = 1 + z1 * initial + + # Forward pass + # The transfer function for the system 1 / (1 - z1 * z^-1) when + # applied to an unit step with initial conditions y0 is + # 1 / (1 - z1 * z^-1) * (z^-1 / (1 - z^-1) + y0) + + # Solving the inverse Z-transform for the given expression yields: + # y[n] = y0 * z1**n * u[n] + + # -z1 / (1 - z1) * z1**(k - 1) * u[k - 1] + + # 1 / (1 - z1) * u[k - 1] + # d is the Kronecker delta function, and u is the unit step + + # y0 * z1**n * u[n] + pos = xp.astype(xp.arange(n), dtype) + comp1 = initial * z1**pos + + # -z1 / (1 - z1) * z1**(k - 1) * u[k - 1] + comp2 = xp.zeros(n, dtype=dtype) + comp2[1:] = -z1 / (1 - z1) * z1**pos[:-1] + + # 1 / (1 - z1) * u[k - 1] + comp3 = xp.zeros(n, dtype=dtype) + comp3[1:] = 1 / (1 - z1) + + expected_fwd = comp1 + comp2 + comp3 + + # Reverse condition + sym_cond = -c0 / (z1 - 1.0) * expected_fwd[-1] + + # Backward pass + # The transfer function for the forward result is equivalent to + # the forward system times c0 / (1 - z1 * z). + + # Computing a closed form for the complete expression is difficult + # The result will be computed iteratively from the difference equation + exp_out = xp.zeros(n, dtype=dtype) + exp_out[0] = sym_cond + + for i in range(1, n): + exp_out[i] = c0 * expected_fwd[n - 1 - i] + z1 * exp_out[i - 1] + + exp_out = xp.flip(exp_out) + + out = symiirorder1(signal, c0, z1, precision) + xp_assert_close(out, exp_out, atol=4e-6, rtol=6e-7) + + @xfail_xp_backends("cupy", reason="sum did not converge") + @skip_xp_backends( + cpu_only=True, exceptions=["cupy"], reason="internals are numpy-only" + ) + @pytest.mark.parametrize('dtype', ['float32', 'float64']) + def test_symiir1_values(self, dtype, xp): + rng = np.random.RandomState(1234) + s = rng.uniform(size=16).astype(dtype) + dtype = getattr(xp, dtype) + s = xp.asarray(s) + res = symiirorder1(s, 0.5, 0.1) + + # values from scipy 1.9.1 + exp_res = xp.asarray([ + 0.14387447, 0.35166047, 0.29735238, 0.46295986, 0.45174927, + 0.19982875, 0.20355805, 0.47378628, 0.57232247, 0.51597393, + 0.25935107, 0.31438554, 0.41096728, 0.4190693 , 0.25812255, + 0.33671467], dtype=res.dtype) + atol = {xp.float64: 1e-15, xp.float32: 1e-7}[dtype] + xp_assert_close(res, exp_res, atol=atol) + + I1 = xp.asarray( + 1 + 1j, dtype=xp.result_type(s, xp.complex64) + ) + s = s * I1 + res = symiirorder1(s, 0.5, 0.1) + assert res.dtype == xp.complex64 if dtype == xp.float32 else xp.complex128 + xp_assert_close(res, I1 * exp_res, atol=atol) + + @skip_xp_backends(np_only=True, + reason="_initial_fwd functions are private and numpy-only") + @pytest.mark.parametrize( + 'dtype', ['float32', 'float64']) + @pytest.mark.parametrize('precision', [-1.0, 0.7, 0.5, 0.25, 0.0075]) + def test_symiir2_initial_fwd(self, dtype, precision, xp): + dtype = getattr(xp, dtype) + c_precision = precision + if precision <= 0.0 or precision > 1.0: + if dtype in {xp.float32, xp.complex64}: + c_precision = 1e-6 + else: + c_precision = 1e-11 + + # Compute the initial conditions for a order-two symmetrical low-pass + # filter with r = 0.5 and omega = pi / 3 for an unit step input. + r = xp.asarray(0.5, dtype=dtype) + omega = xp.asarray(np.pi / 3.0, dtype=dtype) + cs = 1 - 2 * r * xp.cos(omega) + r**2 + + # The index n for the initial condition is bound from 0 to the + # first position where sin(omega * (n + 2)) = 0 => omega * (n + 2) = pi + # For omega = pi / 3, the maximum initial condition occurs when + # sqrt(3) / 2 * r**n < precision. + # => n = log(2 * sqrt(3) / 3 * precision) / log(r) + ub = xp.ceil(xp.log(c_precision / xp.sin(omega)) / math.log(c_precision)) + lb = xp.ceil(math.pi / omega) - 2 + n_exp = min(ub, lb) + + # The forward initial condition for a filter of order two is: + # \frac{cs}{\sin(\omega)} \sum_{n = 0}^{N - 1} { + # r^(n + 1) \sin{\omega(n + 2)}} + cs + # The closed expression for this sum is: + # s[n] = 2 * r * np.cos(omega) - + # r**2 - r**(n + 2) * np.sin(omega * (n + 3)) / np.sin(omega) + + # r**(n + 3) * np.sin(omega * (n + 2)) / np.sin(omega) + cs + fwd_initial_1 = ( + cs + + 2 * r * xp.cos(omega) - + r**2 - + r**(n_exp + 2) * xp.sin(omega * (n_exp + 3)) / xp.sin(omega) + + r**(n_exp + 3) * xp.sin(omega * (n_exp + 2)) / xp.sin(omega)) + + # The second initial condition is given by + # s[n] = 1 / np.sin(omega) * ( + # r**2 * np.sin(3 * omega) - + # r**3 * np.sin(2 * omega) - + # r**(n + 3) * np.sin(omega * (n + 4)) + + # r**(n + 4) * np.sin(omega * (n + 3))) + ub = xp.ceil(xp.log(c_precision / xp.sin(omega)) / math.log(c_precision)) + lb = xp.ceil(xp.pi / omega) - 3 + n_exp = min(ub, lb) + + fwd_initial_2 = ( + cs + cs * 2 * r * xp.cos(omega) + + (r**2 * xp.sin(3 * omega) - + r**3 * xp.sin(2 * omega) - + r**(n_exp + 3) * xp.sin(omega * (n_exp + 4)) + + r**(n_exp + 4) * xp.sin(omega * (n_exp + 3))) / xp.sin(omega)) + + expected = concat_1d(xp, fwd_initial_1, fwd_initial_2)[None, :] + expected = xp.astype(expected, dtype) + + n = 100 + signal = np.ones(n, dtype=dtype) + + out = symiirorder2_ic_fwd(signal, r, omega, precision) + xp_assert_close(out, expected, atol=4e-6, rtol=6e-7) + + @skip_xp_backends(np_only=True, + reason="_initial_bwd functions are private and numpy-only") + @pytest.mark.parametrize( + 'dtype', ['float32', 'float64']) + @pytest.mark.parametrize('precision', [-1.0, 0.7, 0.5, 0.25, 0.0075]) + def test_symiir2_initial_bwd(self, dtype, precision, xp): + dtype = getattr(xp, dtype) + + c_precision = precision + if precision <= 0.0 or precision > 1.0: + if dtype in {xp.float32, xp.complex64}: + c_precision = 1e-6 + else: + c_precision = 1e-11 + + r = xp.asarray(0.5, dtype=dtype) + omega = xp.asarray(xp.pi / 3.0, dtype=dtype) + cs = 1 - 2 * r * xp.cos(omega) + r * r + a2 = 2 * r * xp.cos(omega) + a3 = -r * r + + n = 100 + signal = xp.ones(n, dtype=dtype) + + # Compute initial forward conditions + ic = symiirorder2_ic_fwd(signal, r, omega, precision) + out = xp.zeros(n + 2, dtype=dtype) + out[:2] = ic[0] + + # Apply the forward system cs / (1 - a2 * z^-1 - a3 * z^-2)) + for i in range(2, n + 2): + out[i] = cs * signal[i - 2] + a2 * out[i - 1] + a3 * out[i - 2] + + # Find the backward initial conditions + ic2 = xp.zeros(2, dtype=dtype) + idx = xp.arange(n) + + diff = (_compute_symiirorder2_bwd_hs(idx, cs, r * r, omega) + + _compute_symiirorder2_bwd_hs(idx + 1, cs, r * r, omega)) + ic2_0_all = np.cumsum(diff * out[:1:-1]) + pos = xp.nonzero(diff ** 2 < c_precision)[0] + ic2[0] = ic2_0_all[pos[0]] + + diff = (_compute_symiirorder2_bwd_hs(idx - 1, cs, r * r, omega) + + _compute_symiirorder2_bwd_hs(idx + 2, cs, r * r, omega)) + + ic2_1_all = xp.cumulative_sum(diff * out[:1:-1]) + pos = xp.nonzero(diff ** 2 < c_precision)[0] + ic2[1] = ic2_1_all[pos[0]] + + out_ic = symiirorder2_ic_bwd(out, r, omega, precision)[0] + xp_assert_close(out_ic, ic2, atol=4e-6, rtol=6e-7) + + @skip_xp_backends(cpu_only=True, reason="internals are numpy-only") + @skip_xp_backends("jax.numpy", reason="item assignment in tests") + @pytest.mark.parametrize( + 'dtype', ['float32', 'float64']) + @pytest.mark.parametrize('precision', [-1.0, 0.7, 0.5, 0.25, 0.0075]) + def test_symiir2(self, dtype, precision, xp): + dtype = getattr(xp, dtype) + + r = 0.5 + omega = math.pi / 3.0 + cs = 1 - 2 * r * math.cos(omega) + r * r + a2 = 2 * r * math.cos(omega) + a3 = -r * r + + n = 100 + signal = xp.ones(n, dtype=dtype) + + # Compute initial forward conditions + signal_np = np.asarray(signal) + ic = symiirorder2_ic_fwd(signal_np, r, omega, precision) + ic = xp.asarray(ic) + out1 = xp.zeros(n + 2, dtype=dtype) + out1[:2] = ic[0, :] + + # Apply the forward system cs / (1 - a2 * z^-1 - a3 * z^-2)) + for i in range(2, n + 2): + out1[i] = cs * signal[i - 2] + a2 * out1[i - 1] + a3 * out1[i - 2] + + # Find the backward initial conditions + ic2 = symiirorder2_ic_bwd(np.asarray(out1), r, omega, precision)[0] + ic2 = xp.asarray(ic2) + + # Apply the system cs / (1 - a2 * z - a3 * z^2)) in backwards + exp = xp.empty(n, dtype=dtype) + + exp[-2:] = xp.flip(ic2) + + for i in range(n - 3, -1, -1): + exp[i] = cs * out1[i] + a2 * exp[i + 1] + a3 * exp[i + 2] + + out = symiirorder2(signal, r, omega, precision) + xp_assert_close(out, exp, atol=4e-6, rtol=6e-7) + + @skip_xp_backends(cpu_only=True, exceptions=["cupy"], reason="C internals") + @pytest.mark.parametrize('dtyp', ['float32', 'float64']) + def test_symiir2_values(self, dtyp, xp): + rng = np.random.RandomState(1234) + s = rng.uniform(size=16).astype(dtyp) + s = xp.asarray(s) + + # cupy returns f64 for f32 inputs + dtype = xp.float64 if is_cupy(xp) else getattr(xp, dtyp) + + res = symiirorder2(s, 0.1, 0.1, precision=1e-10) + + # values from scipy 1.9.1 + exp_res = xp.asarray( + [0.26572609, 0.53408018, 0.51032696, 0.72115829, 0.69486885, + 0.3649055 , 0.37349478, 0.74165032, 0.89718521, 0.80582483, + 0.46758053, 0.51898709, 0.65025605, 0.65394321, 0.45273595, + 0.53539183], dtype=dtype + ) + + # The values in SciPy 1.14 agree with those in SciPy 1.9.1 to this + # accuracy only. Implementation differences are twofold: + # 1. boundary conditions are computed differently + # 2. the filter itself uses sosfilt instead of a hardcoded iteration + # The boundary conditions seem are tested separately (see + # test_symiir2_initial_{fwd,bwd} above, so the difference is likely + # due to a different way roundoff errors accumulate in the filter. + # In that respect, sosfilt is likely doing a better job. + xp_assert_close(res, exp_res, atol=2e-6) + + I1 = xp.asarray(1 + 1j, dtype=xp.result_type(s, xp.complex64)) + s = s * I1 + + with pytest.raises((TypeError, ValueError)): + res = symiirorder2(s, 0.5, 0.1) + + @skip_xp_backends(cpu_only=True, exceptions=["cupy"], reason="C internals") + @xfail_xp_backends("cupy", reason="cupy does not accept integer arrays") + def test_symiir1_integer_input(self, xp): + s = xp.where( + xp.astype(xp.arange(100) % 2, xp.bool), + xp.asarray(-1), + xp.asarray(1), + ) + expected = symiirorder1(xp.astype(s, xp_default_dtype(xp)), 0.5, 0.5) + out = symiirorder1(s, 0.5, 0.5) + xp_assert_close(out, expected) + + @skip_xp_backends(cpu_only=True, exceptions=["cupy"], reason="C internals") + @xfail_xp_backends("cupy", reason="cupy does not accept integer arrays") + def test_symiir2_integer_input(self, xp): + s = xp.where( + xp.astype(xp.arange(100) % 2, xp.bool), + xp.asarray(-1), + xp.asarray(1), + ) + expected = symiirorder2(xp.astype(s, xp_default_dtype(xp)), 0.5, xp.pi / 3.0) + out = symiirorder2(s, 0.5, xp.pi / 3.0) + xp_assert_close(out, expected) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_upfirdn.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_upfirdn.py new file mode 100644 index 0000000000000000000000000000000000000000..8c96232478d7f56f16af36d0b7569a17476bd9a7 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_upfirdn.py @@ -0,0 +1,335 @@ +# Code adapted from "upfirdn" python library with permission: +# +# Copyright (c) 2009, Motorola, Inc +# +# All Rights Reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Motorola nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +import numpy as np +from itertools import product + +from pytest import raises as assert_raises +import pytest + +from scipy._lib import array_api_extra as xpx +from scipy._lib._array_api import ( + xp_assert_close, array_namespace, _xp_copy_to_numpy, is_cupy, + make_xp_test_case +) +from scipy._lib.array_api_compat import numpy as np_compat +from scipy.signal import upfirdn, firwin +from scipy.signal._upfirdn import _output_len, _upfirdn_modes +from scipy.signal._upfirdn_apply import _pad_test + +skip_xp_backends = pytest.mark.skip_xp_backends + + + +def upfirdn_naive(x, h, up=1, down=1): + """Naive upfirdn processing in Python. + + Note: arg order (x, h) differs to facilitate apply_along_axis use. + """ + x = np.asarray(x) + h = np.asarray(h) + out = np.zeros(len(x) * up, x.dtype) + out[::up] = x + out = np.convolve(h, out)[::down][:_output_len(len(h), len(x), up, down)] + return out + + +class UpFIRDnCase: + """Test _UpFIRDn object""" + def __init__(self, up, down, h, x_dtype, *, xp=None): + if xp is None: + xp = np_compat + self.up = up + self.down = down + self.h = np.atleast_1d(h) + self.x_dtype = x_dtype + self.rng = np.random.RandomState(17) + self.xp = xp + + def __call__(self): + # tiny signal + self.scrub(np.ones(1, self.x_dtype)) + # ones + self.scrub(np.ones(10, self.x_dtype)) # ones + # randn + x = self.rng.randn(10).astype(self.x_dtype) + if self.x_dtype in (np.complex64, np.complex128): + x += 1j * self.rng.randn(10) + self.scrub(x) + # ramp + self.scrub(np.arange(10).astype(self.x_dtype)) + # 3D, random + if is_cupy(self.xp): + # ndim > 2 is unsupported in CuPy. + return + size = (2, 3, 5) + x = self.rng.randn(*size).astype(self.x_dtype) + if self.x_dtype in (np.complex64, np.complex128): + x += 1j * self.rng.randn(*size) + for axis in range(len(size)): + self.scrub(x, axis=axis) + x = x[:, ::2, 1::3].T + for axis in range(len(size)): + self.scrub(x, axis=axis) + + def scrub(self, x, axis=-1): + xp = self.xp + yr = np.apply_along_axis(upfirdn_naive, axis, x, + self.h, self.up, self.down) + want_len = _output_len(len(self.h), x.shape[axis], self.up, self.down) + assert yr.shape[axis] == want_len + y = upfirdn(xp.asarray(self.h), xp.asarray(x), self.up, self.down, + axis=axis) + assert y.shape[axis] == want_len + assert y.shape == yr.shape + dtypes = (self.h.dtype, x.dtype) + if all(d == np.complex64 for d in dtypes): + assert y.dtype == xp.complex64 + elif np.complex64 in dtypes and np.float32 in dtypes: + assert y.dtype == xp.complex64 + elif all(d == np.float32 for d in dtypes): + assert y.dtype == xp.float32 + elif np.complex128 in dtypes or np.complex64 in dtypes: + assert y.dtype == xp.complex128 + else: + assert y.dtype == xp.float64 + yr = xp.asarray(yr, dtype=y.dtype) + xp_assert_close(yr, y) + + +_UPFIRDN_TYPES = ("int64", "float32", "complex64", "float64", "complex128") + + +@make_xp_test_case(upfirdn) +class TestUpfirdn: + + @skip_xp_backends(np_only=True, reason="enough to only test on numpy") + def test_valid_input(self, xp): + assert_raises(ValueError, upfirdn, [1], [1], 1, 0) # up or down < 1 + assert_raises(ValueError, upfirdn, [], [1], 1, 1) # h.ndim != 1 + assert_raises(ValueError, upfirdn, [[1]], [1], 1, 1) + + @pytest.mark.parametrize('len_h', [1, 2, 3, 4, 5]) + @pytest.mark.parametrize('len_x', [1, 2, 3, 4, 5]) + def test_singleton(self, len_h, len_x, xp): + # gh-9844: lengths producing expected outputs + h = xp.zeros(len_h) + h = xpx.at(h)[len_h // 2].set(1.) # make h a delta + x = xp.ones(len_x) + y = upfirdn(h, x, 1, 1) + want = xpx.pad(x, (len_h // 2, (len_h - 1) // 2), 'constant', xp=xp) + xp_assert_close(y, want) + + def test_shift_x(self, xp): + # gh-9844: shifted x can change values? + y = upfirdn(xp.asarray([1, 1]), xp.asarray([1.]), 1, 1) + xp_assert_close( + y, xp.asarray([1.0, 1.0], dtype=xp.float64) # was [0, 1] in the issue + ) + y = upfirdn(xp.asarray([1, 1]), xp.asarray([0., 1.]), 1, 1) + xp_assert_close(y, xp.asarray([0.0, 1.0, 1.0], dtype=xp.float64)) + + # A bunch of lengths/factors chosen because they exposed differences + # between the "old way" and new way of computing length, and then + # got `expected` from MATLAB + @pytest.mark.parametrize('len_h, len_x, up, down, expected', [ + (2, 2, 5, 2, [1, 0, 0, 0]), + (2, 3, 6, 3, [1, 0, 1, 0, 1]), + (2, 4, 4, 3, [1, 0, 0, 0, 1]), + (3, 2, 6, 2, [1, 0, 0, 1, 0]), + (4, 11, 3, 5, [1, 0, 0, 1, 0, 0, 1]), + ]) + def test_length_factors(self, len_h, len_x, up, down, expected, xp): + # gh-9844: weird factors + h = xp.zeros(len_h) + h = xpx.at(h)[0].set(1.) + x = xp.ones(len_x, dtype=xp.float64) + y = upfirdn(h, x, up, down) + expected = xp.asarray(expected, dtype=xp.float64) + xp_assert_close(y, expected) + + @pytest.mark.parametrize( + 'dtype', ["int64", "float32", "complex64", "float64", "complex128"] + ) + @pytest.mark.parametrize('down, want_len', [ # lengths from MATLAB + (2, 5015), + (11, 912), + (79, 127), + ]) + def test_vs_convolve(self, down, want_len, dtype, xp): + # Check that up=1.0 gives same answer as convolve + slicing + random_state = np.random.RandomState(17) + size = 10000 + + np_dtype = getattr(np, dtype) + x = random_state.randn(size).astype(np_dtype) + if np_dtype in (np.complex64, np.complex128): + x += 1j * random_state.randn(size) + + dtype = getattr(xp, dtype) + x = xp.asarray(x, dtype=dtype) + + h = xp.asarray(firwin(31, 1. / down, window='hamming')) + yl = xp.asarray( + upfirdn_naive(_xp_copy_to_numpy(x), _xp_copy_to_numpy(h), 1, down) + ) + y = upfirdn(h, x, up=1, down=down) + assert y.shape == (want_len,) + assert yl.shape[0] == y.shape[0] + xp_assert_close(yl, y, atol=1e-7, rtol=1e-7) + + @pytest.mark.parametrize('x_dtype', _UPFIRDN_TYPES) + @pytest.mark.parametrize('h', (1., 1j)) + @pytest.mark.parametrize('up, down', [(1, 1), (2, 2), (3, 2), (2, 3)]) + def test_vs_naive_delta(self, x_dtype, h, up, down, xp): + UpFIRDnCase(up, down, h, x_dtype, xp=xp)() + + @pytest.mark.parametrize('x_dtype', _UPFIRDN_TYPES) + @pytest.mark.parametrize('h_dtype', _UPFIRDN_TYPES) + @pytest.mark.parametrize('p_max, q_max', + list(product((10, 100), (10, 100)))) + def test_vs_naive(self, x_dtype, h_dtype, p_max, q_max, xp): + tests = self._random_factors(p_max, q_max, h_dtype, x_dtype, xp=xp) + for test in tests: + test() + + def _random_factors(self, p_max, q_max, h_dtype, x_dtype, *, xp): + n_rep = 3 + longest_h = 25 + random_state = np.random.RandomState(17) + tests = [] + + for _ in range(n_rep): + # Randomize the up/down factors somewhat + p_add = q_max if p_max > q_max else 1 + q_add = p_max if q_max > p_max else 1 + p = random_state.randint(p_max) + p_add + q = random_state.randint(q_max) + q_add + + # Generate random FIR coefficients + len_h = random_state.randint(longest_h) + 1 + h = np.atleast_1d(random_state.randint(len_h)) + h = h.astype(h_dtype) + if h_dtype is complex: + h += 1j * random_state.randint(len_h) + + tests.append(UpFIRDnCase(p, q, h, x_dtype, xp=xp)) + + return tests + + @pytest.mark.parametrize('mode', _upfirdn_modes) + def test_extensions(self, mode, xp): + """Test vs. manually computed results for modes not in numpy's pad.""" + x = np.asarray([1, 2, 3, 1], dtype=np.float64) + npre, npost = 6, 6 + y = _pad_test(x, npre=npre, npost=npost, mode=mode) + + x = xp.asarray(x) + y = xp.asarray(y) + if mode == 'antisymmetric': + y_expected = xp.asarray( + [3.0, 1, -1, -3, -2, -1, 1, 2, 3, 1, -1, -3, -2, -1, 1, 2]) + elif mode == 'antireflect': + y_expected = xp.asarray( + [1.0, 2, 3, 1, -1, 0, 1, 2, 3, 1, -1, 0, 1, 2, 3, 1]) + elif mode == 'smooth': + y_expected = xp.asarray( + [-5.0, -4, -3, -2, -1, 0, 1, 2, 3, 1, -1, -3, -5, -7, -9, -11]) + elif mode == "line": + lin_slope = (x[-1] - x[0]) / (x.shape[0] - 1) + left = x[0] + xp.arange(-npre, 0, 1, dtype=xp.float64) * lin_slope + right = x[-1] + xp.arange(1, npost + 1, dtype=xp.float64) * lin_slope + concat = array_namespace(left).concat + y_expected = concat((left, x, right)) + else: + y_expected = np.pad(_xp_copy_to_numpy(x), (npre, npost), mode=mode) + y_expected = xp.asarray(y_expected) + + y_expected = xp.asarray(y_expected, dtype=xp.float64) + xp_assert_close(y, y_expected) + + @pytest.mark.parametrize( + 'size, h_len, mode, dtype', + product( + [8], + [4, 5, 26], # include cases with h_len > 2*size + _upfirdn_modes, + ["float32", "float64", "complex64", "complex128"], + ) + ) + def test_modes(self, size, h_len, mode, dtype, xp): + if is_cupy(xp) and mode != "constant": + pytest.skip(reason="only mode='constant' supported by CuPy") + dtype_np = getattr(np, dtype) + dtype_xp = getattr(xp, dtype) + + random_state = np.random.RandomState(5) + x = random_state.randn(size).astype(dtype_np) + if dtype in ("complex64", "complex128"): + x += 1j * random_state.randn(size) + h = np.arange(1, 1 + h_len, dtype=x.real.dtype) + + x = xp.asarray(x, dtype=dtype_xp) + h = xp.asarray(h) + + y = upfirdn(h, x, up=1, down=1, mode=mode) + # expected result: pad the input, filter with zero padding, then crop + npad = h_len - 1 + if mode in ['antisymmetric', 'antireflect', 'smooth', 'line']: + # use _pad_test test function for modes not supported by np.pad. + xpad = _pad_test(_xp_copy_to_numpy(x), npre=npad, npost=npad, mode=mode) + else: + xpad = np.pad(_xp_copy_to_numpy(x), npad, mode=mode) + + xpad = xp.asarray(xpad) + ypad = upfirdn(h, xpad, up=1, down=1, mode='constant') + y_expected = ypad[npad:-npad] + + atol = rtol = xp.finfo(dtype_xp).eps * 1e2 + xp_assert_close(y, y_expected, atol=atol, rtol=rtol) + + +@make_xp_test_case(upfirdn) +def test_output_len_long_input(xp): + # Regression test for gh-17375. On Windows, a large enough input + # that should have been well within the capabilities of 64 bit integers + # would result in a 32 bit overflow because of a bug in Cython 0.29.32. + len_h = 1001 + in_len = 10**8 + up = 320 + down = 441 + out_len = _output_len(len_h, in_len, up, down) + # The expected value was computed "by hand" from the formula + # (((in_len - 1) * up + len_h) - 1) // down + 1 + assert out_len == 72562360 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_waveforms.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_waveforms.py new file mode 100644 index 0000000000000000000000000000000000000000..8cf181f55bfd055c21c937529ec1f42fb741d978 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_waveforms.py @@ -0,0 +1,400 @@ +import numpy as np +from pytest import raises as assert_raises +from scipy._lib._array_api import ( + assert_almost_equal, xp_assert_equal, xp_assert_close +) + +import scipy.signal._waveforms as waveforms + + +# These chirp_* functions are the instantaneous frequencies of the signals +# returned by chirp(). + +def chirp_linear(t, f0, f1, t1): + f = f0 + (f1 - f0) * t / t1 + return f + + +def chirp_quadratic(t, f0, f1, t1, vertex_zero=True): + if vertex_zero: + f = f0 + (f1 - f0) * t**2 / t1**2 + else: + f = f1 - (f1 - f0) * (t1 - t)**2 / t1**2 + return f + + +def chirp_geometric(t, f0, f1, t1): + f = f0 * (f1/f0)**(t/t1) + return f + + +def chirp_hyperbolic(t, f0, f1, t1): + f = f0*f1*t1 / ((f0 - f1)*t + f1*t1) + return f + + +def compute_frequency(t, theta): + """ + Compute theta'(t)/(2*pi), where theta'(t) is the derivative of theta(t). + """ + # Assume theta and t are 1-D NumPy arrays. + # Assume that t is uniformly spaced. + dt = t[1] - t[0] + f = np.diff(theta)/(2*np.pi) / dt + tf = 0.5*(t[1:] + t[:-1]) + return tf, f + + +class TestChirp: + + def test_linear_at_zero(self): + w = waveforms.chirp(t=0, f0=1.0, f1=2.0, t1=1.0, method='linear') + assert_almost_equal(w, 1.0) + + def test_linear_freq_01(self): + method = 'linear' + f0 = 1.0 + f1 = 2.0 + t1 = 1.0 + t = np.linspace(0, t1, 100) + phase = waveforms._chirp_phase(t, f0, t1, f1, method) + tf, f = compute_frequency(t, phase) + abserr = np.max(np.abs(f - chirp_linear(tf, f0, f1, t1))) + assert abserr < 1e-6 + + def test_linear_freq_02(self): + method = 'linear' + f0 = 200.0 + f1 = 100.0 + t1 = 10.0 + t = np.linspace(0, t1, 100) + phase = waveforms._chirp_phase(t, f0, t1, f1, method) + tf, f = compute_frequency(t, phase) + abserr = np.max(np.abs(f - chirp_linear(tf, f0, f1, t1))) + assert abserr < 1e-6 + + def test_linear_complex_power(self): + method = 'linear' + f0 = 1.0 + f1 = 2.0 + t1 = 1.0 + t = np.linspace(0, t1, 100) + w_real = waveforms.chirp(t, f0, t1, f1, method, complex=False) + w_complex = waveforms.chirp(t, f0, t1, f1, method, complex=True) + w_pwr_r = np.var(w_real) + w_pwr_c = np.var(w_complex) + + # Making sure that power of the real part is not affected with + # complex conversion operation + err = w_pwr_r - np.real(w_pwr_c) + + assert(err < 1e-6) + + def test_linear_complex_at_zero(self): + w = waveforms.chirp(t=0, f0=-10.0, f1=1.0, t1=1.0, method='linear', + complex=True) + xp_assert_close(w, 1.0+0.0j) # dtype must match + + def test_quadratic_at_zero(self): + w = waveforms.chirp(t=0, f0=1.0, f1=2.0, t1=1.0, method='quadratic') + assert_almost_equal(w, 1.0) + + def test_quadratic_at_zero2(self): + w = waveforms.chirp(t=0, f0=1.0, f1=2.0, t1=1.0, method='quadratic', + vertex_zero=False) + assert_almost_equal(w, 1.0) + + def test_quadratic_complex_at_zero(self): + w = waveforms.chirp(t=0, f0=-1.0, f1=2.0, t1=1.0, method='quadratic', + complex=True) + xp_assert_close(w, 1.0+0j) + + def test_quadratic_freq_01(self): + method = 'quadratic' + f0 = 1.0 + f1 = 2.0 + t1 = 1.0 + t = np.linspace(0, t1, 2000) + phase = waveforms._chirp_phase(t, f0, t1, f1, method) + tf, f = compute_frequency(t, phase) + abserr = np.max(np.abs(f - chirp_quadratic(tf, f0, f1, t1))) + assert abserr < 1e-6 + + def test_quadratic_freq_02(self): + method = 'quadratic' + f0 = 20.0 + f1 = 10.0 + t1 = 10.0 + t = np.linspace(0, t1, 2000) + phase = waveforms._chirp_phase(t, f0, t1, f1, method) + tf, f = compute_frequency(t, phase) + abserr = np.max(np.abs(f - chirp_quadratic(tf, f0, f1, t1))) + assert abserr < 1e-6 + + def test_logarithmic_at_zero(self): + w = waveforms.chirp(t=0, f0=1.0, f1=2.0, t1=1.0, method='logarithmic') + assert_almost_equal(w, 1.0) + + def test_logarithmic_freq_01(self): + method = 'logarithmic' + f0 = 1.0 + f1 = 2.0 + t1 = 1.0 + t = np.linspace(0, t1, 10000) + phase = waveforms._chirp_phase(t, f0, t1, f1, method) + tf, f = compute_frequency(t, phase) + abserr = np.max(np.abs(f - chirp_geometric(tf, f0, f1, t1))) + assert abserr < 1e-6 + + def test_logarithmic_freq_02(self): + method = 'logarithmic' + f0 = 200.0 + f1 = 100.0 + t1 = 10.0 + t = np.linspace(0, t1, 10000) + phase = waveforms._chirp_phase(t, f0, t1, f1, method) + tf, f = compute_frequency(t, phase) + abserr = np.max(np.abs(f - chirp_geometric(tf, f0, f1, t1))) + assert abserr < 1e-6 + + def test_logarithmic_freq_03(self): + method = 'logarithmic' + f0 = 100.0 + f1 = 100.0 + t1 = 10.0 + t = np.linspace(0, t1, 10000) + phase = waveforms._chirp_phase(t, f0, t1, f1, method) + tf, f = compute_frequency(t, phase) + abserr = np.max(np.abs(f - chirp_geometric(tf, f0, f1, t1))) + assert abserr < 1e-6 + + def test_hyperbolic_at_zero(self): + w = waveforms.chirp(t=0, f0=10.0, f1=1.0, t1=1.0, method='hyperbolic') + assert_almost_equal(w, 1.0) + + def test_hyperbolic_freq_01(self): + method = 'hyperbolic' + t1 = 1.0 + t = np.linspace(0, t1, 10000) + # f0 f1 + cases = [[10.0, 1.0], + [1.0, 10.0], + [-10.0, -1.0], + [-1.0, -10.0]] + for f0, f1 in cases: + phase = waveforms._chirp_phase(t, f0, t1, f1, method) + tf, f = compute_frequency(t, phase) + expected = chirp_hyperbolic(tf, f0, f1, t1) + xp_assert_close(f, expected, atol=1e-7) + + def test_hyperbolic_zero_freq(self): + # f0=0 or f1=0 must raise a ValueError. + method = 'hyperbolic' + t1 = 1.0 + t = np.linspace(0, t1, 5) + assert_raises(ValueError, waveforms.chirp, t, 0, t1, 1, method) + assert_raises(ValueError, waveforms.chirp, t, 1, t1, 0, method) + + def test_unknown_method(self): + method = "foo" + f0 = 10.0 + f1 = 20.0 + t1 = 1.0 + t = np.linspace(0, t1, 10) + assert_raises(ValueError, waveforms.chirp, t, f0, t1, f1, method) + + def test_integer_t1(self): + f0 = 10.0 + f1 = 20.0 + t = np.linspace(-1, 1, 11) + t1 = 3.0 + float_result = waveforms.chirp(t, f0, t1, f1) + t1 = 3 + int_result = waveforms.chirp(t, f0, t1, f1) + err_msg = "Integer input 't1=3' gives wrong result" + xp_assert_equal(int_result, float_result, err_msg=err_msg) + + def test_integer_f0(self): + f1 = 20.0 + t1 = 3.0 + t = np.linspace(-1, 1, 11) + f0 = 10.0 + float_result = waveforms.chirp(t, f0, t1, f1) + f0 = 10 + int_result = waveforms.chirp(t, f0, t1, f1) + err_msg = "Integer input 'f0=10' gives wrong result" + xp_assert_equal(int_result, float_result, err_msg=err_msg) + + def test_integer_f1(self): + f0 = 10.0 + t1 = 3.0 + t = np.linspace(-1, 1, 11) + f1 = 20.0 + float_result = waveforms.chirp(t, f0, t1, f1) + f1 = 20 + int_result = waveforms.chirp(t, f0, t1, f1) + err_msg = "Integer input 'f1=20' gives wrong result" + xp_assert_equal(int_result, float_result, err_msg=err_msg) + + def test_integer_all(self): + f0 = 10 + t1 = 3 + f1 = 20 + t = np.linspace(-1, 1, 11) + float_result = waveforms.chirp(t, float(f0), float(t1), float(f1)) + int_result = waveforms.chirp(t, f0, t1, f1) + err_msg = "Integer input 'f0=10, t1=3, f1=20' gives wrong result" + xp_assert_equal(int_result, float_result, err_msg=err_msg) + + +class TestSweepPoly: + + def test_sweep_poly_quad1(self): + p = np.poly1d([1.0, 0.0, 1.0]) + t = np.linspace(0, 3.0, 10000) + phase = waveforms._sweep_poly_phase(t, p) + tf, f = compute_frequency(t, phase) + expected = p(tf) + abserr = np.max(np.abs(f - expected)) + assert abserr < 1e-6 + + def test_sweep_poly_const(self): + p = np.poly1d(2.0) + t = np.linspace(0, 3.0, 10000) + phase = waveforms._sweep_poly_phase(t, p) + tf, f = compute_frequency(t, phase) + expected = p(tf) + abserr = np.max(np.abs(f - expected)) + assert abserr < 1e-6 + + def test_sweep_poly_linear(self): + p = np.poly1d([-1.0, 10.0]) + t = np.linspace(0, 3.0, 10000) + phase = waveforms._sweep_poly_phase(t, p) + tf, f = compute_frequency(t, phase) + expected = p(tf) + abserr = np.max(np.abs(f - expected)) + assert abserr < 1e-6 + + def test_sweep_poly_quad2(self): + p = np.poly1d([1.0, 0.0, -2.0]) + t = np.linspace(0, 3.0, 10000) + phase = waveforms._sweep_poly_phase(t, p) + tf, f = compute_frequency(t, phase) + expected = p(tf) + abserr = np.max(np.abs(f - expected)) + assert abserr < 1e-6 + + def test_sweep_poly_cubic(self): + p = np.poly1d([2.0, 1.0, 0.0, -2.0]) + t = np.linspace(0, 2.0, 10000) + phase = waveforms._sweep_poly_phase(t, p) + tf, f = compute_frequency(t, phase) + expected = p(tf) + abserr = np.max(np.abs(f - expected)) + assert abserr < 1e-6 + + def test_sweep_poly_cubic2(self): + """Use an array of coefficients instead of a poly1d.""" + p = np.array([2.0, 1.0, 0.0, -2.0]) + t = np.linspace(0, 2.0, 10000) + phase = waveforms._sweep_poly_phase(t, p) + tf, f = compute_frequency(t, phase) + expected = np.poly1d(p)(tf) + abserr = np.max(np.abs(f - expected)) + assert abserr < 1e-6 + + def test_sweep_poly_cubic3(self): + """Use a list of coefficients instead of a poly1d.""" + p = [2.0, 1.0, 0.0, -2.0] + t = np.linspace(0, 2.0, 10000) + phase = waveforms._sweep_poly_phase(t, p) + tf, f = compute_frequency(t, phase) + expected = np.poly1d(p)(tf) + abserr = np.max(np.abs(f - expected)) + assert abserr < 1e-6 + + +class TestGaussPulse: + + def test_integer_fc(self): + float_result = waveforms.gausspulse('cutoff', fc=1000.0) + int_result = waveforms.gausspulse('cutoff', fc=1000) + err_msg = "Integer input 'fc=1000' gives wrong result" + xp_assert_equal(int_result, float_result, err_msg=err_msg) + + def test_integer_bw(self): + float_result = waveforms.gausspulse('cutoff', bw=1.0) + int_result = waveforms.gausspulse('cutoff', bw=1) + err_msg = "Integer input 'bw=1' gives wrong result" + xp_assert_equal(int_result, float_result, err_msg=err_msg) + + def test_integer_bwr(self): + float_result = waveforms.gausspulse('cutoff', bwr=-6.0) + int_result = waveforms.gausspulse('cutoff', bwr=-6) + err_msg = "Integer input 'bwr=-6' gives wrong result" + xp_assert_equal(int_result, float_result, err_msg=err_msg) + + def test_integer_tpr(self): + float_result = waveforms.gausspulse('cutoff', tpr=-60.0) + int_result = waveforms.gausspulse('cutoff', tpr=-60) + err_msg = "Integer input 'tpr=-60' gives wrong result" + xp_assert_equal(int_result, float_result, err_msg=err_msg) + + +class TestUnitImpulse: + + def test_no_index(self): + xp_assert_equal(waveforms.unit_impulse(7), + np.asarray([1.0, 0, 0, 0, 0, 0, 0])) + xp_assert_equal(waveforms.unit_impulse((3, 3)), + np.asarray([[1.0, 0, 0], [0, 0, 0], [0, 0, 0]])) + + def test_index(self): + xp_assert_equal(waveforms.unit_impulse(10, 3), + np.asarray([0.0, 0, 0, 1, 0, 0, 0, 0, 0, 0])) + xp_assert_equal(waveforms.unit_impulse((3, 3), (1, 1)), + np.asarray([[0.0, 0, 0], [0, 1, 0], [0, 0, 0]])) + + # Broadcasting + imp = waveforms.unit_impulse((4, 4), 2) + xp_assert_equal(imp, np.asarray([[0.0, 0, 0, 0], + [0.0, 0, 0, 0], + [0.0, 0, 1, 0], + [0.0, 0, 0, 0]])) + + def test_mid(self): + xp_assert_equal(waveforms.unit_impulse((3, 3), 'mid'), + np.asarray([[0.0, 0, 0], [0, 1, 0], [0, 0, 0]])) + xp_assert_equal(waveforms.unit_impulse(9, 'mid'), + np.asarray([0.0, 0, 0, 0, 1, 0, 0, 0, 0])) + + def test_dtype(self): + imp = waveforms.unit_impulse(7) + assert np.issubdtype(imp.dtype, np.floating) + + imp = waveforms.unit_impulse(5, 3, dtype=int) + assert np.issubdtype(imp.dtype, np.integer) + + imp = waveforms.unit_impulse((5, 2), (3, 1), dtype=complex) + assert np.issubdtype(imp.dtype, np.complexfloating) + + +class TestSawtoothWaveform: + def test_dtype(self): + waveform = waveforms.sawtooth( + np.array(1, dtype=np.float32), width=np.float32(1) + ) + assert waveform.dtype == np.float64 + + waveform = waveforms.sawtooth(1) + assert waveform.dtype == np.float64 + + +class TestSquareWaveform: + def test_dtype(self): + waveform = waveforms.square(np.array(1, dtype=np.float32), duty=np.float32(0.5)) + assert waveform.dtype == np.float64 + + waveform = waveforms.square(1) + assert waveform.dtype == np.float64 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_wavelets.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_wavelets.py new file mode 100644 index 0000000000000000000000000000000000000000..7a357d2eaf4a530930d612358b8ca69a18b5248e --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_wavelets.py @@ -0,0 +1,59 @@ +import numpy as np +from numpy.testing import assert_array_equal, assert_array_almost_equal + +import scipy.signal._wavelets as wavelets + + +class TestWavelets: + def test_ricker(self): + w = wavelets._ricker(1.0, 1) + expected = 2 / (np.sqrt(3 * 1.0) * (np.pi ** 0.25)) + assert_array_equal(w, expected) + + lengths = [5, 11, 15, 51, 101] + for length in lengths: + w = wavelets._ricker(length, 1.0) + assert len(w) == length + max_loc = np.argmax(w) + assert max_loc == (length // 2) + + points = 100 + w = wavelets._ricker(points, 2.0) + half_vec = np.arange(0, points // 2) + # Wavelet should be symmetric + assert_array_almost_equal(w[half_vec], w[-(half_vec + 1)]) + + # Check zeros + aas = [5, 10, 15, 20, 30] + points = 99 + for a in aas: + w = wavelets._ricker(points, a) + vec = np.arange(0, points) - (points - 1.0) / 2 + exp_zero1 = np.argmin(np.abs(vec - a)) + exp_zero2 = np.argmin(np.abs(vec + a)) + assert_array_almost_equal(w[exp_zero1], 0) + assert_array_almost_equal(w[exp_zero2], 0) + + def test_cwt(self): + widths = [1.0] + def delta_wavelet(s, t): + return np.array([1]) + len_data = 100 + test_data = np.sin(np.pi * np.arange(0, len_data) / 10.0) + + # Test delta function input gives same data as output + cwt_dat = wavelets._cwt(test_data, delta_wavelet, widths) + assert cwt_dat.shape == (len(widths), len_data) + assert_array_almost_equal(test_data, cwt_dat.flatten()) + + # Check proper shape on output + widths = [1, 3, 4, 5, 10] + cwt_dat = wavelets._cwt(test_data, wavelets._ricker, widths) + assert cwt_dat.shape == (len(widths), len_data) + + widths = [len_data * 10] + # Note: this wavelet isn't defined quite right, but is fine for this test + def flat_wavelet(l, w): + return np.full(w, 1 / w) + cwt_dat = wavelets._cwt(test_data, flat_wavelet, widths) + assert_array_almost_equal(cwt_dat, np.mean(test_data)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_windows.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_windows.py new file mode 100644 index 0000000000000000000000000000000000000000..a704e3a831264765ea6c8c9481524d15c7c0972b --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/tests/test_windows.py @@ -0,0 +1,1098 @@ +import math +import warnings + +import numpy as np +from numpy import array +import pytest +from pytest import raises as assert_raises + +from scipy.fft import fft +from scipy.signal import windows, get_window, resample +from scipy.signal.windows._windows import _WIN_FUNC_DATA, _WIN_FUNCS +from scipy._lib._array_api import ( + xp_assert_close, xp_assert_equal, array_namespace, is_torch, is_jax, is_cupy, + assert_array_almost_equal, SCIPY_DEVICE, is_numpy, make_xp_test_case, + make_xp_pytest_param, _xp_copy_to_numpy +) + +skip_xp_backends = pytest.mark.skip_xp_backends +xfail_xp_backends = pytest.mark.xfail_xp_backends + +lazy_xp_modules = [windows] + + +window_funcs = [ + ('boxcar', ()), + ('triang', ()), + ('parzen', ()), + ('bohman', ()), + ('blackman', ()), + ('nuttall', ()), + ('blackmanharris', ()), + ('flattop', ()), + ('bartlett', ()), + ('barthann', ()), + ('hamming', ()), + ('kaiser', (1,)), + ('dpss', (2,)), + ('gaussian', (0.5,)), + ('general_gaussian', (1.5, 2)), + ('chebwin', (1,)), + ('cosine', ()), + ('hann', ()), + ('exponential', ()), + ('taylor', ()), + ('tukey', (0.5,)), + ('lanczos', ()), + ] + + +@make_xp_test_case(windows.barthann) +class TestBartHann: + + def test_basic(self, xp): + xp_assert_close(windows.barthann(6, sym=True, xp=xp), + xp.asarray([0, 0.35857354213752, 0.8794264578624801, + 0.8794264578624801, 0.3585735421375199, 0], dtype=xp.float64), + rtol=1e-15, atol=1e-15) + xp_assert_close(windows.barthann(7, xp=xp), + xp.asarray([0, 0.27, 0.73, 1.0, 0.73, 0.27, 0], + dtype=xp.float64), + rtol=1e-15, atol=1e-15) + xp_assert_close(windows.barthann(6, False, xp=xp), + xp.asarray([0, 0.27, 0.73, 1.0, 0.73, 0.27], dtype=xp.float64), + rtol=1e-15, atol=1e-15) + + +@make_xp_test_case(windows.bartlett) +class TestBartlett: + + def test_basic(self, xp): + xp_assert_close(windows.bartlett(6, xp=xp), + xp.asarray([0, 0.4, 0.8, 0.8, 0.4, 0], dtype=xp.float64)) + xp_assert_close(windows.bartlett(7, xp=xp), + xp.asarray([0, 1/3, 2/3, 1.0, 2/3, 1/3, 0], dtype=xp.float64)) + xp_assert_close(windows.bartlett(6, False, xp=xp), + xp.asarray([0, 1/3, 2/3, 1.0, 2/3, 1/3], dtype=xp.float64)) + + +@make_xp_test_case(windows.blackman) +class TestBlackman: + + def test_basic(self, xp): + xp_assert_close(windows.blackman(6, sym=False, xp=xp), + xp.asarray([0, 0.13, 0.63, 1.0, 0.63, 0.13], dtype=xp.float64), + atol=1e-14) + xp_assert_close(windows.blackman(7, sym=False, xp=xp), + xp.asarray([0, 0.09045342435412804, 0.4591829575459636, + 0.9203636180999081, 0.9203636180999081, + 0.4591829575459636, 0.09045342435412804], + dtype=xp.float64), + atol=1e-8) + xp_assert_close(windows.blackman(6, xp=xp), + xp.asarray([0, 0.2007701432625305, 0.8492298567374694, + 0.8492298567374694, 0.2007701432625305, 0], + dtype=xp.float64), + atol=1e-14) + xp_assert_close(windows.blackman(7, True, xp=xp), + xp.asarray([0, 0.13, 0.63, 1.0, 0.63, 0.13, 0], + dtype=xp.float64), atol=1e-14) + + +@make_xp_test_case(windows.blackmanharris) +class TestBlackmanHarris: + + def test_basic(self, xp): + xp_assert_close(windows.blackmanharris(6, False, xp=xp), + xp.asarray([6.0e-05, 0.055645, 0.520575, + 1.0, 0.520575, 0.055645], dtype=xp.float64)) + xp_assert_close(windows.blackmanharris(7, sym=False, xp=xp), + xp.asarray([6.0e-05, 0.03339172347815117, 0.332833504298565, + 0.8893697722232837, 0.8893697722232838, + 0.3328335042985652, 0.03339172347815122], + dtype=xp.float64)) + xp_assert_close(windows.blackmanharris(6, xp=xp), + xp.asarray([6.0e-05, 0.1030114893456638, 0.7938335106543362, + 0.7938335106543364, 0.1030114893456638, 6.0e-05], + dtype=xp.float64)) + xp_assert_close(windows.blackmanharris(7, sym=True, xp=xp), + xp.asarray([6.0e-05, 0.055645, 0.520575, 1.0, 0.520575, + 0.055645, 6.0e-05], dtype=xp.float64)) + + +@make_xp_test_case(windows.taylor) +class TestTaylor: + + def test_normalized(self, xp): + """Tests windows of small length that are normalized to 1. See the + documentation for the Taylor window for more information on + normalization. + """ + xp_assert_close(windows.taylor(1, 2, 15, xp=xp), + xp.asarray([1.0], dtype=xp.float64)) + xp_assert_close( + windows.taylor(5, 2, 15, xp=xp), + xp.asarray([0.75803341, 0.90757699, 1.0, 0.90757699, 0.75803341], + dtype=xp.float64) + ) + xp_assert_close( + windows.taylor(6, 2, 15, xp=xp), + xp.asarray([ + 0.7504082, 0.86624416, 0.98208011, 0.98208011, 0.86624416, + 0.7504082 + ], dtype=xp.float64) + ) + + def test_non_normalized(self, xp): + """Test windows of small length that are not normalized to 1. See + the documentation for the Taylor window for more information on + normalization. + """ + xp_assert_close( + windows.taylor(5, 2, 15, norm=False, xp=xp), + xp.asarray([ + 0.87508054, 1.04771499, 1.15440894, 1.04771499, 0.87508054 + ], dtype=xp.float64) + ) + xp_assert_close( + windows.taylor(6, 2, 15, norm=False, xp=xp), + xp.asarray([ + 0.86627793, 1.0, 1.13372207, 1.13372207, 1.0, 0.86627793 + ], dtype=xp.float64) + ) + + def test_correctness(self, xp): + """This test ensures the correctness of the implemented Taylor + Windowing function. A Taylor Window of 1024 points is created, its FFT + is taken, and the Peak Sidelobe Level (PSLL) and 3dB and 18dB bandwidth + are found and checked. + + A publication from Sandia National Laboratories was used as reference + for the correctness values [1]_. + + References + ----- + .. [1] Armin Doerry, "Catalog of Window Taper Functions for + Sidelobe Control", 2017. + https://www.researchgate.net/profile/Armin_Doerry/publication/316281181_Catalog_of_Window_Taper_Functions_for_Sidelobe_Control/links/58f92cb2a6fdccb121c9d54d/Catalog-of-Window-Taper-Functions-for-Sidelobe-Control.pdf + """ + M_win = 1024 + N_fft = 131072 + # Set norm=False for correctness as the values obtained from the + # scientific publication do not normalize the values. Normalizing + # changes the sidelobe level from the desired value. + w = windows.taylor(M_win, nbar=4, sll=35, norm=False, sym=False, xp=xp) + f_np = fft(_xp_copy_to_numpy(w), N_fft) + + spec = 20 * np.log10(np.abs(f_np / np.max(f_np))) + + first_zero = np.argmax(np.diff(spec) > 0) + + PSLL = np.max(spec[first_zero:-first_zero]) + + BW_3dB = 2*np.argmax(spec <= -3.0102999566398121) / N_fft * M_win + BW_18dB = 2*np.argmax(spec <= -18.061799739838872) / N_fft * M_win + + assert math.isclose(PSLL, -35.1672, abs_tol=1) + assert math.isclose(BW_3dB, 1.1822, abs_tol=0.1) + assert math.isclose(BW_18dB, 2.6112, abs_tol=0.1) + + +@make_xp_test_case(windows.bohman) +class TestBohman: + + def test_basic(self, xp): + xp_assert_close(windows.bohman(6, xp=xp), + xp.asarray([0, 0.1791238937062839, 0.8343114522576858, + 0.8343114522576858, 0.1791238937062838, 0], + dtype=xp.float64)) + xp_assert_close(windows.bohman(7, sym=True, xp=xp), + xp.asarray([0, 0.1089977810442293, 0.6089977810442293, 1.0, + 0.6089977810442295, 0.1089977810442293, 0], + dtype=xp.float64)) + xp_assert_close(windows.bohman(6, False, xp=xp), + xp.asarray([0, 0.1089977810442293, 0.6089977810442293, 1.0, + 0.6089977810442295, 0.1089977810442293], + dtype=xp.float64)) + + +@make_xp_test_case(windows.boxcar) +class TestBoxcar: + + def test_basic(self, xp): + xp_assert_close(windows.boxcar(6, xp=xp), + xp.asarray([1.0, 1, 1, 1, 1, 1], dtype=xp.float64)) + xp_assert_close(windows.boxcar(7, xp=xp), + xp.asarray([1.0, 1, 1, 1, 1, 1, 1], dtype=xp.float64)) + xp_assert_close(windows.boxcar(6, False, xp=xp), + xp.asarray([1.0, 1, 1, 1, 1, 1], dtype=xp.float64)) + + +cheb_odd_true = [0.200938, 0.107729, 0.134941, 0.165348, + 0.198891, 0.235450, 0.274846, 0.316836, + 0.361119, 0.407338, 0.455079, 0.503883, + 0.553248, 0.602637, 0.651489, 0.699227, + 0.745266, 0.789028, 0.829947, 0.867485, + 0.901138, 0.930448, 0.955010, 0.974482, + 0.988591, 0.997138, 1.000000, 0.997138, + 0.988591, 0.974482, 0.955010, 0.930448, + 0.901138, 0.867485, 0.829947, 0.789028, + 0.745266, 0.699227, 0.651489, 0.602637, + 0.553248, 0.503883, 0.455079, 0.407338, + 0.361119, 0.316836, 0.274846, 0.235450, + 0.198891, 0.165348, 0.134941, 0.107729, + 0.200938] + +cheb_even_true = [0.203894, 0.107279, 0.133904, + 0.163608, 0.196338, 0.231986, + 0.270385, 0.311313, 0.354493, + 0.399594, 0.446233, 0.493983, + 0.542378, 0.590916, 0.639071, + 0.686302, 0.732055, 0.775783, + 0.816944, 0.855021, 0.889525, + 0.920006, 0.946060, 0.967339, + 0.983557, 0.994494, 1.000000, + 1.000000, 0.994494, 0.983557, + 0.967339, 0.946060, 0.920006, + 0.889525, 0.855021, 0.816944, + 0.775783, 0.732055, 0.686302, + 0.639071, 0.590916, 0.542378, + 0.493983, 0.446233, 0.399594, + 0.354493, 0.311313, 0.270385, + 0.231986, 0.196338, 0.163608, + 0.133904, 0.107279, 0.203894] + + +@make_xp_test_case(windows.chebwin) +class TestChebWin: + + def test_basic(self, xp): + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "This window is not suitable", UserWarning) + xp_assert_close(windows.chebwin(6, 100, xp=xp), + xp.asarray([0.1046401879356917, 0.5075781475823447, + 1.0, 1.0, + 0.5075781475823447, 0.1046401879356917], + dtype=xp.float64), + atol=1e-8 + ) + xp_assert_close(windows.chebwin(7, 100, xp=xp), + xp.asarray([0.05650405062850233, 0.316608530648474, + 0.7601208123539079, 1.0, 0.7601208123539079, + 0.316608530648474, 0.05650405062850233], + dtype=xp.float64)) + xp_assert_close(windows.chebwin(6, 10, xp=xp), + xp.asarray([1.0, 0.6071201674458373, 0.6808391469897297, + 0.6808391469897297, 0.6071201674458373, 1.0], + dtype=xp.float64)) + xp_assert_close(windows.chebwin(7, 10, xp=xp), + xp.asarray([1.0, 0.5190521247588651, 0.5864059018130382, + 0.6101519801307441, 0.5864059018130382, + 0.5190521247588651, 1.0], dtype=xp.float64)) + xp_assert_close(windows.chebwin(6, 10, False, xp=xp), + xp.asarray([1.0, 0.5190521247588651, 0.5864059018130382, + 0.6101519801307441, 0.5864059018130382, + 0.5190521247588651], dtype=xp.float64)) + + def test_cheb_odd_high_attenuation(self, xp): + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "This window is not suitable", UserWarning) + cheb_odd = windows.chebwin(53, at=-40, xp=xp) + assert_array_almost_equal(cheb_odd, xp.asarray(cheb_odd_true), decimal=4) + + def test_cheb_even_high_attenuation(self, xp): + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "This window is not suitable", UserWarning) + cheb_even = windows.chebwin(54, at=40, xp=xp) + assert_array_almost_equal(cheb_even, xp.asarray(cheb_even_true), decimal=4) + + def test_cheb_odd_low_attenuation(self, xp): + cheb_odd_low_at_true = xp.asarray([1.000000, 0.519052, 0.586405, + 0.610151, 0.586405, 0.519052, + 1.000000], dtype=xp.float64) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "This window is not suitable", UserWarning) + cheb_odd = windows.chebwin(7, at=10, xp=xp) + assert_array_almost_equal(cheb_odd, cheb_odd_low_at_true, decimal=4) + + def test_cheb_even_low_attenuation(self, xp): + cheb_even_low_at_true = xp.asarray([1.000000, 0.451924, 0.51027, + 0.541338, 0.541338, 0.51027, + 0.451924, 1.000000], dtype=xp.float64) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "This window is not suitable", UserWarning) + cheb_even = windows.chebwin(8, at=-10, xp=xp) + assert_array_almost_equal(cheb_even, cheb_even_low_at_true, decimal=4) + + +exponential_data = { + (4, None, 0.2, False): + array([4.53999297624848542e-05, + 6.73794699908546700e-03, 1.00000000000000000e+00, + 6.73794699908546700e-03]), + (4, None, 0.2, True): array([0.00055308437014783, 0.0820849986238988, + 0.0820849986238988, 0.00055308437014783]), + (4, None, 1.0, False): array([0.1353352832366127, 0.36787944117144233, 1., + 0.36787944117144233]), + (4, None, 1.0, True): array([0.22313016014842982, 0.60653065971263342, + 0.60653065971263342, 0.22313016014842982]), + (4, 2, 0.2, False): + array([4.53999297624848542e-05, 6.73794699908546700e-03, + 1.00000000000000000e+00, 6.73794699908546700e-03]), + (4, 2, 0.2, True): None, + (4, 2, 1.0, False): array([0.1353352832366127, 0.36787944117144233, 1., + 0.36787944117144233]), + (4, 2, 1.0, True): None, + (5, None, 0.2, True): + array([4.53999297624848542e-05, + 6.73794699908546700e-03, 1.00000000000000000e+00, + 6.73794699908546700e-03, 4.53999297624848542e-05]), + (5, None, 1.0, True): array([0.1353352832366127, 0.36787944117144233, 1., + 0.36787944117144233, 0.1353352832366127]), + (5, 2, 0.2, True): None, + (5, 2, 1.0, True): None +} + + +@make_xp_test_case(windows.exponential) +def test_exponential(xp): + for k, v in exponential_data.items(): + if v is None: + assert_raises(ValueError, windows.exponential, *k, xp=xp) + else: + win = windows.exponential(*k, xp=xp) + xp_assert_close(win, xp.asarray(v), rtol=1e-14) + + +@make_xp_test_case(windows.flattop) +class TestFlatTop: + + def test_basic(self, xp): + xp_assert_close(windows.flattop(6, sym=False, xp=xp), + xp.asarray([-0.000421051, -0.051263156, 0.19821053, 1.0, + 0.19821053, -0.051263156], dtype=xp.float64)) + xp_assert_close(windows.flattop(7, sym=False, xp=xp), + xp.asarray([-0.000421051, -0.03684078115492348, + 0.01070371671615342, 0.7808739149387698, + 0.7808739149387698, 0.01070371671615342, + -0.03684078115492348], dtype=xp.float64)) + xp_assert_close(windows.flattop(6, xp=xp), + xp.asarray([-0.000421051, -0.0677142520762119, + 0.6068721525762117, 0.6068721525762117, + -0.0677142520762119, -0.000421051], + dtype=xp.float64)) + xp_assert_close(windows.flattop(7, True, xp=xp), + xp.asarray([-0.000421051, -0.051263156, 0.19821053, 1.0, + 0.19821053, -0.051263156, -0.000421051], + dtype=xp.float64)) + + +@make_xp_test_case(windows.gaussian) +class TestGaussian: + + def test_basic(self, xp): + xp_assert_close(windows.gaussian(6, 1.0, xp=xp), + xp.asarray([0.04393693362340742, 0.3246524673583497, + 0.8824969025845955, 0.8824969025845955, + 0.3246524673583497, 0.04393693362340742], + dtype=xp.float64)) + xp_assert_close(windows.gaussian(7, 1.2, xp=xp), + xp.asarray([0.04393693362340742, 0.2493522087772962, + 0.7066482778577162, 1.0, 0.7066482778577162, + 0.2493522087772962, 0.04393693362340742], + dtype=xp.float64)) + xp_assert_close(windows.gaussian(7, 3, xp=xp), + xp.asarray([0.6065306597126334, 0.8007374029168081, + 0.9459594689067654, 1.0, 0.9459594689067654, + 0.8007374029168081, 0.6065306597126334], + dtype=xp.float64)) + xp_assert_close(windows.gaussian(6, 3, False, xp=xp), + xp.asarray([0.6065306597126334, 0.8007374029168081, + 0.9459594689067654, 1.0, 0.9459594689067654, + 0.8007374029168081], dtype=xp.float64)) + + +@make_xp_test_case(windows.general_cosine) +class TestGeneralCosine: + + def test_basic(self, xp): + a = xp.asarray([0.5, 0.3, 0.2]) + xp_assert_close(windows.general_cosine(5, a), + xp.asarray([0.4, 0.3, 1, 0.3, 0.4], dtype=xp.float64)) + + a = xp.asarray([0.5, 0.3, 0.2]) + xp_assert_close(windows.general_cosine(4, a, sym=False), + xp.asarray([0.4, 0.3, 1, 0.3], dtype=xp.float64)) + + +@make_xp_test_case(windows.general_hamming) +class TestGeneralHamming: + + def test_basic(self, xp): + xp_assert_close(windows.general_hamming(5, 0.7, xp=xp), + xp.asarray([0.4, 0.7, 1.0, 0.7, 0.4], dtype=xp.float64)) + xp_assert_close(windows.general_hamming(5, 0.75, sym=False, xp=xp), + xp.asarray([0.5, 0.6727457514, 0.9522542486, + 0.9522542486, 0.6727457514], dtype=xp.float64)) + xp_assert_close(windows.general_hamming(6, 0.75, sym=True, xp=xp), + xp.asarray([0.5, 0.6727457514, 0.9522542486, + 0.9522542486, 0.6727457514, 0.5], dtype=xp.float64)) + + +@make_xp_test_case(windows.hamming) +class TestHamming: + + def test_basic(self, xp): + xp_assert_close(windows.hamming(6, False, xp=xp), + xp.asarray([0.08, 0.31, 0.77, 1.0, 0.77, 0.31], + dtype=xp.float64)) + xp_assert_close(windows.hamming(7, sym=False, xp=xp), + xp.asarray([0.08, 0.2531946911449826, 0.6423596296199047, + 0.9544456792351128, 0.9544456792351128, + 0.6423596296199047, 0.2531946911449826], + dtype=xp.float64)) + xp_assert_close(windows.hamming(6, xp=xp), + xp.asarray([0.08, 0.3978521825875242, 0.9121478174124757, + 0.9121478174124757, 0.3978521825875242, 0.08], + dtype=xp.float64)) + xp_assert_close(windows.hamming(7, sym=True, xp=xp), + xp.asarray([0.08, 0.31, 0.77, 1.0, 0.77, 0.31, 0.08], + dtype=xp.float64)) + + +@make_xp_test_case(windows.hann) +class TestHann: + + def test_basic(self, xp): + xp_assert_close(windows.hann(6, sym=False, xp=xp), + xp.asarray([0, 0.25, 0.75, 1.0, 0.75, 0.25], dtype=xp.float64), + rtol=1e-15, atol=1e-15) + xp_assert_close(windows.hann(7, sym=False, xp=xp), + xp.asarray([0, 0.1882550990706332, 0.6112604669781572, + 0.9504844339512095, 0.9504844339512095, + 0.6112604669781572, 0.1882550990706332], + dtype=xp.float64), + rtol=1e-15, atol=1e-15) + xp_assert_close(windows.hann(6, True, xp=xp), + xp.asarray([0, 0.3454915028125263, 0.9045084971874737, + 0.9045084971874737, 0.3454915028125263, 0], + dtype=xp.float64), + rtol=1e-15, atol=1e-15) + xp_assert_close(windows.hann(7, xp=xp), + xp.asarray([0, 0.25, 0.75, 1.0, 0.75, 0.25, 0], + dtype=xp.float64), + rtol=1e-15, atol=1e-15) + + +@make_xp_test_case(windows.kaiser) +class TestKaiser: + + def test_basic(self, xp): + xp_assert_close(windows.kaiser(6, 0.5, xp=xp), + xp.asarray([0.9403061933191572, 0.9782962393705389, + 0.9975765035372042, 0.9975765035372042, + 0.9782962393705389, 0.9403061933191572], + dtype=xp.float64)) + xp_assert_close(windows.kaiser(7, 0.5, xp=xp), + xp.asarray([0.9403061933191572, 0.9732402256999829, + 0.9932754654413773, 1.0, 0.9932754654413773, + 0.9732402256999829, 0.9403061933191572], + dtype=xp.float64)) + xp_assert_close(windows.kaiser(6, 2.7, xp=xp), + xp.asarray([0.2603047507678832, 0.6648106293528054, + 0.9582099802511439, 0.9582099802511439, + 0.6648106293528054, 0.2603047507678832], + dtype=xp.float64)) + xp_assert_close(windows.kaiser(7, 2.7, xp=xp), + xp.asarray([0.2603047507678832, 0.5985765418119844, + 0.8868495172060835, 1.0, 0.8868495172060835, + 0.5985765418119844, 0.2603047507678832], + dtype=xp.float64)) + xp_assert_close(windows.kaiser(6, 2.7, False, xp=xp), + xp.asarray([0.2603047507678832, 0.5985765418119844, + 0.8868495172060835, 1.0, 0.8868495172060835, + 0.5985765418119844], dtype=xp.float64)) + + +@make_xp_test_case(windows.kaiser_bessel_derived) +class TestKaiserBesselDerived: + + def test_basic(self, xp): + # cover case `M < 1` + w = windows.kaiser_bessel_derived(0.5, beta=4.0, xp=xp) + xp_assert_equal(w, xp.asarray([])) + + M = 100 + w = windows.kaiser_bessel_derived(M, beta=4.0, xp=xp) + w2 = windows.get_window(('kaiser bessel derived', 4.0), + M, fftbins=False, xp=xp) + xp_assert_close(w, w2) + + # Test for Princen-Bradley condition + actual = w[:M // 2] ** 2 + w[-M // 2:] ** 2 + xp_assert_close(actual, xp.ones(actual.shape, dtype=actual.dtype)) + + # Test actual values from other implementations + # M = 2: sqrt(2) / 2 + # M = 4: 0.518562710536, 0.855039598640 + # M = 6: 0.436168993154, 0.707106781187, 0.899864772847 + # Ref:https://github.com/scipy/scipy/pull/4747#issuecomment-172849418 + actual = windows.kaiser_bessel_derived(2, beta=np.pi / 2, xp=xp)[:1] + desired = xp.ones_like(actual) * math.sqrt(2) / 2.0 + xp_assert_close(actual, desired) + + xp_assert_close(windows.kaiser_bessel_derived(4, beta=np.pi / 2, xp=xp)[:2], + xp.asarray([0.518562710536, 0.855039598640], dtype=xp.float64)) + + xp_assert_close(windows.kaiser_bessel_derived(6, beta=np.pi / 2, xp=xp)[:3], + xp.asarray([0.436168993154, 0.707106781187, 0.899864772847], + dtype=xp.float64)) + + def test_exceptions(self, xp): + M = 100 + # Assert ValueError for odd window length + msg = ("Kaiser-Bessel Derived windows are only defined for even " + "number of points") + with assert_raises(ValueError, match=msg): + windows.kaiser_bessel_derived(M + 1, beta=4., xp=xp) + + # Assert ValueError for non-symmetric setting + msg = ("Kaiser-Bessel Derived windows are only defined for " + "symmetric shapes") + with assert_raises(ValueError, match=msg): + windows.kaiser_bessel_derived(M + 1, beta=4., sym=False, xp=xp) + + +class TestNuttall: + + def test_basic(self, xp): + xp_assert_close(windows.nuttall(6, sym=False, xp=xp), + xp.asarray([0.0003628, 0.0613345, 0.5292298, 1.0, 0.5292298, + 0.0613345], dtype=xp.float64)) + xp_assert_close(windows.nuttall(7, sym=False, xp=xp), + xp.asarray([0.0003628, 0.03777576895352025, + 0.3427276199688195, + 0.8918518610776603, 0.8918518610776603, + 0.3427276199688196, 0.0377757689535203], + dtype=xp.float64)) + xp_assert_close(windows.nuttall(6, xp=xp), + xp.asarray([0.0003628, 0.1105152530498718, + 0.7982580969501282, 0.7982580969501283, + 0.1105152530498719, 0.0003628], dtype=xp.float64)) + xp_assert_close(windows.nuttall(7, True, xp=xp), + xp.asarray([0.0003628, 0.0613345, 0.5292298, 1.0, + 0.5292298, 0.0613345, 0.0003628], dtype=xp.float64)) + + +@make_xp_test_case(windows.parzen) +class TestParzen: + + def test_basic(self, xp): + xp_assert_close(windows.parzen(6, xp=xp), + xp.asarray([0.009259259259259254, 0.25, 0.8611111111111112, + 0.8611111111111112, 0.25, 0.009259259259259254], + dtype=xp.float64)) + xp_assert_close(windows.parzen(7, sym=True, xp=xp), + xp.asarray([0.00583090379008747, 0.1574344023323616, + 0.6501457725947521, 1.0, 0.6501457725947521, + 0.1574344023323616, 0.00583090379008747], + dtype=xp.float64)) + xp_assert_close(windows.parzen(6, False, xp=xp), + xp.asarray([0.00583090379008747, 0.1574344023323616, + 0.6501457725947521, 1.0, 0.6501457725947521, + 0.1574344023323616], dtype=xp.float64)) + + +@make_xp_test_case(windows.triang) +class TestTriang: + + def test_basic(self, xp): + + xp_assert_close(windows.triang(6, True, xp=xp), + xp.asarray([1/6, 1/2, 5/6, 5/6, 1/2, 1/6], dtype=xp.float64)) + xp_assert_close(windows.triang(7, xp=xp), + xp.asarray([1/4, 1/2, 3/4, 1, 3/4, 1/2, 1/4], dtype=xp.float64)) + xp_assert_close(windows.triang(6, sym=False, xp=xp), + xp.asarray([1/4, 1/2, 3/4, 1, 3/4, 1/2], dtype=xp.float64)) + + +tukey_data = { + (4, 0.5, True): array([0.0, 1.0, 1.0, 0.0]), + (4, 0.9, True): array([0.0, 0.84312081893436686, + 0.84312081893436686, 0.0]), + (4, 1.0, True): array([0.0, 0.75, 0.75, 0.0]), + (4, 0.5, False): array([0.0, 1.0, 1.0, 1.0]), + (4, 0.9, False): array([0.0, 0.58682408883346526, + 1.0, 0.58682408883346526]), + (4, 1.0, False): array([0.0, 0.5, 1.0, 0.5]), + (5, 0.0, True): array([1.0, 1.0, 1.0, 1.0, 1.0]), + (5, 0.8, True): array([0.0, 0.69134171618254492, + 1.0, 0.69134171618254492, 0.0]), + (5, 1.0, True): array([0.0, 0.5, 1.0, 0.5, 0.0]), + + (6, 0): [1.0, 1, 1, 1, 1, 1], + (7, 0): [1.0, 1, 1, 1, 1, 1, 1], + (6, .25): [0.0, 1, 1, 1, 1, 0], + (7, .25): [0.0, 1, 1, 1, 1, 1, 0], + (6,): [0, 0.9045084971874737, 1.0, 1.0, 0.9045084971874735, 0], + (7,): [0, 0.75, 1.0, 1.0, 1.0, 0.75, 0], + (6, .75): [0, 0.5522642316338269, 1.0, 1.0, 0.5522642316338267, 0], + (7, .75): [0, 0.4131759111665348, 0.9698463103929542, 1.0, + 0.9698463103929542, 0.4131759111665347, 0], + (6, 1): [0, 0.3454915028125263, 0.9045084971874737, 0.9045084971874737, + 0.3454915028125263, 0], + (7, 1): [0, 0.25, 0.75, 1.0, 0.75, 0.25, 0], +} + + +@make_xp_test_case(windows.tukey) +class TestTukey: + + def test_basic(self, xp): + # Test against hardcoded data + for k, v in tukey_data.items(): + if v is None: + assert_raises(ValueError, windows.tukey, *k, xp=xp) + else: + if is_torch(xp) and k in [(6,), (6, .75), (7, .75), (6,1)]: + atol_rtol = {'rtol': 3e-8, 'atol': 1e-8} + else: + atol_rtol = {'rtol': 1e-15, 'atol': 1e-15 } + + win = windows.tukey(*k, xp=xp) + xp_assert_close(win, xp.asarray(v), + check_dtype=False, **atol_rtol) + + def test_extremes(self, xp): + # Test extremes of alpha correspond to boxcar and hann + tuk0 = windows.tukey(100, 0, xp=xp) + box0 = windows.boxcar(100, xp=xp) + xp_assert_close(tuk0, box0) + + tuk1 = windows.tukey(100, 1, xp=xp) + han1 = windows.hann(100, xp=xp) + xp_assert_close(tuk1, han1) + + +dpss_data = { + # All values from MATLAB: + # * taper[1] of (3, 1.4, 3) sign-flipped + # * taper[3] of (5, 1.5, 5) sign-flipped + (4, 0.1, 2): ([[0.497943898, 0.502047681, 0.502047681, 0.497943898], [0.670487993, 0.224601537, -0.224601537, -0.670487993]], [0.197961815, 0.002035474]), # noqa: E501 + (3, 1.4, 3): ([[0.410233151, 0.814504464, 0.410233151], [0.707106781, 0.0, -0.707106781], [0.575941629, -0.580157287, 0.575941629]], [0.999998093, 0.998067480, 0.801934426]), # noqa: E501 + (5, 1.5, 5): ([[0.1745071052, 0.4956749177, 0.669109327, 0.495674917, 0.174507105], [0.4399493348, 0.553574369, 0.0, -0.553574369, -0.439949334], [0.631452756, 0.073280238, -0.437943884, 0.073280238, 0.631452756], [0.553574369, -0.439949334, 0.0, 0.439949334, -0.553574369], [0.266110290, -0.498935248, 0.600414741, -0.498935248, 0.266110290147157]], [0.999728571, 0.983706916, 0.768457889, 0.234159338, 0.013947282907567]), # noqa: E501 + (100, 2, 4): ([[0.0030914414, 0.0041266922, 0.005315076, 0.006665149, 0.008184854, 0.0098814158, 0.011761239, 0.013829809, 0.016091597, 0.018549973, 0.02120712, 0.02406396, 0.027120092, 0.030373728, 0.033821651, 0.037459181, 0.041280145, 0.045276872, 0.049440192, 0.053759447, 0.058222524, 0.062815894, 0.067524661, 0.072332638, 0.077222418, 0.082175473, 0.087172252, 0.092192299, 0.097214376, 0.1022166, 0.10717657, 0.11207154, 0.11687856, 0.12157463, 0.12613686, 0.13054266, 0.13476986, 0.13879691, 0.14260302, 0.14616832, 0.14947401, 0.1525025, 0.15523755, 0.15766438, 0.15976981, 0.16154233, 0.16297223, 0.16405162, 0.16477455, 0.16513702, 0.16513702, 0.16477455, 0.16405162, 0.16297223, 0.16154233, 0.15976981, 0.15766438, 0.15523755, 0.1525025, 0.14947401, 0.14616832, 0.14260302, 0.13879691, 0.13476986, 0.13054266, 0.12613686, 0.12157463, 0.11687856, 0.11207154, 0.10717657, 0.1022166, 0.097214376, 0.092192299, 0.087172252, 0.082175473, 0.077222418, 0.072332638, 0.067524661, 0.062815894, 0.058222524, 0.053759447, 0.049440192, 0.045276872, 0.041280145, 0.037459181, 0.033821651, 0.030373728, 0.027120092, 0.02406396, 0.02120712, 0.018549973, 0.016091597, 0.013829809, 0.011761239, 0.0098814158, 0.008184854, 0.006665149, 0.005315076, 0.0041266922, 0.0030914414], [0.018064449, 0.022040342, 0.026325013, 0.030905288, 0.035764398, 0.040881982, 0.046234148, 0.051793558, 0.057529559, 0.063408356, 0.069393216, 0.075444716, 0.081521022, 0.087578202, 0.093570567, 0.099451049, 0.10517159, 0.11068356, 0.11593818, 0.12088699, 0.12548227, 0.12967752, 0.1334279, 0.13669069, 0.13942569, 0.1415957, 0.14316686, 0.14410905, 0.14439626, 0.14400686, 0.14292389, 0.1411353, 0.13863416, 0.13541876, 0.13149274, 0.12686516, 0.12155045, 0.1155684, 0.10894403, 0.10170748, 0.093893752, 0.08554251, 0.076697768, 0.067407559, 0.057723559, 0.04770068, 0.037396627, 0.026871428, 0.016186944, 0.0054063557, -0.0054063557, -0.016186944, -0.026871428, -0.037396627, -0.04770068, -0.057723559, -0.067407559, -0.076697768, -0.08554251, -0.093893752, -0.10170748, -0.10894403, -0.1155684, -0.12155045, -0.12686516, -0.13149274, -0.13541876, -0.13863416, -0.1411353, -0.14292389, -0.14400686, -0.14439626, -0.14410905, -0.14316686, -0.1415957, -0.13942569, -0.13669069, -0.1334279, -0.12967752, -0.12548227, -0.12088699, -0.11593818, -0.11068356, -0.10517159, -0.099451049, -0.093570567, -0.087578202, -0.081521022, -0.075444716, -0.069393216, -0.063408356, -0.057529559, -0.051793558, -0.046234148, -0.040881982, -0.035764398, -0.030905288, -0.026325013, -0.022040342, -0.018064449], [0.064817553, 0.072567801, 0.080292992, 0.087918235, 0.095367076, 0.10256232, 0.10942687, 0.1158846, 0.12186124, 0.12728523, 0.13208858, 0.13620771, 0.13958427, 0.14216587, 0.14390678, 0.14476863, 0.1447209, 0.14374148, 0.14181704, 0.13894336, 0.13512554, 0.13037812, 0.1247251, 0.11819984, 0.11084487, 0.10271159, 0.093859853, 0.084357497, 0.074279719, 0.063708406, 0.052731374, 0.041441525, 0.029935953, 0.018314987, 0.0066811877, -0.0048616765, -0.016209689, -0.027259848, -0.037911124, -0.048065512, -0.05762905, -0.066512804, -0.0746338, -0.081915903, -0.088290621, -0.09369783, -0.098086416, -0.10141482, -0.10365146, -0.10477512, -0.10477512, -0.10365146, -0.10141482, -0.098086416, -0.09369783, -0.088290621, -0.081915903, -0.0746338, -0.066512804, -0.05762905, -0.048065512, -0.037911124, -0.027259848, -0.016209689, -0.0048616765, 0.0066811877, 0.018314987, 0.029935953, 0.041441525, 0.052731374, 0.063708406, 0.074279719, 0.084357497, 0.093859853, 0.10271159, 0.11084487, 0.11819984, 0.1247251, 0.13037812, 0.13512554, 0.13894336, 0.14181704, 0.14374148, 0.1447209, 0.14476863, 0.14390678, 0.14216587, 0.13958427, 0.13620771, 0.13208858, 0.12728523, 0.12186124, 0.1158846, 0.10942687, 0.10256232, 0.095367076, 0.087918235, 0.080292992, 0.072567801, 0.064817553], [0.14985551, 0.15512305, 0.15931467, 0.16236806, 0.16423291, 0.16487165, 0.16426009, 0.1623879, 0.1592589, 0.15489114, 0.14931693, 0.14258255, 0.13474785, 0.1258857, 0.11608124, 0.10543095, 0.094041635, 0.082029213, 0.069517411, 0.056636348, 0.043521028, 0.030309756, 0.017142511, 0.0041592774, -0.0085016282, -0.020705223, -0.032321494, -0.043226982, -0.053306291, -0.062453515, -0.070573544, -0.077583253, -0.083412547, -0.088005244, -0.091319802, -0.093329861, -0.094024602, -0.093408915, -0.091503383, -0.08834406, -0.08398207, -0.078483012, -0.071926192, -0.064403681, -0.056019215, -0.046886954, -0.037130106, -0.026879442, -0.016271713, -0.005448, 0.005448, 0.016271713, 0.026879442, 0.037130106, 0.046886954, 0.056019215, 0.064403681, 0.071926192, 0.078483012, 0.08398207, 0.08834406, 0.091503383, 0.093408915, 0.094024602, 0.093329861, 0.091319802, 0.088005244, 0.083412547, 0.077583253, 0.070573544, 0.062453515, 0.053306291, 0.043226982, 0.032321494, 0.020705223, 0.0085016282, -0.0041592774, -0.017142511, -0.030309756, -0.043521028, -0.056636348, -0.069517411, -0.082029213, -0.094041635, -0.10543095, -0.11608124, -0.1258857, -0.13474785, -0.14258255, -0.14931693, -0.15489114, -0.1592589, -0.1623879, -0.16426009, -0.16487165, -0.16423291, -0.16236806, -0.15931467, -0.15512305, -0.14985551]], [0.999943140, 0.997571533, 0.959465463, 0.721862496]), # noqa: E501 +} + + +@make_xp_test_case(windows.dpss) +class TestDPSS: + + def test_basic(self, xp): + # Test against hardcoded data + for k, v in dpss_data.items(): + win, ratios = windows.dpss(*k, return_ratios=True, xp=xp) + xp_assert_close(win, v[0], atol=1e-7, err_msg=k) + xp_assert_close(ratios, v[1], rtol=1e-5, atol=1e-7, err_msg=k) + + def test_unity(self, xp): + # Test unity value handling (gh-2221) + for M in range(1, 21): + # corrected w/approximation (default) + win = windows.dpss(M, M / 2.1, xp=xp) + expected = M % 2 # one for odd, none for even + xp_assert_equal(np.isclose(win, 1.).sum(), expected, + err_msg=f'{win}') + # corrected w/subsample delay (slower) + win_sub = windows.dpss(M, M / 2.1, norm='subsample', xp=xp) + if M > 2: + # @M=2 the subsample doesn't do anything + xp_assert_equal(np.isclose(win_sub, 1.).sum(), expected, + err_msg=f'{win_sub}') + xp_assert_close(win, win_sub, rtol=0.03) # within 3% + # not the same, l2-norm + win_2 = windows.dpss(M, M / 2.1, norm=2, xp=xp) + expected = 1 if M == 1 else 0 + xp_assert_equal(np.isclose(win_2, 1.).sum(), expected, + err_msg=f'{win_2}') + + def test_extremes(self, xp): + # Test extremes of alpha + lam = windows.dpss(31, 6, 4, return_ratios=True, xp=xp)[1] + xp_assert_close(lam, xp.ones_like(lam)) + lam = windows.dpss(31, 7, 4, return_ratios=True, xp=xp)[1] + xp_assert_close(lam, xp.ones_like(lam)) + lam = windows.dpss(31, 8, 4, return_ratios=True, xp=xp)[1] + xp_assert_close(lam, xp.ones_like(lam)) + + def test_degenerate(self, xp): + # Test failures + assert_raises(ValueError, windows.dpss, 4, 1.5, -1) # Bad Kmax + assert_raises(ValueError, windows.dpss, 4, 1.5, -5) + assert_raises(TypeError, windows.dpss, 4, 1.5, 1.1) + assert_raises(ValueError, windows.dpss, 3, 1.5, 3) # NW must be < N/2. + assert_raises(ValueError, windows.dpss, 3, -1, 3) # NW must be pos + assert_raises(ValueError, windows.dpss, 3, 0, 3) + assert_raises(ValueError, windows.dpss, -1, 1, 3) # negative M + + @skip_xp_backends(np_only=True) + def test_degenerate_signle_samples(self, xp): + # Single samples + w = windows.dpss(1, 1.) + xp_assert_equal(w, [1.]) + w, ratio = windows.dpss(1, 1., return_ratios=True) + xp_assert_equal(w, [1.]) + assert ratio == 1. + w, ratio = windows.dpss(1, 1., Kmax=4, return_ratios=True) + xp_assert_equal(w, [1.]) + assert isinstance(ratio, np.ndarray) + xp_assert_equal(ratio, [1.]) + + assert_raises(ValueError, windows.dpss, 4, 1.5, -1, xp=xp) # Bad Kmax + assert_raises(ValueError, windows.dpss, 4, 1.5, -5, xp=xp) + assert_raises(TypeError, windows.dpss, 4, 1.5, 1.1, xp=xp) + assert_raises(ValueError, windows.dpss, 3, 1.5, 3, xp=xp) # NW must be < N/2. + assert_raises(ValueError, windows.dpss, 3, -1, 3, xp=xp) # NW must be pos + assert_raises(ValueError, windows.dpss, 3, 0, 3, xp=xp) + assert_raises(ValueError, windows.dpss, -1, 1, 3, xp=xp) # negative M + + +@make_xp_test_case(windows.lanczos) +class TestLanczos: + + def test_basic(self, xp): + # Analytical results: + # sinc(x) = sinc(-x) + # sinc(pi) = 0, sinc(0) = 1 + # Hand computation on WolframAlpha: + # sinc(2 pi / 3) = 0.413496672 + # sinc(pi / 3) = 0.826993343 + # sinc(3 pi / 5) = 0.504551152 + # sinc(pi / 5) = 0.935489284 + xp_assert_close(windows.lanczos(6, sym=False, xp=xp), + xp.asarray([0., 0.413496672, + 0.826993343, 1., 0.826993343, + 0.413496672], dtype=xp.float64), + atol=1e-9) + xp_assert_close(windows.lanczos(6, xp=xp), + xp.asarray([0., 0.504551152, + 0.935489284, 0.935489284, + 0.504551152, 0.], dtype=xp.float64), + atol=1e-9) + xp_assert_close(windows.lanczos(7, sym=True, xp=xp), + xp.asarray([0., 0.413496672, + 0.826993343, 1., 0.826993343, + 0.413496672, 0.], dtype=xp.float64), + atol=1e-9) + + def test_array_size(self, xp): + for n in [0, 10, 11]: + assert windows.lanczos(n, sym=False, xp=xp).shape[0] == n + assert windows.lanczos(n, sym=True, xp=xp).shape[0] == n + + +@make_xp_test_case(windows.get_window) +class TestGetWindow: + """Unit test for `scipy.signal.get_windows`. """ + + def test_WIN_FUNC_DATA_integrity(self): + """Verify that the `_windows._WIN_FUNC_DATA` dict is consistent. + + The keys of _WIN_FUNC_DATA are made of tuples of strings of allowed window + names. Its values are 2-tuples made up of the window function and a + entry characterizing the existence of window parameters as ``True``, + ``False`` or ``'OPTIONAL'``. + + + It is verified that the correct window name (i.e., corresponding to the + function in the value tuple) is included in the key tuple. It is also checked + that the second entry in the value tuple is either ``True``, ``False`` or + ``'OPTIONAL'``. + """ + for nn_, v_ in _WIN_FUNC_DATA.items(): + func_name = v_[0].__name__ + msg = f"Function name in {nn_} does not contain name of actual function!" + assert func_name in nn_, msg + assert v_[1] in (True, False, 'OPTIONAL') + + @make_xp_test_case(windows.boxcar) + def test_boxcar(self, xp): + w = windows.get_window('boxcar', 12, xp=xp) + xp_assert_equal(w, xp.ones_like(w)) + + # window is a tuple of len 1 + w = windows.get_window(('boxcar',), 16, xp=xp) + xp_assert_equal(w, xp.ones_like(w)) + + @make_xp_test_case(windows.chebwin) + def test_cheb_odd(self, xp): + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "This window is not suitable", UserWarning) + w = windows.get_window(('chebwin', -40), 53, fftbins=False, xp=xp) + assert_array_almost_equal( + w, xp.asarray(cheb_odd_true, dtype=xp.float64), decimal=4 + ) + + @make_xp_test_case(windows.chebwin) + def test_cheb_even(self, xp): + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "This window is not suitable", UserWarning) + w = windows.get_window(('chebwin', 40), 54, fftbins=False, xp=xp) + assert_array_almost_equal(w, xp.asarray(cheb_even_true), decimal=4) + + @make_xp_test_case(windows.dpss) + def test_dpss(self, xp): + win1 = windows.get_window(('dpss', 3), 64, fftbins=False, xp=xp) + win2 = windows.dpss(64, 3, xp=xp) + xp_assert_equal(win1, win2) + + @make_xp_test_case(windows.kaiser) + def test_kaiser_float(self, xp): + win1 = windows.get_window(7.2, 64, xp=xp) + win2 = windows.kaiser(64, 7.2, False, xp=xp) + if is_jax(xp): + # On JAX with jit enabled, there is a very small discrepancy + # in the results. + xp_assert_close(win1, win2, rtol=xp.finfo(win1.dtype).eps) + else: + xp_assert_equal(win1, win2) + + @pytest.mark.parametrize('Nx', [-1, 3.0, np.float64(3)]) + @make_xp_test_case(windows.hann) + def test_invalid_parameter_NX(self, Nx, xp): + with pytest.raises(ValueError, match="^Parameter Nx=.*"): + windows.get_window('hann', Nx, xp=xp) + + # noinspection PyTypeChecker + def test_invalid_inputs(self, xp): + """Raise all exceptions (except those concerning parameter `Nx`). """ + with pytest.raises(ValueError, match="^Parameter fftbins=.*"): + windows.get_window('hann', 5, fftbins=1, xp=xp) + with pytest.raises(ValueError, match="^Parameter window=.*"): + windows.get_window(['hann',], 5, xp=xp) + with pytest.raises(ValueError, match="^First tuple entry of parameter win.*"): + windows.get_window((42,), 5, xp=xp) + with pytest.raises(ValueError, match="^Invalid window name 'INVALID'.*"): + windows.get_window('INVALID', 5, xp=xp) + with pytest.raises(ValueError, match="^'hann' does not allow parameters.*"): + windows.get_window(('hann', 1), 5, xp=xp) + with pytest.raises(ValueError, match="^'kaiser' must have parameters.*"): + windows.get_window('kaiser', 5, xp=xp) + with pytest.raises(ValueError, match="^Window dpss must have one.*"): + windows.get_window(('dpss', 1, 2), 5, xp=xp) + with pytest.raises(ValueError, match="^'general_cosine' does not accept.*"): + xp_ = xp or np # ensure parameter xp_ is not None + windows.get_window(('general cosine', [1, 2]), 5, xp=xp_) + + @make_xp_test_case(windows.bartlett) + def test_symmetric_periodic(self, xp): + """Ensure that suffixes `_periodic` and `_symmetric` work for window names. """ + w_sym = windows.bartlett(5, sym=True, xp=xp) + xp_assert_close(get_window('bartlett', 5, fftbins=False, xp=xp), w_sym) + xp_assert_close(get_window('bartlett_symmetric', 5, xp=xp), w_sym) + # overwrite parameter `fftbins`: + xp_assert_close(get_window('bartlett_symmetric', 5, fftbins=True, xp=xp), w_sym) + + w_per = windows.bartlett(5, sym=False, xp=xp) + xp_assert_close(get_window('bartlett', 5, xp=xp), w_per) + xp_assert_close(get_window('bartlett', 5, fftbins=True, xp=xp), w_per) + xp_assert_close(get_window('bartlett_periodic', 5, xp=xp), w_per) + # overwrite parameter `fftbins`: + xp_assert_close(get_window('bartlett_periodic', 5, fftbins=False, xp=xp), + w_per) + + @make_xp_test_case(windows.kaiser) + def test_array_as_window(self, xp): + # github issue 3603 + osfactor = 128 + sig = xp.arange(128) + + win = windows.get_window(('kaiser', 8.0), osfactor // 2, xp=xp) + mesg = "^window must" if is_cupy(xp) else "^window.shape=" + with assert_raises(ValueError, match=mesg): + resample(sig, sig.shape[0] * osfactor, window=win) + + @make_xp_test_case(windows.general_cosine) + def test_general_cosine(self, xp): + xp_assert_close(get_window(('general_cosine', xp.asarray([0.5, 0.3, 0.2])), 4), + xp.asarray([0.4, 0.3, 1, 0.3], dtype=xp.float64)) + xp_assert_close(get_window(('general_cosine', xp.asarray([0.5, 0.3, 0.2])), 4, + fftbins=False), + xp.asarray([0.4, 0.55, 0.55, 0.4], dtype=xp.float64)) + + with pytest.raises(ValueError): + get_window(('general_cosine', [0.5, 0.3, 0.2]), 4, xp=xp) + + @make_xp_test_case(windows.general_hamming) + def test_general_hamming(self, xp): + xp_assert_close(get_window(('general_hamming', 0.7), 5, xp=xp), + xp.asarray([0.4, 0.6072949, 0.9427051, 0.9427051, 0.6072949], + dtype=xp.float64)) + xp_assert_close(get_window(('general_hamming', 0.7), 5, fftbins=False, xp=xp), + xp.asarray([0.4, 0.7, 1.0, 0.7, 0.4], dtype=xp.float64)) + + @make_xp_test_case(windows.lanczos) + def test_lanczos(self, xp): + xp_assert_close(get_window('lanczos', 6, xp=xp), + xp.asarray([0., 0.413496672, 0.826993343, 1., 0.826993343, + 0.413496672], dtype=xp.float64), atol=1e-9) + xp_assert_close(get_window('lanczos', 6, fftbins=False, xp=xp), + xp.asarray([0., 0.504551152, 0.935489284, 0.935489284, + 0.504551152, 0.], dtype=xp.float64), atol=1e-9) + xp_assert_close(get_window('lanczos', 6, xp=xp), + get_window('sinc', 6, xp=xp)) + + def test_xp_default(self, xp): + # no explicit xp= argument, default to numpy + win = get_window('lanczos', 6) + assert isinstance(win, np.ndarray) + + win = get_window('lanczos', 6, xp=xp) + if not is_numpy(xp): + assert not isinstance(win, np.ndarray) + + +@skip_xp_backends("dask.array", reason="https://github.com/dask/dask/issues/2620") +@pytest.mark.parametrize( + "window,window_name,params", + [ + make_xp_pytest_param(getattr(windows, window_name), window_name, params) + for window_name, params in window_funcs + ] +) +def test_windowfunc_basics(window, window_name, params, xp): + window = getattr(windows, window_name) + if is_jax(xp) and window_name in ['taylor', 'chebwin']: + pytest.skip(reason=f'{window_name = }: item assignment') + if window_name in ['dpss']: + if is_cupy(xp): + pytest.skip(reason='dpss window is not implemented for cupy') + if is_torch(xp) and SCIPY_DEVICE != 'cpu': + pytest.skip(reason='needs eight_tridiagonal which is CPU only') + + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "This window is not suitable", UserWarning) + # Check symmetry for odd and even lengths + w1 = window(8, *params, sym=True, xp=xp) + w2 = window(7, *params, sym=False, xp=xp) + xp_assert_close(w1[:-1], w2) + + w1 = window(9, *params, sym=True, xp=xp) + w2 = window(8, *params, sym=False, xp=xp) + xp_assert_close(w1[:-1], w2) + + # Check that functions run and output lengths are correct + assert window(6, *params, sym=True, xp=xp).shape[0] == 6 + assert window(6, *params, sym=False, xp=xp).shape[0] == 6 + assert window(7, *params, sym=True, xp=xp).shape[0] == 7 + assert window(7, *params, sym=False, xp=xp).shape[0] == 7 + + # Check invalid lengths + assert_raises(ValueError, window, 5.5, *params, xp=xp) + assert_raises(ValueError, window, -7, *params, xp=xp) + + # Check degenerate cases + xp_assert_equal(window(0, *params, sym=True, xp=xp), + xp.asarray([], dtype=xp.float64)) + xp_assert_equal(window(0, *params, sym=False, xp=xp), + xp.asarray([], dtype=xp.float64)) + xp_assert_equal(window(1, *params, sym=True, xp=xp), + xp.asarray([1.], dtype=xp.float64)) + xp_assert_equal(window(1, *params, sym=False, xp=xp), + xp.asarray([1.], dtype=xp.float64)) + + # Check dtype + assert window(0, *params, sym=True, xp=xp).dtype == xp.float64 + assert window(0, *params, sym=False, xp=xp).dtype == xp.float64 + assert window(1, *params, sym=True, xp=xp).dtype == xp.float64 + assert window(1, *params, sym=False, xp=xp).dtype == xp.float64 + assert window(6, *params, sym=True, xp=xp).dtype == xp.float64 + assert window(6, *params, sym=False, xp=xp).dtype == xp.float64 + + # Check normalization + assert xp.all(window(10, *params, sym=True, xp=xp) < 1.01) + assert xp.all(window(10, *params, sym=False, xp=xp) < 1.01) + assert xp.all(window(9, *params, sym=True, xp=xp) < 1.01) + assert xp.all(window(9, *params, sym=False, xp=xp) < 1.01) + + # Check that DFT-even spectrum is purely real for odd and even + res = fft(window(10, *params, sym=False, xp=xp)) + res = xp.imag(res) + xp_assert_close(res, xp.zeros_like(res), atol=1e-14) + + res = fft(window(11, *params, sym=False, xp=xp)) + res = xp.imag(res) + xp_assert_close(res, xp.zeros_like(res), atol=1e-14) + + +@make_xp_test_case(get_window) +def test_needs_params(xp): + for winstr in ['kaiser', 'ksr', 'kaiser_bessel_derived', 'kbd', + 'gaussian', 'gauss', 'gss', + 'general gaussian', 'general_gaussian', + 'general gauss', 'general_gauss', 'ggs', + 'dss', 'dpss', 'general cosine', 'general_cosine', + 'chebwin', 'cheb', 'general hamming', 'general_hamming', + ]: + assert_raises(ValueError, get_window, winstr, 7, xp=xp) + + +_winstr = ['barthann', + 'bartlett', + 'blackman', + 'blackmanharris', + 'bohman', + 'boxcar', + 'cosine', + 'flattop', + 'hamming', + 'nuttall', + 'parzen', + 'taylor', + 'exponential', + 'poisson', + 'tukey', + 'tuk', + 'triangle', + 'lanczos', + 'sinc', +] + + +@pytest.mark.parametrize( + 'window,winstr', + [ + make_xp_pytest_param(_WIN_FUNCS[winstr][0], winstr) + for winstr in _winstr + ] +) +@make_xp_test_case(get_window) +def test_not_needs_params(xp, window, winstr): + if is_jax(xp) and winstr in ['taylor']: + pytest.skip(reason=f'{winstr}: item assignment') + win = get_window(winstr, 7, xp=xp) + assert win.shape[0] == 7 + + +@make_xp_test_case(windows.lanczos) +def test_symmetric(xp): + + for win in [windows.lanczos]: + # Even sampling points + w = win(4096, xp=xp) + flip = array_namespace(w).flip + error = xp.max(xp.abs(w - flip(w))) + xp_assert_equal(error, xp.asarray(0.0), check_dtype=False, check_0d=False) + + # Odd sampling points + w = win(4097, xp=xp) + error = xp.max(xp.abs(w - flip(w))) + xp_assert_equal(error, xp.asarray(0.0), check_dtype=False, check_0d=False) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/windows/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/windows/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..f260df1367a5f9457b1f6e916def853c6c461924 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/windows/__init__.py @@ -0,0 +1,52 @@ +""" +Window functions (:mod:`scipy.signal.windows`) +============================================== + +The suite of window functions for filtering and spectral estimation. + +.. currentmodule:: scipy.signal.windows + +.. autosummary:: + :toctree: generated/ + + get_window -- Convenience function for creating various windows. + + barthann -- Bartlett-Hann window + bartlett -- Bartlett window + blackman -- Blackman window + blackmanharris -- Minimum 4-term Blackman-Harris window + bohman -- Bohman window + boxcar -- Boxcar window + chebwin -- Dolph-Chebyshev window + cosine -- Cosine window + dpss -- Discrete prolate spheroidal sequences + exponential -- Exponential window + flattop -- Flat top window + gaussian -- Gaussian window + general_cosine -- Generalized Cosine window + general_gaussian -- Generalized Gaussian window + general_hamming -- Generalized Hamming window + hamming -- Hamming window + hann -- Hann window + kaiser -- Kaiser window + kaiser_bessel_derived -- Kaiser-Bessel derived window + lanczos -- Lanczos window also known as a sinc window + nuttall -- Nuttall's minimum 4-term Blackman-Harris window + parzen -- Parzen window + taylor -- Taylor window + triang -- Triangular window + tukey -- Tukey window + +""" + +from ._windows import * + +# Deprecated namespaces, to be removed in v2.0.0 +from . import windows + +__all__ = ['boxcar', 'triang', 'parzen', 'bohman', 'blackman', 'nuttall', + 'blackmanharris', 'flattop', 'bartlett', 'barthann', + 'hamming', 'kaiser', 'kaiser_bessel_derived', 'gaussian', + 'general_gaussian', 'general_cosine', 'general_hamming', + 'chebwin', 'cosine', 'hann', 'exponential', 'tukey', 'taylor', + 'get_window', 'dpss', 'lanczos'] diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/windows/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/windows/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9b83508dd8fe565ed7735a9a19b3f9cbcaaae4a5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/windows/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/windows/__pycache__/windows.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/windows/__pycache__/windows.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..084033ff503490d4806b8b5ba1047eb9ac011501 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/windows/__pycache__/windows.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/windows/_windows.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/windows/_windows.py new file mode 100644 index 0000000000000000000000000000000000000000..e3d341a1cecddccee740e1399f635c0994c86520 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/windows/_windows.py @@ -0,0 +1,2608 @@ +"""The suite of window functions.""" + +import math +import numbers +import operator +import warnings +from scipy._lib import doccer + +from scipy import linalg, special, fft as sp_fft +from scipy._lib.array_api_compat import numpy as np_compat +from scipy._lib._array_api import array_namespace, xp_device +from scipy._lib._array_api import xp_capabilities +from scipy._lib import array_api_extra as xpx + +__all__ = ['boxcar', 'triang', 'parzen', 'bohman', 'blackman', 'nuttall', + 'blackmanharris', 'flattop', 'bartlett', 'barthann', + 'hamming', 'kaiser', 'kaiser_bessel_derived', 'gaussian', + 'general_cosine', 'general_gaussian', 'general_hamming', + 'chebwin', 'cosine', 'hann', 'exponential', 'tukey', 'taylor', + 'dpss', 'get_window', 'lanczos'] + + +def _len_guards(M): + """Handle small or incorrect window lengths""" + if int(M) != M or M < 0: + raise ValueError('Window length M must be a non-negative integer') + return M <= 1 + + +def _extend(M, sym): + """Extend window by 1 sample if needed for DFT-even symmetry""" + if not sym: + return M + 1, True + else: + return M, False + + +def _truncate(w, needed): + """Truncate window by 1 sample if needed for DFT-even symmetry""" + if needed: + return w[:-1] + else: + return w + + +def _namespace(xp): + """A shim for the `device` arg of `np.asarray(x, device=device)` and acos/arccos. + + Will be able to replace with `np_compat if xp is None else xp` when we drop + support for numpy 1.x and cupy 13.x + """ + return np_compat if xp is None else array_namespace(xp.empty(0)) + + +def _general_cosine_impl(M, a, xp, device, sym=True): + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + M, needs_trunc = _extend(M, sym) + + fac = xp.linspace(-xp.pi, xp.pi, M, dtype=xp.float64, device=device) + w = xp.zeros(M, dtype=xp.float64, device=device) + for k in range(a.shape[0]): + w += a[k] * xp.cos(k * fac) + + return _truncate(w, needs_trunc) + + +@xp_capabilities() +def general_cosine(M, a, sym=True): + r""" + Generic weighted sum of cosine terms window + + Parameters + ---------- + M : int + Number of points in the output window + a : array_like + Sequence of weighting coefficients. This uses the convention of being + centered on the origin, so these will typically all be positive + numbers, not alternating sign. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + + Returns + ------- + w : ndarray + The array of window values. + + References + ---------- + .. [1] A. Nuttall, "Some windows with very good sidelobe behavior," IEEE + Transactions on Acoustics, Speech, and Signal Processing, vol. 29, + no. 1, pp. 84-91, Feb 1981. :doi:`10.1109/TASSP.1981.1163506`. + .. [2] Heinzel G. et al., "Spectrum and spectral density estimation by the + Discrete Fourier transform (DFT), including a comprehensive list of + window functions and some new flat-top windows", February 15, 2002 + https://holometer.fnal.gov/GH_FFT.pdf + + Examples + -------- + Heinzel describes a flat-top window named "HFT90D" with formula: [2]_ + + .. math:: w_j = 1 - 1.942604 \cos(z) + 1.340318 \cos(2z) + - 0.440811 \cos(3z) + 0.043097 \cos(4z) + + where + + .. math:: z = \frac{2 \pi j}{N}, j = 0...N - 1 + + Since this uses the convention of starting at the origin, to reproduce the + window, we need to convert every other coefficient to a positive number: + + >>> HFT90D = [1, 1.942604, 1.340318, 0.440811, 0.043097] + + The paper states that the highest sidelobe is at -90.2 dB. Reproduce + Figure 42 by plotting the window and its frequency response, and confirm + the sidelobe level in red: + + >>> import numpy as np + >>> from scipy.signal.windows import general_cosine + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = general_cosine(1000, HFT90D, sym=False) + >>> plt.plot(window) + >>> plt.title("HFT90D window") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 10000) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = np.abs(fftshift(A / abs(A).max())) + >>> response = 20 * np.log10(np.maximum(response, 1e-10)) + >>> plt.plot(freq, response) + >>> plt.axis([-50/1000, 50/1000, -140, 0]) + >>> plt.title("Frequency response of the HFT90D window") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + >>> plt.axhline(-90.2, color='red') + >>> plt.show() + """ + xp = array_namespace(a) + a = xp.asarray(a) + device = xp_device(a) + return _general_cosine_impl(M, a, xp, device, sym=sym) + + +@xp_capabilities() +def boxcar(M, sym=True, *, xp=None, device=None): + """Return a boxcar or rectangular window. + + Also known as a rectangular window or Dirichlet window, this is equivalent + to no window at all. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + sym : bool, optional + Whether the window is symmetric. (Has no effect for boxcar.) + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1. + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.boxcar(51) + >>> plt.plot(window) + >>> plt.title("Boxcar window") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the boxcar window") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + xp = _namespace(xp) + + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + M, needs_trunc = _extend(M, sym) + + w = xp.ones(M, dtype=xp.float64, device=device) + + return _truncate(w, needs_trunc) + + +@xp_capabilities() +def triang(M, sym=True, *, xp=None, device=None): + """Return a triangular window. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + See Also + -------- + bartlett : A triangular window that touches zero + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.triang(51) + >>> plt.plot(window) + >>> plt.title("Triangular window") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = np.abs(fftshift(A / abs(A).max())) + >>> response = 20 * np.log10(np.maximum(response, 1e-10)) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the triangular window") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + xp = _namespace(xp) + + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + M, needs_trunc = _extend(M, sym) + + n = xp.arange(1, (M + 1) // 2 + 1, dtype=xp.float64, device=device) + if M % 2 == 0: + w = (2 * n - 1.0) / M + w = xp.concat([w, xp.flip(w)]) + else: + w = 2 * n / (M + 1.0) + w = xp.concat([w, xp.flip(w[:-1])]) + + return _truncate(w, needs_trunc) + + +@xp_capabilities() +def parzen(M, sym=True, *, xp=None, device=None): + """Return a Parzen window. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + References + ---------- + .. [1] E. Parzen, "Mathematical Considerations in the Estimation of + Spectra", Technometrics, Vol. 3, No. 2 (May, 1961), pp. 167-190 + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.parzen(51) + >>> plt.plot(window) + >>> plt.title("Parzen window") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the Parzen window") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + xp = _namespace(xp) + + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + M, needs_trunc = _extend(M, sym) + + n = xp.arange(-(M - 1) / 2.0, (M - 1) / 2.0 + 0.5, 1.0, + dtype=xp.float64, device=device) + w = xp.where(abs(n) <= (M - 1) / 4.0, + (1 - 6 * (abs(n) / (M / 2.0)) ** 2.0 + + 6 * (abs(n) / (M / 2.0)) ** 3.0), + 2 * (1 - abs(n) / (M / 2.0)) ** 3.0) + return _truncate(w, needs_trunc) + + +@xp_capabilities() +def bohman(M, sym=True, *, xp=None, device=None): + """Return a Bohman window. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.bohman(51) + >>> plt.plot(window) + >>> plt.title("Bohman window") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2047) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the Bohman window") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + xp = _namespace(xp) + + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + M, needs_trunc = _extend(M, sym) + + fac = abs(xp.linspace(-1, 1, M, dtype=xp.float64, device=device)[1:-1]) + w = (1 - fac) * xp.cos(xp.pi * fac) + 1.0 / xp.pi * xp.sin(xp.pi * fac) + one = xp.zeros(1, dtype=xp.float64, device=device) + w = xp.concat([one, w, one]) + + return _truncate(w, needs_trunc) + + +@xp_capabilities() +def blackman(M, sym=True, *, xp=None, device=None): + r""" + Return a Blackman window. + + The Blackman window is a taper formed by using the first three terms of + a summation of cosines. It was designed to have close to the minimal + leakage possible. It is close to optimal, only slightly worse than a + Kaiser window. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + Notes + ----- + The Blackman window is defined as + + .. math:: w(n) = 0.42 - 0.5 \cos(2\pi n/M) + 0.08 \cos(4\pi n/M) + + The "exact Blackman" window was designed to null out the third and fourth + sidelobes, but has discontinuities at the boundaries, resulting in a + 6 dB/oct fall-off. This window is an approximation of the "exact" window, + which does not null the sidelobes as well, but is smooth at the edges, + improving the fall-off rate to 18 dB/oct. [3]_ + + Most references to the Blackman window come from the signal processing + literature, where it is used as one of many windowing functions for + smoothing values. It is also known as an apodization (which means + "removing the foot", i.e. smoothing discontinuities at the beginning + and end of the sampled signal) or tapering function. It is known as a + "near optimal" tapering function, almost as good (by some measures) + as the Kaiser window. + + References + ---------- + .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power + spectra, Dover Publications, New York. + .. [2] Oppenheim, A.V., and R.W. Schafer. Discrete-Time Signal Processing. + Upper Saddle River, NJ: Prentice-Hall, 1999, pp. 468-471. + .. [3] Harris, Fredric J. (Jan 1978). "On the use of Windows for Harmonic + Analysis with the Discrete Fourier Transform". Proceedings of the + IEEE 66 (1): 51-83. :doi:`10.1109/PROC.1978.10837`. + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.blackman(51) + >>> plt.plot(window) + >>> plt.title("Blackman window") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = np.abs(fftshift(A / abs(A).max())) + >>> response = 20 * np.log10(np.maximum(response, 1e-10)) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the Blackman window") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + # Docstring adapted from NumPy's blackman function + xp = _namespace(xp) + a = xp.asarray([0.42, 0.50, 0.08], dtype=xp.float64, device=device) + device = xp_device(a) + return _general_cosine_impl(M, a, xp, device, sym=sym) + + +@xp_capabilities() +def nuttall(M, sym=True, *, xp=None, device=None): + """Return a minimum 4-term Blackman-Harris window according to Nuttall. + + This variation is called "Nuttall4c" by Heinzel. [2]_ + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + References + ---------- + .. [1] A. Nuttall, "Some windows with very good sidelobe behavior," IEEE + Transactions on Acoustics, Speech, and Signal Processing, vol. 29, + no. 1, pp. 84-91, Feb 1981. :doi:`10.1109/TASSP.1981.1163506`. + .. [2] Heinzel G. et al., "Spectrum and spectral density estimation by the + Discrete Fourier transform (DFT), including a comprehensive list of + window functions and some new flat-top windows", February 15, 2002 + https://holometer.fnal.gov/GH_FFT.pdf + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.nuttall(51) + >>> plt.plot(window) + >>> plt.title("Nuttall window") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the Nuttall window") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + xp = _namespace(xp) + a = xp.asarray( + [0.3635819, 0.4891775, 0.1365995, 0.0106411], dtype=xp.float64, device=device + ) + device = xp_device(a) + return _general_cosine_impl(M, a, xp, device, sym=sym) + + +@xp_capabilities() +def blackmanharris(M, sym=True, *, xp=None, device=None): + """Return a minimum 4-term Blackman-Harris window. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.blackmanharris(51) + >>> plt.plot(window) + >>> plt.title("Blackman-Harris window") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the Blackman-Harris window") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + xp = _namespace(xp) + a = xp.asarray( + [0.35875, 0.48829, 0.14128, 0.01168], dtype=xp.float64, device=device + ) + device = xp_device(a) + return _general_cosine_impl(M, a, xp, device, sym=sym) + + +@xp_capabilities() +def flattop(M, sym=True, *, xp=None, device=None): + """Return a flat top window. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + Notes + ----- + Flat top windows are used for taking accurate measurements of signal + amplitude in the frequency domain, with minimal scalloping error from the + center of a frequency bin to its edges, compared to others. This is a + 5th-order cosine window, with the 5 terms optimized to make the main lobe + maximally flat. [1]_ + + References + ---------- + .. [1] D'Antona, Gabriele, and A. Ferrero, "Digital Signal Processing for + Measurement Systems", Springer Media, 2006, p. 70 + :doi:`10.1007/0-387-28666-7`. + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.flattop(51) + >>> plt.plot(window) + >>> plt.title("Flat top window") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the flat top window") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + xp = _namespace(xp) + a = xp.asarray( + [0.21557895, 0.41663158, 0.277263158, 0.083578947, 0.006947368], + dtype=xp.float64, device=device + ) + device = xp_device(a) + return _general_cosine_impl(M, a, xp, device, sym=sym) + + +@xp_capabilities() +def bartlett(M, sym=True, *, xp=None, device=None): + r""" + Return a Bartlett window. + + The Bartlett window is very similar to a triangular window, except + that the end points are at zero. It is often used in signal + processing for tapering a signal, without generating too much + ripple in the frequency domain. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The triangular window, with the first and last samples equal to zero + and the maximum value normalized to 1 (though the value 1 does not + appear if `M` is even and `sym` is True). + + See Also + -------- + triang : A triangular window that does not touch zero at the ends + + Notes + ----- + The Bartlett window is defined as + + .. math:: w(n) = \frac{2}{M-1} \left( + \frac{M-1}{2} - \left|n - \frac{M-1}{2}\right| + \right) + + Most references to the Bartlett window come from the signal + processing literature, where it is used as one of many windowing + functions for smoothing values. Note that convolution with this + window produces linear interpolation. It is also known as an + apodization (which means"removing the foot", i.e. smoothing + discontinuities at the beginning and end of the sampled signal) or + tapering function. The Fourier transform of the Bartlett is the product + of two sinc functions. + Note the excellent discussion in Kanasewich. [2]_ + + References + ---------- + .. [1] M.S. Bartlett, "Periodogram Analysis and Continuous Spectra", + Biometrika 37, 1-16, 1950. + .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", + The University of Alberta Press, 1975, pp. 109-110. + .. [3] A.V. Oppenheim and R.W. Schafer, "Discrete-Time Signal + Processing", Prentice-Hall, 1999, pp. 468-471. + .. [4] Wikipedia, "Window function", + https://en.wikipedia.org/wiki/Window_function + .. [5] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling, + "Numerical Recipes", Cambridge University Press, 1986, page 429. + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.bartlett(51) + >>> plt.plot(window) + >>> plt.title("Bartlett window") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the Bartlett window") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + # Docstring adapted from NumPy's bartlett function + xp = _namespace(xp) + + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + M, needs_trunc = _extend(M, sym) + + n = xp.arange(0, M, dtype=xp.float64, device=device) + + # cf https://github.com/data-apis/array-api-strict/issues/77 + w = xp.where(n <= (M - 1) / 2.0, + 2.0 * n / (M - 1), 2.0 - 2.0 * n / (M - 1)) + + return _truncate(w, needs_trunc) + + +@xp_capabilities() +def hann(M, sym=True, *, xp=None, device=None): + r""" + Return a Hann window. + + The Hann window is a taper formed by using a raised cosine or sine-squared + with ends that touch zero. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + Notes + ----- + The Hann window is defined as + + .. math:: w(n) = 0.5 - 0.5 \cos\left(\frac{2\pi{n}}{M-1}\right) + \qquad 0 \leq n \leq M-1 + + The window was named for Julius von Hann, an Austrian meteorologist. It is + also known as the Cosine Bell. It is sometimes erroneously referred to as + the "Hanning" window, from the use of "hann" as a verb in the original + paper and confusion with the very similar Hamming window. + + Most references to the Hann window come from the signal processing + literature, where it is used as one of many windowing functions for + smoothing values. It is also known as an apodization (which means + "removing the foot", i.e. smoothing discontinuities at the beginning + and end of the sampled signal) or tapering function. + + References + ---------- + .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power + spectra, Dover Publications, New York. + .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", + The University of Alberta Press, 1975, pp. 106-108. + .. [3] Wikipedia, "Window function", + https://en.wikipedia.org/wiki/Window_function + .. [4] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling, + "Numerical Recipes", Cambridge University Press, 1986, page 425. + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.hann(51) + >>> plt.plot(window) + >>> plt.title("Hann window") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = np.abs(fftshift(A / abs(A).max())) + >>> response = 20 * np.log10(np.maximum(response, 1e-10)) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the Hann window") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + # Docstring adapted from NumPy's hanning function + return general_hamming(M, 0.5, sym, xp=xp, device=device) + + +@xp_capabilities() +def tukey(M, alpha=0.5, sym=True, *, xp=None, device=None): + r"""Return a Tukey window, also known as a tapered cosine window. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + alpha : float, optional + Shape parameter of the Tukey window, representing the fraction of the + window inside the cosine tapered region. + If zero, the Tukey window is equivalent to a rectangular window. + If one, the Tukey window is equivalent to a Hann window. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + References + ---------- + .. [1] Harris, Fredric J. (Jan 1978). "On the use of Windows for Harmonic + Analysis with the Discrete Fourier Transform". Proceedings of the + IEEE 66 (1): 51-83. :doi:`10.1109/PROC.1978.10837` + .. [2] Wikipedia, "Window function", + https://en.wikipedia.org/wiki/Window_function#Tukey_window + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.tukey(51) + >>> plt.plot(window) + >>> plt.title("Tukey window") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + >>> plt.ylim([0, 1.1]) + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the Tukey window") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + xp = _namespace(xp) + + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + + if alpha <= 0: + return xp.ones(M, dtype=xp.float64, device=device) + elif alpha >= 1.0: + return hann(M, sym=sym, xp=xp, device=device) + + M, needs_trunc = _extend(M, sym) + + n = xp.arange(0, M, dtype=xp.float64, device=device) + width = int(math.floor(alpha*(M-1)/2.0)) + n1 = n[0:width+1] + n2 = n[width+1:M-width-1] + n3 = n[M-width-1:] + + w1 = 0.5 * (1 + xp.cos(xp.pi * (-1 + 2.0*n1/alpha/(M-1)))) + w2 = xp.ones(n2.shape, device=device) + w3 = 0.5 * (1 + xp.cos(xp.pi * (-2.0/alpha + 1 + 2.0*n3/alpha/(M-1)))) + + w = xp.concat((w1, w2, w3)) + + return _truncate(w, needs_trunc) + + +@xp_capabilities() +def barthann(M, sym=True, *, xp=None, device=None): + """Return a modified Bartlett-Hann window. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.barthann(51) + >>> plt.plot(window) + >>> plt.title("Bartlett-Hann window") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the Bartlett-Hann window") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + xp = _namespace(xp) + + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + M, needs_trunc = _extend(M, sym) + + n = xp.arange(0, M, dtype=xp.float64, device=device) + fac = abs(n / (M - 1.0) - 0.5) + w = 0.62 - 0.48 * fac + 0.38 * xp.cos(2 * xp.pi * fac) + + return _truncate(w, needs_trunc) + + +@xp_capabilities() +def general_hamming(M, alpha, sym=True, *, xp=None, device=None): + r"""Return a generalized Hamming window. + + The generalized Hamming window is constructed by multiplying a rectangular + window by one period of a cosine function [1]_. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + alpha : float + The window coefficient, :math:`\alpha` + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + See Also + -------- + hamming, hann + + Notes + ----- + The generalized Hamming window is defined as + + .. math:: w(n) = \alpha - \left(1 - \alpha\right) + \cos\left(\frac{2\pi{n}}{M-1}\right) \qquad 0 \leq n \leq M-1 + + Both the common Hamming window and Hann window are special cases of the + generalized Hamming window with :math:`\alpha` = 0.54 and :math:`\alpha` = + 0.5, respectively [2]_. + + References + ---------- + .. [1] DSPRelated, "Generalized Hamming Window Family", + https://www.dsprelated.com/freebooks/sasp/Generalized_Hamming_Window_Family.html + .. [2] Wikipedia, "Window function", + https://en.wikipedia.org/wiki/Window_function + .. [3] Riccardo Piantanida ESA, "Sentinel-1 Level 1 Detailed Algorithm + Definition", + https://sentinel.esa.int/documents/247904/1877131/Sentinel-1-Level-1-Detailed-Algorithm-Definition + .. [4] Matthieu Bourbigot ESA, "Sentinel-1 Product Definition", + https://sentinel.esa.int/documents/247904/1877131/Sentinel-1-Product-Definition + + Examples + -------- + The Sentinel-1A/B Instrument Processing Facility uses generalized Hamming + windows in the processing of spaceborne Synthetic Aperture Radar (SAR) + data [3]_. The facility uses various values for the :math:`\alpha` + parameter based on operating mode of the SAR instrument. Some common + :math:`\alpha` values include 0.75, 0.7 and 0.52 [4]_. As an example, we + plot these different windows. + + >>> import numpy as np + >>> from scipy.signal.windows import general_hamming + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> fig1, spatial_plot = plt.subplots() + >>> spatial_plot.set_title("Generalized Hamming Windows") + >>> spatial_plot.set_ylabel("Amplitude") + >>> spatial_plot.set_xlabel("Sample") + + >>> fig2, freq_plot = plt.subplots() + >>> freq_plot.set_title("Frequency Responses") + >>> freq_plot.set_ylabel("Normalized magnitude [dB]") + >>> freq_plot.set_xlabel("Normalized frequency [cycles per sample]") + + >>> for alpha in [0.75, 0.7, 0.52]: + ... window = general_hamming(41, alpha) + ... spatial_plot.plot(window, label="{:.2f}".format(alpha)) + ... A = fft(window, 2048) / (len(window)/2.0) + ... freq = np.linspace(-0.5, 0.5, len(A)) + ... response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + ... freq_plot.plot(freq, response, label="{:.2f}".format(alpha)) + >>> freq_plot.legend(loc="upper right") + >>> spatial_plot.legend(loc="upper right") + + """ + xp = _namespace(xp) + a = xp.asarray([alpha, 1. - alpha], dtype=xp.float64, device=device) + device = xp_device(a) + return _general_cosine_impl(M, a, xp, device, sym=sym) + + +@xp_capabilities() +def hamming(M, sym=True, *, xp=None, device=None): + r"""Return a Hamming window. + + The Hamming window is a taper formed by using a raised cosine with + non-zero endpoints, optimized to minimize the nearest side lobe. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + Notes + ----- + The Hamming window is defined as + + .. math:: w(n) = 0.54 - 0.46 \cos\left(\frac{2\pi{n}}{M-1}\right) + \qquad 0 \leq n \leq M-1 + + The Hamming was named for R. W. Hamming, an associate of J. W. Tukey and + is described in Blackman and Tukey. It was recommended for smoothing the + truncated autocovariance function in the time domain. + Most references to the Hamming window come from the signal processing + literature, where it is used as one of many windowing functions for + smoothing values. It is also known as an apodization (which means + "removing the foot", i.e. smoothing discontinuities at the beginning + and end of the sampled signal) or tapering function. + + References + ---------- + .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power + spectra, Dover Publications, New York. + .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", The + University of Alberta Press, 1975, pp. 109-110. + .. [3] Wikipedia, "Window function", + https://en.wikipedia.org/wiki/Window_function + .. [4] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling, + "Numerical Recipes", Cambridge University Press, 1986, page 425. + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.hamming(51) + >>> plt.plot(window) + >>> plt.title("Hamming window") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the Hamming window") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + # Docstring adapted from NumPy's hamming function + return general_hamming(M, 0.54, sym, xp=xp, device=device) + + +@xp_capabilities() +def kaiser(M, beta, sym=True, *, xp=None, device=None): + r"""Return a Kaiser window. + + The Kaiser window is a taper formed by using a Bessel function. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + beta : float + Shape parameter, determines trade-off between main-lobe width and + side lobe level. As beta gets large, the window narrows. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + Notes + ----- + The Kaiser window is defined as + + .. math:: w(n) = I_0\left( \beta \sqrt{1-\frac{4n^2}{(M-1)^2}} + \right)/I_0(\beta) + + with + + .. math:: \quad -\frac{M-1}{2} \leq n \leq \frac{M-1}{2}, + + where :math:`I_0` is the modified zeroth-order Bessel function. + + The Kaiser was named for Jim Kaiser, who discovered a simple approximation + to the DPSS window based on Bessel functions. + The Kaiser window is a very good approximation to the discrete prolate + spheroidal sequence, or Slepian window, which is the transform which + maximizes the energy in the main lobe of the window relative to total + energy. + + The Kaiser can approximate other windows by varying the beta parameter. + (Some literature uses alpha = beta/pi.) [4]_ + + ==== ======================= + beta Window shape + ==== ======================= + 0 Rectangular + 5 Similar to a Hamming + 6 Similar to a Hann + 8.6 Similar to a Blackman + ==== ======================= + + A beta value of 14 is probably a good starting point. Note that as beta + gets large, the window narrows, and so the number of samples needs to be + large enough to sample the increasingly narrow spike, otherwise NaNs will + be returned. + + Most references to the Kaiser window come from the signal processing + literature, where it is used as one of many windowing functions for + smoothing values. It is also known as an apodization (which means + "removing the foot", i.e. smoothing discontinuities at the beginning + and end of the sampled signal) or tapering function. + + References + ---------- + .. [1] J. F. Kaiser, "Digital Filters" - Ch 7 in "Systems analysis by + digital computer", Editors: F.F. Kuo and J.F. Kaiser, p 218-285. + John Wiley and Sons, New York, (1966). + .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", The + University of Alberta Press, 1975, pp. 177-178. + .. [3] Wikipedia, "Window function", + https://en.wikipedia.org/wiki/Window_function + .. [4] F. J. Harris, "On the use of windows for harmonic analysis with the + discrete Fourier transform," Proceedings of the IEEE, vol. 66, + no. 1, pp. 51-83, Jan. 1978. :doi:`10.1109/PROC.1978.10837`. + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.kaiser(51, beta=14) + >>> plt.plot(window) + >>> plt.title(r"Kaiser window ($\beta$=14)") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title(r"Frequency response of the Kaiser window ($\beta$=14)") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + xp = _namespace(xp) + + # Docstring adapted from NumPy's kaiser function + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + M, needs_trunc = _extend(M, sym) + + n = xp.arange(0, M, dtype=xp.float64, device=device) + alpha = (M - 1) / 2.0 + w = (special.i0(beta * xp.sqrt(1 - ((n - alpha) / alpha) ** 2.0)) / + special.i0(xp.asarray(beta, dtype=xp.float64))) + + return _truncate(w, needs_trunc) + + +@xp_capabilities() +def kaiser_bessel_derived(M, beta, *, sym=True, xp=None, device=None): + """Return a Kaiser-Bessel derived window. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + Note that this window is only defined for an even + number of points. + beta : float + Kaiser window shape parameter. + sym : bool, optional + This parameter only exists to comply with the interface offered by + the other window functions and to be callable by `get_window`. + When True (default), generates a symmetric window, for use in filter + design. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, normalized to fulfil the Princen-Bradley condition. + + See Also + -------- + kaiser + + Notes + ----- + It is designed to be suitable for use with the modified discrete cosine + transform (MDCT) and is mainly used in audio signal processing and + audio coding. + + .. versionadded:: 1.9.0 + + References + ---------- + .. [1] Bosi, Marina, and Richard E. Goldberg. Introduction to Digital + Audio Coding and Standards. Dordrecht: Kluwer, 2003. + .. [2] Wikipedia, "Kaiser window", + https://en.wikipedia.org/wiki/Kaiser_window + + Examples + -------- + Plot the Kaiser-Bessel derived window based on the wikipedia + reference [2]_: + + >>> import numpy as np + >>> from scipy import signal + >>> import matplotlib.pyplot as plt + >>> fig, ax = plt.subplots() + >>> N = 50 + >>> for alpha in [0.64, 2.55, 7.64, 31.83]: + ... ax.plot(signal.windows.kaiser_bessel_derived(2*N, np.pi*alpha), + ... label=f"{alpha=}") + >>> ax.grid(True) + >>> ax.set_title("Kaiser-Bessel derived window") + >>> ax.set_ylabel("Amplitude") + >>> ax.set_xlabel("Sample") + >>> ax.set_xticks([0, N, 2*N-1]) + >>> ax.set_xticklabels(["0", "N", "2N+1"]) # doctest: +SKIP + >>> ax.set_yticks([0.0, 0.2, 0.4, 0.6, 0.707, 0.8, 1.0]) + >>> fig.legend(loc="center") + >>> fig.tight_layout() + >>> fig.show() + """ + xp = _namespace(xp) + + if not sym: + raise ValueError( + "Kaiser-Bessel Derived windows are only defined for symmetric " + "shapes" + ) + elif M < 1: + return xp.asarray([]) + elif M % 2: + raise ValueError( + "Kaiser-Bessel Derived windows are only defined for even number " + "of points" + ) + + kaiser_window = kaiser(M // 2 + 1, beta, xp=xp, device=device) + csum = xp.cumulative_sum(kaiser_window) + half_window = xp.sqrt(csum[:-1] / csum[-1]) + w = xp.concat((half_window, xp.flip(half_window)), axis=0) + return xp.asarray(w, device=device) + + +@xp_capabilities() +def gaussian(M, std, sym=True, *, xp=None, device=None): + r"""Return a Gaussian window. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + std : float + The standard deviation, sigma. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + Notes + ----- + The Gaussian window is defined as + + .. math:: w(n) = e^{ -\frac{1}{2}\left(\frac{n}{\sigma}\right)^2 } + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.gaussian(51, std=7) + >>> plt.plot(window) + >>> plt.title(r"Gaussian window ($\sigma$=7)") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title(r"Frequency response of the Gaussian window ($\sigma$=7)") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + xp = _namespace(xp) + + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + M, needs_trunc = _extend(M, sym) + + n = xp.arange(0, M, dtype=xp.float64, device=device) - (M - 1.0) / 2.0 + sig2 = 2 * std * std + w = xp.exp(-n ** 2 / sig2) + + return _truncate(w, needs_trunc) + + +@xp_capabilities() +def general_gaussian(M, p, sig, sym=True, *, xp=None, device=None): + r"""Return a window with a generalized Gaussian shape. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + p : float + Shape parameter. p = 1 is identical to `gaussian`, p = 0.5 is + the same shape as the Laplace distribution. + sig : float + The standard deviation, sigma. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + Notes + ----- + The generalized Gaussian window is defined as + + .. math:: w(n) = e^{ -\frac{1}{2}\left|\frac{n}{\sigma}\right|^{2p} } + + the half-power point is at + + .. math:: (2 \log(2))^{1/(2 p)} \sigma + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.general_gaussian(51, p=1.5, sig=7) + >>> plt.plot(window) + >>> plt.title(r"Generalized Gaussian window (p=1.5, $\sigma$=7)") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title(r"Freq. resp. of the gen. Gaussian " + ... r"window (p=1.5, $\sigma$=7)") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + xp = _namespace(xp) + + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + M, needs_trunc = _extend(M, sym) + + n = xp.arange(0, M, dtype=xp.float64, device=device) - (M - 1.0) / 2.0 + w = xp.exp(-0.5 * abs(n / sig) ** (2 * p)) + + return _truncate(w, needs_trunc) + + +# `chebwin` contributed by Kumar Appaiah. +@xp_capabilities(skip_backends=(("jax.numpy", "item assignment"), + ("dask.array", "data-dependent output shapes"))) +def chebwin(M, at, sym=True, *, xp=None, device=None): + r"""Return a Dolph-Chebyshev window. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + at : float + Attenuation (in dB). + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value always normalized to 1 + + Notes + ----- + This window optimizes for the narrowest main lobe width for a given order + `M` and sidelobe equiripple attenuation `at`, using Chebyshev + polynomials. It was originally developed by Dolph to optimize the + directionality of radio antenna arrays. + + Unlike most windows, the Dolph-Chebyshev is defined in terms of its + frequency response: + + .. math:: W(k) = \frac + {\cos\{M \cos^{-1}[\beta \cos(\frac{\pi k}{M})]\}} + {\cosh[M \cosh^{-1}(\beta)]} + + where + + .. math:: \beta = \cosh \left [\frac{1}{M} + \cosh^{-1}(10^\frac{A}{20}) \right ] + + and 0 <= abs(k) <= M-1. A is the attenuation in decibels (`at`). + + The time domain window is then generated using the IFFT, so + power-of-two `M` are the fastest to generate, and prime number `M` are + the slowest. + + The equiripple condition in the frequency domain creates impulses in the + time domain, which appear at the ends of the window. + + References + ---------- + .. [1] C. Dolph, "A current distribution for broadside arrays which + optimizes the relationship between beam width and side-lobe level", + Proceedings of the IEEE, Vol. 34, Issue 6 + .. [2] Peter Lynch, "The Dolph-Chebyshev Window: A Simple Optimal Filter", + American Meteorological Society (April 1997) + http://mathsci.ucd.ie/~plynch/Publications/Dolph.pdf + .. [3] F. J. Harris, "On the use of windows for harmonic analysis with the + discrete Fourier transforms", Proceedings of the IEEE, Vol. 66, + No. 1, January 1978 + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.chebwin(51, at=100) + >>> plt.plot(window) + >>> plt.title("Dolph-Chebyshev window (100 dB)") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the Dolph-Chebyshev window (100 dB)") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ + xp = _namespace(xp) + + if abs(at) < 45: + warnings.warn("This window is not suitable for spectral analysis " + "for attenuation values lower than about 45dB because " + "the equivalent noise bandwidth of a Chebyshev window " + "does not grow monotonically with increasing sidelobe " + "attenuation when the attenuation is smaller than " + "about 45 dB.", + stacklevel=2) + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + M, needs_trunc = _extend(M, sym) + + # compute the parameter beta + order = M - 1.0 + _val = xp.asarray(10 ** (abs(at) / 20.), dtype=xp.float64, device=device) + beta = xp.cosh(1.0 / order * xp.acosh(_val)) + k = xp.arange(M, dtype=xp.float64, device=device) + x = beta * xp.cos(xp.pi * k / M) + # Find the window's DFT coefficients + # Use analytic definition of Chebyshev polynomial instead of expansion + # from scipy.special. Using the expansion in scipy.special leads to errors. + p = xp.zeros_like(x) + p[x > 1] = xp.cosh(order * xp.acosh(x[x > 1])) + p[x < -1] = (2 * (M % 2) - 1) * xp.cosh(order * xp.acosh(-x[x < -1])) + p[abs(x) <= 1] = xp.cos(order * xp.acos(x[abs(x) <= 1])) + + # Appropriate IDFT and filling up + # depending on even/odd M + if M % 2: + w = xp.real(sp_fft.fft(p)) + n = (M + 1) // 2 + w = w[:n] + w = xp.concat((xp.flip(w[1:n]), w)) + else: + p = p * xp.exp(1j * xp.pi / M * xp.arange(M, dtype=xp.float64, device=device)) + w = xp.real(sp_fft.fft(p)) + n = M // 2 + 1 + w = xp.concat((xp.flip(w[1:n]), w[1:n])) + w = w / xp.max(w) + + return _truncate(w, needs_trunc) + + +@xp_capabilities() +def cosine(M, sym=True, *, xp=None, device=None): + """Return a window with a simple cosine shape. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + Notes + ----- + + .. versionadded:: 0.13.0 + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.cosine(51) + >>> plt.plot(window) + >>> plt.title("Cosine window") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2047) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the cosine window") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + >>> plt.show() + + """ + xp = _namespace(xp) + + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + M, needs_trunc = _extend(M, sym) + + w = xp.sin(xp.pi / M * (xp.arange(M, dtype=xp.float64, device=device) + .5)) + + return _truncate(w, needs_trunc) + + +@xp_capabilities() +def exponential(M, center=None, tau=1., sym=True, *, xp=None, device=None): + r"""Return an exponential (or Poisson) window. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + center : float, optional + Parameter defining the center location of the window function. + The default value if not given is ``center = (M-1) / 2``. This + parameter must take its default value for symmetric windows. + tau : float, optional + Parameter defining the decay. For ``center = 0`` use + ``tau = -(M-1) / ln(x)`` if ``x`` is the fraction of the window + remaining at the end. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + Notes + ----- + The Exponential window is defined as + + .. math:: w(n) = e^{-|n-center| / \tau} + + References + ---------- + .. [1] S. Gade and H. Herlufsen, "Windows to FFT analysis (Part I)", + Technical Review 3, Bruel & Kjaer, 1987. + + Examples + -------- + Plot the symmetric window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> M = 51 + >>> tau = 3.0 + >>> window = signal.windows.exponential(M, tau=tau) + >>> plt.plot(window) + >>> plt.title("Exponential Window (tau=3.0)") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -35, 0]) + >>> plt.title("Frequency response of the Exponential window (tau=3.0)") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + This function can also generate non-symmetric windows: + + >>> tau2 = -(M-1) / np.log(0.01) + >>> window2 = signal.windows.exponential(M, 0, tau2, False) + >>> plt.figure() + >>> plt.plot(window2) + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + """ + xp = _namespace(xp) + + if sym and center is not None: + raise ValueError("If sym==True, center must be None.") + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + M, needs_trunc = _extend(M, sym) + + if center is None: + center = (M-1) / 2 + + n = xp.arange(0, M, dtype=xp.float64, device=device) + w = xp.exp(-abs(n-center) / tau) + + return _truncate(w, needs_trunc) + + +@xp_capabilities(skip_backends=[("jax.numpy", "item assignment")]) +def taylor(M, nbar=4, sll=30, norm=True, sym=True, *, xp=None, device=None): + """ + Return a Taylor window. + + The Taylor window taper function approximates the Dolph-Chebyshev window's + constant sidelobe level for a parameterized number of near-in sidelobes, + but then allows a taper beyond [2]_. + + The SAR (synthetic aperture radar) community commonly uses Taylor + weighting for image formation processing because it provides strong, + selectable sidelobe suppression with minimum broadening of the + mainlobe [1]_. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + nbar : int, optional + Number of nearly constant level sidelobes adjacent to the mainlobe. + sll : float, optional + Desired suppression of sidelobe level in decibels (dB) relative to the + DC gain of the mainlobe. This should be a positive number. + norm : bool, optional + When True (default), divides the window by the largest (middle) value + for odd-length windows or the value that would occur between the two + repeated middle values for even-length windows such that all values + are less than or equal to 1. When False the DC gain will remain at 1 + (0 dB) and the sidelobes will be `sll` dB down. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + out : array + The window. When `norm` is True (default), the maximum value is + normalized to 1 (though the value 1 does not appear if `M` is + even and `sym` is True). + + See Also + -------- + chebwin, kaiser, bartlett, blackman, hamming, hann + + References + ---------- + .. [1] W. Carrara, R. Goodman, and R. Majewski, "Spotlight Synthetic + Aperture Radar: Signal Processing Algorithms" Pages 512-513, + July 1995. + .. [2] Armin Doerry, "Catalog of Window Taper Functions for + Sidelobe Control", 2017. + https://www.researchgate.net/profile/Armin_Doerry/publication/316281181_Catalog_of_Window_Taper_Functions_for_Sidelobe_Control/links/58f92cb2a6fdccb121c9d54d/Catalog-of-Window-Taper-Functions-for-Sidelobe-Control.pdf + + Examples + -------- + Plot the window and its frequency response: + + >>> import numpy as np + >>> from scipy import signal + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + + >>> window = signal.windows.taylor(51, nbar=20, sll=100, norm=False) + >>> plt.plot(window) + >>> plt.title("Taylor window (100 dB)") + >>> plt.ylabel("Amplitude") + >>> plt.xlabel("Sample") + + >>> plt.figure() + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> plt.plot(freq, response) + >>> plt.axis([-0.5, 0.5, -120, 0]) + >>> plt.title("Frequency response of the Taylor window (100 dB)") + >>> plt.ylabel("Normalized magnitude [dB]") + >>> plt.xlabel("Normalized frequency [cycles per sample]") + + """ # noqa: E501 + xp = _namespace(xp) + + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + M, needs_trunc = _extend(M, sym) + + # Original text uses a negative sidelobe level parameter and then negates + # it in the calculation of B. To keep consistent with other methods we + # assume the sidelobe level parameter to be positive. + B = xp.asarray(10**(sll / 20), device=device) + A = xp.acosh(B) / xp.pi + s2 = nbar**2 / (A**2 + (nbar - 0.5)**2) + ma = xp.arange(1, nbar, dtype=xp.float64, device=device) + + Fm = xp.empty(nbar - 1, dtype=xp.float64, device=device) + signs = xp.empty_like(ma) + signs[::2] = 1 + signs[1::2] = -1 + m2 = ma*ma + for mi, m in enumerate(ma): + numer = signs[mi] * xp.prod(1 - m2[mi]/s2/(A**2 + (ma - 0.5)**2)) + denom = 2 * xp.prod(1 - m2[mi]/m2[:mi]) * xp.prod(1 - m2[mi]/m2[mi+1:]) + Fm[mi] = numer / denom + + def W(n): + return 1 + 2*xp.matmul(Fm, xp.cos( + 2*xp.pi*ma[:, xp.newaxis]*(n-M/2.+0.5)/M)) + + w = W(xp.arange(M, dtype=xp.float64, device=device)) + + # normalize (Note that this is not described in the original text [1]) + if norm: + scale = 1.0 / W((M - 1) / 2) + w *= scale + + return _truncate(w, needs_trunc) + + +@xp_capabilities(np_only=True, reason='banded linear algebra is numpy-only') +def dpss(M, NW, Kmax=None, sym=True, norm=None, return_ratios=False, + *, xp=None, device=None): + """ + Compute the Discrete Prolate Spheroidal Sequences (DPSS). + + DPSS (or Slepian sequences) are often used in multitaper power spectral + density estimation (see [1]_). The first window in the sequence can be + used to maximize the energy concentration in the main lobe, and is also + called the Slepian window. + + Parameters + ---------- + M : int + Window length. + NW : float + Standardized half bandwidth corresponding to ``2*NW = BW/f0 = BW*M*dt`` + where ``dt`` is taken as 1. + Kmax : int | None, optional + Number of DPSS windows to return (orders ``0`` through ``Kmax-1``). + If None (default), return only a single window of shape ``(M,)`` + instead of an array of windows of shape ``(Kmax, M)``. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + norm : {2, 'approximate', 'subsample'} | None, optional + If 'approximate' or 'subsample', then the windows are normalized by the + maximum, and a correction scale-factor for even-length windows + is applied either using ``M**2/(M**2+NW)`` ("approximate") or + a FFT-based subsample shift ("subsample"), see Notes for details. + If None, then "approximate" is used when ``Kmax=None`` and 2 otherwise + (which uses the l2 norm). + return_ratios : bool, optional + If True, also return the concentration ratios in addition to the + windows. + %(xp_device_snippet)s + + Returns + ------- + v : ndarray, shape (Kmax, M) or (M,) + The DPSS windows. Will be 1D if `Kmax` is None. + r : ndarray, shape (Kmax,) or float, optional + The concentration ratios for the windows. Only returned if + `return_ratios` evaluates to True. Will be 0D if `Kmax` is None. + + Notes + ----- + This computation uses the tridiagonal eigenvector formulation given + in [2]_. + + The default normalization for ``Kmax=None``, i.e. window-generation mode, + simply using the l-infinity norm would create a window with two unity + values, which creates slight normalization differences between even and odd + orders. The approximate correction of ``M**2/float(M**2+NW)`` for even + sample numbers is used to counteract this effect (see Examples below). + + For very long signals (e.g., 1e6 elements), it can be useful to compute + windows orders of magnitude shorter and use interpolation (e.g., + `scipy.interpolate.interp1d`) to obtain tapers of length `M`, + but this in general will not preserve orthogonality between the tapers. + + .. versionadded:: 1.1 + + References + ---------- + .. [1] Percival DB, Walden WT. Spectral Analysis for Physical Applications: + Multitaper and Conventional Univariate Techniques. + Cambridge University Press; 1993. + .. [2] Slepian, D. Prolate spheroidal wave functions, Fourier analysis, and + uncertainty V: The discrete case. Bell System Technical Journal, + Volume 57 (1978), 1371430. + .. [3] Kaiser, JF, Schafer RW. On the Use of the I0-Sinh Window for + Spectrum Analysis. IEEE Transactions on Acoustics, Speech and + Signal Processing. ASSP-28 (1): 105-107; 1980. + + Examples + -------- + We can compare the window to `kaiser`, which was invented as an alternative + that was easier to calculate [3]_ (example adapted from + `here `_): + + >>> import numpy as np + >>> import matplotlib.pyplot as plt + >>> from scipy.signal import windows, freqz + >>> M = 51 + >>> fig, axes = plt.subplots(3, 2, figsize=(5, 7)) + >>> for ai, alpha in enumerate((1, 3, 5)): + ... win_dpss = windows.dpss(M, alpha) + ... beta = alpha*np.pi + ... win_kaiser = windows.kaiser(M, beta) + ... for win, c in ((win_dpss, 'k'), (win_kaiser, 'r')): + ... win /= win.sum() + ... axes[ai, 0].plot(win, color=c, lw=1.) + ... axes[ai, 0].set(xlim=[0, M-1], title=rf'$\\alpha$ = {alpha}', + ... ylabel='Amplitude') + ... w, h = freqz(win) + ... axes[ai, 1].plot(w, 20 * np.log10(np.abs(h)), color=c, lw=1.) + ... axes[ai, 1].set(xlim=[0, np.pi], + ... title=rf'$\\beta$ = {beta:0.2f}', + ... ylabel='Magnitude (dB)') + >>> for ax in axes.ravel(): + ... ax.grid(True) + >>> axes[2, 1].legend(['DPSS', 'Kaiser']) + >>> fig.tight_layout() + >>> plt.show() + + And here are examples of the first four windows, along with their + concentration ratios: + + >>> M = 512 + >>> NW = 2.5 + >>> win, eigvals = windows.dpss(M, NW, 4, return_ratios=True) + >>> fig, ax = plt.subplots(1) + >>> ax.plot(win.T, linewidth=1.) + >>> ax.set(xlim=[0, M-1], ylim=[-0.1, 0.1], xlabel='Samples', + ... title=f'DPSS, {M:d}, {NW:0.1f}') + >>> ax.legend([f'win[{ii}] ({ratio:0.4f})' + ... for ii, ratio in enumerate(eigvals)]) + >>> fig.tight_layout() + >>> plt.show() + + Using a standard :math:`l_{\\infty}` norm would produce two unity values + for even `M`, but only one unity value for odd `M`. This produces uneven + window power that can be counteracted by the approximate correction + ``M**2/float(M**2+NW)``, which can be selected by using + ``norm='approximate'`` (which is the same as ``norm=None`` when + ``Kmax=None``, as is the case here). Alternatively, the slower + ``norm='subsample'`` can be used, which uses subsample shifting in the + frequency domain (FFT) to compute the correction: + + >>> Ms = np.arange(1, 41) + >>> factors = (50, 20, 10, 5, 2.0001) + >>> energy = np.empty((3, len(Ms), len(factors))) + >>> for mi, M in enumerate(Ms): + ... for fi, factor in enumerate(factors): + ... NW = M / float(factor) + ... # Corrected using empirical approximation (default) + ... win = windows.dpss(M, NW) + ... energy[0, mi, fi] = np.sum(win ** 2) / np.sqrt(M) + ... # Corrected using subsample shifting + ... win = windows.dpss(M, NW, norm='subsample') + ... energy[1, mi, fi] = np.sum(win ** 2) / np.sqrt(M) + ... # Uncorrected (using l-infinity norm) + ... win /= win.max() + ... energy[2, mi, fi] = np.sum(win ** 2) / np.sqrt(M) + >>> fig, ax = plt.subplots(1) + >>> hs = ax.plot(Ms, energy[2], '-o', markersize=4, + ... markeredgecolor='none') + >>> leg = [hs[-1]] + >>> for hi, hh in enumerate(hs): + ... h1 = ax.plot(Ms, energy[0, :, hi], '-o', markersize=4, + ... color=hh.get_color(), markeredgecolor='none', + ... alpha=0.66) + ... h2 = ax.plot(Ms, energy[1, :, hi], '-o', markersize=4, + ... color=hh.get_color(), markeredgecolor='none', + ... alpha=0.33) + ... if hi == len(hs) - 1: + ... leg.insert(0, h1[0]) + ... leg.insert(0, h2[0]) + >>> ax.set(xlabel='M (samples)', ylabel=r'Power / $\\sqrt{M}$') + >>> ax.legend(leg, ['Uncorrected', r'Corrected: $\\frac{M^2}{M^2+NW}$', + ... 'Corrected (subsample)']) + >>> fig.tight_layout() + + """ + xp = _namespace(xp) + + if norm is None: + norm = 'approximate' if Kmax is None else 2 + known_norms = (2, 'approximate', 'subsample') + if norm not in known_norms: + raise ValueError(f'norm must be one of {known_norms}, got {norm}') + if Kmax is None: + singleton = True + Kmax = 1 + else: + singleton = False + if _len_guards(M): + if not return_ratios: + return xp.ones(M, dtype=xp.float64) + elif singleton: + return xp.ones(M, dtype=xp.float64), 1. + else: + return xp.ones(M, dtype=xp.float64), xp.ones(1, dtype=xp.float64) + Kmax = operator.index(Kmax) + if not 0 < Kmax <= M: + raise ValueError('Kmax must be greater than 0 and less than M') + if NW >= M/2.: + raise ValueError('NW must be less than M/2.') + if NW <= 0: + raise ValueError('NW must be positive') + M, needs_trunc = _extend(M, sym) + W = float(NW) / M + nidx = xp.arange(M, dtype=xp.float64, device=device) + + # Here we want to set up an optimization problem to find a sequence + # whose energy is maximally concentrated within band [-W,W]. + # Thus, the measure lambda(T,W) is the ratio between the energy within + # that band, and the total energy. This leads to the eigen-system + # (A - (l1)I)v = 0, where the eigenvector corresponding to the largest + # eigenvalue is the sequence with maximally concentrated energy. The + # collection of eigenvectors of this system are called Slepian + # sequences, or discrete prolate spheroidal sequences (DPSS). Only the + # first K, K = 2NW/dt orders of DPSS will exhibit good spectral + # concentration + # [see https://en.wikipedia.org/wiki/Spectral_concentration_problem] + + # Here we set up an alternative symmetric tri-diagonal eigenvalue + # problem such that + # (B - (l2)I)v = 0, and v are our DPSS (but eigenvalues l2 != l1) + # the main diagonal = ([M-1-2*t]/2)**2 cos(2PIW), t=[0,1,2,...,M-1] + # and the first off-diagonal = t(M-t)/2, t=[1,2,...,M-1] + # [see Percival and Walden, 1993] + d = ((M - 1 - 2 * nidx) / 2.) ** 2 * xp.cos(xp.asarray(2 * xp.pi * W)) + e = nidx[1:] * (M - nidx[1:]) / 2. + + # only calculate the highest Kmax eigenvalues + w, windows = linalg.eigh_tridiagonal( + d, e, select='i', select_range=(M - Kmax, M - 1)) + w = w[::-1] + windows = windows[:, ::-1].T + + # By convention (Percival and Walden, 1993 pg 379) + # * symmetric tapers (k=0,2,4,...) should have a positive average. + fix_even = (windows[::2, ...].sum(axis=1) < 0) + for i, f in enumerate(fix_even): + if f: + windows[2 * i] *= -1 + # * antisymmetric tapers should begin with a positive lobe + # (this depends on the definition of "lobe", here we'll take the first + # point above the numerical noise, which should be good enough for + # sufficiently smooth functions, and more robust than relying on an + # algorithm that uses max(abs(w)), which is susceptible to numerical + # noise problems) + thresh = max(1e-7, 1. / M) + for i, w in enumerate(windows[1::2, ...]): + if w[w * w > thresh][0] < 0: + windows[2 * i + 1] *= -1 + + # Now find the eigenvalues of the original spectral concentration problem + # Use the autocorr sequence technique from Percival and Walden, 1993 pg 390 + if return_ratios: + dpss_rxx = _fftautocorr(xp.asarray(windows)) + r = 4 * W * xpx.sinc(xp.asarray(2 * W * nidx), xp=xp) + r[0] = 2 * W + ratios = xp.matmul(dpss_rxx, r) + if singleton: + ratios = ratios[0] + ratios = xp.asarray(ratios, device=device) + # Deal with sym and Kmax=None + if norm != 2: + windows /= windows.max() + if M % 2 == 0: + if norm == 'approximate': + correction = M**2 / float(M**2 + NW) + else: + s = sp_fft.rfft(windows[0]) + shift = -(1 - 1./M) * xp.arange(1, M//2 + 1, dtype=xp.float64) + s[1:] *= 2 * xp.exp(-1j * xp.pi * shift) + correction = M / s.real.sum() + windows *= correction + # else we're already l2 normed, so do nothing + if needs_trunc: + windows = windows[:, :-1] + if singleton: + windows = windows[0] + windows = xp.asarray(windows, device=device) + return (windows, ratios) if return_ratios else windows + + +@xp_capabilities() +def lanczos(M, *, sym=True, xp=None, device=None): + r"""Return a Lanczos window also known as a sinc window. + + Parameters + ---------- + M : int + Number of points in the output window. If zero, an empty array + is returned. An exception is thrown when it is negative. + sym : bool, optional + When True (default), generates a symmetric window, for use in filter + design. + When False, generates a periodic window, for use in spectral analysis. + %(xp_device_snippet)s + + Returns + ------- + w : ndarray + The window, with the maximum value normalized to 1 (though the value 1 + does not appear if `M` is even and `sym` is True). + + Notes + ----- + The Lanczos window is defined as + + .. math:: w(n) = sinc \left( \frac{2n}{M - 1} - 1 \right) + + where + + .. math:: sinc(x) = \frac{\sin(\pi x)}{\pi x} + + The Lanczos window has reduced Gibbs oscillations and is widely used for + filtering climate timeseries with good properties in the physical and + spectral domains. + + .. versionadded:: 1.10 + + References + ---------- + .. [1] Lanczos, C., and Teichmann, T. (1957). Applied analysis. + Physics Today, 10, 44. + .. [2] Duchon C. E. (1979) Lanczos Filtering in One and Two Dimensions. + Journal of Applied Meteorology, Vol 18, pp 1016-1022. + .. [3] Thomson, R. E. and Emery, W. J. (2014) Data Analysis Methods in + Physical Oceanography (Third Edition), Elsevier, pp 593-637. + .. [4] Wikipedia, "Window function", + http://en.wikipedia.org/wiki/Window_function + + Examples + -------- + Plot the window + + >>> import numpy as np + >>> from scipy.signal.windows import lanczos + >>> from scipy.fft import fft, fftshift + >>> import matplotlib.pyplot as plt + >>> fig, ax = plt.subplots(1) + >>> window = lanczos(51) + >>> ax.plot(window) + >>> ax.set_title("Lanczos window") + >>> ax.set_ylabel("Amplitude") + >>> ax.set_xlabel("Sample") + >>> fig.tight_layout() + >>> plt.show() + + and its frequency response: + + >>> fig, ax = plt.subplots(1) + >>> A = fft(window, 2048) / (len(window)/2.0) + >>> freq = np.linspace(-0.5, 0.5, len(A)) + >>> response = 20 * np.log10(np.abs(fftshift(A / abs(A).max()))) + >>> ax.plot(freq, response) + >>> ax.set_xlim(-0.5, 0.5) + >>> ax.set_ylim(-120, 0) + >>> ax.set_title("Frequency response of the lanczos window") + >>> ax.set_ylabel("Normalized magnitude [dB]") + >>> ax.set_xlabel("Normalized frequency [cycles per sample]") + >>> fig.tight_layout() + >>> plt.show() + """ + xp = _namespace(xp) + + if _len_guards(M): + return xp.ones(M, dtype=xp.float64, device=device) + M, needs_trunc = _extend(M, sym) + + # To make sure that the window is symmetric, we concatenate the right hand + # half of the window and the flipped one which is the left hand half of + # the window. + def _calc_right_side_lanczos(n, m): + return xpx.sinc(2. * xp.arange(n, m, dtype=xp.float64) / (m - 1) - 1.0, xp=xp) + + if M % 2 == 0: + wh = _calc_right_side_lanczos(M/2, M) + w = xp.concat([xp.flip(wh), wh]) + else: + wh = _calc_right_side_lanczos((M+1)/2, M) + w = xp.concat([xp.flip(wh), xp.ones(1), wh]) + + return _truncate(w, needs_trunc) + + +def _fftautocorr(x): + """Compute the autocorrelation of a real array and crop the result.""" + N = x.shape[-1] + use_N = sp_fft.next_fast_len(2*N-1) + x_fft = sp_fft.rfft(x, use_N, axis=-1) + cxy = sp_fft.irfft(x_fft * x_fft.conj(), n=use_N)[:, :N] + # Or equivalently (but in most cases slower): + # cxy = xp.asarray([xp.convolve(xx, yy[::-1], mode='full') + # for xx, yy in zip(x, x)])[:, N-1:2*N-1] + return cxy + +_WIN_FUNC_DATA = { # Format: {(name0, name1, ...): (function, needs parameters) + ('barthann', 'brthan', 'bth'): (barthann, False), + ('bartlett', 'bart', 'brt'): (bartlett, False), + ('blackman', 'black', 'blk'): (blackman, False), + ('blackmanharris', 'blackharr', 'bkh'): (blackmanharris, False), + ('bohman', 'bman', 'bmn'): (bohman, False), + ('boxcar', 'box', 'ones', 'rect', 'rectangular'): (boxcar, False), + ('chebwin', 'cheb'): (chebwin, True), + ('cosine', 'halfcosine'): (cosine, False), + ('dpss',): (dpss, True), + ('exponential', 'poisson'): (exponential, 'OPTIONAL'), + ('flattop', 'flat', 'flt'): (flattop, False), + ('gaussian', 'gauss', 'gss'): (gaussian, True), + ('general cosine', 'general_cosine'): (general_cosine, True), + ('general gaussian', 'general_gaussian', 'general gauss', + 'general_gauss', 'ggs'): (general_gaussian, True), + ('general hamming', 'general_hamming'): (general_hamming, True), + ('hamming', 'hamm', 'ham'): (hamming, False), + ('hann', 'han'): (hann, False), + ('kaiser', 'ksr'): (kaiser, True), + ('kaiser bessel derived', 'kaiser_bessel_derived', + 'kbd'): (kaiser_bessel_derived, True), + ('lanczos', 'sinc'): (lanczos, False), + ('nuttall', 'nutl', 'nut'): (nuttall, False), + ('parzen', 'parz', 'par'): (parzen, False), + ('taylor', 'taylorwin'): (taylor, 'OPTIONAL'), + ('triangle', 'triang', 'tri'): (triang, False), + ('tukey', 'tuk'): (tukey, 'OPTIONAL'), } +_WIN_FUNCS = dict() +for nn_, v_ in _WIN_FUNC_DATA.items(): + _WIN_FUNCS.update({n_: v_ for n_ in nn_}) + + +@xp_capabilities() +def get_window(window, Nx, fftbins=True, *, xp=None, device=None): + r"""Convenience function for creating various windows. + + This function is a wrapper for the window functions provided in the + `scipy.signal.windows` namespace. + + Parameters + ---------- + window : str | tuple | float + Either a string with the window name or a tuple consisting of window name and + window parameters. If it is a float, a `~scipy.singal.kaiser` window is + created with `window` being the shape parameter. Consult the Notes below for + more details. + Nx : int + The number of samples in the window. + fftbins : bool, optional + If ``True`` (default), create a periodic window, ready to use with `ifftshift` + and be multiplied by the result of an FFT (see also + :func:`~scipy.fft.fftfreq`). If ``False``, create a symmetric window, for use + in filter design. This parameter is ignored, if the window name in the + `window` parameter has a suffix ``'_periodic'`` or ``'_symmetric'`` appended to + it (e.g., ``'hann_symmetric'``). + %(xp_device_snippet)s + + Returns + ------- + get_window : ndarray + Returns the created window as a one-dimensional array made of `Nx` samples. + + Raises + ------ + ValueError + If the provided parameters do not allow to choose a valid window function + with valid parameters. + + Notes + ----- + Note that by default this function returns a periodic window, whereas the wrapped + window functions return a symmetric window by default. This is caused by the + `fftbins` parameter having the inverse meaning of the `sym` parameter of the + wrapped function, which are both ``True`` by default. + + .. currentmodule:: scipy.signal.windows + + The following list shows the wrapped window functions with the respective settings + of the `window` parameter followed by a short description. Aliases for alternative + window names are given in parenthesis. + + `barthann` / ``'barthann'``: + Modified Bartlett-Hann window (aliases: ``'brthan', 'bth'``) + `bartlett` / ``'bartlett'``: + Bartlett window (aliases: ``'bart', 'brt'``) + `blackman`/ ``'blackman'``: + Blackman window (aliases: ``'black', 'blk'``) + `blackmanharris` / ``'blackmanharris'``: + 4-term Blackman-Harris window (aliases: ``'blackharr', 'bkh'``) + `bohman` / ``'bohman'``: + Bohman window (aliases: ``'bman', 'bmn'``) + `boxcar` / ``'boxcar'``: + Rectangular window (aliases: ``'box', 'ones', 'rect', 'rectangular'``) + `chebwin` / ``('chebwin', at)``: + Dolph-Chebyshev window with `at` dB attenuation (aliases: ``'cheb'``) + `cosine` / ``'cosine'``: + Cosine window (aliases: ``'halfcosine'``) + `dpss` / ``('dpss', NW)``: + First window of discrete prolate spheroidal sequence with standardized half + bandwidth ``NW`` and "approximate" norm. + `exponential` / ``'exponential'`` / ``('exponential', center, tau)``: + Exponential / Poisson window centered at ``center`` (default: ``None``) with + deacy ``tau`` (default: ``1``) (aliases: ``'poisson'``) + `flattop`/ ``'flattop'``: + Flat top window (aliases: ``'flat', 'flt'``) + `gaussian` / ``('gaussian', std)``: + Gaussian with standard deviation `std` (aliases: ``'gauss', 'gss'``) + `general_cosine` / ``('general cosine', a)``: + Generic weighted sum of cosine terms with weighting coefficients ``a`` + (aliases: ``'general_cosine'``) + `general_gaussian` / ``('general gaussian', p, sig)``: + Generalized Gaussian with shape parameter ``p`` and standard deviation ``sig`` + (aliases: ``'general_gaussian', 'general gauss', 'general_gauss', 'ggs'``) + `general_hamming` / ``('general hamming', alpha)``: + Generalized Hamming window with coefficent ``alpha`` + (aliases: ``'general_hamming'``) + `hamming` / ``'hamming'``: + Hamming window (aliases: ``'hamm', 'ham'``) + `hann` / ``'hann'``: + Hann window (aliases: ``'han'``) + `kaiser` / ``('kaiser', beta)``: + Kaiser window with shape parameter ``beta`` (aliases: ``'ksr'``) + `kaiser_bessel_derived` / ``('kaiser bessel derived', beta)``: + Kaiser-Bessel derived window with shape parameter ``beta`` + (aliases: ``'kaiser_bessel_derived', 'kbd'``) + `lanczos` / ``'lanczos'``: + Lanczos / sinc window (aliases: ``'sinc'``) + `nuttall`/ ``'nuttall'``: + Minimum 4-term Blackman-Harris window according to Nuttall + (aliases: ``'nutl', 'nut'``) + `parzen` / ``'parzen'``: + Parzen window (aliases: ``'parz', 'par'``) + `taylor` / ``'taylor'`` / (``'taylor', nbar, sll, norm)``: + Taylor window with ``nbar`` adjascent sidelobes (default: ``4``)), ``sll`` dB + suppression level (default: ``30``) and boolean value ``norm`` + (default: ``True``) (aliases: ``taylorwin``) + `triang`/ ``'triangle'``: + Triangle window (aliases: ``'triang', 'tri'``) + `tukey` / ``'tukey'`` / ``('tukey', alpha)``: + Tukey window with shape parameter ``alpha`` (default: ``0.5``) + (aliases: ``'tuk'``) + + + Examples + -------- + This example shows different usages of the `window` parameter: + + >>> from scipy.signal import get_window + >>> get_window('triang', 7) + array([ 0.125, 0.375, 0.625, 0.875, 0.875, 0.625, 0.375]) + >>> get_window(('exponential', None, 1.), 9) + array([ 0.011109 , 0.03019738, 0.082085 , 0.22313016, 0.60653066, + 0.60653066, 0.22313016, 0.082085 , 0.03019738]) + >>> get_window(('kaiser', 4.0), 9) + array([ 0.08848053, 0.29425961, 0.56437221, 0.82160913, 0.97885093, + 0.97885093, 0.82160913, 0.56437221, 0.29425961]) + >>> get_window(4.0, 9) # same as previous call + array([ 0.08848053, 0.29425961, 0.56437221, 0.82160913, 0.97885093, + 0.97885093, 0.82160913, 0.56437221, 0.29425961]) + + The following snippet shows different ways to create identical symmetric and + periodic Bartlett windows: + + >>> from scipy.signal import get_window, windows + >>> # Symmetric window: + >>> windows.bartlett(5) # Parameter `sym` defaults to True + array([0. , 0.5, 1. , 0.5, 0. ]) + >>> get_window('bartlett', 5, fftbins=False) + array([0. , 0.5, 1. , 0.5, 0. ]) + >>> get_window('bartlett_symmetric', 5) + array([0. , 0.5, 1. , 0.5, 0. ]) + >>> # Periodic window: + >>> windows.bartlett(4, sym=False) + array([0. , 0.5, 1. , 0.5]) + >>> get_window('bartlett', 4) # Parameter `fftbins` defaults to True + array([0. , 0.5, 1. , 0.5]) + >>> get_window('bartlett_periodic', 4) + array([0. , 0.5, 1. , 0.5]) + >>> # `_periodic' suffix overrides `fftbins` parameter: + >>> get_window('bartlett_periodic', 4, fftbins=False) + array([0. , 0.5, 1. , 0.5]) + + Note that a periodic window can be created out of a symmetric window by discarding + the last sample. + """ + if not (Nx > 0 and isinstance(Nx, numbers.Integral)): + raise ValueError(f"Parameter {Nx=} is not a positive integer") + if not isinstance(fftbins, bool): + raise ValueError(f"Parameter {fftbins=} is not of type bool!") + + if not isinstance(window, str | tuple): + try: # if parameter window can be converted to a float, return kaiser window: + beta = float(window) + except Exception as float_exception: + err_msg = f"Parameter {window=} must be a tuple, a string or a float!" + raise ValueError(err_msg) from float_exception + return kaiser(Nx, beta, not fftbins, xp=xp, device=device) + + if isinstance(window, tuple) and not isinstance(window[0], str): + raise ValueError(f"First tuple entry of parameter {window=} is not a str!") + + sym = not fftbins + win_name = window if isinstance(window, str) else window[0] + if win_name.endswith('_symmetric'): # overwrite `fftbins` / `sym` if needed + sym, win_name = True, win_name[:-10] # remove '_symmetric' from `win_name` + elif win_name.endswith('_periodic'): + sym, win_name = False, win_name[:-9] # remove '_periodic' from `win_name` + + if win_name not in _WIN_FUNCS: + raise ValueError(f"Invalid window name '{win_name}' in parameter {window=}!") + + func, has_args = _WIN_FUNCS[win_name] + args = window[1:] if isinstance(window, tuple) else tuple() + if len(args) > 0 and has_args is False: + raise ValueError(f"'{win_name}' does not allow parameters, but {window=}!") + if len(args) == 0 and has_args is True: + raise ValueError(f"'{win_name}' must have parameters, but {window=}!") + # has_args == 'OPTIONAL' allows len(args) == 0 as well as len(args) > 0 + + if not has_args: + return func(Nx, sym=sym, xp=xp, device=device) + + # special cases taken from original implementation: + if func is dpss: + if len(args) != 1: + raise ValueError(f"Window {win_name} must have one parameter but {window=}") + return dpss(Nx, args[0], Kmax=None, sym=sym, xp=xp, device=device) + if func is general_cosine: + if not (xp is None and device is None): + raise ValueError("'general_cosine' does not accept the parameters xp " + + "and device not being None!") + return general_cosine(Nx, *args, sym=sym) + + return func(Nx, *args, sym=sym, xp=xp, device=device) + + +########## complete the docstrings, on import +_xp_device_snippet = {'xp_device_snippet': +"""\ +xp : array_namespace, optional + Optional array namespace. + Should be compatible with the array API standard, or supported by array-api-compat. + Default: ``numpy`` +device: any + optional device specification for output. Should match one of the + supported device specification in ``xp``. +""" +} + + +_names = [x for x in __all__ if x != 'general_cosine'] +for name in _names: + window = vars()[name] + window.__doc__ = doccer.docformat(window.__doc__, _xp_device_snippet) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/windows/windows.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/windows/windows.py new file mode 100644 index 0000000000000000000000000000000000000000..6858f71aceeb29ca6110864d01fb250e8c8ce403 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/signal/windows/windows.py @@ -0,0 +1,23 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.signal.windows` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + +__all__ = [ # noqa: F822 + 'boxcar', 'triang', 'parzen', 'bohman', 'blackman', 'nuttall', + 'blackmanharris', 'flattop', 'bartlett', 'barthann', + 'hamming', 'kaiser', 'gaussian', 'general_cosine', + 'general_gaussian', 'general_hamming', 'chebwin', 'cosine', + 'hann', 'exponential', 'tukey', 'taylor', 'dpss', 'get_window', +] + + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="signal.windows", module="windows", + private_modules=["_windows"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1631de91d139edf93916b8aae3e28aa3e3e44939 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_base.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_base.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d9e383e0d5db7fce303dbbd1206b03d7c5fa7bf8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_base.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_bsr.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_bsr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1135ea1336974d31ccf000075a98878ad10678ca Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_bsr.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_compressed.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_compressed.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04b364fe1973776331d893c5bb8333bb13890c19 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_compressed.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_construct.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_construct.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..92164f7a2fee71d74107a9aed8bd91d985826822 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_construct.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_coo.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_coo.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7d11492e7c28af6c1bb93de2b0f769967d0ad0b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_coo.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_csc.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_csc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..be5ecde48678ac0e5ce7afd21cdecc3f28736fcf Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_csc.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_csr.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_csr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1f1b94e95cbb057f95e321f48e3f0d57db7294b3 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_csr.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_data.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_data.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..319e7c4c53b1c436d4989fbd40ed4245e5ce5959 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_data.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_dia.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_dia.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a0e391363199c543f8e0acfbb5e4661e630fee5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_dia.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_dok.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_dok.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..26720e9c6d220985dda3c3b05c1ee4003872de03 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_dok.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_extract.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_extract.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5881b96da2e98125396a9c20223b17a26bbe01be Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_extract.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_index.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_index.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f7bc4ea56127e29eb55c898df0dafd7bc188a383 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_index.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_lil.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_lil.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7c2ddddd63e211de33a8c651bcea7eb1f49b2ad2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_lil.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_matrix.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_matrix.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8e29aa74f44b25fc4c885ecefa7714e9e87c5bbc Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_matrix.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_matrix_io.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_matrix_io.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5eccfdaf9dd30733402ce7b6f71475df378e3da Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_matrix_io.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_spfuncs.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_spfuncs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..51dcfd760e30dd5dc724389f54c1dfce77696976 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_spfuncs.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_sputils.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_sputils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f1698f33a7ea63e38f4046f1b7f0523f99312ec9 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/_sputils.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/base.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/base.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..14e88986ef7ac1916c21d762bad96420eb40bd0e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/base.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/bsr.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/bsr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d68092d768f960989ed8ad0c9550c8e2e04bfd12 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/bsr.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/compressed.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/compressed.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ea9a15a86b91a4a484317290c1c8303b5caf0145 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/compressed.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/construct.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/construct.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..994e58dabc6876ad1c522bea3792661e696ab654 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/construct.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/coo.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/coo.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..44cfc3ba5da5ecae21fce743cac918d27a036a53 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/coo.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/csc.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/csc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..56427aafc5f67ac7f70980f7994b993ace8c3c1b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/csc.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/csr.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/csr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80039ed74155056af3bfca5224777ba7e68b8c32 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/csr.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/data.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/data.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0495a2086c440d39012bddf985ae074ba36b77ae Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/data.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/dia.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/dia.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65beea4e6f0f8d3e3f1b446d813d245546b6737c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/dia.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/dok.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/dok.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0976f46505779c23212a9def148a5aca30ea090a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/dok.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/extract.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/extract.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..181c19830db25ecb3f524acc58196ed774414f25 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/extract.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/lil.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/lil.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5d38877cc450b53ee859fb00edc164cb821e8fc3 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/lil.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/sparsetools.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/sparsetools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07d5ec4429d207356c6778f58b773a7f1697d42f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/sparsetools.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/spfuncs.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/spfuncs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a9cd79ce23a75d644398c4bc587a54483c4a3cf6 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/spfuncs.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/sputils.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/sputils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ffbbb44fed00322cfef4d8048150c3551ec3b76b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/__pycache__/sputils.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..00ab19af4748147d748fccb51a3710d5c711f4b4 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/__init__.py @@ -0,0 +1,210 @@ +r""" +Compressed sparse graph routines (:mod:`scipy.sparse.csgraph`) +============================================================== + +.. currentmodule:: scipy.sparse.csgraph + +Fast graph algorithms based on sparse matrix representations. + +Contents +-------- + +.. autosummary:: + :toctree: generated/ + + connected_components -- determine connected components of a graph + laplacian -- compute the laplacian of a graph + shortest_path -- compute the shortest path between points on a positive graph + dijkstra -- use Dijkstra's algorithm for shortest path + floyd_warshall -- use the Floyd-Warshall algorithm for shortest path + bellman_ford -- use the Bellman-Ford algorithm for shortest path + johnson -- use Johnson's algorithm for shortest path + yen -- use Yen's algorithm for K-shortest paths between to nodes. + breadth_first_order -- compute a breadth-first order of nodes + depth_first_order -- compute a depth-first order of nodes + breadth_first_tree -- construct the breadth-first tree from a given node + depth_first_tree -- construct a depth-first tree from a given node + minimum_spanning_tree -- construct the minimum spanning tree of a graph + reverse_cuthill_mckee -- compute permutation for reverse Cuthill-McKee ordering + maximum_flow -- solve the maximum flow problem for a graph + maximum_bipartite_matching -- compute a maximum matching of a bipartite graph + min_weight_full_bipartite_matching - compute a minimum weight full matching of a bipartite graph + structural_rank -- compute the structural rank of a graph + NegativeCycleError + +.. autosummary:: + :toctree: generated/ + + construct_dist_matrix + csgraph_from_dense + csgraph_from_masked + csgraph_masked_from_dense + csgraph_to_dense + csgraph_to_masked + reconstruct_path + +Graph Representations +--------------------- +This module uses graphs which are stored in a matrix format. A +graph with N nodes can be represented by an (N x N) adjacency matrix G. +If there is a connection from node i to node j, then G[i, j] = w, where +w is the weight of the connection. For nodes i and j which are +not connected, the value depends on the representation: + +- for dense array representations, non-edges are represented by + G[i, j] = 0, infinity, or NaN. + +- for dense masked representations (of type np.ma.MaskedArray), non-edges + are represented by masked values. This can be useful when graphs with + zero-weight edges are desired. + +- for sparse array representations, non-edges are represented by + non-entries in the matrix. This sort of sparse representation also + allows for edges with zero weights. + +As a concrete example, imagine that you would like to represent the following +undirected graph:: + + G + + (0) + / \ + 1 2 + / \ + (2) (1) + +This graph has three nodes, where node 0 and 1 are connected by an edge of +weight 2, and nodes 0 and 2 are connected by an edge of weight 1. +We can construct the dense, masked, and sparse representations as follows, +keeping in mind that an undirected graph is represented by a symmetric matrix:: + + >>> import numpy as np + >>> G_dense = np.array([[0, 2, 1], + ... [2, 0, 0], + ... [1, 0, 0]]) + >>> G_masked = np.ma.masked_values(G_dense, 0) + >>> from scipy.sparse import csr_array + >>> G_sparse = csr_array(G_dense) + +This becomes more difficult when zero edges are significant. For example, +consider the situation when we slightly modify the above graph:: + + G2 + + (0) + / \ + 0 2 + / \ + (2) (1) + +This is identical to the previous graph, except nodes 0 and 2 are connected +by an edge of zero weight. In this case, the dense representation above +leads to ambiguities: how can non-edges be represented if zero is a meaningful +value? In this case, either a masked or sparse representation must be used +to eliminate the ambiguity:: + + >>> import numpy as np + >>> G2_data = np.array([[np.inf, 2, 0 ], + ... [2, np.inf, np.inf], + ... [0, np.inf, np.inf]]) + >>> G2_masked = np.ma.masked_invalid(G2_data) + >>> from scipy.sparse.csgraph import csgraph_from_dense + >>> # G2_sparse = csr_array(G2_data) would give the wrong result + >>> G2_sparse = csgraph_from_dense(G2_data, null_value=np.inf) + >>> G2_sparse.data + array([ 2., 0., 2., 0.]) + +Here we have used a utility routine from the csgraph submodule in order to +convert the dense representation to a sparse representation which can be +understood by the algorithms in submodule. By viewing the data array, we +can see that the zero values are explicitly encoded in the graph. + +Directed vs. undirected +^^^^^^^^^^^^^^^^^^^^^^^ +Matrices may represent either directed or undirected graphs. This is +specified throughout the csgraph module by a boolean keyword. Graphs are +assumed to be directed by default. In a directed graph, traversal from node +i to node j can be accomplished over the edge G[i, j], but not the edge +G[j, i]. Consider the following dense graph:: + + >>> import numpy as np + >>> G_dense = np.array([[0, 1, 0], + ... [2, 0, 3], + ... [0, 4, 0]]) + +When ``directed=True`` we get the graph:: + + ---1--> ---3--> + (0) (1) (2) + <--2--- <--4--- + +In a non-directed graph, traversal from node i to node j can be +accomplished over either G[i, j] or G[j, i]. If both edges are not null, +and the two have unequal weights, then the smaller of the two is used. + +So for the same graph, when ``directed=False`` we get the graph:: + + (0)--1--(1)--3--(2) + +Note that a symmetric matrix will represent an undirected graph, regardless +of whether the 'directed' keyword is set to True or False. In this case, +using ``directed=True`` generally leads to more efficient computation. + +The routines in this module accept as input either scipy.sparse representations +(csr, csc, or lil format), masked representations, or dense representations +with non-edges indicated by zeros, infinities, and NaN entries. +""" # noqa: E501 + +__docformat__ = "restructuredtext en" + +__all__ = ['connected_components', + 'laplacian', + 'shortest_path', + 'floyd_warshall', + 'dijkstra', + 'bellman_ford', + 'johnson', + 'yen', + 'breadth_first_order', + 'depth_first_order', + 'breadth_first_tree', + 'depth_first_tree', + 'minimum_spanning_tree', + 'reverse_cuthill_mckee', + 'maximum_flow', + 'maximum_bipartite_matching', + 'min_weight_full_bipartite_matching', + 'structural_rank', + 'construct_dist_matrix', + 'reconstruct_path', + 'csgraph_masked_from_dense', + 'csgraph_from_dense', + 'csgraph_from_masked', + 'csgraph_to_dense', + 'csgraph_to_masked', + 'NegativeCycleError'] + +from ._laplacian import laplacian +from ._shortest_path import ( + shortest_path, floyd_warshall, dijkstra, bellman_ford, johnson, yen, + NegativeCycleError +) +from ._traversal import ( + breadth_first_order, depth_first_order, breadth_first_tree, + depth_first_tree, connected_components +) +from ._min_spanning_tree import minimum_spanning_tree +from ._flow import maximum_flow +from ._matching import ( + maximum_bipartite_matching, min_weight_full_bipartite_matching +) +from ._reordering import reverse_cuthill_mckee, structural_rank +from ._tools import ( + construct_dist_matrix, reconstruct_path, csgraph_from_dense, + csgraph_to_dense, csgraph_masked_from_dense, csgraph_from_masked, + csgraph_to_masked +) + +from scipy._lib._testutils import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..db40cca2bf97578b7250675e8aca90a8eaaee248 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/__pycache__/_laplacian.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/__pycache__/_laplacian.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b114d5f5c517a34a20d8688bf32b4bd2b266942 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/__pycache__/_laplacian.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/__pycache__/_validation.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/__pycache__/_validation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b94b52c7376c55497c9f4d163b4df7d487853161 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/__pycache__/_validation.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/_laplacian.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/_laplacian.py new file mode 100644 index 0000000000000000000000000000000000000000..e5529a0662a3f9db006bc5411664908f10d8fe23 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/_laplacian.py @@ -0,0 +1,563 @@ +""" +Laplacian of a compressed-sparse graph +""" + +import numpy as np +from scipy.sparse import issparse +from scipy.sparse.linalg import LinearOperator +from scipy.sparse._sputils import convert_pydata_sparse_to_scipy, is_pydata_spmatrix + + +############################################################################### +# Graph laplacian +def laplacian( + csgraph, + normed=False, + return_diag=False, + use_out_degree=False, + *, + copy=True, + form="array", + dtype=None, + symmetrized=False, +): + """ + Return the Laplacian of a directed graph. + + Parameters + ---------- + csgraph : array_like or sparse array or matrix, 2 dimensions + compressed-sparse graph, with shape (N, N). + normed : bool, optional + If True, then compute symmetrically normalized Laplacian. + Default: False. + return_diag : bool, optional + If True, then also return an array related to vertex degrees. + Default: False. + use_out_degree : bool, optional + If True, then use out-degree instead of in-degree. + This distinction matters only if the graph is asymmetric. + Default: False. + copy: bool, optional + If False, then change `csgraph` in place if possible, + avoiding doubling the memory use. + Default: True, for backward compatibility. + form: 'array', or 'function', or 'lo' + Determines the format of the output Laplacian: + + * 'array' is a numpy array; + * 'function' is a pointer to evaluating the Laplacian-vector + or Laplacian-matrix product; + * 'lo' results in the format of the `LinearOperator`. + + Choosing 'function' or 'lo' always avoids doubling + the memory use, ignoring `copy` value. + Default: 'array', for backward compatibility. + dtype: None or one of numeric numpy dtypes, optional + The dtype of the output. If ``dtype=None``, the dtype of the + output matches the dtype of the input csgraph, except for + the case ``normed=True`` and integer-like csgraph, where + the output dtype is 'float' allowing accurate normalization, + but dramatically increasing the memory use. + Default: None, for backward compatibility. + symmetrized: bool, optional + If True, then the output Laplacian is symmetric/Hermitian. + The symmetrization is done by ``csgraph + csgraph.T.conj`` + without dividing by 2 to preserve integer dtypes if possible + prior to the construction of the Laplacian. + The symmetrization will increase the memory footprint of + sparse matrices unless the sparsity pattern is symmetric or + `form` is 'function' or 'lo'. + Default: False, for backward compatibility. + + Returns + ------- + lap : ndarray, or sparse array or matrix, or `LinearOperator` + The N x N Laplacian of csgraph. It will be a NumPy array (dense) + if the input was dense, or a sparse array otherwise, or + the format of a function or `LinearOperator` if + `form` equals 'function' or 'lo', respectively. + diag : ndarray, optional + The length-N main diagonal of the Laplacian matrix. + For the normalized Laplacian, this is the array of square roots + of vertex degrees or 1 if the degree is zero. + + Notes + ----- + The Laplacian matrix of a graph is sometimes referred to as the + "Kirchhoff matrix" or just the "Laplacian", and is useful in many + parts of spectral graph theory. + In particular, the eigen-decomposition of the Laplacian can give + insight into many properties of the graph, e.g., + is commonly used for spectral data embedding and clustering. + + The constructed Laplacian doubles the memory use if ``copy=True`` and + ``form="array"`` which is the default. + Choosing ``copy=False`` has no effect unless ``form="array"`` + or the matrix is sparse in the ``coo`` format, or dense array, except + for the integer input with ``normed=True`` that forces the float output. + + Sparse input is reformatted into ``coo`` if ``form="array"``, + which is the default. + + If the input adjacency matrix is not symmetric, the Laplacian is + also non-symmetric unless ``symmetrized=True`` is used. + + Diagonal entries of the input adjacency matrix are ignored and + replaced with zeros for the purpose of normalization where ``normed=True``. + The normalization uses the inverse square roots of row-sums of the input + adjacency matrix, and thus may fail if the row-sums contain + negative or complex with a non-zero imaginary part values. + + The normalization is symmetric, making the normalized Laplacian also + symmetric if the input csgraph was symmetric. + + References + ---------- + .. [1] Laplacian matrix. https://en.wikipedia.org/wiki/Laplacian_matrix + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csgraph + + Our first illustration is the symmetric graph + + >>> G = np.arange(4) * np.arange(4)[:, np.newaxis] + >>> G + array([[0, 0, 0, 0], + [0, 1, 2, 3], + [0, 2, 4, 6], + [0, 3, 6, 9]]) + + and its symmetric Laplacian matrix + + >>> csgraph.laplacian(G) + array([[ 0, 0, 0, 0], + [ 0, 5, -2, -3], + [ 0, -2, 8, -6], + [ 0, -3, -6, 9]]) + + The non-symmetric graph + + >>> G = np.arange(9).reshape(3, 3) + >>> G + array([[0, 1, 2], + [3, 4, 5], + [6, 7, 8]]) + + has different row- and column sums, resulting in two varieties + of the Laplacian matrix, using an in-degree, which is the default + + >>> L_in_degree = csgraph.laplacian(G) + >>> L_in_degree + array([[ 9, -1, -2], + [-3, 8, -5], + [-6, -7, 7]]) + + or alternatively an out-degree + + >>> L_out_degree = csgraph.laplacian(G, use_out_degree=True) + >>> L_out_degree + array([[ 3, -1, -2], + [-3, 8, -5], + [-6, -7, 13]]) + + Constructing a symmetric Laplacian matrix, one can add the two as + + >>> L_in_degree + L_out_degree.T + array([[ 12, -4, -8], + [ -4, 16, -12], + [ -8, -12, 20]]) + + or use the ``symmetrized=True`` option + + >>> csgraph.laplacian(G, symmetrized=True) + array([[ 12, -4, -8], + [ -4, 16, -12], + [ -8, -12, 20]]) + + that is equivalent to symmetrizing the original graph + + >>> csgraph.laplacian(G + G.T) + array([[ 12, -4, -8], + [ -4, 16, -12], + [ -8, -12, 20]]) + + The goal of normalization is to make the non-zero diagonal entries + of the Laplacian matrix to be all unit, also scaling off-diagonal + entries correspondingly. The normalization can be done manually, e.g., + + >>> G = np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]]) + >>> L, d = csgraph.laplacian(G, return_diag=True) + >>> L + array([[ 2, -1, -1], + [-1, 2, -1], + [-1, -1, 2]]) + >>> d + array([2, 2, 2]) + >>> scaling = np.sqrt(d) + >>> scaling + array([1.41421356, 1.41421356, 1.41421356]) + >>> (1/scaling)*L*(1/scaling) + array([[ 1. , -0.5, -0.5], + [-0.5, 1. , -0.5], + [-0.5, -0.5, 1. ]]) + + Or using ``normed=True`` option + + >>> L, d = csgraph.laplacian(G, return_diag=True, normed=True) + >>> L + array([[ 1. , -0.5, -0.5], + [-0.5, 1. , -0.5], + [-0.5, -0.5, 1. ]]) + + which now instead of the diagonal returns the scaling coefficients + + >>> d + array([1.41421356, 1.41421356, 1.41421356]) + + Zero scaling coefficients are substituted with 1s, where scaling + has thus no effect, e.g., + + >>> G = np.array([[0, 0, 0], [0, 0, 1], [0, 1, 0]]) + >>> G + array([[0, 0, 0], + [0, 0, 1], + [0, 1, 0]]) + >>> L, d = csgraph.laplacian(G, return_diag=True, normed=True) + >>> L + array([[ 0., -0., -0.], + [-0., 1., -1.], + [-0., -1., 1.]]) + >>> d + array([1., 1., 1.]) + + Only the symmetric normalization is implemented, resulting + in a symmetric Laplacian matrix if and only if its graph is symmetric + and has all non-negative degrees, like in the examples above. + + The output Laplacian matrix is by default a dense array or a sparse + array or matrix inferring its class, shape, format, and dtype from + the input graph matrix: + + >>> G = np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]]).astype(np.float32) + >>> G + array([[0., 1., 1.], + [1., 0., 1.], + [1., 1., 0.]], dtype=float32) + >>> csgraph.laplacian(G) + array([[ 2., -1., -1.], + [-1., 2., -1.], + [-1., -1., 2.]], dtype=float32) + + but can alternatively be generated matrix-free as a LinearOperator: + + >>> L = csgraph.laplacian(G, form="lo") + >>> L + <3x3 _CustomLinearOperator with dtype=float32> + >>> L(np.eye(3)) + array([[ 2., -1., -1.], + [-1., 2., -1.], + [-1., -1., 2.]]) + + or as a lambda-function: + + >>> L = csgraph.laplacian(G, form="function") + >>> L + . at 0x0000012AE6F5A598> + >>> L(np.eye(3)) + array([[ 2., -1., -1.], + [-1., 2., -1.], + [-1., -1., 2.]]) + + The Laplacian matrix is used for + spectral data clustering and embedding + as well as for spectral graph partitioning. + Our final example illustrates the latter + for a noisy directed linear graph. + + >>> from scipy.sparse import diags_array, random_array + >>> from scipy.sparse.linalg import lobpcg + + Create a directed linear graph with ``N=35`` vertices + using a sparse adjacency matrix ``G``: + + >>> N = 35 + >>> G = diags_array(np.ones(N - 1), offsets=1, format="csr") + + Fix a random seed ``rng`` and add a random sparse noise to the graph ``G``: + + >>> rng = np.random.default_rng() + >>> G += 1e-2 * random_array((N, N), density=0.1, rng=rng) + + Set initial approximations for eigenvectors: + + >>> X = rng.random((N, 2)) + + The constant vector of ones is always a trivial eigenvector + of the non-normalized Laplacian to be filtered out: + + >>> Y = np.ones((N, 1)) + + Alternating (1) the sign of the graph weights allows determining + labels for spectral max- and min- cuts in a single loop. + Since the graph is undirected, the option ``symmetrized=True`` + must be used in the construction of the Laplacian. + The option ``normed=True`` cannot be used in (2) for the negative weights + here as the symmetric normalization evaluates square roots. + The option ``form="lo"`` in (2) is matrix-free, i.e., guarantees + a fixed memory footprint and read-only access to the graph. + Calling the eigenvalue solver ``lobpcg`` (3) computes the Fiedler vector + that determines the labels as the signs of its components in (5). + Since the sign in an eigenvector is not deterministic and can flip, + we fix the sign of the first component to be always +1 in (4). + + >>> for cut in ["max", "min"]: + ... G = -G # 1. + ... L = csgraph.laplacian(G, symmetrized=True, form="lo") # 2. + ... _, eves = lobpcg(L, X, Y=Y, largest=False, tol=1e-2) # 3. + ... eves *= np.sign(eves[0, 0]) # 4. + ... print(cut + "-cut labels:\\n", 1 * (eves[:, 0]>0)) # 5. + max-cut labels: + [1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1] + min-cut labels: + [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] + + As anticipated for a (slightly noisy) linear graph, + the max-cut strips all the edges of the graph coloring all + odd vertices into one color and all even vertices into another one, + while the balanced min-cut partitions the graph + in the middle by deleting a single edge. + Both determined partitions are optimal. + """ + is_pydata_sparse = is_pydata_spmatrix(csgraph) + if is_pydata_sparse: + pydata_sparse_cls = csgraph.__class__ + csgraph = convert_pydata_sparse_to_scipy(csgraph) + if csgraph.ndim != 2 or csgraph.shape[0] != csgraph.shape[1]: + raise ValueError('csgraph must be a square matrix or array') + + if normed and ( + np.issubdtype(csgraph.dtype, np.signedinteger) + or np.issubdtype(csgraph.dtype, np.uint) + ): + csgraph = csgraph.astype(np.float64) + + if form == "array": + create_lap = ( + _laplacian_sparse if issparse(csgraph) else _laplacian_dense + ) + else: + create_lap = ( + _laplacian_sparse_flo + if issparse(csgraph) + else _laplacian_dense_flo + ) + + degree_axis = 1 if use_out_degree else 0 + + lap, d = create_lap( + csgraph, + normed=normed, + axis=degree_axis, + copy=copy, + form=form, + dtype=dtype, + symmetrized=symmetrized, + ) + if is_pydata_sparse: + lap = pydata_sparse_cls.from_scipy_sparse(lap) + if return_diag: + return lap, d + return lap + + +def _setdiag_dense(m, d): + step = len(d) + 1 + m.flat[::step] = d + + +def _laplace(m, d): + return lambda v: v * d[:, np.newaxis] - m @ v + + +def _laplace_normed(m, d, nd): + laplace = _laplace(m, d) + return lambda v: nd[:, np.newaxis] * laplace(v * nd[:, np.newaxis]) + + +def _laplace_sym(m, d): + return ( + lambda v: v * d[:, np.newaxis] + - m @ v + - np.transpose(np.conjugate(np.transpose(np.conjugate(v)) @ m)) + ) + + +def _laplace_normed_sym(m, d, nd): + laplace_sym = _laplace_sym(m, d) + return lambda v: nd[:, np.newaxis] * laplace_sym(v * nd[:, np.newaxis]) + + +def _linearoperator(mv, shape, dtype): + return LinearOperator(matvec=mv, matmat=mv, shape=shape, dtype=dtype) + + +def _laplacian_sparse_flo(graph, normed, axis, copy, form, dtype, symmetrized): + # The keyword argument `copy` is unused and has no effect here. + del copy + + if dtype is None: + dtype = graph.dtype + + graph_sum = np.asarray(graph.sum(axis=axis)).ravel() + graph_diagonal = graph.diagonal() + diag = graph_sum - graph_diagonal + if symmetrized: + graph_sum += np.asarray(graph.sum(axis=1 - axis)).ravel() + diag = graph_sum - graph_diagonal - graph_diagonal + + if normed: + isolated_node_mask = diag == 0 + w = np.where(isolated_node_mask, 1, np.sqrt(diag)) + if symmetrized: + md = _laplace_normed_sym(graph, graph_sum, 1.0 / w) + else: + md = _laplace_normed(graph, graph_sum, 1.0 / w) + if form == "function": + return md, w.astype(dtype, copy=False) + elif form == "lo": + m = _linearoperator(md, shape=graph.shape, dtype=dtype) + return m, w.astype(dtype, copy=False) + else: + raise ValueError(f"Invalid form: {form!r}") + else: + if symmetrized: + md = _laplace_sym(graph, graph_sum) + else: + md = _laplace(graph, graph_sum) + if form == "function": + return md, diag.astype(dtype, copy=False) + elif form == "lo": + m = _linearoperator(md, shape=graph.shape, dtype=dtype) + return m, diag.astype(dtype, copy=False) + else: + raise ValueError(f"Invalid form: {form!r}") + + +def _laplacian_sparse(graph, normed, axis, copy, form, dtype, symmetrized): + # The keyword argument `form` is unused and has no effect here. + del form + + if dtype is None: + dtype = graph.dtype + + needs_copy = False + if graph.format in ('lil', 'dok'): + m = graph.tocoo() + else: + m = graph + if copy: + needs_copy = True + + if symmetrized: + m += m.T.conj() + + w = np.asarray(m.sum(axis=axis)).ravel() - m.diagonal() + if normed: + m = m.tocoo(copy=needs_copy) + isolated_node_mask = (w == 0) + w = np.where(isolated_node_mask, 1, np.sqrt(w)) + m.data /= w[m.row] + m.data /= w[m.col] + m.data *= -1 + m.setdiag(1 - isolated_node_mask) + else: + if m.format == 'dia': + m = m.copy() + else: + m = m.tocoo(copy=needs_copy) + m.data *= -1 + m.setdiag(w) + + return m.astype(dtype, copy=False), w.astype(dtype) + + +def _laplacian_dense_flo(graph, normed, axis, copy, form, dtype, symmetrized): + + if copy: + m = np.array(graph) + else: + m = np.asarray(graph) + + if dtype is None: + dtype = m.dtype + + graph_sum = m.sum(axis=axis) + graph_diagonal = m.diagonal() + diag = graph_sum - graph_diagonal + if symmetrized: + graph_sum += m.sum(axis=1 - axis) + diag = graph_sum - graph_diagonal - graph_diagonal + + if normed: + isolated_node_mask = diag == 0 + w = np.where(isolated_node_mask, 1, np.sqrt(diag)) + if symmetrized: + md = _laplace_normed_sym(m, graph_sum, 1.0 / w) + else: + md = _laplace_normed(m, graph_sum, 1.0 / w) + if form == "function": + return md, w.astype(dtype, copy=False) + elif form == "lo": + m = _linearoperator(md, shape=graph.shape, dtype=dtype) + return m, w.astype(dtype, copy=False) + else: + raise ValueError(f"Invalid form: {form!r}") + else: + if symmetrized: + md = _laplace_sym(m, graph_sum) + else: + md = _laplace(m, graph_sum) + if form == "function": + return md, diag.astype(dtype, copy=False) + elif form == "lo": + m = _linearoperator(md, shape=graph.shape, dtype=dtype) + return m, diag.astype(dtype, copy=False) + else: + raise ValueError(f"Invalid form: {form!r}") + + +def _laplacian_dense(graph, normed, axis, copy, form, dtype, symmetrized): + + if form != "array": + raise ValueError(f'{form!r} must be "array"') + + if dtype is None: + dtype = graph.dtype + + if copy: + m = np.array(graph) + else: + m = np.asarray(graph) + + if dtype is None: + dtype = m.dtype + + if symmetrized: + m += m.T.conj() + np.fill_diagonal(m, 0) + w = m.sum(axis=axis) + if normed: + isolated_node_mask = (w == 0) + w = np.where(isolated_node_mask, 1, np.sqrt(w)) + m /= w + m /= w[:, np.newaxis] + m *= -1 + _setdiag_dense(m, 1 - isolated_node_mask) + else: + m *= -1 + _setdiag_dense(m, w) + + return m.astype(dtype, copy=False), w.astype(dtype, copy=False) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/_min_spanning_tree.cpython-312-x86_64-linux-gnu.so b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/_min_spanning_tree.cpython-312-x86_64-linux-gnu.so new file mode 100644 index 0000000000000000000000000000000000000000..ca5df9fc85cb5fd1c02b79626c8934eac02724be Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/_min_spanning_tree.cpython-312-x86_64-linux-gnu.so differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/_validation.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/_validation.py new file mode 100644 index 0000000000000000000000000000000000000000..6eb9ce811b73e751ebb1cd6b226b73f7bcfe7ceb --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/_validation.py @@ -0,0 +1,66 @@ +import numpy as np +from scipy.sparse import issparse +from scipy.sparse._sputils import convert_pydata_sparse_to_scipy +from scipy.sparse.csgraph._tools import ( + csgraph_to_dense, csgraph_from_dense, + csgraph_masked_from_dense, csgraph_from_masked +) + +DTYPE = np.float64 + + +def validate_graph(csgraph, directed, dtype=DTYPE, + csr_output=True, dense_output=True, + copy_if_dense=False, copy_if_sparse=False, + null_value_in=0, null_value_out=np.inf, + infinity_null=True, nan_null=True): + """Routine for validation and conversion of csgraph inputs""" + if not (csr_output or dense_output): + raise ValueError("Internal: dense or csr output must be true") + + accept_fv = [null_value_in] + if infinity_null: + accept_fv.append(np.inf) + if nan_null: + accept_fv.append(np.nan) + csgraph = convert_pydata_sparse_to_scipy(csgraph, accept_fv=accept_fv) + + # if undirected and csc storage, then transposing in-place + # is quicker than later converting to csr. + if (not directed) and issparse(csgraph) and csgraph.format == "csc": + csgraph = csgraph.T + + if issparse(csgraph): + if csr_output: + csgraph = csgraph.tocsr(copy=copy_if_sparse).astype(DTYPE, copy=False) + else: + csgraph = csgraph_to_dense(csgraph, null_value=null_value_out) + elif np.ma.isMaskedArray(csgraph): + if dense_output: + mask = csgraph.mask + csgraph = np.array(csgraph.data, dtype=DTYPE, copy=copy_if_dense) + csgraph[mask] = null_value_out + else: + csgraph = csgraph_from_masked(csgraph) + else: + if dense_output: + csgraph = csgraph_masked_from_dense(csgraph, + copy=copy_if_dense, + null_value=null_value_in, + nan_null=nan_null, + infinity_null=infinity_null) + mask = csgraph.mask + csgraph = np.asarray(csgraph.data, dtype=DTYPE) + csgraph[mask] = null_value_out + else: + csgraph = csgraph_from_dense(csgraph, null_value=null_value_in, + infinity_null=infinity_null, + nan_null=nan_null) + + if csgraph.ndim != 2: + raise ValueError("compressed-sparse graph must be 2-D") + + if csgraph.shape[0] != csgraph.shape[1]: + raise ValueError("compressed-sparse graph must be shape (N, N)") + + return csgraph diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..447b6c050e965a8c6671f321fc9c287b8e063352 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_connected_components.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_connected_components.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..471d67a6f81ab02b78e28a3305d5a4556c91c0c9 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_connected_components.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_conversions.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_conversions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7a09c3bfd7cda51f0c195c0e91c5c7022dabe66 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_conversions.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_flow.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_flow.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eaad922569617eeada1ec27cc8b1f5f25b34c385 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_flow.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_graph_laplacian.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_graph_laplacian.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d1238b78f57e72dd13deb506bcf927b5dfc76c55 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_graph_laplacian.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_matching.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_matching.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2f4103666bddd7f659fc0073c84505ef540b3429 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_matching.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_pydata_sparse.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_pydata_sparse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f00017051fd142497b91b028c2292f1474c55415 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_pydata_sparse.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_reordering.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_reordering.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a91bc414cfa61fcba93939f7c42932ebbf9395f5 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_reordering.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_shortest_path.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_shortest_path.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b761f52acadc22eb35aa67db857f59f9b0e20d38 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_shortest_path.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_spanning_tree.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_spanning_tree.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..237f7b387a2d21d5525978471d8b1c92f1bf93e9 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_spanning_tree.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_traversal.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_traversal.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ea62f88fb896eec2eec28139427d721c36f78112 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/__pycache__/test_traversal.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_connected_components.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_connected_components.py new file mode 100644 index 0000000000000000000000000000000000000000..0b190a24deb9f2818893a120f8ea376fbfb8d6fe --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_connected_components.py @@ -0,0 +1,119 @@ +import numpy as np +from numpy.testing import assert_equal, assert_array_almost_equal +from scipy.sparse import csgraph, csr_array + + +def test_weak_connections(): + Xde = np.array([[0, 1, 0], + [0, 0, 0], + [0, 0, 0]]) + + Xsp = csgraph.csgraph_from_dense(Xde, null_value=0) + + for X in Xsp, Xde: + n_components, labels =\ + csgraph.connected_components(X, directed=True, + connection='weak') + + assert_equal(n_components, 2) + assert_array_almost_equal(labels, [0, 0, 1]) + + +def test_strong_connections(): + X1de = np.array([[0, 1, 0], + [0, 0, 0], + [0, 0, 0]]) + X2de = X1de + X1de.T + + X1sp = csgraph.csgraph_from_dense(X1de, null_value=0) + X2sp = csgraph.csgraph_from_dense(X2de, null_value=0) + + for X in X1sp, X1de: + n_components, labels =\ + csgraph.connected_components(X, directed=True, + connection='strong') + + assert_equal(n_components, 3) + labels.sort() + assert_array_almost_equal(labels, [0, 1, 2]) + + for X in X2sp, X2de: + n_components, labels =\ + csgraph.connected_components(X, directed=True, + connection='strong') + + assert_equal(n_components, 2) + labels.sort() + assert_array_almost_equal(labels, [0, 0, 1]) + + +def test_strong_connections2(): + X = np.array([[0, 0, 0, 0, 0, 0], + [1, 0, 1, 0, 0, 0], + [0, 0, 0, 1, 0, 0], + [0, 0, 1, 0, 1, 0], + [0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 1, 0]]) + n_components, labels =\ + csgraph.connected_components(X, directed=True, + connection='strong') + assert_equal(n_components, 5) + labels.sort() + assert_array_almost_equal(labels, [0, 1, 2, 2, 3, 4]) + + +def test_weak_connections2(): + X = np.array([[0, 0, 0, 0, 0, 0], + [1, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0], + [0, 0, 1, 0, 1, 0], + [0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 1, 0]]) + n_components, labels =\ + csgraph.connected_components(X, directed=True, + connection='weak') + assert_equal(n_components, 2) + labels.sort() + assert_array_almost_equal(labels, [0, 0, 1, 1, 1, 1]) + + +def test_ticket1876(): + # Regression test: this failed in the original implementation + # There should be two strongly-connected components; previously gave one + g = np.array([[0, 1, 1, 0], + [1, 0, 0, 1], + [0, 0, 0, 1], + [0, 0, 1, 0]]) + n_components, labels = csgraph.connected_components(g, connection='strong') + + assert_equal(n_components, 2) + assert_equal(labels[0], labels[1]) + assert_equal(labels[2], labels[3]) + + +def test_fully_connected_graph(): + # Fully connected dense matrices raised an exception. + # https://github.com/scipy/scipy/issues/3818 + g = np.ones((4, 4)) + n_components, labels = csgraph.connected_components(g) + assert_equal(n_components, 1) + + +def test_int64_indices_undirected(): + # See https://github.com/scipy/scipy/issues/18716 + g = csr_array(([1], np.array([[0], [1]], dtype=np.int64)), shape=(2, 2)) + assert g.indices.dtype == np.int64 + n, labels = csgraph.connected_components(g, directed=False) + assert n == 1 + assert_array_almost_equal(labels, [0, 0]) + + +def test_int64_indices_directed(): + # See https://github.com/scipy/scipy/issues/18716 + g = csr_array(([1], np.array([[0], [1]], dtype=np.int64)), shape=(2, 2)) + assert g.indices.dtype == np.int64 + n, labels = csgraph.connected_components(g, directed=True, + connection='strong') + assert n == 2 + assert_array_almost_equal(labels, [1, 0]) + diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_conversions.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_conversions.py new file mode 100644 index 0000000000000000000000000000000000000000..65f141e5b371367018a6e9985f8325850d8972da --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_conversions.py @@ -0,0 +1,61 @@ +import numpy as np +from numpy.testing import assert_array_almost_equal +from scipy.sparse import csr_array +from scipy.sparse.csgraph import csgraph_from_dense, csgraph_to_dense + + +def test_csgraph_from_dense(): + np.random.seed(1234) + G = np.random.random((10, 10)) + some_nulls = (G < 0.4) + all_nulls = (G < 0.8) + + for null_value in [0, np.nan, np.inf]: + G[all_nulls] = null_value + with np.errstate(invalid="ignore"): + G_csr = csgraph_from_dense(G, null_value=0) + + G[all_nulls] = 0 + assert_array_almost_equal(G, G_csr.toarray()) + + for null_value in [np.nan, np.inf]: + G[all_nulls] = 0 + G[some_nulls] = null_value + with np.errstate(invalid="ignore"): + G_csr = csgraph_from_dense(G, null_value=0) + + G[all_nulls] = 0 + assert_array_almost_equal(G, G_csr.toarray()) + + +def test_csgraph_to_dense(): + np.random.seed(1234) + G = np.random.random((10, 10)) + nulls = (G < 0.8) + G[nulls] = np.inf + + G_csr = csgraph_from_dense(G) + + for null_value in [0, 10, -np.inf, np.inf]: + G[nulls] = null_value + assert_array_almost_equal(G, csgraph_to_dense(G_csr, null_value)) + + +def test_multiple_edges(): + # create a random square matrix with an even number of elements + np.random.seed(1234) + X = np.random.random((10, 10)) + Xcsr = csr_array(X) + + # now double-up every other column + Xcsr.indices[::2] = Xcsr.indices[1::2] + + # normal sparse toarray() will sum the duplicated edges + Xdense = Xcsr.toarray() + assert_array_almost_equal(Xdense[:, 1::2], + X[:, ::2] + X[:, 1::2]) + + # csgraph_to_dense chooses the minimum of each duplicated edge + Xdense = csgraph_to_dense(Xcsr) + assert_array_almost_equal(Xdense[:, 1::2], + np.minimum(X[:, ::2], X[:, 1::2])) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_flow.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_flow.py new file mode 100644 index 0000000000000000000000000000000000000000..c92eb985a1145c4b7c1777f0449bb423402f6d66 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_flow.py @@ -0,0 +1,209 @@ +import numpy as np +from numpy.testing import assert_array_equal +import pytest + +from scipy.sparse import csr_array, csc_array, csr_matrix +from scipy.sparse.csgraph import maximum_flow +from scipy.sparse.csgraph._flow import ( + _add_reverse_edges, _make_edge_pointers, _make_tails +) + +methods = ['edmonds_karp', 'dinic'] + +def test_raises_on_dense_input(): + with pytest.raises(TypeError): + graph = np.array([[0, 1], [0, 0]]) + maximum_flow(graph, 0, 1) + maximum_flow(graph, 0, 1, method='edmonds_karp') + + +def test_raises_on_csc_input(): + with pytest.raises(TypeError): + graph = csc_array([[0, 1], [0, 0]]) + maximum_flow(graph, 0, 1) + maximum_flow(graph, 0, 1, method='edmonds_karp') + + +def test_raises_on_floating_point_input(): + with pytest.raises(ValueError): + graph = csr_array([[0, 1.5], [0, 0]], dtype=np.float64) + maximum_flow(graph, 0, 1) + maximum_flow(graph, 0, 1, method='edmonds_karp') + + +def test_raises_on_non_square_input(): + with pytest.raises(ValueError): + graph = csr_array([[0, 1, 2], [2, 1, 0]]) + maximum_flow(graph, 0, 1) + + +def test_raises_when_source_is_sink(): + with pytest.raises(ValueError): + graph = csr_array([[0, 1], [0, 0]]) + maximum_flow(graph, 0, 0) + maximum_flow(graph, 0, 0, method='edmonds_karp') + + +@pytest.mark.parametrize('method', methods) +@pytest.mark.parametrize('source', [-1, 2, 3]) +def test_raises_when_source_is_out_of_bounds(source, method): + with pytest.raises(ValueError): + graph = csr_array([[0, 1], [0, 0]]) + maximum_flow(graph, source, 1, method=method) + + +@pytest.mark.parametrize('method', methods) +@pytest.mark.parametrize('sink', [-1, 2, 3]) +def test_raises_when_sink_is_out_of_bounds(sink, method): + with pytest.raises(ValueError): + graph = csr_array([[0, 1], [0, 0]]) + maximum_flow(graph, 0, sink, method=method) + + +@pytest.mark.parametrize('method', methods) +def test_simple_graph(method): + # This graph looks as follows: + # (0) --5--> (1) + graph = csr_array([[0, 5], [0, 0]]) + res = maximum_flow(graph, 0, 1, method=method) + assert res.flow_value == 5 + expected_flow = np.array([[0, 5], [-5, 0]]) + assert_array_equal(res.flow.toarray(), expected_flow) + + +@pytest.mark.parametrize('method', methods) +def test_return_type(method): + graph = csr_array([[0, 5], [0, 0]]) + assert isinstance(maximum_flow(graph, 0, 1, method=method).flow, csr_array) + graph = csr_matrix([[0, 5], [0, 0]]) + assert isinstance(maximum_flow(graph, 0, 1, method=method).flow, csr_matrix) + + +@pytest.mark.parametrize('method', methods) +def test_bottle_neck_graph(method): + # This graph cannot use the full capacity between 0 and 1: + # (0) --5--> (1) --3--> (2) + graph = csr_array([[0, 5, 0], [0, 0, 3], [0, 0, 0]]) + res = maximum_flow(graph, 0, 2, method=method) + assert res.flow_value == 3 + expected_flow = np.array([[0, 3, 0], [-3, 0, 3], [0, -3, 0]]) + assert_array_equal(res.flow.toarray(), expected_flow) + + +@pytest.mark.parametrize('method', methods) +def test_backwards_flow(method): + # This example causes backwards flow between vertices 3 and 4, + # and so this test ensures that we handle that accordingly. See + # https://stackoverflow.com/q/38843963/5085211 + # for more information. + graph = csr_array([[0, 10, 0, 0, 10, 0, 0, 0], + [0, 0, 10, 0, 0, 0, 0, 0], + [0, 0, 0, 10, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 10], + [0, 0, 0, 10, 0, 10, 0, 0], + [0, 0, 0, 0, 0, 0, 10, 0], + [0, 0, 0, 0, 0, 0, 0, 10], + [0, 0, 0, 0, 0, 0, 0, 0]]) + res = maximum_flow(graph, 0, 7, method=method) + assert res.flow_value == 20 + expected_flow = np.array([[0, 10, 0, 0, 10, 0, 0, 0], + [-10, 0, 10, 0, 0, 0, 0, 0], + [0, -10, 0, 10, 0, 0, 0, 0], + [0, 0, -10, 0, 0, 0, 0, 10], + [-10, 0, 0, 0, 0, 10, 0, 0], + [0, 0, 0, 0, -10, 0, 10, 0], + [0, 0, 0, 0, 0, -10, 0, 10], + [0, 0, 0, -10, 0, 0, -10, 0]]) + assert_array_equal(res.flow.toarray(), expected_flow) + + +@pytest.mark.parametrize('method', methods) +def test_example_from_clrs_chapter_26_1(method): + # See page 659 in CLRS second edition, but note that the maximum flow + # we find is slightly different than the one in CLRS; we push a flow of + # 12 to v_1 instead of v_2. + graph = csr_array([[0, 16, 13, 0, 0, 0], + [0, 0, 10, 12, 0, 0], + [0, 4, 0, 0, 14, 0], + [0, 0, 9, 0, 0, 20], + [0, 0, 0, 7, 0, 4], + [0, 0, 0, 0, 0, 0]]) + res = maximum_flow(graph, 0, 5, method=method) + assert res.flow_value == 23 + expected_flow = np.array([[0, 12, 11, 0, 0, 0], + [-12, 0, 0, 12, 0, 0], + [-11, 0, 0, 0, 11, 0], + [0, -12, 0, 0, -7, 19], + [0, 0, -11, 7, 0, 4], + [0, 0, 0, -19, -4, 0]]) + assert_array_equal(res.flow.toarray(), expected_flow) + + +@pytest.mark.parametrize('method', methods) +def test_disconnected_graph(method): + # This tests the following disconnected graph: + # (0) --5--> (1) (2) --3--> (3) + graph = csr_array([[0, 5, 0, 0], + [0, 0, 0, 0], + [0, 0, 9, 3], + [0, 0, 0, 0]]) + res = maximum_flow(graph, 0, 3, method=method) + assert res.flow_value == 0 + expected_flow = np.zeros((4, 4), dtype=np.int32) + assert_array_equal(res.flow.toarray(), expected_flow) + + +@pytest.mark.parametrize('method', methods) +def test_add_reverse_edges_large_graph(method): + # Regression test for https://github.com/scipy/scipy/issues/14385 + n = 100_000 + indices = np.arange(1, n) + indptr = np.array(list(range(n)) + [n - 1]) + data = np.ones(n - 1, dtype=np.int32) + graph = csr_array((data, indices, indptr), shape=(n, n)) + res = maximum_flow(graph, 0, n - 1, method=method) + assert res.flow_value == 1 + expected_flow = graph - graph.transpose() + assert_array_equal(res.flow.data, expected_flow.data) + assert_array_equal(res.flow.indices, expected_flow.indices) + assert_array_equal(res.flow.indptr, expected_flow.indptr) + + +@pytest.mark.parametrize("a,b_data_expected", [ + ([[]], []), + ([[0], [0]], []), + ([[1, 0, 2], [0, 0, 0], [0, 3, 0]], [1, 2, 0, 0, 3]), + ([[9, 8, 7], [4, 5, 6], [0, 0, 0]], [9, 8, 7, 4, 5, 6, 0, 0])]) +def test_add_reverse_edges(a, b_data_expected): + """Test that the reversal of the edges of the input graph works + as expected. + """ + a = csr_array(a, dtype=np.int32, shape=(len(a), len(a))) + b = _add_reverse_edges(a) + assert_array_equal(b.data, b_data_expected) + + +@pytest.mark.parametrize("a,expected", [ + ([[]], []), + ([[0]], []), + ([[1]], [0]), + ([[0, 1], [10, 0]], [1, 0]), + ([[1, 0, 2], [0, 0, 3], [4, 5, 0]], [0, 3, 4, 1, 2]) +]) +def test_make_edge_pointers(a, expected): + a = csr_array(a, dtype=np.int32) + rev_edge_ptr = _make_edge_pointers(a) + assert_array_equal(rev_edge_ptr, expected) + + +@pytest.mark.parametrize("a,expected", [ + ([[]], []), + ([[0]], []), + ([[1]], [0]), + ([[0, 1], [10, 0]], [0, 1]), + ([[1, 0, 2], [0, 0, 3], [4, 5, 0]], [0, 0, 1, 2, 2]) +]) +def test_make_tails(a, expected): + a = csr_array(a, dtype=np.int32) + tails = _make_tails(a) + assert_array_equal(tails, expected) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_graph_laplacian.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_graph_laplacian.py new file mode 100644 index 0000000000000000000000000000000000000000..8d4a99f43b5a17b12726517e0defc970a2a37c4b --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_graph_laplacian.py @@ -0,0 +1,368 @@ +import pytest +import numpy as np +from numpy.testing import assert_allclose +from pytest import raises as assert_raises +from scipy import sparse + +from scipy.sparse import csgraph +from scipy._lib._util import np_long, np_ulong + + +def check_int_type(mat): + return np.issubdtype(mat.dtype, np.signedinteger) or np.issubdtype( + mat.dtype, np_ulong + ) + + +def test_laplacian_value_error(): + for t in int, float, complex: + for m in ([1, 1], + [[[1]]], + [[1, 2, 3], [4, 5, 6]], + [[1, 2], [3, 4], [5, 5]]): + A = np.array(m, dtype=t) + assert_raises(ValueError, csgraph.laplacian, A) + + +def _explicit_laplacian(x, normed=False): + if sparse.issparse(x): + x = x.toarray() + x = np.asarray(x) + y = -1.0 * x + for j in range(y.shape[0]): + y[j,j] = x[j,j+1:].sum() + x[j,:j].sum() + if normed: + d = np.diag(y).copy() + d[d == 0] = 1.0 + y /= d[:,None]**.5 + y /= d[None,:]**.5 + return y + + +def _check_symmetric_graph_laplacian(mat, normed, copy=True): + if not hasattr(mat, 'shape'): + mat = eval(mat, dict(np=np, sparse=sparse)) + + if sparse.issparse(mat): + sp_mat = mat + mat = sp_mat.toarray() + else: + sp_mat = sparse.csr_array(mat) + + mat_copy = np.copy(mat) + sp_mat_copy = sparse.csr_array(sp_mat, copy=True) + + n_nodes = mat.shape[0] + explicit_laplacian = _explicit_laplacian(mat, normed=normed) + laplacian = csgraph.laplacian(mat, normed=normed, copy=copy) + sp_laplacian = csgraph.laplacian(sp_mat, normed=normed, + copy=copy) + + if copy: + assert_allclose(mat, mat_copy) + _assert_allclose_sparse(sp_mat, sp_mat_copy) + else: + if not (normed and check_int_type(mat)): + assert_allclose(laplacian, mat) + if sp_mat.format == 'coo': + _assert_allclose_sparse(sp_laplacian, sp_mat) + + assert_allclose(laplacian, sp_laplacian.toarray()) + + for tested in [laplacian, sp_laplacian.toarray()]: + if not normed: + assert_allclose(tested.sum(axis=0), np.zeros(n_nodes)) + assert_allclose(tested.T, tested) + assert_allclose(tested, explicit_laplacian) + + +def test_symmetric_graph_laplacian(): + symmetric_mats = ( + 'np.arange(10) * np.arange(10)[:, np.newaxis]', + 'np.ones((7, 7))', + 'np.eye(19)', + 'sparse.diags([1.0, 1.0], [-1, 1], shape=(4, 4))', + 'sparse.diags([1.0, 1.0], [-1, 1], shape=(4, 4)).toarray()', + 'sparse.diags([1.0, 1.0], [-1, 1], shape=(4, 4)).todense()', + 'np.vander(np.arange(4)) + np.vander(np.arange(4)).T' + ) + for mat in symmetric_mats: + for normed in True, False: + for copy in True, False: + _check_symmetric_graph_laplacian(mat, normed, copy) + + +def _assert_allclose_sparse(a, b, **kwargs): + # helper function that can deal with sparse matrices + if sparse.issparse(a): + a = a.toarray() + if sparse.issparse(b): + b = b.toarray() + assert_allclose(a, b, **kwargs) + + +def _check_laplacian_dtype_none( + A, desired_L, desired_d, normed, use_out_degree, copy, dtype, arr_type +): + mat = arr_type(A, dtype=dtype) + L, d = csgraph.laplacian( + mat, + normed=normed, + return_diag=True, + use_out_degree=use_out_degree, + copy=copy, + dtype=None, + ) + if normed and check_int_type(mat): + assert L.dtype == np.float64 + assert d.dtype == np.float64 + _assert_allclose_sparse(L, desired_L, atol=1e-12) + _assert_allclose_sparse(d, desired_d, atol=1e-12) + else: + assert L.dtype == dtype + assert d.dtype == dtype + desired_L = np.asarray(desired_L).astype(dtype) + desired_d = np.asarray(desired_d).astype(dtype) + _assert_allclose_sparse(L, desired_L, atol=1e-12) + _assert_allclose_sparse(d, desired_d, atol=1e-12) + + if not copy: + if not (normed and check_int_type(mat)): + if type(mat) is np.ndarray: + assert_allclose(L, mat) + elif mat.format == "coo": + _assert_allclose_sparse(L, mat) + + +def _check_laplacian_dtype( + A, desired_L, desired_d, normed, use_out_degree, copy, dtype, arr_type +): + mat = arr_type(A, dtype=dtype) + L, d = csgraph.laplacian( + mat, + normed=normed, + return_diag=True, + use_out_degree=use_out_degree, + copy=copy, + dtype=dtype, + ) + assert L.dtype == dtype + assert d.dtype == dtype + desired_L = np.asarray(desired_L).astype(dtype) + desired_d = np.asarray(desired_d).astype(dtype) + _assert_allclose_sparse(L, desired_L, atol=1e-12) + _assert_allclose_sparse(d, desired_d, atol=1e-12) + + if not copy: + if not (normed and check_int_type(mat)): + if type(mat) is np.ndarray: + assert_allclose(L, mat) + elif mat.format == 'coo': + _assert_allclose_sparse(L, mat) + + +INT_DTYPES = (np.intc, np_long, np.longlong) +REAL_DTYPES = (np.float32, np.float64, np.longdouble) +COMPLEX_DTYPES = (np.complex64, np.complex128, np.clongdouble) +DTYPES = INT_DTYPES + REAL_DTYPES + COMPLEX_DTYPES + + +@pytest.mark.parametrize("dtype", DTYPES) +@pytest.mark.parametrize("arr_type", [np.array, + sparse.csr_matrix, + sparse.coo_matrix, + sparse.csr_array, + sparse.coo_array]) +@pytest.mark.parametrize("copy", [True, False]) +@pytest.mark.parametrize("normed", [True, False]) +@pytest.mark.parametrize("use_out_degree", [True, False]) +def test_asymmetric_laplacian(use_out_degree, normed, + copy, dtype, arr_type): + # adjacency matrix + A = [[0, 1, 0], + [4, 2, 0], + [0, 0, 0]] + A = arr_type(np.array(A), dtype=dtype) + A_copy = A.copy() + + if not normed and use_out_degree: + # Laplacian matrix using out-degree + L = [[1, -1, 0], + [-4, 4, 0], + [0, 0, 0]] + d = [1, 4, 0] + + if normed and use_out_degree: + # normalized Laplacian matrix using out-degree + L = [[1, -0.5, 0], + [-2, 1, 0], + [0, 0, 0]] + d = [1, 2, 1] + + if not normed and not use_out_degree: + # Laplacian matrix using in-degree + L = [[4, -1, 0], + [-4, 1, 0], + [0, 0, 0]] + d = [4, 1, 0] + + if normed and not use_out_degree: + # normalized Laplacian matrix using in-degree + L = [[1, -0.5, 0], + [-2, 1, 0], + [0, 0, 0]] + d = [2, 1, 1] + + _check_laplacian_dtype_none( + A, + L, + d, + normed=normed, + use_out_degree=use_out_degree, + copy=copy, + dtype=dtype, + arr_type=arr_type, + ) + + _check_laplacian_dtype( + A_copy, + L, + d, + normed=normed, + use_out_degree=use_out_degree, + copy=copy, + dtype=dtype, + arr_type=arr_type, + ) + + +@pytest.mark.parametrize("fmt", ['csr', 'csc', 'coo', 'lil', + 'dok', 'dia', 'bsr']) +@pytest.mark.parametrize("normed", [True, False]) +@pytest.mark.parametrize("copy", [True, False]) +def test_sparse_formats(fmt, normed, copy): + mat = sparse.diags_array([1.0, 1.0], offsets=[-1, 1], shape=(4, 4), format=fmt) + _check_symmetric_graph_laplacian(mat, normed, copy) + + +@pytest.mark.parametrize( + "arr_type", [np.asarray, + sparse.csr_matrix, + sparse.coo_matrix, + sparse.csr_array, + sparse.coo_array] +) +@pytest.mark.parametrize("form", ["array", "function", "lo"]) +def test_laplacian_symmetrized(arr_type, form): + # adjacency matrix + n = 3 + mat = arr_type(np.arange(n * n).reshape(n, n)) + L_in, d_in = csgraph.laplacian( + mat, + return_diag=True, + form=form, + ) + L_out, d_out = csgraph.laplacian( + mat, + return_diag=True, + use_out_degree=True, + form=form, + ) + Ls, ds = csgraph.laplacian( + mat, + return_diag=True, + symmetrized=True, + form=form, + ) + Ls_normed, ds_normed = csgraph.laplacian( + mat, + return_diag=True, + symmetrized=True, + normed=True, + form=form, + ) + mat += mat.T + Lss, dss = csgraph.laplacian(mat, return_diag=True, form=form) + Lss_normed, dss_normed = csgraph.laplacian( + mat, + return_diag=True, + normed=True, + form=form, + ) + + assert_allclose(ds, d_in + d_out) + assert_allclose(ds, dss) + assert_allclose(ds_normed, dss_normed) + + d = {} + for L in ["L_in", "L_out", "Ls", "Ls_normed", "Lss", "Lss_normed"]: + if form == "array": + d[L] = eval(L) + else: + d[L] = eval(L)(np.eye(n, dtype=mat.dtype)) + + _assert_allclose_sparse(d["Ls"], d["L_in"] + d["L_out"].T) + _assert_allclose_sparse(d["Ls"], d["Lss"]) + _assert_allclose_sparse(d["Ls_normed"], d["Lss_normed"]) + + +@pytest.mark.parametrize( + "arr_type", [np.asarray, + sparse.csr_matrix, + sparse.coo_matrix, + sparse.csr_array, + sparse.coo_array] +) +@pytest.mark.parametrize("dtype", DTYPES) +@pytest.mark.parametrize("normed", [True, False]) +@pytest.mark.parametrize("symmetrized", [True, False]) +@pytest.mark.parametrize("use_out_degree", [True, False]) +@pytest.mark.parametrize("form", ["function", "lo"]) +def test_format(dtype, arr_type, normed, symmetrized, use_out_degree, form): + n = 3 + mat = [[0, 1, 0], [4, 2, 0], [0, 0, 0]] + mat = arr_type(np.array(mat), dtype=dtype) + Lo, do = csgraph.laplacian( + mat, + return_diag=True, + normed=normed, + symmetrized=symmetrized, + use_out_degree=use_out_degree, + dtype=dtype, + ) + La, da = csgraph.laplacian( + mat, + return_diag=True, + normed=normed, + symmetrized=symmetrized, + use_out_degree=use_out_degree, + dtype=dtype, + form="array", + ) + assert_allclose(do, da) + _assert_allclose_sparse(Lo, La) + + L, d = csgraph.laplacian( + mat, + return_diag=True, + normed=normed, + symmetrized=symmetrized, + use_out_degree=use_out_degree, + dtype=dtype, + form=form, + ) + assert_allclose(d, do) + assert d.dtype == dtype + Lm = L(np.eye(n, dtype=mat.dtype)).astype(dtype) + _assert_allclose_sparse(Lm, Lo, rtol=2e-7, atol=2e-7) + x = np.arange(6).reshape(3, 2) + if not (normed and dtype in INT_DTYPES): + assert_allclose(L(x), Lo @ x) + else: + # Normalized Lo is casted to integer, but L() is not + pass + + +def test_format_error_message(): + with pytest.raises(ValueError, match="Invalid form: 'toto'"): + _ = csgraph.laplacian(np.eye(1), form='toto') diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_matching.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_matching.py new file mode 100644 index 0000000000000000000000000000000000000000..735ad1cdf283427283d762e16c4e7b51429576c2 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_matching.py @@ -0,0 +1,306 @@ +from itertools import product + +import numpy as np +from numpy.testing import assert_array_equal, assert_equal +import pytest + +from scipy.sparse import csr_array, coo_array, diags_array +from scipy.sparse.csgraph import ( + maximum_bipartite_matching, min_weight_full_bipartite_matching +) + + +def test_maximum_bipartite_matching_raises_on_dense_input(): + with pytest.raises(TypeError): + graph = np.array([[0, 1], [0, 0]]) + maximum_bipartite_matching(graph) + + +def test_maximum_bipartite_matching_empty_graph(): + graph = csr_array((0, 0)) + x = maximum_bipartite_matching(graph, perm_type='row') + y = maximum_bipartite_matching(graph, perm_type='column') + expected_matching = np.array([]) + assert_array_equal(expected_matching, x) + assert_array_equal(expected_matching, y) + + +def test_maximum_bipartite_matching_empty_left_partition(): + graph = csr_array((2, 0)) + x = maximum_bipartite_matching(graph, perm_type='row') + y = maximum_bipartite_matching(graph, perm_type='column') + assert_array_equal(np.array([]), x) + assert_array_equal(np.array([-1, -1]), y) + + +def test_maximum_bipartite_matching_empty_right_partition(): + graph = csr_array((0, 3)) + x = maximum_bipartite_matching(graph, perm_type='row') + y = maximum_bipartite_matching(graph, perm_type='column') + assert_array_equal(np.array([-1, -1, -1]), x) + assert_array_equal(np.array([]), y) + + +def test_maximum_bipartite_matching_graph_with_no_edges(): + graph = csr_array((2, 2)) + x = maximum_bipartite_matching(graph, perm_type='row') + y = maximum_bipartite_matching(graph, perm_type='column') + assert_array_equal(np.array([-1, -1]), x) + assert_array_equal(np.array([-1, -1]), y) + + +def test_maximum_bipartite_matching_graph_that_causes_augmentation(): + # In this graph, column 1 is initially assigned to row 1, but it should be + # reassigned to make room for row 2. + graph = csr_array([[1, 1], [1, 0]]) + x = maximum_bipartite_matching(graph, perm_type='column') + y = maximum_bipartite_matching(graph, perm_type='row') + expected_matching = np.array([1, 0]) + assert_array_equal(expected_matching, x) + assert_array_equal(expected_matching, y) + + +def test_maximum_bipartite_matching_graph_with_more_rows_than_columns(): + graph = csr_array([[1, 1], [1, 0], [0, 1]]) + x = maximum_bipartite_matching(graph, perm_type='column') + y = maximum_bipartite_matching(graph, perm_type='row') + assert_array_equal(np.array([0, -1, 1]), x) + assert_array_equal(np.array([0, 2]), y) + + +def test_maximum_bipartite_matching_graph_with_more_columns_than_rows(): + graph = csr_array([[1, 1, 0], [0, 0, 1]]) + x = maximum_bipartite_matching(graph, perm_type='column') + y = maximum_bipartite_matching(graph, perm_type='row') + assert_array_equal(np.array([0, 2]), x) + assert_array_equal(np.array([0, -1, 1]), y) + + +def test_maximum_bipartite_matching_explicit_zeros_count_as_edges(): + data = [0, 0] + indices = [1, 0] + indptr = [0, 1, 2] + graph = csr_array((data, indices, indptr), shape=(2, 2)) + x = maximum_bipartite_matching(graph, perm_type='row') + y = maximum_bipartite_matching(graph, perm_type='column') + expected_matching = np.array([1, 0]) + assert_array_equal(expected_matching, x) + assert_array_equal(expected_matching, y) + + +def test_maximum_bipartite_matching_feasibility_of_result(): + # This is a regression test for GitHub issue #11458 + data = np.ones(50, dtype=int) + indices = [11, 12, 19, 22, 23, 5, 22, 3, 8, 10, 5, 6, 11, 12, 13, 5, 13, + 14, 20, 22, 3, 15, 3, 13, 14, 11, 12, 19, 22, 23, 5, 22, 3, 8, + 10, 5, 6, 11, 12, 13, 5, 13, 14, 20, 22, 3, 15, 3, 13, 14] + indptr = [0, 5, 7, 10, 10, 15, 20, 22, 22, 23, 25, 30, 32, 35, 35, 40, 45, + 47, 47, 48, 50] + graph = csr_array((data, indices, indptr), shape=(20, 25)) + x = maximum_bipartite_matching(graph, perm_type='row') + y = maximum_bipartite_matching(graph, perm_type='column') + assert (x != -1).sum() == 13 + assert (y != -1).sum() == 13 + # Ensure that each element of the matching is in fact an edge in the graph. + for u, v in zip(range(graph.shape[0]), y): + if v != -1: + assert graph[u, v] + for u, v in zip(x, range(graph.shape[1])): + if u != -1: + assert graph[u, v] + + +def test_matching_large_random_graph_with_one_edge_incident_to_each_vertex(): + np.random.seed(42) + A = diags_array(np.ones(25), offsets=0, format='csr') + rand_perm = np.random.permutation(25) + rand_perm2 = np.random.permutation(25) + + Rrow = np.arange(25) + Rcol = rand_perm + Rdata = np.ones(25, dtype=int) + Rmat = csr_array((Rdata, (Rrow, Rcol))) + + Crow = rand_perm2 + Ccol = np.arange(25) + Cdata = np.ones(25, dtype=int) + Cmat = csr_array((Cdata, (Crow, Ccol))) + # Randomly permute identity matrix + B = Rmat @ A @ Cmat + + # Row permute + perm = maximum_bipartite_matching(B, perm_type='row') + Rrow = np.arange(25) + Rcol = perm + Rdata = np.ones(25, dtype=int) + Rmat = csr_array((Rdata, (Rrow, Rcol))) + C1 = Rmat @ B + + # Column permute + perm2 = maximum_bipartite_matching(B, perm_type='column') + Crow = perm2 + Ccol = np.arange(25) + Cdata = np.ones(25, dtype=int) + Cmat = csr_array((Cdata, (Crow, Ccol))) + C2 = B @ Cmat + + # Should get identity matrix back + assert_equal(any(C1.diagonal() == 0), False) + assert_equal(any(C2.diagonal() == 0), False) + + +@pytest.mark.parametrize('num_rows,num_cols', [(0, 0), (2, 0), (0, 3)]) +def test_min_weight_full_matching_trivial_graph(num_rows, num_cols): + biadjacency = csr_array((num_cols, num_rows)) + biadjacency1 = coo_array((num_cols, num_rows)) + + row_ind, col_ind = min_weight_full_bipartite_matching(biadjacency) + assert len(row_ind) == 0 + assert len(col_ind) == 0 + + row_ind1, col_ind1 = min_weight_full_bipartite_matching(biadjacency1) + assert len(row_ind1) == 0 + assert len(col_ind1) == 0 + + +@pytest.mark.parametrize('biadjacency', + [ + [[1, 1, 1], [1, 0, 0], [1, 0, 0]], + [[1, 1, 1], [0, 0, 1], [0, 0, 1]], + [[1, 0, 0, 1], [1, 1, 0, 1], [0, 0, 0, 0]], + [[1, 0, 0], [2, 0, 0]], + [[0, 1, 0], [0, 2, 0]], + [[1, 0], [2, 0], [5, 0]] + ]) +def test_min_weight_full_matching_infeasible_problems(biadjacency): + with pytest.raises(ValueError): + min_weight_full_bipartite_matching(csr_array(biadjacency)) + with pytest.raises(ValueError): + min_weight_full_bipartite_matching(coo_array(biadjacency)) + + +def test_min_weight_full_matching_large_infeasible(): + # Regression test for GitHub issue #17269 + a = np.asarray([ + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.001, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.001, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.001, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.001, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.001, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.001, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.001, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.001, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.001], + [0.0, 0.11687445, 0.0, 0.0, 0.01319788, 0.07509257, 0.0, + 0.0, 0.0, 0.74228317, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.81087935, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.8408466, 0.0, 0.0, 0.0, 0.0, 0.01194389, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.82994211, 0.0, 0.0, 0.0, 0.11468516, 0.0, 0.0, 0.0, + 0.11173505, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0], + [0.18796507, 0.0, 0.04002318, 0.0, 0.0, 0.0, 0.0, 0.0, 0.75883335, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.71545464, 0.0, 0.0, 0.0, 0.0, 0.0, 0.02748488, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.78470564, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.14829198, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.10870609, 0.0, 0.0, 0.0, 0.8918677, 0.0, 0.0, 0.0, 0.06306644, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.63844085, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.7442354, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.09850549, 0.0, 0.0, 0.18638258, + 0.2769244, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.73182464, 0.0, 0.0, 0.46443561, + 0.38589284, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.29510278, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.09666032, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] + ]) + with pytest.raises(ValueError, match='no full matching exists'): + min_weight_full_bipartite_matching(csr_array(a)) + with pytest.raises(ValueError, match='no full matching exists'): + min_weight_full_bipartite_matching(coo_array(a)) + + +def test_explicit_zero_causes_warning(): + biadjacency = csr_array(((2, 0, 3), (0, 1, 1), (0, 2, 3))) + with pytest.warns(UserWarning): + min_weight_full_bipartite_matching(biadjacency) + with pytest.warns(UserWarning): + min_weight_full_bipartite_matching(biadjacency.tocoo()) + + +# General test for linear sum assignment solvers to make it possible to rely +# on the same tests for scipy.optimize.linear_sum_assignment. +def linear_sum_assignment_assertions( + solver, array_type, sign, test_case +): + cost_matrix, expected_cost = test_case + maximize = sign == -1 + cost_matrix = sign * array_type(cost_matrix) + expected_cost = sign * np.array(expected_cost) + + row_ind, col_ind = solver(cost_matrix, maximize=maximize) + assert_array_equal(row_ind, np.sort(row_ind)) + assert_array_equal(expected_cost, + np.array(cost_matrix[row_ind, col_ind]).flatten()) + + cost_matrix = cost_matrix.T + row_ind, col_ind = solver(cost_matrix, maximize=maximize) + assert_array_equal(row_ind, np.sort(row_ind)) + assert_array_equal(np.sort(expected_cost), + np.sort(np.array( + cost_matrix[row_ind, col_ind])).flatten()) + + +linear_sum_assignment_test_cases = product( + [-1, 1], + [ + # Square + ([[400, 150, 400], + [400, 450, 600], + [300, 225, 300]], + [150, 400, 300]), + + # Rectangular variant + ([[400, 150, 400, 1], + [400, 450, 600, 2], + [300, 225, 300, 3]], + [150, 2, 300]), + + ([[10, 10, 8], + [9, 8, 1], + [9, 7, 4]], + [10, 1, 7]), + + # Square + ([[10, 10, 8, 11], + [9, 8, 1, 1], + [9, 7, 4, 10]], + [10, 1, 4]), + + # Rectangular variant + ([[10, float("inf"), float("inf")], + [float("inf"), float("inf"), 1], + [float("inf"), 7, float("inf")]], + [10, 1, 7]) + ]) + + +@pytest.mark.parametrize('sign,test_case', linear_sum_assignment_test_cases) +def test_min_weight_full_matching_small_inputs(sign, test_case): + linear_sum_assignment_assertions( + min_weight_full_bipartite_matching, csr_array, sign, test_case) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_pydata_sparse.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_pydata_sparse.py new file mode 100644 index 0000000000000000000000000000000000000000..3a4c7e0de24ca61a000e7be7ed810d88655bfee7 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_pydata_sparse.py @@ -0,0 +1,197 @@ +import pytest + +import numpy as np +import scipy.sparse as sp +import scipy.sparse.csgraph as spgraph +from scipy._lib import _pep440 + +from numpy.testing import assert_equal + +try: + import sparse +except Exception: + sparse = None + +pytestmark = pytest.mark.skipif(sparse is None, + reason="pydata/sparse not installed") + + +msg = "pydata/sparse (0.15.1) does not implement necessary operations" + + +sparse_params = (pytest.param("COO"), + pytest.param("DOK", marks=[pytest.mark.xfail(reason=msg)])) + + +def check_sparse_version(min_ver): + if sparse is None: + return pytest.mark.skip(reason="sparse is not installed") + return pytest.mark.skipif( + _pep440.parse(sparse.__version__) < _pep440.Version(min_ver), + reason=f"sparse version >= {min_ver} required" + ) + + +@pytest.fixture(params=sparse_params) +def sparse_cls(request): + return getattr(sparse, request.param) + + +@pytest.fixture +def graphs(sparse_cls): + graph = [ + [0, 1, 1, 0, 0], + [0, 0, 1, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 1], + [0, 0, 0, 0, 0], + ] + A_dense = np.array(graph) + A_sparse = sparse_cls(A_dense) + return A_dense, A_sparse + + +@pytest.mark.parametrize( + "func", + [ + spgraph.shortest_path, + spgraph.dijkstra, + spgraph.floyd_warshall, + spgraph.bellman_ford, + spgraph.johnson, + spgraph.reverse_cuthill_mckee, + spgraph.maximum_bipartite_matching, + spgraph.structural_rank, + ] +) +def test_csgraph_equiv(func, graphs): + A_dense, A_sparse = graphs + actual = func(A_sparse) + desired = func(sp.csc_array(A_dense)) + assert_equal(actual, desired) + + +def test_connected_components(graphs): + A_dense, A_sparse = graphs + func = spgraph.connected_components + + actual_comp, actual_labels = func(A_sparse) + desired_comp, desired_labels, = func(sp.csc_array(A_dense)) + + assert actual_comp == desired_comp + assert_equal(actual_labels, desired_labels) + + +def test_laplacian(graphs): + A_dense, A_sparse = graphs + sparse_cls = type(A_sparse) + func = spgraph.laplacian + + actual = func(A_sparse) + desired = func(sp.csc_array(A_dense)) + + assert isinstance(actual, sparse_cls) + + assert_equal(actual.todense(), desired.todense()) + + +@pytest.mark.parametrize( + "func", [spgraph.breadth_first_order, spgraph.depth_first_order] +) +def test_order_search(graphs, func): + A_dense, A_sparse = graphs + + actual = func(A_sparse, 0) + desired = func(sp.csc_array(A_dense), 0) + + assert_equal(actual, desired) + + +@pytest.mark.parametrize( + "func", [spgraph.breadth_first_tree, spgraph.depth_first_tree] +) +def test_tree_search(graphs, func): + A_dense, A_sparse = graphs + sparse_cls = type(A_sparse) + + actual = func(A_sparse, 0) + desired = func(sp.csc_array(A_dense), 0) + + assert isinstance(actual, sparse_cls) + + assert_equal(actual.todense(), desired.todense()) + + +def test_minimum_spanning_tree(graphs): + A_dense, A_sparse = graphs + sparse_cls = type(A_sparse) + func = spgraph.minimum_spanning_tree + + actual = func(A_sparse) + desired = func(sp.csc_array(A_dense)) + + assert isinstance(actual, sparse_cls) + + assert_equal(actual.todense(), desired.todense()) + + +def test_maximum_flow(graphs): + A_dense, A_sparse = graphs + sparse_cls = type(A_sparse) + func = spgraph.maximum_flow + + actual = func(A_sparse, 0, 2) + desired = func(sp.csr_array(A_dense), 0, 2) + + assert actual.flow_value == desired.flow_value + assert isinstance(actual.flow, sparse_cls) + + assert_equal(actual.flow.todense(), desired.flow.todense()) + + +def test_min_weight_full_bipartite_matching(graphs): + A_dense, A_sparse = graphs + func = spgraph.min_weight_full_bipartite_matching + + actual = func(A_sparse[0:2, 1:3]) + A_csc = sp.csc_array(A_dense) + desired = func(A_csc[0:2, 1:3]) + desired1 = func(A_csc[0:2, 1:3].tocoo()) + + assert_equal(actual, desired) + assert_equal(actual, desired1) + + +@check_sparse_version("0.15.4") +@pytest.mark.parametrize( + "func", + [ + spgraph.shortest_path, + spgraph.dijkstra, + spgraph.floyd_warshall, + spgraph.bellman_ford, + spgraph.johnson, + spgraph.minimum_spanning_tree, + ] +) +@pytest.mark.parametrize( + "fill_value, comp_func", + [(np.inf, np.isposinf), (np.nan, np.isnan)], +) +def test_nonzero_fill_value(graphs, func, fill_value, comp_func): + A_dense, A_sparse = graphs + A_sparse = A_sparse.astype(float) + A_sparse.fill_value = fill_value + sparse_cls = type(A_sparse) + + actual = func(A_sparse) + desired = func(sp.csc_array(A_dense)) + + if func == spgraph.minimum_spanning_tree: + assert isinstance(actual, sparse_cls) + assert comp_func(actual.fill_value) + actual = actual.todense() + actual[comp_func(actual)] = 0.0 + assert_equal(actual, desired.todense()) + else: + assert_equal(actual, desired) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_reordering.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_reordering.py new file mode 100644 index 0000000000000000000000000000000000000000..add76cdc29c39c079f386a6ca73075bb90b0a6e8 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_reordering.py @@ -0,0 +1,70 @@ +import numpy as np +from numpy.testing import assert_equal +from scipy.sparse.csgraph import reverse_cuthill_mckee, structural_rank +from scipy.sparse import csc_array, csr_array, coo_array + + +def test_graph_reverse_cuthill_mckee(): + A = np.array([[1, 0, 0, 0, 1, 0, 0, 0], + [0, 1, 1, 0, 0, 1, 0, 1], + [0, 1, 1, 0, 1, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 1, 0], + [1, 0, 1, 0, 1, 0, 0, 0], + [0, 1, 0, 0, 0, 1, 0, 1], + [0, 0, 0, 1, 0, 0, 1, 0], + [0, 1, 0, 0, 0, 1, 0, 1]], dtype=int) + + graph = csr_array(A) + perm = reverse_cuthill_mckee(graph) + correct_perm = np.array([6, 3, 7, 5, 1, 2, 4, 0]) + assert_equal(perm, correct_perm) + + # Test int64 indices input + graph.indices = graph.indices.astype('int64') + graph.indptr = graph.indptr.astype('int64') + perm = reverse_cuthill_mckee(graph, True) + assert_equal(perm, correct_perm) + + +def test_graph_reverse_cuthill_mckee_ordering(): + data = np.ones(63,dtype=int) + rows = np.array([0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, + 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, + 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, + 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, + 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, + 14, 15, 15, 15, 15, 15]) + cols = np.array([0, 2, 5, 8, 10, 1, 3, 9, 11, 0, 2, + 7, 10, 1, 3, 11, 4, 6, 12, 14, 0, 7, 13, + 15, 4, 6, 14, 2, 5, 7, 15, 0, 8, 10, 13, + 1, 9, 11, 0, 2, 8, 10, 15, 1, 3, 9, 11, + 4, 12, 14, 5, 8, 13, 15, 4, 6, 12, 14, + 5, 7, 10, 13, 15]) + graph = csr_array((data, (rows,cols))) + perm = reverse_cuthill_mckee(graph) + correct_perm = np.array([12, 14, 4, 6, 10, 8, 2, 15, + 0, 13, 7, 5, 9, 11, 1, 3]) + assert_equal(perm, correct_perm) + + +def test_graph_structural_rank(): + # Test square matrix #1 + A = csc_array([[1, 1, 0], + [1, 0, 1], + [0, 1, 0]]) + assert_equal(structural_rank(A), 3) + + # Test square matrix #2 + rows = np.array([0,0,0,0,0,1,1,2,2,3,3,3,3,3,3,4,4,5,5,6,6,7,7]) + cols = np.array([0,1,2,3,4,2,5,2,6,0,1,3,5,6,7,4,5,5,6,2,6,2,4]) + data = np.ones_like(rows) + B = coo_array((data,(rows,cols)), shape=(8,8)) + assert_equal(structural_rank(B), 6) + + #Test non-square matrix + C = csc_array([[1, 0, 2, 0], + [2, 0, 4, 0]]) + assert_equal(structural_rank(C), 2) + + #Test tall matrix + assert_equal(structural_rank(C.T), 2) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_shortest_path.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_shortest_path.py new file mode 100644 index 0000000000000000000000000000000000000000..dd322591caca8b3df6b169f44d6763c7352e668d --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_shortest_path.py @@ -0,0 +1,547 @@ +from io import StringIO +import warnings +import numpy as np +from numpy.testing import assert_array_almost_equal, assert_array_equal, assert_allclose +from pytest import raises as assert_raises +from scipy.sparse.csgraph import (shortest_path, dijkstra, johnson, + bellman_ford, construct_dist_matrix, yen, + NegativeCycleError) +import scipy.sparse +from scipy.io import mmread +import pytest + +directed_G = np.array([[0, 3, 3, 0, 0], + [0, 0, 0, 2, 4], + [0, 0, 0, 0, 0], + [1, 0, 0, 0, 0], + [2, 0, 0, 2, 0]], dtype=float) + +# Undirected version of directed_G +undirected_G = np.array([[0, 3, 3, 1, 2], + [3, 0, 0, 2, 4], + [3, 0, 0, 0, 0], + [1, 2, 0, 0, 2], + [2, 4, 0, 2, 0]], dtype=float) + +unweighted_G = (directed_G > 0).astype(float) + +# Correct shortest path lengths for directed_G and undirected_G +directed_SP = [[0, 3, 3, 5, 7], + [3, 0, 6, 2, 4], + [np.inf, np.inf, 0, np.inf, np.inf], + [1, 4, 4, 0, 8], + [2, 5, 5, 2, 0]] + +directed_2SP_0_to_3 = [[-9999, 0, -9999, 1, -9999], + [-9999, 0, -9999, 4, 1]] + +undirected_SP = np.array([[0, 3, 3, 1, 2], + [3, 0, 6, 2, 4], + [3, 6, 0, 4, 5], + [1, 2, 4, 0, 2], + [2, 4, 5, 2, 0]], dtype=float) + +undirected_SP_limit_2 = np.array([[0, np.inf, np.inf, 1, 2], + [np.inf, 0, np.inf, 2, np.inf], + [np.inf, np.inf, 0, np.inf, np.inf], + [1, 2, np.inf, 0, 2], + [2, np.inf, np.inf, 2, 0]], dtype=float) + +undirected_SP_limit_0 = np.ones((5, 5), dtype=float) - np.eye(5) +undirected_SP_limit_0[undirected_SP_limit_0 > 0] = np.inf + +# Correct predecessors for directed_G and undirected_G +directed_pred = np.array([[-9999, 0, 0, 1, 1], + [3, -9999, 0, 1, 1], + [-9999, -9999, -9999, -9999, -9999], + [3, 0, 0, -9999, 1], + [4, 0, 0, 4, -9999]], dtype=float) + +undirected_pred = np.array([[-9999, 0, 0, 0, 0], + [1, -9999, 0, 1, 1], + [2, 0, -9999, 0, 0], + [3, 3, 0, -9999, 3], + [4, 4, 0, 4, -9999]], dtype=float) + +# Other graphs +directed_sparse_zero_G = scipy.sparse.csr_array( + ( + [0, 1, 2, 3, 1], + ([0, 1, 2, 3, 4], [1, 2, 0, 4, 3]), + ), + shape=(5, 5), +) + +directed_sparse_zero_SP = [[0, 0, 1, np.inf, np.inf], + [3, 0, 1, np.inf, np.inf], + [2, 2, 0, np.inf, np.inf], + [np.inf, np.inf, np.inf, 0, 3], + [np.inf, np.inf, np.inf, 1, 0]] + +undirected_sparse_zero_G = scipy.sparse.csr_array( + ( + [0, 0, 1, 1, 2, 2, 1, 1], + ([0, 1, 1, 2, 2, 0, 3, 4], [1, 0, 2, 1, 0, 2, 4, 3]) + ), + shape=(5, 5), +) + +undirected_sparse_zero_SP = [[0, 0, 1, np.inf, np.inf], + [0, 0, 1, np.inf, np.inf], + [1, 1, 0, np.inf, np.inf], + [np.inf, np.inf, np.inf, 0, 1], + [np.inf, np.inf, np.inf, 1, 0]] + +directed_negative_weighted_G = np.array([[0, 0, 0], + [-1, 0, 0], + [0, -1, 0]], dtype=float) + +directed_negative_weighted_SP = np.array([[0, np.inf, np.inf], + [-1, 0, np.inf], + [-2, -1, 0]], dtype=float) + +methods = ['auto', 'FW', 'D', 'BF', 'J'] + + +def test_dijkstra_limit(): + limits = [0, 2, np.inf] + results = [undirected_SP_limit_0, + undirected_SP_limit_2, + undirected_SP] + + def check(limit, result): + SP = dijkstra(undirected_G, directed=False, limit=limit) + assert_array_almost_equal(SP, result) + + for limit, result in zip(limits, results): + check(limit, result) + + +def test_directed(): + def check(method): + SP = shortest_path(directed_G, method=method, directed=True, + overwrite=False) + assert_array_almost_equal(SP, directed_SP) + + for method in methods: + check(method) + + +def test_undirected(): + def check(method, directed_in): + if directed_in: + SP1 = shortest_path(directed_G, method=method, directed=False, + overwrite=False) + assert_array_almost_equal(SP1, undirected_SP) + else: + SP2 = shortest_path(undirected_G, method=method, directed=True, + overwrite=False) + assert_array_almost_equal(SP2, undirected_SP) + + for method in methods: + for directed_in in (True, False): + check(method, directed_in) + + +def test_directed_sparse_zero(): + # test directed sparse graph with zero-weight edge and two connected components + def check(method): + SP = shortest_path(directed_sparse_zero_G, method=method, directed=True, + overwrite=False) + assert_array_almost_equal(SP, directed_sparse_zero_SP) + + for method in methods: + check(method) + + +def test_undirected_sparse_zero(): + def check(method, directed_in): + if directed_in: + SP1 = shortest_path(directed_sparse_zero_G, method=method, directed=False, + overwrite=False) + assert_array_almost_equal(SP1, undirected_sparse_zero_SP) + else: + SP2 = shortest_path(undirected_sparse_zero_G, method=method, directed=True, + overwrite=False) + assert_array_almost_equal(SP2, undirected_sparse_zero_SP) + + for method in methods: + for directed_in in (True, False): + check(method, directed_in) + + +@pytest.mark.parametrize('directed, SP_ans', + ((True, directed_SP), + (False, undirected_SP))) +@pytest.mark.parametrize('indices', ([0, 2, 4], [0, 4], [3, 4], [0, 0])) +def test_dijkstra_indices_min_only(directed, SP_ans, indices): + SP_ans = np.array(SP_ans) + indices = np.array(indices, dtype=np.int64) + min_ind_ans = indices[np.argmin(SP_ans[indices, :], axis=0)] + min_d_ans = np.zeros(SP_ans.shape[0], SP_ans.dtype) + for k in range(SP_ans.shape[0]): + min_d_ans[k] = SP_ans[min_ind_ans[k], k] + min_ind_ans[np.isinf(min_d_ans)] = -9999 + + SP, pred, sources = dijkstra(directed_G, + directed=directed, + indices=indices, + min_only=True, + return_predecessors=True) + assert_array_almost_equal(SP, min_d_ans) + assert_array_equal(min_ind_ans, sources) + SP = dijkstra(directed_G, + directed=directed, + indices=indices, + min_only=True, + return_predecessors=False) + assert_array_almost_equal(SP, min_d_ans) + + +@pytest.mark.parametrize('n', (10, 100, 1000)) +def test_dijkstra_min_only_random(n): + rng = np.random.default_rng(7345782358920239234) + data = scipy.sparse.random_array((n, n), density=0.5, format='lil', + rng=rng, dtype=np.float64) + data.setdiag(np.zeros(n, dtype=np.bool_)) + # choose some random vertices + v = np.arange(n) + rng.shuffle(v) + indices = v[:int(n*.1)] + ds, pred, sources = dijkstra(data, + directed=True, + indices=indices, + min_only=True, + return_predecessors=True) + for k in range(n): + p = pred[k] + s = sources[k] + while p != -9999: + assert sources[p] == s + p = pred[p] + + +@pytest.mark.parametrize('n', (10, 100)) +@pytest.mark.parametrize("method", ['FW', 'J', 'BF']) +@pytest.mark.parametrize('directed', (True, False)) +def test_star_graph(n, method, directed): + # Build the star graph + star_arr = np.zeros((n, n), dtype=float) + star_center_idx = 0 + star_arr[star_center_idx, :] = star_arr[:, star_center_idx] = range(n) + G = scipy.sparse.csr_matrix(star_arr, shape=(n, n)) + # Build the distances matrix + SP_solution = np.zeros((n, n), dtype=float) + SP_solution[:] = star_arr[star_center_idx] + for idx in range(1, n): + SP_solution[idx] += star_arr[idx, star_center_idx] + np.fill_diagonal(SP_solution, 0) + + SP = shortest_path(G, method=method, directed=directed) + assert_allclose( + SP_solution, SP + ) + + +def test_dijkstra_random(): + # reproduces the hang observed in gh-17782 + n = 10 + indices = [0, 4, 4, 5, 7, 9, 0, 6, 2, 3, 7, 9, 1, 2, 9, 2, 5, 6] + indptr = [0, 0, 2, 5, 6, 7, 8, 12, 15, 18, 18] + data = [0.33629, 0.40458, 0.47493, 0.42757, 0.11497, 0.91653, 0.69084, + 0.64979, 0.62555, 0.743, 0.01724, 0.99945, 0.31095, 0.15557, + 0.02439, 0.65814, 0.23478, 0.24072] + graph = scipy.sparse.csr_array((data, indices, indptr), shape=(n, n)) + dijkstra(graph, directed=True, return_predecessors=True) + + +def test_gh_17782_segfault(): + text = """%%MatrixMarket matrix coordinate real general + 84 84 22 + 2 1 4.699999809265137e+00 + 6 14 1.199999973177910e-01 + 9 6 1.199999973177910e-01 + 10 16 2.012000083923340e+01 + 11 10 1.422000026702881e+01 + 12 1 9.645999908447266e+01 + 13 18 2.012000083923340e+01 + 14 13 4.679999828338623e+00 + 15 11 1.199999973177910e-01 + 16 12 1.199999973177910e-01 + 18 15 1.199999973177910e-01 + 32 2 2.299999952316284e+00 + 33 20 6.000000000000000e+00 + 33 32 5.000000000000000e+00 + 36 9 3.720000028610229e+00 + 36 37 3.720000028610229e+00 + 36 38 3.720000028610229e+00 + 37 44 8.159999847412109e+00 + 38 32 7.903999328613281e+01 + 43 20 2.400000000000000e+01 + 43 33 4.000000000000000e+00 + 44 43 6.028000259399414e+01 + """ + data = mmread(StringIO(text), spmatrix=False) + dijkstra(data, directed=True, return_predecessors=True) + + +def test_shortest_path_indices(): + indices = np.arange(4) + + def check(func, indshape): + outshape = indshape + (5,) + SP = func(directed_G, directed=False, + indices=indices.reshape(indshape)) + assert_array_almost_equal(SP, undirected_SP[indices].reshape(outshape)) + + for indshape in [(4,), (4, 1), (2, 2)]: + for func in (dijkstra, bellman_ford, johnson, shortest_path): + check(func, indshape) + + assert_raises(ValueError, shortest_path, directed_G, method='FW', + indices=indices) + + +def test_predecessors(): + SP_res = {True: directed_SP, + False: undirected_SP} + pred_res = {True: directed_pred, + False: undirected_pred} + + def check(method, directed): + SP, pred = shortest_path(directed_G, method, directed=directed, + overwrite=False, + return_predecessors=True) + assert_array_almost_equal(SP, SP_res[directed]) + assert_array_almost_equal(pred, pred_res[directed]) + + for method in methods: + for directed in (True, False): + check(method, directed) + + +def test_construct_shortest_path(): + def check(method, directed): + SP1, pred = shortest_path(directed_G, + directed=directed, + overwrite=False, + return_predecessors=True) + SP2 = construct_dist_matrix(directed_G, pred, directed=directed) + assert_array_almost_equal(SP1, SP2) + + for method in methods: + for directed in (True, False): + check(method, directed) + +@pytest.mark.parametrize("directed", [True, False]) +def test_construct_dist_matrix_predecessors_error(directed): + SP1, pred = shortest_path(directed_G, + directed=directed, + overwrite=False, + return_predecessors=True) + assert_raises(TypeError, construct_dist_matrix, + directed_G, pred.astype(np.int64), directed) + + +def test_unweighted_path(): + def check(method, directed): + SP1 = shortest_path(directed_G, + directed=directed, + overwrite=False, + unweighted=True) + SP2 = shortest_path(unweighted_G, + directed=directed, + overwrite=False, + unweighted=False) + assert_array_almost_equal(SP1, SP2) + + for method in methods: + for directed in (True, False): + check(method, directed) + + +def test_negative_cycles(): + # create a small graph with a negative cycle + graph = np.ones([5, 5]) + graph.flat[::6] = 0 + graph[1, 2] = -2 + + def check(method, directed): + assert_raises(NegativeCycleError, shortest_path, graph, method, + directed) + + for directed in (True, False): + for method in ['FW', 'J', 'BF']: + check(method, directed) + + assert_raises(NegativeCycleError, yen, graph, 0, 1, 1, + directed=directed) + + +@pytest.mark.parametrize("method", ['FW', 'J', 'BF']) +def test_negative_weights(method): + SP = shortest_path(directed_negative_weighted_G, method, directed=True) + assert_allclose(SP, directed_negative_weighted_SP, atol=1e-10) + + +def test_masked_input(): + np.ma.masked_equal(directed_G, 0) + + def check(method): + SP = shortest_path(directed_G, method=method, directed=True, + overwrite=False) + assert_array_almost_equal(SP, directed_SP) + + for method in methods: + check(method) + + +def test_overwrite(): + G = np.array([[0, 3, 3, 1, 2], + [3, 0, 0, 2, 4], + [3, 0, 0, 0, 0], + [1, 2, 0, 0, 2], + [2, 4, 0, 2, 0]], dtype=float) + foo = G.copy() + shortest_path(foo, overwrite=False) + assert_array_equal(foo, G) + + +@pytest.mark.parametrize('method', methods) +def test_buffer(method): + # Smoke test that sparse matrices with read-only buffers (e.g., those from + # joblib workers) do not cause:: + # + # ValueError: buffer source array is read-only + # + G = scipy.sparse.csr_array([[1.]]) + G.data.flags['WRITEABLE'] = False + shortest_path(G, method=method) + + +def test_NaN_warnings(): + with warnings.catch_warnings(record=True) as record: + shortest_path(np.array([[0, 1], [np.nan, 0]])) + for r in record: + assert r.category is not RuntimeWarning + + +def test_sparse_matrices(): + # Test that using lil,csr and csc sparse matrix do not cause error + G_dense = np.array([[0, 3, 0, 0, 0], + [0, 0, -1, 0, 0], + [0, 0, 0, 2, 0], + [0, 0, 0, 0, 4], + [0, 0, 0, 0, 0]], dtype=float) + SP = shortest_path(G_dense) + G_csr = scipy.sparse.csr_array(G_dense) + G_csc = scipy.sparse.csc_array(G_dense) + G_lil = scipy.sparse.lil_array(G_dense) + assert_array_almost_equal(SP, shortest_path(G_csr)) + assert_array_almost_equal(SP, shortest_path(G_csc)) + assert_array_almost_equal(SP, shortest_path(G_lil)) + + +def test_yen_directed(): + distances, predecessors = yen( + directed_G, + source=0, + sink=3, + K=2, + return_predecessors=True + ) + assert_allclose(distances, [5., 9.]) + assert_allclose(predecessors, directed_2SP_0_to_3) + + +def test_yen_dense(): + dense_undirected_G = np.array([ + [0, 3, 3, 1, 2], + [3, 0, 7, 6, 5], + [3, 7, 0, 4, 0], + [1, 6, 4, 0, 2], + [2, 5, 0, 2, 0]], dtype=float) + distances = yen( + dense_undirected_G, + source=0, + sink=4, + K=5, + directed=False, + ) + assert_allclose(distances, [2., 3., 8., 9., 11.]) + + +def test_yen_undirected(): + distances = yen( + undirected_G, + source=0, + sink=3, + K=4, + directed=False, + ) + assert_allclose(distances, [1., 4., 5., 8.]) + + +def test_yen_unweighted(): + # Ask for more paths than there are, verify only the available paths are returned + distances, predecessors = yen( + directed_G, + source=0, + sink=3, + K=4, + unweighted=True, + return_predecessors=True, + ) + assert_allclose(distances, [2., 3.]) + assert_allclose(predecessors, directed_2SP_0_to_3) + + +def test_yen_no_paths(): + distances = yen( + directed_G, + source=2, + sink=3, + K=1, + ) + assert distances.size == 0 + + +def test_yen_negative_weights(): + distances = yen( + directed_negative_weighted_G, + source=2, + sink=0, + K=1, + ) + assert_allclose(distances, [-2.]) + + +@pytest.mark.parametrize('source, sink', [(0, -1), (10000, 1), (2, 6)]) +def test_yen_source_sink_validation(source, sink): + # directed_G has shape (6, 6) + with pytest.raises(ValueError, match="must have 0 <="): + yen(directed_G, source, sink, 2) + + +@pytest.mark.parametrize("min_only", (True, False)) +@pytest.mark.parametrize("directed", (True, False)) +@pytest.mark.parametrize("return_predecessors", (True, False)) +@pytest.mark.parametrize("index_dtype", (np.int32, np.int64)) +@pytest.mark.parametrize("indices", (None, [1])) +def test_20904(min_only, directed, return_predecessors, index_dtype, indices): + """Test two failures from gh-20904: int32 and indices-as-None.""" + adj_mat = scipy.sparse.eye_array(4, format="csr") + adj_mat = scipy.sparse.csr_array( + ( + adj_mat.data, + adj_mat.indices.astype(index_dtype), + adj_mat.indptr.astype(index_dtype), + ), + ) + dijkstra( + adj_mat, + directed, + indices=indices, + min_only=min_only, + return_predecessors=return_predecessors, + ) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_spanning_tree.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_spanning_tree.py new file mode 100644 index 0000000000000000000000000000000000000000..3237a14584d42022184a54f174b809a2b06d16ed --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_spanning_tree.py @@ -0,0 +1,66 @@ +"""Test the minimum spanning tree function""" +import numpy as np +from numpy.testing import assert_ +import numpy.testing as npt +from scipy.sparse import csr_array +from scipy.sparse.csgraph import minimum_spanning_tree + + +def test_minimum_spanning_tree(): + + # Create a graph with two connected components. + graph = [[0,1,0,0,0], + [1,0,0,0,0], + [0,0,0,8,5], + [0,0,8,0,1], + [0,0,5,1,0]] + graph = np.asarray(graph) + + # Create the expected spanning tree. + expected = [[0,1,0,0,0], + [0,0,0,0,0], + [0,0,0,0,5], + [0,0,0,0,1], + [0,0,0,0,0]] + expected = np.asarray(expected) + + # Ensure minimum spanning tree code gives this expected output. + csgraph = csr_array(graph) + mintree = minimum_spanning_tree(csgraph) + mintree_array = mintree.toarray() + npt.assert_array_equal(mintree_array, expected, + 'Incorrect spanning tree found.') + + # Ensure that the original graph was not modified. + npt.assert_array_equal(csgraph.toarray(), graph, + 'Original graph was modified.') + + # Now let the algorithm modify the csgraph in place. + mintree = minimum_spanning_tree(csgraph, overwrite=True) + npt.assert_array_equal(mintree.toarray(), expected, + 'Graph was not properly modified to contain MST.') + + np.random.seed(1234) + for N in (5, 10, 15, 20): + + # Create a random graph. + graph = 3 + np.random.random((N, N)) + csgraph = csr_array(graph) + + # The spanning tree has at most N - 1 edges. + mintree = minimum_spanning_tree(csgraph) + assert_(mintree.nnz < N) + + # Set the sub diagonal to 1 to create a known spanning tree. + idx = np.arange(N-1) + graph[idx,idx+1] = 1 + csgraph = csr_array(graph) + mintree = minimum_spanning_tree(csgraph) + + # We expect to see this pattern in the spanning tree and otherwise + # have this zero. + expected = np.zeros((N, N)) + expected[idx, idx+1] = 1 + + npt.assert_array_equal(mintree.toarray(), expected, + 'Incorrect spanning tree found.') diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_traversal.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_traversal.py new file mode 100644 index 0000000000000000000000000000000000000000..1716cf044d5fa27b833225c9a8675f02944f132e --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/csgraph/tests/test_traversal.py @@ -0,0 +1,150 @@ +import warnings +import numpy as np +import pytest +from numpy.testing import assert_array_almost_equal +from scipy.sparse import csr_array, csr_matrix, coo_array, coo_matrix +from scipy.sparse.csgraph import (breadth_first_tree, depth_first_tree, + csgraph_to_dense, csgraph_from_dense, csgraph_masked_from_dense) + + +def test_graph_breadth_first(): + csgraph = np.array([[0, 1, 2, 0, 0], + [1, 0, 0, 0, 3], + [2, 0, 0, 7, 0], + [0, 0, 7, 0, 1], + [0, 3, 0, 1, 0]]) + csgraph = csgraph_from_dense(csgraph, null_value=0) + + bfirst = np.array([[0, 1, 2, 0, 0], + [0, 0, 0, 0, 3], + [0, 0, 0, 7, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0]]) + + for directed in [True, False]: + bfirst_test = breadth_first_tree(csgraph, 0, directed) + assert_array_almost_equal(csgraph_to_dense(bfirst_test), + bfirst) + + +def test_graph_depth_first(): + csgraph = np.array([[0, 1, 2, 0, 0], + [1, 0, 0, 0, 3], + [2, 0, 0, 7, 0], + [0, 0, 7, 0, 1], + [0, 3, 0, 1, 0]]) + csgraph = csgraph_from_dense(csgraph, null_value=0) + + dfirst = np.array([[0, 1, 0, 0, 0], + [0, 0, 0, 0, 3], + [0, 0, 0, 0, 0], + [0, 0, 7, 0, 0], + [0, 0, 0, 1, 0]]) + + for directed in [True, False]: + dfirst_test = depth_first_tree(csgraph, 0, directed) + assert_array_almost_equal(csgraph_to_dense(dfirst_test), dfirst) + + +def test_return_type(): + from .._laplacian import laplacian + from .._min_spanning_tree import minimum_spanning_tree + + np_csgraph = np.array([[0, 1, 2, 0, 0], + [1, 0, 0, 0, 3], + [2, 0, 0, 7, 0], + [0, 0, 7, 0, 1], + [0, 3, 0, 1, 0]]) + csgraph = csr_array(np_csgraph) + assert isinstance(laplacian(csgraph), coo_array) + assert isinstance(minimum_spanning_tree(csgraph), csr_array) + for directed in [True, False]: + assert isinstance(depth_first_tree(csgraph, 0, directed), csr_array) + assert isinstance(breadth_first_tree(csgraph, 0, directed), csr_array) + + csgraph = csgraph_from_dense(np_csgraph, null_value=0) + assert isinstance(csgraph, csr_array) + assert isinstance(laplacian(csgraph), coo_array) + assert isinstance(minimum_spanning_tree(csgraph), csr_array) + for directed in [True, False]: + assert isinstance(depth_first_tree(csgraph, 0, directed), csr_array) + assert isinstance(breadth_first_tree(csgraph, 0, directed), csr_array) + + csgraph = csgraph_masked_from_dense(np_csgraph, null_value=0) + assert isinstance(csgraph, np.ma.MaskedArray) + assert csgraph._baseclass is np.ndarray + # laplacian doesnt work with masked arrays so not here + assert isinstance(minimum_spanning_tree(csgraph), csr_array) + for directed in [True, False]: + assert isinstance(depth_first_tree(csgraph, 0, directed), csr_array) + assert isinstance(breadth_first_tree(csgraph, 0, directed), csr_array) + + # start of testing with matrix/spmatrix types + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", "the matrix subclass.*", DeprecationWarning) + warnings.filterwarnings( + "ignore", "the matrix subclass.*", PendingDeprecationWarning) + + nm_csgraph = np.matrix([[0, 1, 2, 0, 0], + [1, 0, 0, 0, 3], + [2, 0, 0, 7, 0], + [0, 0, 7, 0, 1], + [0, 3, 0, 1, 0]]) + + csgraph = csr_matrix(nm_csgraph) + assert isinstance(laplacian(csgraph), coo_matrix) + assert isinstance(minimum_spanning_tree(csgraph), csr_matrix) + for directed in [True, False]: + assert isinstance(depth_first_tree(csgraph, 0, directed), csr_matrix) + assert isinstance(breadth_first_tree(csgraph, 0, directed), csr_matrix) + + csgraph = csgraph_from_dense(nm_csgraph, null_value=0) + assert isinstance(csgraph, csr_matrix) + assert isinstance(laplacian(csgraph), coo_matrix) + assert isinstance(minimum_spanning_tree(csgraph), csr_matrix) + for directed in [True, False]: + assert isinstance(depth_first_tree(csgraph, 0, directed), csr_matrix) + assert isinstance(breadth_first_tree(csgraph, 0, directed), csr_matrix) + + mm_csgraph = csgraph_masked_from_dense(nm_csgraph, null_value=0) + assert isinstance(mm_csgraph, np.ma.MaskedArray) + # laplacian doesnt work with masked arrays so not here + assert isinstance(minimum_spanning_tree(csgraph), csr_matrix) + for directed in [True, False]: + assert isinstance(depth_first_tree(csgraph, 0, directed), csr_matrix) + assert isinstance(breadth_first_tree(csgraph, 0, directed), csr_matrix) + # end of testing with matrix/spmatrix types + + +def test_graph_breadth_first_trivial_graph(): + csgraph = np.array([[0]]) + csgraph = csgraph_from_dense(csgraph, null_value=0) + + bfirst = np.array([[0]]) + + for directed in [True, False]: + bfirst_test = breadth_first_tree(csgraph, 0, directed) + assert_array_almost_equal(csgraph_to_dense(bfirst_test), bfirst) + + +def test_graph_depth_first_trivial_graph(): + csgraph = np.array([[0]]) + csgraph = csgraph_from_dense(csgraph, null_value=0) + + bfirst = np.array([[0]]) + + for directed in [True, False]: + bfirst_test = depth_first_tree(csgraph, 0, directed) + assert_array_almost_equal(csgraph_to_dense(bfirst_test), + bfirst) + + +@pytest.mark.parametrize('directed', [True, False]) +@pytest.mark.parametrize('tree_func', [breadth_first_tree, depth_first_tree]) +def test_int64_indices(tree_func, directed): + # See https://github.com/scipy/scipy/issues/18716 + g = csr_array(([1], np.array([[0], [1]], dtype=np.int64)), shape=(2, 2)) + assert g.indices.dtype == np.int64 + tree = tree_func(g, 0, directed=directed) + assert_array_almost_equal(csgraph_to_dense(tree), [[0, 1], [0, 0]]) + diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e32dd362f8d45f747642719cb60eab8def9af43b --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__init__.py @@ -0,0 +1,150 @@ +""" +Sparse linear algebra (:mod:`scipy.sparse.linalg`) +================================================== + +.. currentmodule:: scipy.sparse.linalg + +Abstract linear operators +------------------------- + +.. autosummary:: + :toctree: generated/ + + LinearOperator -- abstract representation of a linear operator + aslinearoperator -- convert an object to an abstract linear operator + +Matrix Operations +----------------- + +.. autosummary:: + :toctree: generated/ + + inv -- compute the sparse matrix inverse + expm -- compute the sparse matrix exponential + expm_multiply -- compute the product of a matrix exponential and a matrix + funm_multiply_krylov -- use a Krylov method to compute f(A)b for a general f + matrix_power -- compute the matrix power by raising a matrix to an exponent + +Matrix norms +------------ + +.. autosummary:: + :toctree: generated/ + + norm -- Norm of a sparse matrix + onenormest -- Estimate the 1-norm of a sparse matrix + +Solving linear problems +----------------------- + +Direct methods for linear equation systems: + +.. autosummary:: + :toctree: generated/ + + spsolve -- Solve the sparse linear system Ax=b + spsolve_triangular -- Solve sparse linear system Ax=b for a triangular A. + is_sptriangular -- Check if sparse A is triangular. + spbandwidth -- Find the bandwidth of a sparse matrix. + factorized -- Pre-factorize matrix to a function solving a linear system + MatrixRankWarning -- Warning on exactly singular matrices + use_solver -- Select direct solver to use + +Iterative methods for linear equation systems: + +.. autosummary:: + :toctree: generated/ + + bicg -- Use BIConjugate Gradient iteration to solve Ax = b + bicgstab -- Use BIConjugate Gradient STABilized iteration to solve Ax = b + cg -- Use Conjugate Gradient iteration to solve Ax = b + cgs -- Use Conjugate Gradient Squared iteration to solve Ax = b + gmres -- Use Generalized Minimal RESidual iteration to solve Ax = b + lgmres -- Solve a matrix equation using the LGMRES algorithm + minres -- Use MINimum RESidual iteration to solve Ax = b + qmr -- Use Quasi-Minimal Residual iteration to solve Ax = b + gcrotmk -- Solve a matrix equation using the GCROT(m,k) algorithm + tfqmr -- Use Transpose-Free Quasi-Minimal Residual iteration to solve Ax = b + +Iterative methods for least-squares problems: + +.. autosummary:: + :toctree: generated/ + + lsqr -- Find the least-squares solution to a sparse linear equation system + lsmr -- Find the least-squares solution to a sparse linear equation system + +Matrix factorizations +--------------------- + +Eigenvalue problems: + +.. autosummary:: + :toctree: generated/ + + eigs -- Find k eigenvalues and eigenvectors of the square matrix A + eigsh -- Find k eigenvalues and eigenvectors of a symmetric matrix + lobpcg -- Solve symmetric partial eigenproblems with optional preconditioning + +Singular values problems: + +.. autosummary:: + :toctree: generated/ + + svds -- Compute k singular values/vectors for a sparse matrix + +The `svds` function supports the following solvers: + +.. toctree:: + + sparse.linalg.svds-arpack + sparse.linalg.svds-lobpcg + sparse.linalg.svds-propack + +Complete or incomplete LU factorizations + +.. autosummary:: + :toctree: generated/ + + splu -- Compute a LU decomposition for a sparse matrix + spilu -- Compute an incomplete LU decomposition for a sparse matrix + SuperLU -- Object representing an LU factorization + +Sparse arrays with structure +---------------------------- + +.. autosummary:: + :toctree: generated/ + + LaplacianNd -- Laplacian on a uniform rectangular grid in ``N`` dimensions + +Exceptions +---------- + +.. autosummary:: + :toctree: generated/ + + ArpackNoConvergence + ArpackError + +""" + +from ._isolve import * +from ._dsolve import * +from ._interface import * +from ._eigen import * +from ._matfuncs import * +from ._onenormest import * +from ._norm import * +from ._expm_multiply import * +from ._funm_multiply_krylov import * +from ._special_sparse_arrays import * + +# Deprecated namespaces, to be removed in v2.0.0 +from . import isolve, dsolve, interface, eigen, matfuncs + +__all__ = [s for s in dir() if not s.startswith('_')] + +from scipy._lib._testutils import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..09a294ba4c37b32774dd2f27f361e34d8561765d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_expm_multiply.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_expm_multiply.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4128aa8e8db1653f801953efa25bb642f356dfc7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_expm_multiply.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_funm_multiply_krylov.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_funm_multiply_krylov.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..620bd36a7a77742002a478284512cc855eefd0e4 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_funm_multiply_krylov.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_interface.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_interface.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9aa9396979c6af257190ff74cd0ea3085eaae01a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_interface.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_matfuncs.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_matfuncs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3c08af627057ab0a339c4624b54c42aa7c7d276c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_matfuncs.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_norm.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_norm.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..42e80c345af32c2891564a40794222d0d127ff73 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_norm.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_onenormest.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_onenormest.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b877d8eff59b9b51fab0c55ee3490886aed27385 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_onenormest.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_special_sparse_arrays.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_special_sparse_arrays.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7b31300147f379baea34a646df9f9929b36d4c36 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_special_sparse_arrays.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_svdp.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_svdp.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2ae2d292e689edef8a200c45309598ff5ea9690f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/_svdp.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/dsolve.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/dsolve.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c64f808dd4848e2267abdde5a0e0cd608beccaed Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/dsolve.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/eigen.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/eigen.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d6ad2cbb2f3ad3e4724ef3c85b20d8863fbc1817 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/eigen.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/interface.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/interface.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c40e4109749941e3401d883736b46f59b45d919b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/interface.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/isolve.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/isolve.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..df0ecfbd676053bc7eb3871ff821eac8c37cf9ed Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/isolve.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/matfuncs.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/matfuncs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dbdf8a7da2485ea7a548b9fbb2e5395f5d5945f2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/__pycache__/matfuncs.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..90005e3af863d2f7913e6fc4ea8de85962a3efdf --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/__init__.py @@ -0,0 +1,71 @@ +""" +Linear Solvers +============== + +The default solver is SuperLU (included in the scipy distribution), +which can solve real or complex linear systems in both single and +double precisions. It is automatically replaced by UMFPACK, if +available. Note that UMFPACK works in double precision only, so +switch it off by:: + + >>> from scipy.sparse.linalg import spsolve, use_solver + >>> use_solver(useUmfpack=False) + +to solve in the single precision. See also use_solver documentation. + +Example session:: + + >>> from scipy.sparse import csc_array, dia_array + >>> from numpy import array + >>> + >>> print("Inverting a sparse linear system:") + >>> print("The sparse matrix (constructed from diagonals):") + >>> a = dia_array(([[1, 2, 3, 4, 5], [6, 5, 8, 9, 10]], [0, 1]), shape=(5, 5)) + >>> b = array([1, 2, 3, 4, 5]) + >>> print("Solve: single precision complex:") + >>> use_solver( useUmfpack = False ) + >>> a = a.astype('F') + >>> x = spsolve(a, b) + >>> print(x) + >>> print("Error: ", a@x-b) + >>> + >>> print("Solve: double precision complex:") + >>> use_solver( useUmfpack = True ) + >>> a = a.astype('D') + >>> x = spsolve(a, b) + >>> print(x) + >>> print("Error: ", a@x-b) + >>> + >>> print("Solve: double precision:") + >>> a = a.astype('d') + >>> x = spsolve(a, b) + >>> print(x) + >>> print("Error: ", a@x-b) + >>> + >>> print("Solve: single precision:") + >>> use_solver( useUmfpack = False ) + >>> a = a.astype('f') + >>> x = spsolve(a, b.astype('f')) + >>> print(x) + >>> print("Error: ", a@x-b) + +""" + +#import umfpack +#__doc__ = '\n\n'.join( (__doc__, umfpack.__doc__) ) +#del umfpack + +from .linsolve import * +from ._superlu import SuperLU +from . import _add_newdocs +from . import linsolve + +__all__ = [ + 'MatrixRankWarning', 'SuperLU', 'factorized', + 'spilu', 'splu', 'spsolve', 'is_sptriangular', + 'spsolve_triangular', 'use_solver', 'spbandwidth', +] + +from scipy._lib._testutils import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a6168c7c88b3a00d6e0042cb29b6701b7f698405 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/__pycache__/_add_newdocs.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/__pycache__/_add_newdocs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1325d45a029d3a5b0b25c2ae9f1ebcb26e56aa3b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/__pycache__/_add_newdocs.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/__pycache__/linsolve.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/__pycache__/linsolve.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b902c4ced54d60a527e5d4eca4ff4e100f97aec Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/__pycache__/linsolve.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/_add_newdocs.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/_add_newdocs.py new file mode 100644 index 0000000000000000000000000000000000000000..cec34dca456b36a1f77e64f853fc1d821f5215eb --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/_add_newdocs.py @@ -0,0 +1,147 @@ +from numpy.lib import add_newdoc + +add_newdoc('scipy.sparse.linalg._dsolve._superlu', 'SuperLU', + """ + LU factorization of a sparse matrix. + + Factorization is represented as:: + + Pr @ A @ Pc = L @ U + + To construct these `SuperLU` objects, call the `splu` and `spilu` + functions. + + Attributes + ---------- + shape + nnz + perm_c + perm_r + L + U + + Methods + ------- + solve + + Notes + ----- + + .. versionadded:: 0.14.0 + + Examples + -------- + The LU decomposition can be used to solve matrix equations. Consider: + + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import splu + >>> A = csc_array([[1,2,0,4], [1,0,0,1], [1,0,2,1], [2,2,1,0.]]) + + This can be solved for a given right-hand side: + + >>> lu = splu(A) + >>> b = np.array([1, 2, 3, 4]) + >>> x = lu.solve(b) + >>> A.dot(x) + array([ 1., 2., 3., 4.]) + + The ``lu`` object also contains an explicit representation of the + decomposition. The permutations are represented as mappings of + indices: + + >>> lu.perm_r + array([2, 1, 3, 0], dtype=int32) # may vary + >>> lu.perm_c + array([0, 1, 3, 2], dtype=int32) # may vary + + The L and U factors are sparse matrices in CSC format: + + >>> lu.L.toarray() + array([[ 1. , 0. , 0. , 0. ], # may vary + [ 0.5, 1. , 0. , 0. ], + [ 0.5, -1. , 1. , 0. ], + [ 0.5, 1. , 0. , 1. ]]) + >>> lu.U.toarray() + array([[ 2. , 2. , 0. , 1. ], # may vary + [ 0. , -1. , 1. , -0.5], + [ 0. , 0. , 5. , -1. ], + [ 0. , 0. , 0. , 2. ]]) + + The permutation matrices can be constructed: + + >>> Pr = csc_array((np.ones(4), (lu.perm_r, np.arange(4)))) + >>> Pc = csc_array((np.ones(4), (np.arange(4), lu.perm_c))) + + We can reassemble the original matrix: + + >>> (Pr.T @ (lu.L @ lu.U) @ Pc.T).toarray() + array([[ 1., 2., 0., 4.], + [ 1., 0., 0., 1.], + [ 1., 0., 2., 1.], + [ 2., 2., 1., 0.]]) + """) + +add_newdoc('scipy.sparse.linalg._dsolve._superlu', 'SuperLU', ('solve', + """ + solve(rhs[, trans]) + + Solves linear system of equations with one or several right-hand sides. + + Parameters + ---------- + rhs : ndarray, shape (n,) or (n, k) + Right hand side(s) of equation + trans : {'N', 'T', 'H'}, optional + Type of system to solve:: + + 'N': A @ x == rhs (default) + 'T': A^T @ x == rhs + 'H': A^H @ x == rhs + + i.e., normal, transposed, and hermitian conjugate. + + Returns + ------- + x : ndarray, shape ``rhs.shape`` + Solution vector(s) + """)) + +add_newdoc('scipy.sparse.linalg._dsolve._superlu', 'SuperLU', ('L', + """ + Lower triangular factor with unit diagonal as a + `scipy.sparse.csc_array`. + + .. versionadded:: 0.14.0 + """)) + +add_newdoc('scipy.sparse.linalg._dsolve._superlu', 'SuperLU', ('U', + """ + Upper triangular factor as a `scipy.sparse.csc_array`. + + .. versionadded:: 0.14.0 + """)) + +add_newdoc('scipy.sparse.linalg._dsolve._superlu', 'SuperLU', ('shape', + """ + Shape of the original matrix as a tuple of ints. + """)) + +add_newdoc('scipy.sparse.linalg._dsolve._superlu', 'SuperLU', ('nnz', + """ + Number of nonzero elements in the matrix. + """)) + +add_newdoc('scipy.sparse.linalg._dsolve._superlu', 'SuperLU', ('perm_c', + """ + Permutation Pc represented as an array of indices. + + See the `SuperLU` docstring for details. + """)) + +add_newdoc('scipy.sparse.linalg._dsolve._superlu', 'SuperLU', ('perm_r', + """ + Permutation Pr represented as an array of indices. + + See the `SuperLU` docstring for details. + """)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/linsolve.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/linsolve.py new file mode 100644 index 0000000000000000000000000000000000000000..f753fc5f1300ff53c871a29d8c5ec745f8a26282 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/linsolve.py @@ -0,0 +1,885 @@ +from warnings import warn, catch_warnings, simplefilter + +import numpy as np +from numpy import asarray +from scipy.sparse import (issparse, SparseEfficiencyWarning, + csr_array, csc_array, eye_array, diags_array) +from scipy.sparse._sputils import (is_pydata_spmatrix, convert_pydata_sparse_to_scipy, + get_index_dtype, safely_cast_index_arrays) +from scipy.linalg import LinAlgError +import copy +import threading + +from . import _superlu + +noScikit = False +try: + import scikits.umfpack as umfpack +except ImportError: + noScikit = True + +useUmfpack = threading.local() + + +__all__ = ['use_solver', 'spsolve', 'splu', 'spilu', 'factorized', + 'MatrixRankWarning', 'spsolve_triangular', 'is_sptriangular', 'spbandwidth'] + + +class MatrixRankWarning(UserWarning): + """Warning for exactly singular matrices.""" + pass + + +def use_solver(**kwargs): + """ + Select default sparse direct solver to be used. + + Parameters + ---------- + useUmfpack : bool, optional + Use UMFPACK [1]_, [2]_, [3]_, [4]_. over SuperLU. Has effect only + if ``scikits.umfpack`` is installed. Default: True + assumeSortedIndices : bool, optional + Allow UMFPACK to skip the step of sorting indices for a CSR/CSC matrix. + Has effect only if useUmfpack is True and ``scikits.umfpack`` is + installed. Default: False + + Notes + ----- + The default sparse solver is UMFPACK when available + (``scikits.umfpack`` is installed). This can be changed by passing + useUmfpack = False, which then causes the always present SuperLU + based solver to be used. + + UMFPACK requires a CSR/CSC matrix to have sorted column/row indices. If + sure that the matrix fulfills this, pass ``assumeSortedIndices=True`` + to gain some speed. + + References + ---------- + .. [1] T. A. Davis, Algorithm 832: UMFPACK - an unsymmetric-pattern + multifrontal method with a column pre-ordering strategy, ACM + Trans. on Mathematical Software, 30(2), 2004, pp. 196--199. + https://dl.acm.org/doi/abs/10.1145/992200.992206 + + .. [2] T. A. Davis, A column pre-ordering strategy for the + unsymmetric-pattern multifrontal method, ACM Trans. + on Mathematical Software, 30(2), 2004, pp. 165--195. + https://dl.acm.org/doi/abs/10.1145/992200.992205 + + .. [3] T. A. Davis and I. S. Duff, A combined unifrontal/multifrontal + method for unsymmetric sparse matrices, ACM Trans. on + Mathematical Software, 25(1), 1999, pp. 1--19. + https://doi.org/10.1145/305658.287640 + + .. [4] T. A. Davis and I. S. Duff, An unsymmetric-pattern multifrontal + method for sparse LU factorization, SIAM J. Matrix Analysis and + Computations, 18(1), 1997, pp. 140--158. + https://doi.org/10.1137/S0895479894246905T. + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse.linalg import use_solver, spsolve + >>> from scipy.sparse import csc_array + >>> R = np.random.randn(5, 5) + >>> A = csc_array(R) + >>> b = np.random.randn(5) + >>> use_solver(useUmfpack=False) # enforce superLU over UMFPACK + >>> x = spsolve(A, b) + >>> np.allclose(A.dot(x), b) + True + >>> use_solver(useUmfpack=True) # reset umfPack usage to default + """ + global useUmfpack + if 'useUmfpack' in kwargs: + useUmfpack.u = kwargs['useUmfpack'] + if useUmfpack.u and 'assumeSortedIndices' in kwargs: + umfpack.configure(assumeSortedIndices=kwargs['assumeSortedIndices']) + +def _get_umf_family(A): + """Get umfpack family string given the sparse matrix dtype.""" + _families = { + (np.float64, np.int32): 'di', + (np.complex128, np.int32): 'zi', + (np.float64, np.int64): 'dl', + (np.complex128, np.int64): 'zl' + } + + # A.dtype.name can only be "float64" or + # "complex128" in control flow + f_type = getattr(np, A.dtype.name) + # control flow may allow for more index + # types to get through here + i_type = getattr(np, A.indices.dtype.name) + + try: + family = _families[(f_type, i_type)] + + except KeyError as e: + msg = ('only float64 or complex128 matrices with int32 or int64 ' + f'indices are supported! (got: matrix: {f_type}, indices: {i_type})') + raise ValueError(msg) from e + + # See gh-8278. Considered converting only if + # A.shape[0]*A.shape[1] > np.iinfo(np.int32).max, + # but that didn't always fix the issue. + family = family[0] + "l" + A_new = copy.copy(A) + A_new.indptr = np.asarray(A.indptr, dtype=np.int64) + A_new.indices = np.asarray(A.indices, dtype=np.int64) + + return family, A_new + +def spsolve(A, b, permc_spec=None, use_umfpack=True): + """Solve the sparse linear system Ax=b, where b may be a vector or a matrix. + + Parameters + ---------- + A : ndarray or sparse array or matrix + The square matrix A will be converted into CSC or CSR form + b : ndarray or sparse array or matrix + The matrix or vector representing the right hand side of the equation. + If a vector, b.shape must be (n,) or (n, 1). + permc_spec : str, optional + How to permute the columns of the matrix for sparsity preservation. + (default: 'COLAMD') + + - ``NATURAL``: natural ordering. + - ``MMD_ATA``: minimum degree ordering on the structure of A^T A. + - ``MMD_AT_PLUS_A``: minimum degree ordering on the structure of A^T+A. + - ``COLAMD``: approximate minimum degree column ordering [1]_, [2]_. + + use_umfpack : bool, optional + if True (default) then use UMFPACK for the solution [3]_, [4]_, [5]_, + [6]_ . This is only referenced if b is a vector and + ``scikits.umfpack`` is installed. + + Returns + ------- + x : ndarray or sparse array or matrix + the solution of the sparse linear equation. + If b is a vector, then x is a vector of size A.shape[1] + If b is a matrix, then x is a matrix of size (A.shape[1], b.shape[1]) + + Notes + ----- + For solving the matrix expression AX = B, this solver assumes the resulting + matrix X is sparse, as is often the case for very sparse inputs. If the + resulting X is dense, the construction of this sparse result will be + relatively expensive. In that case, consider converting A to a dense + matrix and using scipy.linalg.solve or its variants. + + References + ---------- + .. [1] T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, Algorithm 836: + COLAMD, an approximate column minimum degree ordering algorithm, + ACM Trans. on Mathematical Software, 30(3), 2004, pp. 377--380. + :doi:`10.1145/1024074.1024080` + + .. [2] T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, A column approximate + minimum degree ordering algorithm, ACM Trans. on Mathematical + Software, 30(3), 2004, pp. 353--376. :doi:`10.1145/1024074.1024079` + + .. [3] T. A. Davis, Algorithm 832: UMFPACK - an unsymmetric-pattern + multifrontal method with a column pre-ordering strategy, ACM + Trans. on Mathematical Software, 30(2), 2004, pp. 196--199. + https://dl.acm.org/doi/abs/10.1145/992200.992206 + + .. [4] T. A. Davis, A column pre-ordering strategy for the + unsymmetric-pattern multifrontal method, ACM Trans. + on Mathematical Software, 30(2), 2004, pp. 165--195. + https://dl.acm.org/doi/abs/10.1145/992200.992205 + + .. [5] T. A. Davis and I. S. Duff, A combined unifrontal/multifrontal + method for unsymmetric sparse matrices, ACM Trans. on + Mathematical Software, 25(1), 1999, pp. 1--19. + https://doi.org/10.1145/305658.287640 + + .. [6] T. A. Davis and I. S. Duff, An unsymmetric-pattern multifrontal + method for sparse LU factorization, SIAM J. Matrix Analysis and + Computations, 18(1), 1997, pp. 140--158. + https://doi.org/10.1137/S0895479894246905T. + + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import spsolve + >>> A = csc_array([[3, 2, 0], [1, -1, 0], [0, 5, 1]], dtype=float) + >>> B = csc_array([[2, 0], [-1, 0], [2, 0]], dtype=float) + >>> x = spsolve(A, B) + >>> np.allclose(A.dot(x).toarray(), B.toarray()) + True + """ + is_pydata_sparse = is_pydata_spmatrix(b) + pydata_sparse_cls = b.__class__ if is_pydata_sparse else None + A = convert_pydata_sparse_to_scipy(A) + b = convert_pydata_sparse_to_scipy(b) + + if not (issparse(A) and A.format in ("csc", "csr")): + A = csc_array(A) + warn('spsolve requires A be CSC or CSR matrix format', + SparseEfficiencyWarning, stacklevel=2) + + # b is a vector only if b have shape (n,) or (n, 1) + b_is_sparse = issparse(b) + if not b_is_sparse: + b = asarray(b) + b_is_vector = ((b.ndim == 1) or (b.ndim == 2 and b.shape[1] == 1)) + + # sum duplicates for non-canonical format + A.sum_duplicates() + A = A._asfptype() # upcast to a floating point format + result_dtype = np.promote_types(A.dtype, b.dtype) + if A.dtype != result_dtype: + A = A.astype(result_dtype) + if b.dtype != result_dtype: + b = b.astype(result_dtype) + + # validate input shapes + M, N = A.shape + if (M != N): + raise ValueError(f"matrix must be square (has shape {(M, N)})") + + if M != b.shape[0]: + raise ValueError(f"matrix - rhs dimension mismatch ({A.shape} - {b.shape[0]})") + + if not hasattr(useUmfpack, 'u'): + useUmfpack.u = not noScikit + + use_umfpack = use_umfpack and useUmfpack.u + + if b_is_vector and use_umfpack: + if b_is_sparse: + b_vec = b.toarray() + else: + b_vec = b + b_vec = asarray(b_vec, dtype=A.dtype).ravel() + + if noScikit: + raise RuntimeError('Scikits.umfpack not installed.') + + if A.dtype.char not in 'dD': + raise ValueError("convert matrix data to double, please, using" + " .astype(), or set linsolve.useUmfpack.u = False") + + umf_family, A = _get_umf_family(A) + umf = umfpack.UmfpackContext(umf_family) + x = umf.linsolve(umfpack.UMFPACK_A, A, b_vec, + autoTranspose=True) + else: + if b_is_vector and b_is_sparse: + b = b.toarray() + b_is_sparse = False + + if not b_is_sparse: + if A.format == "csc": + flag = 1 # CSC format + else: + flag = 0 # CSR format + + indices = A.indices.astype(np.intc, copy=False) + indptr = A.indptr.astype(np.intc, copy=False) + options = dict(ColPerm=permc_spec) + x, info = _superlu.gssv(N, A.nnz, A.data, indices, indptr, + b, flag, options=options) + if info != 0: + warn("Matrix is exactly singular", MatrixRankWarning, stacklevel=2) + x.fill(np.nan) + if b_is_vector: + x = x.ravel() + else: + # b is sparse + Afactsolve = factorized(A) + + if not (b.format == "csc" or is_pydata_spmatrix(b)): + warn('spsolve is more efficient when sparse b ' + 'is in the CSC matrix format', + SparseEfficiencyWarning, stacklevel=2) + b = csc_array(b) + + # Create a sparse output matrix by repeatedly applying + # the sparse factorization to solve columns of b. + data_segs = [] + row_segs = [] + col_segs = [] + for j in range(b.shape[1]): + bj = b[:, j].toarray().ravel() + xj = Afactsolve(bj) + w = np.flatnonzero(xj) + segment_length = w.shape[0] + row_segs.append(w) + col_segs.append(np.full(segment_length, j, dtype=int)) + data_segs.append(np.asarray(xj[w], dtype=A.dtype)) + sparse_data = np.concatenate(data_segs) + idx_dtype = get_index_dtype(maxval=max(b.shape)) + sparse_row = np.concatenate(row_segs, dtype=idx_dtype) + sparse_col = np.concatenate(col_segs, dtype=idx_dtype) + x = A.__class__((sparse_data, (sparse_row, sparse_col)), + shape=b.shape, dtype=A.dtype) + + if is_pydata_sparse: + x = pydata_sparse_cls.from_scipy_sparse(x) + + return x + + +def splu(A, permc_spec=None, diag_pivot_thresh=None, + relax=None, panel_size=None, options=None): + """ + Compute the LU decomposition of a sparse, square matrix. + + Parameters + ---------- + A : sparse array or matrix + Sparse array to factorize. Most efficient when provided in CSC + format. Other formats will be converted to CSC before factorization. + permc_spec : str, optional + How to permute the columns of the matrix for sparsity preservation. + (default: 'COLAMD') + + - ``NATURAL``: natural ordering. + - ``MMD_ATA``: minimum degree ordering on the structure of A^T A. + - ``MMD_AT_PLUS_A``: minimum degree ordering on the structure of A^T+A. + - ``COLAMD``: approximate minimum degree column ordering + + diag_pivot_thresh : float, optional + Threshold used for a diagonal entry to be an acceptable pivot. + See SuperLU user's guide for details [1]_ + relax : int, optional + Expert option for customizing the degree of relaxing supernodes. + See SuperLU user's guide for details [1]_ + panel_size : int, optional + Expert option for customizing the panel size. + See SuperLU user's guide for details [1]_ + options : dict, optional + Dictionary containing additional expert options to SuperLU. + See SuperLU user guide [1]_ (section 2.4 on the 'Options' argument) + for more details. For example, you can specify + ``options=dict(Equil=False, IterRefine='SINGLE'))`` + to turn equilibration off and perform a single iterative refinement. + + Returns + ------- + invA : scipy.sparse.linalg.SuperLU + Object, which has a ``solve`` method. + + See also + -------- + spilu : incomplete LU decomposition + + Notes + ----- + When a real array is factorized and the returned SuperLU object's ``solve()`` + method is used with complex arguments an error is generated. Instead, cast the + initial array to complex and then factorize. + + This function uses the SuperLU library. + + References + ---------- + .. [1] SuperLU https://portal.nersc.gov/project/sparse/superlu/ + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import splu + >>> A = csc_array([[1., 0., 0.], [5., 0., 2.], [0., -1., 0.]], dtype=float) + >>> B = splu(A) + >>> x = np.array([1., 2., 3.], dtype=float) + >>> B.solve(x) + array([ 1. , -3. , -1.5]) + >>> A.dot(B.solve(x)) + array([ 1., 2., 3.]) + >>> B.solve(A.dot(x)) + array([ 1., 2., 3.]) + """ + + if is_pydata_spmatrix(A): + A_cls = type(A) + def csc_construct_func(*a, cls=A_cls): + return cls.from_scipy_sparse(csc_array(*a)) + A = A.to_scipy_sparse().tocsc() + else: + csc_construct_func = csc_array + + if not (issparse(A) and A.format == "csc"): + A = csc_array(A) + warn('splu converted its input to CSC format', + SparseEfficiencyWarning, stacklevel=2) + + # sum duplicates for non-canonical format + A.sum_duplicates() + A = A._asfptype() # upcast to a floating point format + + M, N = A.shape + if (M != N): + raise ValueError("can only factor square matrices") # is this true? + + indices, indptr = safely_cast_index_arrays(A, np.intc, "SuperLU") + + _options = dict(DiagPivotThresh=diag_pivot_thresh, ColPerm=permc_spec, + PanelSize=panel_size, Relax=relax) + if options is not None: + _options.update(options) + + # Ensure that no column permutations are applied + if (_options["ColPerm"] == "NATURAL"): + _options["SymmetricMode"] = True + + return _superlu.gstrf(N, A.nnz, A.data, indices, indptr, + csc_construct_func=csc_construct_func, + ilu=False, options=_options) + + +def spilu(A, drop_tol=None, fill_factor=None, drop_rule=None, permc_spec=None, + diag_pivot_thresh=None, relax=None, panel_size=None, options=None): + """ + Compute an incomplete LU decomposition for a sparse, square matrix. + + The resulting object is an approximation to the inverse of `A`. + + Parameters + ---------- + A : (N, N) array_like + Sparse array to factorize. Most efficient when provided in CSC format. + Other formats will be converted to CSC before factorization. + drop_tol : float, optional + Drop tolerance (0 <= tol <= 1) for an incomplete LU decomposition. + (default: 1e-4) + fill_factor : float, optional + Specifies the fill ratio upper bound (>= 1.0) for ILU. (default: 10) + drop_rule : str, optional + Comma-separated string of drop rules to use. + Available rules: ``basic``, ``prows``, ``column``, ``area``, + ``secondary``, ``dynamic``, ``interp``. (Default: ``basic,area``) + + See SuperLU documentation for details. + + Remaining other options + Same as for `splu` + + Returns + ------- + invA_approx : scipy.sparse.linalg.SuperLU + Object, which has a ``solve`` method. + + See also + -------- + splu : complete LU decomposition + + Notes + ----- + When a real array is factorized and the returned SuperLU object's ``solve()`` method + is used with complex arguments an error is generated. Instead, cast the initial + array to complex and then factorize. + + To improve the better approximation to the inverse, you may need to + increase `fill_factor` AND decrease `drop_tol`. + + This function uses the SuperLU library. + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import spilu + >>> A = csc_array([[1., 0., 0.], [5., 0., 2.], [0., -1., 0.]], dtype=float) + >>> B = spilu(A) + >>> x = np.array([1., 2., 3.], dtype=float) + >>> B.solve(x) + array([ 1. , -3. , -1.5]) + >>> A.dot(B.solve(x)) + array([ 1., 2., 3.]) + >>> B.solve(A.dot(x)) + array([ 1., 2., 3.]) + """ + + if is_pydata_spmatrix(A): + A_cls = type(A) + def csc_construct_func(*a, cls=A_cls): + return cls.from_scipy_sparse(csc_array(*a)) + A = A.to_scipy_sparse().tocsc() + else: + csc_construct_func = csc_array + + if not (issparse(A) and A.format == "csc"): + A = csc_array(A) + warn('spilu converted its input to CSC format', + SparseEfficiencyWarning, stacklevel=2) + + # sum duplicates for non-canonical format + A.sum_duplicates() + A = A._asfptype() # upcast to a floating point format + + M, N = A.shape + if (M != N): + raise ValueError("can only factor square matrices") # is this true? + + indices, indptr = safely_cast_index_arrays(A, np.intc, "SuperLU") + + _options = dict(ILU_DropRule=drop_rule, ILU_DropTol=drop_tol, + ILU_FillFactor=fill_factor, + DiagPivotThresh=diag_pivot_thresh, ColPerm=permc_spec, + PanelSize=panel_size, Relax=relax) + if options is not None: + _options.update(options) + + # Ensure that no column permutations are applied + if (_options["ColPerm"] == "NATURAL"): + _options["SymmetricMode"] = True + + return _superlu.gstrf(N, A.nnz, A.data, indices, indptr, + csc_construct_func=csc_construct_func, + ilu=True, options=_options) + + +def factorized(A): + """ + Return a function for solving a sparse linear system, with A pre-factorized. + + Parameters + ---------- + A : (N, N) array_like + Input. A in CSC format is most efficient. A CSR format matrix will + be converted to CSC before factorization. + + Returns + ------- + solve : callable + To solve the linear system of equations given in `A`, the `solve` + callable should be passed an ndarray of shape (N,). + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse.linalg import factorized + >>> from scipy.sparse import csc_array + >>> A = np.array([[ 3. , 2. , -1. ], + ... [ 2. , -2. , 4. ], + ... [-1. , 0.5, -1. ]]) + >>> solve = factorized(csc_array(A)) # Makes LU decomposition. + >>> rhs1 = np.array([1, -2, 0]) + >>> solve(rhs1) # Uses the LU factors. + array([ 1., -2., -2.]) + + """ + if is_pydata_spmatrix(A): + A = A.to_scipy_sparse().tocsc() + + if not hasattr(useUmfpack, 'u'): + useUmfpack.u = not noScikit + + if useUmfpack.u: + if noScikit: + raise RuntimeError('Scikits.umfpack not installed.') + + if not (issparse(A) and A.format == "csc"): + A = csc_array(A) + warn('splu converted its input to CSC format', + SparseEfficiencyWarning, stacklevel=2) + + A = A._asfptype() # upcast to a floating point format + + if A.dtype.char not in 'dD': + raise ValueError("convert matrix data to double, please, using" + " .astype(), or set linsolve.useUmfpack.u = False") + + umf_family, A = _get_umf_family(A) + umf = umfpack.UmfpackContext(umf_family) + + # Make LU decomposition. + umf.numeric(A) + + def solve(b): + with np.errstate(divide="ignore", invalid="ignore"): + # Ignoring warnings with numpy >= 1.23.0, see gh-16523 + result = umf.solve(umfpack.UMFPACK_A, A, b, autoTranspose=True) + + return result + + return solve + else: + return splu(A).solve + + +def spsolve_triangular(A, b, lower=True, overwrite_A=False, overwrite_b=False, + unit_diagonal=False): + """ + Solve the equation ``A x = b`` for `x`, assuming A is a triangular matrix. + + Parameters + ---------- + A : (M, M) sparse array or matrix + A sparse square triangular matrix. Should be in CSR or CSC format. + b : (M,) or (M, N) array_like + Right-hand side matrix in ``A x = b`` + lower : bool, optional + Whether `A` is a lower or upper triangular matrix. + Default is lower triangular matrix. + overwrite_A : bool, optional + Allow changing `A`. + Enabling gives a performance gain. Default is False. + overwrite_b : bool, optional + Allow overwriting data in `b`. + Enabling gives a performance gain. Default is False. + If `overwrite_b` is True, it should be ensured that + `b` has an appropriate dtype to be able to store the result. + unit_diagonal : bool, optional + If True, diagonal elements of `a` are assumed to be 1. + + .. versionadded:: 1.4.0 + + Returns + ------- + x : (M,) or (M, N) ndarray + Solution to the system ``A x = b``. Shape of return matches shape + of `b`. + + Raises + ------ + LinAlgError + If `A` is singular or not triangular. + ValueError + If shape of `A` or shape of `b` do not match the requirements. + + Notes + ----- + .. versionadded:: 0.19.0 + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import spsolve_triangular + >>> A = csc_array([[3, 0, 0], [1, -1, 0], [2, 0, 1]], dtype=float) + >>> B = np.array([[2, 0], [-1, 0], [2, 0]], dtype=float) + >>> x = spsolve_triangular(A, B) + >>> np.allclose(A.dot(x), B) + True + """ + + if is_pydata_spmatrix(A): + A = A.to_scipy_sparse().tocsc() + + trans = "N" + if issparse(A) and A.format == "csr": + A = A.T + trans = "T" + lower = not lower + + if not (issparse(A) and A.format == "csc"): + warn('CSC or CSR matrix format is required. Converting to CSC matrix.', + SparseEfficiencyWarning, stacklevel=2) + A = csc_array(A) + elif not overwrite_A: + A = A.copy() + + + M, N = A.shape + if M != N: + raise ValueError( + f'A must be a square matrix but its shape is {A.shape}.') + + if unit_diagonal: + with catch_warnings(): + simplefilter('ignore', SparseEfficiencyWarning) + A.setdiag(1) + else: + diag = A.diagonal() + if np.any(diag == 0): + raise LinAlgError( + 'A is singular: zero entry on diagonal.') + invdiag = 1/diag + if trans == "N": + A = A @ diags_array(invdiag) + else: + A = (A.T @ diags_array(invdiag)).T + + # sum duplicates for non-canonical format + A.sum_duplicates() + + b = np.asanyarray(b) + + if b.ndim not in [1, 2]: + raise ValueError( + f'b must have 1 or 2 dims but its shape is {b.shape}.') + if M != b.shape[0]: + raise ValueError( + 'The size of the dimensions of A must be equal to ' + 'the size of the first dimension of b but the shape of A is ' + f'{A.shape} and the shape of b is {b.shape}.' + ) + + result_dtype = np.promote_types(np.promote_types(A.dtype, np.float32), b.dtype) + if A.dtype != result_dtype: + A = A.astype(result_dtype) + if b.dtype != result_dtype: + b = b.astype(result_dtype) + elif not overwrite_b: + b = b.copy() + + if lower: + L = A + U = csc_array((N, N), dtype=result_dtype) + else: + L = eye_array(N, dtype=result_dtype, format='csc') + U = A + U.setdiag(0) + + L_indices, L_indptr = safely_cast_index_arrays(L, np.intc, "SuperLU") + U_indices, U_indptr = safely_cast_index_arrays(U, np.intc, "SuperLU") + + x, info = _superlu.gstrs(trans, + N, L.nnz, L.data, L_indices, L_indptr, + N, U.nnz, U.data, U_indices, U_indptr, + b) + if info: + raise LinAlgError('A is singular.') + + if not unit_diagonal: + invdiag = invdiag.reshape(-1, *([1] * (len(x.shape) - 1))) + x = x * invdiag + + return x + + +def is_sptriangular(A): + """Returns 2-tuple indicating lower/upper triangular structure for sparse ``A`` + + Checks for triangular structure in ``A``. The result is summarized in + two boolean values ``lower`` and ``upper`` to designate whether ``A`` is + lower triangular or upper triangular respectively. Diagonal ``A`` will + result in both being True. Non-triangular structure results in False for both. + + Only the sparse structure is used here. Values are not checked for zeros. + + This function will convert a copy of ``A`` to CSC format if it is not already + CSR or CSC format. So it may be more efficient to convert it yourself if you + have other uses for the CSR/CSC version. + + If ``A`` is not square, the portions outside the upper left square of the + matrix do not affect its triangular structure. You probably want to work + with the square portion of the matrix, though it is not requred here. + + Parameters + ---------- + A : SciPy sparse array or matrix + A sparse matrix preferrably in CSR or CSC format. + + Returns + ------- + lower, upper : 2-tuple of bool + + .. versionadded:: 1.15.0 + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array, eye_array + >>> from scipy.sparse.linalg import is_sptriangular + >>> A = csc_array([[3, 0, 0], [1, -1, 0], [2, 0, 1]], dtype=float) + >>> is_sptriangular(A) + (True, False) + >>> D = eye_array(3, format='csr') + >>> is_sptriangular(D) + (True, True) + """ + if not (issparse(A) and A.format in ("csc", "csr", "coo", "dia", "dok", "lil")): + warn('is_sptriangular needs sparse and not BSR format. Converting to CSR.', + SparseEfficiencyWarning, stacklevel=2) + A = csr_array(A) + + # bsr is better off converting to csr + if A.format == "dia": + return A.offsets.max() <= 0, A.offsets.min() >= 0 + elif A.format == "coo": + rows, cols = A.coords + return (cols <= rows).all(), (cols >= rows).all() + elif A.format == "dok": + return all(c <= r for r, c in A.keys()), all(c >= r for r, c in A.keys()) + elif A.format == "lil": + lower = all(col <= row for row, cols in enumerate(A.rows) for col in cols) + upper = all(col >= row for row, cols in enumerate(A.rows) for col in cols) + return lower, upper + # format in ("csc", "csr") + indptr, indices = A.indptr, A.indices + N = len(indptr) - 1 + + lower, upper = True, True + # check middle, 1st, last col (treat as CSC and switch at end if CSR) + for col in [N // 2, 0, -1]: + rows = indices[indptr[col]:indptr[col + 1]] + upper = upper and (col >= rows).all() + lower = lower and (col <= rows).all() + if not upper and not lower: + return False, False + # check all cols + cols = np.repeat(np.arange(N), np.diff(indptr)) + rows = indices + upper = upper and (cols >= rows).all() + lower = lower and (cols <= rows).all() + if A.format == 'csr': + return upper, lower + return lower, upper + + +def spbandwidth(A): + """Return the lower and upper bandwidth of a 2D numeric array. + + Computes the lower and upper limits on the bandwidth of the + sparse 2D array ``A``. The result is summarized as a 2-tuple + of positive integers ``(lo, hi)``. A zero denotes no sub/super + diagonal entries on that side (triangular). The maximum value + for ``lo`` (``hi``) is one less than the number of rows(cols). + + Only the sparse structure is used here. Values are not checked for zeros. + + Parameters + ---------- + A : SciPy sparse array or matrix + A sparse matrix preferrably in CSR or CSC format. + + Returns + ------- + below, above : 2-tuple of int + The distance to the farthest non-zero diagonal below/above the + main diagonal. + + .. versionadded:: 1.15.0 + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse.linalg import spbandwidth + >>> from scipy.sparse import csc_array, eye_array + >>> A = csc_array([[3, 0, 0], [1, -1, 0], [2, 0, 1]], dtype=float) + >>> spbandwidth(A) + (2, 0) + >>> D = eye_array(3, format='csr') + >>> spbandwidth(D) + (0, 0) + """ + if not (issparse(A) and A.format in ("csc", "csr", "coo", "dia", "dok")): + warn('spbandwidth needs sparse format not LIL and BSR. Converting to CSR.', + SparseEfficiencyWarning, stacklevel=2) + A = csr_array(A) + + # bsr and lil are better off converting to csr + if A.format == "dia": + return max(0, -A.offsets.min().item()), max(0, A.offsets.max().item()) + if A.format in ("csc", "csr"): + indptr, indices = A.indptr, A.indices + N = len(indptr) - 1 + gap = np.repeat(np.arange(N), np.diff(indptr)) - indices + if A.format == 'csr': + gap = -gap + elif A.format == "coo": + gap = A.coords[1] - A.coords[0] + elif A.format == "dok": + gap = [(c - r) for r, c in A.keys()] + [0] + return -min(gap), max(gap) + return max(-np.min(gap).item(), 0), max(np.max(gap).item(), 0) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a2eca1462a3f854f97d1f7f9c020309192381949 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/tests/__pycache__/test_linsolve.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/tests/__pycache__/test_linsolve.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..82b81c3423705c8cdf819fb6bdc4203fa8811c9e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/tests/__pycache__/test_linsolve.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/tests/test_linsolve.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/tests/test_linsolve.py new file mode 100644 index 0000000000000000000000000000000000000000..4cdeaf14ad68d3a38778b7dcb99c6d0b67bb3fbe --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_dsolve/tests/test_linsolve.py @@ -0,0 +1,928 @@ +import sys +import threading +import warnings + +import numpy as np +from numpy import array, finfo, arange, eye, all, unique, ones, dot +from numpy.exceptions import ComplexWarning +from numpy.testing import ( + assert_array_almost_equal, assert_almost_equal, + assert_equal, assert_array_equal, assert_, assert_allclose) +import pytest +from pytest import raises as assert_raises, warns as assert_warns + +import scipy.linalg +from scipy.linalg import norm, inv +from scipy.sparse import (dia_array, SparseEfficiencyWarning, csc_array, + csr_array, eye_array, issparse, dok_array, lil_array, bsr_array, kron) +from scipy.sparse.linalg import SuperLU +from scipy.sparse.linalg._dsolve import (spsolve, use_solver, splu, spilu, + MatrixRankWarning, _superlu, spsolve_triangular, factorized, + is_sptriangular, spbandwidth) +import scipy.sparse + +from scipy._lib._testutils import check_free_memory + + +# scikits.umfpack is not a SciPy dependency but it is optionally used in +# dsolve, so check whether it's available +try: + import scikits.umfpack as umfpack + has_umfpack = True +except ImportError: + has_umfpack = False + +def toarray(a): + if issparse(a): + return a.toarray() + else: + return a + + +def setup_bug_8278(): + N = 2 ** 6 + h = 1/N + Ah1D = dia_array(([-1, 2, -1], [-1, 0, 1]), shape=(N-1, N-1))/(h**2) + eyeN = eye_array(N - 1) + A = (kron(eyeN, kron(eyeN, Ah1D)) + + kron(eyeN, kron(Ah1D, eyeN)) + + kron(Ah1D, kron(eyeN, eyeN))) + b = np.random.rand((N-1)**3) + return A, b + + +class TestFactorized: + def setup_method(self): + n = 5 + d = arange(n) + 1 + self.n = n + self.A = dia_array(((d, 2*d, d[::-1]), (-3, 0, 5)), shape=(n,n)).tocsc() + + def _check_singular(self): + A = csc_array((5,5), dtype='d') + b = ones(5) + assert_array_almost_equal(0. * b, factorized(A)(b)) + + def _check_non_singular(self): + # Make a diagonal dominant, to make sure it is not singular + n = 5 + rng = np.random.default_rng(14332) + a = csc_array(rng.random((n, n))) + b = ones(n) + + expected = splu(a).solve(b) + assert_array_almost_equal(factorized(a)(b), expected) + + def test_singular_without_umfpack(self): + use_solver(useUmfpack=False) + with assert_raises(RuntimeError, match="Factor is exactly singular"): + self._check_singular() + + @pytest.mark.skipif(not has_umfpack, reason="umfpack not available") + def test_singular_with_umfpack(self): + use_solver(useUmfpack=True) + with warnings.catch_warnings(): + msg = "divide by zero encountered in double_scalars" + warnings.filterwarnings("ignore", msg, RuntimeWarning) + assert_warns(umfpack.UmfpackWarning, self._check_singular) + + def test_non_singular_without_umfpack(self): + use_solver(useUmfpack=False) + self._check_non_singular() + + @pytest.mark.skipif(not has_umfpack, reason="umfpack not available") + def test_non_singular_with_umfpack(self): + use_solver(useUmfpack=True) + self._check_non_singular() + + def test_cannot_factorize_nonsquare_matrix_without_umfpack(self): + use_solver(useUmfpack=False) + msg = "can only factor square matrices" + with assert_raises(ValueError, match=msg): + factorized(self.A[:, :4]) + + @pytest.mark.skipif(not has_umfpack, reason="umfpack not available") + def test_factorizes_nonsquare_matrix_with_umfpack(self): + use_solver(useUmfpack=True) + # does not raise + factorized(self.A[:,:4]) + + def test_call_with_incorrectly_sized_matrix_without_umfpack(self): + use_solver(useUmfpack=False) + solve = factorized(self.A) + + rng = np.random.default_rng(230498) + b = rng.random(4) + B = rng.random((4, 3)) + BB = rng.random((self.n, 3, 9)) + + with assert_raises(ValueError, match="is of incompatible size"): + solve(b) + with assert_raises(ValueError, match="is of incompatible size"): + solve(B) + with assert_raises(ValueError, + match="object too deep for desired array"): + solve(BB) + + @pytest.mark.skipif(not has_umfpack, reason="umfpack not available") + def test_call_with_incorrectly_sized_matrix_with_umfpack(self): + use_solver(useUmfpack=True) + solve = factorized(self.A) + + rng = np.random.default_rng(643095823) + b = rng.random(4) + B = rng.random((4, 3)) + BB = rng.random((self.n, 3, 9)) + + # does not raise + solve(b) + msg = "object too deep for desired array" + with assert_raises(ValueError, match=msg): + solve(B) + with assert_raises(ValueError, match=msg): + solve(BB) + + def test_call_with_cast_to_complex_without_umfpack(self): + use_solver(useUmfpack=False) + solve = factorized(self.A) + rng = np.random.default_rng(23454) + b = rng.random(4) + for t in [np.complex64, np.complex128]: + with assert_raises(TypeError, match="Cannot cast array data"): + solve(b.astype(t)) + + @pytest.mark.skipif(not has_umfpack, reason="umfpack not available") + def test_call_with_cast_to_complex_with_umfpack(self): + use_solver(useUmfpack=True) + solve = factorized(self.A) + rng = np.random.default_rng(23454) + b = rng.random(4) + for t in [np.complex64, np.complex128]: + assert_warns(ComplexWarning, solve, b.astype(t)) + + @pytest.mark.skipif(not has_umfpack, reason="umfpack not available") + def test_assume_sorted_indices_flag(self): + # a sparse matrix with unsorted indices + unsorted_inds = np.array([2, 0, 1, 0]) + data = np.array([10, 16, 5, 0.4]) + indptr = np.array([0, 1, 2, 4]) + A = csc_array((data, unsorted_inds, indptr), (3, 3)) + b = ones(3) + + # should raise when incorrectly assuming indices are sorted + use_solver(useUmfpack=True, assumeSortedIndices=True) + with assert_raises(RuntimeError, + match="UMFPACK_ERROR_invalid_matrix"): + factorized(A) + + # should sort indices and succeed when not assuming indices are sorted + use_solver(useUmfpack=True, assumeSortedIndices=False) + expected = splu(A.copy()).solve(b) + + assert_equal(A.has_sorted_indices, 0) + assert_array_almost_equal(factorized(A)(b), expected) + + @pytest.mark.slow + @pytest.mark.skipif(not has_umfpack, reason="umfpack not available") + def test_bug_8278(self): + check_free_memory(8000) + use_solver(useUmfpack=True) + A, b = setup_bug_8278() + A = A.tocsc() + f = factorized(A) + x = f(b) + assert_array_almost_equal(A @ x, b) + + +class TestLinsolve: + def setup_method(self): + use_solver(useUmfpack=False) + + def test_singular(self): + A = csc_array((5,5), dtype='d') + b = array([1, 2, 3, 4, 5],dtype='d') + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "Matrix is exactly singular", MatrixRankWarning) + x = spsolve(A, b) + assert_(not np.isfinite(x).any()) + + def test_singular_gh_3312(self): + # "Bad" test case that leads SuperLU to call LAPACK with invalid + # arguments. Check that it fails moderately gracefully. + ij = np.array([(17, 0), (17, 6), (17, 12), (10, 13)], dtype=np.int32) + v = np.array([0.284213, 0.94933781, 0.15767017, 0.38797296]) + A = csc_array((v, ij.T), shape=(20, 20)) + b = np.arange(20) + + try: + # should either raise a runtime error or return value + # appropriate for singular input (which yields the warning) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "Matrix is exactly singular", MatrixRankWarning) + x = spsolve(A, b) + assert not np.isfinite(x).any() + except RuntimeError: + pass + + @pytest.mark.parametrize('format', ['csc', 'csr']) + @pytest.mark.parametrize('idx_dtype', [np.int32, np.int64]) + def test_twodiags(self, format: str, idx_dtype: np.dtype): + A = dia_array(([[1, 2, 3, 4, 5], [6, 5, 8, 9, 10]], [0, 1]), + shape=(5, 5)).asformat(format) + b = array([1, 2, 3, 4, 5]) + + # condition number of A + cond_A = norm(A.toarray(), 2) * norm(inv(A.toarray()), 2) + + for t in ['f','d','F','D']: + eps = finfo(t).eps # floating point epsilon + b = b.astype(t) + Asp = A.astype(t) + Asp.indices = Asp.indices.astype(idx_dtype, copy=False) + Asp.indptr = Asp.indptr.astype(idx_dtype, copy=False) + + x = spsolve(Asp, b) + assert_(norm(b - Asp@x) < 10 * cond_A * eps) + + def test_bvector_smoketest(self): + Adense = array([[0., 1., 1.], + [1., 0., 1.], + [0., 0., 1.]]) + As = csc_array(Adense) + rng = np.random.default_rng(1234) + x = rng.standard_normal(3) + b = As@x + x2 = spsolve(As, b) + + assert_array_almost_equal(x, x2) + + def test_bmatrix_smoketest(self): + Adense = array([[0., 1., 1.], + [1., 0., 1.], + [0., 0., 1.]]) + As = csc_array(Adense) + rng = np.random.default_rng(1234) + x = rng.standard_normal((3, 4)) + Bdense = As.dot(x) + Bs = csc_array(Bdense) + x2 = spsolve(As, Bs) + assert_array_almost_equal(x, x2.toarray()) + + def test_non_square(self): + with warnings.catch_warnings(): + warnings.simplefilter('ignore', SparseEfficiencyWarning) + # A is not square. + A = ones((3, 4)) + b = ones((4, 1)) + assert_raises(ValueError, spsolve, A, b) + # A2 and b2 have incompatible shapes. + A2 = csc_array(eye(3)) + b2 = array([1.0, 2.0]) + assert_raises(ValueError, spsolve, A2, b2) + + def test_example_comparison(self): + with warnings.catch_warnings(): + warnings.simplefilter('ignore', SparseEfficiencyWarning) + row = array([0,0,1,2,2,2]) + col = array([0,2,2,0,1,2]) + data = array([1,2,3,-4,5,6]) + sM = csr_array((data,(row,col)), shape=(3,3), dtype=float) + M = sM.toarray() + + row = array([0,0,1,1,0,0]) + col = array([0,2,1,1,0,0]) + data = array([1,1,1,1,1,1]) + sN = csr_array((data, (row,col)), shape=(3,3), dtype=float) + N = sN.toarray() + + sX = spsolve(sM, sN) + X = scipy.linalg.solve(M, N) + + assert_array_almost_equal(X, sX.toarray()) + + @pytest.mark.skipif(not has_umfpack, reason="umfpack not available") + def test_shape_compatibility(self): + with warnings.catch_warnings(): + warnings.simplefilter('ignore', SparseEfficiencyWarning) + use_solver(useUmfpack=True) + A = csc_array([[1., 0], [0, 2]]) + bs = [ + [1, 6], + array([1, 6]), + [[1], [6]], + array([[1], [6]]), + csc_array([[1], [6]]), + csr_array([[1], [6]]), + dok_array([[1], [6]]), + bsr_array([[1], [6]]), + array([[1., 2., 3.], [6., 8., 10.]]), + csc_array([[1., 2., 3.], [6., 8., 10.]]), + csr_array([[1., 2., 3.], [6., 8., 10.]]), + dok_array([[1., 2., 3.], [6., 8., 10.]]), + bsr_array([[1., 2., 3.], [6., 8., 10.]]), + ] + + for b in bs: + x = np.linalg.solve(A.toarray(), toarray(b)) + for spmattype in [csc_array, csr_array, dok_array, lil_array]: + x1 = spsolve(spmattype(A), b, use_umfpack=True) + x2 = spsolve(spmattype(A), b, use_umfpack=False) + + # check solution + if x.ndim == 2 and x.shape[1] == 1: + # interprets also these as "vectors" + x = x.ravel() + + assert_array_almost_equal(toarray(x1), x, + err_msg=repr((b, spmattype, 1))) + assert_array_almost_equal(toarray(x2), x, + err_msg=repr((b, spmattype, 2))) + + # dense vs. sparse output ("vectors" are always dense) + if issparse(b) and x.ndim > 1: + assert_(issparse(x1), repr((b, spmattype, 1))) + assert_(issparse(x2), repr((b, spmattype, 2))) + else: + assert_(isinstance(x1, np.ndarray), repr((b, spmattype, 1))) + assert_(isinstance(x2, np.ndarray), repr((b, spmattype, 2))) + + # check output shape + if x.ndim == 1: + # "vector" + assert_equal(x1.shape, (A.shape[1],)) + assert_equal(x2.shape, (A.shape[1],)) + else: + # "matrix" + assert_equal(x1.shape, x.shape) + assert_equal(x2.shape, x.shape) + + A = csc_array((3, 3)) + b = csc_array((1, 3)) + assert_raises(ValueError, spsolve, A, b) + + def test_ndarray_support(self): + with warnings.catch_warnings(): + warnings.simplefilter('ignore', SparseEfficiencyWarning) + A = array([[1., 2.], [2., 0.]]) + x = array([[1., 1.], [0.5, -0.5]]) + b = array([[2., 0.], [2., 2.]]) + + assert_array_almost_equal(x, spsolve(A, b)) + + def test_gssv_badinput(self): + N = 10 + d = arange(N) + 1.0 + A = dia_array(((d, 2*d, d[::-1]), (-3, 0, 5)), shape=(N, N)) + + for container in (csc_array, csr_array): + A = container(A) + b = np.arange(N) + + def not_c_contig(x): + return x.repeat(2)[::2] + + def not_1dim(x): + return x[:,None] + + def bad_type(x): + return x.astype(bool) + + def too_short(x): + return x[:-1] + + badops = [not_c_contig, not_1dim, bad_type, too_short] + + for badop in badops: + msg = f"{container!r} {badop!r}" + # Not C-contiguous + assert_raises((ValueError, TypeError), _superlu.gssv, + N, A.nnz, badop(A.data), A.indices, A.indptr, + b, int(A.format == 'csc'), err_msg=msg) + assert_raises((ValueError, TypeError), _superlu.gssv, + N, A.nnz, A.data, badop(A.indices), A.indptr, + b, int(A.format == 'csc'), err_msg=msg) + assert_raises((ValueError, TypeError), _superlu.gssv, + N, A.nnz, A.data, A.indices, badop(A.indptr), + b, int(A.format == 'csc'), err_msg=msg) + + def test_sparsity_preservation(self): + ident = csc_array([ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1]]) + b = csc_array([ + [0, 1], + [1, 0], + [0, 0]]) + x = spsolve(ident, b) + assert_equal(ident.nnz, 3) + assert_equal(b.nnz, 2) + assert_equal(x.nnz, 2) + assert_allclose(x.toarray(), b.toarray(), atol=1e-12, rtol=1e-12) + + def test_dtype_cast(self): + A_real = scipy.sparse.csr_array([[1, 2, 0], + [0, 0, 3], + [4, 0, 5]]) + A_complex = scipy.sparse.csr_array([[1, 2, 0], + [0, 0, 3], + [4, 0, 5 + 1j]]) + b_real = np.array([1,1,1]) + b_complex = np.array([1,1,1]) + 1j*np.array([1,1,1]) + x = spsolve(A_real, b_real) + assert_(np.issubdtype(x.dtype, np.floating)) + x = spsolve(A_real, b_complex) + assert_(np.issubdtype(x.dtype, np.complexfloating)) + x = spsolve(A_complex, b_real) + assert_(np.issubdtype(x.dtype, np.complexfloating)) + x = spsolve(A_complex, b_complex) + assert_(np.issubdtype(x.dtype, np.complexfloating)) + + @pytest.mark.slow + @pytest.mark.skipif(not has_umfpack, reason="umfpack not available") + def test_bug_8278(self): + check_free_memory(8000) + use_solver(useUmfpack=True) + A, b = setup_bug_8278() + x = spsolve(A, b) + assert_array_almost_equal(A @ x, b) + + +class TestSplu: + def setup_method(self): + use_solver(useUmfpack=False) + n = 40 + d = arange(n) + 1 + self.n = n + self.A = dia_array(((d, 2*d, d[::-1]), (-3, 0, 5)), shape=(n, n)).tocsc() + + def _smoketest(self, spxlu, check, dtype, idx_dtype): + if np.issubdtype(dtype, np.complexfloating): + A = self.A + 1j*self.A.T + else: + A = self.A + + A = A.astype(dtype) + A.indices = A.indices.astype(idx_dtype, copy=False) + A.indptr = A.indptr.astype(idx_dtype, copy=False) + lu = spxlu(A) + + rng = np.random.RandomState(1234) + + # Input shapes + for k in [None, 1, 2, self.n, self.n+2]: + msg = f"k={k!r}" + + if k is None: + b = rng.rand(self.n) + else: + b = rng.rand(self.n, k) + + if np.issubdtype(dtype, np.complexfloating): + b = b + 1j*rng.rand(*b.shape) + b = b.astype(dtype) + + x = lu.solve(b) + check(A, b, x, msg) + + x = lu.solve(b, 'T') + check(A.T, b, x, msg) + + x = lu.solve(b, 'H') + check(A.T.conj(), b, x, msg) + + def test_splu_smoketest(self): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + self._internal_test_splu_smoketest() + + def _internal_test_splu_smoketest(self): + # Check that splu works at all + def check(A, b, x, msg=""): + eps = np.finfo(A.dtype).eps + r = A @ x + assert_(abs(r - b).max() < 1e3*eps, msg) + + for dtype in [np.float32, np.float64, np.complex64, np.complex128]: + for idx_dtype in [np.int32, np.int64]: + self._smoketest(splu, check, dtype, idx_dtype) + + def test_spilu_smoketest(self): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + self._internal_test_spilu_smoketest() + + def _internal_test_spilu_smoketest(self): + errors = [] + + def check(A, b, x, msg=""): + r = A @ x + err = abs(r - b).max() + assert_(err < 1e-2, msg) + if b.dtype in (np.float64, np.complex128): + errors.append(err) + + for dtype in [np.float32, np.float64, np.complex64, np.complex128]: + for idx_dtype in [np.int32, np.int64]: + self._smoketest(spilu, check, dtype, idx_dtype) + + assert_(max(errors) > 1e-5) + + def test_spilu_drop_rule(self): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + # Test passing in the drop_rule argument to spilu. + A = eye_array(2) + + rules = [ + b'basic,area'.decode('ascii'), # unicode + b'basic,area', # ascii + [b'basic', b'area'.decode('ascii')] + ] + for rule in rules: + # Argument should be accepted + assert_(isinstance(spilu(A, drop_rule=rule), SuperLU)) + + def test_splu_nnz0(self): + A = csc_array((5,5), dtype='d') + assert_raises(RuntimeError, splu, A) + + def test_spilu_nnz0(self): + A = csc_array((5,5), dtype='d') + assert_raises(RuntimeError, spilu, A) + + def test_splu_basic(self): + # Test basic splu functionality. + n = 30 + rng = np.random.RandomState(12) + a = rng.rand(n, n) + a[a < 0.95] = 0 + # First test with a singular matrix + a[:, 0] = 0 + a_ = csc_array(a) + # Matrix is exactly singular + assert_raises(RuntimeError, splu, a_) + + # Make a diagonal dominant, to make sure it is not singular + a += 4*eye(n) + a_ = csc_array(a) + lu = splu(a_) + b = ones(n) + x = lu.solve(b) + assert_almost_equal(dot(a, x), b) + + def test_splu_perm(self): + # Test the permutation vectors exposed by splu. + n = 30 + rng = np.random.default_rng(1342354) + a = rng.random((n, n)) + a[a < 0.95] = 0 + # Make a diagonal dominant, to make sure it is not singular + a += 4*eye(n) + a_ = csc_array(a) + lu = splu(a_) + # Check that the permutation indices do belong to [0, n-1]. + for perm in (lu.perm_r, lu.perm_c): + assert_(all(perm > -1)) + assert_(all(perm < n)) + assert_equal(len(unique(perm)), len(perm)) + + # Now make a symmetric, and test that the two permutation vectors are + # the same + # Note: a += a.T relies on undefined behavior. + a = a + a.T + a_ = csc_array(a) + lu = splu(a_) + assert_array_equal(lu.perm_r, lu.perm_c) + + @pytest.mark.parametrize("splu_fun, rtol", [(splu, 1e-7), (spilu, 1e-1)]) + def test_natural_permc(self, splu_fun, rtol): + # Test that the "NATURAL" permc_spec does not permute the matrix + rng = np.random.RandomState(42) + n = 500 + p = 0.01 + A = scipy.sparse.random(n, n, p, random_state=rng) + x = rng.rand(n) + # Make A diagonal dominant to make sure it is not singular + A += (n+1)*scipy.sparse.eye_array(n) + A_ = csc_array(A) + b = A_ @ x + + # without permc_spec, permutation is not identity + lu = splu_fun(A_) + assert_(np.any(lu.perm_c != np.arange(n))) + + # with permc_spec="NATURAL", permutation is identity + lu = splu_fun(A_, permc_spec="NATURAL") + assert_array_equal(lu.perm_c, np.arange(n)) + + # Also, lu decomposition is valid + x2 = lu.solve(b) + assert_allclose(x, x2, rtol=rtol) + + @pytest.mark.skipif(not hasattr(sys, 'getrefcount'), reason="no sys.getrefcount") + def test_lu_refcount(self): + # Test that we are keeping track of the reference count with splu. + n = 30 + rng = np.random.default_rng(1342354) + a = rng.random((n, n)) + a[a < 0.95] = 0 + # Make a diagonal dominant, to make sure it is not singular + a += 4*eye(n) + a_ = csc_array(a) + lu = splu(a_) + + # And now test that we don't have a refcount bug + rc = sys.getrefcount(lu) + for attr in ('perm_r', 'perm_c'): + perm = getattr(lu, attr) + assert_equal(sys.getrefcount(lu), rc + 1) + del perm + assert_equal(sys.getrefcount(lu), rc) + + def test_bad_inputs(self): + A = self.A.tocsc() + rng = np.random.default_rng(235634) + + assert_raises(ValueError, splu, A[:,:4]) + assert_raises(ValueError, spilu, A[:,:4]) + + for lu in [splu(A), spilu(A)]: + b = rng.random(42) + B = rng.random((42, 3)) + BB = rng.random((self.n, 3, 9)) + assert_raises(ValueError, lu.solve, b) + assert_raises(ValueError, lu.solve, B) + assert_raises(ValueError, lu.solve, BB) + assert_raises(TypeError, lu.solve, + b.astype(np.complex64)) + assert_raises(TypeError, lu.solve, + b.astype(np.complex128)) + + def test_superlu_dlamch_i386_nan(self): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + # SuperLU 4.3 calls some functions returning floats without + # declaring them. On i386@linux call convention, this fails to + # clear floating point registers after call. As a result, NaN + # can appear in the next floating point operation made. + # + # Here's a test case that triggered the issue. + n = 8 + d = np.arange(n) + 1 + A = dia_array(((d, 2*d, d[::-1]), (-3, 0, 5)), shape=(n, n)) + A = A.astype(np.float32) + spilu(A) + A = A + 1j*A + B = A.toarray() + assert_(not np.isnan(B).any()) + + def test_lu_attr(self): + def check(dtype, complex_2=False): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + + A = self.A.astype(dtype) + + if complex_2: + A = A + 1j*A.T + + n = A.shape[0] + lu = splu(A) + + # Check that the decomposition is as advertised + + Pc = np.zeros((n, n)) + Pc[np.arange(n), lu.perm_c] = 1 + + Pr = np.zeros((n, n)) + Pr[lu.perm_r, np.arange(n)] = 1 + + Ad = A.toarray() + lhs = Pr.dot(Ad).dot(Pc) + rhs = (lu.L @ lu.U).toarray() + + eps = np.finfo(dtype).eps + + assert_allclose(lhs, rhs, atol=100*eps) + + check(np.float32) + check(np.float64) + check(np.complex64) + check(np.complex128) + check(np.complex64, True) + check(np.complex128, True) + + @pytest.mark.slow + def test_threads_parallel(self): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + oks = [] + + def worker(): + try: + self.test_splu_basic() + self._internal_test_splu_smoketest() + self._internal_test_spilu_smoketest() + oks.append(True) + except Exception: + pass + + threads = [threading.Thread(target=worker) + for k in range(20)] + for t in threads: + t.start() + for t in threads: + t.join() + + assert_equal(len(oks), 20) + + def test_singular_matrix(self): + # Test that SuperLU does not print to stdout when a singular matrix is + # passed. See gh-20993. + A = eye_array(10, format='csr') + A[-1, -1] = 0 + b = np.zeros(10) + with pytest.warns(MatrixRankWarning): + res = spsolve(A, b) + assert np.isnan(res).all() + + +class TestGstrsErrors: + def setup_method(self): + self.A = array([[1.0,2.0,3.0],[4.0,5.0,6.0],[7.0,8.0,9.0]], dtype=np.float64) + self.b = np.array([[1.0],[2.0],[3.0]], dtype=np.float64) + + def test_trans(self): + L = scipy.sparse.tril(self.A, format='csc') + U = scipy.sparse.triu(self.A, k=1, format='csc') + with assert_raises(ValueError, match="trans must be N, T, or H"): + _superlu.gstrs('X', L.shape[0], L.nnz, L.data, L.indices, L.indptr, + U.shape[0], U.nnz, U.data, U.indices, U.indptr, self.b) + + def test_shape_LU(self): + L = scipy.sparse.tril(self.A[0:2,0:2], format='csc') + U = scipy.sparse.triu(self.A, k=1, format='csc') + with assert_raises(ValueError, match="L and U must have the same dimension"): + _superlu.gstrs('N', L.shape[0], L.nnz, L.data, L.indices, L.indptr, + U.shape[0], U.nnz, U.data, U.indices, U.indptr, self.b) + + def test_shape_b(self): + L = scipy.sparse.tril(self.A, format='csc') + U = scipy.sparse.triu(self.A, k=1, format='csc') + with assert_raises(ValueError, match="right hand side array has invalid shape"): + _superlu.gstrs('N', L.shape[0], L.nnz, L.data, L.indices, L.indptr, + U.shape[0], U.nnz, U.data, U.indices, U.indptr, + self.b[0:2]) + + def test_types_differ(self): + L = scipy.sparse.tril(self.A.astype(np.float32), format='csc') + U = scipy.sparse.triu(self.A, k=1, format='csc') + with assert_raises(TypeError, match="nzvals types of L and U differ"): + _superlu.gstrs('N', L.shape[0], L.nnz, L.data, L.indices, L.indptr, + U.shape[0], U.nnz, U.data, U.indices, U.indptr, self.b) + + def test_types_unsupported(self): + L = scipy.sparse.tril(self.A.astype(np.uint8), format='csc') + U = scipy.sparse.triu(self.A.astype(np.uint8), k=1, format='csc') + with assert_raises(TypeError, match="nzvals is not of a type supported"): + _superlu.gstrs('N', L.shape[0], L.nnz, L.data, L.indices, L.indptr, + U.shape[0], U.nnz, U.data, U.indices, U.indptr, + self.b.astype(np.uint8)) + +class TestSpsolveTriangular: + def setup_method(self): + use_solver(useUmfpack=False) + + @pytest.mark.parametrize("fmt",["csr","csc"]) + def test_zero_diagonal(self,fmt): + n = 5 + rng = np.random.default_rng(43876432987) + A = rng.standard_normal((n, n)) + b = np.arange(n) + A = scipy.sparse.tril(A, k=0, format=fmt) + + x = spsolve_triangular(A, b, unit_diagonal=True, lower=True) + + A.setdiag(1) + assert_allclose(A.dot(x), b) + + # Regression test from gh-15199 + A = np.array([[0, 0, 0], [1, 0, 0], [1, 1, 0]], dtype=np.float64) + b = np.array([1., 2., 3.]) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "CSC or CSR matrix format is", SparseEfficiencyWarning) + spsolve_triangular(A, b, unit_diagonal=True) + + @pytest.mark.parametrize("fmt",["csr","csc"]) + def test_singular(self,fmt): + n = 5 + if fmt == "csr": + A = csr_array((n, n)) + else: + A = csc_array((n, n)) + b = np.arange(n) + for lower in (True, False): + assert_raises(scipy.linalg.LinAlgError, + spsolve_triangular, A, b, lower=lower) + + def test_bad_shape(self): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + # A is not square. + A = np.zeros((3, 4)) + b = ones((4, 1)) + assert_raises(ValueError, spsolve_triangular, A, b) + # A2 and b2 have incompatible shapes. + A2 = csr_array(eye(3)) + b2 = array([1.0, 2.0]) + assert_raises(ValueError, spsolve_triangular, A2, b2) + + def test_input_types(self): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + A = array([[1., 0.], [1., 2.]]) + b = array([[2., 0.], [2., 2.]]) + for matrix_type in (array, csc_array, csr_array): + x = spsolve_triangular(matrix_type(A), b, lower=True) + assert_array_almost_equal(A.dot(x), b) + + @pytest.mark.slow + @pytest.mark.parametrize("n", [10, 10**2, 10**3]) + @pytest.mark.parametrize("m", [1, 10]) + @pytest.mark.parametrize("lower", [True, False]) + @pytest.mark.parametrize("format", ["csr", "csc"]) + @pytest.mark.parametrize("unit_diagonal", [False, True]) + @pytest.mark.parametrize("choice_of_A", ["real", "complex"]) + @pytest.mark.parametrize("choice_of_b", ["floats", "ints", "complexints"]) + def test_random(self, n, m, lower, format, unit_diagonal, choice_of_A, choice_of_b): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + def random_triangle_matrix(n, lower=True, format="csr", choice_of_A="real"): + if choice_of_A == "real": + dtype = np.float64 + elif choice_of_A == "complex": + dtype = np.complex128 + else: + raise ValueError("choice_of_A must be 'real' or 'complex'.") + rng = np.random.default_rng(789002319) + rvs = rng.random + A = scipy.sparse.random(n, n, density=0.1, format='lil', dtype=dtype, + random_state=rng, data_rvs=rvs) + if lower: + A = scipy.sparse.tril(A, format="lil") + else: + A = scipy.sparse.triu(A, format="lil") + for i in range(n): + A[i, i] = np.random.rand() + 1 + if format == "csc": + A = A.tocsc(copy=False) + else: + A = A.tocsr(copy=False) + return A + + rng = np.random.default_rng(1234) + A = random_triangle_matrix(n, lower=lower) + if choice_of_b == "floats": + b = rng.random((n, m)) + elif choice_of_b == "ints": + b = rng.integers(-9, 9, (n, m)) + elif choice_of_b == "complexints": + b = rng.integers(-9, 9, (n, m)) + rng.integers(-9, 9, (n, m)) * 1j + else: + raise ValueError( + "choice_of_b must be 'floats', 'ints', or 'complexints'.") + x = spsolve_triangular(A, b, lower=lower, unit_diagonal=unit_diagonal) + if unit_diagonal: + A.setdiag(1) + assert_allclose(A.dot(x), b, atol=1.5e-6) + + +@pytest.mark.parametrize("nnz", [10, 10**2, 10**3]) +@pytest.mark.parametrize("fmt", ["csr", "csc", "coo", "dia", "dok", "lil"]) +def test_is_sptriangular_and_spbandwidth(nnz, fmt): + with warnings.catch_warnings(): + warnings.simplefilter('ignore', SparseEfficiencyWarning) + rng = np.random.default_rng(42) + + N = nnz // 2 + dens = 0.1 + A = scipy.sparse.random_array((N, N), density=dens, format="csr", rng=rng) + A[1, 3] = A[3, 1] = 22 # ensure not upper or lower + A = A.asformat(fmt) + AU = scipy.sparse.triu(A, format=fmt) + AL = scipy.sparse.tril(A, format=fmt) + D = 0.1 * scipy.sparse.eye_array(N, format=fmt) + + assert is_sptriangular(A) == (False, False) + assert is_sptriangular(AL) == (True, False) + assert is_sptriangular(AU) == (False, True) + assert is_sptriangular(D) == (True, True) + + assert spbandwidth(A) == scipy.linalg.bandwidth(A.toarray()) + assert spbandwidth(AU) == scipy.linalg.bandwidth(AU.toarray()) + assert spbandwidth(AL) == scipy.linalg.bandwidth(AL.toarray()) + assert spbandwidth(D) == scipy.linalg.bandwidth(D.toarray()) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..25278d34ecd3353d409a25f7a94797902fe6ef93 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/__init__.py @@ -0,0 +1,22 @@ +""" +Sparse Eigenvalue Solvers +------------------------- + +The submodules of sparse.linalg._eigen: + 1. lobpcg: Locally Optimal Block Preconditioned Conjugate Gradient Method + +""" +from .arpack import * +from .lobpcg import * +from ._svds import svds + +from . import arpack + +__all__ = [ + 'ArpackError', 'ArpackNoConvergence', + 'eigs', 'eigsh', 'lobpcg', 'svds' +] + +from scipy._lib._testutils import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..002b6b88d3de80999e0b11fbee0dc3c6f74a3f3e Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/__pycache__/_svds.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/__pycache__/_svds.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4449cade3d2bc84d22eb55909b73a73789077b28 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/__pycache__/_svds.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/__pycache__/_svds_doc.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/__pycache__/_svds_doc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b4139ee1f453e8530b5f4e789a9a3bfe88623c37 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/__pycache__/_svds_doc.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/_svds.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/_svds.py new file mode 100644 index 0000000000000000000000000000000000000000..f0591f8fe252b85b77c32fda509cc656ffdf7b29 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/_svds.py @@ -0,0 +1,545 @@ +import math +import numbers +import numpy as np +from . import eigsh + +from scipy._lib._util import _transition_to_rng +from scipy.sparse.linalg._interface import LinearOperator, aslinearoperator +from scipy.sparse.linalg._eigen.lobpcg import lobpcg # type: ignore[no-redef] +from scipy.sparse.linalg._svdp import _svdp +from scipy.linalg import svd + +__all__ = ['svds'] + + +def _herm(x): + return x.T.conj() + + +def _iv(A, k, ncv, tol, which, v0, maxiter, + return_singular, solver, rng): + + # input validation/standardization for `solver` + # out of order because it's needed for other parameters + solver = str(solver).lower() + solvers = {"arpack", "lobpcg", "propack"} + if solver not in solvers: + raise ValueError(f"solver must be one of {solvers}.") + + # input validation/standardization for `A` + A = aslinearoperator(A) # this takes care of some input validation + if not np.issubdtype(A.dtype, np.number): + message = "`A` must be of numeric data type." + raise ValueError(message) + if math.prod(A.shape) == 0: + message = "`A` must not be empty." + raise ValueError(message) + + # input validation/standardization for `k` + kmax = min(A.shape) if solver == 'propack' else min(A.shape) - 1 + if int(k) != k or not (0 < k <= kmax): + message = "`k` must be an integer satisfying `0 < k < min(A.shape)`." + raise ValueError(message) + k = int(k) + + # input validation/standardization for `ncv` + if solver == "arpack" and ncv is not None: + if int(ncv) != ncv or not (k < ncv < min(A.shape)): + message = ("`ncv` must be an integer satisfying " + "`k < ncv < min(A.shape)`.") + raise ValueError(message) + ncv = int(ncv) + + # input validation/standardization for `tol` + if tol < 0 or not np.isfinite(tol): + message = "`tol` must be a non-negative floating point value." + raise ValueError(message) + tol = float(tol) + + # input validation/standardization for `which` + which = str(which).upper() + whichs = {'LM', 'SM'} + if which not in whichs: + raise ValueError(f"`which` must be in {whichs}.") + + # input validation/standardization for `v0` + if v0 is not None: + v0 = np.atleast_1d(v0) + if not (np.issubdtype(v0.dtype, np.complexfloating) + or np.issubdtype(v0.dtype, np.floating)): + message = ("`v0` must be of floating or complex floating " + "data type.") + raise ValueError(message) + + shape = (A.shape[0],) if solver == 'propack' else (min(A.shape),) + if v0.shape != shape: + message = f"`v0` must have shape {shape}." + raise ValueError(message) + + # input validation/standardization for `maxiter` + if maxiter is not None and (int(maxiter) != maxiter or maxiter <= 0): + message = "`maxiter` must be a positive integer." + raise ValueError(message) + maxiter = int(maxiter) if maxiter is not None else maxiter + + # input validation/standardization for `return_singular_vectors` + # not going to be flexible with this; too complicated for little gain + rs_options = {True, False, "vh", "u"} + if return_singular not in rs_options: + raise ValueError(f"`return_singular_vectors` must be in {rs_options}.") + + if isinstance(rng, numbers.Integral | np.integer): + rng = np.random.default_rng(np.random.RandomState(rng)) + elif isinstance(rng, np.random.RandomState): + rng = np.random.default_rng(rng) + elif rng is None: + rng = np.random.default_rng() + elif isinstance(rng, np.random.Generator): + pass + else: + raise ValueError(f"'{rng}' is neither a NumPy Generator nor an integer seed" + " to instantiate one. For future-proofing, prefer using a" + " NumPy Generator.") + + return (A, k, ncv, tol, which, v0, maxiter, + return_singular, solver, rng) + + +@_transition_to_rng("random_state", position_num=9) +def svds(A, k=6, ncv=None, tol=0, which='LM', v0=None, + maxiter=None, return_singular_vectors=True, + solver='arpack', rng=None, options=None): + """ + Partial singular value decomposition of a sparse matrix. + + Compute the largest or smallest `k` singular values and corresponding + singular vectors of a sparse matrix `A`. The order in which the singular + values are returned is not guaranteed. + + In the descriptions below, let ``M, N = A.shape``. + + Parameters + ---------- + A : ndarray, sparse matrix, or LinearOperator + Matrix to decompose of a floating point numeric dtype. + k : int, default: 6 + Number of singular values and singular vectors to compute. + Must satisfy ``1 <= k <= kmax``, where ``kmax=min(M, N)`` for + ``solver='propack'`` and ``kmax=min(M, N) - 1`` otherwise. + ncv : int, optional + When ``solver='arpack'``, this is the number of Lanczos vectors + generated. See :ref:`'arpack' ` for details. + When ``solver='lobpcg'`` or ``solver='propack'``, this parameter is + ignored. + tol : float, optional + Tolerance for singular values. Zero (default) means machine precision. + which : {'LM', 'SM'} + Which `k` singular values to find: either the largest magnitude ('LM') + or smallest magnitude ('SM') singular values. + v0 : ndarray, optional + The starting vector for iteration; see method-specific + documentation (:ref:`'arpack' `, + :ref:`'lobpcg' `), or + :ref:`'propack' ` for details. + maxiter : int, optional + Maximum number of iterations; see method-specific + documentation (:ref:`'arpack' `, + :ref:`'lobpcg' `), or + :ref:`'propack' ` for details. + return_singular_vectors : {True, False, "u", "vh"} + Singular values are always computed and returned; this parameter + controls the computation and return of singular vectors. + + - ``True``: return singular vectors. + - ``False``: do not return singular vectors. + - ``"u"``: if ``M <= N``, compute only the left singular vectors and + return ``None`` for the right singular vectors. Otherwise, compute + all singular vectors. + - ``"vh"``: if ``M > N``, compute only the right singular vectors and + return ``None`` for the left singular vectors. Otherwise, compute + all singular vectors. + + If ``solver='propack'``, the option is respected regardless of the + matrix shape. + + solver : {'arpack', 'propack', 'lobpcg'}, optional + The solver used. + :ref:`'arpack' `, + :ref:`'lobpcg' `, and + :ref:`'propack' ` are supported. + Default: `'arpack'`. + rng : `numpy.random.Generator`, optional + Pseudorandom number generator state. When `rng` is None, a new + `numpy.random.Generator` is created using entropy from the + operating system. Types other than `numpy.random.Generator` are + passed to `numpy.random.default_rng` to instantiate a ``Generator``. + options : dict, optional + A dictionary of solver-specific options. No solver-specific options + are currently supported; this parameter is reserved for future use. + + Returns + ------- + u : ndarray, shape=(M, k) + Unitary matrix having left singular vectors as columns. + s : ndarray, shape=(k,) + The singular values. + vh : ndarray, shape=(k, N) + Unitary matrix having right singular vectors as rows. + + Notes + ----- + When ARPACK or LOBPCG is selected as the method, the singular values and + singular vectors are computed as the eigenvalues and eigenvectors of the + corresponding Gram matrix, either ``A.conj().T @ A`` or ``A @ A.conj().T``, + depending on which one is computationally cheaper. It is then followed by + the Rayleigh-Ritz method as postprocessing; see Using the normal matrix, + in Rayleigh-Ritz method, (2022, Nov. 19), Wikipedia, https://w.wiki/4zms. + + Alternatively, the PROPACK solver can be called. + + Dtype of `A` is mapped, if possible, to float(32,64) and complex(64,128) + for internal computations. + + Examples + -------- + Construct a matrix `A` from singular values and vectors. + + >>> import numpy as np + >>> from scipy import sparse, linalg, stats + >>> from scipy.sparse.linalg import svds, aslinearoperator, LinearOperator + + Construct a dense matrix `A` from singular values and vectors. + + >>> rng = np.random.default_rng(258265244568965474821194062361901728911) + >>> orthogonal = stats.ortho_group.rvs(10, random_state=rng) + >>> s = [1e-3, 1, 2, 3, 4] # non-zero singular values + >>> u = orthogonal[:, :5] # left singular vectors + >>> vT = orthogonal[:, 5:].T # right singular vectors + >>> A = u @ np.diag(s) @ vT + + With only four singular values/vectors, the SVD approximates the original + matrix. + + >>> u4, s4, vT4 = svds(A, k=4) + >>> A4 = u4 @ np.diag(s4) @ vT4 + >>> np.allclose(A4, A, atol=1e-3) + True + + With all five non-zero singular values/vectors, we can reproduce + the original matrix more accurately. + + >>> u5, s5, vT5 = svds(A, k=5) + >>> A5 = u5 @ np.diag(s5) @ vT5 + >>> np.allclose(A5, A) + True + + The singular values match the expected singular values. + + >>> np.allclose(s5, s) + True + + Since the singular values are not close to each other in this example, + every singular vector matches as expected up to a difference in sign. + + >>> (np.allclose(np.abs(u5), np.abs(u)) and + ... np.allclose(np.abs(vT5), np.abs(vT))) + True + + The singular vectors are also orthogonal. + + >>> (np.allclose(u5.T @ u5, np.eye(5)) and + ... np.allclose(vT5 @ vT5.T, np.eye(5))) + True + + If there are (nearly) multiple singular values, the corresponding + individual singular vectors may be unstable, but the whole invariant + subspace containing all such singular vectors is computed accurately + as can be measured by angles between subspaces via 'subspace_angles'. + + >>> rng = np.random.default_rng(178686584221410808734965903901790843963) + >>> s = [1, 1 + 1e-6] # non-zero singular values + >>> u, _ = np.linalg.qr(rng.standard_normal((99, 2))) + >>> v, _ = np.linalg.qr(rng.standard_normal((99, 2))) + >>> vT = v.T + >>> A = u @ np.diag(s) @ vT + >>> A = A.astype(np.float32) + >>> u2, s2, vT2 = svds(A, k=2, rng=rng) + >>> np.allclose(s2, s) + True + + The angles between the individual exact and computed singular vectors + may not be so small. To check use: + + >>> (linalg.subspace_angles(u2[:, :1], u[:, :1]) + + ... linalg.subspace_angles(u2[:, 1:], u[:, 1:])) + array([0.06562513]) # may vary + >>> (linalg.subspace_angles(vT2[:1, :].T, vT[:1, :].T) + + ... linalg.subspace_angles(vT2[1:, :].T, vT[1:, :].T)) + array([0.06562507]) # may vary + + As opposed to the angles between the 2-dimensional invariant subspaces + that these vectors span, which are small for rights singular vectors + + >>> linalg.subspace_angles(u2, u).sum() < 1e-6 + True + + as well as for left singular vectors. + + >>> linalg.subspace_angles(vT2.T, vT.T).sum() < 1e-6 + True + + The next example follows that of 'sklearn.decomposition.TruncatedSVD'. + + >>> rng = np.random.default_rng(0) + >>> X_dense = rng.random(size=(100, 100)) + >>> X_dense[:, 2 * np.arange(50)] = 0 + >>> X = sparse.csr_array(X_dense) + >>> _, singular_values, _ = svds(X, k=5, rng=rng) + >>> print(singular_values) + [ 4.3221... 4.4043... 4.4907... 4.5858... 35.4549...] + + The function can be called without the transpose of the input matrix + ever explicitly constructed. + + >>> rng = np.random.default_rng(102524723947864966825913730119128190974) + >>> G = sparse.random_array((8, 9), density=0.5, rng=rng) + >>> Glo = aslinearoperator(G) + >>> _, singular_values_svds, _ = svds(Glo, k=5, rng=rng) + >>> _, singular_values_svd, _ = linalg.svd(G.toarray()) + >>> np.allclose(singular_values_svds, singular_values_svd[-4::-1]) + True + + The most memory efficient scenario is where neither + the original matrix, nor its transpose, is explicitly constructed. + Our example computes the smallest singular values and vectors + of 'LinearOperator' constructed from the numpy function 'np.diff' used + column-wise to be consistent with 'LinearOperator' operating on columns. + + >>> diff0 = lambda a: np.diff(a, axis=0) + + Let us create the matrix from 'diff0' to be used for validation only. + + >>> n = 5 # The dimension of the space. + >>> M_from_diff0 = diff0(np.eye(n)) + >>> print(M_from_diff0.astype(int)) + [[-1 1 0 0 0] + [ 0 -1 1 0 0] + [ 0 0 -1 1 0] + [ 0 0 0 -1 1]] + + The matrix 'M_from_diff0' is bi-diagonal and could be alternatively + created directly by + + >>> M = - np.eye(n - 1, n, dtype=int) + >>> np.fill_diagonal(M[:,1:], 1) + >>> np.allclose(M, M_from_diff0) + True + + Its transpose + + >>> print(M.T) + [[-1 0 0 0] + [ 1 -1 0 0] + [ 0 1 -1 0] + [ 0 0 1 -1] + [ 0 0 0 1]] + + can be viewed as the incidence matrix; see + Incidence matrix, (2022, Nov. 19), Wikipedia, https://w.wiki/5YXU, + of a linear graph with 5 vertices and 4 edges. The 5x5 normal matrix + ``M.T @ M`` thus is + + >>> print(M.T @ M) + [[ 1 -1 0 0 0] + [-1 2 -1 0 0] + [ 0 -1 2 -1 0] + [ 0 0 -1 2 -1] + [ 0 0 0 -1 1]] + + the graph Laplacian, while the actually used in 'svds' smaller size + 4x4 normal matrix ``M @ M.T`` + + >>> print(M @ M.T) + [[ 2 -1 0 0] + [-1 2 -1 0] + [ 0 -1 2 -1] + [ 0 0 -1 2]] + + is the so-called edge-based Laplacian; see + Symmetric Laplacian via the incidence matrix, in Laplacian matrix, + (2022, Nov. 19), Wikipedia, https://w.wiki/5YXW. + + The 'LinearOperator' setup needs the options 'rmatvec' and 'rmatmat' + of multiplication by the matrix transpose ``M.T``, but we want to be + matrix-free to save memory, so knowing how ``M.T`` looks like, we + manually construct the following function to be + used in ``rmatmat=diff0t``. + + >>> def diff0t(a): + ... if a.ndim == 1: + ... a = a[:,np.newaxis] # Turn 1D into 2D array + ... d = np.zeros((a.shape[0] + 1, a.shape[1]), dtype=a.dtype) + ... d[0, :] = - a[0, :] + ... d[1:-1, :] = a[0:-1, :] - a[1:, :] + ... d[-1, :] = a[-1, :] + ... return d + + We check that our function 'diff0t' for the matrix transpose is valid. + + >>> np.allclose(M.T, diff0t(np.eye(n-1))) + True + + Now we setup our matrix-free 'LinearOperator' called 'diff0_func_aslo' + and for validation the matrix-based 'diff0_matrix_aslo'. + + >>> def diff0_func_aslo_def(n): + ... return LinearOperator(matvec=diff0, + ... matmat=diff0, + ... rmatvec=diff0t, + ... rmatmat=diff0t, + ... shape=(n - 1, n)) + >>> diff0_func_aslo = diff0_func_aslo_def(n) + >>> diff0_matrix_aslo = aslinearoperator(M_from_diff0) + + And validate both the matrix and its transpose in 'LinearOperator'. + + >>> np.allclose(diff0_func_aslo(np.eye(n)), + ... diff0_matrix_aslo(np.eye(n))) + True + >>> np.allclose(diff0_func_aslo.T(np.eye(n-1)), + ... diff0_matrix_aslo.T(np.eye(n-1))) + True + + Having the 'LinearOperator' setup validated, we run the solver. + + >>> n = 100 + >>> diff0_func_aslo = diff0_func_aslo_def(n) + >>> u, s, vT = svds(diff0_func_aslo, k=3, which='SM') + + The singular values squared and the singular vectors are known + explicitly; see + Pure Dirichlet boundary conditions, in + Eigenvalues and eigenvectors of the second derivative, + (2022, Nov. 19), Wikipedia, https://w.wiki/5YX6, + since 'diff' corresponds to first + derivative, and its smaller size n-1 x n-1 normal matrix + ``M @ M.T`` represent the discrete second derivative with the Dirichlet + boundary conditions. We use these analytic expressions for validation. + + >>> se = 2. * np.sin(np.pi * np.arange(1, 4) / (2. * n)) + >>> ue = np.sqrt(2 / n) * np.sin(np.pi * np.outer(np.arange(1, n), + ... np.arange(1, 4)) / n) + >>> np.allclose(s, se, atol=1e-3) + True + >>> np.allclose(np.abs(u), np.abs(ue), atol=1e-6) + True + + """ + args = _iv(A, k, ncv, tol, which, v0, maxiter, return_singular_vectors, + solver, rng) + (A, k, ncv, tol, which, v0, maxiter, + return_singular_vectors, solver, rng) = args + + largest = (which == 'LM') + n, m = A.shape + + if n >= m: + X_dot = A.matvec + X_matmat = A.matmat + XH_dot = A.rmatvec + XH_mat = A.rmatmat + transpose = False + else: + X_dot = A.rmatvec + X_matmat = A.rmatmat + XH_dot = A.matvec + XH_mat = A.matmat + transpose = True + + dtype = getattr(A, 'dtype', None) + if dtype is None: + dtype = A.dot(np.zeros([m, 1])).dtype + + def matvec_XH_X(x): + return XH_dot(X_dot(x)) + + def matmat_XH_X(x): + return XH_mat(X_matmat(x)) + + XH_X = LinearOperator(matvec=matvec_XH_X, dtype=A.dtype, + matmat=matmat_XH_X, + shape=(min(A.shape), min(A.shape))) + + # Get a low rank approximation of the implicitly defined gramian matrix. + # This is not a stable way to approach the problem. + if solver == 'lobpcg': + + if k == 1 and v0 is not None: + X = np.reshape(v0, (-1, 1)) + else: + X = rng.standard_normal(size=(min(A.shape), k)) + + _, eigvec = lobpcg(XH_X, X, tol=tol ** 2, maxiter=maxiter, + largest=largest) + + elif solver == 'propack': + jobu = return_singular_vectors in {True, 'u'} + jobv = return_singular_vectors in {True, 'vh'} + irl_mode = (which == 'SM') + res = _svdp(A, k=k, tol=tol**2, which=which, maxiter=None, + compute_u=jobu, compute_v=jobv, irl_mode=irl_mode, + kmax=maxiter, v0=v0, rng=rng) + + u, s, vh, _ = res # but we'll ignore bnd, the last output + + # PROPACK order appears to be largest first. `svds` output order is not + # guaranteed, according to documentation, but for ARPACK and LOBPCG + # they actually are ordered smallest to largest, so reverse for + # consistency. + s = s[::-1] + u = u[:, ::-1] + vh = vh[::-1] + + u = u if jobu else None + vh = vh if jobv else None + + if return_singular_vectors: + return u, s, vh + else: + return s + + elif solver == 'arpack' or solver is None: + if v0 is None: + v0 = rng.standard_normal(size=(min(A.shape),)) + _, eigvec = eigsh(XH_X, k=k, tol=tol ** 2, maxiter=maxiter, + ncv=ncv, which=which, v0=v0) + # arpack do not guarantee exactly orthonormal eigenvectors + # for clustered eigenvalues, especially in complex arithmetic + eigvec, _ = np.linalg.qr(eigvec) + + # the eigenvectors eigvec must be orthonomal here; see gh-16712 + Av = X_matmat(eigvec) + if not return_singular_vectors: + s = svd(Av, compute_uv=False, overwrite_a=True) + return s[::-1] + + # compute the left singular vectors of X and update the right ones + # accordingly + u, s, vh = svd(Av, full_matrices=False, overwrite_a=True) + u = u[:, ::-1] + s = s[::-1] + vh = vh[::-1] + + jobu = return_singular_vectors in {True, 'u'} + jobv = return_singular_vectors in {True, 'vh'} + + if transpose: + u_tmp = eigvec @ _herm(vh) if jobu else None + vh = _herm(u) if jobv else None + u = u_tmp + else: + if not jobu: + u = None + vh = vh @ _herm(eigvec) if jobv else None + + return u, s, vh diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/_svds_doc.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/_svds_doc.py new file mode 100644 index 0000000000000000000000000000000000000000..90b85876d2a69dd3c2efa56445e46c93bf0eaa9e --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/_svds_doc.py @@ -0,0 +1,382 @@ +def _svds_arpack_doc(A, k=6, ncv=None, tol=0, which='LM', v0=None, + maxiter=None, return_singular_vectors=True, + solver='arpack', rng=None): + """ + Partial singular value decomposition of a sparse matrix using ARPACK. + + Compute the largest or smallest `k` singular values and corresponding + singular vectors of a sparse matrix `A`. The order in which the singular + values are returned is not guaranteed. + + In the descriptions below, let ``M, N = A.shape``. + + Parameters + ---------- + A : sparse matrix or LinearOperator + Matrix to decompose. + k : int, optional + Number of singular values and singular vectors to compute. + Must satisfy ``1 <= k <= min(M, N) - 1``. + Default is 6. + ncv : int, optional + The number of Lanczos vectors generated. + The default is ``min(n, max(2*k + 1, 20))``. + If specified, must satisfy ``k + 1 < ncv < min(M, N)``; ``ncv > 2*k`` + is recommended. + tol : float, optional + Tolerance for singular values. Zero (default) means machine precision. + which : {'LM', 'SM'} + Which `k` singular values to find: either the largest magnitude ('LM') + or smallest magnitude ('SM') singular values. + v0 : ndarray, optional + The starting vector for iteration: + an (approximate) left singular vector if ``N > M`` and a right singular + vector otherwise. Must be of length ``min(M, N)``. + Default: random + maxiter : int, optional + Maximum number of Arnoldi update iterations allowed; + default is ``min(M, N) * 10``. + return_singular_vectors : {True, False, "u", "vh"} + Singular values are always computed and returned; this parameter + controls the computation and return of singular vectors. + + - ``True``: return singular vectors. + - ``False``: do not return singular vectors. + - ``"u"``: if ``M <= N``, compute only the left singular vectors and + return ``None`` for the right singular vectors. Otherwise, compute + all singular vectors. + - ``"vh"``: if ``M > N``, compute only the right singular vectors and + return ``None`` for the left singular vectors. Otherwise, compute + all singular vectors. + + solver : {'arpack', 'propack', 'lobpcg'}, optional + This is the solver-specific documentation for ``solver='arpack'``. + :ref:`'lobpcg' ` and + :ref:`'propack' ` + are also supported. + rng : `numpy.random.Generator`, optional + Pseudorandom number generator state. When `rng` is None, a new + `numpy.random.Generator` is created using entropy from the + operating system. Types other than `numpy.random.Generator` are + passed to `numpy.random.default_rng` to instantiate a ``Generator``. + options : dict, optional + A dictionary of solver-specific options. No solver-specific options + are currently supported; this parameter is reserved for future use. + + Returns + ------- + u : ndarray, shape=(M, k) + Unitary matrix having left singular vectors as columns. + s : ndarray, shape=(k,) + The singular values. + vh : ndarray, shape=(k, N) + Unitary matrix having right singular vectors as rows. + + Notes + ----- + This is a naive implementation using ARPACK as an eigensolver + on ``A.conj().T @ A`` or ``A @ A.conj().T``, depending on which one is more + efficient. + + Examples + -------- + Construct a matrix ``A`` from singular values and vectors. + + >>> import numpy as np + >>> from scipy.stats import ortho_group + >>> from scipy.sparse import csc_array, diags_array + >>> from scipy.sparse.linalg import svds + >>> rng = np.random.default_rng() + >>> orthogonal = csc_array(ortho_group.rvs(10, random_state=rng)) + >>> s = [0.0001, 0.001, 3, 4, 5] # singular values + >>> u = orthogonal[:, :5] # left singular vectors + >>> vT = orthogonal[:, 5:].T # right singular vectors + >>> A = u @ diags_array(s) @ vT + + With only three singular values/vectors, the SVD approximates the original + matrix. + + >>> u2, s2, vT2 = svds(A, k=3, solver='arpack') + >>> A2 = u2 @ np.diag(s2) @ vT2 + >>> np.allclose(A2, A.toarray(), atol=1e-3) + True + + With all five singular values/vectors, we can reproduce the original + matrix. + + >>> u3, s3, vT3 = svds(A, k=5, solver='arpack') + >>> A3 = u3 @ np.diag(s3) @ vT3 + >>> np.allclose(A3, A.toarray()) + True + + The singular values match the expected singular values, and the singular + vectors are as expected up to a difference in sign. + + >>> (np.allclose(s3, s) and + ... np.allclose(np.abs(u3), np.abs(u.toarray())) and + ... np.allclose(np.abs(vT3), np.abs(vT.toarray()))) + True + + The singular vectors are also orthogonal. + + >>> (np.allclose(u3.T @ u3, np.eye(5)) and + ... np.allclose(vT3 @ vT3.T, np.eye(5))) + True + """ + pass + + +def _svds_lobpcg_doc(A, k=6, ncv=None, tol=0, which='LM', v0=None, + maxiter=None, return_singular_vectors=True, + solver='lobpcg', rng=None): + """ + Partial singular value decomposition of a sparse matrix using LOBPCG. + + Compute the largest or smallest `k` singular values and corresponding + singular vectors of a sparse matrix `A`. The order in which the singular + values are returned is not guaranteed. + + In the descriptions below, let ``M, N = A.shape``. + + Parameters + ---------- + A : sparse matrix or LinearOperator + Matrix to decompose. + k : int, default: 6 + Number of singular values and singular vectors to compute. + Must satisfy ``1 <= k <= min(M, N) - 1``. + ncv : int, optional + Ignored. + tol : float, optional + Tolerance for singular values. Zero (default) means machine precision. + which : {'LM', 'SM'} + Which `k` singular values to find: either the largest magnitude ('LM') + or smallest magnitude ('SM') singular values. + v0 : ndarray, optional + If `k` is 1, the starting vector for iteration: + an (approximate) left singular vector if ``N > M`` and a right singular + vector otherwise. Must be of length ``min(M, N)``. + Ignored otherwise. + Default: random + maxiter : int, default: 20 + Maximum number of iterations. + return_singular_vectors : {True, False, "u", "vh"} + Singular values are always computed and returned; this parameter + controls the computation and return of singular vectors. + + - ``True``: return singular vectors. + - ``False``: do not return singular vectors. + - ``"u"``: if ``M <= N``, compute only the left singular vectors and + return ``None`` for the right singular vectors. Otherwise, compute + all singular vectors. + - ``"vh"``: if ``M > N``, compute only the right singular vectors and + return ``None`` for the left singular vectors. Otherwise, compute + all singular vectors. + + solver : {'arpack', 'propack', 'lobpcg'}, optional + This is the solver-specific documentation for ``solver='lobpcg'``. + :ref:`'arpack' ` and + :ref:`'propack' ` + are also supported. + rng : `numpy.random.Generator`, optional + Pseudorandom number generator state. When `rng` is None, a new + `numpy.random.Generator` is created using entropy from the + operating system. Types other than `numpy.random.Generator` are + passed to `numpy.random.default_rng` to instantiate a ``Generator``. + options : dict, optional + A dictionary of solver-specific options. No solver-specific options + are currently supported; this parameter is reserved for future use. + + Returns + ------- + u : ndarray, shape=(M, k) + Unitary matrix having left singular vectors as columns. + s : ndarray, shape=(k,) + The singular values. + vh : ndarray, shape=(k, N) + Unitary matrix having right singular vectors as rows. + + Notes + ----- + This is a naive implementation using LOBPCG as an eigensolver + on ``A.conj().T @ A`` or ``A @ A.conj().T``, depending on which one is more + efficient. + + Examples + -------- + Construct a matrix ``A`` from singular values and vectors. + + >>> import numpy as np + >>> from scipy.stats import ortho_group + >>> from scipy.sparse import csc_array, diags_array + >>> from scipy.sparse.linalg import svds + >>> rng = np.random.default_rng() + >>> orthogonal = csc_array(ortho_group.rvs(10, random_state=rng)) + >>> s = [0.0001, 0.001, 3, 4, 5] # singular values + >>> u = orthogonal[:, :5] # left singular vectors + >>> vT = orthogonal[:, 5:].T # right singular vectors + >>> A = u @ diags_array(s) @ vT + + With only three singular values/vectors, the SVD approximates the original + matrix. + + >>> u2, s2, vT2 = svds(A, k=3, solver='lobpcg') + >>> A2 = u2 @ np.diag(s2) @ vT2 + >>> np.allclose(A2, A.toarray(), atol=1e-3) + True + + With all five singular values/vectors, we can reproduce the original + matrix. + + >>> u3, s3, vT3 = svds(A, k=5, solver='lobpcg') + >>> A3 = u3 @ np.diag(s3) @ vT3 + >>> np.allclose(A3, A.toarray()) + True + + The singular values match the expected singular values, and the singular + vectors are as expected up to a difference in sign. + + >>> (np.allclose(s3, s) and + ... np.allclose(np.abs(u3), np.abs(u.todense())) and + ... np.allclose(np.abs(vT3), np.abs(vT.todense()))) + True + + The singular vectors are also orthogonal. + + >>> (np.allclose(u3.T @ u3, np.eye(5)) and + ... np.allclose(vT3 @ vT3.T, np.eye(5))) + True + + """ + pass + + +def _svds_propack_doc(A, k=6, ncv=None, tol=0, which='LM', v0=None, + maxiter=None, return_singular_vectors=True, + solver='propack', rng=None): + """ + Partial singular value decomposition of a sparse matrix using PROPACK. + + Compute the largest or smallest `k` singular values and corresponding + singular vectors of a sparse matrix `A`. The order in which the singular + values are returned is not guaranteed. + + In the descriptions below, let ``M, N = A.shape``. + + Parameters + ---------- + A : sparse matrix or LinearOperator + Matrix to decompose. If `A` is a ``LinearOperator`` + object, it must define both ``matvec`` and ``rmatvec`` methods. + k : int, default: 6 + Number of singular values and singular vectors to compute. + Must satisfy ``1 <= k <= min(M, N)``. + ncv : int, optional + Ignored. + tol : float, optional + The desired relative accuracy for computed singular values. + Zero (default) means machine precision. + which : {'LM', 'SM'} + Which `k` singular values to find: either the largest magnitude ('LM') + or smallest magnitude ('SM') singular values. Note that choosing + ``which='SM'`` will force the ``irl`` option to be set ``True``. + v0 : ndarray, optional + Starting vector for iterations: must be of length ``A.shape[0]``. + If not specified, PROPACK will generate a starting vector. + maxiter : int, optional + Maximum number of iterations / maximal dimension of the Krylov + subspace. Default is ``10 * k``. + return_singular_vectors : {True, False, "u", "vh"} + Singular values are always computed and returned; this parameter + controls the computation and return of singular vectors. + + - ``True``: return singular vectors. + - ``False``: do not return singular vectors. + - ``"u"``: compute only the left singular vectors; return ``None`` for + the right singular vectors. + - ``"vh"``: compute only the right singular vectors; return ``None`` + for the left singular vectors. + + solver : {'arpack', 'propack', 'lobpcg'}, optional + This is the solver-specific documentation for ``solver='propack'``. + :ref:`'arpack' ` and + :ref:`'lobpcg' ` + are also supported. + rng : `numpy.random.Generator`, optional + Pseudorandom number generator state. When `rng` is None, a new + `numpy.random.Generator` is created using entropy from the + operating system. Types other than `numpy.random.Generator` are + passed to `numpy.random.default_rng` to instantiate a ``Generator``. + options : dict, optional + A dictionary of solver-specific options. No solver-specific options + are currently supported; this parameter is reserved for future use. + + Returns + ------- + u : ndarray, shape=(M, k) + Unitary matrix having left singular vectors as columns. + s : ndarray, shape=(k,) + The singular values. + vh : ndarray, shape=(k, N) + Unitary matrix having right singular vectors as rows. + + Notes + ----- + This is an interface to the Fortran library PROPACK [1]_. + The current default is to run with IRL mode disabled unless seeking the + smallest singular values/vectors (``which='SM'``). + + References + ---------- + + .. [1] Larsen, Rasmus Munk. "PROPACK-Software for large and sparse SVD + calculations." Available online. URL + http://sun.stanford.edu/~rmunk/PROPACK (2004): 2008-2009. + + Examples + -------- + Construct a matrix ``A`` from singular values and vectors. + + >>> import numpy as np + >>> from scipy.stats import ortho_group + >>> from scipy.sparse import csc_array, diags_array + >>> from scipy.sparse.linalg import svds + >>> rng = np.random.default_rng() + >>> orthogonal = csc_array(ortho_group.rvs(10, random_state=rng)) + >>> s = [0.0001, 0.001, 3, 4, 5] # singular values + >>> u = orthogonal[:, :5] # left singular vectors + >>> vT = orthogonal[:, 5:].T # right singular vectors + >>> A = u @ diags_array(s) @ vT + + With only three singular values/vectors, the SVD approximates the original + matrix. + + >>> u2, s2, vT2 = svds(A, k=3, solver='propack') + >>> A2 = u2 @ np.diag(s2) @ vT2 + >>> np.allclose(A2, A.todense(), atol=1e-3) + True + + With all five singular values/vectors, we can reproduce the original + matrix. + + >>> u3, s3, vT3 = svds(A, k=5, solver='propack') + >>> A3 = u3 @ np.diag(s3) @ vT3 + >>> np.allclose(A3, A.todense()) + True + + The singular values match the expected singular values, and the singular + vectors are as expected up to a difference in sign. + + >>> (np.allclose(s3, s) and + ... np.allclose(np.abs(u3), np.abs(u.toarray())) and + ... np.allclose(np.abs(vT3), np.abs(vT.toarray()))) + True + + The singular vectors are also orthogonal. + + >>> (np.allclose(u3.T @ u3, np.eye(5)) and + ... np.allclose(vT3 @ vT3.T, np.eye(5))) + True + + """ + pass diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..679b94480d7ff5a11e037ffb758f2214c6e5097f --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/__init__.py @@ -0,0 +1,20 @@ +""" +Eigenvalue solver using iterative methods. + +Find k eigenvectors and eigenvalues of a matrix A using the +Arnoldi/Lanczos iterative methods from ARPACK [1]_,[2]_. + +These methods are most useful for large sparse matrices. + + - eigs(A,k) + - eigsh(A,k) + +References +---------- +.. [1] ARPACK Software, http://www.caam.rice.edu/software/ARPACK/ +.. [2] R. B. Lehoucq, D. C. Sorensen, and C. Yang, ARPACK USERS GUIDE: + Solution of Large Scale Eigenvalue Problems by Implicitly Restarted + Arnoldi Methods. SIAM, Philadelphia, PA, 1998. + +""" +from .arpack import * diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08d1b5d941b0afb0e99859cd5af660e43b0ab554 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/__pycache__/arpack.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/__pycache__/arpack.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..28111d875a5725f1db8002fa64f16df79d9c4bfb Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/__pycache__/arpack.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/arpack.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/arpack.py new file mode 100644 index 0000000000000000000000000000000000000000..0f5f802c3f6ba3d22bdb7de5a23c824cd86c6d0a --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/arpack.py @@ -0,0 +1,1781 @@ +""" +Find a few eigenvectors and eigenvalues of a matrix. + + +Uses ARPACK: https://github.com/opencollab/arpack-ng + +""" +# Wrapper implementation notes +# +# ARPACK Entry Points +# ------------------- +# The entry points to ARPACK are +# - (s,d)seupd : single and double precision symmetric matrix +# - (s,d,c,z)neupd: single,double,complex,double complex general matrix +# This wrapper puts the *neupd (general matrix) interfaces in eigs() +# and the *seupd (symmetric matrix) in eigsh(). +# There is no specialized interface for complex Hermitian matrices. +# To find eigenvalues of a complex Hermitian matrix you +# may use eigsh(), but eigsh() will simply call eigs() +# and return the real part of the eigenvalues thus obtained. + +# Number of eigenvalues returned and complex eigenvalues +# ------------------------------------------------------ +# The ARPACK nonsymmetric real and double interface (s,d)naupd return +# eigenvalues and eigenvectors in real (float,double) arrays. +# Since the eigenvalues and eigenvectors are, in general, complex +# ARPACK puts the real and imaginary parts in consecutive entries +# in real-valued arrays. This wrapper puts the real entries +# into complex data types and attempts to return the requested eigenvalues +# and eigenvectors. + + +# Solver modes +# ------------ +# ARPACK and handle shifted and shift-inverse computations +# for eigenvalues by providing a shift (sigma) and a solver. + +import numpy as np +import warnings +from scipy.sparse.linalg._interface import aslinearoperator, LinearOperator +from scipy.sparse import eye, issparse +from scipy.linalg import eig, eigh, lu_factor, lu_solve +from scipy.sparse._sputils import ( + convert_pydata_sparse_to_scipy, isdense, is_pydata_spmatrix, +) +from scipy.sparse.linalg import gmres, splu + +from . import _arpacklib + +__docformat__ = "restructuredtext en" + +__all__ = ['eigs', 'eigsh', 'ArpackError', 'ArpackNoConvergence'] + + +_type_conv = {'f': 's', 'd': 'd', 'F': 'c', 'D': 'z'} +_ndigits = {'f': 5, 'd': 12, 'F': 5, 'D': 12} + +DNAUPD_ERRORS = { + 0: "Normal exit.", + 1: "Maximum number of iterations taken. " + "All possible eigenvalues of OP has been found. IPARAM(5) " + "returns the number of wanted converged Ritz values.", + 2: "No longer an informational error. Deprecated starting " + "with release 2 of ARPACK.", + 3: "No shifts could be applied during a cycle of the " + "Implicitly restarted Arnoldi iteration. One possibility " + "is to increase the size of NCV relative to NEV. ", + -1: "N must be positive.", + -2: "NEV must be positive.", + -3: "NCV-NEV >= 2 and less than or equal to N.", + -4: "The maximum number of Arnoldi update iterations allowed " + "must be greater than zero.", + -5: " WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI'", + -6: "BMAT must be one of 'I' or 'G'.", + -7: "Length of private work array WORKL is not sufficient.", + -8: "Error return from LAPACK eigenvalue calculation;", + -9: "Starting vector is zero.", + -10: "IPARAM(7) must be 1,2,3,4.", + -11: "IPARAM(7) = 1 and BMAT = 'G' are incompatible.", + -12: "IPARAM(1) must be equal to 0 or 1.", + -13: "NEV and WHICH = 'BE' are incompatible.", + -9999: "Could not build an Arnoldi factorization. " + "IPARAM(5) returns the size of the current Arnoldi " + "factorization. The user is advised to check that " + "enough workspace and array storage has been allocated." +} + +SNAUPD_ERRORS = DNAUPD_ERRORS + +ZNAUPD_ERRORS = DNAUPD_ERRORS.copy() +ZNAUPD_ERRORS[-10] = "IPARAM(7) must be 1,2,3." + +CNAUPD_ERRORS = ZNAUPD_ERRORS + +DSAUPD_ERRORS = { + 0: "Normal exit.", + 1: "Maximum number of iterations taken. " + "All possible eigenvalues of OP has been found.", + 2: "No longer an informational error. Deprecated starting with " + "release 2 of ARPACK.", + 3: "No shifts could be applied during a cycle of the Implicitly " + "restarted Arnoldi iteration. One possibility is to increase " + "the size of NCV relative to NEV. ", + -1: "N must be positive.", + -2: "NEV must be positive.", + -3: "NCV must be greater than NEV and less than or equal to N.", + -4: "The maximum number of Arnoldi update iterations allowed " + "must be greater than zero.", + -5: "WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'.", + -6: "BMAT must be one of 'I' or 'G'.", + -7: "Length of private work array WORKL is not sufficient.", + -8: "Error return from trid. eigenvalue calculation; " + "Informational error from LAPACK routine dsteqr .", + -9: "Starting vector is zero.", + -10: "IPARAM(7) must be 1,2,3,4,5.", + -11: "IPARAM(7) = 1 and BMAT = 'G' are incompatible.", + -12: "IPARAM(1) must be equal to 0 or 1.", + -13: "NEV and WHICH = 'BE' are incompatible. ", + -9999: "Could not build an Arnoldi factorization. " + "IPARAM(5) returns the size of the current Arnoldi " + "factorization. The user is advised to check that " + "enough workspace and array storage has been allocated.", +} + +SSAUPD_ERRORS = DSAUPD_ERRORS + +DNEUPD_ERRORS = { + 0: "Normal exit.", + 1: "The Schur form computed by LAPACK routine dlahqr " + "could not be reordered by LAPACK routine dtrsen. " + "Re-enter subroutine dneupd with IPARAM(5)NCV and " + "increase the size of the arrays DR and DI to have " + "dimension at least dimension NCV and allocate at least NCV " + "columns for Z. NOTE: Not necessary if Z and V share " + "the same space. Please notify the authors if this error" + "occurs.", + -1: "N must be positive.", + -2: "NEV must be positive.", + -3: "NCV-NEV >= 2 and less than or equal to N.", + -5: "WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI'", + -6: "BMAT must be one of 'I' or 'G'.", + -7: "Length of private work WORKL array is not sufficient.", + -8: "Error return from calculation of a real Schur form. " + "Informational error from LAPACK routine dlahqr .", + -9: "Error return from calculation of eigenvectors. " + "Informational error from LAPACK routine dtrevc.", + -10: "IPARAM(7) must be 1,2,3,4.", + -11: "IPARAM(7) = 1 and BMAT = 'G' are incompatible.", + -12: "HOWMNY = 'S' not yet implemented", + -13: "HOWMNY must be one of 'A' or 'P' if RVEC = .true.", + -14: "DNAUPD did not find any eigenvalues to sufficient " + "accuracy.", + -15: "DNEUPD got a different count of the number of converged " + "Ritz values than DNAUPD got. This indicates the user " + "probably made an error in passing data from DNAUPD to " + "DNEUPD or that the data was modified before entering " + "DNEUPD", +} + +SNEUPD_ERRORS = DNEUPD_ERRORS.copy() +SNEUPD_ERRORS[1] = ("The Schur form computed by LAPACK routine slahqr " + "could not be reordered by LAPACK routine strsen . " + "Re-enter subroutine dneupd with IPARAM(5)=NCV and " + "increase the size of the arrays DR and DI to have " + "dimension at least dimension NCV and allocate at least " + "NCV columns for Z. NOTE: Not necessary if Z and V share " + "the same space. Please notify the authors if this error " + "occurs.") +SNEUPD_ERRORS[-14] = ("SNAUPD did not find any eigenvalues to sufficient " + "accuracy.") +SNEUPD_ERRORS[-15] = ("SNEUPD got a different count of the number of " + "converged Ritz values than SNAUPD got. This indicates " + "the user probably made an error in passing data from " + "SNAUPD to SNEUPD or that the data was modified before " + "entering SNEUPD") + +ZNEUPD_ERRORS = {0: "Normal exit.", + 1: "The Schur form computed by LAPACK routine csheqr " + "could not be reordered by LAPACK routine ztrsen. " + "Re-enter subroutine zneupd with IPARAM(5)=NCV and " + "increase the size of the array D to have " + "dimension at least dimension NCV and allocate at least " + "NCV columns for Z. NOTE: Not necessary if Z and V share " + "the same space. Please notify the authors if this error " + "occurs.", + -1: "N must be positive.", + -2: "NEV must be positive.", + -3: "NCV-NEV >= 1 and less than or equal to N.", + -5: "WHICH must be one of 'LM', 'SM', 'LR', 'SR', 'LI', 'SI'", + -6: "BMAT must be one of 'I' or 'G'.", + -7: "Length of private work WORKL array is not sufficient.", + -8: "Error return from LAPACK eigenvalue calculation. " + "This should never happened.", + -9: "Error return from calculation of eigenvectors. " + "Informational error from LAPACK routine ztrevc.", + -10: "IPARAM(7) must be 1,2,3", + -11: "IPARAM(7) = 1 and BMAT = 'G' are incompatible.", + -12: "HOWMNY = 'S' not yet implemented", + -13: "HOWMNY must be one of 'A' or 'P' if RVEC = .true.", + -14: "ZNAUPD did not find any eigenvalues to sufficient " + "accuracy.", + -15: "ZNEUPD got a different count of the number of " + "converged Ritz values than ZNAUPD got. This " + "indicates the user probably made an error in passing " + "data from ZNAUPD to ZNEUPD or that the data was " + "modified before entering ZNEUPD" + } + +CNEUPD_ERRORS = ZNEUPD_ERRORS.copy() +CNEUPD_ERRORS[-14] = ("CNAUPD did not find any eigenvalues to sufficient " + "accuracy.") +CNEUPD_ERRORS[-15] = ("CNEUPD got a different count of the number of " + "converged Ritz values than CNAUPD got. This indicates " + "the user probably made an error in passing data from " + "CNAUPD to CNEUPD or that the data was modified before " + "entering CNEUPD") + +DSEUPD_ERRORS = { + 0: "Normal exit.", + -1: "N must be positive.", + -2: "NEV must be positive.", + -3: "NCV must be greater than NEV and less than or equal to N.", + -5: "WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'.", + -6: "BMAT must be one of 'I' or 'G'.", + -7: "Length of private work WORKL array is not sufficient.", + -8: ("Error return from trid. eigenvalue calculation; " + "Information error from LAPACK routine dsteqr."), + -9: "Starting vector is zero.", + -10: "IPARAM(7) must be 1,2,3,4,5.", + -11: "IPARAM(7) = 1 and BMAT = 'G' are incompatible.", + -12: "NEV and WHICH = 'BE' are incompatible.", + -14: "DSAUPD did not find any eigenvalues to sufficient accuracy.", + -15: "HOWMNY must be one of 'A' or 'S' if RVEC = .true.", + -16: "HOWMNY = 'S' not yet implemented", + -17: ("DSEUPD got a different count of the number of converged " + "Ritz values than DSAUPD got. This indicates the user " + "probably made an error in passing data from DSAUPD to " + "DSEUPD or that the data was modified before entering " + "DSEUPD.") +} + +SSEUPD_ERRORS = DSEUPD_ERRORS.copy() +SSEUPD_ERRORS[-14] = ("SSAUPD did not find any eigenvalues " + "to sufficient accuracy.") +SSEUPD_ERRORS[-17] = ("SSEUPD got a different count of the number of " + "converged " + "Ritz values than SSAUPD got. This indicates the user " + "probably made an error in passing data from SSAUPD to " + "SSEUPD or that the data was modified before entering " + "SSEUPD.") + +_SAUPD_ERRORS = {'d': DSAUPD_ERRORS, + 's': SSAUPD_ERRORS} +_NAUPD_ERRORS = {'d': DNAUPD_ERRORS, + 's': SNAUPD_ERRORS, + 'z': ZNAUPD_ERRORS, + 'c': CNAUPD_ERRORS} +_SEUPD_ERRORS = {'d': DSEUPD_ERRORS, + 's': SSEUPD_ERRORS} +_NEUPD_ERRORS = {'d': DNEUPD_ERRORS, + 's': SNEUPD_ERRORS, + 'z': ZNEUPD_ERRORS, + 'c': CNEUPD_ERRORS} + +# accepted values of parameter WHICH in _SEUPD +_SEUPD_WHICH = ['LM', 'SM', 'LA', 'SA', 'BE'] + +# accepted values of parameter WHICH in _NAUPD +_NEUPD_WHICH = ['LM', 'SM', 'LR', 'SR', 'LI', 'SI'] + +# The enum values for the parameter WHICH in _NAUPD and _SEUPD +WHICH_DICT = { + 'LM': 0, 'SM': 1, 'LR': 2, 'SR': 3, 'LI': 4, 'SI': 5, 'LA': 6, 'SA': 7, 'BE': 8 +} + +# The enum values for the parameter HOWMNY in _NEUPD and _SEUPD +HOWMNY_DICT = {'A': 0, 'P': 1, 'S': 2} + +class ArpackError(RuntimeError): + """ + ARPACK error + """ + + def __init__(self, info, infodict=None): + if infodict is None: + infodict = _NAUPD_ERRORS + + msg = infodict.get(info, "Unknown error") + super().__init__(f"ARPACK error {info}: {msg}") + + + +class ArpackNoConvergence(ArpackError): + """ + ARPACK iteration did not converge + + Attributes + ---------- + eigenvalues : ndarray + Partial result. Converged eigenvalues. + eigenvectors : ndarray + Partial result. Converged eigenvectors. + + """ + + def __init__(self, msg, eigenvalues, eigenvectors): + ArpackError.__init__(self, -1, {-1: msg}) + self.eigenvalues = eigenvalues + self.eigenvectors = eigenvectors + + +def choose_ncv(k): + """ + Choose number of lanczos vectors based on target number + of singular/eigen values and vectors to compute, k. + """ + return max(2 * k + 1, 20) + + +class _ArpackParams: + def __init__(self, n, k, tp, rng, mode=1, sigma=None, ncv=None, v0=None, + maxiter=None, which="LM", tol=0): + if k <= 0: + raise ValueError(f"k must be positive, k={k}") + + if maxiter is None: + maxiter = n * 10 + if maxiter <= 0: + raise ValueError(f"maxiter must be positive, maxiter={maxiter}") + + if tp not in 'fdFD': + # Use `float64` libraries from integer dtypes. + if np.can_cast(tp, 'd'): + tp = 'd' + else: + raise ValueError("matrix type must be 'f', 'd', 'F', or 'D'") + + if v0 is not None: + # ARPACK overwrites its initial resid, make a copy + self.resid = np.array(v0, copy=True, dtype=tp) + info = 1 + else: + # ARPACK will use a random initial vector. + self.resid = rng.uniform(low=-1.0, high=1.0, size=[n]).astype(tp) + info = 0 + + if sigma is None: + #sigma not used + self.sigma = 0 + else: + self.sigma = sigma + + if ncv is None: + ncv = choose_ncv(k) + self.ncv = min(ncv, n) + self.n = n + self.v = np.zeros((n, ncv), tp) # holds Ritz vectors + self.which = which + + # set solver mode and parameters + self.mode = mode + self.arpack_dict = { + 'tol': tol, + 'getv0_rnorm0': 0.0, + 'aitr_betaj': 0.0, + 'aitr_rnorm1': 0.0, + 'aitr_wnorm': 0.0, + 'aup2_rnorm': 0.0, + 'ido': 0, + 'which': WHICH_DICT[which], + 'bmat': 0, + 'info': info, + 'iter': 0, + 'maxiter': int(maxiter), + 'mode': mode, + 'n': n, + 'nconv': 0, + 'ncv': self.ncv, + 'nev': k, + 'np': 0, + 'shift': 1, + 'getv0_first': 0, + 'getv0_iter': 0, + 'getv0_itry': 0, + 'getv0_orth': 0, + 'aitr_iter': 0, + 'aitr_j': 0, + 'aitr_orth1': 0, + 'aitr_orth2': 0, + 'aitr_restart': 0, + 'aitr_step3': 0, + 'aitr_step4': 0, + 'aitr_ierr': 0, + 'aup2_initv': 0, + 'aup2_iter': 0, + 'aup2_getv0': 0, + 'aup2_cnorm': 0, + 'aup2_kplusp': 0, + 'aup2_nev': 0, + 'aup2_nev0': 0, + 'aup2_np0': 0, + 'aup2_numcnv': 0, + 'aup2_update': 0, + 'aup2_ushift': 0, + } + + self.k = k + self.tp = tp + self.converged = False + + def _raise_no_convergence(self): + msg = "No convergence (%d iterations, %d/%d eigenvectors converged)" + k_ok = self.arpack_dict['nconv'] + num_iter = self.arpack_dict['iter'] + try: + ev, vec = self.extract(True) + except ArpackError as err: + msg = f"{msg} [{err}]" + ev = np.zeros((0,)) + vec = np.zeros((self.n, 0)) + k_ok = 0 + raise ArpackNoConvergence(f"No convergence ({num_iter} iterations, " + f"{k_ok}/{self.k} eigenvectors converged)", + ev, vec) + + +class _SymmetricArpackParams(_ArpackParams): + def __init__(self, n, k, tp, matvec, mode=1, M_matvec=None, Minv_matvec=None, + sigma=None, ncv=None, v0=None, maxiter=None, which="LM", tol=0, + rng=None): + # The following modes are supported: + # mode = 1: + # Solve the standard eigenvalue problem: + # A*x = lambda*x : + # A - symmetric + # Arguments should be + # matvec = left multiplication by A + # M_matvec = None [not used] + # Minv_matvec = None [not used] + # + # mode = 2: + # Solve the general eigenvalue problem: + # A*x = lambda*M*x + # A - symmetric + # M - symmetric positive definite + # Arguments should be + # matvec = left multiplication by A + # M_matvec = left multiplication by M + # Minv_matvec = left multiplication by M^-1 + # + # mode = 3: + # Solve the general eigenvalue problem in shift-invert mode: + # A*x = lambda*M*x + # A - symmetric + # M - symmetric positive semi-definite + # Arguments should be + # matvec = None [not used] + # M_matvec = left multiplication by M + # or None, if M is the identity + # Minv_matvec = left multiplication by [A-sigma*M]^-1 + # + # mode = 4: + # Solve the general eigenvalue problem in Buckling mode: + # A*x = lambda*AG*x + # A - symmetric positive semi-definite + # AG - symmetric indefinite + # Arguments should be + # matvec = left multiplication by A + # M_matvec = None [not used] + # Minv_matvec = left multiplication by [A-sigma*AG]^-1 + # + # mode = 5: + # Solve the general eigenvalue problem in Cayley-transformed mode: + # A*x = lambda*M*x + # A - symmetric + # M - symmetric positive semi-definite + # Arguments should be + # matvec = left multiplication by A + # M_matvec = left multiplication by M + # or None, if M is the identity + # Minv_matvec = left multiplication by [A-sigma*M]^-1 + if mode == 1: + if matvec is None: + raise ValueError("matvec must be specified for mode=1") + if M_matvec is not None: + raise ValueError("M_matvec cannot be specified for mode=1") + if Minv_matvec is not None: + raise ValueError("Minv_matvec cannot be specified for mode=1") + + self.OP = matvec + self.B = lambda x: x + self.bmat = 'I' + elif mode == 2: + if matvec is None: + raise ValueError("matvec must be specified for mode=2") + if M_matvec is None: + raise ValueError("M_matvec must be specified for mode=2") + if Minv_matvec is None: + raise ValueError("Minv_matvec must be specified for mode=2") + + self.OP = lambda x: Minv_matvec(matvec(x)) + self.OPa = Minv_matvec + self.OPb = matvec + self.B = M_matvec + self.bmat = 'G' + elif mode == 3: + if matvec is not None: + raise ValueError("matvec must not be specified for mode=3") + if Minv_matvec is None: + raise ValueError("Minv_matvec must be specified for mode=3") + + if M_matvec is None: + self.OP = Minv_matvec + self.OPa = Minv_matvec + self.B = lambda x: x + self.bmat = 'I' + else: + self.OP = lambda x: Minv_matvec(M_matvec(x)) + self.OPa = Minv_matvec + self.B = M_matvec + self.bmat = 'G' + elif mode == 4: + if matvec is None: + raise ValueError("matvec must be specified for mode=4") + if M_matvec is not None: + raise ValueError("M_matvec must not be specified for mode=4") + if Minv_matvec is None: + raise ValueError("Minv_matvec must be specified for mode=4") + self.OPa = Minv_matvec + self.OP = lambda x: self.OPa(matvec(x)) + self.B = matvec + self.bmat = 'G' + elif mode == 5: + if matvec is None: + raise ValueError("matvec must be specified for mode=5") + if Minv_matvec is None: + raise ValueError("Minv_matvec must be specified for mode=5") + + self.OPa = Minv_matvec + self.A_matvec = matvec + + if M_matvec is None: + self.OP = lambda x: Minv_matvec(matvec(x) + sigma * x) + self.B = lambda x: x + self.bmat = 'I' + else: + self.OP = lambda x: Minv_matvec(matvec(x) + + sigma * M_matvec(x)) + self.B = M_matvec + self.bmat = 'G' + else: + raise ValueError(f"mode={mode} not implemented") + + if which not in _SEUPD_WHICH: + raise ValueError(f"which must be one of {' '.join(_SEUPD_WHICH)}") + if k >= n: + raise ValueError(f"k must be less than ndim(A), k={k}") + + self.rng = np.random.default_rng(rng) + _ArpackParams.__init__(self, n, k, tp, self.rng, mode, sigma, ncv, v0, + maxiter, which, tol) + + self.arpack_dict['bmat'] = 0 if self.bmat == 'I' else 1 + + if self.ncv > n or self.ncv <= k: + raise ValueError(f"ncv must be k= n - 1: + raise ValueError(f"k must be less than ndim(A)-1, k={k}") + + self.rng = np.random.default_rng(rng) + _ArpackParams.__init__(self, n, k, tp, rng, mode, sigma, ncv, v0, maxiter, + which, tol) + + self.arpack_dict['bmat'] = 0 if self.bmat == 'I' else 1 + + if self.ncv > n or self.ncv <= k + 1: + raise ValueError(f"ncv must be k+1 k, so we'll + # throw out this case. + nreturned -= 1 + i += 1 + + else: + # real matrix, mode 3 or 4, imag(sigma) is nonzero: + # see remark 3 in neupd.f + # Build complex eigenvalues from real and imaginary parts + i = 0 + while i <= k: + if abs(d[i].imag) == 0: + d[i] = np.dot(zr[:, i], self.matvec(zr[:, i])) + else: + if i < k: + z[:, i] = zr[:, i] + 1.0j * zr[:, i + 1] + z[:, i + 1] = z[:, i].conjugate() + d[i] = ((np.dot(zr[:, i], + self.matvec(zr[:, i])) + + np.dot(zr[:, i + 1], + self.matvec(zr[:, i + 1]))) + + 1j * (np.dot(zr[:, i], + self.matvec(zr[:, i + 1])) + - np.dot(zr[:, i + 1], + self.matvec(zr[:, i])))) + d[i + 1] = d[i].conj() + i += 1 + else: + #last eigenvalue is complex: the imaginary part of + # the eigenvector has not been returned + #this can only happen if nreturned > k, so we'll + # throw out this case. + nreturned -= 1 + i += 1 + + # Now we have k+1 possible eigenvalues and eigenvectors + # Return the ones specified by the keyword "which" + + if nreturned <= k: + # we got less or equal as many eigenvalues we wanted + d = d[:nreturned] + z = z[:, :nreturned] + else: + # we got one extra eigenvalue (likely a cc pair, but which?) + if self.mode in (1, 2): + rd = d + elif self.mode in (3, 4): + rd = 1 / (d - self.sigma) + + if self.which in ['LR', 'SR']: + ind = np.argsort(rd.real) + elif self.which in ['LI', 'SI']: + # for LI,SI ARPACK returns largest,smallest + # abs(imaginary) (complex pairs come together) + ind = np.argsort(abs(rd.imag)) + else: + ind = np.argsort(abs(rd)) + + if self.which in ['LR', 'LM', 'LI']: + ind = ind[-k:][::-1] + elif self.which in ['SR', 'SM', 'SI']: + ind = ind[:k] + + d = d[ind] + z = z[:, ind] + else: + d = np.zeros([k], dtype=self.tp) + z = np.zeros([n, k], dtype=self.tp, order='F') + self._arpack_extract( + self.arpack_dict, return_eigenvectors, howmny, sselect, d, z, + self.sigma, workev, self.resid, self.v, self.ipntr, self.workd, + self.workl, self.rwork) + + ierr = self.arpack_dict['info'] + + if ierr != 0: + raise ArpackError(ierr, infodict=self.extract_infodict) + + k_ok = self.arpack_dict['nconv'] + d = d[:k_ok] + z = z[:, :k_ok] + + if return_eigenvectors: + return d, z + else: + return d + +class SpLuInv(LinearOperator): + """ + SpLuInv: + helper class to repeatedly solve M*x=b + using a sparse LU-decomposition of M + """ + + def __init__(self, M): + self.M_lu = splu(M) + self.shape = M.shape + self.dtype = M.dtype + self.isreal = not np.issubdtype(self.dtype, np.complexfloating) + + def _matvec(self, x): + # careful here: splu.solve will throw away imaginary + # part of x if M is real + x = np.asarray(x) + if self.isreal and np.issubdtype(x.dtype, np.complexfloating): + return (self.M_lu.solve(np.real(x).astype(self.dtype)) + + 1j * self.M_lu.solve(np.imag(x).astype(self.dtype))) + else: + return self.M_lu.solve(x.astype(self.dtype)) + + +class LuInv(LinearOperator): + """ + LuInv: + helper class to repeatedly solve M*x=b + using an LU-decomposition of M + """ + + def __init__(self, M): + self.M_lu = lu_factor(M) + self.shape = M.shape + self.dtype = M.dtype + + def _matvec(self, x): + return lu_solve(self.M_lu, x) + + +def gmres_loose(A, b, tol): + """ + gmres with looser termination condition. + """ + b = np.asarray(b) + min_tol = 1000 * np.sqrt(b.size) * np.finfo(b.dtype).eps + return gmres(A, b, rtol=max(tol, min_tol), atol=0) + + +class IterInv(LinearOperator): + """ + IterInv: + helper class to repeatedly solve M*x=b + using an iterative method. + """ + + def __init__(self, M, ifunc=gmres_loose, tol=0): + self.M = M + if hasattr(M, 'dtype'): + self.dtype = M.dtype + else: + x = np.zeros(M.shape[1]) + self.dtype = (M * x).dtype + self.shape = M.shape + + if tol <= 0: + # when tol=0, ARPACK uses machine tolerance as calculated + # by LAPACK's _LAMCH function. We should match this + tol = 2 * np.finfo(self.dtype).eps + self.ifunc = ifunc + self.tol = tol + + def _matvec(self, x): + b, info = self.ifunc(self.M, x, tol=self.tol) + if info != 0: + raise ValueError( + f"Error in inverting M: function {self.ifunc.__name__} " + f"did not converge (info = {info})." + ) + return b + + +class IterOpInv(LinearOperator): + """ + IterOpInv: + helper class to repeatedly solve [A-sigma*M]*x = b + using an iterative method + """ + + def __init__(self, A, M, sigma, ifunc=gmres_loose, tol=0): + self.A = A + self.M = M + self.sigma = sigma + + def mult_func(x): + return A.matvec(x) - sigma * M.matvec(x) + + def mult_func_M_None(x): + return A.matvec(x) - sigma * x + + x = np.zeros(A.shape[1]) + if M is None: + dtype = mult_func_M_None(x).dtype + self.OP = LinearOperator(self.A.shape, + mult_func_M_None, + dtype=dtype) + else: + dtype = mult_func(x).dtype + self.OP = LinearOperator(self.A.shape, + mult_func, + dtype=dtype) + self.shape = A.shape + + if tol <= 0: + # when tol=0, ARPACK uses machine tolerance as calculated + # by LAPACK's _LAMCH function. We should match this + tol = 2 * np.finfo(self.OP.dtype).eps + self.ifunc = ifunc + self.tol = tol + + def _matvec(self, x): + b, info = self.ifunc(self.OP, x, tol=self.tol) + if info != 0: + raise ValueError( + f"Error in inverting [A-sigma*M]: function {self.ifunc.__name__} " + f"did not converge (info = {info})." + ) + return b + + @property + def dtype(self): + return self.OP.dtype + + +def _fast_spmatrix_to_csc(A, hermitian=False): + """Convert sparse matrix to CSC (by transposing, if possible)""" + if (A.format == "csr" and hermitian + and not np.issubdtype(A.dtype, np.complexfloating)): + return A.T + elif is_pydata_spmatrix(A): + # No need to convert + return A + else: + return A.tocsc() + + +def get_inv_matvec(M, hermitian=False, tol=0): + if isdense(M): + return LuInv(M).matvec + elif issparse(M) or is_pydata_spmatrix(M): + M = _fast_spmatrix_to_csc(M, hermitian=hermitian) + return SpLuInv(M).matvec + else: + return IterInv(M, tol=tol).matvec + + +def get_OPinv_matvec(A, M, sigma, hermitian=False, tol=0): + if sigma == 0: + return get_inv_matvec(A, hermitian=hermitian, tol=tol) + + if M is None: + #M is the identity matrix + if isdense(A): + if (np.issubdtype(A.dtype, np.complexfloating) + or np.imag(sigma) == 0): + A = np.copy(A) + else: + A = A + 0j + A.flat[::A.shape[1] + 1] -= sigma + return LuInv(A).matvec + elif issparse(A) or is_pydata_spmatrix(A): + A = A - sigma * eye(A.shape[0]) + A = _fast_spmatrix_to_csc(A, hermitian=hermitian) + return SpLuInv(A).matvec + else: + return IterOpInv(aslinearoperator(A), + M, sigma, tol=tol).matvec + else: + if ((not isdense(A) and not issparse(A) and not is_pydata_spmatrix(A)) or + (not isdense(M) and not issparse(M) and not is_pydata_spmatrix(A))): + return IterOpInv(aslinearoperator(A), + aslinearoperator(M), + sigma, tol=tol).matvec + elif isdense(A) or isdense(M): + return LuInv(A - sigma * M).matvec + else: + OP = A - sigma * M + OP = _fast_spmatrix_to_csc(OP, hermitian=hermitian) + return SpLuInv(OP).matvec + + +def eigs(A, k=6, M=None, sigma=None, which='LM', v0=None, + ncv=None, maxiter=None, tol=0, return_eigenvectors=True, + Minv=None, OPinv=None, OPpart=None, rng=None): + """ + Find k eigenvalues and eigenvectors of the square matrix A. + + Solves ``A @ x[i] = w[i] * x[i]``, the standard eigenvalue problem + for w[i] eigenvalues with corresponding eigenvectors x[i]. + + If M is specified, solves ``A @ x[i] = w[i] * M @ x[i]``, the + generalized eigenvalue problem for w[i] eigenvalues + with corresponding eigenvectors x[i] + + Parameters + ---------- + A : ndarray, sparse matrix or LinearOperator + An array, sparse matrix, or LinearOperator representing + the operation ``A @ x``, where A is a real or complex square matrix. + k : int, optional + The number of eigenvalues and eigenvectors desired. + `k` must be smaller than N-1. It is not possible to compute all + eigenvectors of a matrix. + M : ndarray, sparse matrix or LinearOperator, optional + An array, sparse matrix, or LinearOperator representing + the operation M@x for the generalized eigenvalue problem + + A @ x = w * M @ x. + + M must represent a real symmetric matrix if A is real, and must + represent a complex Hermitian matrix if A is complex. For best + results, the data type of M should be the same as that of A. + Additionally: + + If `sigma` is None, M is positive definite + + If sigma is specified, M is positive semi-definite + + If sigma is None, eigs requires an operator to compute the solution + of the linear equation ``M @ x = b``. This is done internally via a + (sparse) LU decomposition for an explicit matrix M, or via an + iterative solver for a general linear operator. Alternatively, + the user can supply the matrix or operator Minv, which gives + ``x = Minv @ b = M^-1 @ b``. + sigma : real or complex, optional + Find eigenvalues near sigma using shift-invert mode. This requires + an operator to compute the solution of the linear system + ``[A - sigma * M] @ x = b``, where M is the identity matrix if + unspecified. This is computed internally via a (sparse) LU + decomposition for explicit matrices A & M, or via an iterative + solver if either A or M is a general linear operator. + Alternatively, the user can supply the matrix or operator OPinv, + which gives ``x = OPinv @ b = [A - sigma * M]^-1 @ b``. + For a real matrix A, shift-invert can either be done in imaginary + mode or real mode, specified by the parameter OPpart ('r' or 'i'). + Note that when sigma is specified, the keyword 'which' (below) + refers to the shifted eigenvalues ``w'[i]`` where: + + If A is real and OPpart == 'r' (default), + ``w'[i] = 1/2 * [1/(w[i]-sigma) + 1/(w[i]-conj(sigma))]``. + + If A is real and OPpart == 'i', + ``w'[i] = 1/2i * [1/(w[i]-sigma) - 1/(w[i]-conj(sigma))]``. + + If A is complex, ``w'[i] = 1/(w[i]-sigma)``. + + v0 : ndarray, optional + Starting vector for iteration. + Default: random + ncv : int, optional + The number of Lanczos vectors generated + `ncv` must be greater than `k`; it is recommended that ``ncv > 2*k``. + Default: ``min(n, max(2*k + 1, 20))`` + which : str, ['LM' | 'SM' | 'LR' | 'SR' | 'LI' | 'SI'], optional + Which `k` eigenvectors and eigenvalues to find: + + 'LM' : largest magnitude + + 'SM' : smallest magnitude + + 'LR' : largest real part + + 'SR' : smallest real part + + 'LI' : largest imaginary part + + 'SI' : smallest imaginary part + + When sigma != None, 'which' refers to the shifted eigenvalues w'[i] + (see discussion in 'sigma', above). ARPACK is generally better + at finding large values than small values. If small eigenvalues are + desired, consider using shift-invert mode for better performance. + maxiter : int, optional + Maximum number of Arnoldi update iterations allowed + Default: ``n*10`` + tol : float, optional + Relative accuracy for eigenvalues (stopping criterion) + The default value of 0 implies machine precision. + return_eigenvectors : bool, optional + Return eigenvectors (True) in addition to eigenvalues + Minv : ndarray, sparse matrix or LinearOperator, optional + See notes in M, above. + OPinv : ndarray, sparse matrix or LinearOperator, optional + See notes in sigma, above. + OPpart : {'r' or 'i'}, optional + See notes in sigma, above + rng : `numpy.random.Generator`, optional + Pseudorandom number generator state. When `rng` is None, a new + `numpy.random.Generator` is created using entropy from the + operating system. Types other than `numpy.random.Generator` are + passed to `numpy.random.default_rng` to instantiate a ``Generator``. + + Returns + ------- + w : ndarray + Array of k eigenvalues. + v : ndarray + An array of `k` eigenvectors. + ``v[:, i]`` is the eigenvector corresponding to the eigenvalue w[i]. + + Raises + ------ + ArpackNoConvergence + When the requested convergence is not obtained. + The currently converged eigenvalues and eigenvectors can be found + as ``eigenvalues`` and ``eigenvectors`` attributes of the exception + object. + + See Also + -------- + eigsh : eigenvalues and eigenvectors for symmetric matrix A + svds : singular value decomposition for a matrix A + + Notes + ----- + This function is a wrapper to the ARPACK [1]_ SNEUPD, DNEUPD, CNEUPD, + ZNEUPD, functions which use the Implicitly Restarted Arnoldi Method to + find the eigenvalues and eigenvectors [2]_. + + References + ---------- + .. [1] ARPACK Software, https://github.com/opencollab/arpack-ng + .. [2] R. B. Lehoucq, D. C. Sorensen, and C. Yang, ARPACK USERS GUIDE: + Solution of Large Scale Eigenvalue Problems by Implicitly Restarted + Arnoldi Methods. SIAM, Philadelphia, PA, 1998. + + Examples + -------- + Find 6 eigenvectors of the identity matrix: + + >>> import numpy as np + >>> from scipy.sparse.linalg import eigs + >>> id = np.eye(13) + >>> vals, vecs = eigs(id, k=6) + >>> vals + array([ 1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j]) + >>> vecs.shape + (13, 6) + + """ + A = convert_pydata_sparse_to_scipy(A) + M = convert_pydata_sparse_to_scipy(M) + if A.shape[0] != A.shape[1]: + raise ValueError(f'expected square matrix (shape={A.shape})') + if M is not None: + if M.shape != A.shape: + raise ValueError(f'wrong M dimensions {M.shape}, should be {A.shape}') + if np.dtype(M.dtype).char.lower() != np.dtype(A.dtype).char.lower(): + warnings.warn('M does not have the same type precision as A. ' + 'This may adversely affect ARPACK convergence', + stacklevel=2) + + n = A.shape[0] + + if k <= 0: + raise ValueError(f"k={k} must be greater than 0.") + + if k >= n - 1: + warnings.warn("k >= N - 1 for N * N square matrix. " + "Attempting to use scipy.linalg.eig instead.", + RuntimeWarning, stacklevel=2) + + if issparse(A): + raise TypeError("Cannot use scipy.linalg.eig for sparse A with " + "k >= N - 1. Use scipy.linalg.eig(A.toarray()) or" + " reduce k.") + if isinstance(A, LinearOperator): + raise TypeError("Cannot use scipy.linalg.eig for LinearOperator " + "A with k >= N - 1.") + if isinstance(M, LinearOperator): + raise TypeError("Cannot use scipy.linalg.eig for LinearOperator " + "M with k >= N - 1.") + + return eig(A, b=M, right=return_eigenvectors) + + if sigma is None: + matvec = aslinearoperator(A).matvec + + if OPinv is not None: + raise ValueError("OPinv should not be specified " + "with sigma = None.") + if OPpart is not None: + raise ValueError("OPpart should not be specified with " + "sigma = None or complex A") + + if M is None: + #standard eigenvalue problem + mode = 1 + M_matvec = None + Minv_matvec = None + if Minv is not None: + raise ValueError("Minv should not be " + "specified with M = None.") + else: + #general eigenvalue problem + mode = 2 + if Minv is None: + Minv_matvec = get_inv_matvec(M, hermitian=True, tol=tol) + else: + Minv = aslinearoperator(Minv) + Minv_matvec = Minv.matvec + M_matvec = aslinearoperator(M).matvec + else: + #sigma is not None: shift-invert mode + if np.issubdtype(A.dtype, np.complexfloating): + if OPpart is not None: + raise ValueError("OPpart should not be specified " + "with sigma=None or complex A") + mode = 3 + elif OPpart is None or OPpart.lower() == 'r': + mode = 3 + elif OPpart.lower() == 'i': + if np.imag(sigma) == 0: + raise ValueError("OPpart cannot be 'i' if sigma is real") + mode = 4 + else: + raise ValueError("OPpart must be one of ('r','i')") + + matvec = aslinearoperator(A).matvec + if Minv is not None: + raise ValueError("Minv should not be specified when sigma is" + "specified.") + if OPinv is None: + Minv_matvec = get_OPinv_matvec(A, M, sigma, + hermitian=False, tol=tol) + else: + OPinv = aslinearoperator(OPinv) + Minv_matvec = OPinv.matvec + if M is None: + M_matvec = None + else: + M_matvec = aslinearoperator(M).matvec + + rng = np.random.default_rng(rng) + params = _UnsymmetricArpackParams(n, k, A.dtype.char, matvec, mode, + M_matvec, Minv_matvec, sigma, + ncv, v0, maxiter, which, tol, rng) + + while not params.converged: + params.iterate() + + return params.extract(return_eigenvectors) + + +def eigsh(A, k=6, M=None, sigma=None, which='LM', v0=None, + ncv=None, maxiter=None, tol=0, return_eigenvectors=True, + Minv=None, OPinv=None, mode='normal', rng=None): + """ + Find k eigenvalues and eigenvectors of the real symmetric square matrix + or complex Hermitian matrix A. + + Solves ``A @ x[i] = w[i] * x[i]``, the standard eigenvalue problem for + w[i] eigenvalues with corresponding eigenvectors x[i]. + + If M is specified, solves ``A @ x[i] = w[i] * M @ x[i]``, the + generalized eigenvalue problem for w[i] eigenvalues + with corresponding eigenvectors x[i]. + + Note that there is no specialized routine for the case when A is a complex + Hermitian matrix. In this case, ``eigsh()`` will call ``eigs()`` and return + the real parts of the eigenvalues thus obtained. + + Parameters + ---------- + A : ndarray, sparse matrix or LinearOperator + A square operator representing the operation ``A @ x``, where ``A`` is + real symmetric or complex Hermitian. For buckling mode (see below) + ``A`` must additionally be positive-definite. + k : int, optional + The number of eigenvalues and eigenvectors desired. + `k` must be smaller than N. It is not possible to compute all + eigenvectors of a matrix. + + Returns + ------- + w : array + Array of k eigenvalues. + v : array + An array representing the `k` eigenvectors. The column ``v[:, i]`` is + the eigenvector corresponding to the eigenvalue ``w[i]``. + + Other Parameters + ---------------- + M : An N x N matrix, array, sparse matrix, or linear operator representing + the operation ``M @ x`` for the generalized eigenvalue problem + + A @ x = w * M @ x. + + M must represent a real symmetric matrix if A is real, and must + represent a complex Hermitian matrix if A is complex. For best + results, the data type of M should be the same as that of A. + Additionally: + + If sigma is None, M is symmetric positive definite. + + If sigma is specified, M is symmetric positive semi-definite. + + In buckling mode, M is symmetric indefinite. + + If sigma is None, eigsh requires an operator to compute the solution + of the linear equation ``M @ x = b``. This is done internally via a + (sparse) LU decomposition for an explicit matrix M, or via an + iterative solver for a general linear operator. Alternatively, + the user can supply the matrix or operator Minv, which gives + ``x = Minv @ b = M^-1 @ b``. + sigma : real + Find eigenvalues near sigma using shift-invert mode. This requires + an operator to compute the solution of the linear system + ``[A - sigma * M] x = b``, where M is the identity matrix if + unspecified. This is computed internally via a (sparse) LU + decomposition for explicit matrices A & M, or via an iterative + solver if either A or M is a general linear operator. + Alternatively, the user can supply the matrix or operator `OPinv`, + which gives ``x = OPinv @ b = [A - sigma * M]^-1 @ b``. + Regardless of the selected mode (normal, cayley, or buckling), + `OPinv` should always be supplied as ``OPinv = [A - sigma * M]^-1``. + + Note that when sigma is specified, the keyword 'which' refers to + the shifted eigenvalues ``w'[i]`` where: + + if ``mode == 'normal'``: ``w'[i] = 1 / (w[i] - sigma)``. + + if ``mode == 'cayley'``: ``w'[i] = (w[i] + sigma) / (w[i] - sigma)``. + + if ``mode == 'buckling'``: ``w'[i] = w[i] / (w[i] - sigma)``. + + (see further discussion in 'mode' below) + v0 : ndarray, optional + Starting vector for iteration. + Default: random + ncv : int, optional + The number of Lanczos vectors generated ncv must be greater than k and + smaller than n; it is recommended that ``ncv > 2*k``. + Default: ``min(n, max(2*k + 1, 20))`` + which : str ['LM' | 'SM' | 'LA' | 'SA' | 'BE'] + If A is a complex Hermitian matrix, 'BE' is invalid. + Which `k` eigenvectors and eigenvalues to find: + + 'LM' : Largest (in magnitude) eigenvalues. + + 'SM' : Smallest (in magnitude) eigenvalues. + + 'LA' : Largest (algebraic) eigenvalues. + + 'SA' : Smallest (algebraic) eigenvalues. + + 'BE' : Half (k/2) from each end of the spectrum. + + When k is odd, return one more (k/2+1) from the high end. + When sigma != None, 'which' refers to the shifted eigenvalues ``w'[i]`` + (see discussion in 'sigma', above). ARPACK is generally better + at finding large values than small values. If small eigenvalues are + desired, consider using shift-invert mode for better performance. + maxiter : int, optional + Maximum number of Arnoldi update iterations allowed. + Default: ``n*10`` + tol : float + Relative accuracy for eigenvalues (stopping criterion). + The default value of 0 implies machine precision. + Minv : N x N matrix, array, sparse matrix, or LinearOperator + See notes in M, above. + OPinv : N x N matrix, array, sparse matrix, or LinearOperator + See notes in sigma, above. + return_eigenvectors : bool + Return eigenvectors (True) in addition to eigenvalues. + This value determines the order in which eigenvalues are sorted. + The sort order is also dependent on the `which` variable. + + For which = 'LM' or 'SA': + If `return_eigenvectors` is True, eigenvalues are sorted by + algebraic value. + + If `return_eigenvectors` is False, eigenvalues are sorted by + absolute value. + + For which = 'BE' or 'LA': + eigenvalues are always sorted by algebraic value. + + For which = 'SM': + If `return_eigenvectors` is True, eigenvalues are sorted by + algebraic value. + + If `return_eigenvectors` is False, eigenvalues are sorted by + decreasing absolute value. + + mode : string ['normal' | 'buckling' | 'cayley'] + Specify strategy to use for shift-invert mode. This argument applies + only for real-valued A and sigma != None. For shift-invert mode, + ARPACK internally solves the eigenvalue problem + ``OP @ x'[i] = w'[i] * B @ x'[i]`` + and transforms the resulting Ritz vectors x'[i] and Ritz values w'[i] + into the desired eigenvectors and eigenvalues of the problem + ``A @ x[i] = w[i] * M @ x[i]``. + The modes are as follows: + + 'normal' : + OP = [A - sigma * M]^-1 @ M, + B = M, + w'[i] = 1 / (w[i] - sigma) + + 'buckling' : + OP = [A - sigma * M]^-1 @ A, + B = A, + w'[i] = w[i] / (w[i] - sigma) + + 'cayley' : + OP = [A - sigma * M]^-1 @ [A + sigma * M], + B = M, + w'[i] = (w[i] + sigma) / (w[i] - sigma) + + The choice of mode will affect which eigenvalues are selected by + the keyword 'which', and can also impact the stability of + convergence (see [2] for a discussion). + rng : `numpy.random.Generator`, optional + Pseudorandom number generator state. When `rng` is None, a new + `numpy.random.Generator` is created using entropy from the + operating system. Types other than `numpy.random.Generator` are + passed to `numpy.random.default_rng` to instantiate a ``Generator``. + + Raises + ------ + ArpackNoConvergence + When the requested convergence is not obtained. + + The currently converged eigenvalues and eigenvectors can be found + as ``eigenvalues`` and ``eigenvectors`` attributes of the exception + object. + + See Also + -------- + eigs : eigenvalues and eigenvectors for a general (nonsymmetric) matrix A + svds : singular value decomposition for a matrix A + + Notes + ----- + This function is a wrapper to the ARPACK [1]_ SSEUPD and DSEUPD + functions which use the Implicitly Restarted Lanczos Method to + find the eigenvalues and eigenvectors [2]_. + + References + ---------- + .. [1] ARPACK Software, https://github.com/opencollab/arpack-ng + .. [2] R. B. Lehoucq, D. C. Sorensen, and C. Yang, ARPACK USERS GUIDE: + Solution of Large Scale Eigenvalue Problems by Implicitly Restarted + Arnoldi Methods. SIAM, Philadelphia, PA, 1998. + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse.linalg import eigsh + >>> identity = np.eye(13) + >>> eigenvalues, eigenvectors = eigsh(identity, k=6) + >>> eigenvalues + array([1., 1., 1., 1., 1., 1.]) + >>> eigenvectors.shape + (13, 6) + + """ + # complex Hermitian matrices should be solved with eigs + if np.issubdtype(A.dtype, np.complexfloating): + if mode != 'normal': + raise ValueError(f"mode={mode} cannot be used with complex matrix A") + if which == 'BE': + raise ValueError("which='BE' cannot be used with complex matrix A") + elif which == 'LA': + which = 'LR' + elif which == 'SA': + which = 'SR' + ret = eigs(A, k, M=M, sigma=sigma, which=which, v0=v0, + ncv=ncv, maxiter=maxiter, tol=tol, + return_eigenvectors=return_eigenvectors, Minv=Minv, + OPinv=OPinv) + + if return_eigenvectors: + return ret[0].real, ret[1] + else: + return ret.real + + if A.shape[0] != A.shape[1]: + raise ValueError(f'expected square matrix (shape={A.shape})') + if M is not None: + if M.shape != A.shape: + raise ValueError(f'wrong M dimensions {M.shape}, should be {A.shape}') + if np.dtype(M.dtype).char.lower() != np.dtype(A.dtype).char.lower(): + warnings.warn('M does not have the same type precision as A. ' + 'This may adversely affect ARPACK convergence', + stacklevel=2) + + n = A.shape[0] + + if k <= 0: + raise ValueError("k must be greater than 0.") + + if k >= n: + warnings.warn("k >= N for N * N square matrix. " + "Attempting to use scipy.linalg.eigh instead.", + RuntimeWarning, stacklevel=2) + + if issparse(A): + raise TypeError("Cannot use scipy.linalg.eigh for sparse A with " + "k >= N. Use scipy.linalg.eigh(A.toarray()) or" + " reduce k.") + if isinstance(A, LinearOperator): + raise TypeError("Cannot use scipy.linalg.eigh for LinearOperator " + "A with k >= N.") + if isinstance(M, LinearOperator): + raise TypeError("Cannot use scipy.linalg.eigh for LinearOperator " + "M with k >= N.") + + return eigh(A, b=M, eigvals_only=not return_eigenvectors) + + if sigma is None: + A = aslinearoperator(A) + matvec = A.matvec + + if OPinv is not None: + raise ValueError("OPinv should not be specified with sigma = None.") + if M is None: + #standard eigenvalue problem + mode = 1 + M_matvec = None + Minv_matvec = None + if Minv is not None: + raise ValueError("Minv should not be specified with M = None.") + else: + #general eigenvalue problem + mode = 2 + if Minv is None: + Minv_matvec = get_inv_matvec(M, hermitian=True, tol=tol) + else: + Minv = aslinearoperator(Minv) + Minv_matvec = Minv.matvec + M_matvec = aslinearoperator(M).matvec + else: + # sigma is not None: shift-invert mode + if Minv is not None: + raise ValueError("Minv should not be specified when sigma is " + "specified.") + + # normal mode + if mode == 'normal': + mode = 3 + matvec = None + if OPinv is None: + Minv_matvec = get_OPinv_matvec(A, M, sigma, + hermitian=True, tol=tol) + else: + OPinv = aslinearoperator(OPinv) + Minv_matvec = OPinv.matvec + if M is None: + M_matvec = None + else: + M = aslinearoperator(M) + M_matvec = M.matvec + + # buckling mode + elif mode == 'buckling': + mode = 4 + if OPinv is None: + Minv_matvec = get_OPinv_matvec(A, M, sigma, + hermitian=True, tol=tol) + else: + Minv_matvec = aslinearoperator(OPinv).matvec + matvec = aslinearoperator(A).matvec + M_matvec = None + + # cayley-transform mode + elif mode == 'cayley': + mode = 5 + matvec = aslinearoperator(A).matvec + if OPinv is None: + Minv_matvec = get_OPinv_matvec(A, M, sigma, + hermitian=True, tol=tol) + else: + Minv_matvec = aslinearoperator(OPinv).matvec + if M is None: + M_matvec = None + else: + M_matvec = aslinearoperator(M).matvec + + # unrecognized mode + else: + raise ValueError(f"unrecognized mode '{mode}'") + rng = np.random.default_rng(rng) + params = _SymmetricArpackParams(n, k, A.dtype.char, matvec, mode, + M_matvec, Minv_matvec, sigma, + ncv, v0, maxiter, which, tol, rng) + + while not params.converged: + params.iterate() + + return params.extract(return_eigenvectors) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6254b2781014d5710af2faac684d58f8036c4651 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/tests/__pycache__/test_arpack.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/tests/__pycache__/test_arpack.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f31561d54a003c179291e6782bc4bf8dd45d51d4 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/tests/__pycache__/test_arpack.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/tests/test_arpack.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/tests/test_arpack.py new file mode 100644 index 0000000000000000000000000000000000000000..eea4dad950ce6da30ed54b448efd116cea1a2647 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/arpack/tests/test_arpack.py @@ -0,0 +1,708 @@ +import threading +import itertools +import warnings + +import numpy as np + +from numpy.testing import assert_allclose, assert_equal +from pytest import raises as assert_raises +import pytest + +from numpy import dot, conj +from scipy.linalg import eig, eigh +from scipy.sparse import csc_array, csr_array, diags_array, random_array +from scipy.sparse.linalg import LinearOperator, aslinearoperator +from scipy.sparse.linalg._eigen.arpack import (eigs, eigsh, arpack, + ArpackNoConvergence) + + +from scipy._lib._gcutils import assert_deallocated, IS_PYPY + + +# precision for tests +_ndigits = {'f': 3, 'd': 11, 'F': 3, 'D': 11} + + +def _get_test_tolerance(type_char, mattype=None, D_type=None, which=None): + """ + Return tolerance values suitable for a given test: + + Parameters + ---------- + type_char : {'f', 'd', 'F', 'D'} + Data type in ARPACK eigenvalue problem + mattype : {csr_array, aslinearoperator, asarray}, optional + Linear operator type + + Returns + ------- + tol + Tolerance to pass to the ARPACK routine + rtol + Relative tolerance for outputs + atol + Absolute tolerance for outputs + + """ + + rtol = {'f': 3000 * np.finfo(np.float32).eps, + 'F': 3000 * np.finfo(np.float32).eps, + 'd': 2000 * np.finfo(np.float64).eps, + 'D': 2000 * np.finfo(np.float64).eps}[type_char] + atol = rtol + tol = 0 + + if mattype is aslinearoperator and type_char in ('f', 'F'): + # iterative methods in single precision: worse errors + # also: bump ARPACK tolerance so that the iterative method converges + tol = 30 * np.finfo(np.float32).eps + rtol *= 5 + + if ( + isinstance(mattype, type) and issubclass(mattype, csr_array) + and type_char in ('f', 'F') + ): + # sparse in single precision: worse errors + rtol *= 5 + + if ( + which in ('LM', 'SM', 'LA') + and D_type.name == "gen-hermitian-Mc" + ): + if type_char == 'F': + # missing case 1, 2, and more, from PR 14798 + rtol *= 5 + + if type_char == 'D': + # missing more cases, from PR 14798 + rtol *= 10 + atol *= 10 + + return tol, rtol, atol + + +def generate_matrix(N, complex_=False, hermitian=False, + pos_definite=False, sparse=False, rng=None): + M = rng.random((N, N)) + if complex_: + M = M + 1j * rng.random((N, N)) + + if hermitian: + if pos_definite: + if sparse: + i = np.arange(N) + j = rng.randint(N, size=N-2) + i, j = np.meshgrid(i, j) + M[i, j] = 0 + M = np.dot(M.conj(), M.T) + else: + M = np.dot(M.conj(), M.T) + if sparse: + i = rng.randint(N, size=N * N // 4) + j = rng.randint(N, size=N * N // 4) + ind = np.nonzero(i == j) + j[ind] = (j[ind] + 1) % N + M[i, j] = 0 + M[j, i] = 0 + else: + if sparse: + i = rng.randint(N, size=N * N // 2) + j = rng.randint(N, size=N * N // 2) + M[i, j] = 0 + return M + + +def generate_matrix_symmetric(N, pos_definite=False, sparse=False, rng=None): + M = rng.random((N, N)) + + M = 0.5 * (M + M.T) # Make M symmetric + + if pos_definite: + Id = N * np.eye(N) + if sparse: + M = csr_array(M) + M += Id + else: + if sparse: + M = csr_array(M) + + return M + + +def assert_allclose_cc(actual, desired, **kw): + """Almost equal or complex conjugates almost equal""" + try: + assert_allclose(actual, desired, **kw) + except AssertionError: + assert_allclose(actual, conj(desired), **kw) + + +def argsort_which(eigenvalues, typ, k, which, + sigma=None, OPpart=None, mode=None): + """Return sorted indices of eigenvalues using the "which" keyword + from eigs and eigsh""" + if sigma is None: + reval = np.round(eigenvalues, decimals=_ndigits[typ]) + else: + if mode is None or mode == 'normal': + if OPpart is None: + reval = 1. / (eigenvalues - sigma) + elif OPpart == 'r': + reval = 0.5 * (1. / (eigenvalues - sigma) + + 1. / (eigenvalues - np.conj(sigma))) + elif OPpart == 'i': + reval = -0.5j * (1. / (eigenvalues - sigma) + - 1. / (eigenvalues - np.conj(sigma))) + elif mode == 'cayley': + reval = (eigenvalues + sigma) / (eigenvalues - sigma) + elif mode == 'buckling': + reval = eigenvalues / (eigenvalues - sigma) + else: + raise ValueError(f"mode='{mode}' not recognized") + + reval = np.round(reval, decimals=_ndigits[typ]) + + if which in ['LM', 'SM']: + ind = np.argsort(abs(reval)) + elif which in ['LR', 'SR', 'LA', 'SA', 'BE']: + ind = np.argsort(np.real(reval)) + elif which in ['LI', 'SI']: + # for LI,SI ARPACK returns largest,smallest abs(imaginary) why? + if typ.islower(): + ind = np.argsort(abs(np.imag(reval))) + else: + ind = np.argsort(np.imag(reval)) + else: + raise ValueError(f"which='{which}' is unrecognized") + + if which in ['LM', 'LA', 'LR', 'LI']: + return ind[-k:] + elif which in ['SM', 'SA', 'SR', 'SI']: + return ind[:k] + elif which == 'BE': + return np.concatenate((ind[:k//2], ind[k//2-k:])) + + +def eval_evec(symmetric, d, typ, k, which, v0=None, sigma=None, + mattype=np.asarray, OPpart=None, mode='normal', rng=None): + general = ('bmat' in d) + + if symmetric: + eigs_func = eigsh + else: + eigs_func = eigs + + if general: + err = (f"error for {eigs_func.__name__}:general, typ={typ}, which={which}, " + f"sigma={sigma}, mattype={mattype.__name__}," + f" OPpart={OPpart}, mode={mode}") + else: + err = (f"error for {eigs_func.__name__}:standard, typ={typ}, which={which}, " + f"sigma={sigma}, mattype={mattype.__name__}, " + f"OPpart={OPpart}, mode={mode}") + + a = d['mat'].astype(typ) + ac = mattype(a) + + if general: + b = d['bmat'].astype(typ) + bc = mattype(b) + + # get exact eigenvalues + exact_eval = d['eval'].astype(typ.upper()) + ind = argsort_which(exact_eval, typ, k, which, + sigma, OPpart, mode) + exact_eval = exact_eval[ind] + + # compute arpack eigenvalues + kwargs = dict(which=which, v0=v0, sigma=sigma, rng=rng) + if eigs_func is eigsh: + kwargs['mode'] = mode + else: + kwargs['OPpart'] = OPpart + + # compute suitable tolerances + kwargs['tol'], rtol, atol = _get_test_tolerance(typ, mattype, d, which) + # on rare occasions, ARPACK routines return results that are proper + # eigenvalues and -vectors, but not necessarily the ones requested in + # the parameter which. This is inherent to the Krylov methods, and + # should not be treated as a failure. If such a rare situation + # occurs, the calculation is tried again (but at most a few times). + ntries = 0 + while ntries < 5: + # solve + if general: + try: + eigenvalues, evec = eigs_func(ac, k, bc, **kwargs) + except ArpackNoConvergence: + kwargs['maxiter'] = 20*a.shape[0] + eigenvalues, evec = eigs_func(ac, k, bc, **kwargs) + else: + try: + eigenvalues, evec = eigs_func(ac, k, **kwargs) + except ArpackNoConvergence: + kwargs['maxiter'] = 20*a.shape[0] + eigenvalues, evec = eigs_func(ac, k, **kwargs) + + ind = argsort_which(eigenvalues, typ, k, which, + sigma, OPpart, mode) + eigenvalues = eigenvalues[ind] + evec = evec[:, ind] + + try: + # check eigenvalues + assert_allclose_cc(eigenvalues, exact_eval, rtol=rtol, atol=atol, + err_msg=err) + check_evecs = True + except AssertionError: + check_evecs = False + ntries += 1 + + if check_evecs: + # check eigenvectors + LHS = np.dot(a, evec) + if general: + RHS = eigenvalues * np.dot(b, evec) + else: + RHS = eigenvalues * evec + + assert_allclose(LHS, RHS, rtol=rtol, atol=atol, err_msg=err) + break + + # check eigenvalues + assert_allclose_cc(eigenvalues, exact_eval, rtol=rtol, atol=atol, err_msg=err) + + +class DictWithRepr(dict): + def __init__(self, name): + self.name = name + + def __repr__(self): + return f"<{self.name}>" + + +class SymmetricParams: + def __init__(self): + self.eigs = eigsh + self.which = ['LM', 'SM', 'LA', 'SA', 'BE'] + self.mattypes = [csr_array, aslinearoperator, np.asarray] + self.sigmas_modes = {None: ['normal'], + 0.5: ['normal', 'buckling', 'cayley']} + + # generate matrices + # these should all be float32 so that the eigenvalues + # are the same in float32 and float64 + N = 6 + rng = np.random.RandomState(2300) + Ar = generate_matrix(N, hermitian=True, + pos_definite=True, + rng=rng).astype('f').astype('d') + M = generate_matrix(N, hermitian=True, + pos_definite=True, + rng=rng).astype('f').astype('d') + Ac = generate_matrix(N, hermitian=True, pos_definite=True, + complex_=True, rng=rng).astype('F').astype('D') + Mc = generate_matrix(N, hermitian=True, pos_definite=True, + complex_=True, rng=rng).astype('F').astype('D') + v0 = rng.random(N) + + # standard symmetric problem + SS = DictWithRepr("std-symmetric") + SS['mat'] = Ar + SS['v0'] = v0 + SS['eval'] = eigh(SS['mat'], eigvals_only=True) + + # general symmetric problem + GS = DictWithRepr("gen-symmetric") + GS['mat'] = Ar + GS['bmat'] = M + GS['v0'] = v0 + GS['eval'] = eigh(GS['mat'], GS['bmat'], eigvals_only=True) + + # standard hermitian problem + SH = DictWithRepr("std-hermitian") + SH['mat'] = Ac + SH['v0'] = v0 + SH['eval'] = eigh(SH['mat'], eigvals_only=True) + + # general hermitian problem + GH = DictWithRepr("gen-hermitian") + GH['mat'] = Ac + GH['bmat'] = M + GH['v0'] = v0 + GH['eval'] = eigh(GH['mat'], GH['bmat'], eigvals_only=True) + + # general hermitian problem with hermitian M + GHc = DictWithRepr("gen-hermitian-Mc") + GHc['mat'] = Ac + GHc['bmat'] = Mc + GHc['v0'] = v0 + GHc['eval'] = eigh(GHc['mat'], GHc['bmat'], eigvals_only=True) + + self.real_test_cases = [SS, GS] + self.complex_test_cases = [SH, GH, GHc] + + +class NonSymmetricParams: + def __init__(self): + self.eigs = eigs + self.which = ['LM', 'LR', 'LI'] # , 'SM', 'LR', 'SR', 'LI', 'SI'] + self.mattypes = [csr_array, aslinearoperator, np.asarray] + self.sigmas_OPparts = {None: [None], + 0.1: ['r'], + 0.1 + 0.1j: ['r', 'i']} + + # generate matrices + # these should all be float32 so that the eigenvalues + # are the same in float32 and float64 + N = 6 + rng = np.random.RandomState(2300) + Ar = generate_matrix(N, rng=rng).astype('f').astype('d') + M = generate_matrix(N, hermitian=True, + pos_definite=True, rng=rng).astype('f').astype('d') + Ac = generate_matrix(N, complex_=True, rng=rng).astype('F').astype('D') + v0 = rng.random(N) + + # standard real nonsymmetric problem + SNR = DictWithRepr("std-real-nonsym") + SNR['mat'] = Ar + SNR['v0'] = v0 + SNR['eval'] = eig(SNR['mat'], left=False, right=False) + + # general real nonsymmetric problem + GNR = DictWithRepr("gen-real-nonsym") + GNR['mat'] = Ar + GNR['bmat'] = M + GNR['v0'] = v0 + GNR['eval'] = eig(GNR['mat'], GNR['bmat'], left=False, right=False) + + # standard complex nonsymmetric problem + SNC = DictWithRepr("std-cmplx-nonsym") + SNC['mat'] = Ac + SNC['v0'] = v0 + SNC['eval'] = eig(SNC['mat'], left=False, right=False) + + # general complex nonsymmetric problem + GNC = DictWithRepr("gen-cmplx-nonsym") + GNC['mat'] = Ac + GNC['bmat'] = M + GNC['v0'] = v0 + GNC['eval'] = eig(GNC['mat'], GNC['bmat'], left=False, right=False) + + self.real_test_cases = [SNR, GNR] + self.complex_test_cases = [SNC, GNC] + + +@pytest.mark.parametrize("sigma, mode", [(None, 'normal'), (0.5, 'normal'), + (0.5, 'buckling'), (0.5, 'cayley')]) +@pytest.mark.parametrize("mattype", [csr_array, aslinearoperator, np.asarray]) +@pytest.mark.parametrize("which", ['LM', 'SM', 'LA', 'SA', 'BE']) +@pytest.mark.parametrize("typ", ['f', 'd']) +@pytest.mark.parametrize("D", SymmetricParams().real_test_cases) +def test_symmetric_modes(D, typ, which, mattype, sigma, mode): + rng = np.random.default_rng(1749531508689996) + k = 2 + eval_evec(True, D, typ, k, which, None, sigma, mattype, None, mode, rng=rng) + + +@pytest.mark.parametrize("sigma", [None, 0.5]) +@pytest.mark.parametrize("mattype", [csr_array, aslinearoperator, np.asarray]) +@pytest.mark.parametrize("which", ['LM', 'SM', 'LA', 'SA']) +@pytest.mark.parametrize("typ", ['F', 'D']) +@pytest.mark.parametrize("D", SymmetricParams().complex_test_cases) +def test_hermitian_modes(D, typ, which, mattype, sigma): + rng = np.random.default_rng(1749531706842957) + k = 2 + eval_evec(True, D, typ, k, which, None, sigma, mattype, rng=rng) + + +@pytest.mark.parametrize("typ", ['f', 'd']) +@pytest.mark.parametrize("D", SymmetricParams().real_test_cases) +@pytest.mark.parametrize("k", [1, 2, 3, 4, 5]) +def test_symmetric_starting_vector(k, D, typ): + rng = np.random.default_rng(1749532110418901) + v0 = rng.uniform(size=len(D['v0'])).astype(typ) + eval_evec(True, D, typ, k, 'LM', v0, rng=rng) + + +def test_symmetric_no_convergence(): + rng = np.random.RandomState(1234) + m = generate_matrix(30, hermitian=True, pos_definite=True, rng=rng) + tol, rtol, atol = _get_test_tolerance('d') + try: + w, v = eigsh(m, 4, which='LM', v0=m[:, 0], maxiter=5, tol=tol, ncv=9) + raise AssertionError("Spurious no-error exit") + except ArpackNoConvergence as err: + k = len(err.eigenvalues) + if k <= 0: + raise AssertionError("Spurious no-eigenvalues-found case") from err + w, v = err.eigenvalues, err.eigenvectors + assert_allclose(dot(m, v), w * v, rtol=rtol, atol=atol) + + +@pytest.mark.parametrize("sigma, OPpart", [(None, None), (0.1, 'r'), + (0.1 + 0.1j, 'r'), (0.1 + 0.1j, 'i')]) +@pytest.mark.parametrize("mattype", [csr_array, aslinearoperator, np.asarray]) +@pytest.mark.parametrize("which", ['LM', 'LR', 'LI']) +@pytest.mark.parametrize("typ", ['f', 'd']) +@pytest.mark.parametrize("D", NonSymmetricParams().real_test_cases) +def test_real_nonsymmetric_modes(D, typ, which, mattype, + sigma, OPpart): + rng = np.random.default_rng(174953334412726) + k = 2 + eval_evec(False, D, typ, k, which, None, sigma, mattype, OPpart, rng=rng) + + +@pytest.mark.parametrize("sigma", [None, 0.1, 0.1 + 0.1j]) +@pytest.mark.parametrize("mattype", [csr_array, aslinearoperator, np.asarray]) +@pytest.mark.parametrize("which", ['LM', 'LR', 'LI']) +@pytest.mark.parametrize("typ", ['F', 'D']) +@pytest.mark.parametrize("D", NonSymmetricParams().complex_test_cases) +def test_complex_nonsymmetric_modes(D, typ, which, mattype, sigma): + rng = np.random.default_rng(1749533536274527) + k = 2 + eval_evec(False, D, typ, k, which, None, sigma, mattype, rng=rng) + + +@pytest.mark.parametrize("typ", ['F', 'D']) +@pytest.mark.parametrize("D", NonSymmetricParams().complex_test_cases) +@pytest.mark.parametrize("k", [1, 2, 3, 4]) +def test_nonsymmetric_starting_vector(k, D, typ): + rng = np.random.default_rng(174953366983161) + A = D['mat'] + n = A.shape[0] + v0 = rng.uniform(size=n).astype(typ) + eval_evec(False, D, typ, k, "LM", v0, sigma=None, rng=rng) + + +def test_standard_nonsymmetric_no_convergence(): + rng = np.random.RandomState(1234) + m = generate_matrix(30, complex_=True, rng=rng) + tol, rtol, atol = _get_test_tolerance('d') + try: + w, v = eigs(m, 4, which='LM', v0=m[:, 0], maxiter=5, tol=tol) + raise AssertionError("Spurious no-error exit") + except ArpackNoConvergence as err: + k = len(err.eigenvalues) + if k <= 0: + raise AssertionError("Spurious no-eigenvalues-found case") from err + w, v = err.eigenvalues, err.eigenvectors + for ww, vv in zip(w, v.T): + assert_allclose(dot(m, vv), ww * vv, rtol=rtol, atol=atol) + + +def test_eigen_bad_shapes(): + # A is not square. + A = csc_array(np.zeros((2, 3))) + assert_raises(ValueError, eigs, A) + + +def test_eigen_bad_kwargs(): + # Test eigen on wrong keyword argument + A = csc_array(np.zeros((8, 8))) + assert_raises(ValueError, eigs, A, which='XX') + + +def test_ticket_1459_arpack_crash(): + for dtype in [np.float32, np.float64]: + # This test does not seem to catch the issue for float32, + # but we made the same fix there, just to be sure + + N = 6 + k = 2 + + np.random.seed(2301) + A = np.random.random((N, N)).astype(dtype) + v0 = np.array([-0.71063568258907849895, -0.83185111795729227424, + -0.34365925382227402451, 0.46122533684552280420, + -0.58001341115969040629, -0.78844877570084292984e-01], + dtype=dtype) + + # Should not crash: + evals, evecs = eigs(A, k, v0=v0) + + +@pytest.mark.skipif(IS_PYPY, reason="Test not meaningful on PyPy") +def test_linearoperator_deallocation(): + # Check that the linear operators used by the Arpack wrappers are + # deallocatable by reference counting -- they are big objects, so + # Python's cyclic GC may not collect them fast enough before + # running out of memory if eigs/eigsh are called in a tight loop. + + M_d = np.eye(10) + M_s = csc_array(M_d) + M_o = aslinearoperator(M_d) + + with assert_deallocated(lambda: arpack.SpLuInv(M_s)): + pass + with assert_deallocated(lambda: arpack.LuInv(M_d)): + pass + with assert_deallocated(lambda: arpack.IterInv(M_s)): + pass + with assert_deallocated(lambda: arpack.IterOpInv(M_o, None, 0.3)): + pass + with assert_deallocated(lambda: arpack.IterOpInv(M_o, M_o, 0.3)): + pass + + +def test_parallel_threads(num_parallel_threads): + results = [] + rng = np.random.default_rng(1234) + v0 = rng.random(50) + + def worker(): + x = diags_array([1.0, -2.0, 1.0], offsets=[-1, 0, 1], shape=(50, 50)) + w, v = eigs(x, k=3, v0=v0) + results.append(w) + + w, v = eigsh(x, k=3, v0=v0) + results.append(w) + + nthreads = 9 // num_parallel_threads + 1 + threads = [threading.Thread(target=worker) for _ in range(nthreads)] + for t in threads: + t.start() + for t in threads: + t.join() + + worker() + + for r in results: + assert_allclose(r, results[-1]) + + +def test_reentering(): + # Just some linear operator that calls eigs recursively + def A_matvec(x): + x = diags_array([1.0, -2.0, 1.0], offsets=[-1, 0, 1], shape=(50, 50)) + w, v = eigs(x, k=1) + return v.real / w[0].real + A = LinearOperator(matvec=A_matvec, dtype=float, shape=(50, 50)) + + # ================= Old Fortran tests ================== + # The Fortran code is not reentrant, so this fails (gracefully, not crashing) + # assert_raises(RuntimeError, eigs, A, k=1) + # assert_raises(RuntimeError, eigsh, A, k=1) + # + # These should not crash upon reentrance + eigs(A, k=1) + eigsh(A, k=1) + + +def test_regression_arpackng_1315(): + # Check that issue arpack-ng/#1315 is not present. + # Adapted from arpack-ng/TESTS/bug_1315_single.c + # If this fails, then the installed ARPACK library is faulty. + + for dtype in [np.float32, np.float64]: + np.random.seed(1234) + + w0 = np.arange(1, 1000+1).astype(dtype) + A = diags_array([w0], offsets=[0], shape=(1000, 1000)) + + v0 = np.random.rand(1000).astype(dtype) + w, v = eigs(A, k=9, ncv=2*9+1, which="LM", v0=v0) + + assert_allclose(np.sort(w), np.sort(w0[-9:]), + rtol=1e-4) + + +def test_eigs_for_k_greater(): + # Test eigs() for k beyond limits. + rng = np.random.RandomState(1234) + A_sparse = diags_array([1.0, -2.0, 1.0], offsets=[-1, 0, 1], shape=(4, 4)) + A = generate_matrix(4, sparse=False, rng=rng) + M_dense = rng.random((4, 4)) + M_sparse = generate_matrix(4, sparse=True, rng=rng) + M_linop = aslinearoperator(M_dense) + eig_tuple1 = eig(A, b=M_dense) + eig_tuple2 = eig(A, b=M_sparse) + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", RuntimeWarning) + + assert_equal(eigs(A, M=M_dense, k=3), eig_tuple1) + assert_equal(eigs(A, M=M_dense, k=4), eig_tuple1) + assert_equal(eigs(A, M=M_dense, k=5), eig_tuple1) + assert_equal(eigs(A, M=M_sparse, k=5), eig_tuple2) + + # M as LinearOperator + assert_raises(TypeError, eigs, A, M=M_linop, k=3) + + # Test 'A' for different types + assert_raises(TypeError, eigs, aslinearoperator(A), k=3) + assert_raises(TypeError, eigs, A_sparse, k=3) + + +def test_eigsh_for_k_greater(): + # Test eigsh() for k beyond limits. + rng = np.random.RandomState(1234) + A_sparse = diags_array([1.0, -2.0, 1.0], offsets=[-1, 0, 1], shape=(4, 4)) + A = generate_matrix(4, sparse=False, rng=rng) + M_dense = generate_matrix_symmetric(4, pos_definite=True, rng=rng) + M_sparse = generate_matrix_symmetric( + 4, pos_definite=True, sparse=True, rng=rng) + M_linop = aslinearoperator(M_dense) + eig_tuple1 = eigh(A, b=M_dense) + eig_tuple2 = eigh(A, b=M_sparse) + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", RuntimeWarning) + + assert_equal(eigsh(A, M=M_dense, k=4), eig_tuple1) + assert_equal(eigsh(A, M=M_dense, k=5), eig_tuple1) + assert_equal(eigsh(A, M=M_sparse, k=5), eig_tuple2) + + # M as LinearOperator + assert_raises(TypeError, eigsh, A, M=M_linop, k=4) + + # Test 'A' for different types + assert_raises(TypeError, eigsh, aslinearoperator(A), k=4) + assert_raises(TypeError, eigsh, A_sparse, M=M_dense, k=4) + + +def test_real_eigs_real_k_subset(): + rng = np.random.default_rng(2) + + n = 10 + A = random_array(shape=(n, n), density=0.5, rng=rng) + A.data *= 2 + A.data -= 1 + A += A.T # make symmetric to test real eigenvalues + + v0 = np.ones(n) + + whichs = ['LM', 'SM', 'LR', 'SR', 'LI', 'SI'] + dtypes = [np.float32, np.float64] + + for which, sigma, dtype in itertools.product(whichs, [None, 0, 5], dtypes): + prev_w = np.array([], dtype=dtype) + eps = np.finfo(dtype).eps + for k in range(1, 9): + w, z = eigs(A.astype(dtype), k=k, which=which, sigma=sigma, + v0=v0.astype(dtype), tol=0) + assert_allclose(np.linalg.norm(A.dot(z) - z * w), 0, atol=np.sqrt(eps)) + + # Check that the set of eigenvalues for `k` is a subset of that for `k+1` + dist = abs(prev_w[:,None] - w).min(axis=1) + assert_allclose(dist, 0, atol=np.sqrt(eps)) + + prev_w = w + + +@pytest.mark.parametrize("dtype", [np.float32, np.float64, np.complex64, np.complex128]) +def test_gh24358(dtype): + # gh-24358: eigs with which="SR" returned zeros due to nev variable was modifed + # after naupd calls in the C ARPACK implementation. This was due to hitting a + # complex valued eig but requesting only one of them. + + # Test the specific issue in gh-24358 + A = csr_array(np.array([[-1.3, 2.7, 0.2], + [0.8, 4.1, 2.2], + [2.1, 4.4, -1.9]], dtype=dtype)) + w, z = eigs(A, 1, which="SR") + atol = 1e-4 if dtype in [np.float32, np.complex64] else 1e-6 + assert_allclose(w.real, -2.495689365014214, atol=atol, rtol=0.0) + # ARPACK can sometimes pick up the conjugate + assert_allclose(np.abs(w.imag), 0.5173365219668336, atol=atol, rtol=0.0) + assert_allclose(A @ z, w * z, atol=atol, rtol=0.0) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..6ab5330361a6bcc2a8403f9b3788aedae750d57f --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/__init__.py @@ -0,0 +1,16 @@ +""" +Locally Optimal Block Preconditioned Conjugate Gradient Method (LOBPCG) + +LOBPCG is a preconditioned eigensolver for large symmetric positive definite +(SPD) generalized eigenproblems. + +Call the function lobpcg - see help for lobpcg.lobpcg. + +""" +from .lobpcg import * + +__all__ = [s for s in dir() if not s.startswith('_')] + +from scipy._lib._testutils import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3926627bb55f9d731650967dcabc0726c4c96717 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/__pycache__/lobpcg.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/__pycache__/lobpcg.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..15afd64d1588c45f4dfd27c30a00a46a8fee271a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/__pycache__/lobpcg.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/lobpcg.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/lobpcg.py new file mode 100644 index 0000000000000000000000000000000000000000..63e8287c971c91fc88afd120c542ceb6f484e9c7 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/lobpcg.py @@ -0,0 +1,1108 @@ +""" +Locally Optimal Block Preconditioned Conjugate Gradient Method (LOBPCG). + +References +---------- +.. [1] A. V. Knyazev (2001), + Toward the Optimal Preconditioned Eigensolver: Locally Optimal + Block Preconditioned Conjugate Gradient Method. + SIAM Journal on Scientific Computing 23, no. 2, + pp. 517-541. :doi:`10.1137/S1064827500366124` + +.. [2] A. V. Knyazev, I. Lashuk, M. E. Argentati, and E. Ovchinnikov (2007), + Block Locally Optimal Preconditioned Eigenvalue Xolvers (BLOPEX) + in hypre and PETSc. :arxiv:`0705.2626` + +.. [3] A. V. Knyazev's C and MATLAB implementations: + https://github.com/lobpcg/blopex +""" + +import warnings +import numpy as np +from scipy.linalg import (inv, eigh, cho_factor, cho_solve, + cholesky, LinAlgError) +from scipy.sparse.linalg import LinearOperator +from scipy.sparse import issparse + +__all__ = ["lobpcg"] + + +def _report_nonhermitian(M, name): + """ + Report if `M` is not a Hermitian matrix given its type. + """ + from scipy.linalg import norm + + md = M - M.T.conj() + nmd = norm(md, 1) + tol = 10 * np.finfo(M.dtype).eps + tol = max(tol, tol * norm(M, 1)) + if nmd > tol: + warnings.warn( + f"Matrix {name} of the type {M.dtype} is not Hermitian: " + f"condition: {nmd} < {tol} fails.", + UserWarning, stacklevel=4 + ) + +def _as2d(ar): + """ + If the input array is 2D return it, if it is 1D, append a dimension, + making it a column vector. + """ + if ar.ndim == 2: + return ar + else: # Assume 1! + aux = np.asarray(ar).reshape((ar.shape[0], 1)) + return aux + + +def _makeMatMat(m): + if m is None: + return None + elif callable(m): + return lambda v: m(v) + else: + return lambda v: m @ v + + +def _matmul_inplace(x, y, verbosityLevel=0): + """Perform 'np.matmul' in-place if possible. + + If some sufficient conditions for inplace matmul are met, do so. + Otherwise try inplace update and fall back to overwrite if that fails. + """ + if x.flags["CARRAY"] and x.shape[1] == y.shape[1] and x.dtype == y.dtype: + # conditions where we can guarantee that inplace updates will work; + # i.e. x is not a view/slice, x & y have compatible dtypes, and the + # shape of the result of x @ y matches the shape of x. + np.matmul(x, y, out=x) + else: + # ideally, we'd have an exhaustive list of conditions above when + # inplace updates are possible; since we don't, we opportunistically + # try if it works, and fall back to overwriting if necessary + try: + np.matmul(x, y, out=x) + except Exception: + if verbosityLevel: + warnings.warn( + "Inplace update of x = x @ y failed, " + "x needs to be overwritten.", + UserWarning, stacklevel=3 + ) + x = x @ y + return x + + +def _applyConstraints(blockVectorV, factYBY, blockVectorBY, blockVectorY): + """Changes blockVectorV in-place.""" + YBV = blockVectorBY.T.conj() @ blockVectorV + tmp = cho_solve(factYBY, YBV) + blockVectorV -= blockVectorY @ tmp + + +def _b_orthonormalize(B, blockVectorV, blockVectorBV=None, + verbosityLevel=0): + """in-place B-orthonormalize the given block vector using Cholesky.""" + if blockVectorBV is None: + if B is None: + blockVectorBV = blockVectorV + else: + try: + blockVectorBV = B(blockVectorV) + except Exception as e: + if verbosityLevel: + warnings.warn( + f"Secondary MatMul call failed with error\n" + f"{e}\n", + UserWarning, stacklevel=3 + ) + return None, None, None + if blockVectorBV.shape != blockVectorV.shape: + raise ValueError( + f"The shape {blockVectorV.shape} " + f"of the orthogonalized matrix not preserved\n" + f"and changed to {blockVectorBV.shape} " + f"after multiplying by the secondary matrix.\n" + ) + + VBV = blockVectorV.T.conj() @ blockVectorBV + try: + # VBV is a Cholesky factor from now on... + VBV = cholesky(VBV, overwrite_a=True) + VBV = inv(VBV, overwrite_a=True) + blockVectorV = _matmul_inplace( + blockVectorV, VBV, + verbosityLevel=verbosityLevel + ) + if B is not None: + blockVectorBV = _matmul_inplace( + blockVectorBV, VBV, + verbosityLevel=verbosityLevel + ) + return blockVectorV, blockVectorBV, VBV + except LinAlgError: + if verbosityLevel: + warnings.warn( + "Cholesky has failed.", + UserWarning, stacklevel=3 + ) + return None, None, None + + +def _get_indx(_lambda, num, largest): + """Get `num` indices into `_lambda` depending on `largest` option.""" + ii = np.argsort(_lambda) + if largest: + ii = ii[:-num - 1:-1] + else: + ii = ii[:num] + + return ii + + +def _handle_gramA_gramB_verbosity(gramA, gramB, verbosityLevel): + if verbosityLevel: + _report_nonhermitian(gramA, "gramA") + _report_nonhermitian(gramB, "gramB") + + +def lobpcg( + A, + X, + B=None, + M=None, + Y=None, + tol=None, + maxiter=None, + largest=True, + verbosityLevel=0, + retLambdaHistory=False, + retResidualNormsHistory=False, + restartControl=20, +): + """Locally Optimal Block Preconditioned Conjugate Gradient Method (LOBPCG). + + LOBPCG is a preconditioned eigensolver for large real symmetric and complex + Hermitian definite generalized eigenproblems. + + Parameters + ---------- + A : {sparse matrix, ndarray, LinearOperator, callable object} + The Hermitian linear operator of the problem, usually given by a + sparse matrix. Often called the "stiffness matrix". + X : ndarray, float32 or float64 + Initial approximation to the ``k`` eigenvectors (non-sparse). + If `A` has ``shape=(n,n)`` then `X` must have ``shape=(n,k)``. + B : {sparse matrix, ndarray, LinearOperator, callable object} + Optional. By default ``B = None``, which is equivalent to identity. + The right hand side operator in a generalized eigenproblem if present. + Often called the "mass matrix". Must be Hermitian positive definite. + M : {sparse matrix, ndarray, LinearOperator, callable object} + Optional. By default ``M = None``, which is equivalent to identity. + Preconditioner aiming to accelerate convergence. + Y : ndarray, float32 or float64, default: None + An ``n-by-sizeY`` ndarray of constraints with ``sizeY < n``. + The iterations will be performed in the ``B``-orthogonal complement + of the column-space of `Y`. `Y` must be full rank if present. + tol : scalar, optional + The default is ``tol=n*sqrt(eps)``. + Solver tolerance for the stopping criterion. + maxiter : int, default: 20 + Maximum number of iterations. + largest : bool, default: True + When True, solve for the largest eigenvalues, otherwise the smallest. + verbosityLevel : int, optional + By default ``verbosityLevel=0`` no output. + Controls the solver standard/screen output. + retLambdaHistory : bool, default: False + Whether to return iterative eigenvalue history. + retResidualNormsHistory : bool, default: False + Whether to return iterative history of residual norms. + restartControl : int, optional. + Iterations restart if the residuals jump ``2**restartControl`` times + compared to the smallest recorded in ``retResidualNormsHistory``. + The default is ``restartControl=20``, making the restarts rare for + backward compatibility. + + Returns + ------- + lambda : ndarray of the shape ``(k, )``. + Array of ``k`` approximate eigenvalues. + v : ndarray of the same shape as ``X.shape``. + An array of ``k`` approximate eigenvectors. + lambdaHistory : ndarray, optional. + The eigenvalue history, if `retLambdaHistory` is ``True``. + ResidualNormsHistory : ndarray, optional. + The history of residual norms, if `retResidualNormsHistory` + is ``True``. + + Notes + ----- + The iterative loop runs ``maxit=maxiter`` (20 if ``maxit=None``) + iterations at most and finishes earlier if the tolerance is met. + Breaking backward compatibility with the previous version, LOBPCG + now returns the block of iterative vectors with the best accuracy rather + than the last one iterated, as a cure for possible divergence. + + If ``X.dtype == np.float32`` and user-provided operations/multiplications + by `A`, `B`, and `M` all preserve the ``np.float32`` data type, + all the calculations and the output are in ``np.float32``. + + The size of the iteration history output equals to the number of the best + (limited by `maxit`) iterations plus 3: initial, final, and postprocessing. + + If both `retLambdaHistory` and `retResidualNormsHistory` are ``True``, + the return tuple has the following format + ``(lambda, V, lambda history, residual norms history)``. + + In the following ``n`` denotes the matrix size and ``k`` the number + of required eigenvalues (smallest or largest). + + The LOBPCG code internally solves eigenproblems of the size ``3k`` on every + iteration by calling the dense eigensolver `eigh`, so if ``k`` is not + small enough compared to ``n``, it makes no sense to call the LOBPCG code. + Moreover, if one calls the LOBPCG algorithm for ``5k > n``, it would likely + break internally, so the code calls the standard function `eigh` instead. + It is not that ``n`` should be large for the LOBPCG to work, but rather the + ratio ``n / k`` should be large. It you call LOBPCG with ``k=1`` + and ``n=10``, it works though ``n`` is small. The method is intended + for extremely large ``n / k``. + + The convergence speed depends basically on three factors: + + 1. Quality of the initial approximations `X` to the seeking eigenvectors. + Randomly distributed around the origin vectors work well if no better + choice is known. + + 2. Relative separation of the desired eigenvalues from the rest + of the eigenvalues. One can vary ``k`` to improve the separation. + + 3. Proper preconditioning to shrink the spectral spread. + For example, a rod vibration test problem (under tests + directory) is ill-conditioned for large ``n``, so convergence will be + slow, unless efficient preconditioning is used. For this specific + problem, a good simple preconditioner function would be a linear solve + for `A`, which is easy to code since `A` is tridiagonal. + + References + ---------- + .. [1] A. V. Knyazev (2001), + Toward the Optimal Preconditioned Eigensolver: Locally Optimal + Block Preconditioned Conjugate Gradient Method. + SIAM Journal on Scientific Computing 23, no. 2, + pp. 517-541. :doi:`10.1137/S1064827500366124` + + .. [2] A. V. Knyazev, I. Lashuk, M. E. Argentati, and E. Ovchinnikov + (2007), Block Locally Optimal Preconditioned Eigenvalue Xolvers + (BLOPEX) in hypre and PETSc. :arxiv:`0705.2626` + + .. [3] A. V. Knyazev's C and MATLAB implementations: + https://github.com/lobpcg/blopex + + Examples + -------- + Our first example is minimalistic - find the largest eigenvalue of + a diagonal matrix by solving the non-generalized eigenvalue problem + ``A x = lambda x`` without constraints or preconditioning. + + >>> import numpy as np + >>> from scipy.sparse import diags_array + >>> from scipy.sparse.linalg import LinearOperator, aslinearoperator + >>> from scipy.sparse.linalg import lobpcg + + The square matrix size is + + >>> n = 100 + + and its diagonal entries are 1, ..., 100 defined by + + >>> vals = np.arange(1, n + 1).astype(np.int16) + + The first mandatory input parameter in this test is + the sparse diagonal matrix `A` + of the eigenvalue problem ``A x = lambda x`` to solve. + + >>> A = diags_array(vals, offsets=0, shape=(n, n), dtype=None) + >>> A.toarray() + array([[ 1, 0, 0, ..., 0, 0, 0], + [ 0, 2, 0, ..., 0, 0, 0], + [ 0, 0, 3, ..., 0, 0, 0], + ..., + [ 0, 0, 0, ..., 98, 0, 0], + [ 0, 0, 0, ..., 0, 99, 0], + [ 0, 0, 0, ..., 0, 0, 100]], shape=(100, 100), dtype=int16) + + The second mandatory input parameter `X` is a 2D array with the + row dimension determining the number of requested eigenvalues. + `X` is an initial guess for targeted eigenvectors. + `X` must have linearly independent columns. + If no initial approximations available, randomly oriented vectors + commonly work best, e.g., with components normally distributed + around zero or uniformly distributed on the interval [-1 1]. + Setting the initial approximations to dtype ``np.float32`` + forces all iterative values to dtype ``np.float32`` speeding up + the run while still allowing accurate eigenvalue computations. + + >>> k = 1 + >>> rng = np.random.default_rng() + >>> X = rng.normal(size=(n, k)) + >>> X = X.astype(np.float32) + + >>> eigenvalues, _ = lobpcg(A, X, maxiter=60) + >>> eigenvalues + array([100.], dtype=float32) + + `lobpcg` needs only access the matrix product with `A` rather + then the matrix itself. Since the matrix `A` is diagonal in + this example, one can write a function of the matrix product + ``A @ X`` using the diagonal values ``vals`` only, e.g., by + element-wise multiplication with broadcasting in the lambda-function + + >>> A_lambda = lambda X: vals[:, np.newaxis] * X + + or the regular function + + >>> def A_matmat(X): + ... return vals[:, np.newaxis] * X + + and use the handle to one of these callables as an input + + >>> eigenvalues, _ = lobpcg(A_lambda, X, maxiter=60) + >>> eigenvalues + array([100.], dtype=float32) + >>> eigenvalues, _ = lobpcg(A_matmat, X, maxiter=60) + >>> eigenvalues + array([100.], dtype=float32) + + The traditional callable `LinearOperator` is no longer + necessary but still supported as the input to `lobpcg`. + Specifying ``matmat=A_matmat`` explicitly improves performance. + + >>> A_lo = LinearOperator((n, n), matvec=A_matmat, matmat=A_matmat, dtype=np.int16) + >>> eigenvalues, _ = lobpcg(A_lo, X, maxiter=80) + >>> eigenvalues + array([100.], dtype=float32) + + The least efficient callable option is `aslinearoperator`: + + >>> eigenvalues, _ = lobpcg(aslinearoperator(A), X, maxiter=80) + >>> eigenvalues + array([100.], dtype=float32) + + We now switch to computing the three smallest eigenvalues specifying + + >>> k = 3 + >>> X = np.random.default_rng().normal(size=(n, k)) + + and ``largest=False`` parameter + + >>> eigenvalues, _ = lobpcg(A, X, largest=False, maxiter=90) + >>> print(eigenvalues) + [1. 2. 3.] + + The next example illustrates computing 3 smallest eigenvalues of + the same matrix `A` given by the function handle ``A_matmat`` but + with constraints and preconditioning. + + Constraints - an optional input parameter is a 2D array comprising + of column vectors that the eigenvectors must be orthogonal to + + >>> Y = np.eye(n, 3) + + The preconditioner acts as the inverse of `A` in this example, but + in the reduced precision ``np.float32`` even though the initial `X` + and thus all iterates and the output are in full ``np.float64``. + + >>> inv_vals = 1./vals + >>> inv_vals = inv_vals.astype(np.float32) + >>> M = lambda X: inv_vals[:, np.newaxis] * X + + Let us now solve the eigenvalue problem for the matrix `A` first + without preconditioning requesting 80 iterations + + >>> eigenvalues, _ = lobpcg(A_matmat, X, Y=Y, largest=False, maxiter=80) + >>> eigenvalues + array([4., 5., 6.]) + >>> eigenvalues.dtype + dtype('float64') + + With preconditioning we need only 20 iterations from the same `X` + + >>> eigenvalues, _ = lobpcg(A_matmat, X, Y=Y, M=M, largest=False, maxiter=20) + >>> eigenvalues + array([4., 5., 6.]) + + Note that the vectors passed in `Y` are the eigenvectors of the 3 + smallest eigenvalues. The results returned above are orthogonal to those. + + The primary matrix `A` may be indefinite, e.g., after shifting + ``vals`` by 50 from 1, ..., 100 to -49, ..., 50, we still can compute + the 3 smallest or largest eigenvalues. + + >>> vals = vals - 50 + >>> X = rng.normal(size=(n, k)) + >>> eigenvalues, _ = lobpcg(A_matmat, X, largest=False, maxiter=99) + >>> eigenvalues + array([-49., -48., -47.]) + >>> eigenvalues, _ = lobpcg(A_matmat, X, largest=True, maxiter=99) + >>> eigenvalues + array([50., 49., 48.]) + + """ + blockVectorX = X + bestblockVectorX = blockVectorX + blockVectorY = Y + residualTolerance = tol + if maxiter is None: + maxiter = 20 + + bestIterationNumber = maxiter + + sizeY = 0 + if blockVectorY is not None: + if len(blockVectorY.shape) != 2: + warnings.warn( + f"Expected rank-2 array for argument Y, instead got " + f"{len(blockVectorY.shape)}, " + f"so ignore it and use no constraints.", + UserWarning, stacklevel=2 + ) + blockVectorY = None + else: + sizeY = blockVectorY.shape[1] + + # Block size. + if blockVectorX is None: + raise ValueError("The mandatory initial matrix X cannot be None") + if len(blockVectorX.shape) != 2: + raise ValueError("expected rank-2 array for argument X") + + n, sizeX = blockVectorX.shape + + # Data type of iterates, determined by X, must be inexact + if not np.issubdtype(blockVectorX.dtype, np.inexact): + warnings.warn( + f"Data type for argument X is {blockVectorX.dtype}, " + f"which is not inexact, so casted to np.float32.", + UserWarning, stacklevel=2 + ) + blockVectorX = np.asarray(blockVectorX, dtype=np.float32) + + if retLambdaHistory: + lambdaHistory = np.zeros((maxiter + 3, sizeX), + dtype=blockVectorX.dtype) + if retResidualNormsHistory: + residualNormsHistory = np.zeros((maxiter + 3, sizeX), + dtype=blockVectorX.dtype) + + if verbosityLevel: + aux = "Solving " + if B is None: + aux += "standard" + else: + aux += "generalized" + aux += " eigenvalue problem with" + if M is None: + aux += "out" + aux += " preconditioning\n\n" + aux += f"matrix size {n}\n" + aux += f"block size {sizeX}\n\n" + if blockVectorY is None: + aux += "No constraints\n\n" + else: + if sizeY > 1: + aux += f"{sizeY} constraints\n\n" + else: + aux += f"{sizeY} constraint\n\n" + print(aux) + + if (n - sizeY) < (5 * sizeX): + warnings.warn( + f"The problem size {n} minus the constraints size {sizeY} " + f"is too small relative to the block size {sizeX}. " + f"Using a dense eigensolver instead of LOBPCG iterations." + f"No output of the history of the iterations.", + UserWarning, stacklevel=2 + ) + + sizeX = min(sizeX, n) + + if blockVectorY is not None: + raise NotImplementedError( + "The dense eigensolver does not support constraints." + ) + + # Define the closed range of indices of eigenvalues to return. + if largest: + eigvals = (n - sizeX, n - 1) + else: + eigvals = (0, sizeX - 1) + + try: + if isinstance(A, LinearOperator): + A = A(np.eye(n, dtype=int)) + elif callable(A): + A = A(np.eye(n, dtype=int)) + if A.shape != (n, n): + raise ValueError( + f"The shape {A.shape} of the primary matrix\n" + f"defined by a callable object is wrong.\n" + ) + elif issparse(A): + A = A.toarray() + else: + A = np.asarray(A) + except Exception as e: + raise Exception( + f"Primary MatMul call failed with error\n" + f"{e}\n") + + if B is not None: + try: + if isinstance(B, LinearOperator): + B = B(np.eye(n, dtype=int)) + elif callable(B): + B = B(np.eye(n, dtype=int)) + if B.shape != (n, n): + raise ValueError( + f"The shape {B.shape} of the secondary matrix\n" + f"defined by a callable object is wrong.\n" + ) + elif issparse(B): + B = B.toarray() + else: + B = np.asarray(B) + except Exception as e: + raise Exception( + f"Secondary MatMul call failed with error\n" + f"{e}\n") + + try: + vals, vecs = eigh(A, + B, + subset_by_index=eigvals, + check_finite=False) + if largest: + # Reverse order to be compatible with eigs() in 'LM' mode. + vals = vals[::-1] + vecs = vecs[:, ::-1] + + return vals, vecs + except Exception as e: + raise Exception( + f"Dense eigensolver failed with error\n" + f"{e}\n" + ) + + if (residualTolerance is None) or (residualTolerance <= 0.0): + residualTolerance = np.sqrt(np.finfo(blockVectorX.dtype).eps) * n + + A = _makeMatMat(A) + B = _makeMatMat(B) + M = _makeMatMat(M) + + # Apply constraints to X. + if blockVectorY is not None: + + if B is not None: + blockVectorBY = B(blockVectorY) + if blockVectorBY.shape != blockVectorY.shape: + raise ValueError( + f"The shape {blockVectorY.shape} " + f"of the constraint not preserved\n" + f"and changed to {blockVectorBY.shape} " + f"after multiplying by the secondary matrix.\n" + ) + else: + blockVectorBY = blockVectorY + + # gramYBY is a dense array. + gramYBY = blockVectorY.T.conj() @ blockVectorBY + try: + # gramYBY is a Cholesky factor from now on... + gramYBY = cho_factor(gramYBY, overwrite_a=True) + except LinAlgError as e: + raise ValueError("Linearly dependent constraints") from e + + _applyConstraints(blockVectorX, gramYBY, blockVectorBY, blockVectorY) + + ## + # B-orthonormalize X. + blockVectorX, blockVectorBX, _ = _b_orthonormalize( + B, blockVectorX, verbosityLevel=verbosityLevel) + if blockVectorX is None: + raise ValueError("Linearly dependent initial approximations") + + ## + # Compute the initial Ritz vectors: solve the eigenproblem. + blockVectorAX = A(blockVectorX) + if blockVectorAX.shape != blockVectorX.shape: + raise ValueError( + f"The shape {blockVectorX.shape} " + f"of the initial approximations not preserved\n" + f"and changed to {blockVectorAX.shape} " + f"after multiplying by the primary matrix.\n" + ) + + gramXAX = blockVectorX.T.conj() @ blockVectorAX + + _lambda, eigBlockVector = eigh(gramXAX, check_finite=False) + ii = _get_indx(_lambda, sizeX, largest) + _lambda = _lambda[ii] + if retLambdaHistory: + lambdaHistory[0, :] = _lambda + + eigBlockVector = np.asarray(eigBlockVector[:, ii]) + blockVectorX = _matmul_inplace( + blockVectorX, eigBlockVector, + verbosityLevel=verbosityLevel + ) + blockVectorAX = _matmul_inplace( + blockVectorAX, eigBlockVector, + verbosityLevel=verbosityLevel + ) + if B is not None: + blockVectorBX = _matmul_inplace( + blockVectorBX, eigBlockVector, + verbosityLevel=verbosityLevel + ) + + ## + # Active index set. + activeMask = np.ones((sizeX,), dtype=bool) + + ## + # Main iteration loop. + + blockVectorP = None # set during iteration + blockVectorAP = None + blockVectorBP = None + + smallestResidualNorm = np.abs(np.finfo(blockVectorX.dtype).max) + + iterationNumber = -1 + restart = True + forcedRestart = False + explicitGramFlag = False + while iterationNumber < maxiter: + iterationNumber += 1 + + if B is not None: + aux = blockVectorBX * _lambda[np.newaxis, :] + else: + aux = blockVectorX * _lambda[np.newaxis, :] + + blockVectorR = blockVectorAX - aux + + aux = np.sum(blockVectorR.conj() * blockVectorR, 0) + residualNorms = np.sqrt(np.abs(aux)) + if retResidualNormsHistory: + residualNormsHistory[iterationNumber, :] = residualNorms + residualNorm = np.sum(np.abs(residualNorms)) / sizeX + + if residualNorm < smallestResidualNorm: + smallestResidualNorm = residualNorm + bestIterationNumber = iterationNumber + bestblockVectorX = blockVectorX + elif residualNorm > 2**restartControl * smallestResidualNorm: + forcedRestart = True + blockVectorAX = A(blockVectorX) + if blockVectorAX.shape != blockVectorX.shape: + raise ValueError( + f"The shape {blockVectorX.shape} " + f"of the restarted iterate not preserved\n" + f"and changed to {blockVectorAX.shape} " + f"after multiplying by the primary matrix.\n" + ) + if B is not None: + blockVectorBX = B(blockVectorX) + if blockVectorBX.shape != blockVectorX.shape: + raise ValueError( + f"The shape {blockVectorX.shape} " + f"of the restarted iterate not preserved\n" + f"and changed to {blockVectorBX.shape} " + f"after multiplying by the secondary matrix.\n" + ) + + ii = np.where(residualNorms > residualTolerance, True, False) + activeMask = activeMask & ii + currentBlockSize = activeMask.sum() + + if verbosityLevel: + print(f"iteration {iterationNumber}") + print(f"current block size: {currentBlockSize}") + print(f"eigenvalue(s):\n{_lambda}") + print(f"residual norm(s):\n{residualNorms}") + + if currentBlockSize == 0: + break + + activeBlockVectorR = _as2d(blockVectorR[:, activeMask]) + + if iterationNumber > 0: + activeBlockVectorP = _as2d(blockVectorP[:, activeMask]) + activeBlockVectorAP = _as2d(blockVectorAP[:, activeMask]) + if B is not None: + activeBlockVectorBP = _as2d(blockVectorBP[:, activeMask]) + + if M is not None: + # Apply preconditioner T to the active residuals. + activeBlockVectorR = M(activeBlockVectorR) + + ## + # Apply constraints to the preconditioned residuals. + if blockVectorY is not None: + _applyConstraints(activeBlockVectorR, + gramYBY, + blockVectorBY, + blockVectorY) + + ## + # B-orthogonalize the preconditioned residuals to X. + if B is not None: + activeBlockVectorR = activeBlockVectorR - ( + blockVectorX @ + (blockVectorBX.T.conj() @ activeBlockVectorR) + ) + else: + activeBlockVectorR = activeBlockVectorR - ( + blockVectorX @ + (blockVectorX.T.conj() @ activeBlockVectorR) + ) + + ## + # B-orthonormalize the preconditioned residuals. + aux = _b_orthonormalize( + B, activeBlockVectorR, verbosityLevel=verbosityLevel) + activeBlockVectorR, activeBlockVectorBR, _ = aux + + if activeBlockVectorR is None: + warnings.warn( + f"Failed at iteration {iterationNumber} with accuracies " + f"{residualNorms}\n not reaching the requested " + f"tolerance {residualTolerance}.", + UserWarning, stacklevel=2 + ) + break + activeBlockVectorAR = A(activeBlockVectorR) + + if iterationNumber > 0: + if B is not None: + aux = _b_orthonormalize( + B, activeBlockVectorP, activeBlockVectorBP, + verbosityLevel=verbosityLevel + ) + activeBlockVectorP, activeBlockVectorBP, invR = aux + else: + aux = _b_orthonormalize(B, activeBlockVectorP, + verbosityLevel=verbosityLevel) + activeBlockVectorP, _, invR = aux + # Function _b_orthonormalize returns None if Cholesky fails + if activeBlockVectorP is not None: + activeBlockVectorAP = _matmul_inplace( + activeBlockVectorAP, invR, + verbosityLevel=verbosityLevel + ) + restart = forcedRestart + else: + restart = True + + ## + # Perform the Rayleigh Ritz Procedure: + # Compute symmetric Gram matrices: + + if activeBlockVectorAR.dtype == "float32": + myeps = 1 + else: + myeps = np.sqrt(np.finfo(activeBlockVectorR.dtype).eps) + + if residualNorms.max() > myeps and not explicitGramFlag: + explicitGramFlag = False + else: + # Once explicitGramFlag, forever explicitGramFlag. + explicitGramFlag = True + + # Shared memory assignments to simplify the code + if B is None: + blockVectorBX = blockVectorX + activeBlockVectorBR = activeBlockVectorR + if not restart: + activeBlockVectorBP = activeBlockVectorP + + # Common submatrices: + gramXAR = np.dot(blockVectorX.T.conj(), activeBlockVectorAR) + gramRAR = np.dot(activeBlockVectorR.T.conj(), activeBlockVectorAR) + + gramDtype = activeBlockVectorAR.dtype + if explicitGramFlag: + gramRAR = (gramRAR + gramRAR.T.conj()) / 2 + gramXAX = np.dot(blockVectorX.T.conj(), blockVectorAX) + gramXAX = (gramXAX + gramXAX.T.conj()) / 2 + gramXBX = np.dot(blockVectorX.T.conj(), blockVectorBX) + gramRBR = np.dot(activeBlockVectorR.T.conj(), activeBlockVectorBR) + gramXBR = np.dot(blockVectorX.T.conj(), activeBlockVectorBR) + else: + gramXAX = np.diag(_lambda).astype(gramDtype) + gramXBX = np.eye(sizeX, dtype=gramDtype) + gramRBR = np.eye(currentBlockSize, dtype=gramDtype) + gramXBR = np.zeros((sizeX, currentBlockSize), dtype=gramDtype) + + if not restart: + gramXAP = np.dot(blockVectorX.T.conj(), activeBlockVectorAP) + gramRAP = np.dot(activeBlockVectorR.T.conj(), activeBlockVectorAP) + gramPAP = np.dot(activeBlockVectorP.T.conj(), activeBlockVectorAP) + gramXBP = np.dot(blockVectorX.T.conj(), activeBlockVectorBP) + gramRBP = np.dot(activeBlockVectorR.T.conj(), activeBlockVectorBP) + if explicitGramFlag: + gramPAP = (gramPAP + gramPAP.T.conj()) / 2 + gramPBP = np.dot(activeBlockVectorP.T.conj(), + activeBlockVectorBP) + else: + gramPBP = np.eye(currentBlockSize, dtype=gramDtype) + + gramA = np.block( + [ + [gramXAX, gramXAR, gramXAP], + [gramXAR.T.conj(), gramRAR, gramRAP], + [gramXAP.T.conj(), gramRAP.T.conj(), gramPAP], + ] + ) + gramB = np.block( + [ + [gramXBX, gramXBR, gramXBP], + [gramXBR.T.conj(), gramRBR, gramRBP], + [gramXBP.T.conj(), gramRBP.T.conj(), gramPBP], + ] + ) + + _handle_gramA_gramB_verbosity(gramA, gramB, verbosityLevel) + + try: + _lambda, eigBlockVector = eigh(gramA, + gramB, + check_finite=False) + except LinAlgError as e: + # raise ValueError("eigh failed in lobpcg iterations") from e + if verbosityLevel: + warnings.warn( + f"eigh failed at iteration {iterationNumber} \n" + f"with error {e} causing a restart.\n", + UserWarning, stacklevel=2 + ) + # try again after dropping the direction vectors P from RR + restart = True + + if restart: + gramA = np.block([[gramXAX, gramXAR], [gramXAR.T.conj(), gramRAR]]) + gramB = np.block([[gramXBX, gramXBR], [gramXBR.T.conj(), gramRBR]]) + + _handle_gramA_gramB_verbosity(gramA, gramB, verbosityLevel) + + try: + _lambda, eigBlockVector = eigh(gramA, + gramB, + check_finite=False) + except LinAlgError as e: + # raise ValueError("eigh failed in lobpcg iterations") from e + warnings.warn( + f"eigh failed at iteration {iterationNumber} with error\n" + f"{e}\n", + UserWarning, stacklevel=2 + ) + break + + ii = _get_indx(_lambda, sizeX, largest) + _lambda = _lambda[ii] + eigBlockVector = eigBlockVector[:, ii] + if retLambdaHistory: + lambdaHistory[iterationNumber + 1, :] = _lambda + + # Compute Ritz vectors. + if B is not None: + if not restart: + eigBlockVectorX = eigBlockVector[:sizeX] + eigBlockVectorR = eigBlockVector[sizeX: + sizeX + currentBlockSize] + eigBlockVectorP = eigBlockVector[sizeX + currentBlockSize:] + + pp = np.dot(activeBlockVectorR, eigBlockVectorR) + pp += np.dot(activeBlockVectorP, eigBlockVectorP) + + app = np.dot(activeBlockVectorAR, eigBlockVectorR) + app += np.dot(activeBlockVectorAP, eigBlockVectorP) + + bpp = np.dot(activeBlockVectorBR, eigBlockVectorR) + bpp += np.dot(activeBlockVectorBP, eigBlockVectorP) + else: + eigBlockVectorX = eigBlockVector[:sizeX] + eigBlockVectorR = eigBlockVector[sizeX:] + + pp = np.dot(activeBlockVectorR, eigBlockVectorR) + app = np.dot(activeBlockVectorAR, eigBlockVectorR) + bpp = np.dot(activeBlockVectorBR, eigBlockVectorR) + + blockVectorX = np.dot(blockVectorX, eigBlockVectorX) + pp + blockVectorAX = np.dot(blockVectorAX, eigBlockVectorX) + app + blockVectorBX = np.dot(blockVectorBX, eigBlockVectorX) + bpp + + blockVectorP, blockVectorAP, blockVectorBP = pp, app, bpp + + else: + if not restart: + eigBlockVectorX = eigBlockVector[:sizeX] + eigBlockVectorR = eigBlockVector[sizeX: + sizeX + currentBlockSize] + eigBlockVectorP = eigBlockVector[sizeX + currentBlockSize:] + + pp = np.dot(activeBlockVectorR, eigBlockVectorR) + pp += np.dot(activeBlockVectorP, eigBlockVectorP) + + app = np.dot(activeBlockVectorAR, eigBlockVectorR) + app += np.dot(activeBlockVectorAP, eigBlockVectorP) + else: + eigBlockVectorX = eigBlockVector[:sizeX] + eigBlockVectorR = eigBlockVector[sizeX:] + + pp = np.dot(activeBlockVectorR, eigBlockVectorR) + app = np.dot(activeBlockVectorAR, eigBlockVectorR) + + blockVectorX = np.dot(blockVectorX, eigBlockVectorX) + pp + blockVectorAX = np.dot(blockVectorAX, eigBlockVectorX) + app + + blockVectorP, blockVectorAP = pp, app + + if B is not None: + aux = blockVectorBX * _lambda[np.newaxis, :] + else: + aux = blockVectorX * _lambda[np.newaxis, :] + + blockVectorR = blockVectorAX - aux + + aux = np.sum(blockVectorR.conj() * blockVectorR, 0) + residualNorms = np.sqrt(np.abs(aux)) + # Use old lambda in case of early loop exit. + if retLambdaHistory: + lambdaHistory[iterationNumber + 1, :] = _lambda + if retResidualNormsHistory: + residualNormsHistory[iterationNumber + 1, :] = residualNorms + residualNorm = np.sum(np.abs(residualNorms)) / sizeX + if residualNorm < smallestResidualNorm: + smallestResidualNorm = residualNorm + bestIterationNumber = iterationNumber + 1 + bestblockVectorX = blockVectorX + + if np.max(np.abs(residualNorms)) > residualTolerance: + warnings.warn( + f"Exited at iteration {iterationNumber} with accuracies \n" + f"{residualNorms}\n" + f"not reaching the requested tolerance {residualTolerance}.\n" + f"Use iteration {bestIterationNumber} instead with accuracy \n" + f"{smallestResidualNorm}.\n", + UserWarning, stacklevel=2 + ) + + if verbosityLevel: + print(f"Final iterative eigenvalue(s):\n{_lambda}") + print(f"Final iterative residual norm(s):\n{residualNorms}") + + blockVectorX = bestblockVectorX + # Making eigenvectors "exactly" satisfy the blockVectorY constrains + if blockVectorY is not None: + _applyConstraints(blockVectorX, + gramYBY, + blockVectorBY, + blockVectorY) + + # Making eigenvectors "exactly" othonormalized by final "exact" RR + blockVectorAX = A(blockVectorX) + if blockVectorAX.shape != blockVectorX.shape: + raise ValueError( + f"The shape {blockVectorX.shape} " + f"of the postprocessing iterate not preserved\n" + f"and changed to {blockVectorAX.shape} " + f"after multiplying by the primary matrix.\n" + ) + gramXAX = np.dot(blockVectorX.T.conj(), blockVectorAX) + + blockVectorBX = blockVectorX + if B is not None: + blockVectorBX = B(blockVectorX) + if blockVectorBX.shape != blockVectorX.shape: + raise ValueError( + f"The shape {blockVectorX.shape} " + f"of the postprocessing iterate not preserved\n" + f"and changed to {blockVectorBX.shape} " + f"after multiplying by the secondary matrix.\n" + ) + + gramXBX = np.dot(blockVectorX.T.conj(), blockVectorBX) + _handle_gramA_gramB_verbosity(gramXAX, gramXBX, verbosityLevel) + gramXAX = (gramXAX + gramXAX.T.conj()) / 2 + gramXBX = (gramXBX + gramXBX.T.conj()) / 2 + try: + _lambda, eigBlockVector = eigh(gramXAX, + gramXBX, + check_finite=False) + except LinAlgError as e: + raise ValueError("eigh has failed in lobpcg postprocessing") from e + + ii = _get_indx(_lambda, sizeX, largest) + _lambda = _lambda[ii] + eigBlockVector = np.asarray(eigBlockVector[:, ii]) + + blockVectorX = np.dot(blockVectorX, eigBlockVector) + blockVectorAX = np.dot(blockVectorAX, eigBlockVector) + + if B is not None: + blockVectorBX = np.dot(blockVectorBX, eigBlockVector) + aux = blockVectorBX * _lambda[np.newaxis, :] + else: + aux = blockVectorX * _lambda[np.newaxis, :] + + blockVectorR = blockVectorAX - aux + + aux = np.sum(blockVectorR.conj() * blockVectorR, 0) + residualNorms = np.sqrt(np.abs(aux)) + + if retLambdaHistory: + lambdaHistory[bestIterationNumber + 1, :] = _lambda + if retResidualNormsHistory: + residualNormsHistory[bestIterationNumber + 1, :] = residualNorms + + if retLambdaHistory: + lambdaHistory = lambdaHistory[ + : bestIterationNumber + 2, :] + if retResidualNormsHistory: + residualNormsHistory = residualNormsHistory[ + : bestIterationNumber + 2, :] + + if np.max(np.abs(residualNorms)) > residualTolerance: + warnings.warn( + f"Exited postprocessing with accuracies \n" + f"{residualNorms}\n" + f"not reaching the requested tolerance {residualTolerance}.", + UserWarning, stacklevel=2 + ) + + if verbosityLevel: + print(f"Final postprocessing eigenvalue(s):\n{_lambda}") + print(f"Final residual norm(s):\n{residualNorms}") + + if retLambdaHistory: + lambdaHistory = np.vsplit(lambdaHistory, np.shape(lambdaHistory)[0]) + lambdaHistory = [np.squeeze(i) for i in lambdaHistory] + if retResidualNormsHistory: + residualNormsHistory = np.vsplit(residualNormsHistory, + np.shape(residualNormsHistory)[0]) + residualNormsHistory = [np.squeeze(i) for i in residualNormsHistory] + + if retLambdaHistory: + if retResidualNormsHistory: + return _lambda, blockVectorX, lambdaHistory, residualNormsHistory + else: + return _lambda, blockVectorX, lambdaHistory + else: + if retResidualNormsHistory: + return _lambda, blockVectorX, residualNormsHistory + else: + return _lambda, blockVectorX diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..122b8c0bf336b629d035de0da8f4a25ad3493081 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/tests/__pycache__/test_lobpcg.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/tests/__pycache__/test_lobpcg.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..78281e8c3c49422ea3e8b19045f2401f8ab0f63c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/tests/__pycache__/test_lobpcg.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/tests/test_lobpcg.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/tests/test_lobpcg.py new file mode 100644 index 0000000000000000000000000000000000000000..c9027e7611656206aa2879ce72d2c411bdb17257 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/lobpcg/tests/test_lobpcg.py @@ -0,0 +1,723 @@ +""" Test functions for the sparse.linalg._eigen.lobpcg module +""" + +import itertools +import platform +import sys +import pytest +import numpy as np +from numpy import ones, r_, diag +from numpy.testing import (assert_almost_equal, assert_equal, + assert_allclose, assert_array_less) + +from scipy import sparse +from scipy.linalg import (eigh, toeplitz, + cholesky_banded, cho_solve_banded) +from scipy.sparse import dia_array, eye_array, csr_array +from scipy.sparse.linalg import eigsh, LinearOperator +from scipy.sparse.linalg._eigen.lobpcg import lobpcg +from scipy.sparse.linalg._eigen.lobpcg.lobpcg import _b_orthonormalize +from scipy._lib._util import np_long, np_ulong +from scipy.sparse.linalg._special_sparse_arrays import (Sakurai, + MikotaPair) + +_IS_32BIT = (sys.maxsize < 2**32) + +INT_DTYPES = (np.intc, np_long, np.longlong, np.uintc, np_ulong, np.ulonglong) +# np.half is unsupported on many test systems so excluded +REAL_DTYPES = (np.float32, np.float64, np.longdouble) +COMPLEX_DTYPES = (np.complex64, np.complex128, np.clongdouble) +INEXACTDTYPES = REAL_DTYPES + COMPLEX_DTYPES +ALLDTYPES = INT_DTYPES + INEXACTDTYPES + + +def sign_align(A, B): + """Align signs of columns of A match those of B: column-wise remove + sign of A by multiplying with its sign then multiply in sign of B. + """ + return np.array([col_A * np.sign(col_A[0]) * np.sign(col_B[0]) + for col_A, col_B in zip(A.T, B.T)]).T + +def ElasticRod(n): + """Build the matrices for the generalized eigenvalue problem of the + fixed-free elastic rod vibration model. + """ + L = 1.0 + le = L/n + rho = 7.85e3 + S = 1.e-4 + E = 2.1e11 + mass = rho*S*le/6. + k = E*S/le + A = k*(diag(r_[2.*ones(n-1), 1])-diag(ones(n-1), 1)-diag(ones(n-1), -1)) + B = mass*(diag(r_[4.*ones(n-1), 2])+diag(ones(n-1), 1)+diag(ones(n-1), -1)) + return A, B + + +@pytest.mark.filterwarnings("ignore:The problem size") +@pytest.mark.parametrize("n", [10, 20]) +@pytest.mark.filterwarnings("ignore:Exited at iteration") +@pytest.mark.filterwarnings("ignore:Exited postprocessing") +def test_ElasticRod(n): + """Check eigh vs. lobpcg consistency for elastic rod model. + """ + A, B = ElasticRod(n) + m = 2 + rnd = np.random.RandomState(0) + X = rnd.standard_normal((n, m)) + eigvals, _ = lobpcg(A, X, B=B, tol=1e-2, maxiter=50, largest=False) + eigvals.sort() + w, _ = eigh(A, b=B) + w.sort() + assert_almost_equal(w[:int(m/2)], eigvals[:int(m/2)], decimal=2) + + +@pytest.mark.parametrize("n", [50]) +@pytest.mark.parametrize("m", [1, 2, 10]) +@pytest.mark.filterwarnings("ignore:Casting complex values to real") +@pytest.mark.filterwarnings("ignore:An ill-conditioned matrix") +@pytest.mark.parametrize("Vdtype", INEXACTDTYPES) +@pytest.mark.parametrize("Bdtype", ALLDTYPES) +@pytest.mark.parametrize("BVdtype", INEXACTDTYPES) +def test_b_orthonormalize(n, m, Vdtype, Bdtype, BVdtype): + """Test B-orthonormalization by Cholesky with callable 'B'. + The function '_b_orthonormalize' is key in LOBPCG but may + lead to numerical instabilities. The input vectors are often + badly scaled, so the function needs scale-invariant Cholesky; + see https://netlib.org/lapack/lawnspdf/lawn14.pdf. + """ + rnd = np.random.RandomState(0) + X = rnd.standard_normal((n, m)).astype(Vdtype) + Xcopy = np.copy(X) + vals = np.arange(1, n+1, dtype=float) + B = dia_array(([vals], [0]), shape=(n, n)).astype(Bdtype) + BX = B @ X + BX = BX.astype(BVdtype) + is_all_complex = (np.issubdtype(Vdtype, np.complexfloating) and + np.issubdtype(BVdtype, np.complexfloating)) + is_all_notcomplex = (not np.issubdtype(Vdtype, np.complexfloating) and + not np.issubdtype(Bdtype, np.complexfloating) and + not np.issubdtype(BVdtype, np.complexfloating)) + + # All complex or all not complex can calculate in-place + check_inplace = is_all_complex or is_all_notcomplex + # np.longdouble tol cannot be achieved on most systems + atol = m * n * max(np.finfo(Vdtype).eps, + np.finfo(BVdtype).eps, + np.finfo(np.float64).eps) + + Xo, BXo, _ = _b_orthonormalize(lambda v: B @ v, X, BX) + if check_inplace: + # Check in-place + assert_equal(X, Xo) + assert_equal(id(X), id(Xo)) + assert_equal(BX, BXo) + assert_equal(id(BX), id(BXo)) + # Check BXo + assert_allclose(B @ Xo, BXo, atol=atol, rtol=atol) + # Check B-orthonormality + assert_allclose(Xo.T.conj() @ B @ Xo, np.identity(m), + atol=atol, rtol=atol) + # Repeat without BX in outputs + X = np.copy(Xcopy) + Xo1, BXo1, _ = _b_orthonormalize(lambda v: B @ v, X) + assert_allclose(Xo, Xo1, atol=atol, rtol=atol) + assert_allclose(BXo, BXo1, atol=atol, rtol=atol) + if check_inplace: + # Check in-place. + assert_equal(X, Xo1) + assert_equal(id(X), id(Xo1)) + # Check BXo1 + assert_allclose(B @ Xo1, BXo1, atol=atol, rtol=atol) + + # Introduce column-scaling in X + scaling = 1.0 / np.geomspace(10, 1e10, num=m) + X = Xcopy * scaling + X = X.astype(Vdtype) + BX = B @ X + BX = BX.astype(BVdtype) + # Check scaling-invariance of Cholesky-based orthonormalization + # XXX: internally, _b_orthonormalize tries to invert an ill-conditioned matrix + Xo1, BXo1, _ = _b_orthonormalize(lambda v: B @ v, X, BX) + # The output should be the same, up the signs of the columns + Xo1 = sign_align(Xo1, Xo) + assert_allclose(Xo, Xo1, atol=atol, rtol=atol) + BXo1 = sign_align(BXo1, BXo) + assert_allclose(BXo, BXo1, atol=atol, rtol=atol) + + +@pytest.mark.filterwarnings("ignore:Exited at iteration 0") +@pytest.mark.filterwarnings("ignore:Exited postprocessing") +def test_nonhermitian_warning(capsys): + """Check the warning of a Ritz matrix being not Hermitian + by feeding a non-Hermitian input matrix. + Also check stdout since verbosityLevel=1 and lack of stderr. + """ + n = 10 + X = np.arange(n * 2).reshape(n, 2).astype(np.float32) + A = np.arange(n * n).reshape(n, n).astype(np.float32) + with pytest.warns(UserWarning, match="Matrix gramA"): + _, _ = lobpcg(A, X, verbosityLevel=1, maxiter=0) + out, err = capsys.readouterr() # Capture output + assert out.startswith("Solving standard eigenvalue") # Test stdout + assert err == '' # Test empty stderr + # Make the matrix symmetric and the UserWarning disappears. + A += A.T + _, _ = lobpcg(A, X, verbosityLevel=1, maxiter=0) + out, err = capsys.readouterr() # Capture output + assert out.startswith("Solving standard eigenvalue") # Test stdout + assert err == '' # Test empty stderr + + +def test_regression(): + """Check the eigenvalue of the identity matrix is one. + """ + # https://mail.python.org/pipermail/scipy-user/2010-October/026944.html + n = 10 + X = np.ones((n, 1)) + A = np.identity(n) + w, _ = lobpcg(A, X) + assert_allclose(w, [1]) + + +@pytest.mark.filterwarnings("ignore:The problem size") +@pytest.mark.parametrize('n, m, m_excluded', [(30, 4, 3), (4, 2, 0)]) +def test_diagonal(n, m, m_excluded): + """Test ``m - m_excluded`` eigenvalues and eigenvectors of + diagonal matrices of the size ``n`` varying matrix formats: + dense array, spare matrix, and ``LinearOperator`` for both + matrixes in the generalized eigenvalue problem ``Av = cBv`` + and for the preconditioner. + """ + rnd = np.random.RandomState(0) + + # Define the generalized eigenvalue problem Av = cBv + # where (c, v) is a generalized eigenpair, + # A is the diagonal matrix whose entries are 1,...n, + # B is the identity matrix. + vals = np.arange(1, n+1, dtype=float) + A_s = dia_array(([vals], [0]), shape=(n, n)) + A_a = A_s.toarray() + + def A_f(x): + return A_s @ x + + A_lo = LinearOperator(matvec=A_f, + matmat=A_f, + shape=(n, n), dtype=float) + + B_a = eye_array(n) + B_s = csr_array(B_a) + + def B_f(x): + return B_a @ x + + B_lo = LinearOperator(matvec=B_f, + matmat=B_f, + shape=(n, n), dtype=float) + + # Let the preconditioner M be the inverse of A. + M_s = dia_array(([1./vals], [0]), shape=(n, n)) + M_a = M_s.toarray() + + def M_f(x): + return M_s @ x + + M_lo = LinearOperator(matvec=M_f, + matmat=M_f, + shape=(n, n), dtype=float) + + # Pick random initial vectors. + X = rnd.normal(size=(n, m)) + + # Require that the returned eigenvectors be in the orthogonal complement + # of the first few standard basis vectors. + if m_excluded > 0: + Y = np.eye(n, m_excluded) + else: + Y = None + + for A in [A_a, A_s, A_lo]: + for B in [B_a, B_s, B_lo]: + for M in [M_a, M_s, M_lo]: + eigvals, vecs = lobpcg(A, X, B, M=M, Y=Y, + maxiter=40, largest=False) + + assert_allclose(eigvals, np.arange(1+m_excluded, + 1+m_excluded+m)) + _check_eigen(A, eigvals, vecs, rtol=1e-3, atol=1e-3) + + +def _check_eigen(M, w, V, rtol=1e-8, atol=1e-14): + """Check if the eigenvalue residual is small. + """ + mult_wV = np.multiply(w, V) + dot_MV = M.dot(V) + assert_allclose(mult_wV, dot_MV, rtol=rtol, atol=atol) + + +def _check_fiedler(n, p): + """Check the Fiedler vector computation. + """ + # This is not necessarily the recommended way to find the Fiedler vector. + col = np.zeros(n) + col[1] = 1 + A = toeplitz(col) + D = np.diag(A.sum(axis=1)) + L = D - A + # Compute the full eigendecomposition using tricks, e.g. + # http://www.cs.yale.edu/homes/spielman/561/2009/lect02-09.pdf + tmp = np.pi * np.arange(n) / n + analytic_w = 2 * (1 - np.cos(tmp)) + analytic_V = np.cos(np.outer(np.arange(n) + 1/2, tmp)) + _check_eigen(L, analytic_w, analytic_V) + # Compute the full eigendecomposition using eigh. + eigh_w, eigh_V = eigh(L) + _check_eigen(L, eigh_w, eigh_V) + # Check that the first eigenvalue is near zero and that the rest agree. + assert_array_less(np.abs([eigh_w[0], analytic_w[0]]), 1e-14) + assert_allclose(eigh_w[1:], analytic_w[1:]) + + # Check small lobpcg eigenvalues. + X = analytic_V[:, :p] + lobpcg_w, lobpcg_V = lobpcg(L, X, largest=False) + assert_equal(lobpcg_w.shape, (p,)) + assert_equal(lobpcg_V.shape, (n, p)) + _check_eigen(L, lobpcg_w, lobpcg_V) + assert_array_less(np.abs(np.min(lobpcg_w)), 1e-14) + assert_allclose(np.sort(lobpcg_w)[1:], analytic_w[1:p]) + + # Check large lobpcg eigenvalues. + X = analytic_V[:, -p:] + lobpcg_w, lobpcg_V = lobpcg(L, X, largest=True) + assert_equal(lobpcg_w.shape, (p,)) + assert_equal(lobpcg_V.shape, (n, p)) + _check_eigen(L, lobpcg_w, lobpcg_V) + assert_allclose(np.sort(lobpcg_w), analytic_w[-p:]) + + # Look for the Fiedler vector using good but not exactly correct guesses. + fiedler_guess = np.concatenate((np.ones(n//2), -np.ones(n-n//2))) + X = np.vstack((np.ones(n), fiedler_guess)).T + lobpcg_w, _ = lobpcg(L, X, largest=False) + # Mathematically, the smaller eigenvalue should be zero + # and the larger should be the algebraic connectivity. + lobpcg_w = np.sort(lobpcg_w) + assert_allclose(lobpcg_w, analytic_w[:2], atol=1e-14) + + +def test_fiedler_small_8(): + """Check the dense workaround path for small matrices. + """ + # This triggers the dense path because 8 < 2*5. + with pytest.warns(UserWarning, match="The problem size"): + _check_fiedler(8, 2) + + +def test_fiedler_large_12(): + """Check the dense workaround path avoided for non-small matrices. + """ + # This does not trigger the dense path, because 2*5 <= 12. + _check_fiedler(12, 2) + + +@pytest.mark.filterwarnings("ignore:Failed at iteration") +@pytest.mark.filterwarnings("ignore:Exited at iteration") +@pytest.mark.filterwarnings("ignore:Exited postprocessing") +def test_failure_to_run_iterations(): + """Check that the code exits gracefully without breaking. Issue #10974. + The code may or not issue a warning, filtered out. Issue #15935, #17954. + """ + rnd = np.random.RandomState(0) + X = rnd.standard_normal((100, 10)) + A = X @ X.T + Q = rnd.standard_normal((X.shape[0], 4)) + eigenvalues, _ = lobpcg(A, Q, maxiter=40, tol=1e-12) + assert np.max(eigenvalues) > 0 + + +def test_failure_to_run_iterations_nonsymmetric(): + """Check that the code exists gracefully without breaking + if the matrix in not symmetric. + """ + A = np.zeros((10, 10)) + A[0, 1] = 1 + Q = np.ones((10, 1)) + msg = "Exited at iteration 2|Exited postprocessing with accuracies.*" + with pytest.warns(UserWarning, match=msg): + eigenvalues, _ = lobpcg(A, Q, maxiter=20) + assert np.max(eigenvalues) > 0 + + +@pytest.mark.skipif(_IS_32BIT and np.lib.NumpyVersion(np.__version__) < "2.0.0", + reason="Was failing in CI, see gh-23077") +@pytest.mark.filterwarnings("ignore:The problem size") +def test_hermitian(): + """Check complex-value Hermitian cases. + """ + rnd = np.random.RandomState(0) + + sizes = [3, 12] + ks = [1, 2] + gens = [True, False] + + for s, k, gen, dh, dx, db in ( + itertools.product(sizes, ks, gens, gens, gens, gens) + ): + H = rnd.random((s, s)) + 1.j * rnd.random((s, s)) + H = 10 * np.eye(s) + H + H.T.conj() + H = H.astype(np.complex128) if dh else H.astype(np.complex64) + + X = rnd.standard_normal((s, k)) + X = X + 1.j * rnd.standard_normal((s, k)) + X = X.astype(np.complex128) if dx else X.astype(np.complex64) + + if not gen: + B = np.eye(s) + w, v = lobpcg(H, X, maxiter=99, verbosityLevel=0) + # Also test mixing complex H with real B. + wb, _ = lobpcg(H, X, B, maxiter=99, verbosityLevel=0) + assert_allclose(w, wb, rtol=1e-6) + w0, _ = eigh(H) + else: + B = rnd.random((s, s)) + 1.j * rnd.random((s, s)) + B = 10 * np.eye(s) + B.dot(B.T.conj()) + B = B.astype(np.complex128) if db else B.astype(np.complex64) + w, v = lobpcg(H, X, B, maxiter=99, verbosityLevel=0) + w0, _ = eigh(H, B) + + for wx, vx in zip(w, v.T): + # Check eigenvector + assert_allclose(np.linalg.norm(H.dot(vx) - B.dot(vx) * wx) + / np.linalg.norm(H.dot(vx)), + 0, atol=5e-2, rtol=0) + + # Compare eigenvalues + j = np.argmin(abs(w0 - wx)) + assert_allclose(wx, w0[j], rtol=1e-4) + + +# The n=5 case tests the alternative small matrix code path that uses eigh(). +@pytest.mark.filterwarnings("ignore:The problem size") +@pytest.mark.parametrize('n, atol', [(20, 1e-3), (5, 1e-8)]) +def test_eigsh_consistency(n, atol): + """Check eigsh vs. lobpcg consistency. + """ + vals = np.arange(1, n+1, dtype=np.float64) + A = dia_array((vals, 0), shape=(n, n)) + rnd = np.random.RandomState(0) + X = rnd.standard_normal((n, 2)) + lvals, lvecs = lobpcg(A, X, largest=True, maxiter=100) + vals, _ = eigsh(A, k=2) + + _check_eigen(A, lvals, lvecs, atol=atol, rtol=0) + assert_allclose(np.sort(vals), np.sort(lvals), atol=1e-14) + + +def test_verbosity(): + """Check that nonzero verbosity level code runs. + """ + rnd = np.random.RandomState(0) + X = rnd.standard_normal((10, 10)) + A = X @ X.T + Q = rnd.standard_normal((X.shape[0], 1)) + msg = "Exited at iteration.*|Exited postprocessing with accuracies.*" + with pytest.warns(UserWarning, match=msg): + _, _ = lobpcg(A, Q, maxiter=3, verbosityLevel=9) + + +@pytest.mark.xfail(_IS_32BIT and sys.platform == 'win32', + reason="tolerance violation on windows") +@pytest.mark.xfail(platform.machine() == 'ppc64le', + reason="fails on ppc64le") +@pytest.mark.filterwarnings("ignore:Exited postprocessing") +def test_tolerance_float32(): + """Check lobpcg for attainable tolerance in float32. + """ + rnd = np.random.RandomState(0) + n = 50 + m = 3 + vals = -np.arange(1, n + 1) + A = dia_array(([vals], [0]), shape=(n, n)) + A = A.astype(np.float32) + X = rnd.standard_normal((n, m)) + X = X.astype(np.float32) + eigvals, _ = lobpcg(A, X, tol=1.25e-5, maxiter=50, verbosityLevel=0) + assert_allclose(eigvals, -np.arange(1, 1 + m), atol=2e-5, rtol=1e-5) + + +@pytest.mark.parametrize("vdtype", INEXACTDTYPES) +@pytest.mark.parametrize("mdtype", ALLDTYPES) +@pytest.mark.parametrize("arr_type", [np.array, + sparse.csr_array, + sparse.coo_array]) +def test_dtypes(vdtype, mdtype, arr_type): + """Test lobpcg in various dtypes. + """ + rnd = np.random.RandomState(0) + n = 12 + m = 2 + A = arr_type(np.diag(np.arange(1, n + 1)).astype(mdtype)) + X = rnd.random((n, m)) + X = X.astype(vdtype) + eigvals, eigvecs = lobpcg(A, X, tol=1e-2, largest=False) + assert_allclose(eigvals, np.arange(1, 1 + m), atol=1e-1) + # eigenvectors must be nearly real in any case + assert_allclose(np.sum(np.abs(eigvecs - eigvecs.conj())), 0, atol=1e-2) + + +@pytest.mark.filterwarnings("ignore:Exited at iteration") +@pytest.mark.filterwarnings("ignore:Exited postprocessing") +def test_inplace_warning(): + """Check lobpcg gives a warning in '_b_orthonormalize' + that in-place orthogonalization is impossible due to dtype mismatch. + """ + rnd = np.random.RandomState(0) + n = 6 + m = 1 + vals = -np.arange(1, n + 1) + A = dia_array(([vals], [0]), shape=(n, n)) + A = A.astype(np.cdouble) + X = rnd.standard_normal((n, m)) + with pytest.warns(UserWarning, match="Inplace update"): + eigvals, _ = lobpcg(A, X, maxiter=2, verbosityLevel=1) + + +def test_maxit(): + """Check lobpcg if maxit=maxiter runs maxiter iterations and + if maxit=None runs 20 iterations (the default) + by checking the size of the iteration history output, which should + be the number of iterations plus 3 (initial, final, and postprocessing) + typically when maxiter is small and the choice of the best is passive. + """ + rnd = np.random.RandomState(0) + n = 50 + m = 4 + vals = -np.arange(1, n + 1) + A = dia_array(([vals], [0]), shape=(n, n)) + A = A.astype(np.float32) + X = rnd.standard_normal((n, m)) + X = X.astype(np.float64) + msg = "Exited at iteration.*|Exited postprocessing with accuracies.*" + for maxiter in range(1, 4): + with pytest.warns(UserWarning, match=msg): + _, _, l_h, r_h = lobpcg(A, X, tol=1e-8, maxiter=maxiter, + retLambdaHistory=True, + retResidualNormsHistory=True) + assert_allclose(np.shape(l_h)[0], maxiter+3) + assert_allclose(np.shape(r_h)[0], maxiter+3) + with pytest.warns(UserWarning, match=msg): + l, _, l_h, r_h = lobpcg(A, X, tol=1e-8, + retLambdaHistory=True, + retResidualNormsHistory=True) + assert_allclose(np.shape(l_h)[0], 20+3) + assert_allclose(np.shape(r_h)[0], 20+3) + # Check that eigenvalue output is the last one in history + assert_allclose(l, l_h[-1]) + # Make sure that both history outputs are lists + assert isinstance(l_h, list) + assert isinstance(r_h, list) + # Make sure that both history lists are arrays-like + assert_allclose(np.shape(l_h), np.shape(np.asarray(l_h))) + assert_allclose(np.shape(r_h), np.shape(np.asarray(r_h))) + + +@pytest.mark.xslow +@pytest.mark.filterwarnings("ignore:Exited at iteration") +@pytest.mark.filterwarnings("ignore:Exited postprocessing") +def test_sakurai(): + """Check lobpcg and eighs accuracy for the Sakurai example + already used in `benchmarks/benchmarks/sparse_linalg_lobpcg.py`. + """ + n = 50 + tol = 100 * n * n * n* np.finfo(float).eps + sakurai_obj = Sakurai(n, dtype='int') + A = sakurai_obj + m = 3 + ee = sakurai_obj.eigenvalues(3) + rng = np.random.default_rng(0) + X = rng.normal(size=(n, m)) + el, _ = lobpcg(A, X, tol=1e-9, maxiter=5000, largest=False) + accuracy = max(abs(ee - el) / ee) + assert_allclose(accuracy, 0., atol=tol) + a_l = LinearOperator((n, n), matvec=A, matmat=A, dtype='float64') + ea, _ = eigsh(a_l, k=m, which='SA', tol=1e-9, maxiter=15000, + v0 = rng.normal(size=(n, 1))) + accuracy = max(abs(ee - ea) / ee) + assert_allclose(accuracy, 0., atol=tol) + + +@pytest.mark.parametrize("n", [500, 1000]) +@pytest.mark.filterwarnings("ignore:Exited at iteration") +@pytest.mark.filterwarnings("ignore:Exited postprocessing") +def test_sakurai_inverse(n): + """Check lobpcg and eighs accuracy for the sakurai_inverse example + already used in `benchmarks/benchmarks/sparse_linalg_lobpcg.py`. + """ + def a(x): + return cho_solve_banded((c, False), x) + tol = 100 * n * n * n* np.finfo(float).eps + sakurai_obj = Sakurai(n) + A = sakurai_obj.tobanded().astype(np.float64) + m = 3 + ee = sakurai_obj.eigenvalues(3) + rng = np.random.default_rng(0) + X = rng.normal(size=(n, m)) + c = cholesky_banded(A) + el, _ = lobpcg(a, X, tol=1e-9, maxiter=8) + accuracy = max(abs(ee - 1. / el) / ee) + assert_allclose(accuracy, 0., atol=tol) + a_l = LinearOperator((n, n), matvec=a, matmat=a, dtype='float64') + ea, _ = eigsh(a_l, k=m, which='LA', tol=1e-9, maxiter=8, + v0 = rng.normal(size=(n, 1))) + accuracy = max(abs(ee - np.sort(1. / ea)) / ee) + assert_allclose(accuracy, 0., atol=tol) + + +@pytest.mark.filterwarnings("ignore:The problem size") +@pytest.mark.parametrize("n", [10, 20, 128, 256, 512, 1024, 2048]) +@pytest.mark.filterwarnings("ignore:Exited at iteration") +@pytest.mark.filterwarnings("ignore:Exited postprocessing") +def test_MikotaPair(n): + """Check lobpcg and eighs accuracy for the Mikota example + already used in `benchmarks/benchmarks/sparse_linalg_lobpcg.py`. + """ + def a(x): + return cho_solve_banded((c, False), x) + mik = MikotaPair(n) + mik_k = mik.k + mik_m = mik.m + Ac = mik_k + Bc = mik_m + Ab = mik_k.tobanded() + eigenvalues = mik.eigenvalues + if n == 10: + m = 3 # lobpcg calls eigh + elif n == 20: + m = 2 + else: + m = 10 + ee = eigenvalues(m) + tol = 100 * m * n * n * np.finfo(float).eps + rng = np.random.default_rng(0) + X = rng.normal(size=(n, m)) + c = cholesky_banded(Ab.astype(np.float32)) + el, _ = lobpcg(Ac, X, Bc, M=a, tol=1e-4, + maxiter=40, largest=False) + accuracy = max(abs(ee - el) / ee) + assert_allclose(accuracy, 0., atol=tol) + B = LinearOperator((n, n), matvec=Bc, matmat=Bc, dtype='float64') + A = LinearOperator((n, n), matvec=Ac, matmat=Ac, dtype='float64') + c = cholesky_banded(Ab) + a_l = LinearOperator((n, n), matvec=a, matmat=a, dtype='float64') + ea, _ = eigsh(B, k=m, M=A, Minv=a_l, which='LA', tol=1e-4, maxiter=50, + v0 = rng.normal(size=(n, 1))) + accuracy = max(abs(ee - np.sort(1./ea)) / ee) + assert_allclose(accuracy, 0., atol=tol) + + +@pytest.mark.slow +@pytest.mark.parametrize("n", [15]) +@pytest.mark.parametrize("m", [1, 2]) +@pytest.mark.filterwarnings("ignore:Exited at iteration") +@pytest.mark.filterwarnings("ignore:Exited postprocessing") +def test_diagonal_data_types(n, m): + """Check lobpcg for diagonal matrices for all matrix types. + Constraints are imposed, so a dense eigensolver eig cannot run. + """ + rnd = np.random.RandomState(0) + # Define the generalized eigenvalue problem Av = cBv + # where (c, v) is a generalized eigenpair, + # and where we choose A and B to be diagonal. + vals = np.arange(1, n + 1) + + list_sparse_format = ['bsr', 'coo', 'csc', 'csr', 'dia', 'dok', 'lil'] + for s_f_i, s_f in enumerate(list_sparse_format): + + As64 = dia_array(([vals * vals], [0]), shape=(n, n)).asformat(s_f) + As32 = As64.astype(np.float32) + Af64 = As64.toarray() + Af32 = Af64.astype(np.float32) + + def As32f(x): + return As32 @ x + As32LO = LinearOperator(matvec=As32f, + matmat=As32f, + shape=(n, n), + dtype=As32.dtype) + + listA = [Af64, As64, Af32, As32, As32f, As32LO, lambda v: As32 @ v] + + Bs64 = dia_array(([vals], [0]), shape=(n, n)).asformat(s_f) + Bf64 = Bs64.toarray() + Bs32 = Bs64.astype(np.float32) + + def Bs32f(x): + return Bs32 @ x + Bs32LO = LinearOperator(matvec=Bs32f, + matmat=Bs32f, + shape=(n, n), + dtype=Bs32.dtype) + listB = [Bf64, Bs64, Bs32, Bs32f, Bs32LO, lambda v: Bs32 @ v] + + # Define the preconditioner function as LinearOperator. + Ms64 = dia_array(([1./vals], [0]), shape=(n, n)).asformat(s_f) + + def Ms64precond(x): + return Ms64 @ x + Ms64precondLO = LinearOperator(matvec=Ms64precond, + matmat=Ms64precond, + shape=(n, n), + dtype=Ms64.dtype) + Mf64 = Ms64.toarray() + + def Mf64precond(x): + return Mf64 @ x + Mf64precondLO = LinearOperator(matvec=Mf64precond, + matmat=Mf64precond, + shape=(n, n), + dtype=Mf64.dtype) + Ms32 = Ms64.astype(np.float32) + + def Ms32precond(x): + return Ms32 @ x + Ms32precondLO = LinearOperator(matvec=Ms32precond, + matmat=Ms32precond, + shape=(n, n), + dtype=Ms32.dtype) + Mf32 = Ms32.toarray() + + def Mf32precond(x): + return Mf32 @ x + Mf32precondLO = LinearOperator(matvec=Mf32precond, + matmat=Mf32precond, + shape=(n, n), + dtype=Mf32.dtype) + listM = [None, Ms64, Ms64precondLO, Mf64precondLO, Ms64precond, + Ms32, Ms32precondLO, Mf32precondLO, Ms32precond] + + # Setup matrix of the initial approximation to the eigenvectors + # (cannot be sparse array). + Xf64 = rnd.random((n, m)) + Xf32 = Xf64.astype(np.float32) + listX = [Xf64, Xf32] + + # Require that the returned eigenvectors be in the orthogonal complement + # of the first few standard basis vectors (cannot be sparse array). + m_excluded = 3 + Yf64 = np.eye(n, m_excluded, dtype=float) + Yf32 = np.eye(n, m_excluded, dtype=np.float32) + listY = [Yf64, Yf32] + + tests = list(itertools.product(listA, listB, listM, listX, listY)) + + for A, B, M, X, Y in tests: + # This is one of the slower tests because there are >1,000 configs + # to test here. Flip a biased coin to decide whether to run each + # test to get decent coverage in less time. + if rnd.random() < 0.98: + continue # too many tests + eigvals, _ = lobpcg(A, X, B=B, M=M, Y=Y, tol=1e-4, + maxiter=100, largest=False) + assert_allclose(eigvals, + np.arange(1 + m_excluded, 1 + m_excluded + m), + atol=1e-5) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b0be2af919e4c7cb046ea0443f182c3a94e37957 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/tests/__pycache__/test_svds.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/tests/__pycache__/test_svds.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7ceeb744f52baba7e1bde16fcb9f93395462cbe9 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/tests/__pycache__/test_svds.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/tests/test_svds.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/tests/test_svds.py new file mode 100644 index 0000000000000000000000000000000000000000..c2b85d3dd5a3f7c3d46e64d1bd9197d37f1ae402 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_eigen/tests/test_svds.py @@ -0,0 +1,880 @@ +import re +import copy +import numpy as np + +from numpy.testing import assert_allclose, assert_equal, assert_array_equal +import pytest + +from scipy.linalg import svd, null_space +from scipy.sparse import csc_array, issparse, dia_array, random_array +from scipy.sparse.linalg import LinearOperator, aslinearoperator +from scipy.sparse.linalg import svds +from scipy.sparse.linalg._eigen.arpack import ArpackNoConvergence + + +# --- Helper Functions / Classes --- + + +def sorted_svd(m, k, which='LM'): + # Compute svd of a dense matrix m, and return singular vectors/values + # sorted. + if issparse(m): + m = m.toarray() + u, s, vh = svd(m) + if which == 'LM': + ii = np.argsort(s)[-k:] + elif which == 'SM': + ii = np.argsort(s)[:k] + else: + raise ValueError(f"unknown which={which!r}") + + return u[:, ii], s[ii], vh[ii] + + +def _check_svds(A, k, u, s, vh, which="LM", check_usvh_A=False, + check_svd=True, atol=1e-10, rtol=1e-7): + n, m = A.shape + + # Check shapes. + assert_equal(u.shape, (n, k)) + assert_equal(s.shape, (k,)) + assert_equal(vh.shape, (k, m)) + + # Check that the original matrix can be reconstituted. + A_rebuilt = (u*s).dot(vh) + assert_equal(A_rebuilt.shape, A.shape) + if check_usvh_A: + assert_allclose(A_rebuilt, A, atol=atol, rtol=rtol) + + # Check that u is a semi-orthogonal matrix. + uh_u = np.dot(u.T.conj(), u) + assert_equal(uh_u.shape, (k, k)) + assert_allclose(uh_u, np.identity(k), atol=atol, rtol=rtol) + + # Check that vh is a semi-orthogonal matrix. + vh_v = np.dot(vh, vh.T.conj()) + assert_equal(vh_v.shape, (k, k)) + assert_allclose(vh_v, np.identity(k), atol=atol, rtol=rtol) + + # Check that scipy.sparse.linalg.svds ~ scipy.linalg.svd + if check_svd: + u2, s2, vh2 = sorted_svd(A, k, which) + assert_allclose(np.abs(u), np.abs(u2), atol=atol, rtol=rtol) + assert_allclose(s, s2, atol=atol, rtol=rtol) + assert_allclose(np.abs(vh), np.abs(vh2), atol=atol, rtol=rtol) + + +def _check_svds_n(A, k, u, s, vh, which="LM", check_res=True, + check_svd=True, atol=1e-10, rtol=1e-7): + n, m = A.shape + + # Check shapes. + assert_equal(u.shape, (n, k)) + assert_equal(s.shape, (k,)) + assert_equal(vh.shape, (k, m)) + + # Check that u is a semi-orthogonal matrix. + uh_u = np.dot(u.T.conj(), u) + assert_equal(uh_u.shape, (k, k)) + error = np.sum(np.abs(uh_u - np.identity(k))) / (k * k) + assert_allclose(error, 0.0, atol=atol, rtol=rtol) + + # Check that vh is a semi-orthogonal matrix. + vh_v = np.dot(vh, vh.T.conj()) + assert_equal(vh_v.shape, (k, k)) + error = np.sum(np.abs(vh_v - np.identity(k))) / (k * k) + assert_allclose(error, 0.0, atol=atol, rtol=rtol) + + # Check residuals + if check_res: + ru = A.T.conj() @ u - vh.T.conj() * s + rus = np.sum(np.abs(ru)) / (n * k) + rvh = A @ vh.T.conj() - u * s + rvhs = np.sum(np.abs(rvh)) / (m * k) + assert_allclose(rus, 0.0, atol=atol, rtol=rtol) + assert_allclose(rvhs, 0.0, atol=atol, rtol=rtol) + + # Check that scipy.sparse.linalg.svds ~ scipy.linalg.svd + if check_svd: + u2, s2, vh2 = sorted_svd(A, k, which) + assert_allclose(s, s2, atol=atol, rtol=rtol) + A_rebuilt_svd = (u2*s2).dot(vh2) + A_rebuilt = (u*s).dot(vh) + assert_equal(A_rebuilt.shape, A.shape) + error = np.sum(np.abs(A_rebuilt_svd - A_rebuilt)) / (k * k) + assert_allclose(error, 0.0, atol=atol, rtol=rtol) + + +class CheckingLinearOperator(LinearOperator): + def __init__(self, A): + self.A = A + self.dtype = A.dtype + self.shape = A.shape + + def _matvec(self, x): + assert_equal(max(x.shape), np.size(x)) + return self.A.dot(x) + + def _rmatvec(self, x): + assert_equal(max(x.shape), np.size(x)) + return self.A.T.conjugate().dot(x) + + +# --- Test Input Validation --- +# Tests input validation on parameters `k` and `which`. +# Needs better input validation checks for all other parameters. + +class SVDSCommonTests: + + solver = None + + # some of these IV tests could run only once, say with solver=None + + _A_empty_msg = "`A` must not be empty." + _A_dtype_msg = "`A` must be of numeric data type" + _A_type_msg = "type not understood" + _A_ndim_msg = "array must have ndim <= 2" + _A_validation_inputs = [ + (np.asarray([[]]), ValueError, _A_empty_msg), + (np.array([['a', 'b'], ['c', 'd']], dtype='object'), ValueError, _A_dtype_msg), + ("hi", TypeError, _A_type_msg), + (np.asarray([[[1., 2.], [3., 4.]]]), ValueError, _A_ndim_msg)] + + @pytest.mark.parametrize("args", _A_validation_inputs) + def test_svds_input_validation_A(self, args): + A, error_type, message = args + with pytest.raises(error_type, match=message): + svds(A, k=1, solver=self.solver, rng=0) + + @pytest.mark.parametrize("which", ["LM", "SM"]) + def test_svds_int_A(self, which): + A = np.asarray([[1, 2], [3, 4]]) + if self.solver == 'lobpcg': + with pytest.warns(UserWarning, match="The problem size"): + res = svds(A, k=1, which=which, solver=self.solver, rng=0) + else: + res = svds(A, k=1, which=which, solver=self.solver, rng=0) + _check_svds(A, 1, *res, which=which, atol=8e-10) + + def test_svds_diff0_docstring_example(self): + def diff0(a): + return np.diff(a, axis=0) + def diff0t(a): + if a.ndim == 1: + a = a[:,np.newaxis] # Turn 1D into 2D array + d = np.zeros((a.shape[0] + 1, a.shape[1]), dtype=a.dtype) + d[0, :] = - a[0, :] + d[1:-1, :] = a[0:-1, :] - a[1:, :] + d[-1, :] = a[-1, :] + return d + def diff0_func_aslo_def(n): + return LinearOperator(matvec=diff0, + matmat=diff0, + rmatvec=diff0t, + rmatmat=diff0t, + shape=(n - 1, n)) + n = 100 + diff0_func_aslo = diff0_func_aslo_def(n) + rng = np.random.default_rng(1758043640965324) + u, s, _ = svds(diff0_func_aslo, k=3, which='SM', rng=rng) + se = 2. * np.sin(np.pi * np.arange(1, 4) / (2. * n)) + ue = np.sqrt(2 / n) * np.sin(np.pi * np.outer(np.arange(1, n), + np.arange(1, 4)) / n) + assert_allclose(s, se, atol=1e-3) + assert_allclose(np.abs(u), np.abs(ue), atol=1e-6) + + @pytest.mark.parametrize("k", [-1, 0, 3, 4, 5, 1.5, "1"]) + def test_svds_input_validation_k_1(self, k): + rng = np.random.default_rng(0) + A = rng.random((4, 3)) + + # propack can do complete SVD + if self.solver == 'propack' and k == 3: + res = svds(A, k=k, solver=self.solver, rng=0) + _check_svds(A, k, *res, check_usvh_A=True, check_svd=True) + return + + message = ("`k` must be an integer satisfying") + with pytest.raises(ValueError, match=message): + svds(A, k=k, solver=self.solver, rng=0) + + def test_svds_input_validation_k_2(self): + # I think the stack trace is reasonable when `k` can't be converted + # to an int. + message = "int() argument must be a" + with pytest.raises(TypeError, match=re.escape(message)): + svds(np.eye(10), k=[], solver=self.solver, rng=0) + + message = "invalid literal for int()" + with pytest.raises(ValueError, match=message): + svds(np.eye(10), k="hi", solver=self.solver, rng=0) + + @pytest.mark.parametrize("tol", (-1, np.inf, np.nan)) + def test_svds_input_validation_tol_1(self, tol): + message = "`tol` must be a non-negative floating point value." + with pytest.raises(ValueError, match=message): + svds(np.eye(10), tol=tol, solver=self.solver, rng=0) + + @pytest.mark.parametrize("tol", ([], 'hi')) + def test_svds_input_validation_tol_2(self, tol): + # I think the stack trace is reasonable here + message = "'<' not supported between instances" + with pytest.raises(TypeError, match=message): + svds(np.eye(10), tol=tol, solver=self.solver, rng=0) + + @pytest.mark.parametrize("which", ('LA', 'SA', 'ekki', 0)) + def test_svds_input_validation_which(self, which): + # Regression test for a github issue. + # https://github.com/scipy/scipy/issues/4590 + # Function was not checking for eigenvalue type and unintended + # values could be returned. + with pytest.raises(ValueError, match="`which` must be in"): + svds(np.eye(10), which=which, solver=self.solver, rng=0) + + @pytest.mark.parametrize("transpose", (True, False)) + @pytest.mark.parametrize("n", range(4, 9)) + def test_svds_input_validation_v0_1(self, transpose, n): + rng = np.random.default_rng(0) + A = rng.random((5, 7)) + v0 = rng.random(n) + if transpose: + A = A.T + k = 2 + message = "`v0` must have shape" + + required_length = (A.shape[0] if self.solver == 'propack' + else min(A.shape)) + if n != required_length: + with pytest.raises(ValueError, match=message): + svds(A, k=k, v0=v0, solver=self.solver, rng=0) + + def test_svds_input_validation_v0_2(self): + A = np.ones((10, 10)) + v0 = np.ones((1, 10)) + message = "`v0` must have shape" + with pytest.raises(ValueError, match=message): + svds(A, k=1, v0=v0, solver=self.solver, rng=0) + + @pytest.mark.parametrize("v0", ("hi", 1, np.ones(10, dtype=int))) + def test_svds_input_validation_v0_3(self, v0): + A = np.ones((10, 10)) + message = "`v0` must be of floating or complex floating data type." + with pytest.raises(ValueError, match=message): + svds(A, k=1, v0=v0, solver=self.solver, rng=0) + + @pytest.mark.parametrize("maxiter", (-1, 0, 5.5)) + def test_svds_input_validation_maxiter_1(self, maxiter): + message = ("`maxiter` must be a positive integer.") + with pytest.raises(ValueError, match=message): + svds(np.eye(10), maxiter=maxiter, solver=self.solver, rng=0) + + def test_svds_input_validation_maxiter_2(self): + # I think the stack trace is reasonable when `k` can't be converted + # to an int. + message = "int() argument must be a" + with pytest.raises(TypeError, match=re.escape(message)): + svds(np.eye(10), maxiter=[], solver=self.solver, rng=0) + + message = "invalid literal for int()" + with pytest.raises(ValueError, match=message): + svds(np.eye(10), maxiter="hi", solver=self.solver, rng=0) + + @pytest.mark.parametrize("rsv", ('ekki', 10)) + def test_svds_input_validation_return_singular_vectors(self, rsv): + message = "`return_singular_vectors` must be in" + with pytest.raises(ValueError, match=message): + svds(np.eye(10), return_singular_vectors=rsv, solver=self.solver, rng=0) + + # --- Test Parameters --- + @pytest.mark.parametrize("k", [3, 5]) + @pytest.mark.parametrize("which", ["LM", "SM"]) + def test_svds_parameter_k_which(self, k, which): + # check that the `k` parameter sets the number of eigenvalues/ + # eigenvectors returned. + # Also check that the `which` parameter sets whether the largest or + # smallest eigenvalues are returned + rng = np.random.default_rng(0) + A = rng.random((10, 10)) + if self.solver == 'lobpcg': + with pytest.warns(UserWarning, match="The problem size"): + res = svds(A, k=k, which=which, solver=self.solver, rng=0) + else: + res = svds(A, k=k, which=which, solver=self.solver, rng=0) + _check_svds(A, k, *res, which=which, atol=1e-9, rtol=2e-13) + + @pytest.mark.filterwarnings("ignore:Exited", + reason="Ignore LOBPCG early exit.") + # loop instead of parametrize for simplicity + def test_svds_parameter_tol(self): + # check the effect of the `tol` parameter on solver accuracy by solving + # the same problem with varying `tol` and comparing the eigenvalues + # against ground truth computed + n = 100 # matrix size + k = 3 # number of eigenvalues to check + + # generate a random, sparse-ish matrix + # effect isn't apparent for matrices that are too small + rng = np.random.default_rng(0) + A = rng.random((n, n)) + A[A > .1] = 0 + A = A @ A.T + + _, s, _ = svd(A) # calculate ground truth + + # calculate the error as a function of `tol` + A = csc_array(A) + + def err(tol): + _, s2, _ = svds(A, k=k, v0=np.ones(n), maxiter=1000, + solver=self.solver, tol=tol, rng=0) + return np.linalg.norm((s2 - s[k-1::-1])/s[k-1::-1]) + + tols = [1e-4, 1e-2, 1e0] # tolerance levels to check + # for 'arpack' and 'propack', accuracies make discrete steps + accuracies = {'propack': [1e-12, 1e-6, 1e-4], + 'arpack': [2.5e-15, 1e-10, 1e-10], + 'lobpcg': [2e-12, 4e-2, 2]} + + for tol, accuracy in zip(tols, accuracies[self.solver]): + error = err(tol) + assert error < accuracy + + def test_svd_v0(self): + # check that the `v0` parameter affects the solution + n = 100 + k = 1 + # If k != 1, LOBPCG needs more initial vectors, which are generated + # with rng, so it does not pass w/ k >= 2. + # For some other values of `n`, the AssertionErrors are not raised + # with different v0s, which is reasonable. + + rng = np.random.default_rng(0) + A = rng.random((n, n)) + + # with the same v0, solutions are the same, and they are accurate + # v0 takes precedence over rng + v0a = rng.random(n) + res1a = svds(A, k, v0=v0a, solver=self.solver, rng=0) + res2a = svds(A, k, v0=v0a, solver=self.solver, rng=1) + for idx in range(3): + assert_allclose(res1a[idx], res2a[idx], rtol=1e-15, atol=2e-16) + _check_svds(A, k, *res1a) + + # with the same v0, solutions are the same, and they are accurate + v0b = rng.random(n) + res1b = svds(A, k, v0=v0b, solver=self.solver, rng=2) + res2b = svds(A, k, v0=v0b, solver=self.solver, rng=3) + for idx in range(3): + assert_allclose(res1b[idx], res2b[idx], rtol=1e-15, atol=2e-16) + _check_svds(A, k, *res1b) + + # with different v0, solutions can be numerically different + message = "Arrays are not equal" + with pytest.raises(AssertionError, match=message): + assert_equal(res1a, res1b) + + def test_svd_rng(self): + # check that the `rng` parameter affects the solution + # Admittedly, `n` and `k` are chosen so that all solver pass all + # these checks. That's a tall order, since LOBPCG doesn't want to + # achieve the desired accuracy and ARPACK often returns the same + # singular values/vectors for different v0. + n = 100 + k = 1 + + rng = np.random.default_rng(0) + A = rng.random((n, n)) + + # with the same rng, solutions are the same and accurate + res1a = svds(A, k, solver=self.solver, rng=0) + res2a = svds(A, k, solver=self.solver, rng=0) + for idx in range(3): + assert_allclose(res1a[idx], res2a[idx], rtol=1e-15, atol=2e-16) + _check_svds(A, k, *res1a) + + # with the same rng, solutions are the same and accurate + res1b = svds(A, k, solver=self.solver, rng=1) + res2b = svds(A, k, solver=self.solver, rng=1) + for idx in range(3): + assert_allclose(res1b[idx], res2b[idx], rtol=1e-15, atol=2e-16) + _check_svds(A, k, *res1b) + + # with different rng, solutions can be numerically different + message = "Arrays are not equal" + with pytest.raises(AssertionError, match=message): + assert_equal(res1a, res1b) + + def test_svd_rng_2(self): + n = 100 + k = 1 + + rng = np.random.default_rng(234981) + A = rng.random((n, n)) + rng_2 = copy.deepcopy(rng) + + # with the same rng, solutions are the same and accurate + res1a = svds(A, k, solver=self.solver, rng=rng) + res2a = svds(A, k, solver=self.solver, rng=rng_2) + for idx in range(3): + assert_allclose(res1a[idx], res2a[idx], rtol=1e-15, atol=2e-16) + _check_svds(A, k, *res1a) + + @pytest.mark.filterwarnings("ignore:Exited", + reason="Ignore LOBPCG early exit.") + def test_svd_rng_3(self): + n = 100 + k = 5 + + rng1 = np.random.default_rng(0) + rng2 = np.random.default_rng(234832) + A = rng1.random((n, n)) + + # rng in different state produces accurate - but not + # not necessarily identical - results + res1a = svds(A, k, solver=self.solver, rng=rng1, maxiter=1000) + res2a = svds(A, k, solver=self.solver, rng=rng2, maxiter=1000) + _check_svds(A, k, *res1a, atol=2e-7) + _check_svds(A, k, *res2a, atol=2e-7) + + message = "Arrays are not equal" + with pytest.raises(AssertionError, match=message): + assert_equal(res1a, res2a) + + @pytest.mark.filterwarnings("ignore:Exited postprocessing") + def test_svd_maxiter(self): + # check that maxiter works as expected: should not return accurate + # solution after 1 iteration, but should with default `maxiter` + A = np.diag(np.arange(9)).astype(np.float64) + k = 1 + u, s, vh = sorted_svd(A, k) + # Use default maxiter by default + maxiter = None + + if self.solver == 'arpack': + message = "ARPACK error -1: No convergence" + with pytest.raises(ArpackNoConvergence, match=message): + svds(A, k, ncv=3, maxiter=1, solver=self.solver, rng=0) + elif self.solver == 'lobpcg': + # Set maxiter higher so test passes without changing + # default and breaking backward compatibility (gh-20221) + maxiter = 30 + with pytest.warns(UserWarning, match="Exited at iteration"): + svds(A, k, maxiter=1, solver=self.solver, rng=0) + elif self.solver == 'propack': + message = "k=1 singular triplets did not converge within" + with pytest.raises(np.linalg.LinAlgError, match=message): + svds(A, k, maxiter=1, solver=self.solver, rng=0) + + ud, sd, vhd = svds(A, k, solver=self.solver, maxiter=maxiter, rng=0) + _check_svds(A, k, ud, sd, vhd, atol=1e-8) + assert_allclose(np.abs(ud), np.abs(u), atol=1e-8) + assert_allclose(np.abs(vhd), np.abs(vh), atol=1e-8) + assert_allclose(np.abs(sd), np.abs(s), atol=1e-9) + + @pytest.mark.parametrize("rsv", (True, False, 'u', 'vh')) + @pytest.mark.parametrize("shape", ((5, 7), (6, 6), (7, 5))) + def test_svd_return_singular_vectors(self, rsv, shape): + # check that the return_singular_vectors parameter works as expected + rng = np.random.default_rng(0) + A = rng.random(shape) + k = 2 + M, N = shape + u, s, vh = sorted_svd(A, k) + + respect_u = True if self.solver == 'propack' else M <= N + respect_vh = True if self.solver == 'propack' else M > N + + if self.solver == 'lobpcg': + with pytest.warns(UserWarning, match="The problem size"): + if rsv is False: + s2 = svds(A, k, return_singular_vectors=rsv, + solver=self.solver, rng=rng) + assert_allclose(s2, s) + elif rsv == 'u' and respect_u: + u2, s2, vh2 = svds(A, k, return_singular_vectors=rsv, + solver=self.solver, rng=rng) + assert_allclose(np.abs(u2), np.abs(u)) + assert_allclose(s2, s) + assert vh2 is None + elif rsv == 'vh' and respect_vh: + u2, s2, vh2 = svds(A, k, return_singular_vectors=rsv, + solver=self.solver, rng=rng) + assert u2 is None + assert_allclose(s2, s) + assert_allclose(np.abs(vh2), np.abs(vh)) + else: + u2, s2, vh2 = svds(A, k, return_singular_vectors=rsv, + solver=self.solver, rng=rng) + if u2 is not None: + assert_allclose(np.abs(u2), np.abs(u)) + assert_allclose(s2, s) + if vh2 is not None: + assert_allclose(np.abs(vh2), np.abs(vh)) + else: + if rsv is False: + s2 = svds(A, k, return_singular_vectors=rsv, + solver=self.solver, rng=rng) + assert_allclose(s2, s) + elif rsv == 'u' and respect_u: + u2, s2, vh2 = svds(A, k, return_singular_vectors=rsv, + solver=self.solver, rng=rng) + assert_allclose(np.abs(u2), np.abs(u)) + assert_allclose(s2, s) + assert vh2 is None + elif rsv == 'vh' and respect_vh: + u2, s2, vh2 = svds(A, k, return_singular_vectors=rsv, + solver=self.solver, rng=rng) + assert u2 is None + assert_allclose(s2, s) + assert_allclose(np.abs(vh2), np.abs(vh)) + else: + u2, s2, vh2 = svds(A, k, return_singular_vectors=rsv, + solver=self.solver, rng=rng) + if u2 is not None: + assert_allclose(np.abs(u2), np.abs(u)) + assert_allclose(s2, s) + if vh2 is not None: + assert_allclose(np.abs(vh2), np.abs(vh)) + + # --- Test Basic Functionality --- + # Tests the accuracy of each solver for real and complex matrices provided + # as list, dense array, sparse matrix, and LinearOperator. + + A1 = [[1, 2, 3], [3, 4, 3], [1 + 1j, 0, 2], [0, 0, 1]] + A2 = [[1, 2, 3, 8 + 5j], [3 - 2j, 4, 3, 5], [1, 0, 2, 3], [0, 0, 1, 0]] + + @pytest.mark.filterwarnings("ignore:k >= N - 1", + reason="needed to demonstrate #16725") + @pytest.mark.parametrize('A', (A1, A2)) + @pytest.mark.parametrize('k', range(1, 5)) + # PROPACK fails a lot if @pytest.mark.parametrize('which', ("SM", "LM")) + @pytest.mark.parametrize('real', (True, False)) + @pytest.mark.parametrize('transpose', (False, True)) + # In gh-14299, it was suggested the `svds` should _not_ work with lists + @pytest.mark.parametrize('lo_type', (np.asarray, csc_array, + aslinearoperator)) + def test_svd_simple(self, A, k, real, transpose, lo_type): + + A = np.asarray(A) + A = np.real(A) if real else A + A = A.T if transpose else A + A2 = lo_type(A) + + # could check for the appropriate errors, but that is tested above + if k > min(A.shape): + pytest.skip("`k` cannot be greater than `min(A.shape)`") + if self.solver != 'propack' and k >= min(A.shape): + pytest.skip("Only PROPACK supports complete SVD") + if self.solver == 'arpack' and not real and k == min(A.shape) - 1: + pytest.skip("#16725") + + atol = 3e-10 + if self.solver == 'propack': + atol = 3e-9 # otherwise test fails on Linux aarch64 (see gh-19855) + + if self.solver == 'lobpcg': + with pytest.warns(UserWarning, match="The problem size"): + u, s, vh = svds(A2, k, solver=self.solver, rng=0) + else: + u, s, vh = svds(A2, k, solver=self.solver, rng=0) + _check_svds(A, k, u, s, vh, atol=atol) + + def test_svd_linop(self): + solver = self.solver + + nmks = [(6, 7, 3), + (9, 5, 4), + (10, 8, 5)] + + def reorder(args): + U, s, VH = args + j = np.argsort(s) + return U[:, j], s[j], VH[j, :] + + for n, m, k in nmks: + # Test svds on a LinearOperator. + A = np.random.RandomState(52).randn(n, m) + L = CheckingLinearOperator(A) + + if solver == 'propack': + v0 = np.ones(n) + else: + v0 = np.ones(min(A.shape)) + if solver == 'lobpcg': + with pytest.warns(UserWarning, match="The problem size"): + U1, s1, VH1 = reorder(svds(A, k, v0=v0, solver=solver, rng=0)) + U2, s2, VH2 = reorder(svds(L, k, v0=v0, solver=solver, rng=0)) + else: + U1, s1, VH1 = reorder(svds(A, k, v0=v0, solver=solver, rng=0)) + U2, s2, VH2 = reorder(svds(L, k, v0=v0, solver=solver, rng=0)) + + assert_allclose(np.abs(U1), np.abs(U2)) + assert_allclose(s1, s2) + assert_allclose(np.abs(VH1), np.abs(VH2)) + assert_allclose(np.dot(U1, np.dot(np.diag(s1), VH1)), + np.dot(U2, np.dot(np.diag(s2), VH2))) + + # Try again with which="SM". + A = np.random.RandomState(1909).randn(n, m) + L = CheckingLinearOperator(A) + + # TODO: arpack crashes when v0=v0, which="SM" + kwargs = {'v0': v0} if solver not in {None, 'arpack'} else {} + if self.solver == 'lobpcg': + with pytest.warns(UserWarning, match="The problem size"): + U1, s1, VH1 = reorder(svds(A, k, which="SM", solver=solver, + rng=0, **kwargs)) + U2, s2, VH2 = reorder(svds(L, k, which="SM", solver=solver, + rng=0, **kwargs)) + else: + U1, s1, VH1 = reorder(svds(A, k, which="SM", solver=solver, + rng=0, **kwargs)) + U2, s2, VH2 = reorder(svds(L, k, which="SM", solver=solver, + rng=0, **kwargs)) + + assert_allclose(np.abs(U1), np.abs(U2)) + assert_allclose(s1 + 1, s2 + 1) + assert_allclose(np.abs(VH1), np.abs(VH2)) + assert_allclose(np.dot(U1, np.dot(np.diag(s1), VH1)), + np.dot(U2, np.dot(np.diag(s2), VH2))) + + if k < min(n, m) - 1: + # Complex input and explicit which="LM". + for (dt, eps) in [(complex, 1e-7), (np.complex64, 3e-3)]: + rng = np.random.RandomState(1648) + A = (rng.randn(n, m) + 1j * rng.randn(n, m)).astype(dt) + L = CheckingLinearOperator(A) + + if self.solver == 'lobpcg': + with pytest.warns(UserWarning, + match="The problem size"): + U1, s1, VH1 = reorder(svds(A, k, which="LM", + solver=solver, rng=0)) + U2, s2, VH2 = reorder(svds(L, k, which="LM", + solver=solver, rng=0)) + else: + U1, s1, VH1 = reorder(svds(A, k, which="LM", + solver=solver, rng=0)) + U2, s2, VH2 = reorder(svds(L, k, which="LM", + solver=solver, rng=0)) + + assert_allclose(np.abs(U1), np.abs(U2), rtol=eps) + assert_allclose(s1, s2, rtol=eps) + assert_allclose(np.abs(VH1), np.abs(VH2), rtol=eps) + assert_allclose(np.dot(U1, np.dot(np.diag(s1), VH1)), + np.dot(U2, np.dot(np.diag(s2), VH2)), + rtol=eps) + + SHAPES = ((100, 100), (100, 101), (101, 100)) + + @pytest.mark.filterwarnings("ignore:Exited at iteration") + @pytest.mark.filterwarnings("ignore:Exited postprocessing") + @pytest.mark.parallel_threads_limit(4) # Very slow + @pytest.mark.parametrize("shape", SHAPES) + @pytest.mark.parametrize("dtype", (np.float32, np.float64, + np.complex64, np.complex128)) + def test_small_sigma_sparse(self, shape, dtype): + # https://github.com/scipy/scipy/pull/11829 + solver = self.solver + # 2do: PROPACK fails orthogonality of singular vectors + # if dtype == complex and self.solver == 'propack': + # pytest.skip("PROPACK unsupported for complex dtype") + rng = np.random.default_rng(0) + k = 5 + (m, n) = shape + S = random_array(shape=(m, n), density=0.1, rng=rng) + if dtype is complex: + S = + 1j * random_array(shape=(m, n), density=0.1, rng=rng) + e = np.ones(m) + e[0:5] *= 1e1 ** np.arange(-5, 0, 1) + S = dia_array((e, 0), shape=(m, m)) @ S + S = S.astype(dtype) + u, s, vh = svds(S, k, which='SM', solver=solver, maxiter=1000, rng=0) + c_svd = False # partial SVD can be different from full SVD + _check_svds_n(S, k, u, s, vh, which="SM", check_svd=c_svd, atol=2e-1) + + # --- Test Edge Cases --- + # Checks a few edge cases. + @pytest.mark.parametrize("shape", ((6, 5), (5, 5), (5, 6))) + @pytest.mark.parametrize("dtype", (float, complex)) + def test_svd_LM_ones_matrix(self, shape, dtype): + # Check that svds can deal with matrix_rank less than k in LM mode. + k = 3 + n, m = shape + A = np.ones((n, m), dtype=dtype) + + if self.solver == 'lobpcg': + with pytest.warns(UserWarning, match="The problem size"): + U, s, VH = svds(A, k, solver=self.solver, rng=0) + else: + U, s, VH = svds(A, k, solver=self.solver, rng=0) + + _check_svds(A, k, U, s, VH, check_usvh_A=True, check_svd=False) + + # Check that the largest singular value is near sqrt(n*m) + # and the other singular values have been forced to zero. + assert_allclose(np.max(s), np.sqrt(n*m)) + s = np.array(sorted(s)[:-1]) + 1 + z = np.ones_like(s) + assert_allclose(s, z) + + @pytest.mark.filterwarnings("ignore:k >= N - 1", + reason="needed to demonstrate #16725") + @pytest.mark.parametrize("shape", ((3, 4), (4, 4), (4, 3), (4, 2))) + @pytest.mark.parametrize("dtype", (float, complex)) + def test_zero_matrix(self, shape, dtype): + # Check that svds can deal with matrices containing only zeros; + # see https://github.com/scipy/scipy/issues/3452/ + # shape = (4, 2) is included because it is the particular case + # reported in the issue + k = 1 + n, m = shape + A = np.zeros((n, m), dtype=dtype) + + if (self.solver == 'arpack'): + pytest.skip('See gh-21110.') + + if (self.solver == 'arpack' and dtype is complex + and k == min(A.shape) - 1): + pytest.skip("#16725") + + if self.solver == 'propack': + pytest.skip("PROPACK failures unrelated to PR #16712") + + if self.solver == 'lobpcg': + with pytest.warns(UserWarning, match="The problem size"): + U, s, VH = svds(A, k, solver=self.solver, rng=0) + else: + U, s, VH = svds(A, k, solver=self.solver, rng=0) + + # Check some generic properties of svd. + _check_svds(A, k, U, s, VH, check_usvh_A=True, check_svd=False) + + # Check that the singular values are zero. + assert_array_equal(s, 0) + + @pytest.mark.parametrize("shape", ((20, 20), (20, 21), (21, 20))) + @pytest.mark.parametrize("dtype", (np.float32, np.float64, + np.complex64, np.complex128)) + @pytest.mark.filterwarnings("ignore:Exited", + reason="Ignore LOBPCG early exit.") + def test_small_sigma(self, shape, dtype): + rng = np.random.default_rng(179847540) + A = rng.random(shape).astype(dtype) + u, _, vh = svd(A, full_matrices=False) + if dtype in [np.float32, np.complex64]: + e = 10.0 + else: + e = 100.0 + t = e**(-np.arange(len(vh))).astype(dtype) + A = (u*t).dot(vh) + k = 4 + u, s, vh = svds(A, k, solver=self.solver, maxiter=100, rng=0) + t = np.sum(s > 0) + assert_equal(t, k) + # LOBPCG needs larger atol and rtol to pass + _check_svds_n(A, k, u, s, vh, atol=1e-3, rtol=1e0, check_svd=False) + + @pytest.mark.filterwarnings("ignore:The problem size") + @pytest.mark.parametrize("dtype", (np.float32, np.float64, + np.complex64, np.complex128)) + def test_small_sigma2(self, dtype): + rng = np.random.default_rng(179847540) + # create a 10x10 singular matrix with a 4-dim null space + dim = 4 + size = 10 + x = rng.random((size, size-dim)) + y = x[:, :dim] * rng.random(dim) + mat = np.hstack((x, y)) + mat = mat.astype(dtype) + + nz = null_space(mat) + assert_equal(nz.shape[1], dim) + + # Tolerances atol and rtol adjusted to pass np.float32 + # Use non-sparse svd + u, s, vh = svd(mat) + # Singular values are 0: + assert_allclose(s[-dim:], 0, atol=1e-6, rtol=1e0) + # Smallest right singular vectors in null space: + assert_allclose(mat @ vh[-dim:, :].T, 0, atol=1e-6, rtol=1e0) + + # Smallest singular values should be 0 + sp_mat = csc_array(mat) + su, ss, svh = svds(sp_mat, k=dim, which='SM', solver=self.solver, rng=0) + # Smallest dim singular values are 0: + assert_allclose(ss, 0, atol=1e-5, rtol=1e0) + # Smallest singular vectors via svds in null space: + n, m = mat.shape + if n < m: # else the assert fails with some libraries unclear why + assert_allclose(sp_mat.transpose() @ su, 0, atol=1e-5, rtol=1e0) + assert_allclose(sp_mat @ svh.T, 0, atol=1e-5, rtol=1e0) + +# --- Perform tests with each solver --- + + +class Test_SVDS_once: + @pytest.mark.parametrize("solver", ['ekki', object]) + def test_svds_input_validation_solver(self, solver): + message = "solver must be one of" + with pytest.raises(ValueError, match=message): + svds(np.ones((3, 4)), k=2, solver=solver, rng=0) + + +class Test_SVDS_ARPACK(SVDSCommonTests): + + def setup_method(self): + self.solver = 'arpack' + + @pytest.mark.parametrize("ncv", list(range(-1, 8)) + [4.5, "5"]) + def test_svds_input_validation_ncv_1(self, ncv): + rng = np.random.default_rng(0) + A = rng.random((6, 7)) + k = 3 + if ncv in {4, 5}: + u, s, vh = svds(A, k=k, ncv=ncv, solver=self.solver, rng=0) + # partial decomposition, so don't check that u@diag(s)@vh=A; + # do check that scipy.sparse.linalg.svds ~ scipy.linalg.svd + _check_svds(A, k, u, s, vh) + else: + message = ("`ncv` must be an integer satisfying") + with pytest.raises(ValueError, match=message): + svds(A, k=k, ncv=ncv, solver=self.solver, rng=0) + + def test_svds_input_validation_ncv_2(self): + # I think the stack trace is reasonable when `ncv` can't be converted + # to an int. + message = "int() argument must be a" + with pytest.raises(TypeError, match=re.escape(message)): + svds(np.eye(10), ncv=[], solver=self.solver, rng=0) + + message = "invalid literal for int()" + with pytest.raises(ValueError, match=message): + svds(np.eye(10), ncv="hi", solver=self.solver, rng=0) + + # I can't see a robust relationship between `ncv` and relevant outputs + # (e.g. accuracy, time), so no test of the parameter. + + +class Test_SVDS_LOBPCG(SVDSCommonTests): + + def setup_method(self): + self.solver = 'lobpcg' + + +class Test_SVDS_PROPACK(SVDSCommonTests): + + def setup_method(self): + self.solver = 'propack' + + def test_svd_LM_ones_matrix(self): + message = ("PROPACK does not return orthonormal singular vectors " + "associated with zero singular values.") + # There are some other issues with this matrix of all ones, e.g. + # `which='sm'` and `k=1` returns the largest singular value + pytest.xfail(message) + + def test_svd_LM_zeros_matrix(self): + message = ("PROPACK does not return orthonormal singular vectors " + "associated with zero singular values.") + pytest.xfail(message) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_expm_multiply.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_expm_multiply.py new file mode 100644 index 0000000000000000000000000000000000000000..8f5a7a8508a6a9d102a836469d8fb76ddc9534b4 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_expm_multiply.py @@ -0,0 +1,816 @@ +"""Compute the action of the matrix exponential.""" +from warnings import warn + +import numpy as np + +import scipy.linalg +import scipy.sparse.linalg +from scipy.linalg._decomp_qr import qr +from scipy.sparse._sputils import is_pydata_spmatrix +from scipy.sparse.linalg import aslinearoperator +from scipy.sparse.linalg._interface import IdentityOperator +from scipy.sparse.linalg._onenormest import onenormest + +__all__ = ['expm_multiply'] + + +def _exact_inf_norm(A): + # A compatibility function which should eventually disappear. + if scipy.sparse.issparse(A): + return max(abs(A).sum(axis=1).flat) + elif is_pydata_spmatrix(A): + return max(abs(A).sum(axis=1)) + else: + return np.linalg.norm(A, np.inf) + + +def _exact_1_norm(A): + # A compatibility function which should eventually disappear. + if scipy.sparse.issparse(A): + return max(abs(A).sum(axis=0).flat) + elif is_pydata_spmatrix(A): + return max(abs(A).sum(axis=0)) + else: + return np.linalg.norm(A, 1) + + +def _trace(A): + # A compatibility function which should eventually disappear. + if is_pydata_spmatrix(A): + return A.to_scipy_sparse().trace() + else: + return A.trace() + + +def traceest(A, m3, seed=None): + """Estimate `np.trace(A)` using `3*m3` matrix-vector products. + + The result is not deterministic. + + Parameters + ---------- + A : LinearOperator + Linear operator whose trace will be estimated. Has to be square. + m3 : int + Number of matrix-vector products divided by 3 used to estimate the + trace. + seed : optional + Seed for `numpy.random.default_rng`. + Can be provided to obtain deterministic results. + + Returns + ------- + trace : LinearOperator.dtype + Estimate of the trace + + Notes + ----- + This is the Hutch++ algorithm given in [1]_. + + References + ---------- + .. [1] Meyer, Raphael A., Cameron Musco, Christopher Musco, and David P. + Woodruff. "Hutch++: Optimal Stochastic Trace Estimation." In Symposium + on Simplicity in Algorithms (SOSA), pp. 142-155. Society for Industrial + and Applied Mathematics, 2021 + https://doi.org/10.1137/1.9781611976496.16 + + """ + rng = np.random.default_rng(seed) + if len(A.shape) != 2 or A.shape[-1] != A.shape[-2]: + raise ValueError("Expected A to be like a square matrix.") + n = A.shape[-1] + S = rng.choice([-1.0, +1.0], [n, m3]) + Q, _ = qr(A.matmat(S), overwrite_a=True, mode='economic') + trQAQ = np.trace(Q.conj().T @ A.matmat(Q)) + G = rng.choice([-1, +1], [n, m3]) + right = G - Q@(Q.conj().T @ G) + trGAG = np.trace(right.conj().T @ A.matmat(right)) + return trQAQ + trGAG/m3 + + +def _ident_like(A): + # A compatibility function which should eventually disappear. + if scipy.sparse.issparse(A): + # Creates a sparse matrix in dia format + out = scipy.sparse.eye(A.shape[0], A.shape[1], dtype=A.dtype) + if scipy.sparse.issparse(A): + return out.asformat(A.format) + return scipy.sparse.dia_array(out).asformat(A.format) + elif is_pydata_spmatrix(A): + import sparse + return sparse.eye(A.shape[0], A.shape[1], dtype=A.dtype) + elif isinstance(A, scipy.sparse.linalg.LinearOperator): + return IdentityOperator(A.shape, dtype=A.dtype) + else: + return np.eye(A.shape[0], A.shape[1], dtype=A.dtype) + + +def expm_multiply(A, B, start=None, stop=None, num=None, + endpoint=None, traceA=None): + """ + Compute the action of the matrix exponential of A on B. + + Parameters + ---------- + A : transposable linear operator + The operator whose exponential is of interest. + B : ndarray, sparse array + The matrix or vector to be multiplied by the matrix exponential of A. + start : scalar, optional + The starting time point of the sequence. + stop : scalar, optional + The end time point of the sequence, unless `endpoint` is set to False. + In that case, the sequence consists of all but the last of ``num + 1`` + evenly spaced time points, so that `stop` is excluded. + Note that the step size changes when `endpoint` is False. + num : int, optional + Number of time points to use. + endpoint : bool, optional + If True, `stop` is the last time point. Otherwise, it is not included. + traceA : scalar, optional + Trace of `A`. If not given the trace is estimated for linear operators, + or calculated exactly for sparse matrices. It is used to precondition + `A`, thus an approximate trace is acceptable. + For linear operators, `traceA` should be provided to ensure performance + as the estimation is not guaranteed to be reliable for all cases. + + .. versionadded:: 1.9.0 + + Returns + ------- + expm_A_B : ndarray + The result of the action :math:`e^{t_k A} B`. + + Warns + ----- + UserWarning + If `A` is a linear operator and ``traceA=None`` (default). + + Notes + ----- + The optional arguments defining the sequence of evenly spaced time points + are compatible with the arguments of `numpy.linspace`. + + The output ndarray shape is somewhat complicated so I explain it here. + The ndim of the output could be either 1, 2, or 3. + It would be 1 if you are computing the expm action on a single vector + at a single time point. + It would be 2 if you are computing the expm action on a vector + at multiple time points, or if you are computing the expm action + on a matrix at a single time point. + It would be 3 if you want the action on a matrix with multiple + columns at multiple time points. + If multiple time points are requested, expm_A_B[0] will always + be the action of the expm at the first time point, + regardless of whether the action is on a vector or a matrix. + + References + ---------- + .. [1] Awad H. Al-Mohy and Nicholas J. Higham (2011) + "Computing the Action of the Matrix Exponential, + with an Application to Exponential Integrators." + SIAM Journal on Scientific Computing, + 33 (2). pp. 488-511. ISSN 1064-8275 + http://eprints.ma.man.ac.uk/1591/ + + .. [2] Nicholas J. Higham and Awad H. Al-Mohy (2010) + "Computing Matrix Functions." + Acta Numerica, + 19. 159-208. ISSN 0962-4929 + http://eprints.ma.man.ac.uk/1451/ + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import expm, expm_multiply + >>> A = csc_array([[1, 0], [0, 1]]) + >>> A.toarray() + array([[1, 0], + [0, 1]], dtype=int64) + >>> B = np.array([np.exp(-1.), np.exp(-2.)]) + >>> B + array([ 0.36787944, 0.13533528]) + >>> expm_multiply(A, B, start=1, stop=2, num=3, endpoint=True) + array([[ 1. , 0.36787944], + [ 1.64872127, 0.60653066], + [ 2.71828183, 1. ]]) + >>> expm(A).dot(B) # Verify 1st timestep + array([ 1. , 0.36787944]) + >>> expm(1.5*A).dot(B) # Verify 2nd timestep + array([ 1.64872127, 0.60653066]) + >>> expm(2*A).dot(B) # Verify 3rd timestep + array([ 2.71828183, 1. ]) + """ + if all(arg is None for arg in (start, stop, num, endpoint)): + X = _expm_multiply_simple(A, B, traceA=traceA) + else: + X, status = _expm_multiply_interval(A, B, start, stop, num, + endpoint, traceA=traceA) + return X + + +def _expm_multiply_simple(A, B, t=1.0, traceA=None, balance=False): + """ + Compute the action of the matrix exponential at a single time point. + + Parameters + ---------- + A : transposable linear operator + The operator whose exponential is of interest. + B : ndarray + The matrix to be multiplied by the matrix exponential of A. + t : float + A time point. + traceA : scalar, optional + Trace of `A`. If not given the trace is estimated for linear operators, + or calculated exactly for sparse matrices. It is used to precondition + `A`, thus an approximate trace is acceptable + balance : bool + Indicates whether or not to apply balancing. + + Returns + ------- + F : ndarray + :math:`e^{t A} B` + + Notes + ----- + This is algorithm (3.2) in Al-Mohy and Higham (2011). + + """ + if balance: + raise NotImplementedError + if len(A.shape) != 2 or A.shape[0] != A.shape[1]: + raise ValueError('expected A to be like a square matrix') + if A.shape[1] != B.shape[0]: + raise ValueError(f'shapes of matrices A {A.shape} and B {B.shape}' + ' are incompatible') + ident = _ident_like(A) + is_linear_operator = isinstance(A, scipy.sparse.linalg.LinearOperator) + n = A.shape[0] + if len(B.shape) == 1: + n0 = 1 + elif len(B.shape) == 2: + n0 = B.shape[1] + else: + raise ValueError('expected B to be like a matrix or a vector') + u_d = 2**-53 + tol = u_d + if traceA is None: + if is_linear_operator: + warn("Trace of LinearOperator not available, it will be estimated." + " Provide `traceA` to ensure performance.", stacklevel=3) + # m3=1 is bit arbitrary choice, a more accurate trace (larger m3) might + # speed up exponential calculation, but trace estimation is more costly + traceA = traceest(A, m3=1) if is_linear_operator else _trace(A) + mu = traceA / float(n) + A = A - mu * ident + A_1_norm = onenormest(A) if is_linear_operator else _exact_1_norm(A) + if t*A_1_norm == 0: + m_star, s = 0, 1 + else: + ell = 2 + norm_info = LazyOperatorNormInfo(t*A, A_1_norm=t*A_1_norm, ell=ell) + m_star, s = _fragment_3_1(norm_info, n0, tol, ell=ell) + return _expm_multiply_simple_core(A, B, t, mu, m_star, s, tol, balance) + + +def _expm_multiply_simple_core(A, B, t, mu, m_star, s, tol=None, balance=False): + """ + A helper function. + """ + if balance: + raise NotImplementedError + if tol is None: + u_d = 2 ** -53 + tol = u_d + F = B + eta = np.exp(t*mu / float(s)) + for i in range(s): + c1 = _exact_inf_norm(B) + for j in range(m_star): + coeff = t / float(s*(j+1)) + B = coeff * A.dot(B) + c2 = _exact_inf_norm(B) + F = F + B + if c1 + c2 <= tol * _exact_inf_norm(F): + break + c1 = c2 + F = eta * F + B = F + return F + + +# This table helps to compute bounds. +# They seem to have been difficult to calculate, involving symbolic +# manipulation of equations, followed by numerical root finding. +_theta = { + # The first 30 values are from table A.3 of Computing Matrix Functions. + 1: 2.29e-16, + 2: 2.58e-8, + 3: 1.39e-5, + 4: 3.40e-4, + 5: 2.40e-3, + 6: 9.07e-3, + 7: 2.38e-2, + 8: 5.00e-2, + 9: 8.96e-2, + 10: 1.44e-1, + # 11 + 11: 2.14e-1, + 12: 3.00e-1, + 13: 4.00e-1, + 14: 5.14e-1, + 15: 6.41e-1, + 16: 7.81e-1, + 17: 9.31e-1, + 18: 1.09, + 19: 1.26, + 20: 1.44, + # 21 + 21: 1.62, + 22: 1.82, + 23: 2.01, + 24: 2.22, + 25: 2.43, + 26: 2.64, + 27: 2.86, + 28: 3.08, + 29: 3.31, + 30: 3.54, + # The rest are from table 3.1 of + # Computing the Action of the Matrix Exponential. + 35: 4.7, + 40: 6.0, + 45: 7.2, + 50: 8.5, + 55: 9.9, + } + + +def _onenormest_matrix_power(A, p, + t=2, itmax=5, compute_v=False, compute_w=False): + """ + Efficiently estimate the 1-norm of A^p. + + Parameters + ---------- + A : ndarray + Matrix whose 1-norm of a power is to be computed. + p : int + Non-negative integer power. + t : int, optional + A positive parameter controlling the tradeoff between + accuracy versus time and memory usage. + Larger values take longer and use more memory + but give more accurate output. + itmax : int, optional + Use at most this many iterations. + compute_v : bool, optional + Request a norm-maximizing linear operator input vector if True. + compute_w : bool, optional + Request a norm-maximizing linear operator output vector if True. + + Returns + ------- + est : float + An underestimate of the 1-norm of the sparse matrix. + v : ndarray, optional + The vector such that ||Av||_1 == est*||v||_1. + It can be thought of as an input to the linear operator + that gives an output with particularly large norm. + w : ndarray, optional + The vector Av which has relatively large 1-norm. + It can be thought of as an output of the linear operator + that is relatively large in norm compared to the input. + + """ + #XXX Eventually turn this into an API function in the _onenormest module, + #XXX and remove its underscore, + #XXX but wait until expm_multiply goes into scipy. + from scipy.sparse.linalg._onenormest import onenormest + return onenormest(aslinearoperator(A) ** p) + +class LazyOperatorNormInfo: + """ + Information about an operator is lazily computed. + + The information includes the exact 1-norm of the operator, + in addition to estimates of 1-norms of powers of the operator. + This uses the notation of Computing the Action (2011). + This class is specialized enough to probably not be of general interest + outside of this module. + + """ + + def __init__(self, A, A_1_norm=None, ell=2, scale=1): + """ + Provide the operator and some norm-related information. + + Parameters + ---------- + A : linear operator + The operator of interest. + A_1_norm : float, optional + The exact 1-norm of A. + ell : int, optional + A technical parameter controlling norm estimation quality. + scale : int, optional + If specified, return the norms of scale*A instead of A. + + """ + self._A = A + self._A_1_norm = A_1_norm + self._ell = ell + self._d = {} + self._scale = scale + + def set_scale(self,scale): + """ + Set the scale parameter. + """ + self._scale = scale + + def onenorm(self): + """ + Compute the exact 1-norm. + """ + if self._A_1_norm is None: + self._A_1_norm = _exact_1_norm(self._A) + return self._scale*self._A_1_norm + + def d(self, p): + """ + Lazily estimate :math:`d_p(A) ~= || A^p ||^(1/p)` + where :math:`||.||` is the 1-norm. + """ + if p not in self._d: + est = _onenormest_matrix_power(self._A, p, self._ell) + self._d[p] = est ** (1.0 / p) + return self._scale*self._d[p] + + def alpha(self, p): + """ + Lazily compute max(d(p), d(p+1)). + """ + return max(self.d(p), self.d(p+1)) + +def _compute_cost_div_m(m, p, norm_info): + """ + A helper function for computing bounds. + + This is equation (3.10). + It measures cost in terms of the number of required matrix products. + + Parameters + ---------- + m : int + A valid key of _theta. + p : int + A matrix power. + norm_info : LazyOperatorNormInfo + Information about 1-norms of related operators. + + Returns + ------- + cost_div_m : int + Required number of matrix products divided by m. + + """ + return int(np.ceil(norm_info.alpha(p) / _theta[m])) + + +def _compute_p_max(m_max): + """ + Compute the largest positive integer p such that p*(p-1) <= m_max + 1. + + Do this in a slightly dumb way, but safe and not too slow. + + Parameters + ---------- + m_max : int + A count related to bounds. + + """ + sqrt_m_max = np.sqrt(m_max) + p_low = int(np.floor(sqrt_m_max)) + p_high = int(np.ceil(sqrt_m_max + 1)) + return max(p for p in range(p_low, p_high+1) if p*(p-1) <= m_max + 1) + + +def _fragment_3_1(norm_info, n0, tol, m_max=55, ell=2): + """ + A helper function for the _expm_multiply_* functions. + + Parameters + ---------- + norm_info : LazyOperatorNormInfo + Information about norms of certain linear operators of interest. + n0 : int + Number of columns in the _expm_multiply_* B matrix. + tol : float + Expected to be + :math:`2^{-24}` for single precision or + :math:`2^{-53}` for double precision. + m_max : int + A value related to a bound. + ell : int + The number of columns used in the 1-norm approximation. + This is usually taken to be small, maybe between 1 and 5. + + Returns + ------- + best_m : int + Related to bounds for error control. + best_s : int + Amount of scaling. + + Notes + ----- + This is code fragment (3.1) in Al-Mohy and Higham (2011). + The discussion of default values for m_max and ell + is given between the definitions of equation (3.11) + and the definition of equation (3.12). + + """ + if ell < 1: + raise ValueError('expected ell to be a positive integer') + best_m = None + best_s = None + if _condition_3_13(norm_info.onenorm(), n0, m_max, ell): + for m, theta in _theta.items(): + s = int(np.ceil(norm_info.onenorm() / theta)) + if best_m is None or m * s < best_m * best_s: + best_m = m + best_s = s + else: + # Equation (3.11). + for p in range(2, _compute_p_max(m_max) + 1): + for m in range(p*(p-1)-1, m_max+1): + if m in _theta: + s = _compute_cost_div_m(m, p, norm_info) + if best_m is None or m * s < best_m * best_s: + best_m = m + best_s = s + best_s = max(best_s, 1) + return best_m, best_s + + +def _condition_3_13(A_1_norm, n0, m_max, ell): + """ + A helper function for the _expm_multiply_* functions. + + Parameters + ---------- + A_1_norm : float + The precomputed 1-norm of A. + n0 : int + Number of columns in the _expm_multiply_* B matrix. + m_max : int + A value related to a bound. + ell : int + The number of columns used in the 1-norm approximation. + This is usually taken to be small, maybe between 1 and 5. + + Returns + ------- + value : bool + Indicates whether or not the condition has been met. + + Notes + ----- + This is condition (3.13) in Al-Mohy and Higham (2011). + + """ + + # This is the rhs of equation (3.12). + p_max = _compute_p_max(m_max) + a = 2 * ell * p_max * (p_max + 3) + + # Evaluate the condition (3.13). + b = _theta[m_max] / float(n0 * m_max) + return A_1_norm <= a * b + + +def _expm_multiply_interval(A, B, start=None, stop=None, num=None, + endpoint=None, traceA=None, balance=False, + status_only=False): + """ + Compute the action of the matrix exponential at multiple time points. + + Parameters + ---------- + A : transposable linear operator + The operator whose exponential is of interest. + B : ndarray + The matrix to be multiplied by the matrix exponential of A. + start : scalar, optional + The starting time point of the sequence. + stop : scalar, optional + The end time point of the sequence, unless `endpoint` is set to False. + In that case, the sequence consists of all but the last of ``num + 1`` + evenly spaced time points, so that `stop` is excluded. + Note that the step size changes when `endpoint` is False. + num : int, optional + Number of time points to use. + traceA : scalar, optional + Trace of `A`. If not given the trace is estimated for linear operators, + or calculated exactly for sparse matrices. It is used to precondition + `A`, thus an approximate trace is acceptable + endpoint : bool, optional + If True, `stop` is the last time point. Otherwise, it is not included. + balance : bool + Indicates whether or not to apply balancing. + status_only : bool + A flag that is set to True for some debugging and testing operations. + + Returns + ------- + F : ndarray + :math:`e^{t_k A} B` + status : int + An integer status for testing and debugging. + + Notes + ----- + This is algorithm (5.2) in Al-Mohy and Higham (2011). + + There seems to be a typo, where line 15 of the algorithm should be + moved to line 6.5 (between lines 6 and 7). + + """ + if balance: + raise NotImplementedError + if len(A.shape) != 2 or A.shape[0] != A.shape[1]: + raise ValueError('expected A to be like a square matrix') + if A.shape[1] != B.shape[0]: + raise ValueError(f'shapes of matrices A {A.shape} and B {B.shape}' + ' are incompatible') + ident = _ident_like(A) + is_linear_operator = isinstance(A, scipy.sparse.linalg.LinearOperator) + n = A.shape[0] + if len(B.shape) == 1: + n0 = 1 + elif len(B.shape) == 2: + n0 = B.shape[1] + else: + raise ValueError('expected B to be like a matrix or a vector') + u_d = 2**-53 + tol = u_d + if traceA is None: + if is_linear_operator: + warn("Trace of LinearOperator not available, it will be estimated." + " Provide `traceA` to ensure performance.", stacklevel=3) + # m3=5 is bit arbitrary choice, a more accurate trace (larger m3) might + # speed up exponential calculation, but trace estimation is also costly + # an educated guess would need to consider the number of time points + traceA = traceest(A, m3=5) if is_linear_operator else _trace(A) + mu = traceA / float(n) + + # Get the linspace samples, attempting to preserve the linspace defaults. + linspace_kwargs = {'retstep': True} + if num is not None: + linspace_kwargs['num'] = num + if endpoint is not None: + linspace_kwargs['endpoint'] = endpoint + samples, step = np.linspace(start, stop, **linspace_kwargs) + + # Convert the linspace output to the notation used by the publication. + nsamples = len(samples) + if nsamples < 2: + raise ValueError('at least two time points are required') + q = nsamples - 1 + h = step + t_0 = samples[0] + t_q = samples[q] + + # Define the output ndarray. + # Use an ndim=3 shape, such that the last two indices + # are the ones that may be involved in level 3 BLAS operations. + X_shape = (nsamples,) + B.shape + X = np.empty(X_shape, dtype=np.result_type(A.dtype, B.dtype, float)) + t = t_q - t_0 + A = A - mu * ident + A_1_norm = onenormest(A) if is_linear_operator else _exact_1_norm(A) + ell = 2 + norm_info = LazyOperatorNormInfo(t*A, A_1_norm=t*A_1_norm, ell=ell) + if t*A_1_norm == 0: + m_star, s = 0, 1 + else: + m_star, s = _fragment_3_1(norm_info, n0, tol, ell=ell) + + # Compute the expm action up to the initial time point. + action_t0 = _expm_multiply_simple_core(A, B, t_0, mu, m_star, s) + if scipy.sparse.issparse(action_t0): + action_t0 = action_t0.toarray() + elif is_pydata_spmatrix(action_t0): + action_t0 = action_t0.todense() + X[0] = action_t0 + + # Compute the expm action at the rest of the time points. + if q <= s: + if status_only: + return 0 + else: + return _expm_multiply_interval_core_0(A, X, + h, mu, q, norm_info, tol, ell,n0) + elif not (q % s): + if status_only: + return 1 + else: + return _expm_multiply_interval_core_1(A, X, + h, mu, m_star, s, q, tol) + elif (q % s): + if status_only: + return 2 + else: + return _expm_multiply_interval_core_2(A, X, + h, mu, m_star, s, q, tol) + else: + raise Exception('internal error') + + +def _expm_multiply_interval_core_0(A, X, h, mu, q, norm_info, tol, ell, n0): + """ + A helper function, for the case q <= s. + """ + + # Compute the new values of m_star and s which should be applied + # over intervals of size t/q + if norm_info.onenorm() == 0: + m_star, s = 0, 1 + else: + norm_info.set_scale(1./q) + m_star, s = _fragment_3_1(norm_info, n0, tol, ell=ell) + norm_info.set_scale(1) + + for k in range(q): + X[k+1] = _expm_multiply_simple_core(A, X[k], h, mu, m_star, s) + return X, 0 + + +def _expm_multiply_interval_core_1(A, X, h, mu, m_star, s, q, tol): + """ + A helper function, for the case q > s and q % s == 0. + """ + d = q // s + input_shape = X.shape[1:] + K_shape = (m_star + 1, ) + input_shape + K = np.empty(K_shape, dtype=X.dtype) + for i in range(s): + Z = X[i*d] + K[0] = Z + high_p = 0 + for k in range(1, d+1): + F = K[0] + c1 = _exact_inf_norm(F) + for p in range(1, m_star+1): + if p > high_p: + K[p] = h * A.dot(K[p-1]) / float(p) + coeff = float(pow(k, p)) + F = F + coeff * K[p] + inf_norm_K_p_1 = _exact_inf_norm(K[p]) + c2 = coeff * inf_norm_K_p_1 + if c1 + c2 <= tol * _exact_inf_norm(F): + break + c1 = c2 + X[k + i*d] = np.exp(k*h*mu) * F + return X, 1 + + +def _expm_multiply_interval_core_2(A, X, h, mu, m_star, s, q, tol): + """ + A helper function, for the case q > s and q % s > 0. + """ + d = q // s + j = q // d + r = q - d * j + input_shape = X.shape[1:] + K_shape = (m_star + 1, ) + input_shape + K = np.empty(K_shape, dtype=X.dtype) + for i in range(j + 1): + Z = X[i*d] + K[0] = Z + high_p = 0 + if i < j: + effective_d = d + else: + effective_d = r + for k in range(1, effective_d+1): + F = K[0] + c1 = _exact_inf_norm(F) + for p in range(1, m_star+1): + if p == high_p + 1: + K[p] = h * A.dot(K[p-1]) / float(p) + high_p = p + coeff = float(pow(k, p)) + F = F + coeff * K[p] + inf_norm_K_p_1 = _exact_inf_norm(K[p]) + c2 = coeff * inf_norm_K_p_1 + if c1 + c2 <= tol * _exact_inf_norm(F): + break + c1 = c2 + X[k + i*d] = np.exp(k*h*mu) * F + return X, 2 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_funm_multiply_krylov.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_funm_multiply_krylov.py new file mode 100644 index 0000000000000000000000000000000000000000..c0fb2e1aa5ae992969d4794e7806657a0c46ff67 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_funm_multiply_krylov.py @@ -0,0 +1,348 @@ +""" + Restared Krylov method for evaluating f(A)b + + The original code was written in MATLAB by Stefan Guttel. + It was later adapted to C++ and Python by Nicolas Guidotti. + Both authors agrees to relicense the code under the BSD license. + + Copyright (C) 2025 Nicolas Guidotti and Stefan Guttel. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" + +import numpy as np +from scipy.linalg import norm +from ._isolve.iterative import _get_atol_rtol + +__all__ = ['funm_multiply_krylov'] + +def _funm_multiply_krylov_arnoldi(A, b, bnorm, V, H, m): + """ + The Arnoldi iteration for constructing the basis V and the projection H = V * A V + for the Krylov subspace Km(A, b) of order m. + + Parameters + ---------- + A : transposable linear operator + The operator whose matrix function is of interest. + b : ndarray + The vector b to multiply the f(A) with. + V : ndarray + The n x (m + 1) matrix whose columns determines the basis for + Krylov subspace Km(A, b). + H : ndarray + A (m + 1) x m upper Hessenberg matrix representing the projection of A + onto Km(A, b). + m : int + The order of the Krylov subspace. + + Returns + ------- + breakdown : bool + Indicate if the Arnoldi broke down or not + + iter : int + Returns the last valid iteration. + + """ + + dotprod = np.vdot if np.iscomplexobj(b) else np.dot + norm_tol = np.finfo(b.dtype.char).eps ** 2 + V[:, 0] = b / bnorm + + for k in range(0, m): + V[:, k + 1] = A.dot(V[:, k]) + + # Uses the modified Gram-Schmift process to orthogonalize V[:, k + 1] + # against the previous basis vectors + for i in range(0, k + 1): + H[i, k] = dotprod(V[:, i], V[:, k + 1]) + V[:, k + 1] = V[:, k + 1] - H[i, k] * V[:, i] + + H[k + 1, k] = norm(V[:, k + 1]) + if H[k + 1, k] < norm_tol: + return True, k + + V[:, k + 1] = V[:, k + 1] / H[k + 1, k] + + return False, m + +def _funm_multiply_krylov_lanczos(A, b, bnorm, V, H, m): + """ + The Lanczos iteration for constructing the basis V and the projection H = V * A V + for the Krylov subspace Km(A, b) of order m. A must be Hermitian. + + Parameters + ---------- + A : transposable linear operator + The operator whose matrix function is of interest. + b : ndarray + The vector b to multiply the f(A) with. + V : ndarray + The n x (m + 1) matrix whose columns determines the basis for + Krylov subspace Km(A, b). + H : ndarray + A (m + 1) x m upper Hessenberg matrix representing the projection of A + onto Km(A, b). + m : int + The order of the Krylov subspace. + + Returns + ------- + breakdown : bool + Indicate if the Arnoldi broke down or not + + iter : int + Returns the last valid iteration. + + """ + dotprod = np.vdot if np.iscomplexobj(b) else np.dot + norm_tol = np.finfo(b.dtype.char).eps ** 2 + V[:, 0] = b / bnorm + + for k in range(0, m): + if k > 0: + V[:, k + 1] = A.dot(V[:, k]) - H[k, k - 1] * V[:, k - 1] + else: + V[:, k + 1] = A.dot(V[:, k]) + + H[k, k] = dotprod(V[:, k + 1], V[:, k]) + V[:, k + 1] = V[:, k + 1] - H[k, k] * V[:, k] + + H[k + 1, k] = norm(V[:, k + 1]) + + if H[k + 1, k] < norm_tol: + return True, k + + V[:, k + 1] = V[:, k + 1] / H[k + 1, k] + if k < m - 1: + H[k, k + 1] = H[k + 1, k] + + return False, m + + +def funm_multiply_krylov(f, A, b, *, assume_a = "general", t = 1.0, atol = 0.0, + rtol = 1e-6, restart_every_m = None, max_restarts = 20): + """ + A restarted Krylov method for evaluating ``y = f(tA) b`` from [1]_ [2]_. + + Parameters + ---------- + f : callable + Callable object that computes the matrix function ``F = f(X)``. + + A : {sparse array, ndarray, LinearOperator} + A real or complex N-by-N matrix. + Alternatively, `A` can be a linear operator which can + produce ``Ax`` using, e.g., ``scipy.sparse.linalg.LinearOperator``. + + b : ndarray + A vector to multiply the ``f(tA)`` with. + + assume_a : string, optional + Indicate the structure of ``A``. The algorithm will use this information + to select the appropriated code path. The available options are + 'hermitian'/'her' and 'general'/'gen'. If ommited, then it is assumed + that ``A`` has a 'general' structure. + + t : float, optional + The value to scale the matrix ``A`` with. The default is ``t = 1.0`` + + atol, rtol : float, optional + Parameters for the convergence test. For convergence, + ``norm(||y_k - y_k-1||) <= max(rtol*norm(b), atol)`` should be satisfied. + The default is ``atol=0.`` and ``rtol=1e-6``. + + restart_every_m : integer + If the iteration number reaches this value a restart is triggered. + Larger values increase iteration cost but may be necessary for convergence. + If omitted, ``min(20, n)`` is used. + + max_restarts : int, optional + Maximum number of restart cycles. The algorithm will stop + after max_restarts cycles even if the specified tolerance has not been + achieved. The default is ``max_restarts=20`` + + Returns + ------- + y : ndarray + The result of ``f(tA) b``. + + Notes + ----- + The convergence of the Krylov method heavily depends on the spectrum + of ``A`` and the function ``f``. With restarting, there are only formal + proofs for functions of order 1 (e.g., ``exp``, ``sin``, ``cos``) and + Stieltjes functions [2]_ [3]_, while the general case remains an open problem. + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csr_array + >>> from scipy.sparse.linalg import funm_multiply_krylov + >>> from scipy.linalg import expm, solve + >>> A = csr_array([[3, 2, 0], [1, -1, 0], [0, 5, 1]], dtype=float) + >>> b = np.array([2, 4, -1], dtype=float) + >>> t = 0.1 + + Compute ``y = exp(tA) b``. + + >>> y = funm_multiply_krylov(expm, A, b, t = t) + >>> y + array([3.6164913 , 3.88421511 , 0.96073457]) + + >>> ref = expm(t * A.todense()) @ b + >>> err = y - ref + >>> err + array([4.44089210e-16 , 0.00000000e+00 , 2.22044605e-16]) + + Compute :math:`y = (A^3 - A) b`. + + >>> poly = lambda X : X @ X @ X - X + >>> y = funm_multiply_krylov(poly, A, b) + >>> y + array([132. , 24. , 70.]) + + >>> ref = poly(A.todense()) @ b + >>> err = y - ref + >>> err + array([ 0.00000000e+00 , 7.10542736e-15 , -2.84217094e-14]) + + Compute :math:`y = f(tA) b`, where :math:`f(X) = X^{-1}(e^{X} - I)`. This is + known as the "phi function" from the exponential integrator literature. + + >>> phim_1 = lambda X : solve(X, expm(X) - np.eye(X.shape[0])) + >>> y = funm_multiply_krylov(phim_1, A, b, t = t) + >>> y + array([ 2.76984306 , 3.92769192 , -0.03111392]) + + >>> ref = phim_1(t * A.todense()) @ b + >>> err = y - ref + >>> err + array([ 0.00000000e+00 , 8.88178420e-16 , -4.60742555e-15]) + + References + ---------- + .. [1] M. Afanasjew, M. Eiermann, O. G. Ernst, and S. Güttel, + "Implementation of a restarted Krylov subspace method for the + evaluation of matrix functions," Linear Algebra and its Applications, + vol. 429, no. 10, pp. 2293-2314, Nov. 2008, :doi:`10.1016/j.laa.2008.06.029`. + + .. [2] M. Eiermann and O. G. Ernst, "A Restarted Krylov Subspace Method + for the Evaluation of Matrix Functions," SIAM J. Numer. Anal., vol. 44, + no. 6, pp. 2481-2504, Jan. 2006, :doi:`10.1137/050633846`. + + .. [3] A. Frommer, S. Güttel, and M. Schweitzer, "Convergence of Restarted + Krylov Subspace Methods for Stieltjes Functions of Matrices," SIAM J. + Matrix Anal. Appl., vol. 35, no. 4, pp. 1602-1624, + Jan. 2014, :doi:`10.1137/140973463`. + + """ + + if assume_a not in {'hermitian', 'general', 'her', 'gen'}: + raise ValueError(f'scipy.sparse.linalg.funm_multiply_krylov: {assume_a} ' + 'is not a recognized matrix structure') + is_hermitian = (assume_a == 'her') or (assume_a == 'hermitian') + + if len(b.shape) != 1: + raise ValueError("scipy.sparse.linalg.funm_multiply_krylov: " + "argument 'b' must be a 1D array.") + n = b.shape[0] + + if restart_every_m is None: + restart_every_m = min(20, n) + + restart_every_m = int(restart_every_m) + max_restarts = int(max_restarts) + + if restart_every_m <= 0: + raise ValueError("scipy.sparse.linalg.funm_multiply_krylov: " + "argument 'restart_every_m' must be positive.") + + if max_restarts <= 0: + raise ValueError("scipy.sparse.linalg.funm_multiply_krylov: " + "argument 'max_restarts' must be positive.") + + m = restart_every_m + max_restarts = min(max_restarts, int(n / m) + 1) + mmax = m * max_restarts + + bnorm = norm(b) + atol, _ = _get_atol_rtol("funm_multiply_krylov", bnorm, atol, rtol) + + if bnorm == 0: + y = np.array(b) + return y + + # Preallocate the maximum memory space. + # Using the column major order here since we work with + # each individual column separately. + internal_type = np.common_type(A, b) + V = np.zeros((n, m + 1), dtype = internal_type, order = 'F') + H = np.zeros((mmax + 1, mmax), dtype = internal_type, order = 'F') + + restart = 1 + + if is_hermitian: + breakdown, j = _funm_multiply_krylov_lanczos(A, b, bnorm, V, + H[:m + 1, :m], m) + else: + breakdown, j = _funm_multiply_krylov_arnoldi(A, b, bnorm, V, + H[:m + 1, :m], m) + + fH = f(t * H[:j, :j]) + y = bnorm * V[:, :j].dot(fH[:, 0]) + + if breakdown: + return y + + update_norm = norm(bnorm * fH[:, 0]) + + while restart < max_restarts and update_norm > atol: + begin = restart * m + end = (restart + 1) * m + + if is_hermitian: + breakdown, j = _funm_multiply_krylov_lanczos(A, V[:, m], 1, V, + H[begin:end + 1, begin:end], m) + else: + breakdown, j = _funm_multiply_krylov_arnoldi(A, V[:, m], 1, V, + H[begin:end + 1, begin:end], m) + + if breakdown: + end = begin + j + fH = f(t * H[:end, :end]) + y[:end] = y[:end] + bnorm * V[:, :m].dot(fH[begin:end, 0]) + return y + + fH = f(t * H[:end, :end]) + y = y + bnorm * V[:, :m].dot(fH[begin:end, 0]) + update_norm = norm(bnorm * fH[begin:end, 0]) + restart += 1 + + return y diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_interface.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_interface.py new file mode 100644 index 0000000000000000000000000000000000000000..5f9cfdff556439fee8c1ffed3888cb48dafca6fd --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_interface.py @@ -0,0 +1,924 @@ +"""Abstract linear algebra library. + +This module defines a class hierarchy that implements a kind of "lazy" +matrix representation, called the ``LinearOperator``. It can be used to do +linear algebra with extremely large sparse or structured matrices, without +representing those explicitly in memory. Such matrices can be added, +multiplied, transposed, etc. + +As a motivating example, suppose you want have a matrix where almost all of +the elements have the value one. The standard sparse matrix representation +skips the storage of zeros, but not ones. By contrast, a LinearOperator is +able to represent such matrices efficiently. First, we need a compact way to +represent an all-ones matrix:: + + >>> import numpy as np + >>> from scipy.sparse.linalg._interface import LinearOperator + >>> class Ones(LinearOperator): + ... def __init__(self, shape): + ... super().__init__(dtype=None, shape=shape) + ... def _matvec(self, x): + ... return np.repeat(x.sum(), self.shape[0]) + +Instances of this class emulate ``np.ones(shape)``, but using a constant +amount of storage, independent of ``shape``. The ``_matvec`` method specifies +how this linear operator multiplies with (operates on) a vector. We can now +add this operator to a sparse matrix that stores only offsets from one:: + + >>> from scipy.sparse.linalg._interface import aslinearoperator + >>> from scipy.sparse import csr_array + >>> offsets = csr_array([[1, 0, 2], [0, -1, 0], [0, 0, 3]]) + >>> A = aslinearoperator(offsets) + Ones(offsets.shape) + >>> A.dot([1, 2, 3]) + array([13, 4, 15]) + +The result is the same as that given by its dense, explicitly-stored +counterpart:: + + >>> (np.ones(A.shape, A.dtype) + offsets.toarray()).dot([1, 2, 3]) + array([13, 4, 15]) + +Several algorithms in the ``scipy.sparse`` library are able to operate on +``LinearOperator`` instances. +""" + +import types +import warnings + +import numpy as np + +from scipy.sparse import issparse +from scipy.sparse._sputils import isshape, isintlike, asmatrix, is_pydata_spmatrix + +__all__ = ['LinearOperator', 'aslinearoperator'] + + +class LinearOperator: + """Common interface for performing matrix vector products + + Many iterative methods (e.g. `cg`, `gmres`) do not need to know the + individual entries of a matrix to solve a linear system ``A@x = b``. + Such solvers only require the computation of matrix vector + products, ``A@v`` where ``v`` is a dense vector. This class serves as + an abstract interface between iterative solvers and matrix-like + objects. + + To construct a concrete `LinearOperator`, either pass appropriate + callables to the constructor of this class, or subclass it. + + A subclass must implement either one of the methods ``_matvec`` + and ``_matmat``, and the attributes/properties ``shape`` (pair of + integers) and ``dtype`` (may be None). It may call the ``__init__`` + on this class to have these attributes validated. Implementing + ``_matvec`` automatically implements ``_matmat`` (using a naive + algorithm) and vice-versa. + + Optionally, a subclass may implement ``_rmatvec`` or ``_adjoint`` + to implement the Hermitian adjoint (conjugate transpose). As with + ``_matvec`` and ``_matmat``, implementing either ``_rmatvec`` or + ``_adjoint`` implements the other automatically. Implementing + ``_adjoint`` is preferable; ``_rmatvec`` is mostly there for + backwards compatibility. + + Parameters + ---------- + shape : tuple + Matrix dimensions ``(M, N)``. + matvec : callable f(v) + Returns returns ``A @ v``. + rmatvec : callable f(v) + Returns ``A^H @ v``, where ``A^H`` is the conjugate transpose of ``A``. + matmat : callable f(V) + Returns ``A @ V``, where ``V`` is a dense matrix with dimensions ``(N, K)``. + dtype : dtype + Data type of the matrix. + rmatmat : callable f(V) + Returns ``A^H @ V``, where ``V`` is a dense matrix with dimensions ``(M, K)``. + + Attributes + ---------- + args : tuple + For linear operators describing products etc. of other linear + operators, the operands of the binary operation. + ndim : int + Number of dimensions (this is always 2) + + See Also + -------- + aslinearoperator : Construct LinearOperators + + Notes + ----- + The user-defined `matvec` function must properly handle the case + where ``v`` has shape ``(N,)`` as well as the ``(N,1)`` case. The shape of + the return type is handled internally by `LinearOperator`. + + It is highly recommended to explicitly specify the `dtype`, otherwise + it is determined automatically at the cost of a single matvec application + on ``int8`` zero vector using the promoted `dtype` of the output. + Python ``int`` could be difficult to automatically cast to numpy integers + in the definition of the `matvec` so the determination may be inaccurate. + It is assumed that `matmat`, `rmatvec`, and `rmatmat` would result in + the same dtype of the output given an ``int8`` input as `matvec`. + + LinearOperator instances can also be multiplied, added with each + other and exponentiated, all lazily: the result of these operations + is always a new, composite LinearOperator, that defers linear + operations to the original operators and combines the results. + + More details regarding how to subclass a LinearOperator and several + examples of concrete LinearOperator instances can be found in the + external project `PyLops `_. + + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse.linalg import LinearOperator + >>> def mv(v): + ... return np.array([2*v[0], 3*v[1]]) + ... + >>> A = LinearOperator((2,2), matvec=mv) + >>> A + <2x2 _CustomLinearOperator with dtype=int8> + >>> A.matvec(np.ones(2)) + array([ 2., 3.]) + >>> A @ np.ones(2) + array([ 2., 3.]) + + """ + + ndim = 2 + # Necessary for right matmul with numpy arrays. + __array_ufunc__ = None + + # generic type compatibility with scipy-stubs + __class_getitem__ = classmethod(types.GenericAlias) + + def __new__(cls, *args, **kwargs): + if cls is LinearOperator: + # Operate as _CustomLinearOperator factory. + return super().__new__(_CustomLinearOperator) + else: + obj = super().__new__(cls) + + if (type(obj)._matvec == LinearOperator._matvec + and type(obj)._matmat == LinearOperator._matmat): + warnings.warn("LinearOperator subclass should implement" + " at least one of _matvec and _matmat.", + category=RuntimeWarning, stacklevel=2) + + return obj + + def __init__(self, dtype, shape): + """Initialize this LinearOperator. + + To be called by subclasses. ``dtype`` may be None; ``shape`` should + be convertible to a length-2 tuple. + """ + if dtype is not None: + dtype = np.dtype(dtype) + + shape = tuple(shape) + if not isshape(shape): + raise ValueError(f"invalid shape {shape!r} (must be 2-d)") + + self.dtype = dtype + self.shape = shape + + def _init_dtype(self): + """Determine the dtype by executing `matvec` on an `int8` test vector. + + In `np.promote_types` hierarchy, the type `int8` is the smallest, + so we call `matvec` on `int8` and use the promoted dtype of the output + to set the default `dtype` of the `LinearOperator`. + We assume that `matmat`, `rmatvec`, and `rmatmat` would result in + the same dtype of the output given an `int8` input as `matvec`. + + Called from subclasses at the end of the __init__ routine. + """ + if self.dtype is None: + v = np.zeros(self.shape[-1], dtype=np.int8) + try: + matvec_v = np.asarray(self.matvec(v)) + except OverflowError: + # Python large `int` promoted to `np.int64`or `np.int32` + self.dtype = np.dtype(int) + else: + self.dtype = matvec_v.dtype + + def _matmat(self, X): + """Default matrix-matrix multiplication handler. + + Falls back on the user-defined _matvec method, so defining that will + define matrix multiplication (though in a very suboptimal way). + """ + + return np.hstack([self.matvec(col.reshape(-1,1)) for col in X.T]) + + def _matvec(self, x): + """Default matrix-vector multiplication handler. + + If self is a linear operator of shape (M, N), then this method will + be called on a shape (N,) or (N, 1) ndarray, and should return a + shape (M,) or (M, 1) ndarray. + + This default implementation falls back on _matmat, so defining that + will define matrix-vector multiplication as well. + """ + return self.matmat(x.reshape(-1, 1)) + + def matvec(self, x): + """Matrix-vector multiplication. + + Performs the operation y=A@x where A is an MxN linear + operator and x is a column vector or 1-d array. + + Parameters + ---------- + x : {matrix, ndarray} + An array with shape (N,) or (N,1). + + Returns + ------- + y : {matrix, ndarray} + A matrix or ndarray with shape (M,) or (M,1) depending + on the type and shape of the x argument. + + Notes + ----- + This matvec wraps the user-specified matvec routine or overridden + _matvec method to ensure that y has the correct shape and type. + + """ + + x = np.asanyarray(x) + + M,N = self.shape + + if x.shape != (N,) and x.shape != (N,1): + raise ValueError('dimension mismatch') + + y = self._matvec(x) + + if isinstance(x, np.matrix): + y = asmatrix(y) + else: + y = np.asarray(y) + + if x.ndim == 1: + y = y.reshape(M) + elif x.ndim == 2: + y = y.reshape(M,1) + else: + raise ValueError('invalid shape returned by user-defined matvec()') + + return y + + def rmatvec(self, x): + """Adjoint matrix-vector multiplication. + + Performs the operation y = A^H @ x where A is an MxN linear + operator and x is a column vector or 1-d array. + + Parameters + ---------- + x : {matrix, ndarray} + An array with shape (M,) or (M,1). + + Returns + ------- + y : {matrix, ndarray} + A matrix or ndarray with shape (N,) or (N,1) depending + on the type and shape of the x argument. + + Notes + ----- + This rmatvec wraps the user-specified rmatvec routine or overridden + _rmatvec method to ensure that y has the correct shape and type. + + """ + + x = np.asanyarray(x) + + M,N = self.shape + + if x.shape != (M,) and x.shape != (M,1): + raise ValueError('dimension mismatch') + + y = self._rmatvec(x) + + if isinstance(x, np.matrix): + y = asmatrix(y) + else: + y = np.asarray(y) + + if x.ndim == 1: + y = y.reshape(N) + elif x.ndim == 2: + y = y.reshape(N,1) + else: + raise ValueError('invalid shape returned by user-defined rmatvec()') + + return y + + def _rmatvec(self, x): + """Default implementation of _rmatvec; defers to adjoint.""" + if type(self)._adjoint == LinearOperator._adjoint: + # _adjoint not overridden, prevent infinite recursion + if (hasattr(self, "_rmatmat") + and type(self)._rmatmat != LinearOperator._rmatmat): + # Try to use _rmatmat as a fallback + return self._rmatmat(x.reshape(-1, 1)).reshape(-1) + raise NotImplementedError + else: + return self.H.matvec(x) + + def matmat(self, X): + """Matrix-matrix multiplication. + + Performs the operation y=A@X where A is an MxN linear + operator and X dense N*K matrix or ndarray. + + Parameters + ---------- + X : {matrix, ndarray} + An array with shape (N,K). + + Returns + ------- + Y : {matrix, ndarray} + A matrix or ndarray with shape (M,K) depending on + the type of the X argument. + + Notes + ----- + This matmat wraps any user-specified matmat routine or overridden + _matmat method to ensure that y has the correct type. + + """ + if not (issparse(X) or is_pydata_spmatrix(X)): + X = np.asanyarray(X) + + if X.ndim != 2: + raise ValueError(f'expected 2-d ndarray or matrix, not {X.ndim}-d') + + if X.shape[0] != self.shape[1]: + raise ValueError(f'dimension mismatch: {self.shape}, {X.shape}') + + try: + Y = self._matmat(X) + except Exception as e: + if issparse(X) or is_pydata_spmatrix(X): + raise TypeError( + "Unable to multiply a LinearOperator with a sparse matrix." + " Wrap the matrix in aslinearoperator first." + ) from e + raise + + if isinstance(Y, np.matrix): + Y = asmatrix(Y) + + return Y + + def rmatmat(self, X): + """Adjoint matrix-matrix multiplication. + + Performs the operation y = A^H @ x where A is an MxN linear + operator and x is a column vector or 1-d array, or 2-d array. + The default implementation defers to the adjoint. + + Parameters + ---------- + X : {matrix, ndarray} + A matrix or 2D array. + + Returns + ------- + Y : {matrix, ndarray} + A matrix or 2D array depending on the type of the input. + + Notes + ----- + This rmatmat wraps the user-specified rmatmat routine. + + """ + if not (issparse(X) or is_pydata_spmatrix(X)): + X = np.asanyarray(X) + + if X.ndim != 2: + raise ValueError(f'expected 2-d ndarray or matrix, not {X.ndim}-d') + + if X.shape[0] != self.shape[0]: + raise ValueError(f'dimension mismatch: {self.shape}, {X.shape}') + + try: + Y = self._rmatmat(X) + except Exception as e: + if issparse(X) or is_pydata_spmatrix(X): + raise TypeError( + "Unable to multiply a LinearOperator with a sparse matrix." + " Wrap the matrix in aslinearoperator() first." + ) from e + raise + + if isinstance(Y, np.matrix): + Y = asmatrix(Y) + return Y + + def _rmatmat(self, X): + """Default implementation of _rmatmat defers to rmatvec or adjoint.""" + if type(self)._adjoint == LinearOperator._adjoint: + return np.hstack([self.rmatvec(col.reshape(-1, 1)) for col in X.T]) + else: + return self.H.matmat(X) + + def __call__(self, x): + return self@x + + def __mul__(self, x): + return self.dot(x) + + def __truediv__(self, other): + if not np.isscalar(other): + raise ValueError("Can only divide a linear operator by a scalar.") + + return _ScaledLinearOperator(self, 1.0/other) + + def dot(self, x): + """Matrix-matrix or matrix-vector multiplication. + + Parameters + ---------- + x : array_like + 1-d or 2-d array, representing a vector or matrix. + + Returns + ------- + Ax : array + 1-d or 2-d array (depending on the shape of x) that represents + the result of applying this linear operator on x. + + """ + if isinstance(x, LinearOperator): + return _ProductLinearOperator(self, x) + elif np.isscalar(x): + return _ScaledLinearOperator(self, x) + else: + if not issparse(x) and not is_pydata_spmatrix(x): + # Sparse matrices shouldn't be converted to numpy arrays. + x = np.asarray(x) + + if x.ndim == 1 or x.ndim == 2 and x.shape[1] == 1: + return self.matvec(x) + elif x.ndim == 2: + return self.matmat(x) + else: + raise ValueError(f'expected 1-d or 2-d array or matrix, got {x!r}') + + def __matmul__(self, other): + if np.isscalar(other): + raise ValueError("Scalar operands are not allowed, " + "use '*' instead") + return self.__mul__(other) + + def __rmatmul__(self, other): + if np.isscalar(other): + raise ValueError("Scalar operands are not allowed, " + "use '*' instead") + return self.__rmul__(other) + + def __rmul__(self, x): + if np.isscalar(x): + return _ScaledLinearOperator(self, x) + else: + return self._rdot(x) + + def _rdot(self, x): + """Matrix-matrix or matrix-vector multiplication from the right. + + Parameters + ---------- + x : array_like + 1-d or 2-d array, representing a vector or matrix. + + Returns + ------- + xA : array + 1-d or 2-d array (depending on the shape of x) that represents + the result of applying this linear operator on x from the right. + + Notes + ----- + This is copied from dot to implement right multiplication. + """ + if isinstance(x, LinearOperator): + return _ProductLinearOperator(x, self) + elif np.isscalar(x): + return _ScaledLinearOperator(self, x) + else: + if not issparse(x) and not is_pydata_spmatrix(x): + # Sparse matrices shouldn't be converted to numpy arrays. + x = np.asarray(x) + + # We use transpose instead of rmatvec/rmatmat to avoid + # unnecessary complex conjugation if possible. + if x.ndim == 1 or x.ndim == 2 and x.shape[0] == 1: + return self.T.matvec(x.T).T + elif x.ndim == 2: + return self.T.matmat(x.T).T + else: + raise ValueError(f'expected 1-d or 2-d array or matrix, got {x!r}') + + def __pow__(self, p): + if np.isscalar(p): + return _PowerLinearOperator(self, p) + else: + return NotImplemented + + def __add__(self, x): + if isinstance(x, LinearOperator): + return _SumLinearOperator(self, x) + else: + return NotImplemented + + def __neg__(self): + return _ScaledLinearOperator(self, -1) + + def __sub__(self, x): + return self.__add__(-x) + + def __repr__(self): + M,N = self.shape + if self.dtype is None: + dt = 'unspecified dtype' + else: + dt = 'dtype=' + str(self.dtype) + + return f'<{M}x{N} {self.__class__.__name__} with {dt}>' + + def adjoint(self): + """Hermitian adjoint. + + Returns the Hermitian adjoint of self, aka the Hermitian + conjugate or Hermitian transpose. For a complex matrix, the + Hermitian adjoint is equal to the conjugate transpose. + + Can be abbreviated self.H instead of self.adjoint(). + + Returns + ------- + A_H : LinearOperator + Hermitian adjoint of self. + """ + return self._adjoint() + + H = property(adjoint) + + def transpose(self): + """Transpose this linear operator. + + Returns a LinearOperator that represents the transpose of this one. + Can be abbreviated self.T instead of self.transpose(). + """ + return self._transpose() + + T = property(transpose) + + def _adjoint(self): + """Default implementation of _adjoint; defers to rmatvec.""" + return _AdjointLinearOperator(self) + + def _transpose(self): + """ Default implementation of _transpose; defers to rmatvec + conj""" + return _TransposedLinearOperator(self) + + +class _CustomLinearOperator(LinearOperator): + """Linear operator defined in terms of user-specified operations.""" + + def __init__(self, shape, matvec, rmatvec=None, matmat=None, + dtype=None, rmatmat=None): + super().__init__(dtype, shape) + + self.args = () + + self.__matvec_impl = matvec + self.__rmatvec_impl = rmatvec + self.__rmatmat_impl = rmatmat + self.__matmat_impl = matmat + + self._init_dtype() + + def _matmat(self, X): + if self.__matmat_impl is not None: + return self.__matmat_impl(X) + else: + return super()._matmat(X) + + def _matvec(self, x): + return self.__matvec_impl(x) + + def _rmatvec(self, x): + func = self.__rmatvec_impl + if func is None: + raise NotImplementedError("rmatvec is not defined") + return self.__rmatvec_impl(x) + + def _rmatmat(self, X): + if self.__rmatmat_impl is not None: + return self.__rmatmat_impl(X) + else: + return super()._rmatmat(X) + + def _adjoint(self): + return _CustomLinearOperator(shape=(self.shape[1], self.shape[0]), + matvec=self.__rmatvec_impl, + rmatvec=self.__matvec_impl, + matmat=self.__rmatmat_impl, + rmatmat=self.__matmat_impl, + dtype=self.dtype) + + +class _AdjointLinearOperator(LinearOperator): + """Adjoint of arbitrary Linear Operator""" + + def __init__(self, A): + shape = (A.shape[1], A.shape[0]) + super().__init__(dtype=A.dtype, shape=shape) + self.A = A + self.args = (A,) + + def _matvec(self, x): + return self.A._rmatvec(x) + + def _rmatvec(self, x): + return self.A._matvec(x) + + def _matmat(self, x): + return self.A._rmatmat(x) + + def _rmatmat(self, x): + return self.A._matmat(x) + +class _TransposedLinearOperator(LinearOperator): + """Transposition of arbitrary Linear Operator""" + + def __init__(self, A): + shape = (A.shape[1], A.shape[0]) + super().__init__(dtype=A.dtype, shape=shape) + self.A = A + self.args = (A,) + + def _matvec(self, x): + # NB. np.conj works also on sparse matrices + return np.conj(self.A._rmatvec(np.conj(x))) + + def _rmatvec(self, x): + return np.conj(self.A._matvec(np.conj(x))) + + def _matmat(self, x): + # NB. np.conj works also on sparse matrices + return np.conj(self.A._rmatmat(np.conj(x))) + + def _rmatmat(self, x): + return np.conj(self.A._matmat(np.conj(x))) + +def _get_dtype(operators, dtypes=None): + if dtypes is None: + dtypes = [] + for obj in operators: + if obj is not None and hasattr(obj, 'dtype'): + dtypes.append(obj.dtype) + return np.result_type(*dtypes) + + +class _SumLinearOperator(LinearOperator): + def __init__(self, A, B): + if not isinstance(A, LinearOperator) or \ + not isinstance(B, LinearOperator): + raise ValueError('both operands have to be a LinearOperator') + if A.shape != B.shape: + raise ValueError(f'cannot add {A} and {B}: shape mismatch') + self.args = (A, B) + super().__init__(_get_dtype([A, B]), A.shape) + + def _matvec(self, x): + return self.args[0].matvec(x) + self.args[1].matvec(x) + + def _rmatvec(self, x): + return self.args[0].rmatvec(x) + self.args[1].rmatvec(x) + + def _rmatmat(self, x): + return self.args[0].rmatmat(x) + self.args[1].rmatmat(x) + + def _matmat(self, x): + return self.args[0].matmat(x) + self.args[1].matmat(x) + + def _adjoint(self): + A, B = self.args + return A.H + B.H + + +class _ProductLinearOperator(LinearOperator): + def __init__(self, A, B): + if not isinstance(A, LinearOperator) or \ + not isinstance(B, LinearOperator): + raise ValueError('both operands have to be a LinearOperator') + if A.shape[1] != B.shape[0]: + raise ValueError(f'cannot multiply {A} and {B}: shape mismatch') + super().__init__(_get_dtype([A, B]), + (A.shape[0], B.shape[1])) + self.args = (A, B) + + def _matvec(self, x): + return self.args[0].matvec(self.args[1].matvec(x)) + + def _rmatvec(self, x): + return self.args[1].rmatvec(self.args[0].rmatvec(x)) + + def _rmatmat(self, x): + return self.args[1].rmatmat(self.args[0].rmatmat(x)) + + def _matmat(self, x): + return self.args[0].matmat(self.args[1].matmat(x)) + + def _adjoint(self): + A, B = self.args + return B.H @ A.H + + +class _ScaledLinearOperator(LinearOperator): + def __init__(self, A, alpha): + if not isinstance(A, LinearOperator): + raise ValueError('LinearOperator expected as A') + if not np.isscalar(alpha): + raise ValueError('scalar expected as alpha') + if isinstance(A, _ScaledLinearOperator): + A, alpha_original = A.args + # Avoid in-place multiplication so that we don't accidentally mutate + # the original prefactor. + alpha = alpha * alpha_original + + dtype = _get_dtype([A], [type(alpha)]) + super().__init__(dtype, A.shape) + self.args = (A, alpha) + # Note: args[1] is alpha (a scalar), so use `*` below, not `@` + + def _matvec(self, x): + return self.args[1] * self.args[0].matvec(x) + + def _rmatvec(self, x): + return np.conj(self.args[1]) * self.args[0].rmatvec(x) + + def _rmatmat(self, x): + return np.conj(self.args[1]) * self.args[0].rmatmat(x) + + def _matmat(self, x): + return self.args[1] * self.args[0].matmat(x) + + def _adjoint(self): + A, alpha = self.args + return A.H * np.conj(alpha) + + +class _PowerLinearOperator(LinearOperator): + def __init__(self, A, p): + if not isinstance(A, LinearOperator): + raise ValueError('LinearOperator expected as A') + if A.shape[0] != A.shape[1]: + raise ValueError(f'square LinearOperator expected, got {A!r}') + if not isintlike(p) or p < 0: + raise ValueError('non-negative integer expected as p') + + super().__init__(_get_dtype([A]), A.shape) + self.args = (A, p) + + def _power(self, fun, x): + res = np.array(x, copy=True) + for i in range(self.args[1]): + res = fun(res) + return res + + def _matvec(self, x): + return self._power(self.args[0].matvec, x) + + def _rmatvec(self, x): + return self._power(self.args[0].rmatvec, x) + + def _rmatmat(self, x): + return self._power(self.args[0].rmatmat, x) + + def _matmat(self, x): + return self._power(self.args[0].matmat, x) + + def _adjoint(self): + A, p = self.args + return A.H ** p + + +class MatrixLinearOperator(LinearOperator): + def __init__(self, A): + super().__init__(A.dtype, A.shape) + self.A = A + self.__adj = None + self.args = (A,) + + def _matmat(self, X): + return self.A.dot(X) + + def _adjoint(self): + if self.__adj is None: + self.__adj = _AdjointMatrixOperator(self.A) + return self.__adj + + +class _AdjointMatrixOperator(MatrixLinearOperator): + def __init__(self, adjoint_array): + self.A = adjoint_array.T.conj() + self.args = (adjoint_array,) + self.shape = adjoint_array.shape[1], adjoint_array.shape[0] + + @property + def dtype(self): + return self.args[0].dtype + + def _adjoint(self): + return MatrixLinearOperator(self.args[0]) + + +class IdentityOperator(LinearOperator): + def __init__(self, shape, dtype=None): + super().__init__(dtype, shape) + + def _matvec(self, x): + return x + + def _rmatvec(self, x): + return x + + def _rmatmat(self, x): + return x + + def _matmat(self, x): + return x + + def _adjoint(self): + return self + + +def aslinearoperator(A): + """Return A as a LinearOperator. + + 'A' may be any of the following types: + - ndarray + - matrix + - sparse array (e.g. csr_array, lil_array, etc.) + - LinearOperator + - An object with .shape and .matvec attributes + + See the LinearOperator documentation for additional information. + + Notes + ----- + If 'A' has no .dtype attribute, the data type is determined by calling + :func:`LinearOperator.matvec()` - set the .dtype attribute to prevent this + call upon the linear operator creation. + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse.linalg import aslinearoperator + >>> M = np.array([[1,2,3],[4,5,6]], dtype=np.int32) + >>> aslinearoperator(M) + <2x3 MatrixLinearOperator with dtype=int32> + """ + if isinstance(A, LinearOperator): + return A + + elif isinstance(A, np.ndarray) or isinstance(A, np.matrix): + if A.ndim > 2: + raise ValueError('array must have ndim <= 2') + A = np.atleast_2d(np.asarray(A)) + return MatrixLinearOperator(A) + + elif issparse(A) or is_pydata_spmatrix(A): + return MatrixLinearOperator(A) + + else: + if hasattr(A, 'shape') and hasattr(A, 'matvec'): + rmatvec = None + rmatmat = None + dtype = None + + if hasattr(A, 'rmatvec'): + rmatvec = A.rmatvec + if hasattr(A, 'rmatmat'): + rmatmat = A.rmatmat + if hasattr(A, 'dtype'): + dtype = A.dtype + return LinearOperator(A.shape, A.matvec, rmatvec=rmatvec, + rmatmat=rmatmat, dtype=dtype) + + else: + raise TypeError('type not understood') diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3b57274542928e79c234bb6955849a90be21990e --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__init__.py @@ -0,0 +1,20 @@ +"Iterative Solvers for Sparse Linear Systems" + +#from info import __doc__ +from .iterative import * +from .minres import minres +from .lgmres import lgmres +from .lsqr import lsqr +from .lsmr import lsmr +from ._gcrotmk import gcrotmk +from .tfqmr import tfqmr + +__all__ = [ + 'bicg', 'bicgstab', 'cg', 'cgs', 'gcrotmk', 'gmres', + 'lgmres', 'lsmr', 'lsqr', + 'minres', 'qmr', 'tfqmr' +] + +from scipy._lib._testutils import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08a1ba22767823377d9377b3577258a808495a37 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/_gcrotmk.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/_gcrotmk.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d6d64d64ae8044e18ea216a1565021ccb8f873c8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/_gcrotmk.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/iterative.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/iterative.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..77ec4502a37e9d5a4a91137af42e53eda35e0405 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/iterative.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/lgmres.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/lgmres.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9d5578d7ed2ed403a8d2544b7c9a2baa2b4e4932 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/lgmres.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/lsmr.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/lsmr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..416a96e1a877cf8ea114ddfde0070d9197df9a39 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/lsmr.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/lsqr.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/lsqr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cabf86e7e5d056adf3eaf015500742f959d69667 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/lsqr.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/minres.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/minres.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1a2b5debc28d58bb0727fb272582fa699e98be8d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/minres.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/tfqmr.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/tfqmr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..713c4445be2dcf76d65fa4debf67a7b89fa50b35 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/tfqmr.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/utils.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..452b7487fd1f4ce96eb985992d333b9012cd2939 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/__pycache__/utils.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/_gcrotmk.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/_gcrotmk.py new file mode 100644 index 0000000000000000000000000000000000000000..1b053919c101b542aa8e48cbbba33411591a1441 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/_gcrotmk.py @@ -0,0 +1,503 @@ +# Copyright (C) 2015, Pauli Virtanen +# Distributed under the same license as SciPy. + +import numpy as np +from numpy.linalg import LinAlgError +from scipy.linalg import (get_blas_funcs, qr, solve, svd, qr_insert, lstsq) +from .iterative import _get_atol_rtol +from scipy.sparse.linalg._isolve.utils import make_system + + +__all__ = ['gcrotmk'] + + +def _fgmres(matvec, v0, m, atol, lpsolve=None, rpsolve=None, cs=(), outer_v=(), + prepend_outer_v=False): + """ + FGMRES Arnoldi process, with optional projection or augmentation + + Parameters + ---------- + matvec : callable + Operation A*x + v0 : ndarray + Initial vector, normalized to nrm2(v0) == 1 + m : int + Number of GMRES rounds + atol : float + Absolute tolerance for early exit + lpsolve : callable + Left preconditioner L + rpsolve : callable + Right preconditioner R + cs : list of (ndarray, ndarray) + Columns of matrices C and U in GCROT + outer_v : list of ndarrays + Augmentation vectors in LGMRES + prepend_outer_v : bool, optional + Whether augmentation vectors come before or after + Krylov iterates + + Raises + ------ + LinAlgError + If nans encountered + + Returns + ------- + Q, R : ndarray + QR decomposition of the upper Hessenberg H=QR + B : ndarray + Projections corresponding to matrix C + vs : list of ndarray + Columns of matrix V + zs : list of ndarray + Columns of matrix Z + y : ndarray + Solution to ||H y - e_1||_2 = min! + res : float + The final (preconditioned) residual norm + + """ + + if lpsolve is None: + def lpsolve(x): + return x + if rpsolve is None: + def rpsolve(x): + return x + + axpy, dot, scal, nrm2 = get_blas_funcs(['axpy', 'dot', 'scal', 'nrm2'], (v0,)) + + vs = [v0] + zs = [] + y = None + res = np.nan + + m = m + len(outer_v) + + # Orthogonal projection coefficients + B = np.zeros((len(cs), m), dtype=v0.dtype) + + # H is stored in QR factorized form + Q = np.ones((1, 1), dtype=v0.dtype) + R = np.zeros((1, 0), dtype=v0.dtype) + + eps = np.finfo(v0.dtype).eps + + breakdown = False + + # FGMRES Arnoldi process + for j in range(m): + # L A Z = C B + V H + + if prepend_outer_v and j < len(outer_v): + z, w = outer_v[j] + elif prepend_outer_v and j == len(outer_v): + z = rpsolve(v0) + w = None + elif not prepend_outer_v and j >= m - len(outer_v): + z, w = outer_v[j - (m - len(outer_v))] + else: + z = rpsolve(vs[-1]) + w = None + + if w is None: + w = lpsolve(matvec(z)) + else: + # w is clobbered below + w = w.copy() + + w_norm = nrm2(w) + + # GCROT projection: L A -> (1 - C C^H) L A + # i.e. orthogonalize against C + for i, c in enumerate(cs): + alpha = dot(c, w) + B[i,j] = alpha + w = axpy(c, w, c.shape[0], -alpha) # w -= alpha*c + + # Orthogonalize against V + hcur = np.zeros(j+2, dtype=Q.dtype) + for i, v in enumerate(vs): + alpha = dot(v, w) + hcur[i] = alpha + w = axpy(v, w, v.shape[0], -alpha) # w -= alpha*v + hcur[i+1] = nrm2(w) + + with np.errstate(over='ignore', divide='ignore'): + # Careful with denormals + alpha = 1/hcur[-1] + + if np.isfinite(alpha): + w = scal(alpha, w) + + if not (hcur[-1] > eps * w_norm): + # w essentially in the span of previous vectors, + # or we have nans. Bail out after updating the QR + # solution. + breakdown = True + + vs.append(w) + zs.append(z) + + # Arnoldi LSQ problem + + # Add new column to H=Q@R, padding other columns with zeros + Q2 = np.zeros((j+2, j+2), dtype=Q.dtype, order='F') + Q2[:j+1,:j+1] = Q + Q2[j+1,j+1] = 1 + + R2 = np.zeros((j+2, j), dtype=R.dtype, order='F') + R2[:j+1,:] = R + + Q, R = qr_insert(Q2, R2, hcur, j, which='col', + overwrite_qru=True, check_finite=False) + + # Transformed least squares problem + # || Q R y - inner_res_0 * e_1 ||_2 = min! + # Since R = [R'; 0], solution is y = inner_res_0 (R')^{-1} (Q^H)[:j,0] + + # Residual is immediately known + res = abs(Q[0,-1]) + + # Check for termination + if res < atol or breakdown: + break + + if not np.isfinite(R[j,j]): + # nans encountered, bail out + raise LinAlgError() + + # -- Get the LSQ problem solution + + # The problem is triangular, but the condition number may be + # bad (or in case of breakdown the last diagonal entry may be + # zero), so use lstsq instead of trtrs. + y, _, _, _, = lstsq(R[:j+1,:j+1], Q[0,:j+1].conj()) + + B = B[:,:j+1] + + return Q, R, B, vs, zs, y, res + + +def gcrotmk(A, b, x0=None, *, rtol=1e-5, atol=0., maxiter=1000, M=None, callback=None, + m=20, k=None, CU=None, discard_C=False, truncate='oldest'): + """ + Solve ``Ax = b`` with the flexible GCROT(m,k) algorithm. + + Parameters + ---------- + A : {sparse array, ndarray, LinearOperator} + The real or complex N-by-N matrix of the linear system. + Alternatively, `A` can be a linear operator which can + produce ``Ax`` using, e.g., + `LinearOperator`. + b : ndarray + Right hand side of the linear system. Has shape (N,) or (N,1). + x0 : ndarray + Starting guess for the solution. + rtol, atol : float, optional + Parameters for the convergence test. For convergence, + ``norm(b - A @ x) <= max(rtol*norm(b), atol)`` should be satisfied. + The default is ``rtol=1e-5`` and ``atol=0.0``. + maxiter : int, optional + Maximum number of iterations. Iteration will stop after maxiter + steps even if the specified tolerance has not been achieved. The + default is ``1000``. + M : {sparse array, ndarray, LinearOperator}, optional + Preconditioner for `A`. The preconditioner should approximate the + inverse of `A`. gcrotmk is a 'flexible' algorithm and the preconditioner + can vary from iteration to iteration. Effective preconditioning + dramatically improves the rate of convergence, which implies that + fewer iterations are needed to reach a given error tolerance. + callback : function, optional + User-supplied function to call after each iteration. It is called + as ``callback(xk)``, where ``xk`` is the current solution vector. + m : int, optional + Number of inner FGMRES iterations per each outer iteration. + Default: 20 + k : int, optional + Number of vectors to carry between inner FGMRES iterations. + According to [2]_, good values are around `m`. + Default: `m` + CU : list of tuples, optional + List of tuples ``(c, u)`` which contain the columns of the matrices + C and U in the GCROT(m,k) algorithm. For details, see [2]_. + The list given and vectors contained in it are modified in-place. + If not given, start from empty matrices. The ``c`` elements in the + tuples can be ``None``, in which case the vectors are recomputed + via ``c = A u`` on start and orthogonalized as described in [3]_. + discard_C : bool, optional + Discard the C-vectors at the end. Useful if recycling Krylov subspaces + for different linear systems. + truncate : {'oldest', 'smallest'}, optional + Truncation scheme to use. Drop: oldest vectors, or vectors with + smallest singular values using the scheme discussed in [1,2]. + See [2]_ for detailed comparison. + Default: 'oldest' + + Returns + ------- + x : ndarray + The solution found. + info : int + Provides convergence information: + + * 0 : successful exit + * >0 : convergence to tolerance not achieved, number of iterations + + References + ---------- + .. [1] E. de Sturler, ''Truncation strategies for optimal Krylov subspace + methods'', SIAM J. Numer. Anal. 36, 864 (1999). + .. [2] J.E. Hicken and D.W. Zingg, ''A simplified and flexible variant + of GCROT for solving nonsymmetric linear systems'', + SIAM J. Sci. Comput. 32, 172 (2010). + .. [3] M.L. Parks, E. de Sturler, G. Mackey, D.D. Johnson, S. Maiti, + ''Recycling Krylov subspaces for sequences of linear systems'', + SIAM J. Sci. Comput. 28, 1651 (2006). + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import gcrotmk + >>> R = np.random.randn(5, 5) + >>> A = csc_array(R) + >>> b = np.random.randn(5) + >>> x, exit_code = gcrotmk(A, b, atol=1e-5) + >>> print(exit_code) + 0 + >>> np.allclose(A.dot(x), b) + True + + """ + A,M,x,b = make_system(A,M,x0,b) + + if not np.isfinite(b).all(): + raise ValueError("RHS must contain only finite numbers") + + if truncate not in ('oldest', 'smallest'): + raise ValueError(f"Invalid value for 'truncate': {truncate!r}") + + matvec = A.matvec + psolve = M.matvec + + if CU is None: + CU = [] + + if k is None: + k = m + + axpy, dot, scal = None, None, None + + if x0 is None: + r = b.copy() + else: + r = b - matvec(x) + + axpy, dot, scal, nrm2 = get_blas_funcs(['axpy', 'dot', 'scal', 'nrm2'], (x, r)) + + b_norm = nrm2(b) + + # we call this to get the right atol/rtol and raise errors as necessary + atol, rtol = _get_atol_rtol('gcrotmk', b_norm, atol, rtol) + + if b_norm == 0: + x = b + return (x, 0) + + if discard_C: + CU[:] = [(None, u) for c, u in CU] + + # Reorthogonalize old vectors + if CU: + # Sort already existing vectors to the front + CU.sort(key=lambda cu: cu[0] is not None) + + # Fill-in missing ones + C = np.empty((A.shape[0], len(CU)), dtype=r.dtype, order='F') + us = [] + j = 0 + while CU: + # More memory-efficient: throw away old vectors as we go + c, u = CU.pop(0) + if c is None: + c = matvec(u) + C[:,j] = c + j += 1 + us.append(u) + + # Orthogonalize + Q, R, P = qr(C, overwrite_a=True, mode='economic', pivoting=True) + del C + + # C := Q + cs = list(Q.T) + + # U := U P R^-1, back-substitution + new_us = [] + for j in range(len(cs)): + u = us[P[j]] + for i in range(j): + u = axpy(us[P[i]], u, u.shape[0], -R[i,j]) + if abs(R[j,j]) < 1e-12 * abs(R[0,0]): + # discard rest of the vectors + break + u = scal(1.0/R[j,j], u) + new_us.append(u) + + # Form the new CU lists + CU[:] = list(zip(cs, new_us))[::-1] + + if CU: + axpy, dot = get_blas_funcs(['axpy', 'dot'], (r,)) + + # Solve first the projection operation with respect to the CU + # vectors. This corresponds to modifying the initial guess to + # be + # + # x' = x + U y + # y = argmin_y || b - A (x + U y) ||^2 + # + # The solution is y = C^H (b - A x) + for c, u in CU: + yc = dot(c, r) + x = axpy(u, x, x.shape[0], yc) + r = axpy(c, r, r.shape[0], -yc) + + # GCROT main iteration + for j_outer in range(maxiter): + # -- callback + if callback is not None: + callback(x) + + beta = nrm2(r) + + # -- check stopping condition + beta_tol = max(atol, rtol * b_norm) + + if beta <= beta_tol and (j_outer > 0 or CU): + # recompute residual to avoid rounding error + r = b - matvec(x) + beta = nrm2(r) + + if beta <= beta_tol: + j_outer = -1 + break + + ml = m + max(k - len(CU), 0) + + cs = [c for c, u in CU] + + try: + Q, R, B, vs, zs, y, pres = _fgmres(matvec, + r/beta, + ml, + rpsolve=psolve, + atol=max(atol, rtol*b_norm)/beta, + cs=cs) + y *= beta + except LinAlgError: + # Floating point over/underflow, non-finite result from + # matmul etc. -- report failure. + break + + # + # At this point, + # + # [A U, A Z] = [C, V] G; G = [ I B ] + # [ 0 H ] + # + # where [C, V] has orthonormal columns, and r = beta v_0. Moreover, + # + # || b - A (x + Z y + U q) ||_2 = || r - C B y - V H y - C q ||_2 = min! + # + # from which y = argmin_y || beta e_1 - H y ||_2, and q = -B y + # + + # + # GCROT(m,k) update + # + + # Define new outer vectors + + # ux := (Z - U B) y + ux = zs[0]*y[0] + for z, yc in zip(zs[1:], y[1:]): + ux = axpy(z, ux, ux.shape[0], yc) # ux += z*yc + by = B.dot(y) + for cu, byc in zip(CU, by): + c, u = cu + ux = axpy(u, ux, ux.shape[0], -byc) # ux -= u*byc + + # cx := V H y + with np.errstate(invalid="ignore"): + hy = Q.dot(R.dot(y)) + cx = vs[0] * hy[0] + for v, hyc in zip(vs[1:], hy[1:]): + cx = axpy(v, cx, cx.shape[0], hyc) # cx += v*hyc + + # Normalize cx, maintaining cx = A ux + # This new cx is orthogonal to the previous C, by construction + try: + alpha = 1/nrm2(cx) + if not np.isfinite(alpha): + raise FloatingPointError() + except (FloatingPointError, ZeroDivisionError): + # Cannot update, so skip it + continue + + cx = scal(alpha, cx) + ux = scal(alpha, ux) + + # Update residual and solution + gamma = dot(cx, r) + r = axpy(cx, r, r.shape[0], -gamma) # r -= gamma*cx + x = axpy(ux, x, x.shape[0], gamma) # x += gamma*ux + + # Truncate CU + if truncate == 'oldest': + while len(CU) >= k and CU: + del CU[0] + elif truncate == 'smallest': + if len(CU) >= k and CU: + # cf. [1,2] + D = solve(R[:-1,:].T, B.T).T + W, sigma, V = svd(D) + + # C := C W[:,:k-1], U := U W[:,:k-1] + new_CU = [] + for j, w in enumerate(W[:,:k-1].T): + c, u = CU[0] + c = c * w[0] + u = u * w[0] + for cup, wp in zip(CU[1:], w[1:]): + cp, up = cup + c = axpy(cp, c, c.shape[0], wp) + u = axpy(up, u, u.shape[0], wp) + + # Reorthogonalize at the same time; not necessary + # in exact arithmetic, but floating point error + # tends to accumulate here + for cp, up in new_CU: + alpha = dot(cp, c) + c = axpy(cp, c, c.shape[0], -alpha) + u = axpy(up, u, u.shape[0], -alpha) + alpha = nrm2(c) + c = scal(1.0/alpha, c) + u = scal(1.0/alpha, u) + + new_CU.append((c, u)) + CU[:] = new_CU + + # Add new vector to CU + CU.append((cx, ux)) + + # Include the solution vector to the span + CU.append((None, x.copy())) + if discard_C: + CU[:] = [(None, uz) for cz, uz in CU] + + return x, j_outer + 1 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/iterative.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/iterative.py new file mode 100644 index 0000000000000000000000000000000000000000..637f2d021f62f5a864b92f3a828498ce0f4210ae --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/iterative.py @@ -0,0 +1,1051 @@ +import warnings +import numpy as np +from scipy.sparse.linalg._interface import LinearOperator +from .utils import make_system +from scipy.linalg import get_lapack_funcs + +__all__ = ['bicg', 'bicgstab', 'cg', 'cgs', 'gmres', 'qmr'] + + +def _get_atol_rtol(name, b_norm, atol=0., rtol=1e-5): + """ + A helper function to handle tolerance normalization + """ + if atol == 'legacy' or atol is None or atol < 0: + msg = (f"'scipy.sparse.linalg.{name}' called with invalid `atol`={atol}; " + "if set, `atol` must be a real, non-negative number.") + raise ValueError(msg) + + atol = max(float(atol), float(rtol) * float(b_norm)) + + return atol, rtol + + +def bicg(A, b, x0=None, *, rtol=1e-5, atol=0., maxiter=None, M=None, callback=None): + """ + Solve ``Ax = b`` with the BIConjugate Gradient method. + + Parameters + ---------- + A : {sparse array, ndarray, LinearOperator} + The real or complex N-by-N matrix of the linear system. + Alternatively, `A` can be a linear operator which can + produce ``Ax`` and ``A^T x`` using, e.g., + ``scipy.sparse.linalg.LinearOperator``. + b : ndarray + Right hand side of the linear system. Has shape (N,) or (N,1). + x0 : ndarray + Starting guess for the solution. + rtol, atol : float, optional + Parameters for the convergence test. For convergence, + ``norm(b - A @ x) <= max(rtol*norm(b), atol)`` should be satisfied. + The default is ``atol=0.`` and ``rtol=1e-5``. + maxiter : integer + Maximum number of iterations. Iteration will stop after maxiter + steps even if the specified tolerance has not been achieved. + M : {sparse array, ndarray, LinearOperator} + Preconditioner for `A`. It should approximate the + inverse of `A` (see Notes). Effective preconditioning dramatically improves the + rate of convergence, which implies that fewer iterations are needed + to reach a given error tolerance. + callback : function + User-supplied function to call after each iteration. It is called + as ``callback(xk)``, where ``xk`` is the current solution vector. + + Returns + ------- + x : ndarray + The converged solution. + info : integer + Provides convergence information: + 0 : successful exit + >0 : convergence to tolerance not achieved, number of iterations + <0 : parameter breakdown + + Notes + ----- + The preconditioner `M` should be a matrix such that ``M @ A`` has a smaller + condition number than `A`, see [1]_ . + + References + ---------- + .. [1] "Preconditioner", Wikipedia, + https://en.wikipedia.org/wiki/Preconditioner + .. [2] "Biconjugate gradient method", Wikipedia, + https://en.wikipedia.org/wiki/Biconjugate_gradient_method + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import bicg + >>> A = csc_array([[3, 2, 0], [1, -1, 0], [0, 5, 1.]]) + >>> b = np.array([2., 4., -1.]) + >>> x, exitCode = bicg(A, b, atol=1e-5) + >>> print(exitCode) # 0 indicates successful convergence + 0 + >>> np.allclose(A.dot(x), b) + True + """ + A, M, x, b = make_system(A, M, x0, b) + bnrm2 = np.linalg.norm(b) + + atol, _ = _get_atol_rtol('bicg', bnrm2, atol, rtol) + + if bnrm2 == 0: + return b, 0 + + n = len(b) + dotprod = np.vdot if np.iscomplexobj(x) else np.dot + + if maxiter is None: + maxiter = n*10 + + matvec, rmatvec = A.matvec, A.rmatvec + psolve, rpsolve = M.matvec, M.rmatvec + + rhotol = np.finfo(x.dtype.char).eps**2 + + # Dummy values to initialize vars, silence linter warnings + rho_prev, p, ptilde = None, None, None + + r = b - matvec(x) if x.any() else b.copy() + rtilde = r.copy() + + for iteration in range(maxiter): + if np.linalg.norm(r) < atol: # Are we done? + return x, 0 + + z = psolve(r) + ztilde = rpsolve(rtilde) + # order matters in this dot product + rho_cur = dotprod(rtilde, z) + + if np.abs(rho_cur) < rhotol: # Breakdown case + return x, -10 + + if iteration > 0: + beta = rho_cur / rho_prev + p *= beta + p += z + ptilde *= beta.conj() + ptilde += ztilde + else: # First spin + p = z.copy() + ptilde = ztilde.copy() + + q = matvec(p) + qtilde = rmatvec(ptilde) + rv = dotprod(ptilde, q) + + if rv == 0: + return x, -11 + + alpha = rho_cur / rv + x += alpha*p + r -= alpha*q + rtilde -= alpha.conj()*qtilde + rho_prev = rho_cur + + if callback: + callback(x) + + else: # for loop exhausted + # Return incomplete progress + return x, maxiter + + +def bicgstab(A, b, x0=None, *, rtol=1e-5, atol=0., maxiter=None, M=None, + callback=None): + """ + Solve ``Ax = b`` with the BIConjugate Gradient STABilized method. + + Parameters + ---------- + A : {sparse array, ndarray, LinearOperator} + The real or complex N-by-N matrix of the linear system. + Alternatively, `A` can be a linear operator which can + produce ``Ax`` and ``A^T x`` using, e.g., + ``scipy.sparse.linalg.LinearOperator``. + b : ndarray + Right hand side of the linear system. Has shape (N,) or (N,1). + x0 : ndarray + Starting guess for the solution. + rtol, atol : float, optional + Parameters for the convergence test. For convergence, + ``norm(b - A @ x) <= max(rtol*norm(b), atol)`` should be satisfied. + The default is ``atol=0.`` and ``rtol=1e-5``. + maxiter : integer + Maximum number of iterations. Iteration will stop after maxiter + steps even if the specified tolerance has not been achieved. + M : {sparse array, ndarray, LinearOperator} + Preconditioner for `A`. It should approximate the + inverse of `A` (see Notes). Effective preconditioning dramatically improves the + rate of convergence, which implies that fewer iterations are needed + to reach a given error tolerance. + callback : function + User-supplied function to call after each iteration. It is called + as ``callback(xk)``, where ``xk`` is the current solution vector. + + Returns + ------- + x : ndarray + The converged solution. + info : integer + Provides convergence information: + 0 : successful exit + >0 : convergence to tolerance not achieved, number of iterations + <0 : parameter breakdown + + Notes + ----- + The preconditioner `M` should be a matrix such that ``M @ A`` has a smaller + condition number than `A`, see [1]_ . + + References + ---------- + .. [1] "Preconditioner", Wikipedia, + https://en.wikipedia.org/wiki/Preconditioner + .. [2] "Biconjugate gradient stabilized method", + Wikipedia, https://en.wikipedia.org/wiki/Biconjugate_gradient_stabilized_method + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import bicgstab + >>> R = np.array([[4, 2, 0, 1], + ... [3, 0, 0, 2], + ... [0, 1, 1, 1], + ... [0, 2, 1, 0]]) + >>> A = csc_array(R) + >>> b = np.array([-1, -0.5, -1, 2]) + >>> x, exit_code = bicgstab(A, b, atol=1e-5) + >>> print(exit_code) # 0 indicates successful convergence + 0 + >>> np.allclose(A.dot(x), b) + True + """ + A, M, x, b = make_system(A, M, x0, b) + bnrm2 = np.linalg.norm(b) + + atol, _ = _get_atol_rtol('bicgstab', bnrm2, atol, rtol) + + if bnrm2 == 0: + return b, 0 + + n = len(b) + + dotprod = np.vdot if np.iscomplexobj(x) else np.dot + + if maxiter is None: + maxiter = n*10 + + matvec = A.matvec + psolve = M.matvec + + # These values make no sense but coming from original Fortran code + # sqrt might have been meant instead. + rhotol = np.finfo(x.dtype.char).eps**2 + omegatol = rhotol + + # Dummy values to initialize vars, silence linter warnings + rho_prev, omega, alpha, p, v = None, None, None, None, None + + r = b - matvec(x) if x.any() else b.copy() + rtilde = r.copy() + + for iteration in range(maxiter): + if np.linalg.norm(r) < atol: # Are we done? + return x, 0 + + rho = dotprod(rtilde, r) + if np.abs(rho) < rhotol: # rho breakdown + return x, -10 + + if iteration > 0: + if np.abs(omega) < omegatol: # omega breakdown + return x, -11 + + beta = (rho / rho_prev) * (alpha / omega) + p -= omega*v + p *= beta + p += r + else: # First spin + s = np.empty_like(r) + p = r.copy() + + phat = psolve(p) + v = matvec(phat) + rv = dotprod(rtilde, v) + if rv == 0: + return x, -11 + alpha = rho / rv + r -= alpha*v + s[:] = r[:] + + if np.linalg.norm(s) < atol: + x += alpha*phat + return x, 0 + + shat = psolve(s) + t = matvec(shat) + omega = dotprod(t, s) / dotprod(t, t) + x += alpha*phat + x += omega*shat + r -= omega*t + rho_prev = rho + + if callback: + callback(x) + + else: # for loop exhausted + # Return incomplete progress + return x, maxiter + + +def cg(A, b, x0=None, *, rtol=1e-5, atol=0., maxiter=None, M=None, callback=None): + """ + Solve ``Ax = b`` with the Conjugate Gradient method, for a symmetric, + positive-definite `A`. + + Parameters + ---------- + A : {sparse array, ndarray, LinearOperator} + The real or complex N-by-N matrix of the linear system. + `A` must represent a hermitian, positive definite matrix. + Alternatively, `A` can be a linear operator which can + produce ``Ax`` using, e.g., + ``scipy.sparse.linalg.LinearOperator``. + b : ndarray + Right hand side of the linear system. Has shape (N,) or (N,1). + x0 : ndarray + Starting guess for the solution. + rtol, atol : float, optional + Parameters for the convergence test. For convergence, + ``norm(b - A @ x) <= max(rtol*norm(b), atol)`` should be satisfied. + The default is ``atol=0.`` and ``rtol=1e-5``. + maxiter : integer + Maximum number of iterations. Iteration will stop after maxiter + steps even if the specified tolerance has not been achieved. + M : {sparse array, ndarray, LinearOperator} + Preconditioner for `A`. `M` must represent a hermitian, positive definite + matrix. It should approximate the inverse of `A` (see Notes). + Effective preconditioning dramatically improves the + rate of convergence, which implies that fewer iterations are needed + to reach a given error tolerance. + callback : function + User-supplied function to call after each iteration. It is called + as ``callback(xk)``, where ``xk`` is the current solution vector. + + Returns + ------- + x : ndarray + The converged solution. + info : integer + Provides convergence information: + 0 : successful exit + >0 : convergence to tolerance not achieved, number of iterations + + Notes + ----- + The preconditioner `M` should be a matrix such that ``M @ A`` has a smaller + condition number than `A`, see [2]_. + + References + ---------- + .. [1] "Conjugate Gradient Method, Wikipedia, + https://en.wikipedia.org/wiki/Conjugate_gradient_method + .. [2] "Preconditioner", + Wikipedia, https://en.wikipedia.org/wiki/Preconditioner + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import cg + >>> P = np.array([[4, 0, 1, 0], + ... [0, 5, 0, 0], + ... [1, 0, 3, 2], + ... [0, 0, 2, 4]]) + >>> A = csc_array(P) + >>> b = np.array([-1, -0.5, -1, 2]) + >>> x, exit_code = cg(A, b, atol=1e-5) + >>> print(exit_code) # 0 indicates successful convergence + 0 + >>> np.allclose(A.dot(x), b) + True + """ + A, M, x, b = make_system(A, M, x0, b) + bnrm2 = np.linalg.norm(b) + + atol, _ = _get_atol_rtol('cg', bnrm2, atol, rtol) + + if bnrm2 == 0: + return b, 0 + + n = len(b) + + if maxiter is None: + maxiter = n*10 + + dotprod = np.vdot if np.iscomplexobj(x) else np.dot + + matvec = A.matvec + psolve = M.matvec + r = b - matvec(x) if x.any() else b.copy() + + # Dummy value to initialize var, silences warnings + rho_prev, p = None, None + + for iteration in range(maxiter): + if np.linalg.norm(r) < atol: # Are we done? + return x, 0 + + z = psolve(r) + rho_cur = dotprod(r, z) + if iteration > 0: + beta = rho_cur / rho_prev + p *= beta + p += z + else: # First spin + p = np.empty_like(r) + p[:] = z[:] + + q = matvec(p) + alpha = rho_cur / dotprod(p, q) + x += alpha*p + r -= alpha*q + rho_prev = rho_cur + + if callback: + callback(x) + + else: # for loop exhausted + # Return incomplete progress + return x, maxiter + + +def cgs(A, b, x0=None, *, rtol=1e-5, atol=0., maxiter=None, M=None, callback=None): + """ + Solve ``Ax = b`` with the Conjugate Gradient Squared method. + + Parameters + ---------- + A : {sparse array, ndarray, LinearOperator} + The real-valued N-by-N matrix of the linear system. + Alternatively, `A` can be a linear operator which can + produce ``Ax`` using, e.g., + ``scipy.sparse.linalg.LinearOperator``. + b : ndarray + Right hand side of the linear system. Has shape (N,) or (N,1). + x0 : ndarray + Starting guess for the solution. + rtol, atol : float, optional + Parameters for the convergence test. For convergence, + ``norm(b - A @ x) <= max(rtol*norm(b), atol)`` should be satisfied. + The default is ``atol=0.`` and ``rtol=1e-5``. + maxiter : integer + Maximum number of iterations. Iteration will stop after maxiter + steps even if the specified tolerance has not been achieved. + M : {sparse array, ndarray, LinearOperator} + Preconditioner for ``A``. It should approximate the + inverse of `A` (see Notes). Effective preconditioning dramatically improves the + rate of convergence, which implies that fewer iterations are needed + to reach a given error tolerance. + callback : function + User-supplied function to call after each iteration. It is called + as ``callback(xk)``, where ``xk`` is the current solution vector. + + Returns + ------- + x : ndarray + The converged solution. + info : integer + Provides convergence information: + 0 : successful exit + >0 : convergence to tolerance not achieved, number of iterations + <0 : parameter breakdown + + Notes + ----- + The preconditioner `M` should be a matrix such that ``M @ A`` has a smaller + condition number than `A`, see [1]_. + + References + ---------- + .. [1] "Preconditioner", Wikipedia, + https://en.wikipedia.org/wiki/Preconditioner + .. [2] "Conjugate gradient squared", Wikipedia, + https://en.wikipedia.org/wiki/Conjugate_gradient_squared_method + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import cgs + >>> R = np.array([[4, 2, 0, 1], + ... [3, 0, 0, 2], + ... [0, 1, 1, 1], + ... [0, 2, 1, 0]]) + >>> A = csc_array(R) + >>> b = np.array([-1, -0.5, -1, 2]) + >>> x, exit_code = cgs(A, b) + >>> print(exit_code) # 0 indicates successful convergence + 0 + >>> np.allclose(A.dot(x), b) + True + """ + A, M, x, b = make_system(A, M, x0, b) + bnrm2 = np.linalg.norm(b) + + atol, _ = _get_atol_rtol('cgs', bnrm2, atol, rtol) + + if bnrm2 == 0: + return b, 0 + + n = len(b) + + dotprod = np.vdot if np.iscomplexobj(x) else np.dot + + if maxiter is None: + maxiter = n*10 + + matvec = A.matvec + psolve = M.matvec + + rhotol = np.finfo(x.dtype.char).eps**2 + + r = b - matvec(x) if x.any() else b.copy() + + rtilde = r.copy() + bnorm = np.linalg.norm(b) + if bnorm == 0: + bnorm = 1 + + # Dummy values to initialize vars, silence linter warnings + rho_prev, p, u, q = None, None, None, None + + for iteration in range(maxiter): + rnorm = np.linalg.norm(r) + if rnorm < atol: # Are we done? + return x, 0 + + rho_cur = dotprod(rtilde, r) + if np.abs(rho_cur) < rhotol: # Breakdown case + return x, -10 + + if iteration > 0: + beta = rho_cur / rho_prev + + # u = r + beta * q + # p = u + beta * (q + beta * p); + u[:] = r[:] + u += beta*q + + p *= beta + p += q + p *= beta + p += u + + else: # First spin + p = r.copy() + u = r.copy() + q = np.empty_like(r) + + phat = psolve(p) + vhat = matvec(phat) + rv = dotprod(rtilde, vhat) + + if rv == 0: # Dot product breakdown + return x, -11 + + alpha = rho_cur / rv + q[:] = u[:] + q -= alpha*vhat + uhat = psolve(u + q) + x += alpha*uhat + + # Due to numerical error build-up the actual residual is computed + # instead of the following two lines that were in the original + # FORTRAN templates, still using a single matvec. + + # qhat = matvec(uhat) + # r -= alpha*qhat + r = b - matvec(x) + + rho_prev = rho_cur + + if callback: + callback(x) + + else: # for loop exhausted + # Return incomplete progress + return x, maxiter + + +def gmres(A, b, x0=None, *, rtol=1e-5, atol=0., restart=None, maxiter=None, M=None, + callback=None, callback_type=None): + """ + Solve ``Ax = b`` with the Generalized Minimal RESidual method. + + Parameters + ---------- + A : {sparse array, ndarray, LinearOperator} + The real or complex N-by-N matrix of the linear system. + Alternatively, `A` can be a linear operator which can + produce ``Ax`` using, e.g., + ``scipy.sparse.linalg.LinearOperator``. + b : ndarray + Right hand side of the linear system. Has shape (N,) or (N,1). + x0 : ndarray + Starting guess for the solution (a vector of zeros by default). + atol, rtol : float + Parameters for the convergence test. For convergence, + ``norm(b - A @ x) <= max(rtol*norm(b), atol)`` should be satisfied. + The default is ``atol=0.`` and ``rtol=1e-5``. + restart : int, optional + Number of iterations between restarts. Larger values increase + iteration cost, but may be necessary for convergence. + If omitted, ``min(20, n)`` is used. + maxiter : int, optional + Maximum number of iterations (restart cycles). Iteration will stop + after maxiter steps even if the specified tolerance has not been + achieved. See `callback_type`. + M : {sparse array, ndarray, LinearOperator} + Inverse of the preconditioner of `A`. `M` should approximate the + inverse of `A` and be easy to solve for (see Notes). Effective + preconditioning dramatically improves the rate of convergence, + which implies that fewer iterations are needed to reach a given + error tolerance. By default, no preconditioner is used. + In this implementation, left preconditioning is used, + and the preconditioned residual is minimized. However, the final + convergence is tested with respect to the ``b - A @ x`` residual. + callback : function + User-supplied function to call after each iteration. It is called + as ``callback(args)``, where ``args`` are selected by `callback_type`. + callback_type : {'x', 'pr_norm', 'legacy'}, optional + Callback function argument requested: + - ``x``: current iterate (ndarray), called on every restart + - ``pr_norm``: relative (preconditioned) residual norm (float), + called on every inner iteration + - ``legacy`` (default): same as ``pr_norm``, but also changes the + meaning of `maxiter` to count inner iterations instead of restart + cycles. + + This keyword has no effect if `callback` is not set. + + Returns + ------- + x : ndarray + The converged solution. + info : int + Provides convergence information: + 0 : successful exit + >0 : convergence to tolerance not achieved, number of iterations + + See Also + -------- + LinearOperator + + Notes + ----- + A preconditioner, P, is chosen such that P is close to A but easy to solve + for. The preconditioner parameter required by this routine is + ``M = P^-1``. The inverse should preferably not be calculated + explicitly. Rather, use the following template to produce M:: + + # Construct a linear operator that computes P^-1 @ x. + import scipy.sparse.linalg as spla + M_x = lambda x: spla.spsolve(P, x) + M = spla.LinearOperator((n, n), M_x) + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import gmres + >>> A = csc_array([[3, 2, 0], [1, -1, 0], [0, 5, 1]], dtype=float) + >>> b = np.array([2, 4, -1], dtype=float) + >>> x, exitCode = gmres(A, b, atol=1e-5) + >>> print(exitCode) # 0 indicates successful convergence + 0 + >>> np.allclose(A.dot(x), b) + True + """ + if callback is not None and callback_type is None: + # Warn about 'callback_type' semantic changes. + # Probably should be removed only in far future, Scipy 2.0 or so. + msg = ("scipy.sparse.linalg.gmres called without specifying " + "`callback_type`. The default value will be changed in" + " a future release. For compatibility, specify a value " + "for `callback_type` explicitly, e.g., " + "``gmres(..., callback_type='pr_norm')``, or to retain the " + "old behavior ``gmres(..., callback_type='legacy')``" + ) + warnings.warn(msg, category=DeprecationWarning, stacklevel=3) + + if callback_type is None: + callback_type = 'legacy' + + if callback_type not in ('x', 'pr_norm', 'legacy'): + raise ValueError(f"Unknown callback_type: {callback_type!r}") + + if callback is None: + callback_type = None + + A, M, x, b = make_system(A, M, x0, b) + matvec = A.matvec + psolve = M.matvec + n = len(b) + bnrm2 = np.linalg.norm(b) + + atol, _ = _get_atol_rtol('gmres', bnrm2, atol, rtol) + + if bnrm2 == 0: + return b, 0 + + eps = np.finfo(x.dtype.char).eps + + dotprod = np.vdot if np.iscomplexobj(x) else np.dot + + if maxiter is None: + maxiter = n*10 + + if restart is None: + restart = 20 + restart = min(restart, n) + + Mb_nrm2 = np.linalg.norm(psolve(b)) + + # ==================================================== + # =========== Tolerance control from gh-8400 ========= + # ==================================================== + # Tolerance passed to GMRESREVCOM applies to the inner + # iteration and deals with the left-preconditioned + # residual. + ptol_max_factor = 1. + ptol = Mb_nrm2 * min(ptol_max_factor, atol / bnrm2) + presid = 0. + # ==================================================== + lartg = get_lapack_funcs('lartg', dtype=x.dtype) + + # allocate internal variables + v = np.empty([restart+1, n], dtype=x.dtype) + h = np.zeros([restart, restart+1], dtype=x.dtype) + givens = np.zeros([restart, 2], dtype=x.dtype) + + # legacy iteration count + inner_iter = 0 + + for iteration in range(maxiter): + if iteration == 0: + r = b - matvec(x) if x.any() else b.copy() + if np.linalg.norm(r) < atol: # Are we done? + return x, 0 + + v[0, :] = psolve(r) + tmp = np.linalg.norm(v[0, :]) + v[0, :] *= (1 / tmp) + # RHS of the Hessenberg problem + S = np.zeros(restart+1, dtype=x.dtype) + S[0] = tmp + + breakdown = False + for col in range(restart): + av = matvec(v[col, :]) + w = psolve(av) + + # Modified Gram-Schmidt + h0 = np.linalg.norm(w) + for k in range(col+1): + tmp = dotprod(v[k, :], w) + h[col, k] = tmp + w -= tmp*v[k, :] + + h1 = np.linalg.norm(w) + h[col, col + 1] = h1 + v[col + 1, :] = w[:] + + # Exact solution indicator + if h1 <= eps*h0: + h[col, col + 1] = 0 + breakdown = True + else: + v[col + 1, :] *= (1 / h1) + + # apply past Givens rotations to current h column + for k in range(col): + c, s = givens[k, 0], givens[k, 1] + n0, n1 = h[col, [k, k+1]] + h[col, [k, k + 1]] = [c*n0 + s*n1, -s.conj()*n0 + c*n1] + + # get and apply current rotation to h and S + c, s, mag = lartg(h[col, col], h[col, col+1]) + givens[col, :] = [c, s] + h[col, [col, col+1]] = mag, 0 + + # S[col+1] component is always 0 + tmp = -np.conjugate(s)*S[col] + S[[col, col + 1]] = [c*S[col], tmp] + presid = np.abs(tmp) + inner_iter += 1 + + if callback_type in ('legacy', 'pr_norm'): + callback(presid / bnrm2) + # Legacy behavior + if callback_type == 'legacy' and inner_iter == maxiter: + break + if presid <= ptol or breakdown: + break + + # Solve h(col, col) upper triangular system and allow pseudo-solve + # singular cases as in (but without the f2py copies): + # y = trsv(h[:col+1, :col+1].T, S[:col+1]) + + if h[col, col] == 0: + S[col] = 0 + + y = np.zeros([col+1], dtype=x.dtype) + y[:] = S[:col+1] + for k in range(col, 0, -1): + if y[k] != 0: + y[k] /= h[k, k] + tmp = y[k] + y[:k] -= tmp*h[k, :k] + if y[0] != 0: + y[0] /= h[0, 0] + + x += y @ v[:col+1, :] + + r = b - matvec(x) + rnorm = np.linalg.norm(r) + + # Legacy exit + if callback_type == 'legacy' and inner_iter == maxiter: + return x, 0 if rnorm <= atol else maxiter + + if callback_type == 'x': + callback(x) + + if rnorm <= atol: + break + elif breakdown: + # Reached breakdown (= exact solution), but the external + # tolerance check failed. Bail out with failure. + break + elif presid <= ptol: + # Inner loop passed but outer didn't + ptol_max_factor = max(eps, 0.25 * ptol_max_factor) + else: + ptol_max_factor = min(1.0, 1.5 * ptol_max_factor) + + ptol = presid * min(ptol_max_factor, atol / rnorm) + + info = 0 if (rnorm <= atol) else maxiter + return x, info + + +def qmr(A, b, x0=None, *, rtol=1e-5, atol=0., maxiter=None, M1=None, M2=None, + callback=None): + """ + Solve ``Ax = b`` with the Quasi-Minimal Residual method. + + Parameters + ---------- + A : {sparse array, ndarray, LinearOperator} + The real-valued N-by-N matrix of the linear system. + Alternatively, ``A`` can be a linear operator which can + produce ``Ax`` and ``A^T x`` using, e.g., + ``scipy.sparse.linalg.LinearOperator``. + b : ndarray + Right hand side of the linear system. Has shape (N,) or (N,1). + x0 : ndarray + Starting guess for the solution. + atol, rtol : float, optional + Parameters for the convergence test. For convergence, + ``norm(b - A @ x) <= max(rtol*norm(b), atol)`` should be satisfied. + The default is ``atol=0.`` and ``rtol=1e-5``. + maxiter : integer + Maximum number of iterations. Iteration will stop after maxiter + steps even if the specified tolerance has not been achieved. + M1 : {sparse array, ndarray, LinearOperator} + Left preconditioner for A. + M2 : {sparse array, ndarray, LinearOperator} + Right preconditioner for A. Used together with the left + preconditioner M1. The matrix M1@A@M2 should have better + conditioned than A alone. + callback : function + User-supplied function to call after each iteration. It is called + as callback(xk), where xk is the current solution vector. + + Returns + ------- + x : ndarray + The converged solution. + info : integer + Provides convergence information: + 0 : successful exit + >0 : convergence to tolerance not achieved, number of iterations + <0 : parameter breakdown + + See Also + -------- + LinearOperator + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import qmr + >>> A = csc_array([[3., 2., 0.], [1., -1., 0.], [0., 5., 1.]]) + >>> b = np.array([2., 4., -1.]) + >>> x, exitCode = qmr(A, b, atol=1e-5) + >>> print(exitCode) # 0 indicates successful convergence + 0 + >>> np.allclose(A.dot(x), b) + True + """ + A_ = A + A, M, x, b = make_system(A, None, x0, b) + bnrm2 = np.linalg.norm(b) + + atol, _ = _get_atol_rtol('qmr', bnrm2, atol, rtol) + + if bnrm2 == 0: + return b, 0 + + if M1 is None and M2 is None: + if hasattr(A_, 'psolve'): + def left_psolve(b): + return A_.psolve(b, 'left') + + def right_psolve(b): + return A_.psolve(b, 'right') + + def left_rpsolve(b): + return A_.rpsolve(b, 'left') + + def right_rpsolve(b): + return A_.rpsolve(b, 'right') + M1 = LinearOperator(A.shape, + matvec=left_psolve, + rmatvec=left_rpsolve) + M2 = LinearOperator(A.shape, + matvec=right_psolve, + rmatvec=right_rpsolve) + else: + def id(b): + return b + M1 = LinearOperator(A.shape, matvec=id, rmatvec=id) + M2 = LinearOperator(A.shape, matvec=id, rmatvec=id) + + n = len(b) + if maxiter is None: + maxiter = n*10 + + dotprod = np.vdot if np.iscomplexobj(x) else np.dot + + rhotol = np.finfo(x.dtype.char).eps + betatol = rhotol + gammatol = rhotol + deltatol = rhotol + epsilontol = rhotol + xitol = rhotol + + r = b - A.matvec(x) if x.any() else b.copy() + + vtilde = r.copy() + y = M1.matvec(vtilde) + rho = np.linalg.norm(y) + wtilde = r.copy() + z = M2.rmatvec(wtilde) + xi = np.linalg.norm(z) + gamma, eta, theta = 1, -1, 0 + v = np.empty_like(vtilde) + w = np.empty_like(wtilde) + + # Dummy values to initialize vars, silence linter warnings + epsilon, q, d, p, s = None, None, None, None, None + + for iteration in range(maxiter): + if np.linalg.norm(r) < atol: # Are we done? + return x, 0 + if np.abs(rho) < rhotol: # rho breakdown + return x, -10 + if np.abs(xi) < xitol: # xi breakdown + return x, -15 + + v[:] = vtilde[:] + v *= (1 / rho) + y *= (1 / rho) + w[:] = wtilde[:] + w *= (1 / xi) + z *= (1 / xi) + delta = dotprod(z, y) + + if np.abs(delta) < deltatol: # delta breakdown + return x, -13 + + ytilde = M2.matvec(y) + ztilde = M1.rmatvec(z) + + if iteration > 0: + ytilde -= (xi * delta / epsilon) * p + p[:] = ytilde[:] + ztilde -= (rho * (delta / epsilon).conj()) * q + q[:] = ztilde[:] + else: # First spin + p = ytilde.copy() + q = ztilde.copy() + + ptilde = A.matvec(p) + epsilon = dotprod(q, ptilde) + if np.abs(epsilon) < epsilontol: # epsilon breakdown + return x, -14 + + beta = epsilon / delta + if np.abs(beta) < betatol: # beta breakdown + return x, -11 + + vtilde[:] = ptilde[:] + vtilde -= beta*v + y = M1.matvec(vtilde) + + rho_prev = rho + rho = np.linalg.norm(y) + wtilde[:] = w[:] + wtilde *= - beta.conj() + wtilde += A.rmatvec(q) + z = M2.rmatvec(wtilde) + xi = np.linalg.norm(z) + gamma_prev = gamma + theta_prev = theta + theta = rho / (gamma_prev * np.abs(beta)) + gamma = 1 / np.sqrt(1 + theta**2) + + if np.abs(gamma) < gammatol: # gamma breakdown + return x, -12 + + eta *= -(rho_prev / beta) * (gamma / gamma_prev)**2 + + if iteration > 0: + d *= (theta_prev * gamma) ** 2 + d += eta*p + s *= (theta_prev * gamma) ** 2 + s += eta*ptilde + else: + d = p.copy() + d *= eta + s = ptilde.copy() + s *= eta + + x += d + r -= s + + if callback: + callback(x) + + else: # for loop exhausted + # Return incomplete progress + return x, maxiter diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/lgmres.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/lgmres.py new file mode 100644 index 0000000000000000000000000000000000000000..e44613c94691f6c345630303fca049201247a8a1 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/lgmres.py @@ -0,0 +1,230 @@ +# Copyright (C) 2009, Pauli Virtanen +# Distributed under the same license as SciPy. + +import numpy as np +from numpy.linalg import LinAlgError +from scipy.linalg import get_blas_funcs +from .iterative import _get_atol_rtol +from .utils import make_system + +from ._gcrotmk import _fgmres + +__all__ = ['lgmres'] + + +def lgmres(A, b, x0=None, *, rtol=1e-5, atol=0., maxiter=1000, M=None, callback=None, + inner_m=30, outer_k=3, outer_v=None, store_outer_Av=True, + prepend_outer_v=False): + """ + Solve ``Ax = b`` with the LGMRES algorithm. + + The LGMRES algorithm [1]_ [2]_ is designed to avoid some problems + in the convergence in restarted GMRES, and often converges in fewer + iterations. + + Parameters + ---------- + A : {sparse array, ndarray, LinearOperator} + The real or complex N-by-N matrix of the linear system. + Alternatively, ``A`` can be a linear operator which can + produce ``Ax`` using, e.g., + ``scipy.sparse.linalg.LinearOperator``. + b : ndarray + Right hand side of the linear system. Has shape (N,) or (N,1). + x0 : ndarray + Starting guess for the solution. + rtol, atol : float, optional + Parameters for the convergence test. For convergence, + ``norm(b - A @ x) <= max(rtol*norm(b), atol)`` should be satisfied. + The default is ``rtol=1e-5``, the default for ``atol`` is ``0.0``. + maxiter : int, optional + Maximum number of iterations. Iteration will stop after maxiter + steps even if the specified tolerance has not been achieved. + M : {sparse array, ndarray, LinearOperator}, optional + Preconditioner for A. The preconditioner should approximate the + inverse of A. Effective preconditioning dramatically improves the + rate of convergence, which implies that fewer iterations are needed + to reach a given error tolerance. + callback : function, optional + User-supplied function to call after each iteration. It is called + as callback(xk), where xk is the current solution vector. + inner_m : int, optional + Number of inner GMRES iterations per each outer iteration. + outer_k : int, optional + Number of vectors to carry between inner GMRES iterations. + According to [1]_, good values are in the range of 1...3. + However, note that if you want to use the additional vectors to + accelerate solving multiple similar problems, larger values may + be beneficial. + outer_v : list of tuples, optional + List containing tuples ``(v, Av)`` of vectors and corresponding + matrix-vector products, used to augment the Krylov subspace, and + carried between inner GMRES iterations. The element ``Av`` can + be `None` if the matrix-vector product should be re-evaluated. + This parameter is modified in-place by `lgmres`, and can be used + to pass "guess" vectors in and out of the algorithm when solving + similar problems. + store_outer_Av : bool, optional + Whether LGMRES should store also A@v in addition to vectors `v` + in the `outer_v` list. Default is True. + prepend_outer_v : bool, optional + Whether to put outer_v augmentation vectors before Krylov iterates. + In standard LGMRES, prepend_outer_v=False. + + Returns + ------- + x : ndarray + The converged solution. + info : int + Provides convergence information: + + - 0 : successful exit + - >0 : convergence to tolerance not achieved, number of iterations + - <0 : illegal input or breakdown + + Notes + ----- + The LGMRES algorithm [1]_ [2]_ is designed to avoid the + slowing of convergence in restarted GMRES, due to alternating + residual vectors. Typically, it often outperforms GMRES(m) of + comparable memory requirements by some measure, or at least is not + much worse. + + Another advantage in this algorithm is that you can supply it with + 'guess' vectors in the `outer_v` argument that augment the Krylov + subspace. If the solution lies close to the span of these vectors, + the algorithm converges faster. This can be useful if several very + similar matrices need to be inverted one after another, such as in + Newton-Krylov iteration where the Jacobian matrix often changes + little in the nonlinear steps. + + References + ---------- + .. [1] A.H. Baker and E.R. Jessup and T. Manteuffel, "A Technique for + Accelerating the Convergence of Restarted GMRES", SIAM J. Matrix + Anal. Appl. 26, 962 (2005). + .. [2] A.H. Baker, "On Improving the Performance of the Linear Solver + restarted GMRES", PhD thesis, University of Colorado (2003). + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import lgmres + >>> A = csc_array([[3, 2, 0], [1, -1, 0], [0, 5, 1]], dtype=float) + >>> b = np.array([2, 4, -1], dtype=float) + >>> x, exitCode = lgmres(A, b, atol=1e-5) + >>> print(exitCode) # 0 indicates successful convergence + 0 + >>> np.allclose(A.dot(x), b) + True + """ + A,M,x,b = make_system(A,M,x0,b) + + if not np.isfinite(b).all(): + raise ValueError("RHS must contain only finite numbers") + + matvec = A.matvec + psolve = M.matvec + + if outer_v is None: + outer_v = [] + + axpy, dot, scal = None, None, None + nrm2 = get_blas_funcs('nrm2', [b]) + + b_norm = nrm2(b) + + # we call this to get the right atol/rtol and raise errors as necessary + atol, rtol = _get_atol_rtol('lgmres', b_norm, atol, rtol) + + if b_norm == 0: + x = b + return (x, 0) + + ptol_max_factor = 1.0 + + for k_outer in range(maxiter): + r_outer = matvec(x) - b + + # -- callback + if callback is not None: + callback(x) + + # -- determine input type routines + if axpy is None: + if np.iscomplexobj(r_outer) and not np.iscomplexobj(x): + x = x.astype(r_outer.dtype) + axpy, dot, scal, nrm2 = get_blas_funcs(['axpy', 'dot', 'scal', 'nrm2'], + (x, r_outer)) + + # -- check stopping condition + r_norm = nrm2(r_outer) + if r_norm <= max(atol, rtol * b_norm): + break + + # -- inner LGMRES iteration + v0 = -psolve(r_outer) + inner_res_0 = nrm2(v0) + + if inner_res_0 == 0: + rnorm = nrm2(r_outer) + raise RuntimeError("Preconditioner returned a zero vector; " + f"|v| ~ {rnorm:.1g}, |M v| = 0") + + v0 = scal(1.0/inner_res_0, v0) + + ptol = min(ptol_max_factor, max(atol, rtol*b_norm)/r_norm) + + try: + Q, R, B, vs, zs, y, pres = _fgmres(matvec, + v0, + inner_m, + lpsolve=psolve, + atol=ptol, + outer_v=outer_v, + prepend_outer_v=prepend_outer_v) + y *= inner_res_0 + if not np.isfinite(y).all(): + # Overflow etc. in computation. There's no way to + # recover from this, so we have to bail out. + raise LinAlgError() + except LinAlgError: + # Floating point over/underflow, non-finite result from + # matmul etc. -- report failure. + return x, k_outer + 1 + + # Inner loop tolerance control + if pres > ptol: + ptol_max_factor = min(1.0, 1.5 * ptol_max_factor) + else: + ptol_max_factor = max(1e-16, 0.25 * ptol_max_factor) + + # -- GMRES terminated: eval solution + dx = zs[0]*y[0] + for w, yc in zip(zs[1:], y[1:]): + dx = axpy(w, dx, dx.shape[0], yc) # dx += w*yc + + # -- Store LGMRES augmentation vectors + nx = nrm2(dx) + if nx > 0: + if store_outer_Av: + q = Q.dot(R.dot(y)) + ax = vs[0]*q[0] + for v, qc in zip(vs[1:], q[1:]): + ax = axpy(v, ax, ax.shape[0], qc) + outer_v.append((dx/nx, ax/nx)) + else: + outer_v.append((dx/nx, None)) + + # -- Retain only a finite number of augmentation vectors + while len(outer_v) > outer_k: + del outer_v[0] + + # -- Apply step + x += dx + else: + # didn't converge ... + return x, maxiter + + return x, 0 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/lsmr.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/lsmr.py new file mode 100644 index 0000000000000000000000000000000000000000..97eb734aa64c3145044a81e97b0e1b8df9506ce2 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/lsmr.py @@ -0,0 +1,486 @@ +""" +Copyright (C) 2010 David Fong and Michael Saunders + +LSMR uses an iterative method. + +07 Jun 2010: Documentation updated +03 Jun 2010: First release version in Python + +David Chin-lung Fong clfong@stanford.edu +Institute for Computational and Mathematical Engineering +Stanford University + +Michael Saunders saunders@stanford.edu +Systems Optimization Laboratory +Dept of MS&E, Stanford University. + +""" + +__all__ = ['lsmr'] + +from numpy import zeros, inf, atleast_1d, result_type +from numpy.linalg import norm +from math import sqrt +from scipy.sparse.linalg._interface import aslinearoperator + +from scipy.sparse.linalg._isolve.lsqr import _sym_ortho + + +def lsmr(A, b, damp=0.0, atol=1e-6, btol=1e-6, conlim=1e8, + maxiter=None, show=False, x0=None): + """Iterative solver for least-squares problems. + + lsmr solves the system of linear equations ``Ax = b``. If the system + is inconsistent, it solves the least-squares problem ``min ||b - Ax||_2``. + ``A`` is a rectangular matrix of dimension m-by-n, where all cases are + allowed: m = n, m > n, or m < n. ``b`` is a vector of length m. + The matrix A may be dense or sparse (usually sparse). + + Parameters + ---------- + A : {sparse array, ndarray, LinearOperator} + Matrix A in the linear system. + Alternatively, ``A`` can be a linear operator which can + produce ``Ax`` and ``A^H x`` using, e.g., + ``scipy.sparse.linalg.LinearOperator``. + b : array_like, shape (m,) + Vector ``b`` in the linear system. + damp : float + Damping factor for regularized least-squares. `lsmr` solves + the regularized least-squares problem:: + + min ||(b) - ( A )x|| + ||(0) (damp*I) ||_2 + + where damp is a scalar. If damp is None or 0, the system + is solved without regularization. Default is 0. + atol, btol : float, optional + Stopping tolerances. `lsmr` continues iterations until a + certain backward error estimate is smaller than some quantity + depending on atol and btol. Let ``r = b - Ax`` be the + residual vector for the current approximate solution ``x``. + If ``Ax = b`` seems to be consistent, `lsmr` terminates + when ``norm(r) <= atol * norm(A) * norm(x) + btol * norm(b)``. + Otherwise, `lsmr` terminates when ``norm(A^H r) <= + atol * norm(A) * norm(r)``. If both tolerances are 1.0e-6 (default), + the final ``norm(r)`` should be accurate to about 6 + digits. (The final ``x`` will usually have fewer correct digits, + depending on ``cond(A)`` and the size of LAMBDA.) If `atol` + or `btol` is None, a default value of 1.0e-6 will be used. + Ideally, they should be estimates of the relative error in the + entries of ``A`` and ``b`` respectively. For example, if the entries + of ``A`` have 7 correct digits, set ``atol = 1e-7``. This prevents + the algorithm from doing unnecessary work beyond the + uncertainty of the input data. + conlim : float, optional + `lsmr` terminates if an estimate of ``cond(A)`` exceeds + `conlim`. For compatible systems ``Ax = b``, conlim could be + as large as 1.0e+12 (say). For least-squares problems, + `conlim` should be less than 1.0e+8. If `conlim` is None, the + default value is 1e+8. Maximum precision can be obtained by + setting ``atol = btol = conlim = 0``, but the number of + iterations may then be excessive. Default is 1e8. + maxiter : int, optional + `lsmr` terminates if the number of iterations reaches + `maxiter`. The default is ``maxiter = min(m, n)``. For + ill-conditioned systems, a larger value of `maxiter` may be + needed. Default is False. + show : bool, optional + Print iterations logs if ``show=True``. Default is False. + x0 : array_like, shape (n,), optional + Initial guess of ``x``, if None zeros are used. Default is None. + + .. versionadded:: 1.0.0 + + Returns + ------- + x : ndarray of float + Least-square solution returned. + istop : int + istop gives the reason for stopping:: + + istop = 0 means x=0 is a solution. If x0 was given, then x=x0 is a + solution. + = 1 means x is an approximate solution to A@x = B, + according to atol and btol. + = 2 means x approximately solves the least-squares problem + according to atol. + = 3 means COND(A) seems to be greater than CONLIM. + = 4 is the same as 1 with atol = btol = eps (machine + precision) + = 5 is the same as 2 with atol = eps. + = 6 is the same as 3 with CONLIM = 1/eps. + = 7 means ITN reached maxiter before the other stopping + conditions were satisfied. + + itn : int + Number of iterations used. + normr : float + ``norm(b-Ax)`` + normar : float + ``norm(A^H (b - Ax))`` + norma : float + ``norm(A)`` + conda : float + Condition number of A. + normx : float + ``norm(x)`` + + Notes + ----- + + .. versionadded:: 0.11.0 + + References + ---------- + .. [1] D. C.-L. Fong and M. A. Saunders, + "LSMR: An iterative algorithm for sparse least-squares problems", + SIAM J. Sci. Comput., vol. 33, pp. 2950-2971, 2011. + :arxiv:`1006.0758` + .. [2] LSMR Software, https://web.stanford.edu/group/SOL/software/lsmr/ + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import lsmr + >>> A = csc_array([[1., 0.], [1., 1.], [0., 1.]], dtype=float) + + The first example has the trivial solution ``[0, 0]`` + + >>> b = np.array([0., 0., 0.], dtype=float) + >>> x, istop, itn, normr = lsmr(A, b)[:4] + >>> istop + 0 + >>> x + array([0., 0.]) + + The stopping code ``istop=0`` returned indicates that a vector of zeros was + found as a solution. The returned solution `x` indeed contains + ``[0., 0.]``. The next example has a non-trivial solution: + + >>> b = np.array([1., 0., -1.], dtype=float) + >>> x, istop, itn, normr = lsmr(A, b)[:4] + >>> istop + 1 + >>> x + array([ 1., -1.]) + >>> itn + 1 + >>> normr + 4.440892098500627e-16 + + As indicated by ``istop=1``, `lsmr` found a solution obeying the tolerance + limits. The given solution ``[1., -1.]`` obviously solves the equation. The + remaining return values include information about the number of iterations + (`itn=1`) and the remaining difference of left and right side of the solved + equation. + The final example demonstrates the behavior in the case where there is no + solution for the equation: + + >>> b = np.array([1., 0.01, -1.], dtype=float) + >>> x, istop, itn, normr = lsmr(A, b)[:4] + >>> istop + 2 + >>> x + array([ 1.00333333, -0.99666667]) + >>> A.dot(x)-b + array([ 0.00333333, -0.00333333, 0.00333333]) + >>> normr + 0.005773502691896255 + + `istop` indicates that the system is inconsistent and thus `x` is rather an + approximate solution to the corresponding least-squares problem. `normr` + contains the minimal distance that was found. + """ + + A = aslinearoperator(A) + b = atleast_1d(b) + if b.ndim > 1: + b = b.squeeze() + + msg = ('The exact solution is x = 0, or x = x0, if x0 was given ', + 'Ax - b is small enough, given atol, btol ', + 'The least-squares solution is good enough, given atol ', + 'The estimate of cond(Abar) has exceeded conlim ', + 'Ax - b is small enough for this machine ', + 'The least-squares solution is good enough for this machine', + 'Cond(Abar) seems to be too large for this machine ', + 'The iteration limit has been reached ') + + hdg1 = ' itn x(1) norm r norm Ar' + hdg2 = ' compatible LS norm A cond A' + pfreq = 20 # print frequency (for repeating the heading) + pcount = 0 # print counter + + m, n = A.shape + + # stores the num of singular values + minDim = min([m, n]) + + if maxiter is None: + maxiter = minDim + + if x0 is None: + dtype = result_type(A, b, float) + else: + dtype = result_type(A, b, x0, float) + + if show: + print(' ') + print('LSMR Least-squares solution of Ax = b\n') + print(f'The matrix A has {m} rows and {n} columns') + print(f'damp = {damp:20.14e}\n') + print(f'atol = {atol:8.2e} conlim = {conlim:8.2e}\n') + print(f'btol = {btol:8.2e} maxiter = {maxiter:8g}\n') + + u = b + normb = norm(b) + if x0 is None: + x = zeros(n, dtype) + beta = normb.copy() + else: + x = atleast_1d(x0.copy()) + u = u - A.matvec(x) + beta = norm(u) + + if beta > 0: + u = (1 / beta) * u + v = A.rmatvec(u) + alpha = norm(v) + else: + v = zeros(n, dtype) + alpha = 0 + + if alpha > 0: + v = (1 / alpha) * v + + # Initialize variables for 1st iteration. + + itn = 0 + zetabar = alpha * beta + alphabar = alpha + rho = 1 + rhobar = 1 + cbar = 1 + sbar = 0 + + h = v.copy() + hbar = zeros(n, dtype) + + # Initialize variables for estimation of ||r||. + + betadd = beta + betad = 0 + rhodold = 1 + tautildeold = 0 + thetatilde = 0 + zeta = 0 + d = 0 + + # Initialize variables for estimation of ||A|| and cond(A) + + normA2 = alpha * alpha + maxrbar = 0 + minrbar = 1e+100 + normA = sqrt(normA2) + condA = 1 + normx = 0 + + # Items for use in stopping rules, normb set earlier + istop = 0 + ctol = 0 + if conlim > 0: + ctol = 1 / conlim + normr = beta + + # Reverse the order here from the original matlab code because + # there was an error on return when arnorm==0 + normar = alpha * beta + if normar == 0: + if show: + print(msg[0]) + return x, istop, itn, normr, normar, normA, condA, normx + + if normb == 0: + x[()] = 0 + return x, istop, itn, normr, normar, normA, condA, normx + + if show: + print(' ') + print(hdg1, hdg2) + test1 = 1 + test2 = alpha / beta + str1 = f'{itn:6g} {x[0]:12.5e}' + str2 = f' {normr:10.3e} {normar:10.3e}' + str3 = f' {test1:8.1e} {test2:8.1e}' + print(''.join([str1, str2, str3])) + + # Main iteration loop. + while itn < maxiter: + itn = itn + 1 + + # Perform the next step of the bidiagonalization to obtain the + # next beta, u, alpha, v. These satisfy the relations + # beta*u = A@v - alpha*u, + # alpha*v = A'@u - beta*v. + + u *= -alpha + u += A.matvec(v) + beta = norm(u) + + if beta > 0: + u *= (1 / beta) + v *= -beta + v += A.rmatvec(u) + alpha = norm(v) + if alpha > 0: + v *= (1 / alpha) + + # At this point, beta = beta_{k+1}, alpha = alpha_{k+1}. + + # Construct rotation Qhat_{k,2k+1}. + + chat, shat, alphahat = _sym_ortho(alphabar, damp) + + # Use a plane rotation (Q_i) to turn B_i to R_i + + rhoold = rho + c, s, rho = _sym_ortho(alphahat, beta) + thetanew = s*alpha + alphabar = c*alpha + + # Use a plane rotation (Qbar_i) to turn R_i^T to R_i^bar + + rhobarold = rhobar + zetaold = zeta + thetabar = sbar * rho + rhotemp = cbar * rho + cbar, sbar, rhobar = _sym_ortho(cbar * rho, thetanew) + zeta = cbar * zetabar + zetabar = - sbar * zetabar + + # Update h, h_hat, x. + + hbar *= - (thetabar * rho / (rhoold * rhobarold)) + hbar += h + x += (zeta / (rho * rhobar)) * hbar + h *= - (thetanew / rho) + h += v + + # Estimate of ||r||. + + # Apply rotation Qhat_{k,2k+1}. + betaacute = chat * betadd + betacheck = -shat * betadd + + # Apply rotation Q_{k,k+1}. + betahat = c * betaacute + betadd = -s * betaacute + + # Apply rotation Qtilde_{k-1}. + # betad = betad_{k-1} here. + + thetatildeold = thetatilde + ctildeold, stildeold, rhotildeold = _sym_ortho(rhodold, thetabar) + thetatilde = stildeold * rhobar + rhodold = ctildeold * rhobar + betad = - stildeold * betad + ctildeold * betahat + + # betad = betad_k here. + # rhodold = rhod_k here. + + tautildeold = (zetaold - thetatildeold * tautildeold) / rhotildeold + taud = (zeta - thetatilde * tautildeold) / rhodold + d = d + betacheck * betacheck + normr = sqrt(d + (betad - taud)**2 + betadd * betadd) + + # Estimate ||A||. + normA2 = normA2 + beta * beta + normA = sqrt(normA2) + normA2 = normA2 + alpha * alpha + + # Estimate cond(A). + maxrbar = max(maxrbar, rhobarold) + if itn > 1: + minrbar = min(minrbar, rhobarold) + condA = max(maxrbar, rhotemp) / min(minrbar, rhotemp) + + # Test for convergence. + + # Compute norms for convergence testing. + normar = abs(zetabar) + normx = norm(x) + + # Now use these norms to estimate certain other quantities, + # some of which will be small near a solution. + + test1 = normr / normb + if (normA * normr) != 0: + test2 = normar / (normA * normr) + else: + test2 = inf + test3 = 1 / condA + t1 = test1 / (1 + normA * normx / normb) + rtol = btol + atol * normA * normx / normb + + # The following tests guard against extremely small values of + # atol, btol or ctol. (The user may have set any or all of + # the parameters atol, btol, conlim to 0.) + # The effect is equivalent to the normAl tests using + # atol = eps, btol = eps, conlim = 1/eps. + + if itn >= maxiter: + istop = 7 + if 1 + test3 <= 1: + istop = 6 + if 1 + test2 <= 1: + istop = 5 + if 1 + t1 <= 1: + istop = 4 + + # Allow for tolerances set by the user. + + if test3 <= ctol: + istop = 3 + if test2 <= atol: + istop = 2 + if test1 <= rtol: + istop = 1 + + # See if it is time to print something. + + if show: + if (n <= 40) or (itn <= 10) or (itn >= maxiter - 10) or \ + (itn % 10 == 0) or (test3 <= 1.1 * ctol) or \ + (test2 <= 1.1 * atol) or (test1 <= 1.1 * rtol) or \ + (istop != 0): + + if pcount >= pfreq: + pcount = 0 + print(' ') + print(hdg1, hdg2) + pcount = pcount + 1 + str1 = f'{itn:6g} {x[0]:12.5e}' + str2 = f' {normr:10.3e} {normar:10.3e}' + str3 = f' {test1:8.1e} {test2:8.1e}' + str4 = f' {normA:8.1e} {condA:8.1e}' + print(''.join([str1, str2, str3, str4])) + + if istop > 0: + break + + # Print the stopping condition. + + if show: + print(' ') + print('LSMR finished') + print(msg[istop]) + print(f'istop ={istop:8g} normr ={normr:8.1e}') + print(f' normA ={normA:8.1e} normAr ={normar:8.1e}') + print(f'itn ={itn:8g} condA ={condA:8.1e}') + print(f' normx ={normx:8.1e}') + print(str1, str2) + print(str3, str4) + + return x, istop, itn, normr, normar, normA, condA, normx diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/lsqr.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/lsqr.py new file mode 100644 index 0000000000000000000000000000000000000000..3e490a0769e6d20303b1e5fdd111237b72d3abc9 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/lsqr.py @@ -0,0 +1,589 @@ +"""Sparse Equations and Least Squares. + +The original Fortran code was written by C. C. Paige and M. A. Saunders as +described in + +C. C. Paige and M. A. Saunders, LSQR: An algorithm for sparse linear +equations and sparse least squares, TOMS 8(1), 43--71 (1982). + +C. C. Paige and M. A. Saunders, Algorithm 583; LSQR: Sparse linear +equations and least-squares problems, TOMS 8(2), 195--209 (1982). + +It is licensed under the following BSD license: + +Copyright (c) 2006, Systems Optimization Laboratory +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Stanford University nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The Fortran code was translated to Python for use in CVXOPT by Jeffery +Kline with contributions by Mridul Aanjaneya and Bob Myhill. + +Adapted for SciPy by Stefan van der Walt. + +""" + +__all__ = ['lsqr'] + +import numpy as np +from math import sqrt +from scipy.sparse.linalg._interface import aslinearoperator +from scipy.sparse._sputils import convert_pydata_sparse_to_scipy + +eps = np.finfo(np.float64).eps + + +def _sym_ortho(a, b): + """ + Stable implementation of Givens rotation. + + Notes + ----- + The routine 'SymOrtho' was added for numerical stability. This is + recommended by S.-C. Choi in [1]_. It removes the unpleasant potential of + ``1/eps`` in some important places (see, for example text following + "Compute the next plane rotation Qk" in minres.py). + + References + ---------- + .. [1] S.-C. Choi, "Iterative Methods for Singular Linear Equations + and Least-Squares Problems", Dissertation, + http://www.stanford.edu/group/SOL/dissertations/sou-cheng-choi-thesis.pdf + + """ + if b == 0: + return np.sign(a), 0, abs(a) + elif a == 0: + return 0, np.sign(b), abs(b) + elif abs(b) > abs(a): + tau = a / b + s = np.sign(b) / sqrt(1 + tau * tau) + c = s * tau + r = b / s + else: + tau = b / a + c = np.sign(a) / sqrt(1+tau*tau) + s = c * tau + r = a / c + return c, s, r + + +def lsqr(A, b, damp=0.0, atol=1e-6, btol=1e-6, conlim=1e8, + iter_lim=None, show=False, calc_var=False, x0=None): + """Find the least-squares solution to a large, sparse, linear system + of equations. + + The function solves ``Ax = b`` or ``min ||Ax - b||^2`` or + ``min ||Ax - b||^2 + d^2 ||x - x0||^2``. + + The matrix A may be square or rectangular (over-determined or + under-determined), and may have any rank. + + :: + + 1. Unsymmetric equations -- solve Ax = b + + 2. Linear least squares -- solve Ax = b + in the least-squares sense + + 3. Damped least squares -- solve ( A )*x = ( b ) + ( damp*I ) ( damp*x0 ) + in the least-squares sense + + Parameters + ---------- + A : {sparse array, ndarray, LinearOperator} + Representation of an m-by-n matrix. + Alternatively, ``A`` can be a linear operator which can + produce ``Ax`` and ``A^T x`` using, e.g., + ``scipy.sparse.linalg.LinearOperator``. + b : array_like, shape (m,) + Right-hand side vector ``b``. + damp : float + Damping coefficient. Default is 0. + atol, btol : float, optional + Stopping tolerances. `lsqr` continues iterations until a + certain backward error estimate is smaller than some quantity + depending on atol and btol. Let ``r = b - Ax`` be the + residual vector for the current approximate solution ``x``. + If ``Ax = b`` seems to be consistent, `lsqr` terminates + when ``norm(r) <= atol * norm(A) * norm(x) + btol * norm(b)``. + Otherwise, `lsqr` terminates when ``norm(A^H r) <= + atol * norm(A) * norm(r)``. If both tolerances are 1.0e-6 (default), + the final ``norm(r)`` should be accurate to about 6 + digits. (The final ``x`` will usually have fewer correct digits, + depending on ``cond(A)`` and the size of LAMBDA.) If `atol` + or `btol` is None, a default value of 1.0e-6 will be used. + Ideally, they should be estimates of the relative error in the + entries of ``A`` and ``b`` respectively. For example, if the entries + of ``A`` have 7 correct digits, set ``atol = 1e-7``. This prevents + the algorithm from doing unnecessary work beyond the + uncertainty of the input data. + conlim : float, optional + Another stopping tolerance. lsqr terminates if an estimate of + ``cond(A)`` exceeds `conlim`. For compatible systems ``Ax = + b``, `conlim` could be as large as 1.0e+12 (say). For + least-squares problems, conlim should be less than 1.0e+8. + Maximum precision can be obtained by setting ``atol = btol = + conlim = zero``, but the number of iterations may then be + excessive. Default is 1e8. + iter_lim : int, optional + Explicit limitation on number of iterations (for safety). + show : bool, optional + Display an iteration log. Default is False. + calc_var : bool, optional + Whether to estimate diagonals of ``(A'A + damp^2*I)^{-1}``. + x0 : array_like, shape (n,), optional + Initial guess of x, if None zeros are used. Default is None. + + .. versionadded:: 1.0.0 + + Returns + ------- + x : ndarray of float + The final solution. + istop : int + Gives the reason for termination. + 1 means x is an approximate solution to Ax = b. + 2 means x approximately solves the least-squares problem. + itn : int + Iteration number upon termination. + r1norm : float + ``norm(r)``, where ``r = b - Ax``. + r2norm : float + ``sqrt( norm(r)^2 + damp^2 * norm(x - x0)^2 )``. Equal to `r1norm` + if ``damp == 0``. + anorm : float + Estimate of Frobenius norm of ``Abar = [[A]; [damp*I]]``. + acond : float + Estimate of ``cond(Abar)``. + arnorm : float + Estimate of ``norm(A'@r - damp^2*(x - x0))``. + xnorm : float + ``norm(x)`` + var : ndarray of float + If ``calc_var`` is True, estimates all diagonals of + ``(A'A)^{-1}`` (if ``damp == 0``) or more generally ``(A'A + + damp^2*I)^{-1}``. This is well defined if A has full column + rank or ``damp > 0``. (Not sure what var means if ``rank(A) + < n`` and ``damp = 0.``) + + Notes + ----- + LSQR uses an iterative method to approximate the solution. The + number of iterations required to reach a certain accuracy depends + strongly on the scaling of the problem. Poor scaling of the rows + or columns of A should therefore be avoided where possible. + + For example, in problem 1 the solution is unaltered by + row-scaling. If a row of A is very small or large compared to + the other rows of A, the corresponding row of ( A b ) should be + scaled up or down. + + In problems 1 and 2, the solution x is easily recovered + following column-scaling. Unless better information is known, + the nonzero columns of A should be scaled so that they all have + the same Euclidean norm (e.g., 1.0). + + In problem 3, there is no freedom to re-scale if damp is + nonzero. However, the value of damp should be assigned only + after attention has been paid to the scaling of A. + + The parameter damp is intended to help regularize + ill-conditioned systems, by preventing the true solution from + being very large. Another aid to regularization is provided by + the parameter acond, which may be used to terminate iterations + before the computed solution becomes very large. + + If some initial estimate ``x0`` is known and if ``damp == 0``, + one could proceed as follows: + + 1. Compute a residual vector ``r0 = b - A@x0``. + 2. Use LSQR to solve the system ``A@dx = r0``. + 3. Add the correction dx to obtain a final solution ``x = x0 + dx``. + + This requires that ``x0`` be available before and after the call + to LSQR. To judge the benefits, suppose LSQR takes k1 iterations + to solve A@x = b and k2 iterations to solve A@dx = r0. + If x0 is "good", norm(r0) will be smaller than norm(b). + If the same stopping tolerances atol and btol are used for each + system, k1 and k2 will be similar, but the final solution x0 + dx + should be more accurate. The only way to reduce the total work + is to use a larger stopping tolerance for the second system. + If some value btol is suitable for A@x = b, the larger value + btol*norm(b)/norm(r0) should be suitable for A@dx = r0. + + Preconditioning is another way to reduce the number of iterations. + If it is possible to solve a related system ``M@x = b`` + efficiently, where M approximates A in some helpful way (e.g. M - + A has low rank or its elements are small relative to those of A), + LSQR may converge more rapidly on the system ``A@M(inverse)@z = + b``, after which x can be recovered by solving M@x = z. + + If A is symmetric, LSQR should not be used! + + Alternatives are the symmetric conjugate-gradient method (cg) + and/or SYMMLQ. SYMMLQ is an implementation of symmetric cg that + applies to any symmetric A and will converge more rapidly than + LSQR. If A is positive definite, there are other implementations + of symmetric cg that require slightly less work per iteration than + SYMMLQ (but will take the same number of iterations). + + References + ---------- + .. [1] C. C. Paige and M. A. Saunders (1982a). + "LSQR: An algorithm for sparse linear equations and + sparse least squares", ACM TOMS 8(1), 43-71. + .. [2] C. C. Paige and M. A. Saunders (1982b). + "Algorithm 583. LSQR: Sparse linear equations and least + squares problems", ACM TOMS 8(2), 195-209. + .. [3] M. A. Saunders (1995). "Solution of sparse rectangular + systems using LSQR and CRAIG", BIT 35, 588-604. + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import lsqr + >>> A = csc_array([[1., 0.], [1., 1.], [0., 1.]], dtype=float) + + The first example has the trivial solution ``[0, 0]`` + + >>> b = np.array([0., 0., 0.], dtype=float) + >>> x, istop, itn, normr = lsqr(A, b)[:4] + >>> istop + 0 + >>> x + array([ 0., 0.]) + + The stopping code ``istop=0`` returned indicates that a vector of zeros was + found as a solution. The returned solution `x` indeed contains + ``[0., 0.]``. The next example has a non-trivial solution: + + >>> b = np.array([1., 0., -1.], dtype=float) + >>> x, istop, itn, r1norm = lsqr(A, b)[:4] + >>> istop + 1 + >>> x + array([ 1., -1.]) + >>> itn + 1 + >>> r1norm + 4.440892098500627e-16 + + As indicated by ``istop=1``, `lsqr` found a solution obeying the tolerance + limits. The given solution ``[1., -1.]`` obviously solves the equation. The + remaining return values include information about the number of iterations + (`itn=1`) and the remaining difference of left and right side of the solved + equation. + The final example demonstrates the behavior in the case where there is no + solution for the equation: + + >>> b = np.array([1., 0.01, -1.], dtype=float) + >>> x, istop, itn, r1norm = lsqr(A, b)[:4] + >>> istop + 2 + >>> x + array([ 1.00333333, -0.99666667]) + >>> A.dot(x)-b + array([ 0.00333333, -0.00333333, 0.00333333]) + >>> r1norm + 0.005773502691896255 + + `istop` indicates that the system is inconsistent and thus `x` is rather an + approximate solution to the corresponding least-squares problem. `r1norm` + contains the norm of the minimal residual that was found. + """ + A = convert_pydata_sparse_to_scipy(A) + A = aslinearoperator(A) + b = np.atleast_1d(b) + if b.ndim > 1: + b = b.squeeze() + + m, n = A.shape + if iter_lim is None: + iter_lim = 2 * n + var = np.zeros(n) + + msg = ('The exact solution is x = 0 ', + 'Ax - b is small enough, given atol, btol ', + 'The least-squares solution is good enough, given atol ', + 'The estimate of cond(Abar) has exceeded conlim ', + 'Ax - b is small enough for this machine ', + 'The least-squares solution is good enough for this machine', + 'Cond(Abar) seems to be too large for this machine ', + 'The iteration limit has been reached ') + + if show: + print(' ') + print('LSQR Least-squares solution of Ax = b') + str1 = f'The matrix A has {m} rows and {n} columns' + str2 = f'damp = {damp:20.14e} calc_var = {calc_var:8g}' + str3 = f'atol = {atol:8.2e} conlim = {conlim:8.2e}' + str4 = f'btol = {btol:8.2e} iter_lim = {iter_lim:8g}' + print(str1) + print(str2) + print(str3) + print(str4) + + itn = 0 + istop = 0 + ctol = 0 + if conlim > 0: + ctol = 1/conlim + anorm = 0 + acond = 0 + dampsq = damp**2 + ddnorm = 0 + res2 = 0 + xnorm = 0 + xxnorm = 0 + z = 0 + cs2 = -1 + sn2 = 0 + + # Set up the first vectors u and v for the bidiagonalization. + # These satisfy beta*u = b - A@x, alfa*v = A'@u. + u = b + bnorm = np.linalg.norm(b) + + if x0 is None: + x = np.zeros(n) + beta = bnorm.copy() + else: + x = np.asarray(x0) + u = u - A.matvec(x) + beta = np.linalg.norm(u) + + if beta > 0: + u = (1/beta) * u + v = A.rmatvec(u) + alfa = np.linalg.norm(v) + else: + v = x.copy() + alfa = 0 + + if alfa > 0: + v = (1/alfa) * v + w = v.copy() + + rhobar = alfa + phibar = beta + rnorm = beta + r1norm = rnorm + r2norm = rnorm + + # Reverse the order here from the original matlab code because + # there was an error on return when arnorm==0 + arnorm = alfa * beta + if arnorm == 0: + if show: + print(msg[0]) + return x, istop, itn, r1norm, r2norm, anorm, acond, arnorm, xnorm, var + + head1 = ' Itn x[0] r1norm r2norm ' + head2 = ' Compatible LS Norm A Cond A' + + if show: + print(' ') + print(head1, head2) + test1 = 1 + test2 = alfa / beta + str1 = f'{itn:6g} {x[0]:12.5e}' + str2 = f' {r1norm:10.3e} {r2norm:10.3e}' + str3 = f' {test1:8.1e} {test2:8.1e}' + print(str1, str2, str3) + + # Main iteration loop. + while itn < iter_lim: + itn = itn + 1 + # Perform the next step of the bidiagonalization to obtain the + # next beta, u, alfa, v. These satisfy the relations + # beta*u = a@v - alfa*u, + # alfa*v = A'@u - beta*v. + u = A.matvec(v) - alfa * u + beta = np.linalg.norm(u) + + if beta > 0: + u = (1/beta) * u + anorm = sqrt(anorm**2 + alfa**2 + beta**2 + dampsq) + v = A.rmatvec(u) - beta * v + alfa = np.linalg.norm(v) + if alfa > 0: + v = (1 / alfa) * v + + # Use a plane rotation to eliminate the damping parameter. + # This alters the diagonal (rhobar) of the lower-bidiagonal matrix. + if damp > 0: + rhobar1 = sqrt(rhobar**2 + dampsq) + cs1 = rhobar / rhobar1 + sn1 = damp / rhobar1 + psi = sn1 * phibar + phibar = cs1 * phibar + else: + # cs1 = 1 and sn1 = 0 + rhobar1 = rhobar + psi = 0. + + # Use a plane rotation to eliminate the subdiagonal element (beta) + # of the lower-bidiagonal matrix, giving an upper-bidiagonal matrix. + cs, sn, rho = _sym_ortho(rhobar1, beta) + + theta = sn * alfa + rhobar = -cs * alfa + phi = cs * phibar + phibar = sn * phibar + tau = sn * phi + + # Update x and w. + t1 = phi / rho + t2 = -theta / rho + dk = (1 / rho) * w + + x = x + t1 * w + w = v + t2 * w + ddnorm = ddnorm + np.linalg.norm(dk)**2 + + if calc_var: + var = var + dk**2 + + # Use a plane rotation on the right to eliminate the + # super-diagonal element (theta) of the upper-bidiagonal matrix. + # Then use the result to estimate norm(x). + delta = sn2 * rho + gambar = -cs2 * rho + rhs = phi - delta * z + zbar = rhs / gambar + xnorm = sqrt(xxnorm + zbar**2) + gamma = sqrt(gambar**2 + theta**2) + cs2 = gambar / gamma + sn2 = theta / gamma + z = rhs / gamma + xxnorm = xxnorm + z**2 + + # Test for convergence. + # First, estimate the condition of the matrix Abar, + # and the norms of rbar and Abar'rbar. + acond = anorm * sqrt(ddnorm) + res1 = phibar**2 + res2 = res2 + psi**2 + rnorm = sqrt(res1 + res2) + arnorm = alfa * abs(tau) + + # Distinguish between + # r1norm = ||b - Ax|| and + # r2norm = rnorm in current code + # = sqrt(r1norm^2 + damp^2*||x - x0||^2). + # Estimate r1norm from + # r1norm = sqrt(r2norm^2 - damp^2*||x - x0||^2). + # Although there is cancellation, it might be accurate enough. + if damp > 0: + r1sq = rnorm**2 - dampsq * xxnorm + r1norm = sqrt(abs(r1sq)) + if r1sq < 0: + r1norm = -r1norm + else: + r1norm = rnorm + r2norm = rnorm + + # Now use these norms to estimate certain other quantities, + # some of which will be small near a solution. + test1 = rnorm / bnorm + test2 = arnorm / (anorm * rnorm + eps) + test3 = 1 / (acond + eps) + t1 = test1 / (1 + anorm * xnorm / bnorm) + rtol = btol + atol * anorm * xnorm / bnorm + + # The following tests guard against extremely small values of + # atol, btol or ctol. (The user may have set any or all of + # the parameters atol, btol, conlim to 0.) + # The effect is equivalent to the normal tests using + # atol = eps, btol = eps, conlim = 1/eps. + if itn >= iter_lim: + istop = 7 + if 1 + test3 <= 1: + istop = 6 + if 1 + test2 <= 1: + istop = 5 + if 1 + t1 <= 1: + istop = 4 + + # Allow for tolerances set by the user. + if test3 <= ctol: + istop = 3 + if test2 <= atol: + istop = 2 + if test1 <= rtol: + istop = 1 + + if show: + # See if it is time to print something. + prnt = False + if n <= 40: + prnt = True + if itn <= 10: + prnt = True + if itn >= iter_lim-10: + prnt = True + # if itn%10 == 0: prnt = True + if test3 <= 2*ctol: + prnt = True + if test2 <= 10*atol: + prnt = True + if test1 <= 10*rtol: + prnt = True + if istop != 0: + prnt = True + + if prnt: + str1 = f'{itn:6g} {x[0]:12.5e}' + str2 = f' {r1norm:10.3e} {r2norm:10.3e}' + str3 = f' {test1:8.1e} {test2:8.1e}' + str4 = f' {anorm:8.1e} {acond:8.1e}' + print(str1, str2, str3, str4) + + if istop != 0: + break + + # End of iteration loop. + # Print the stopping condition. + if show: + print(' ') + print('LSQR finished') + print(msg[istop]) + print(' ') + str1 = f'istop ={istop:8g} r1norm ={r1norm:8.1e}' + str2 = f'anorm ={anorm:8.1e} arnorm ={arnorm:8.1e}' + str3 = f'itn ={itn:8g} r2norm ={r2norm:8.1e}' + str4 = f'acond ={acond:8.1e} xnorm ={xnorm:8.1e}' + print(str1 + ' ' + str2) + print(str3 + ' ' + str4) + print(' ') + + return x, istop, itn, r1norm, r2norm, anorm, acond, arnorm, xnorm, var diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/minres.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/minres.py new file mode 100644 index 0000000000000000000000000000000000000000..b5933175e589a258a5f7c48e432981ef6e74a233 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/minres.py @@ -0,0 +1,372 @@ +from numpy import inner, zeros, inf, finfo +from numpy.linalg import norm +from math import sqrt + +from .utils import make_system + +__all__ = ['minres'] + + +def minres(A, b, x0=None, *, rtol=1e-5, shift=0.0, maxiter=None, + M=None, callback=None, show=False, check=False): + """ + Solve ``Ax = b`` with the MINimum RESidual method, for a symmetric `A`. + + MINRES minimizes norm(Ax - b) for a real symmetric matrix A. Unlike + the Conjugate Gradient method, A can be indefinite or singular. + + If shift != 0 then the method solves (A - shift*I)x = b + + Parameters + ---------- + A : {sparse array, ndarray, LinearOperator} + The real symmetric N-by-N matrix of the linear system + Alternatively, ``A`` can be a linear operator which can + produce ``Ax`` using, e.g., + ``scipy.sparse.linalg.LinearOperator``. + b : ndarray + Right hand side of the linear system. Has shape (N,) or (N,1). + + Returns + ------- + x : ndarray + The converged solution. + info : integer + Provides convergence information: + 0 : successful exit + >0 : convergence to tolerance not achieved, number of iterations + <0 : illegal input or breakdown + + Other Parameters + ---------------- + x0 : ndarray + Starting guess for the solution. + shift : float + Value to apply to the system ``(A - shift * I)x = b``. Default is 0. + rtol : float + Tolerance to achieve. The algorithm terminates when the relative + residual is below ``rtol``. + maxiter : integer + Maximum number of iterations. Iteration will stop after maxiter + steps even if the specified tolerance has not been achieved. + M : {sparse array, ndarray, LinearOperator} + Preconditioner for A. The preconditioner should approximate the + inverse of A. Effective preconditioning dramatically improves the + rate of convergence, which implies that fewer iterations are needed + to reach a given error tolerance. + callback : function + User-supplied function to call after each iteration. It is called + as callback(xk), where xk is the current solution vector. + show : bool + If ``True``, print out a summary and metrics related to the solution + during iterations. Default is ``False``. + check : bool + If ``True``, run additional input validation to check that `A` and + `M` (if specified) are symmetric. Default is ``False``. + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import minres + >>> A = csc_array([[3, 2, 0], [1, -1, 0], [0, 5, 1]], dtype=float) + >>> A = A + A.T + >>> b = np.array([2, 4, -1], dtype=float) + >>> x, exitCode = minres(A, b) + >>> print(exitCode) # 0 indicates successful convergence + 0 + >>> np.allclose(A.dot(x), b) + True + + References + ---------- + Solution of sparse indefinite systems of linear equations, + C. C. Paige and M. A. Saunders (1975), + SIAM J. Numer. Anal. 12(4), pp. 617-629. + https://web.stanford.edu/group/SOL/software/minres/ + + This file is a translation of the following MATLAB implementation: + https://web.stanford.edu/group/SOL/software/minres/minres-matlab.zip + + """ + A, M, x, b = make_system(A, M, x0, b) + + matvec = A.matvec + psolve = M.matvec + + first = 'Enter minres. ' + last = 'Exit minres. ' + + n = A.shape[0] + + if maxiter is None: + maxiter = 5 * n + + msg = [' beta2 = 0. If M = I, b and x are eigenvectors ', # -1 + ' beta1 = 0. The exact solution is x0 ', # 0 + ' A solution to Ax = b was found, given rtol ', # 1 + ' A least-squares solution was found, given rtol ', # 2 + ' Reasonable accuracy achieved, given eps ', # 3 + ' x has converged to an eigenvector ', # 4 + ' acond has exceeded 0.1/eps ', # 5 + ' The iteration limit was reached ', # 6 + ' A does not define a symmetric matrix ', # 7 + ' M does not define a symmetric matrix ', # 8 + ' M does not define a pos-def preconditioner '] # 9 + + if show: + print(first + 'Solution of symmetric Ax = b') + print(first + f'n = {n:3g} shift = {shift:23.14e}') + print(first + f'itnlim = {maxiter:3g} rtol = {rtol:11.2e}') + print() + + istop = 0 + itn = 0 + Anorm = 0 + Acond = 0 + rnorm = 0 + ynorm = 0 + + xtype = x.dtype + + eps = finfo(xtype).eps + + # Set up y and v for the first Lanczos vector v1. + # y = beta1 P' v1, where P = C**(-1). + # v is really P' v1. + + if x0 is None: + r1 = b.copy() + else: + r1 = b - A@x + y = psolve(r1) + + beta1 = inner(r1, y) + + if beta1 < 0: + raise ValueError('indefinite preconditioner') + elif beta1 == 0: + return (x, 0) + + bnorm = norm(b) + if bnorm == 0: + x = b + return (x, 0) + + beta1 = sqrt(beta1) + + if check: + # are these too strict? + + # see if A is symmetric + w = matvec(y) + r2 = matvec(w) + s = inner(w,w) + t = inner(y,r2) + z = abs(s - t) + epsa = (s + eps) * eps**(1.0/3.0) + if z > epsa: + raise ValueError('non-symmetric matrix') + + # see if M is symmetric + r2 = psolve(y) + s = inner(y,y) + t = inner(r1,r2) + z = abs(s - t) + epsa = (s + eps) * eps**(1.0/3.0) + if z > epsa: + raise ValueError('non-symmetric preconditioner') + + # Initialize other quantities + oldb = 0 + beta = beta1 + dbar = 0 + epsln = 0 + qrnorm = beta1 + phibar = beta1 + rhs1 = beta1 + rhs2 = 0 + tnorm2 = 0 + gmax = 0 + gmin = finfo(xtype).max + cs = -1 + sn = 0 + w = zeros(n, dtype=xtype) + w2 = zeros(n, dtype=xtype) + r2 = r1 + + if show: + print() + print() + print(' Itn x(1) Compatible LS norm(A) cond(A) gbar/|A|') + + while itn < maxiter: + itn += 1 + + s = 1.0/beta + v = s*y + + y = matvec(v) + y = y - shift * v + + if itn >= 2: + y = y - (beta/oldb)*r1 + + alfa = inner(v,y) + y = y - (alfa/beta)*r2 + r1 = r2 + r2 = y + y = psolve(r2) + oldb = beta + beta = inner(r2,y) + if beta < 0: + raise ValueError('non-symmetric matrix') + beta = sqrt(beta) + tnorm2 += alfa**2 + oldb**2 + beta**2 + + if itn == 1: + if beta/beta1 <= 10*eps: + istop = -1 # Terminate later + + # Apply previous rotation Qk-1 to get + # [deltak epslnk+1] = [cs sn][dbark 0 ] + # [gbar k dbar k+1] [sn -cs][alfak betak+1]. + + oldeps = epsln + delta = cs * dbar + sn * alfa # delta1 = 0 deltak + gbar = sn * dbar - cs * alfa # gbar 1 = alfa1 gbar k + epsln = sn * beta # epsln2 = 0 epslnk+1 + dbar = - cs * beta # dbar 2 = beta2 dbar k+1 + root = norm([gbar, dbar]) + Arnorm = phibar * root + + # Compute the next plane rotation Qk + + gamma = norm([gbar, beta]) # gammak + gamma = max(gamma, eps) + cs = gbar / gamma # ck + sn = beta / gamma # sk + phi = cs * phibar # phik + phibar = sn * phibar # phibark+1 + + # Update x. + + denom = 1.0/gamma + w1 = w2 + w2 = w + w = (v - oldeps*w1 - delta*w2) * denom + x = x + phi*w + + # Go round again. + + gmax = max(gmax, gamma) + gmin = min(gmin, gamma) + z = rhs1 / gamma + rhs1 = rhs2 - delta*z + rhs2 = - epsln*z + + # Estimate various norms and test for convergence. + + Anorm = sqrt(tnorm2) + ynorm = norm(x) + epsa = Anorm * eps + epsx = Anorm * ynorm * eps + epsr = Anorm * ynorm * rtol + diag = gbar + + if diag == 0: + diag = epsa + + qrnorm = phibar + rnorm = qrnorm + if ynorm == 0 or Anorm == 0: + test1 = inf + else: + test1 = rnorm / (Anorm*ynorm) # ||r|| / (||A|| ||x||) + if Anorm == 0: + test2 = inf + else: + test2 = root / Anorm # ||Ar|| / (||A|| ||r||) + + # Estimate cond(A). + # In this version we look at the diagonals of R in the + # factorization of the lower Hessenberg matrix, Q @ H = R, + # where H is the tridiagonal matrix from Lanczos with one + # extra row, beta(k+1) e_k^T. + + Acond = gmax/gmin + + # See if any of the stopping criteria are satisfied. + # In rare cases, istop is already -1 from above (Abar = const*I). + + if istop == 0: + t1 = 1 + test1 # These tests work if rtol < eps + t2 = 1 + test2 + if t2 <= 1: + istop = 2 + if t1 <= 1: + istop = 1 + + if itn >= maxiter: + istop = 6 + if Acond >= 0.1/eps: + istop = 4 + if epsx >= beta1: + istop = 3 + # if rnorm <= epsx : istop = 2 + # if rnorm <= epsr : istop = 1 + if test2 <= rtol: + istop = 2 + if test1 <= rtol: + istop = 1 + + # See if it is time to print something. + + prnt = False + if n <= 40: + prnt = True + if itn <= 10: + prnt = True + if itn >= maxiter-10: + prnt = True + if itn % 10 == 0: + prnt = True + if qrnorm <= 10*epsx: + prnt = True + if qrnorm <= 10*epsr: + prnt = True + if Acond <= 1e-2/eps: + prnt = True + if istop != 0: + prnt = True + + if show and prnt: + str1 = f'{itn:6g} {x[0]:12.5e} {test1:10.3e}' + str2 = f' {test2:10.3e}' + str3 = f' {Anorm:8.1e} {Acond:8.1e} {gbar/Anorm:8.1e}' + + print(str1 + str2 + str3) + + if itn % 10 == 0: + print() + + if callback is not None: + callback(x) + + if istop != 0: + break # TODO check this + + if show: + print() + print(last + f' istop = {istop:3g} itn ={itn:5g}') + print(last + f' Anorm = {Anorm:12.4e} Acond = {Acond:12.4e}') + print(last + f' rnorm = {rnorm:12.4e} ynorm = {ynorm:12.4e}') + print(last + f' Arnorm = {Arnorm:12.4e}') + print(last + msg[istop+1]) + + if istop == 6: + info = maxiter + else: + info = 0 + + return (x,info) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..986a777f9d0fdca33367d1940cda3c06ae42ced7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_gcrotmk.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_gcrotmk.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e5ad06e45c332442db895cdc308053467f638ebc Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_gcrotmk.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_iterative.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_iterative.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6cd166b6e4b7a6eebac27b60facfbe545066eea6 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_iterative.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_lgmres.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_lgmres.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..87a5f28e5f9e4a2f3730483bf895677a8bf89eeb Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_lgmres.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_lsmr.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_lsmr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..33314210838360ebdd7efe05b833555e7e715e21 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_lsmr.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_lsqr.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_lsqr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..350508fe641a236ebe0485224c0efc7c7f1820e8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_lsqr.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_minres.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_minres.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9656c1f538ab5c843542c10337a8a0c41321383 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_minres.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_utils.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1ede79b211d37f76168e95da503323a6328d0f46 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/__pycache__/test_utils.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_gcrotmk.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_gcrotmk.py new file mode 100644 index 0000000000000000000000000000000000000000..25fb61d1c06adc06d93b115d6cbcdb6a986d4459 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_gcrotmk.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python +"""Tests for the linalg._isolve.gcrotmk module +""" +import threading +import warnings + +from numpy.testing import (assert_, assert_allclose, assert_equal) + +import numpy as np +from numpy import zeros, array, allclose +from scipy.linalg import norm +from scipy.sparse import csr_array, eye_array, random_array + +from scipy.sparse.linalg._interface import LinearOperator +from scipy.sparse.linalg import splu +from scipy.sparse.linalg._isolve import gcrotmk, gmres + + +Am = csr_array(array([[-2,1,0,0,0,9], + [1,-2,1,0,5,0], + [0,1,-2,1,0,0], + [0,0,1,-2,1,0], + [0,3,0,1,-2,1], + [1,0,0,0,1,-2]])) +b = array([1,2,3,4,5,6]) +count = threading.local() # [0] +niter = threading.local() # [0] + + +def matvec(v): + if not hasattr(count, 'c'): + count.c = [0] + count.c[0] += 1 + return Am@v + + +def cb(v): + if not hasattr(niter, 'n'): + niter.n = [0] + niter.n[0] += 1 + + +A = LinearOperator(matvec=matvec, shape=Am.shape, dtype=Am.dtype) + + +def do_solve(**kw): + if not hasattr(niter, 'n'): + niter.n = [0] + + if not hasattr(count, 'c'): + count.c = [0] + + count.c[0] = 0 + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", ".*called without specifying.*", DeprecationWarning) + x0, flag = gcrotmk(A, b, x0=zeros(A.shape[0]), rtol=1e-14, **kw) + count_0 = count.c[0] + assert_(allclose(A@x0, b, rtol=1e-12, atol=1e-12), norm(A@x0-b)) + return x0, count_0 + + +class TestGCROTMK: + def test_preconditioner(self): + # Check that preconditioning works + pc = splu(Am.tocsc()) + M = LinearOperator(matvec=pc.solve, shape=A.shape, dtype=A.dtype) + + x0, count_0 = do_solve() + niter.n[0] = 0 + x1, count_1 = do_solve(M=M, callback=cb) + + assert_equal(count_1, 3) + assert count_1 < count_0/2 + assert allclose(x1, x0, rtol=1e-14) + assert niter.n[0] < 3 + + def test_arnoldi(self): + rng = np.random.default_rng(1) + + A = eye_array(2000) + random_array((2000, 2000), density=5e-4, rng=rng) + b = rng.random(2000) + + # The inner arnoldi should be equivalent to gmres + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", ".*called without specifying.*", DeprecationWarning) + x0, flag0 = gcrotmk(A, b, x0=zeros(A.shape[0]), m=10, k=0, maxiter=1) + x1, flag1 = gmres(A, b, x0=zeros(A.shape[0]), restart=10, maxiter=1) + + assert_equal(flag0, 1) + assert_equal(flag1, 1) + assert np.linalg.norm(A.dot(x0) - b) > 1e-4 + + assert_allclose(x0, x1) + + def test_cornercase(self): + np.random.seed(1234) + + # Rounding error may prevent convergence with tol=0 --- ensure + # that the return values in this case are correct, and no + # exceptions are raised + + for n in [3, 5, 10, 100]: + A = 2*eye_array(n) + + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", ".*called without specifying.*", DeprecationWarning) + b = np.ones(n) + x, info = gcrotmk(A, b, maxiter=10) + assert_equal(info, 0) + assert_allclose(A.dot(x) - b, 0, atol=1e-14) + + x, info = gcrotmk(A, b, rtol=0, maxiter=10) + if info == 0: + assert_allclose(A.dot(x) - b, 0, atol=1e-14) + + b = np.random.rand(n) + x, info = gcrotmk(A, b, maxiter=10) + assert_equal(info, 0) + assert_allclose(A.dot(x) - b, 0, atol=1e-14) + + x, info = gcrotmk(A, b, rtol=0, maxiter=10) + if info == 0: + assert_allclose(A.dot(x) - b, 0, atol=1e-14) + + def test_nans(self): + A = eye_array(3, format='lil') + A[1,1] = np.nan + b = np.ones(3) + + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", ".*called without specifying.*", DeprecationWarning) + x, info = gcrotmk(A, b, rtol=0, maxiter=10) + assert_equal(info, 1) + + def test_truncate(self): + np.random.seed(1234) + A = np.random.rand(30, 30) + np.eye(30) + b = np.random.rand(30) + + for truncate in ['oldest', 'smallest']: + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", ".*called without specifying.*", DeprecationWarning) + x, info = gcrotmk(A, b, m=10, k=10, truncate=truncate, + rtol=1e-4, maxiter=200) + assert_equal(info, 0) + assert_allclose(A.dot(x) - b, 0, atol=1e-3) + + def test_CU(self): + for discard_C in (True, False): + # Check that C,U behave as expected + CU = [] + x0, count_0 = do_solve(CU=CU, discard_C=discard_C) + assert_(len(CU) > 0) + assert_(len(CU) <= 6) + + if discard_C: + for c, u in CU: + assert_(c is None) + + # should converge immediately + x1, count_1 = do_solve(CU=CU, discard_C=discard_C) + if discard_C: + assert_equal(count_1, 2 + len(CU)) + else: + assert_equal(count_1, 3) + assert_(count_1 <= count_0/2) + assert_allclose(x1, x0, atol=1e-14) + + def test_denormals(self): + # Check that no warnings are emitted if the matrix contains + # numbers for which 1/x has no float representation, and that + # the solver behaves properly. + A = np.array([[1, 2], [3, 4]], dtype=float) + A *= 100 * np.nextafter(0, 1) + + b = np.array([1, 1]) + + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", ".*called without specifying.*", DeprecationWarning) + xp, info = gcrotmk(A, b) + + if info == 0: + assert_allclose(A.dot(xp), b) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_iterative.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_iterative.py new file mode 100644 index 0000000000000000000000000000000000000000..cd15445a8443207c9fa649f54d0d84f49d8bc4db --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_iterative.py @@ -0,0 +1,811 @@ +""" Test functions for the sparse.linalg._isolve module +""" + +from contextlib import nullcontext +import itertools +import platform +import pytest + +import numpy as np +from numpy.testing import assert_array_equal, assert_allclose +from numpy import zeros, arange, array, ones, eye, iscomplexobj +from numpy.linalg import norm + +from scipy.sparse import dia_array, csr_array, kronsum + +from scipy.sparse.linalg import LinearOperator, aslinearoperator +from scipy.sparse.linalg._isolve import (bicg, bicgstab, cg, cgs, + gcrotmk, gmres, lgmres, + minres, qmr, tfqmr) + +# TODO check that method preserve shape and type +# TODO test both preconditioner methods + + +# list of all solvers under test +_SOLVERS = [bicg, bicgstab, cg, cgs, gcrotmk, gmres, lgmres, + minres, qmr, tfqmr] + +CB_TYPE_FILTER = ".*called without specifying `callback_type`.*" + + +# create parametrized fixture for easy reuse in tests +@pytest.fixture(params=_SOLVERS, scope="session") +def solver(request): + """ + Fixture for all solvers in scipy.sparse.linalg._isolve + """ + return request.param + + +class Case: + def __init__(self, name, A, b=None, skip=None, nonconvergence=None): + self.name = name + self.A = A + if b is None: + self.b = arange(A.shape[0], dtype=float) + else: + self.b = b + if skip is None: + self.skip = [] + else: + self.skip = skip + if nonconvergence is None: + self.nonconvergence = [] + else: + self.nonconvergence = nonconvergence + + +class SingleTest: + def __init__(self, A, b, solver, casename, convergence=True): + self.A = A + self.b = b + self.solver = solver + self.name = casename + '-' + solver.__name__ + self.convergence = convergence + + def __repr__(self): + return f"<{self.name}>" + + +class IterativeParams: + def __init__(self): + sym_solvers = [minres, cg] + posdef_solvers = [cg] + real_solvers = [minres] + + # list of Cases + self.cases = [] + + # Symmetric and Positive Definite + N = 40 + data = ones((3, N)) + data[0, :] = 2 + data[1, :] = -1 + data[2, :] = -1 + Poisson1D = dia_array((data, [0, -1, 1]), shape=(N, N)).tocsr() + self.cases.append(Case("poisson1d", Poisson1D)) + # note: minres fails for single precision + self.cases.append(Case("poisson1d-F", Poisson1D.astype('f'), + skip=[minres])) + + # Symmetric and Negative Definite + self.cases.append(Case("neg-poisson1d", -Poisson1D, + skip=posdef_solvers)) + # note: minres fails for single precision + self.cases.append(Case("neg-poisson1d-F", (-Poisson1D).astype('f'), + skip=posdef_solvers + [minres])) + + # 2-dimensional Poisson equations + Poisson2D = kronsum(Poisson1D, Poisson1D) + # note: minres fails for 2-d poisson problem, + # it will be fixed in the future PR + self.cases.append(Case("poisson2d", Poisson2D, skip=[minres])) + # note: minres fails for single precision + self.cases.append(Case("poisson2d-F", Poisson2D.astype('f'), + skip=[minres])) + + # Symmetric and Indefinite + data = array([[6, -5, 2, 7, -1, 10, 4, -3, -8, 9]], dtype='d') + RandDiag = dia_array((data, [0]), shape=(10, 10)).tocsr() + self.cases.append(Case("rand-diag", RandDiag, skip=posdef_solvers)) + self.cases.append(Case("rand-diag-F", RandDiag.astype('f'), + skip=posdef_solvers)) + + # Random real-valued + rng = np.random.RandomState(1234) + data = rng.rand(4, 4) + self.cases.append(Case("rand", data, + skip=posdef_solvers + sym_solvers)) + self.cases.append(Case("rand-F", data.astype('f'), + skip=posdef_solvers + sym_solvers)) + + # Random symmetric real-valued + rng = np.random.RandomState(1234) + data = rng.rand(4, 4) + data = data + data.T + self.cases.append(Case("rand-sym", data, skip=posdef_solvers)) + self.cases.append(Case("rand-sym-F", data.astype('f'), + skip=posdef_solvers)) + + # Random pos-def symmetric real + np.random.seed(1234) + data = np.random.rand(9, 9) + data = np.dot(data.conj(), data.T) + self.cases.append(Case("rand-sym-pd", data)) + # note: minres fails for single precision + self.cases.append(Case("rand-sym-pd-F", data.astype('f'), + skip=[minres])) + + # Random complex-valued + rng = np.random.RandomState(1234) + data = rng.rand(4, 4) + 1j * rng.rand(4, 4) + skip_cmplx = posdef_solvers + sym_solvers + real_solvers + self.cases.append(Case("rand-cmplx", data, skip=skip_cmplx)) + self.cases.append(Case("rand-cmplx-F", data.astype('F'), + skip=skip_cmplx)) + + # Random hermitian complex-valued + rng = np.random.RandomState(1234) + data = rng.rand(4, 4) + 1j * rng.rand(4, 4) + data = data + data.T.conj() + self.cases.append(Case("rand-cmplx-herm", data, + skip=posdef_solvers + real_solvers)) + self.cases.append(Case("rand-cmplx-herm-F", data.astype('F'), + skip=posdef_solvers + real_solvers)) + + # Random pos-def hermitian complex-valued + rng = np.random.RandomState(1234) + data = rng.rand(9, 9) + 1j * rng.rand(9, 9) + data = np.dot(data.conj(), data.T) + self.cases.append(Case("rand-cmplx-sym-pd", data, skip=real_solvers)) + self.cases.append(Case("rand-cmplx-sym-pd-F", data.astype('F'), + skip=real_solvers)) + + # Non-symmetric and Positive Definite + # + # cgs, qmr, bicg and tfqmr fail to converge on this one + # -- algorithmic limitation apparently + data = ones((2, 10)) + data[0, :] = 2 + data[1, :] = -1 + A = dia_array((data, [0, -1]), shape=(10, 10)).tocsr() + self.cases.append(Case("nonsymposdef", A, + skip=sym_solvers + [cgs, qmr, bicg, tfqmr])) + self.cases.append(Case("nonsymposdef-F", A.astype('F'), + skip=sym_solvers + [cgs, qmr, bicg, tfqmr])) + + # Symmetric, non-pd, hitting cgs/bicg/bicgstab/qmr/tfqmr breakdown + A = np.array([[0, 0, 0, 0, 0, 1, -1, -0, -0, -0, -0], + [0, 0, 0, 0, 0, 2, -0, -1, -0, -0, -0], + [0, 0, 0, 0, 0, 2, -0, -0, -1, -0, -0], + [0, 0, 0, 0, 0, 2, -0, -0, -0, -1, -0], + [0, 0, 0, 0, 0, 1, -0, -0, -0, -0, -1], + [1, 2, 2, 2, 1, 0, -0, -0, -0, -0, -0], + [-1, 0, 0, 0, 0, 0, -1, -0, -0, -0, -0], + [0, -1, 0, 0, 0, 0, -0, -1, -0, -0, -0], + [0, 0, -1, 0, 0, 0, -0, -0, -1, -0, -0], + [0, 0, 0, -1, 0, 0, -0, -0, -0, -1, -0], + [0, 0, 0, 0, -1, 0, -0, -0, -0, -0, -1]], dtype=float) + b = np.array([0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], dtype=float) + assert (A == A.T).all() + self.cases.append(Case("sym-nonpd", A, b, + skip=posdef_solvers, + nonconvergence=[cgs, bicg, bicgstab, qmr, tfqmr] + ) + ) + + def generate_tests(self): + # generate test cases with skips applied + tests = [] + for case in self.cases: + for solver in _SOLVERS: + if (solver in case.skip): + continue + if solver in case.nonconvergence: + tests += [SingleTest(case.A, case.b, solver, case.name, + convergence=False)] + else: + tests += [SingleTest(case.A, case.b, solver, case.name)] + return tests + + +cases = IterativeParams().generate_tests() + + +@pytest.fixture(params=cases, ids=[x.name for x in cases], scope="module") +def case(request): + """ + Fixture for all cases in IterativeParams + """ + return request.param + +def test_maxiter(case): + if not case.convergence: + pytest.skip("Solver - Breakdown case, see gh-8829") + A = case.A + rtol = 1e-12 + + b = case.b + x0 = 0 * b + + residuals = [] + + def callback(x): + if x.ndim == 0: + residuals.append(norm(b - case.A * x)) + else: + residuals.append(norm(b - case.A @ x)) + + if case.solver == gmres: + with pytest.warns(DeprecationWarning, match=CB_TYPE_FILTER): + x, info = case.solver(A, b, x0=x0, rtol=rtol, maxiter=1, callback=callback) + else: + x, info = case.solver(A, b, x0=x0, rtol=rtol, maxiter=1, callback=callback) + + assert len(residuals) == 1 + assert info == 1 + + +def test_convergence(case): + A = case.A + + if A.dtype.char in "dD": + rtol = 1e-8 + else: + rtol = 1e-2 + + b = case.b + x0 = 0 * b + + x, info = case.solver(A, b, x0=x0, rtol=rtol) + + assert_array_equal(x0, 0 * b) # ensure that x0 is not overwritten + if case.convergence: + assert info == 0 + assert norm(A @ x - b) <= norm(b) * rtol + else: + assert info != 0 + assert norm(A @ x - b) <= norm(b) + + +def test_precond_dummy(case): + if not case.convergence: + pytest.skip("Solver - Breakdown case, see gh-8829") + + rtol = 1e-8 + + def identity(b, which=None): + """trivial preconditioner""" + return b + + A = case.A + + M, N = A.shape + # Ensure the diagonal elements of A are non-zero before calculating + # 1.0/A.diagonal() + diagOfA = A.diagonal() + if np.count_nonzero(diagOfA) == len(diagOfA): + dia_array(([1.0 / diagOfA], [0]), shape=(M, N)) + + b = case.b + x0 = 0 * b + + precond = LinearOperator(A.shape, identity, rmatvec=identity) + + if case.solver is qmr: + x, info = case.solver(A, b, M1=precond, M2=precond, x0=x0, rtol=rtol) + else: + x, info = case.solver(A, b, M=precond, x0=x0, rtol=rtol) + assert info == 0 + assert norm(A @ x - b) <= norm(b) * rtol + + A = aslinearoperator(A) + A.psolve = identity + A.rpsolve = identity + + x, info = case.solver(A, b, x0=x0, rtol=rtol) + assert info == 0 + assert norm(A @ x - b) <= norm(b) * rtol + + +# Specific test for poisson1d and poisson2d cases +@pytest.mark.fail_slow(10) +@pytest.mark.parametrize('case', [x for x in IterativeParams().cases + if x.name in ('poisson1d', 'poisson2d')], + ids=['poisson1d', 'poisson2d']) +def test_precond_inverse(case): + for solver in _SOLVERS: + if solver in case.skip or solver is qmr: + continue + + rtol = 1e-8 + + def inverse(b, which=None): + """inverse preconditioner""" + A = case.A + if not isinstance(A, np.ndarray): + A = A.toarray() + return np.linalg.solve(A, b) + + def rinverse(b, which=None): + """inverse preconditioner""" + A = case.A + if not isinstance(A, np.ndarray): + A = A.toarray() + return np.linalg.solve(A.T, b) + + matvec_count = [0] + + def matvec(b): + matvec_count[0] += 1 + return case.A @ b + + def rmatvec(b): + matvec_count[0] += 1 + return case.A.T @ b + + b = case.b + x0 = 0 * b + + A = LinearOperator(case.A.shape, matvec, rmatvec=rmatvec) + precond = LinearOperator(case.A.shape, inverse, rmatvec=rinverse) + + # Solve with preconditioner + matvec_count = [0] + x, info = solver(A, b, M=precond, x0=x0, rtol=rtol) + + assert info == 0 + assert norm(case.A @ x - b) <= norm(b) * rtol + + # Solution should be nearly instant + assert matvec_count[0] <= 3 + + +def test_atol(solver): + # TODO: minres / tfqmr. It didn't historically use absolute tolerances, so + # fixing it is less urgent. + if solver in (minres, tfqmr): + pytest.skip("TODO: Add atol to minres/tfqmr") + + # Historically this is tested as below, all pass but for some reason + # gcrotmk is over-sensitive to difference between random.seed/rng.random + # Hence tol lower bound is changed from -10 to -9 + # np.random.seed(1234) + # A = np.random.rand(10, 10) + # A = A @ A.T + 10 * np.eye(10) + # b = 1e3*np.random.rand(10) + + rng = np.random.default_rng(168441431005389) + A = rng.uniform(size=[10, 10]) + A = A @ A.T + 10*np.eye(10) + b = 1e3 * rng.uniform(size=10) + + b_norm = np.linalg.norm(b) + + tols = np.r_[0, np.logspace(-9, 2, 7), np.inf] + + # Check effect of badly scaled preconditioners + M0 = rng.standard_normal(size=(10, 10)) + M0 = M0 @ M0.T + Ms = [None, 1e-6 * M0, 1e6 * M0] + + for M, rtol, atol in itertools.product(Ms, tols, tols): + if rtol == 0 and atol == 0: + continue + + if solver is qmr: + if M is not None: + M = aslinearoperator(M) + M2 = aslinearoperator(np.eye(10)) + else: + M2 = None + x, info = solver(A, b, M1=M, M2=M2, rtol=rtol, atol=atol) + else: + x, info = solver(A, b, M=M, rtol=rtol, atol=atol) + + assert info == 0 + residual = A @ x - b + err = np.linalg.norm(residual) + atol2 = rtol * b_norm + # Added 1.00025 fudge factor because of `err` exceeding `atol` just + # very slightly on s390x (see gh-17839) + assert err <= 1.00025 * max(atol, atol2) + + +def test_zero_rhs(solver): + rng = np.random.default_rng(1684414984100503) + A = rng.random(size=[10, 10]) + A = A @ A.T + 10 * np.eye(10) + + b = np.zeros(10) + tols = np.r_[np.logspace(-10, 2, 7)] + + for tol in tols: + x, info = solver(A, b, rtol=tol) + assert info == 0 + assert_allclose(x, 0., atol=1e-15) + + x, info = solver(A, b, rtol=tol, x0=ones(10)) + assert info == 0 + assert_allclose(x, 0., atol=tol) + + if solver is not minres: + x, info = solver(A, b, rtol=tol, atol=0, x0=ones(10)) + if info == 0: + assert_allclose(x, 0) + + x, info = solver(A, b, rtol=tol, atol=tol) + assert info == 0 + assert_allclose(x, 0, atol=1e-300) + + x, info = solver(A, b, rtol=tol, atol=0) + assert info == 0 + assert_allclose(x, 0, atol=1e-300) + + +@pytest.mark.xfail(reason="see gh-18697") +def test_maxiter_worsening(solver): + if solver not in (gmres, lgmres, qmr): + # these were skipped from the very beginning, see gh-9201; gh-14160 + pytest.skip("Solver breakdown case") + # Check error does not grow (boundlessly) with increasing maxiter. + # This can occur due to the solvers hitting close to breakdown, + # which they should detect and halt as necessary. + # cf. gh-9100 + if (solver is lgmres and + platform.machine() not in ['x86_64' 'x86', 'aarch64', 'arm64']): + # see gh-17839 + pytest.xfail(reason="fails on at least ppc64le, ppc64 and riscv64") + + # Singular matrix, rhs numerically not in range + A = np.array([[-0.1112795288033378, 0, 0, 0.16127952880333685], + [0, -0.13627952880333782 + 6.283185307179586j, 0, 0], + [0, 0, -0.13627952880333782 - 6.283185307179586j, 0], + [0.1112795288033368, 0j, 0j, -0.16127952880333785]]) + v = np.ones(4) + best_error = np.inf + + # Unable to match the Fortran code tolerance levels with this example + # Original tolerance values + + # slack_tol = 7 if platform.machine() == 'aarch64' else 5 + slack_tol = 9 + + for maxiter in range(1, 20): + x, info = solver(A, v, maxiter=maxiter, rtol=1e-8, atol=0) + + if info == 0: + assert norm(A @ x - v) <= 1e-8 * norm(v) + + error = np.linalg.norm(A @ x - v) + best_error = min(best_error, error) + + # Check with slack + assert error <= slack_tol * best_error + + +def test_x0_working(solver): + # Easy problem + rng = np.random.default_rng(1685363802304750) + n = 10 + A = rng.random(size=[n, n]) + A = A @ A.T + b = rng.random(n) + x0 = rng.random(n) + + if solver is minres: + kw = dict(rtol=1e-6) + else: + kw = dict(atol=0, rtol=1e-6) + + x, info = solver(A, b, **kw) + assert info == 0 + assert norm(A @ x - b) <= 1e-6 * norm(b) + + x, info = solver(A, b, x0=x0, **kw) + assert info == 0 + assert norm(A @ x - b) <= 1e-5*norm(b) + + +def test_x0_equals_Mb(case): + if (case.solver is bicgstab) and (case.name == 'nonsymposdef-bicgstab'): + pytest.skip("Solver fails due to numerical noise " + "on some architectures (see gh-15533).") + if case.solver is tfqmr: + pytest.skip("Solver does not support x0='Mb'") + + A = case.A + b = case.b + x0 = 'Mb' + rtol = 1e-8 + x, info = case.solver(A, b, x0=x0, rtol=rtol) + + assert_array_equal(x0, 'Mb') # ensure that x0 is not overwritten + assert info == 0 + assert norm(A @ x - b) <= rtol * norm(b) + + +@pytest.mark.parametrize('solver', _SOLVERS) +def test_x0_solves_problem_exactly(solver): + # See gh-19948 + mat = np.eye(2) + rhs = np.array([-1., -1.]) + + sol, info = solver(mat, rhs, x0=rhs) + assert_allclose(sol, rhs) + assert info == 0 + + +# Specific tfqmr test +@pytest.mark.parametrize('case', IterativeParams().cases) +def test_show(case, capsys): + def cb(x): + pass + + ctx = np.errstate(all='ignore') if case.name == "nonsymposdef" else nullcontext() + with ctx: + x, info = tfqmr(case.A, case.b, callback=cb, show=True) + + out, err = capsys.readouterr() + + if case.name == "sym-nonpd": + # no logs for some reason + exp = "" + elif case.name in ("nonsymposdef", "nonsymposdef-F"): + # Asymmetric and Positive Definite + exp = "TFQMR: Linear solve not converged due to reach MAXIT iterations" + else: # all other cases + exp = "TFQMR: Linear solve converged due to reach TOL iterations" + + assert out.startswith(exp) + assert err == "" + + +def test_positional_error(solver): + # from test_x0_working + rng = np.random.default_rng(1685363802304750) + n = 10 + A = rng.random(size=[n, n]) + A = A @ A.T + b = rng.random(n) + x0 = rng.random(n) + with pytest.raises(TypeError): + solver(A, b, x0, 1e-5) + + +@pytest.mark.parametrize("atol", ["legacy", None, -1]) +def test_invalid_atol(solver, atol): + if solver == minres: + pytest.skip("minres has no `atol` argument") + # from test_x0_working + rng = np.random.default_rng(1685363802304750) + n = 10 + A = rng.random(size=[n, n]) + A = A @ A.T + b = rng.random(n) + x0 = rng.random(n) + with pytest.raises(ValueError): + solver(A, b, x0, atol=atol) + + +class TestQMR: + @pytest.mark.filterwarnings('ignore::scipy.sparse.SparseEfficiencyWarning') + def test_leftright_precond(self): + """Check that QMR works with left and right preconditioners""" + + from scipy.sparse.linalg._dsolve import splu + from scipy.sparse.linalg._interface import LinearOperator + + n = 100 + + dat = ones(n) + A = dia_array(([-2 * dat, 4 * dat, -dat], [-1, 0, 1]), shape=(n, n)) + b = arange(n, dtype='d') + + L = dia_array(([-dat / 2, dat], [-1, 0]), shape=(n, n)) + U = dia_array(([4 * dat, -dat], [0, 1]), shape=(n, n)) + L_solver = splu(L) + U_solver = splu(U) + + def L_solve(b): + return L_solver.solve(b) + + def U_solve(b): + return U_solver.solve(b) + + def LT_solve(b): + return L_solver.solve(b, 'T') + + def UT_solve(b): + return U_solver.solve(b, 'T') + + M1 = LinearOperator((n, n), matvec=L_solve, rmatvec=LT_solve) + M2 = LinearOperator((n, n), matvec=U_solve, rmatvec=UT_solve) + + rtol = 1e-8 + x, info = qmr(A, b, rtol=rtol, maxiter=15, M1=M1, M2=M2) + + assert info == 0 + assert norm(A @ x - b) <= rtol * norm(b) + + +class TestGMRES: + def test_basic(self): + A = np.vander(np.arange(10) + 1)[:, ::-1] + b = np.zeros(10) + b[0] = 1 + + x_gm, err = gmres(A, b, restart=5, maxiter=1) + + assert_allclose(x_gm[0], 0.359, rtol=1e-2) + + @pytest.mark.filterwarnings(f"ignore:{CB_TYPE_FILTER}:DeprecationWarning") + def test_callback(self): + + def store_residual(r, rvec): + rvec[rvec.nonzero()[0].max() + 1] = r + + # Define, A,b + A = csr_array(array([[-2, 1, 0, 0, 0, 0], + [1, -2, 1, 0, 0, 0], + [0, 1, -2, 1, 0, 0], + [0, 0, 1, -2, 1, 0], + [0, 0, 0, 1, -2, 1], + [0, 0, 0, 0, 1, -2]])) + b = ones((A.shape[0],)) + maxiter = 1 + rvec = zeros(maxiter + 1) + rvec[0] = 1.0 + + def callback(r): + return store_residual(r, rvec) + + x, flag = gmres(A, b, x0=zeros(A.shape[0]), rtol=1e-16, + maxiter=maxiter, callback=callback) + + # Expected output from SciPy 1.0.0 + assert_allclose(rvec, array([1.0, 0.81649658092772603]), rtol=1e-10) + + # Test preconditioned callback + M = 1e-3 * np.eye(A.shape[0]) + rvec = zeros(maxiter + 1) + rvec[0] = 1.0 + x, flag = gmres(A, b, M=M, rtol=1e-16, maxiter=maxiter, + callback=callback) + + # Expected output from SciPy 1.0.0 + # (callback has preconditioned residual!) + assert_allclose(rvec, array([1.0, 1e-3 * 0.81649658092772603]), + rtol=1e-10) + + def test_abi(self): + # Check we don't segfault on gmres with complex argument + A = eye(2) + b = ones(2) + r_x, r_info = gmres(A, b) + r_x = r_x.astype(complex) + x, info = gmres(A.astype(complex), b.astype(complex)) + + assert iscomplexobj(x) + assert_allclose(r_x, x) + assert r_info == info + + @pytest.mark.fail_slow(10) + def test_atol_legacy(self): + + A = eye(2) + b = ones(2) + x, info = gmres(A, b, rtol=1e-5) + assert np.linalg.norm(A @ x - b) <= 1e-5 * np.linalg.norm(b) + assert_allclose(x, b, atol=0, rtol=1e-8) + + rndm = np.random.RandomState(12345) + A = rndm.rand(30, 30) + b = 1e-6 * ones(30) + x, info = gmres(A, b, rtol=1e-7, restart=20) + assert np.linalg.norm(A @ x - b) > 1e-7 + + A = eye(2) + b = 1e-10 * ones(2) + x, info = gmres(A, b, rtol=1e-8, atol=0) + assert np.linalg.norm(A @ x - b) <= 1e-8 * np.linalg.norm(b) + + def test_defective_precond_breakdown(self): + # Breakdown due to defective preconditioner + M = np.eye(3) + M[2, 2] = 0 + + b = np.array([0, 1, 1]) + x = np.array([1, 0, 0]) + A = np.diag([2, 3, 4]) + + x, info = gmres(A, b, x0=x, M=M, rtol=1e-15, atol=0) + + # Should not return nans, nor terminate with false success + assert not np.isnan(x).any() + if info == 0: + assert np.linalg.norm(A @ x - b) <= 1e-15 * np.linalg.norm(b) + + # The solution should be OK outside null space of M + assert_allclose(M @ (A @ x), M @ b) + + def test_defective_matrix_breakdown(self): + # Breakdown due to defective matrix + A = np.array([[0, 1, 0], [1, 0, 0], [0, 0, 0]]) + b = np.array([1, 0, 1]) + rtol = 1e-8 + x, info = gmres(A, b, rtol=rtol, atol=0) + + # Should not return nans, nor terminate with false success + assert not np.isnan(x).any() + if info == 0: + assert np.linalg.norm(A @ x - b) <= rtol * np.linalg.norm(b) + + # The solution should be OK outside null space of A + assert_allclose(A @ (A @ x), A @ b) + + @pytest.mark.filterwarnings(f"ignore:{CB_TYPE_FILTER}:DeprecationWarning") + def test_callback_type(self): + # The legacy callback type changes meaning of 'maxiter' + np.random.seed(1) + A = np.random.rand(20, 20) + b = np.random.rand(20) + + cb_count = [0] + + def pr_norm_cb(r): + cb_count[0] += 1 + assert isinstance(r, float) + + def x_cb(x): + cb_count[0] += 1 + assert isinstance(x, np.ndarray) + + # 2 iterations is not enough to solve the problem + cb_count = [0] + x, info = gmres(A, b, rtol=1e-6, atol=0, callback=pr_norm_cb, + maxiter=2, restart=50) + assert info == 2 + assert cb_count[0] == 2 + + # With `callback_type` specified, no warning should be raised + cb_count = [0] + x, info = gmres(A, b, rtol=1e-6, atol=0, callback=pr_norm_cb, + maxiter=2, restart=50, callback_type='legacy') + assert info == 2 + assert cb_count[0] == 2 + + # 2 restart cycles is enough to solve the problem + cb_count = [0] + x, info = gmres(A, b, rtol=1e-6, atol=0, callback=pr_norm_cb, + maxiter=2, restart=50, callback_type='pr_norm') + assert info == 0 + assert cb_count[0] > 2 + + # 2 restart cycles is enough to solve the problem + cb_count = [0] + x, info = gmres(A, b, rtol=1e-6, atol=0, callback=x_cb, maxiter=2, + restart=50, callback_type='x') + assert info == 0 + assert cb_count[0] == 1 + + def test_callback_x_monotonic(self): + # Check that callback_type='x' gives monotonic norm decrease + rng = np.random.RandomState(1) + A = rng.rand(20, 20) + np.eye(20) + b = rng.rand(20) + + prev_r = [np.inf] + count = [0] + + def x_cb(x): + r = np.linalg.norm(A @ x - b) + assert r <= prev_r[0] + prev_r[0] = r + count[0] += 1 + + x, info = gmres(A, b, rtol=1e-6, atol=0, callback=x_cb, maxiter=20, + restart=10, callback_type='x') + assert info == 20 + assert count[0] == 20 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_lgmres.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_lgmres.py new file mode 100644 index 0000000000000000000000000000000000000000..7c3abf7411fc8c40ae2851c403ae0598428dec86 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_lgmres.py @@ -0,0 +1,232 @@ +"""Tests for the linalg._isolve.lgmres module +""" +import threading +import warnings + +from numpy.testing import (assert_, assert_allclose, assert_equal) + +import pytest +from platform import python_implementation + +import numpy as np +from numpy import zeros, array, allclose +from scipy.linalg import norm +from scipy.sparse import csr_array, eye_array, random_array + +from scipy.sparse.linalg._interface import LinearOperator +from scipy.sparse.linalg import splu +from scipy.sparse.linalg._isolve import lgmres, gmres + + +Am = csr_array(array([[-2, 1, 0, 0, 0, 9], + [1, -2, 1, 0, 5, 0], + [0, 1, -2, 1, 0, 0], + [0, 0, 1, -2, 1, 0], + [0, 3, 0, 1, -2, 1], + [1, 0, 0, 0, 1, -2]])) +b = array([1, 2, 3, 4, 5, 6]) +count = threading.local() # [0] +niter = threading.local() # [0] + + +def matvec(v): + if not hasattr(count, 'c'): + count.c = [0] + count.c[0] += 1 + return Am@v + + +def cb(v): + if not hasattr(niter, 'n'): + niter.n = [0] + niter.n[0] += 1 + + +A = LinearOperator(matvec=matvec, shape=Am.shape, dtype=Am.dtype) + + +def do_solve(**kw): + if not hasattr(niter, 'n'): + niter.n = [0] + if not hasattr(count, 'c'): + count.c = [0] + count.c[0] = 0 + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", ".*called without specifying.*", DeprecationWarning) + x0, flag = lgmres(A, b, x0=zeros(A.shape[0]), + inner_m=6, rtol=1e-14, **kw) + count_0 = count.c[0] + assert_(allclose(A@x0, b, rtol=1e-12, atol=1e-12), norm(A@x0-b)) + return x0, count_0 + + +class TestLGMRES: + def test_preconditioner(self): + # Check that preconditioning works + pc = splu(Am.tocsc()) + M = LinearOperator(matvec=pc.solve, shape=A.shape, dtype=A.dtype) + + x0, count_0 = do_solve() + niter.n[0] = 0 + x1, count_1 = do_solve(M=M, callback=cb) + + assert count_1 == 3 + assert count_1 < count_0/2 + assert allclose(x1, x0, rtol=1e-14) + assert niter.n[0] < 3 + + def test_outer_v(self): + # Check that the augmentation vectors behave as expected + + outer_v = [] + x0, count_0 = do_solve(outer_k=6, outer_v=outer_v) + assert_(len(outer_v) > 0) + assert_(len(outer_v) <= 6) + + x1, count_1 = do_solve(outer_k=6, outer_v=outer_v, + prepend_outer_v=True) + assert_(count_1 == 2, count_1) + assert_(count_1 < count_0/2) + assert_(allclose(x1, x0, rtol=1e-14)) + + # --- + + outer_v = [] + x0, count_0 = do_solve(outer_k=6, outer_v=outer_v, + store_outer_Av=False) + assert_(array([v[1] is None for v in outer_v]).all()) + assert_(len(outer_v) > 0) + assert_(len(outer_v) <= 6) + + x1, count_1 = do_solve(outer_k=6, outer_v=outer_v, + prepend_outer_v=True) + assert_(count_1 == 3, count_1) + assert_(count_1 < count_0/2) + assert_(allclose(x1, x0, rtol=1e-14)) + + @pytest.mark.skipif(python_implementation() == 'PyPy', + reason="Fails on PyPy CI runs. See #9507") + def test_arnoldi(self): + rng = np.random.default_rng(123) + + A = eye_array(2000) + random_array((2000, 2000), density=5e-4, rng=rng) + b = rng.random(2000) + + # The inner arnoldi should be equivalent to gmres + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", ".*called without specifying.*", DeprecationWarning) + x0, flag0 = lgmres(A, b, x0=zeros(A.shape[0]), inner_m=10, maxiter=1) + x1, flag1 = gmres(A, b, x0=zeros(A.shape[0]), restart=10, maxiter=1) + + assert_equal(flag0, 1) + assert_equal(flag1, 1) + norm = np.linalg.norm(A.dot(x0) - b) + assert_(norm > 1e-4) + assert_allclose(x0, x1) + + def test_cornercase(self): + rng = np.random.RandomState(1234) + + # Rounding error may prevent convergence with tol=0 --- ensure + # that the return values in this case are correct, and no + # exceptions are raised + + for n in [3, 5, 10, 100]: + A = 2*eye_array(n) + + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", ".*called without specifying.*", DeprecationWarning) + + b = np.ones(n) + x, info = lgmres(A, b, maxiter=10) + assert_equal(info, 0) + assert_allclose(A.dot(x) - b, 0, atol=1e-14) + + x, info = lgmres(A, b, rtol=0, maxiter=10) + if info == 0: + assert_allclose(A.dot(x) - b, 0, atol=1e-14) + + b = rng.rand(n) + x, info = lgmres(A, b, maxiter=10) + assert_equal(info, 0) + assert_allclose(A.dot(x) - b, 0, atol=1e-14) + + x, info = lgmres(A, b, rtol=0, maxiter=10) + if info == 0: + assert_allclose(A.dot(x) - b, 0, atol=1e-14) + + def test_nans(self): + A = eye_array(3, format='lil') + A[1, 1] = np.nan + b = np.ones(3) + + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", ".*called without specifying.*", DeprecationWarning) + x, info = lgmres(A, b, rtol=0, maxiter=10) + assert_equal(info, 1) + + def test_breakdown_with_outer_v(self): + A = np.array([[1, 2], [3, 4]], dtype=float) + b = np.array([1, 2]) + + x = np.linalg.solve(A, b) + v0 = np.array([1, 0]) + + # The inner iteration should converge to the correct solution, + # since it's in the outer vector list + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", ".*called without specifying.*", DeprecationWarning) + xp, info = lgmres(A, b, outer_v=[(v0, None), (x, None)], maxiter=1) + + assert_allclose(xp, x, atol=1e-12) + + def test_breakdown_underdetermined(self): + # Should find LSQ solution in the Krylov span in one inner + # iteration, despite solver breakdown from nilpotent A. + A = np.array([[0, 1, 1, 1], + [0, 0, 1, 1], + [0, 0, 0, 1], + [0, 0, 0, 0]], dtype=float) + + bs = [ + np.array([1, 1, 1, 1]), + np.array([1, 1, 1, 0]), + np.array([1, 1, 0, 0]), + np.array([1, 0, 0, 0]), + ] + + for b in bs: + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", ".*called without specifying.*", DeprecationWarning) + xp, info = lgmres(A, b, maxiter=1) + resp = np.linalg.norm(A.dot(xp) - b) + + K = np.c_[b, A.dot(b), A.dot(A.dot(b)), A.dot(A.dot(A.dot(b)))] + y, _, _, _ = np.linalg.lstsq(A.dot(K), b, rcond=-1) + x = K.dot(y) + res = np.linalg.norm(A.dot(x) - b) + + assert_allclose(resp, res, err_msg=repr(b)) + + def test_denormals(self): + # Check that no warnings are emitted if the matrix contains + # numbers for which 1/x has no float representation, and that + # the solver behaves properly. + A = np.array([[1, 2], [3, 4]], dtype=float) + A *= 100 * np.nextafter(0, 1) + + b = np.array([1, 1]) + + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", ".*called without specifying.*", DeprecationWarning) + xp, info = lgmres(A, b) + + if info == 0: + assert_allclose(A.dot(xp), b) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_lsmr.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_lsmr.py new file mode 100644 index 0000000000000000000000000000000000000000..0d1196b23e0b7a24513850116ee134193709619e --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_lsmr.py @@ -0,0 +1,185 @@ +""" +Copyright (C) 2010 David Fong and Michael Saunders +Distributed under the same license as SciPy + +Testing Code for LSMR. + +03 Jun 2010: First version release with lsmr.py + +David Chin-lung Fong clfong@stanford.edu +Institute for Computational and Mathematical Engineering +Stanford University + +Michael Saunders saunders@stanford.edu +Systems Optimization Laboratory +Dept of MS&E, Stanford University. + +""" + +from numpy import array, arange, eye, zeros, ones, transpose, hstack +from numpy.linalg import norm +from numpy.testing import assert_allclose +import pytest +from scipy.sparse import coo_array +from scipy.sparse.linalg._interface import aslinearoperator +from scipy.sparse.linalg import lsmr +from .test_lsqr import G, b + + +class TestLSMR: + def setup_method(self): + self.n = 10 + self.m = 10 + + def assertCompatibleSystem(self, A, xtrue): + Afun = aslinearoperator(A) + b = Afun.matvec(xtrue) + x = lsmr(A, b)[0] + assert norm(x - xtrue) == pytest.approx(0, abs=1e-5) + + def testIdentityACase1(self): + A = eye(self.n) + xtrue = zeros((self.n, 1)) + self.assertCompatibleSystem(A, xtrue) + + def testIdentityACase2(self): + A = eye(self.n) + xtrue = ones((self.n,1)) + self.assertCompatibleSystem(A, xtrue) + + def testIdentityACase3(self): + A = eye(self.n) + xtrue = transpose(arange(self.n,0,-1)) + self.assertCompatibleSystem(A, xtrue) + + def testBidiagonalA(self): + A = lowerBidiagonalMatrix(20,self.n) + xtrue = transpose(arange(self.n,0,-1)) + self.assertCompatibleSystem(A,xtrue) + + def testScalarB(self): + A = array([[1.0, 2.0]]) + b = 3.0 + x = lsmr(A, b)[0] + assert norm(A.dot(x) - b) == pytest.approx(0) + + def testComplexX(self): + A = eye(self.n) + xtrue = transpose(arange(self.n, 0, -1) * (1 + 1j)) + self.assertCompatibleSystem(A, xtrue) + + def testComplexX0(self): + A = 4 * eye(self.n) + ones((self.n, self.n)) + xtrue = transpose(arange(self.n, 0, -1)) + b = aslinearoperator(A).matvec(xtrue) + x0 = zeros(self.n, dtype=complex) + x = lsmr(A, b, x0=x0)[0] + assert norm(x - xtrue) == pytest.approx(0, abs=1e-5) + + def testComplexA(self): + A = 4 * eye(self.n) + 1j * ones((self.n, self.n)) + xtrue = transpose(arange(self.n, 0, -1).astype(complex)) + self.assertCompatibleSystem(A, xtrue) + + def testComplexB(self): + A = 4 * eye(self.n) + ones((self.n, self.n)) + xtrue = transpose(arange(self.n, 0, -1) * (1 + 1j)) + b = aslinearoperator(A).matvec(xtrue) + x = lsmr(A, b)[0] + assert norm(x - xtrue) == pytest.approx(0, abs=1e-5) + + def testColumnB(self): + A = eye(self.n) + b = ones((self.n, 1)) + x = lsmr(A, b)[0] + assert norm(A.dot(x) - b.ravel()) == pytest.approx(0) + + def testInitialization(self): + # Test that the default setting is not modified + x_ref, _, itn_ref, normr_ref, *_ = lsmr(G, b) + assert_allclose(norm(b - G@x_ref), normr_ref, atol=1e-6) + + # Test passing zeros yields similar result + x0 = zeros(b.shape) + x = lsmr(G, b, x0=x0)[0] + assert_allclose(x, x_ref) + + # Test warm-start with single iteration + x0 = lsmr(G, b, maxiter=1)[0] + + x, _, itn, normr, *_ = lsmr(G, b, x0=x0) + assert_allclose(norm(b - G@x), normr, atol=1e-6) + + # NOTE(gh-12139): This doesn't always converge to the same value as + # ref because error estimates will be slightly different when calculated + # from zeros vs x0 as a result only compare norm and itn (not x). + + # x generally converges 1 iteration faster because it started at x0. + # itn == itn_ref means that lsmr(x0) took an extra iteration see above. + # -1 is technically possible but is rare (1 in 100000) so it's more + # likely to be an error elsewhere. + assert itn - itn_ref in (0, 1) + + # If an extra iteration is performed normr may be 0, while normr_ref + # may be much larger. + assert normr < normr_ref * (1 + 1e-6) + + +class TestLSMRReturns: + def setup_method(self): + self.n = 10 + self.A = lowerBidiagonalMatrix(20, self.n) + self.xtrue = transpose(arange(self.n, 0, -1)) + self.Afun = aslinearoperator(self.A) + self.b = self.Afun.matvec(self.xtrue) + self.x0 = ones(self.n) + self.x00 = self.x0.copy() + self.returnValues = lsmr(self.A, self.b) + self.returnValuesX0 = lsmr(self.A, self.b, x0=self.x0) + + def test_unchanged_x0(self): + x, istop, itn, normr, normar, normA, condA, normx = self.returnValuesX0 + assert_allclose(self.x00, self.x0) + + def testNormr(self): + x, istop, itn, normr, normar, normA, condA, normx = self.returnValues + assert norm(self.b - self.Afun.matvec(x)) == pytest.approx(normr) + + def testNormar(self): + x, istop, itn, normr, normar, normA, condA, normx = self.returnValues + assert (norm(self.Afun.rmatvec(self.b - self.Afun.matvec(x))) + == pytest.approx(normar)) + + def testNormx(self): + x, istop, itn, normr, normar, normA, condA, normx = self.returnValues + assert norm(x) == pytest.approx(normx) + + +def lowerBidiagonalMatrix(m, n): + # This is a simple example for testing LSMR. + # It uses the leading m*n submatrix from + # A = [ 1 + # 1 2 + # 2 3 + # 3 4 + # ... + # n ] + # suitably padded by zeros. + # + # 04 Jun 2010: First version for distribution with lsmr.py + if m <= n: + row = hstack((arange(m, dtype=int), + arange(1, m, dtype=int))) + col = hstack((arange(m, dtype=int), + arange(m-1, dtype=int))) + data = hstack((arange(1, m+1, dtype=float), + arange(1,m, dtype=float))) + return coo_array((data, (row, col)), shape=(m,n)) + else: + row = hstack((arange(n, dtype=int), + arange(1, n+1, dtype=int))) + col = hstack((arange(n, dtype=int), + arange(n, dtype=int))) + data = hstack((arange(1, n+1, dtype=float), + arange(1,n+1, dtype=float))) + return coo_array((data,(row, col)), shape=(m,n)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_lsqr.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_lsqr.py new file mode 100644 index 0000000000000000000000000000000000000000..d77048af48a6b4495d23c9bc9a3b2d71466bade6 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_lsqr.py @@ -0,0 +1,120 @@ +import numpy as np +from numpy.testing import assert_allclose, assert_array_equal, assert_equal +import pytest +import scipy.sparse +import scipy.sparse.linalg +from scipy.sparse.linalg import lsqr + +# Set up a test problem +n = 35 +G = np.eye(n) +normal = np.random.normal +norm = np.linalg.norm + +for jj in range(5): + gg = normal(size=n) + hh = gg * gg.T + G += (hh + hh.T) * 0.5 + G += normal(size=n) * normal(size=n) + +b = normal(size=n) + +# tolerance for atol/btol keywords of lsqr() +tol = 2e-10 +# tolerances for testing the results of the lsqr() call with assert_allclose +# These tolerances are a bit fragile - see discussion in gh-15301. +atol_test = 4e-10 +rtol_test = 2e-8 +show = False +maxit = None + + +def test_lsqr_basic(): + b_copy = b.copy() + xo, *_ = lsqr(G, b, show=show, atol=tol, btol=tol, iter_lim=maxit) + assert_array_equal(b_copy, b) + + svx = np.linalg.solve(G, b) + assert_allclose(xo, svx, atol=atol_test, rtol=rtol_test) + + # Now the same but with damp > 0. + # This is equivalent to solving the extended system: + # ( G ) @ x = ( b ) + # ( damp*I ) ( 0 ) + damp = 1.5 + xo, *_ = lsqr( + G, b, damp=damp, show=show, atol=tol, btol=tol, iter_lim=maxit) + + Gext = np.r_[G, damp * np.eye(G.shape[1])] + bext = np.r_[b, np.zeros(G.shape[1])] + svx, *_ = np.linalg.lstsq(Gext, bext, rcond=None) + assert_allclose(xo, svx, atol=atol_test, rtol=rtol_test) + + +def test_gh_2466(): + row = np.array([0, 0]) + col = np.array([0, 1]) + val = np.array([1, -1]) + A = scipy.sparse.coo_array((val, (row, col)), shape=(1, 2)) + b = np.asarray([4]) + lsqr(A, b) + + +def test_well_conditioned_problems(): + # Test that sparse the lsqr solver returns the right solution + # on various problems with different random seeds. + # This is a non-regression test for a potential ZeroDivisionError + # raised when computing the `test2` & `test3` convergence conditions. + n = 10 + A_sparse = scipy.sparse.eye_array(n, n) + A_dense = A_sparse.toarray() + + with np.errstate(invalid='raise'): + for seed in range(30): + rng = np.random.RandomState(seed + 10) + beta = rng.rand(n) + beta[beta == 0] = 0.00001 # ensure that all the betas are not null + b = A_sparse @ beta[:, np.newaxis] + output = lsqr(A_sparse, b, show=show) + + # Check that the termination condition corresponds to an approximate + # solution to Ax = b + assert_equal(output[1], 1) + solution = output[0] + + # Check that we recover the ground truth solution + assert_allclose(solution, beta) + + # Sanity check: compare to the dense array solver + reference_solution = np.linalg.solve(A_dense, b).ravel() + assert_allclose(solution, reference_solution) + + +def test_b_shapes(): + # Test b being a scalar. + A = np.array([[1.0, 2.0]]) + b = 3.0 + x = lsqr(A, b)[0] + assert norm(A.dot(x) - b) == pytest.approx(0) + + # Test b being a column vector. + A = np.eye(10) + b = np.ones((10, 1)) + x = lsqr(A, b)[0] + assert norm(A.dot(x) - b.ravel()) == pytest.approx(0) + + +def test_initialization(): + # Test the default setting is the same as zeros + b_copy = b.copy() + x_ref = lsqr(G, b, show=show, atol=tol, btol=tol, iter_lim=maxit) + x0 = np.zeros(x_ref[0].shape) + x = lsqr(G, b, show=show, atol=tol, btol=tol, iter_lim=maxit, x0=x0) + assert_array_equal(b_copy, b) + assert_allclose(x_ref[0], x[0]) + + # Test warm-start with single iteration + x0 = lsqr(G, b, show=show, atol=tol, btol=tol, iter_lim=1)[0] + x = lsqr(G, b, show=show, atol=tol, btol=tol, iter_lim=maxit, x0=x0) + assert_allclose(x_ref[0], x[0]) + assert_array_equal(b_copy, b) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_minres.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_minres.py new file mode 100644 index 0000000000000000000000000000000000000000..cae169e14f0306b195bca73ce86547391851aab6 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_minres.py @@ -0,0 +1,97 @@ +import numpy as np +from numpy.linalg import norm +from numpy.testing import assert_equal, assert_allclose, assert_ +from scipy.sparse.linalg._isolve import minres + +from pytest import raises as assert_raises + + +def get_sample_problem(): + # A random 10 x 10 symmetric matrix + rng = np.random.RandomState(1234) + matrix = rng.rand(10, 10) + matrix = matrix + matrix.T + # A random vector of length 10 + vector = rng.rand(10) + return matrix, vector + + +def test_singular(): + A, b = get_sample_problem() + A[0, ] = 0 + b[0] = 0 + xp, info = minres(A, b) + assert_equal(info, 0) + assert norm(A @ xp - b) <= 1e-5 * norm(b) + + +def test_x0_is_used_by(): + A, b = get_sample_problem() + # Random x0 to feed minres + rng = np.random.RandomState(12345) + x0 = rng.rand(10) + trace = [] + + def trace_iterates(xk): + trace.append(xk) + minres(A, b, x0=x0, callback=trace_iterates) + trace_with_x0 = trace + + trace = [] + minres(A, b, callback=trace_iterates) + assert_(not np.array_equal(trace_with_x0[0], trace[0])) + + +def test_shift(): + A, b = get_sample_problem() + shift = 0.5 + shifted_A = A - shift * np.eye(10) + x1, info1 = minres(A, b, shift=shift) + x2, info2 = minres(shifted_A, b) + assert_equal(info1, 0) + assert_allclose(x1, x2, rtol=1e-5) + + +def test_asymmetric_fail(): + """Asymmetric matrix should raise `ValueError` when check=True""" + A, b = get_sample_problem() + A[1, 2] = 1 + A[2, 1] = 2 + with assert_raises(ValueError): + xp, info = minres(A, b, check=True) + + +def test_minres_non_default_x0(): + rng = np.random.RandomState(1234) + rtol = 1e-6 + a = rng.randn(5, 5) + a = np.dot(a, a.T) + b = rng.randn(5) + c = rng.randn(5) + x = minres(a, b, x0=c, rtol=rtol)[0] + assert norm(a @ x - b) <= rtol * norm(b) + + +def test_minres_precond_non_default_x0(): + rng = np.random.RandomState(12345) + rtol = 1e-6 + a = rng.randn(5, 5) + a = np.dot(a, a.T) + b = rng.randn(5) + c = rng.randn(5) + m = rng.randn(5, 5) + m = np.dot(m, m.T) + x = minres(a, b, M=m, x0=c, rtol=rtol)[0] + assert norm(a @ x - b) <= rtol * norm(b) + + +def test_minres_precond_exact_x0(): + rng = np.random.RandomState(1234) + rtol = 1e-6 + a = np.eye(10) + b = np.ones(10) + c = np.ones(10) + m = rng.randn(10, 10) + m = np.dot(m, m.T) + x = minres(a, b, M=m, x0=c, rtol=rtol)[0] + assert norm(a @ x - b) <= rtol * norm(b) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_utils.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..bb62e2223d515288bd5aa6c5a70028279c4f6d30 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tests/test_utils.py @@ -0,0 +1,9 @@ +import numpy as np +from pytest import raises as assert_raises + +import scipy.sparse.linalg._isolve.utils as utils + + +def test_make_system_bad_shape(): + assert_raises(ValueError, + utils.make_system, np.zeros((5,3)), None, np.zeros(4), np.zeros(4)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tfqmr.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tfqmr.py new file mode 100644 index 0000000000000000000000000000000000000000..3904c27663419a3ad02cb6451633c0aaac9c19c2 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/tfqmr.py @@ -0,0 +1,179 @@ +import numpy as np +from .iterative import _get_atol_rtol +from .utils import make_system + + +__all__ = ['tfqmr'] + + +def tfqmr(A, b, x0=None, *, rtol=1e-5, atol=0., maxiter=None, M=None, + callback=None, show=False): + """ + Solve ``Ax = b`` with the Transpose-Free Quasi-Minimal Residual method. + + Parameters + ---------- + A : {sparse array, ndarray, LinearOperator} + The real or complex N-by-N matrix of the linear system. + Alternatively, `A` can be a linear operator which can + produce ``Ax`` using, e.g., + `scipy.sparse.linalg.LinearOperator`. + b : {ndarray} + Right hand side of the linear system. Has shape (N,) or (N,1). + x0 : {ndarray} + Starting guess for the solution. + rtol, atol : float, optional + Parameters for the convergence test. For convergence, + ``norm(b - A @ x) <= max(rtol*norm(b), atol)`` should be satisfied. + The default is ``rtol=1e-5``, the default for ``atol`` is ``0.0``. + maxiter : int, optional + Maximum number of iterations. Iteration will stop after maxiter + steps even if the specified tolerance has not been achieved. + Default is ``min(10000, ndofs * 10)``, where ``ndofs = A.shape[0]``. + M : {sparse array, ndarray, LinearOperator} + Inverse of the preconditioner of A. M should approximate the + inverse of A and be easy to solve for (see Notes). Effective + preconditioning dramatically improves the rate of convergence, + which implies that fewer iterations are needed to reach a given + error tolerance. By default, no preconditioner is used. + callback : function, optional + User-supplied function to call after each iteration. It is called + as ``callback(xk)``, where ``xk`` is the current solution vector. + show : bool, optional + Specify ``show = True`` to show the convergence, ``show = False`` is + to close the output of the convergence. + Default is `False`. + + Returns + ------- + x : ndarray + The converged solution. + info : int + Provides convergence information: + + - 0 : successful exit + - >0 : convergence to tolerance not achieved, number of iterations + - <0 : illegal input or breakdown + + Notes + ----- + The Transpose-Free QMR algorithm is derived from the CGS algorithm. + However, unlike CGS, the convergence curves for the TFQMR method is + smoothed by computing a quasi minimization of the residual norm. The + implementation supports left preconditioner, and the "residual norm" + to compute in convergence criterion is actually an upper bound on the + actual residual norm ``||b - Axk||``. + + References + ---------- + .. [1] R. W. Freund, A Transpose-Free Quasi-Minimal Residual Algorithm for + Non-Hermitian Linear Systems, SIAM J. Sci. Comput., 14(2), 470-482, + 1993. + .. [2] Y. Saad, Iterative Methods for Sparse Linear Systems, 2nd edition, + SIAM, Philadelphia, 2003. + .. [3] C. T. Kelley, Iterative Methods for Linear and Nonlinear Equations, + number 16 in Frontiers in Applied Mathematics, SIAM, Philadelphia, + 1995. + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import tfqmr + >>> A = csc_array([[3, 2, 0], [1, -1, 0], [0, 5, 1]], dtype=float) + >>> b = np.array([2, 4, -1], dtype=float) + >>> x, exitCode = tfqmr(A, b, atol=0.0) + >>> print(exitCode) # 0 indicates successful convergence + 0 + >>> np.allclose(A.dot(x), b) + True + """ + + # Check data type + dtype = A.dtype + if np.issubdtype(dtype, np.int64): + dtype = float + A = A.astype(dtype) + if np.issubdtype(b.dtype, np.int64): + b = b.astype(dtype) + + A, M, x, b = make_system(A, M, x0, b) + + # Check if the R.H.S is a zero vector + if np.linalg.norm(b) == 0.: + x = b.copy() + return (x, 0) + + ndofs = A.shape[0] + if maxiter is None: + maxiter = min(10000, ndofs * 10) + + if x0 is None: + r = b.copy() + else: + r = b - A.matvec(x) + u = r + w = r.copy() + # Take rstar as b - Ax0, that is rstar := r = b - Ax0 mathematically + rstar = r + v = M.matvec(A.matvec(r)) + uhat = v + d = theta = eta = 0. + # at this point we know rstar == r, so rho is always real + rho = np.inner(rstar.conjugate(), r).real + rhoLast = rho + r0norm = np.sqrt(rho) + tau = r0norm + if r0norm == 0: + return (x, 0) + + # we call this to get the right atol and raise errors as necessary + atol, _ = _get_atol_rtol('tfqmr', r0norm, atol, rtol) + + for iter in range(maxiter): + even = iter % 2 == 0 + if (even): + vtrstar = np.inner(rstar.conjugate(), v) + # Check breakdown + if vtrstar == 0.: + return (x, -1) + alpha = rho / vtrstar + uNext = u - alpha * v # [1]-(5.6) + w -= alpha * uhat # [1]-(5.8) + d = u + (theta**2 / alpha) * eta * d # [1]-(5.5) + # [1]-(5.2) + theta = np.linalg.norm(w) / tau + c = np.sqrt(1. / (1 + theta**2)) + tau *= theta * c + # Calculate step and direction [1]-(5.4) + eta = (c**2) * alpha + z = M.matvec(d) + x += eta * z + + if callback is not None: + callback(x) + + # Convergence criterion + if tau * np.sqrt(iter+1) < atol: + if (show): + print("TFQMR: Linear solve converged due to reach TOL " + f"iterations {iter+1}") + return (x, 0) + + if (not even): + # [1]-(5.7) + rho = np.inner(rstar.conjugate(), w) + beta = rho / rhoLast + u = w + beta * u + v = beta * uhat + (beta**2) * v + uhat = M.matvec(A.matvec(u)) + v += uhat + else: + uhat = M.matvec(A.matvec(uNext)) + u = uNext + rhoLast = rho + + if (show): + print("TFQMR: Linear solve not converged due to reach MAXIT " + f"iterations {iter+1}") + return (x, maxiter) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/utils.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..28925f48014b1dfd8479a2de52f7dde1c367765c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_isolve/utils.py @@ -0,0 +1,121 @@ +__docformat__ = "restructuredtext en" + +__all__ = [] + + +from numpy import asanyarray, asarray, array, zeros + +from scipy.sparse.linalg._interface import aslinearoperator, LinearOperator, \ + IdentityOperator + +_coerce_rules = {('f','f'):'f', ('f','d'):'d', ('f','F'):'F', + ('f','D'):'D', ('d','f'):'d', ('d','d'):'d', + ('d','F'):'D', ('d','D'):'D', ('F','f'):'F', + ('F','d'):'D', ('F','F'):'F', ('F','D'):'D', + ('D','f'):'D', ('D','d'):'D', ('D','F'):'D', + ('D','D'):'D'} + + +def coerce(x,y): + if x not in 'fdFD': + x = 'd' + if y not in 'fdFD': + y = 'd' + return _coerce_rules[x,y] + + +def id(x): + return x + + +def make_system(A, M, x0, b): + """Make a linear system Ax=b + + Parameters + ---------- + A : LinearOperator + sparse or dense matrix (or any valid input to aslinearoperator) + M : {LinearOperator, Nones} + preconditioner + sparse or dense matrix (or any valid input to aslinearoperator) + x0 : {array_like, str, None} + initial guess to iterative method. + ``x0 = 'Mb'`` means using the nonzero initial guess ``M @ b``. + Default is `None`, which means using the zero initial guess. + b : array_like + right hand side + + Returns + ------- + (A, M, x, b) + A : LinearOperator + matrix of the linear system + M : LinearOperator + preconditioner + x : rank 1 ndarray + initial guess + b : rank 1 ndarray + right hand side + + """ + A_ = A + A = aslinearoperator(A) + + if A.shape[0] != A.shape[1]: + raise ValueError(f'expected square matrix, but got shape={(A.shape,)}') + + N = A.shape[0] + + b = asanyarray(b) + + if not (b.shape == (N,1) or b.shape == (N,)): + raise ValueError(f'shapes of A {A.shape} and b {b.shape} are ' + 'incompatible') + + if b.dtype.char not in 'fdFD': + b = b.astype('d') # upcast non-FP types to double + + if hasattr(A,'dtype'): + xtype = A.dtype.char + else: + xtype = A.matvec(b).dtype.char + xtype = coerce(xtype, b.dtype.char) + + b = asarray(b,dtype=xtype) # make b the same type as x + b = b.ravel() + + # process preconditioner + if M is None: + if hasattr(A_,'psolve'): + psolve = A_.psolve + else: + psolve = id + if hasattr(A_,'rpsolve'): + rpsolve = A_.rpsolve + else: + rpsolve = id + if psolve is id and rpsolve is id: + M = IdentityOperator(shape=A.shape, dtype=A.dtype) + else: + M = LinearOperator(A.shape, matvec=psolve, rmatvec=rpsolve, + dtype=A.dtype) + else: + M = aslinearoperator(M) + if A.shape != M.shape: + raise ValueError('matrix and preconditioner have different shapes') + + # set initial guess + if x0 is None: + x = zeros(N, dtype=xtype) + elif isinstance(x0, str): + if x0 == 'Mb': # use nonzero initial guess ``M @ b`` + bCopy = b.copy() + x = M.matvec(bCopy) + else: + x = array(x0, dtype=xtype) + if not (x.shape == (N, 1) or x.shape == (N,)): + raise ValueError(f'shapes of A {A.shape} and ' + f'x0 {x.shape} are incompatible') + x = x.ravel() + + return A, M, x, b diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_matfuncs.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_matfuncs.py new file mode 100644 index 0000000000000000000000000000000000000000..9191e7f2c38daeaf3eee7bf052741d370b1565ce --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_matfuncs.py @@ -0,0 +1,940 @@ +""" +Sparse matrix functions +""" + +# +# Authors: Travis Oliphant, March 2002 +# Anthony Scopatz, August 2012 (Sparse Updates) +# Jake Vanderplas, August 2012 (Sparse Updates) +# + +__all__ = ['expm', 'inv', 'matrix_power'] + +import numpy as np +from scipy.linalg._basic import solve, solve_triangular + +from scipy.sparse._base import issparse +from scipy.sparse.linalg import spsolve +from scipy.sparse._sputils import is_pydata_spmatrix, isintlike + +import scipy.sparse +import scipy.sparse.linalg +from scipy.sparse.linalg._interface import LinearOperator +from scipy.sparse._construct import eye_array + +from ._expm_multiply import _ident_like, _exact_1_norm as _onenorm + + +UPPER_TRIANGULAR = 'upper_triangular' + + +def inv(A): + """ + Compute the inverse of a sparse arrays + + Parameters + ---------- + A : (M, M) sparse arrays + square matrix to be inverted + + Returns + ------- + Ainv : (M, M) sparse arrays + inverse of `A` + + Notes + ----- + This computes the sparse inverse of `A`. If the inverse of `A` is expected + to be non-sparse, it will likely be faster to convert `A` to dense and use + `scipy.linalg.inv`. + + Examples + -------- + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import inv + >>> A = csc_array([[1., 0.], [1., 2.]]) + >>> Ainv = inv(A) + >>> Ainv + + >>> A.dot(Ainv) + + >>> A.dot(Ainv).toarray() + array([[ 1., 0.], + [ 0., 1.]]) + + .. versionadded:: 0.12.0 + + """ + # Check input + if not (issparse(A) or is_pydata_spmatrix(A)): + raise TypeError('Input must be a sparse arrays') + + # Use sparse direct solver to solve "AX = I" accurately + I = _ident_like(A) + Ainv = spsolve(A, I) + return Ainv + + +def _onenorm_matrix_power_nnm(A, p): + """ + Compute the 1-norm of a non-negative integer power of a non-negative matrix. + + Parameters + ---------- + A : a square ndarray or matrix or sparse arrays + Input matrix with non-negative entries. + p : non-negative integer + The power to which the matrix is to be raised. + + Returns + ------- + out : float + The 1-norm of the matrix power p of A. + + """ + # Check input + if int(p) != p or p < 0: + raise ValueError('expected non-negative integer p') + p = int(p) + if len(A.shape) != 2 or A.shape[0] != A.shape[1]: + raise ValueError('expected A to be like a square matrix') + + # Explicitly make a column vector so that this works when A is a + # numpy matrix (in addition to ndarray and sparse arrays). + v = np.ones((A.shape[0], 1), dtype=float) + M = A.T + for i in range(p): + v = M.dot(v) + return np.max(v) + + +def _is_upper_triangular(A): + # This function could possibly be of wider interest. + if issparse(A): + lower_part = scipy.sparse.tril(A, -1) + # Check structural upper triangularity, + # then coincidental upper triangularity if needed. + return lower_part.nnz == 0 or lower_part.count_nonzero() == 0 + elif is_pydata_spmatrix(A): + import sparse + lower_part = sparse.tril(A, -1) + return lower_part.nnz == 0 + else: + return not np.tril(A, -1).any() + + +def _smart_matrix_product(A, B, alpha=None, structure=None): + """ + A matrix product that knows about sparse and structured matrices. + + Parameters + ---------- + A : 2d ndarray + First matrix. + B : 2d ndarray + Second matrix. + alpha : float + The matrix product will be scaled by this constant. + structure : str, optional + A string describing the structure of both matrices `A` and `B`. + Only `upper_triangular` is currently supported. + + Returns + ------- + M : 2d ndarray + Matrix product of A and B. + + """ + if len(A.shape) != 2: + raise ValueError('expected A to be a rectangular matrix') + if len(B.shape) != 2: + raise ValueError('expected B to be a rectangular matrix') + f = None + if structure == UPPER_TRIANGULAR: + if (not issparse(A) and not issparse(B) + and not is_pydata_spmatrix(A) and not is_pydata_spmatrix(B)): + f, = scipy.linalg.get_blas_funcs(('trmm',), (A, B)) + if f is not None: + if alpha is None: + alpha = 1. + out = f(alpha, A, B) + else: + if alpha is None: + out = A.dot(B) + else: + out = alpha * A.dot(B) + return out + + +class MatrixPowerOperator(LinearOperator): + + def __init__(self, A, p, structure=None): + if A.ndim != 2 or A.shape[0] != A.shape[1]: + raise ValueError('expected A to be like a square matrix') + if p < 0: + raise ValueError('expected p to be a non-negative integer') + self._A = A + self._p = p + self._structure = structure + self.dtype = A.dtype + self.ndim = A.ndim + self.shape = A.shape + + def _matvec(self, x): + for i in range(self._p): + x = self._A.dot(x) + return x + + def _rmatvec(self, x): + A_T = self._A.T + x = x.ravel() + for i in range(self._p): + x = A_T.dot(x) + return x + + def _matmat(self, X): + for i in range(self._p): + X = _smart_matrix_product(self._A, X, structure=self._structure) + return X + + @property + def T(self): + return MatrixPowerOperator(self._A.T, self._p) + + +class ProductOperator(LinearOperator): + """ + For now, this is limited to products of multiple square matrices. + """ + + def __init__(self, *args, **kwargs): + self._structure = kwargs.get('structure', None) + for A in args: + if len(A.shape) != 2 or A.shape[0] != A.shape[1]: + raise ValueError( + 'For now, the ProductOperator implementation is ' + 'limited to the product of multiple square matrices.') + if args: + n = args[0].shape[0] + for A in args: + for d in A.shape: + if d != n: + raise ValueError( + 'The square matrices of the ProductOperator ' + 'must all have the same shape.') + self.shape = (n, n) + self.ndim = len(self.shape) + self.dtype = np.result_type(*[x.dtype for x in args]) + self._operator_sequence = args + + def _matvec(self, x): + for A in reversed(self._operator_sequence): + x = A.dot(x) + return x + + def _rmatvec(self, x): + x = x.ravel() + for A in self._operator_sequence: + x = A.T.dot(x) + return x + + def _matmat(self, X): + for A in reversed(self._operator_sequence): + X = _smart_matrix_product(A, X, structure=self._structure) + return X + + @property + def T(self): + T_args = [A.T for A in reversed(self._operator_sequence)] + return ProductOperator(*T_args) + + +def _onenormest_matrix_power(A, p, + t=2, itmax=5, compute_v=False, compute_w=False, structure=None): + """ + Efficiently estimate the 1-norm of A^p. + + Parameters + ---------- + A : ndarray + Matrix whose 1-norm of a power is to be computed. + p : int + Non-negative integer power. + t : int, optional + A positive parameter controlling the tradeoff between + accuracy versus time and memory usage. + Larger values take longer and use more memory + but give more accurate output. + itmax : int, optional + Use at most this many iterations. + compute_v : bool, optional + Request a norm-maximizing linear operator input vector if True. + compute_w : bool, optional + Request a norm-maximizing linear operator output vector if True. + + Returns + ------- + est : float + An underestimate of the 1-norm of the sparse arrays. + v : ndarray, optional + The vector such that ||Av||_1 == est*||v||_1. + It can be thought of as an input to the linear operator + that gives an output with particularly large norm. + w : ndarray, optional + The vector Av which has relatively large 1-norm. + It can be thought of as an output of the linear operator + that is relatively large in norm compared to the input. + + """ + return scipy.sparse.linalg.onenormest( + MatrixPowerOperator(A, p, structure=structure)) + + +def _onenormest_product(operator_seq, + t=2, itmax=5, compute_v=False, compute_w=False, structure=None): + """ + Efficiently estimate the 1-norm of the matrix product of the args. + + Parameters + ---------- + operator_seq : linear operator sequence + Matrices whose 1-norm of product is to be computed. + t : int, optional + A positive parameter controlling the tradeoff between + accuracy versus time and memory usage. + Larger values take longer and use more memory + but give more accurate output. + itmax : int, optional + Use at most this many iterations. + compute_v : bool, optional + Request a norm-maximizing linear operator input vector if True. + compute_w : bool, optional + Request a norm-maximizing linear operator output vector if True. + structure : str, optional + A string describing the structure of all operators. + Only `upper_triangular` is currently supported. + + Returns + ------- + est : float + An underestimate of the 1-norm of the sparse arrays. + v : ndarray, optional + The vector such that ||Av||_1 == est*||v||_1. + It can be thought of as an input to the linear operator + that gives an output with particularly large norm. + w : ndarray, optional + The vector Av which has relatively large 1-norm. + It can be thought of as an output of the linear operator + that is relatively large in norm compared to the input. + + """ + return scipy.sparse.linalg.onenormest( + ProductOperator(*operator_seq, structure=structure)) + + +class _ExpmPadeHelper: + """ + Help lazily evaluate a matrix exponential. + + The idea is to not do more work than we need for high expm precision, + so we lazily compute matrix powers and store or precompute + other properties of the matrix. + + """ + + def __init__(self, A, structure=None, use_exact_onenorm=False): + """ + Initialize the object. + + Parameters + ---------- + A : a dense or sparse square numpy matrix or ndarray + The matrix to be exponentiated. + structure : str, optional + A string describing the structure of matrix `A`. + Only `upper_triangular` is currently supported. + use_exact_onenorm : bool, optional + If True then only the exact one-norm of matrix powers and products + will be used. Otherwise, the one-norm of powers and products + may initially be estimated. + """ + self.A = A + self._A2 = None + self._A4 = None + self._A6 = None + self._A8 = None + self._A10 = None + self._d4_exact = None + self._d6_exact = None + self._d8_exact = None + self._d10_exact = None + self._d4_approx = None + self._d6_approx = None + self._d8_approx = None + self._d10_approx = None + self.ident = _ident_like(A) + self.structure = structure + self.use_exact_onenorm = use_exact_onenorm + + @property + def A2(self): + if self._A2 is None: + self._A2 = _smart_matrix_product( + self.A, self.A, structure=self.structure) + return self._A2 + + @property + def A4(self): + if self._A4 is None: + self._A4 = _smart_matrix_product( + self.A2, self.A2, structure=self.structure) + return self._A4 + + @property + def A6(self): + if self._A6 is None: + self._A6 = _smart_matrix_product( + self.A4, self.A2, structure=self.structure) + return self._A6 + + @property + def A8(self): + if self._A8 is None: + self._A8 = _smart_matrix_product( + self.A6, self.A2, structure=self.structure) + return self._A8 + + @property + def A10(self): + if self._A10 is None: + self._A10 = _smart_matrix_product( + self.A4, self.A6, structure=self.structure) + return self._A10 + + @property + def d4_tight(self): + if self._d4_exact is None: + self._d4_exact = _onenorm(self.A4)**(1/4.) + return self._d4_exact + + @property + def d6_tight(self): + if self._d6_exact is None: + self._d6_exact = _onenorm(self.A6)**(1/6.) + return self._d6_exact + + @property + def d8_tight(self): + if self._d8_exact is None: + self._d8_exact = _onenorm(self.A8)**(1/8.) + return self._d8_exact + + @property + def d10_tight(self): + if self._d10_exact is None: + self._d10_exact = _onenorm(self.A10)**(1/10.) + return self._d10_exact + + @property + def d4_loose(self): + if self.use_exact_onenorm: + return self.d4_tight + if self._d4_exact is not None: + return self._d4_exact + else: + if self._d4_approx is None: + self._d4_approx = _onenormest_matrix_power(self.A2, 2, + structure=self.structure)**(1/4.) + return self._d4_approx + + @property + def d6_loose(self): + if self.use_exact_onenorm: + return self.d6_tight + if self._d6_exact is not None: + return self._d6_exact + else: + if self._d6_approx is None: + self._d6_approx = _onenormest_matrix_power(self.A2, 3, + structure=self.structure)**(1/6.) + return self._d6_approx + + @property + def d8_loose(self): + if self.use_exact_onenorm: + return self.d8_tight + if self._d8_exact is not None: + return self._d8_exact + else: + if self._d8_approx is None: + self._d8_approx = _onenormest_matrix_power(self.A4, 2, + structure=self.structure)**(1/8.) + return self._d8_approx + + @property + def d10_loose(self): + if self.use_exact_onenorm: + return self.d10_tight + if self._d10_exact is not None: + return self._d10_exact + else: + if self._d10_approx is None: + self._d10_approx = _onenormest_product((self.A4, self.A6), + structure=self.structure)**(1/10.) + return self._d10_approx + + def pade3(self): + b = (120., 60., 12., 1.) + U = _smart_matrix_product(self.A, + b[3]*self.A2 + b[1]*self.ident, + structure=self.structure) + V = b[2]*self.A2 + b[0]*self.ident + return U, V + + def pade5(self): + b = (30240., 15120., 3360., 420., 30., 1.) + U = _smart_matrix_product(self.A, + b[5]*self.A4 + b[3]*self.A2 + b[1]*self.ident, + structure=self.structure) + V = b[4]*self.A4 + b[2]*self.A2 + b[0]*self.ident + return U, V + + def pade7(self): + b = (17297280., 8648640., 1995840., 277200., 25200., 1512., 56., 1.) + U = _smart_matrix_product(self.A, + b[7]*self.A6 + b[5]*self.A4 + b[3]*self.A2 + b[1]*self.ident, + structure=self.structure) + V = b[6]*self.A6 + b[4]*self.A4 + b[2]*self.A2 + b[0]*self.ident + return U, V + + def pade9(self): + b = (17643225600., 8821612800., 2075673600., 302702400., 30270240., + 2162160., 110880., 3960., 90., 1.) + U = _smart_matrix_product(self.A, + (b[9]*self.A8 + b[7]*self.A6 + b[5]*self.A4 + + b[3]*self.A2 + b[1]*self.ident), + structure=self.structure) + V = (b[8]*self.A8 + b[6]*self.A6 + b[4]*self.A4 + + b[2]*self.A2 + b[0]*self.ident) + return U, V + + def pade13_scaled(self, s): + b = (64764752532480000., 32382376266240000., 7771770303897600., + 1187353796428800., 129060195264000., 10559470521600., + 670442572800., 33522128640., 1323241920., 40840800., 960960., + 16380., 182., 1.) + B = self.A * 2**-s + B2 = self.A2 * 2**(-2*s) + B4 = self.A4 * 2**(-4*s) + B6 = self.A6 * 2**(-6*s) + U2 = _smart_matrix_product(B6, + b[13]*B6 + b[11]*B4 + b[9]*B2, + structure=self.structure) + U = _smart_matrix_product(B, + (U2 + b[7]*B6 + b[5]*B4 + + b[3]*B2 + b[1]*self.ident), + structure=self.structure) + V2 = _smart_matrix_product(B6, + b[12]*B6 + b[10]*B4 + b[8]*B2, + structure=self.structure) + V = V2 + b[6]*B6 + b[4]*B4 + b[2]*B2 + b[0]*self.ident + return U, V + + +def expm(A): + """ + Compute the matrix exponential using Pade approximation. + + Parameters + ---------- + A : (M,M) array_like or sparse array + 2D Array or Matrix (sparse or dense) to be exponentiated + + Returns + ------- + expA : (M,M) ndarray + Matrix exponential of `A` + + Notes + ----- + This is algorithm (6.1) which is a simplification of algorithm (5.1). + + .. versionadded:: 0.12.0 + + References + ---------- + .. [1] Awad H. Al-Mohy and Nicholas J. Higham (2009) + "A New Scaling and Squaring Algorithm for the Matrix Exponential." + SIAM Journal on Matrix Analysis and Applications. + 31 (3). pp. 970-989. ISSN 1095-7162 + + Examples + -------- + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import expm + >>> A = csc_array([[1, 0, 0], [0, 2, 0], [0, 0, 3]]) + >>> A.toarray() + array([[1, 0, 0], + [0, 2, 0], + [0, 0, 3]], dtype=int64) + >>> Aexp = expm(A) + >>> Aexp + + >>> Aexp.toarray() + array([[ 2.71828183, 0. , 0. ], + [ 0. , 7.3890561 , 0. ], + [ 0. , 0. , 20.08553692]]) + """ + return _expm(A, use_exact_onenorm='auto') + + +def _expm(A, use_exact_onenorm): + # Core of expm, separated to allow testing exact and approximate + # algorithms. + + # Avoid indiscriminate asarray() to allow sparse or other strange arrays. + if isinstance(A, list | tuple | np.matrix): + A = np.asarray(A) + if len(A.shape) != 2 or A.shape[0] != A.shape[1]: + raise ValueError('expected a square matrix') + + # gracefully handle size-0 input, + # carefully handling sparse scenario + if A.shape == (0, 0): + out = np.zeros([0, 0], dtype=A.dtype) + if issparse(A) or is_pydata_spmatrix(A): + return A.__class__(out) + return out + + # Trivial case + if A.shape == (1, 1): + out = [[np.exp(A[0, 0])]] + + # Avoid indiscriminate casting to ndarray to + # allow for sparse or other strange arrays + if issparse(A) or is_pydata_spmatrix(A): + return A.__class__(out) + + return np.array(out) + + # Ensure input is of float type, to avoid integer overflows etc. + if ((isinstance(A, np.ndarray) or issparse(A) or is_pydata_spmatrix(A)) + and not np.issubdtype(A.dtype, np.inexact)): + A = A.astype(float) + + # Detect upper triangularity. + structure = UPPER_TRIANGULAR if _is_upper_triangular(A) else None + + if use_exact_onenorm == "auto": + # Hardcode a matrix order threshold for exact vs. estimated one-norms. + use_exact_onenorm = A.shape[0] < 200 + + # Track functions of A to help compute the matrix exponential. + h = _ExpmPadeHelper( + A, structure=structure, use_exact_onenorm=use_exact_onenorm) + + # Try Pade order 3. + eta_1 = max(h.d4_loose, h.d6_loose) + if eta_1 < 1.495585217958292e-002 and _ell(h.A, 3) == 0: + U, V = h.pade3() + return _solve_P_Q(U, V, structure=structure) + + # Try Pade order 5. + eta_2 = max(h.d4_tight, h.d6_loose) + if eta_2 < 2.539398330063230e-001 and _ell(h.A, 5) == 0: + U, V = h.pade5() + return _solve_P_Q(U, V, structure=structure) + + # Try Pade orders 7 and 9. + eta_3 = max(h.d6_tight, h.d8_loose) + if eta_3 < 9.504178996162932e-001 and _ell(h.A, 7) == 0: + U, V = h.pade7() + return _solve_P_Q(U, V, structure=structure) + if eta_3 < 2.097847961257068e+000 and _ell(h.A, 9) == 0: + U, V = h.pade9() + return _solve_P_Q(U, V, structure=structure) + + # Use Pade order 13. + eta_4 = max(h.d8_loose, h.d10_loose) + eta_5 = min(eta_3, eta_4) + theta_13 = 4.25 + + # Choose smallest s>=0 such that 2**(-s) eta_5 <= theta_13 + if eta_5 == 0: + # Nilpotent special case + s = 0 + else: + s = max(int(np.ceil(np.log2(eta_5 / theta_13))), 0) + s = s + _ell(2**-s * h.A, 13) + U, V = h.pade13_scaled(s) + X = _solve_P_Q(U, V, structure=structure) + if structure == UPPER_TRIANGULAR: + # Invoke Code Fragment 2.1. + X = _fragment_2_1(X, h.A, s) + else: + # X = r_13(A)^(2^s) by repeated squaring. + for i in range(s): + X = X.dot(X) + return X + + +def _solve_P_Q(U, V, structure=None): + """ + A helper function for expm_2009. + + Parameters + ---------- + U : ndarray + Pade numerator. + V : ndarray + Pade denominator. + structure : str, optional + A string describing the structure of both matrices `U` and `V`. + Only `upper_triangular` is currently supported. + + Notes + ----- + The `structure` argument is inspired by similar args + for theano and cvxopt functions. + + """ + P = U + V + Q = -U + V + if issparse(U) or is_pydata_spmatrix(U): + return spsolve(Q, P) + elif structure is None: + return solve(Q, P) + elif structure == UPPER_TRIANGULAR: + return solve_triangular(Q, P) + else: + raise ValueError('unsupported matrix structure: ' + str(structure)) + + +def _exp_sinch(a, x): + """ + Stably evaluate exp(a)*sinh(x)/x + + Notes + ----- + The strategy of falling back to a sixth order Taylor expansion + was suggested by the Spallation Neutron Source docs + which was found on the internet by google search. + http://www.ornl.gov/~t6p/resources/xal/javadoc/gov/sns/tools/math/ElementaryFunction.html + The details of the cutoff point and the Horner-like evaluation + was picked without reference to anything in particular. + + Note that sinch is not currently implemented in scipy.special, + whereas the "engineer's" definition of sinc is implemented. + The implementation of sinc involves a scaling factor of pi + that distinguishes it from the "mathematician's" version of sinc. + + """ + + # If x is small then use sixth order Taylor expansion. + # How small is small? I am using the point where the relative error + # of the approximation is less than 1e-14. + # If x is large then directly evaluate sinh(x) / x. + if abs(x) < 0.0135: + x2 = x*x + return np.exp(a) * (1 + (x2/6.)*(1 + (x2/20.)*(1 + (x2/42.)))) + else: + return (np.exp(a + x) - np.exp(a - x)) / (2*x) + + +def _eq_10_42(lam_1, lam_2, t_12): + """ + Equation (10.42) of Functions of Matrices: Theory and Computation. + + Notes + ----- + This is a helper function for _fragment_2_1 of expm_2009. + Equation (10.42) is on page 251 in the section on Schur algorithms. + In particular, section 10.4.3 explains the Schur-Parlett algorithm. + expm([[lam_1, t_12], [0, lam_1]) + = + [[exp(lam_1), t_12*exp((lam_1 + lam_2)/2)*sinch((lam_1 - lam_2)/2)], + [0, exp(lam_2)] + """ + + # The plain formula t_12 * (exp(lam_2) - exp(lam_2)) / (lam_2 - lam_1) + # apparently suffers from cancellation, according to Higham's textbook. + # A nice implementation of sinch, defined as sinh(x)/x, + # will apparently work around the cancellation. + a = 0.5 * (lam_1 + lam_2) + b = 0.5 * (lam_1 - lam_2) + return t_12 * _exp_sinch(a, b) + + +def _fragment_2_1(X, T, s): + """ + A helper function for expm_2009. + + Notes + ----- + The argument X is modified in-place, but this modification is not the same + as the returned value of the function. + This function also takes pains to do things in ways that are compatible + with sparse arrays, for example by avoiding fancy indexing + and by using methods of the matrices whenever possible instead of + using functions of the numpy or scipy libraries themselves. + + """ + # Form X = r_m(2^-s T) + # Replace diag(X) by exp(2^-s diag(T)). + n = X.shape[0] + diag_T = np.ravel(T.diagonal().copy()) + + # Replace diag(X) by exp(2^-s diag(T)). + scale = 2 ** -s + exp_diag = np.exp(scale * diag_T) + for k in range(n): + X[k, k] = exp_diag[k] + + for i in range(s-1, -1, -1): + X = X.dot(X) + + # Replace diag(X) by exp(2^-i diag(T)). + scale = 2 ** -i + exp_diag = np.exp(scale * diag_T) + for k in range(n): + X[k, k] = exp_diag[k] + + # Replace (first) superdiagonal of X by explicit formula + # for superdiagonal of exp(2^-i T) from Eq (10.42) of + # the author's 2008 textbook + # Functions of Matrices: Theory and Computation. + for k in range(n-1): + lam_1 = scale * diag_T[k] + lam_2 = scale * diag_T[k+1] + t_12 = scale * T[k, k+1] + value = _eq_10_42(lam_1, lam_2, t_12) + X[k, k+1] = value + + # Return the updated X matrix. + return X + + +def _ell(A, m): + """ + A helper function for expm_2009. + + Parameters + ---------- + A : linear operator + A linear operator whose norm of power we care about. + m : int + The power of the linear operator + + Returns + ------- + value : int + A value related to a bound. + + """ + if len(A.shape) != 2 or A.shape[0] != A.shape[1]: + raise ValueError('expected A to be like a square matrix') + + # The c_i are explained in (2.2) and (2.6) of the 2005 expm paper. + # They are coefficients of terms of a generating function series expansion. + c_i = {3: 100800., + 5: 10059033600., + 7: 4487938430976000., + 9: 5914384781877411840000., + 13: 113250775606021113483283660800000000. + } + abs_c_recip = c_i[m] + + # This is explained after Eq. (1.2) of the 2009 expm paper. + # It is the "unit roundoff" of IEEE double precision arithmetic. + u = 2**-53 + + # Compute the one-norm of matrix power p of abs(A). + A_abs_onenorm = _onenorm_matrix_power_nnm(abs(A), 2*m + 1) + + # Treat zero norm as a special case. + if not A_abs_onenorm: + return 0 + + alpha = A_abs_onenorm / (_onenorm(A) * abs_c_recip) + log2_alpha_div_u = np.log2(alpha/u) + value = int(np.ceil(log2_alpha_div_u / (2 * m))) + return max(value, 0) + +def matrix_power(A, power): + """ + Raise a square matrix to the integer power, `power`. + + For non-negative integers, ``A**power`` is computed using repeated + matrix multiplications. Negative integers are not supported. + + Parameters + ---------- + A : (M, M) square sparse array or matrix + sparse array that will be raised to power `power` + power : int + Exponent used to raise sparse array `A` + + Returns + ------- + A**power : (M, M) sparse array or matrix + The output matrix will be the same shape as A, and will preserve + the class of A, but the format of the output may be changed. + + Notes + ----- + This uses a recursive implementation of the matrix power. For computing + the matrix power using a reasonably large `power`, this may be less efficient + than computing the product directly, using A @ A @ ... @ A. + This is contingent upon the number of nonzero entries in the matrix. + + .. versionadded:: 1.12.0 + + Examples + -------- + >>> from scipy import sparse + >>> A = sparse.csc_array([[0,1,0],[1,0,1],[0,1,0]]) + >>> A.todense() + array([[0, 1, 0], + [1, 0, 1], + [0, 1, 0]]) + >>> (A @ A).todense() + array([[1, 0, 1], + [0, 2, 0], + [1, 0, 1]]) + >>> A2 = sparse.linalg.matrix_power(A, 2) + >>> A2.todense() + array([[1, 0, 1], + [0, 2, 0], + [1, 0, 1]]) + >>> A4 = sparse.linalg.matrix_power(A, 4) + >>> A4.todense() + array([[2, 0, 2], + [0, 4, 0], + [2, 0, 2]]) + + """ + M, N = A.shape + if M != N: + raise TypeError('sparse matrix is not square') + + if isintlike(power): + power = int(power) + if power < 0: + raise ValueError('exponent must be >= 0') + + if power == 0: + return eye_array(M, dtype=A.dtype) + + if power == 1: + return A.copy() + + tmp = matrix_power(A, power // 2) + if power % 2: + return A @ tmp @ tmp + else: + return tmp @ tmp + else: + raise ValueError("exponent must be an integer") diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_norm.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_norm.py new file mode 100644 index 0000000000000000000000000000000000000000..ad7bdc562813a258ad493a50ff713d1f618ed8ca --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_norm.py @@ -0,0 +1,194 @@ +"""Sparse matrix norms. + +""" +import numpy as np +from scipy.sparse import issparse +from scipy.sparse.linalg import svds +from scipy.sparse._sputils import convert_pydata_sparse_to_scipy +import scipy.sparse as sp + +from numpy import sqrt, abs + +__all__ = ['norm'] + + +def _sparse_frobenius_norm(x): + data = sp._sputils._todata(x) + return np.linalg.norm(data) + + +def norm(x, ord=None, axis=None): + """ + Norm of a sparse matrix + + This function is able to return one of seven different matrix norms, + depending on the value of the ``ord`` parameter. + + Parameters + ---------- + x : a sparse array + Input sparse array. + ord : {non-zero int, inf, -inf, 'fro'}, optional + Order of the norm (see table under ``Notes``). inf means numpy's + `inf` object. + axis : {int, 2-tuple of ints, None}, optional + If `axis` is an integer, it specifies the axis of `x` along which to + compute the vector norms. If `axis` is a 2-tuple, it specifies the + axes that hold 2-D matrices, and the matrix norms of these matrices + are computed. If `axis` is None then either a vector norm (when `x` + is 1-D) or a matrix norm (when `x` is 2-D) is returned. + + Returns + ------- + n : float or ndarray + + Notes + ----- + Some of the ord are not implemented because some associated functions like, + _multi_svd_norm, are not yet available for sparse array. + + This docstring is modified based on numpy.linalg.norm. + https://github.com/numpy/numpy/blob/main/numpy/linalg/linalg.py + + The following norms can be calculated: + + ===== ============================ + ord norm for sparse arrays + ===== ============================ + None Frobenius norm + 'fro' Frobenius norm + inf max(sum(abs(x), axis=1)) + -inf min(sum(abs(x), axis=1)) + 0 abs(x).sum(axis=axis) + 1 max(sum(abs(x), axis=0)) + -1 min(sum(abs(x), axis=0)) + 2 Spectral norm (the largest singular value) + -2 Not implemented + other Not implemented + ===== ============================ + + The Frobenius norm is given by [1]_: + + :math:`||A||_F = [\\sum_{i,j} abs(a_{i,j})^2]^{1/2}` + + References + ---------- + .. [1] G. H. Golub and C. F. Van Loan, *Matrix Computations*, + Baltimore, MD, Johns Hopkins University Press, 1985, pg. 15 + + Examples + -------- + >>> from scipy.sparse import csr_array, diags_array + >>> import numpy as np + >>> from scipy.sparse.linalg import norm + >>> a = np.arange(9) - 4 + >>> a + array([-4, -3, -2, -1, 0, 1, 2, 3, 4]) + >>> b = a.reshape((3, 3)) + >>> b + array([[-4, -3, -2], + [-1, 0, 1], + [ 2, 3, 4]]) + + >>> b = csr_array(b) + >>> norm(b) + 7.745966692414834 + >>> norm(b, 'fro') + 7.745966692414834 + >>> norm(b, np.inf) + 9 + >>> norm(b, -np.inf) + 2 + >>> norm(b, 1) + 7 + >>> norm(b, -1) + 6 + + The matrix 2-norm or the spectral norm is the largest singular + value, computed approximately and with limitations. + + >>> b = diags_array([-1, 1], offsets=[0, 1], shape=(9, 10)) + >>> norm(b, 2) + 1.9753... + """ + x = convert_pydata_sparse_to_scipy(x, target_format="csr") + if not issparse(x): + raise TypeError("input is not sparse. use numpy.linalg.norm") + + # Check the default case first and handle it immediately. + if axis is None and ord in (None, 'fro', 'f'): + return _sparse_frobenius_norm(x) + + # Some norms require functions that are not implemented for all types. + x = x.tocsr() + + if axis is None: + axis = tuple(range(x.ndim)) + elif not isinstance(axis, tuple): + msg = "'axis' must be None, an integer or a tuple of integers" + try: + int_axis = int(axis) + except TypeError as e: + raise TypeError(msg) from e + if axis != int_axis: + raise TypeError(msg) + axis = (int_axis,) + + nd = x.ndim + if len(axis) == 2: + row_axis, col_axis = axis + if not (-nd <= row_axis < nd and -nd <= col_axis < nd): + message = f'Invalid axis {axis!r} for an array with shape {x.shape!r}' + raise ValueError(message) + if row_axis % nd == col_axis % nd: + raise ValueError('Duplicate axes given.') + if ord == 2: + _, s, _ = svds(x, k=1, solver="arpack", rng=None) + return s[0] + elif ord == -2: + raise NotImplementedError + #return _multi_svd_norm(x, row_axis, col_axis, amin) + elif ord == 1: + return abs(x).sum(axis=row_axis).max() + elif ord == np.inf: + return abs(x).sum(axis=col_axis).max() + elif ord == -1: + return abs(x).sum(axis=row_axis).min() + elif ord == -np.inf: + return abs(x).sum(axis=col_axis).min() + elif ord in (None, 'f', 'fro'): + # The axis order does not matter for this norm. + return _sparse_frobenius_norm(x) + else: + raise ValueError("Invalid norm order for matrices.") + elif len(axis) == 1: + a, = axis + if not (-nd <= a < nd): + message = f'Invalid axis {axis!r} for an array with shape {x.shape!r}' + raise ValueError(message) + if ord == np.inf: + M = abs(x).max(axis=a) + elif ord == -np.inf: + M = abs(x).min(axis=a) + elif ord == 0: + # Zero norm + M = (x != 0).sum(axis=a) + elif ord == 1: + # special case for speedup + M = abs(x).sum(axis=a) + elif ord in (2, None): + M = sqrt(abs(x).power(2).sum(axis=a)) + else: + try: + ord + 1 + except TypeError as e: + raise ValueError('Invalid norm order for vectors.') from e + M = np.power(abs(x).power(ord).sum(axis=a), 1 / ord) + if hasattr(M, 'toarray'): + return M.toarray().ravel() + elif hasattr(M, 'A'): + return M.A.ravel() + else: + return M.ravel() + else: + raise ValueError("Improper number of dimensions to norm.") diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_onenormest.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_onenormest.py new file mode 100644 index 0000000000000000000000000000000000000000..aa9b7f3ef0ce55ea0fbd5bf17de73f5c57073e8c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_onenormest.py @@ -0,0 +1,467 @@ +"""Sparse block 1-norm estimator. +""" + +import numpy as np +from scipy.sparse.linalg import aslinearoperator + + +__all__ = ['onenormest'] + + +def onenormest(A, t=2, itmax=5, compute_v=False, compute_w=False): + """ + Compute a lower bound of the 1-norm of a sparse array. + + Parameters + ---------- + A : ndarray or other linear operator + A linear operator that can be transposed and that can + produce matrix products. + t : int, optional + A positive parameter controlling the tradeoff between + accuracy versus time and memory usage. + Larger values take longer and use more memory + but give more accurate output. + itmax : int, optional + Use at most this many iterations. + compute_v : bool, optional + Request a norm-maximizing linear operator input vector if True. + compute_w : bool, optional + Request a norm-maximizing linear operator output vector if True. + + Returns + ------- + est : float + An underestimate of the 1-norm of the sparse array. + v : ndarray, optional + The vector such that ||Av||_1 == est*||v||_1. + It can be thought of as an input to the linear operator + that gives an output with particularly large norm. + w : ndarray, optional + The vector Av which has relatively large 1-norm. + It can be thought of as an output of the linear operator + that is relatively large in norm compared to the input. + + Notes + ----- + This is algorithm 2.4 of [1]_. + + In [2]_ it is described as follows. + "This algorithm typically requires the evaluation of + about 4t matrix-vector products and almost invariably + produces a norm estimate (which is, in fact, a lower + bound on the norm) correct to within a factor 3." + + .. versionadded:: 0.13.0 + + References + ---------- + .. [1] Nicholas J. Higham and Francoise Tisseur (2000), + "A Block Algorithm for Matrix 1-Norm Estimation, + with an Application to 1-Norm Pseudospectra." + SIAM J. Matrix Anal. Appl. Vol. 21, No. 4, pp. 1185-1201. + + .. [2] Awad H. Al-Mohy and Nicholas J. Higham (2009), + "A new scaling and squaring algorithm for the matrix exponential." + SIAM J. Matrix Anal. Appl. Vol. 31, No. 3, pp. 970-989. + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse import csc_array + >>> from scipy.sparse.linalg import onenormest + >>> A = csc_array([[1., 0., 0.], [5., 8., 2.], [0., -1., 0.]], dtype=float) + >>> A.toarray() + array([[ 1., 0., 0.], + [ 5., 8., 2.], + [ 0., -1., 0.]]) + >>> onenormest(A) + 9.0 + >>> np.linalg.norm(A.toarray(), ord=1) + 9.0 + """ + + # Check the input. + A = aslinearoperator(A) + if A.shape[0] != A.shape[1]: + raise ValueError('expected the operator to act like a square matrix') + + # If the operator size is small compared to t, + # then it is easier to compute the exact norm. + # Otherwise estimate the norm. + n = A.shape[1] + if t >= n: + A_explicit = np.asarray(aslinearoperator(A).matmat(np.identity(n))) + if A_explicit.shape != (n, n): + raise Exception('internal error: ', + 'unexpected shape ' + str(A_explicit.shape)) + col_abs_sums = abs(A_explicit).sum(axis=0) + if col_abs_sums.shape != (n, ): + raise Exception('internal error: ', + 'unexpected shape ' + str(col_abs_sums.shape)) + argmax_j = np.argmax(col_abs_sums) + v = elementary_vector(n, argmax_j) + w = A_explicit[:, argmax_j] + est = col_abs_sums[argmax_j] + else: + est, v, w, nmults, nresamples = _onenormest_core(A, A.H, t, itmax) + + # Report the norm estimate along with some certificates of the estimate. + if compute_v or compute_w: + result = (est,) + if compute_v: + result += (v,) + if compute_w: + result += (w,) + return result + else: + return est + + +def _blocked_elementwise(func): + """ + Decorator for an elementwise function, to apply it blockwise along + first dimension, to avoid excessive memory usage in temporaries. + """ + block_size = 2**20 + + def wrapper(x): + if x.shape[0] < block_size: + return func(x) + else: + y0 = func(x[:block_size]) + y = np.zeros((x.shape[0],) + y0.shape[1:], dtype=y0.dtype) + y[:block_size] = y0 + del y0 + for j in range(block_size, x.shape[0], block_size): + y[j:j+block_size] = func(x[j:j+block_size]) + return y + return wrapper + + +@_blocked_elementwise +def sign_round_up(X): + """ + This should do the right thing for both real and complex matrices. + + From Higham and Tisseur: + "Everything in this section remains valid for complex matrices + provided that sign(A) is redefined as the matrix (aij / |aij|) + (and sign(0) = 1) transposes are replaced by conjugate transposes." + + """ + Y = X.copy() + Y[Y == 0] = 1 + Y /= np.abs(Y) + return Y + + +@_blocked_elementwise +def _max_abs_axis1(X): + return np.max(np.abs(X), axis=1) + + +def _sum_abs_axis0(X): + block_size = 2**20 + r = None + for j in range(0, X.shape[0], block_size): + y = np.sum(np.abs(X[j:j+block_size]), axis=0) + if r is None: + r = y + else: + r += y + return r + + +def elementary_vector(n, i): + v = np.zeros(n, dtype=float) + v[i] = 1 + return v + + +def vectors_are_parallel(v, w): + # Columns are considered parallel when they are equal or negative. + # Entries are required to be in {-1, 1}, + # which guarantees that the magnitudes of the vectors are identical. + if v.ndim != 1 or v.shape != w.shape: + raise ValueError('expected conformant vectors with entries in {-1,1}') + n = v.shape[0] + return np.dot(v, w) == n + + +def every_col_of_X_is_parallel_to_a_col_of_Y(X, Y): + for v in X.T: + if not any(vectors_are_parallel(v, w) for w in Y.T): + return False + return True + + +def column_needs_resampling(i, X, Y=None): + # column i of X needs resampling if either + # it is parallel to a previous column of X or + # it is parallel to a column of Y + n, t = X.shape + v = X[:, i] + if any(vectors_are_parallel(v, X[:, j]) for j in range(i)): + return True + if Y is not None: + if any(vectors_are_parallel(v, w) for w in Y.T): + return True + return False + + +def resample_column(i, X): + X[:, i] = np.random.randint(0, 2, size=X.shape[0])*2 - 1 + + +def less_than_or_close(a, b): + return np.allclose(a, b) or (a < b) + + +def _algorithm_2_2(A, AT, t): + """ + This is Algorithm 2.2. + + Parameters + ---------- + A : ndarray or other linear operator + A linear operator that can produce matrix products. + AT : ndarray or other linear operator + The transpose of A. + t : int, optional + A positive parameter controlling the tradeoff between + accuracy versus time and memory usage. + + Returns + ------- + g : sequence + A non-negative decreasing vector + such that g[j] is a lower bound for the 1-norm + of the column of A of jth largest 1-norm. + The first entry of this vector is therefore a lower bound + on the 1-norm of the linear operator A. + This sequence has length t. + ind : sequence + The ith entry of ind is the index of the column A whose 1-norm + is given by g[i]. + This sequence of indices has length t, and its entries are + chosen from range(n), possibly with repetition, + where n is the order of the operator A. + + Notes + ----- + This algorithm is mainly for testing. + It uses the 'ind' array in a way that is similar to + its usage in algorithm 2.4. This algorithm 2.2 may be easier to test, + so it gives a chance of uncovering bugs related to indexing + which could have propagated less noticeably to algorithm 2.4. + + """ + A_linear_operator = aslinearoperator(A) + AT_linear_operator = aslinearoperator(AT) + n = A_linear_operator.shape[0] + + # Initialize the X block with columns of unit 1-norm. + X = np.ones((n, t)) + if t > 1: + X[:, 1:] = np.random.randint(0, 2, size=(n, t-1))*2 - 1 + X /= float(n) + + # Iteratively improve the lower bounds. + # Track extra things, to assert invariants for debugging. + g_prev = None + h_prev = None + k = 1 + ind = range(t) + while True: + Y = np.asarray(A_linear_operator.matmat(X)) + g = _sum_abs_axis0(Y) + best_j = np.argmax(g) + g.sort() + g = g[::-1] + S = sign_round_up(Y) + Z = np.asarray(AT_linear_operator.matmat(S)) + h = _max_abs_axis1(Z) + + # If this algorithm runs for fewer than two iterations, + # then its return values do not have the properties indicated + # in the description of the algorithm. + # In particular, the entries of g are not 1-norms of any + # column of A until the second iteration. + # Therefore we will require the algorithm to run for at least + # two iterations, even though this requirement is not stated + # in the description of the algorithm. + if k >= 2: + if less_than_or_close(max(h), np.dot(Z[:, best_j], X[:, best_j])): + break + ind = np.argsort(h)[::-1][:t] + h = h[ind] + for j in range(t): + X[:, j] = elementary_vector(n, ind[j]) + + # Check invariant (2.2). + if k >= 2: + if not less_than_or_close(g_prev[0], h_prev[0]): + raise Exception('invariant (2.2) is violated') + if not less_than_or_close(h_prev[0], g[0]): + raise Exception('invariant (2.2) is violated') + + # Check invariant (2.3). + if k >= 3: + for j in range(t): + if not less_than_or_close(g[j], g_prev[j]): + raise Exception('invariant (2.3) is violated') + + # Update for the next iteration. + g_prev = g + h_prev = h + k += 1 + + # Return the lower bounds and the corresponding column indices. + return g, ind + + +def _onenormest_core(A, AT, t, itmax): + """ + Compute a lower bound of the 1-norm of a sparse array. + + Parameters + ---------- + A : ndarray or other linear operator + A linear operator that can produce matrix products. + AT : ndarray or other linear operator + The transpose of A. + t : int, optional + A positive parameter controlling the tradeoff between + accuracy versus time and memory usage. + itmax : int, optional + Use at most this many iterations. + + Returns + ------- + est : float + An underestimate of the 1-norm of the sparse array. + v : ndarray, optional + The vector such that ||Av||_1 == est*||v||_1. + It can be thought of as an input to the linear operator + that gives an output with particularly large norm. + w : ndarray, optional + The vector Av which has relatively large 1-norm. + It can be thought of as an output of the linear operator + that is relatively large in norm compared to the input. + nmults : int, optional + The number of matrix products that were computed. + nresamples : int, optional + The number of times a parallel column was observed, + necessitating a re-randomization of the column. + + Notes + ----- + This is algorithm 2.4. + + """ + # This function is a more or less direct translation + # of Algorithm 2.4 from the Higham and Tisseur (2000) paper. + A_linear_operator = aslinearoperator(A) + AT_linear_operator = aslinearoperator(AT) + if itmax < 2: + raise ValueError('at least two iterations are required') + if t < 1: + raise ValueError('at least one column is required') + n = A.shape[0] + if t >= n: + raise ValueError('t should be smaller than the order of A') + # Track the number of big*small matrix multiplications + # and the number of resamplings. + nmults = 0 + nresamples = 0 + # "We now explain our choice of starting matrix. We take the first + # column of X to be the vector of 1s [...] This has the advantage that + # for a matrix with nonnegative elements the algorithm converges + # with an exact estimate on the second iteration, and such matrices + # arise in applications [...]" + X = np.ones((n, t), dtype=float) + # "The remaining columns are chosen as rand{-1,1}, + # with a check for and correction of parallel columns, + # exactly as for S in the body of the algorithm." + if t > 1: + for i in range(1, t): + # These are technically initial samples, not resamples, + # so the resampling count is not incremented. + resample_column(i, X) + for i in range(t): + while column_needs_resampling(i, X): + resample_column(i, X) + nresamples += 1 + # "Choose starting matrix X with columns of unit 1-norm." + X /= float(n) + # "indices of used unit vectors e_j" + ind_hist = np.zeros(0, dtype=np.intp) + est_old = 0 + S = np.zeros((n, t), dtype=float) + k = 1 + ind = None + while True: + Y = np.asarray(A_linear_operator.matmat(X)) + nmults += 1 + mags = _sum_abs_axis0(Y) + est = np.max(mags) + best_j = np.argmax(mags) + if est > est_old or k == 2: + if k >= 2: + ind_best = ind[best_j] + w = Y[:, best_j] + # (1) + if k >= 2 and est <= est_old: + est = est_old + break + est_old = est + S_old = S + if k > itmax: + break + S = sign_round_up(Y) + del Y + # (2) + if every_col_of_X_is_parallel_to_a_col_of_Y(S, S_old): + break + if t > 1: + # "Ensure that no column of S is parallel to another column of S + # or to a column of S_old by replacing columns of S by rand{-1,1}." + for i in range(t): + while column_needs_resampling(i, S, S_old): + resample_column(i, S) + nresamples += 1 + del S_old + # (3) + Z = np.asarray(AT_linear_operator.matmat(S)) + nmults += 1 + h = _max_abs_axis1(Z) + del Z + # (4) + if k >= 2 and max(h) == h[ind_best]: + break + # "Sort h so that h_first >= ... >= h_last + # and re-order ind correspondingly." + # + # Later on, we will need at most t+len(ind_hist) largest + # entries, so drop the rest + ind = np.argsort(h)[::-1][:t+len(ind_hist)].copy() + del h + if t > 1: + # (5) + # Break if the most promising t vectors have been visited already. + if np.isin(ind[:t], ind_hist).all(): + break + # Put the most promising unvisited vectors at the front of the list + # and put the visited vectors at the end of the list. + # Preserve the order of the indices induced by the ordering of h. + seen = np.isin(ind, ind_hist) + ind = np.concatenate((ind[~seen], ind[seen])) + for j in range(t): + X[:, j] = elementary_vector(n, ind[j]) + + new_ind = ind[:t][~np.isin(ind[:t], ind_hist)] + ind_hist = np.concatenate((ind_hist, new_ind)) + k += 1 + v = elementary_vector(n, ind_best) + return est, v, w, nmults, nresamples diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_special_sparse_arrays.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_special_sparse_arrays.py new file mode 100644 index 0000000000000000000000000000000000000000..cf412a9d9513584373db2cae53f5a19c79874ca4 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_special_sparse_arrays.py @@ -0,0 +1,952 @@ +import numpy as np +from scipy.sparse.linalg import LinearOperator +from scipy.sparse import kron, eye_array, dia_array + +__all__ = ['LaplacianNd'] +# Sakurai and Mikota classes are intended for tests and benchmarks +# and explicitly not included in the public API of this module. + + +class LaplacianNd(LinearOperator): + """ + The grid Laplacian in ``N`` dimensions and its eigenvalues/eigenvectors. + + Construct Laplacian on a uniform rectangular grid in `N` dimensions + and output its eigenvalues and eigenvectors. + The Laplacian ``L`` is square, negative definite, real symmetric array + with signed integer entries and zeros otherwise. + + Parameters + ---------- + grid_shape : tuple + A tuple of integers of length ``N`` (corresponding to the dimension of + the Lapacian), where each entry gives the size of that dimension. The + Laplacian matrix is square of the size ``np.prod(grid_shape)``. + boundary_conditions : {'neumann', 'dirichlet', 'periodic'}, optional + The type of the boundary conditions on the boundaries of the grid. + Valid values are ``'dirichlet'`` or ``'neumann'``(default) or + ``'periodic'``. + dtype : dtype + Numerical type of the array. Default is ``np.int8``. + + Methods + ------- + toarray() + Construct a dense array from Laplacian data + tosparse() + Construct a sparse array from Laplacian data + eigenvalues(m=None) + Construct a 1D array of `m` largest (smallest in absolute value) + eigenvalues of the Laplacian matrix in ascending order. + eigenvectors(m=None): + Construct the array with columns made of `m` eigenvectors (``float``) + of the ``Nd`` Laplacian corresponding to the `m` ordered eigenvalues. + + .. versionadded:: 1.12.0 + + Notes + ----- + Compared to the MATLAB/Octave implementation [1] of 1-, 2-, and 3-D + Laplacian, this code allows the arbitrary N-D case and the matrix-free + callable option, but is currently limited to pure Dirichlet, Neumann or + Periodic boundary conditions only. + + The Laplacian matrix of a graph (`scipy.sparse.csgraph.laplacian`) of a + rectangular grid corresponds to the negative Laplacian with the Neumann + conditions, i.e., ``boundary_conditions = 'neumann'``. + + All eigenvalues and eigenvectors of the discrete Laplacian operator for + an ``N``-dimensional regular grid of shape `grid_shape` with the grid + step size ``h=1`` are analytically known [2]. + + References + ---------- + .. [1] https://github.com/lobpcg/blopex/blob/master/blopex_\ +tools/matlab/laplacian/laplacian.m + .. [2] "Eigenvalues and eigenvectors of the second derivative", Wikipedia + https://en.wikipedia.org/wiki/Eigenvalues_and_eigenvectors_\ +of_the_second_derivative + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse.linalg import LaplacianNd + >>> from scipy.sparse import diags_array, csgraph + >>> from scipy.linalg import eigvalsh + + The one-dimensional Laplacian demonstrated below for pure Neumann boundary + conditions on a regular grid with ``n=6`` grid points is exactly the + negative graph Laplacian for the undirected linear graph with ``n`` + vertices using the sparse adjacency matrix ``G`` represented by the + famous tri-diagonal matrix: + + >>> n = 6 + >>> G = diags_array(np.ones(n - 1), offsets=1, format='csr') + >>> Lf = csgraph.laplacian(G, symmetrized=True, form='function') + >>> grid_shape = (n, ) + >>> lap = LaplacianNd(grid_shape, boundary_conditions='neumann') + >>> np.array_equal(lap.matmat(np.eye(n)), -Lf(np.eye(n))) + True + + Since all matrix entries of the Laplacian are integers, ``'int8'`` is + the default dtype for storing matrix representations. + + >>> lap.tosparse() + + >>> lap.toarray() + array([[-1, 1, 0, 0, 0, 0], + [ 1, -2, 1, 0, 0, 0], + [ 0, 1, -2, 1, 0, 0], + [ 0, 0, 1, -2, 1, 0], + [ 0, 0, 0, 1, -2, 1], + [ 0, 0, 0, 0, 1, -1]], dtype=int8) + >>> np.array_equal(lap.matmat(np.eye(n)), lap.toarray()) + True + >>> np.array_equal(lap.tosparse().toarray(), lap.toarray()) + True + + Any number of extreme eigenvalues and/or eigenvectors can be computed. + + >>> lap = LaplacianNd(grid_shape, boundary_conditions='periodic') + >>> lap.eigenvalues() + array([-4., -3., -3., -1., -1., 0.]) + >>> lap.eigenvalues()[-2:] + array([-1., 0.]) + >>> lap.eigenvalues(2) + array([-1., 0.]) + >>> lap.eigenvectors(1) + array([[0.40824829], + [0.40824829], + [0.40824829], + [0.40824829], + [0.40824829], + [0.40824829]]) + >>> lap.eigenvectors(2) + array([[ 0.28867513, 0.40824829], + [ 0.57735027, 0.40824829], + [ 0.28867513, 0.40824829], + [-0.28867513, 0.40824829], + [-0.57735027, 0.40824829], + [-0.28867513, 0.40824829]]) + >>> lap.eigenvectors() + array([[ 0.40824829, 0.5 , 0.28867513, 0.28867513, 0.5 , + 0.40824829], + [-0.40824829, 0. , -0.57735027, 0.57735027, 0. , + 0.40824829], + [ 0.40824829, -0.5 , 0.28867513, 0.28867513, -0.5 , + 0.40824829], + [-0.40824829, 0.5 , 0.28867513, -0.28867513, -0.5 , + 0.40824829], + [ 0.40824829, 0. , -0.57735027, -0.57735027, 0. , + 0.40824829], + [-0.40824829, -0.5 , 0.28867513, -0.28867513, 0.5 , + 0.40824829]]) + + The two-dimensional Laplacian is illustrated on a regular grid with + ``grid_shape = (2, 3)`` points in each dimension. + + >>> grid_shape = (2, 3) + >>> n = np.prod(grid_shape) + + Numeration of grid points is as follows: + + >>> np.arange(n).reshape(grid_shape + (-1,)) + array([[[0], + [1], + [2]], + + [[3], + [4], + [5]]]) + + Each of the boundary conditions ``'dirichlet'``, ``'periodic'``, and + ``'neumann'`` is illustrated separately; with ``'dirichlet'`` + + >>> lap = LaplacianNd(grid_shape, boundary_conditions='dirichlet') + >>> lap.tosparse() + + >>> lap.toarray() + array([[-4, 1, 0, 1, 0, 0], + [ 1, -4, 1, 0, 1, 0], + [ 0, 1, -4, 0, 0, 1], + [ 1, 0, 0, -4, 1, 0], + [ 0, 1, 0, 1, -4, 1], + [ 0, 0, 1, 0, 1, -4]], dtype=int8) + >>> np.array_equal(lap.matmat(np.eye(n)), lap.toarray()) + True + >>> np.array_equal(lap.tosparse().toarray(), lap.toarray()) + True + >>> lap.eigenvalues() + array([-6.41421356, -5. , -4.41421356, -3.58578644, -3. , + -1.58578644]) + >>> eigvals = eigvalsh(lap.toarray().astype(np.float64)) + >>> np.allclose(lap.eigenvalues(), eigvals) + True + >>> np.allclose(lap.toarray() @ lap.eigenvectors(), + ... lap.eigenvectors() @ np.diag(lap.eigenvalues())) + True + + with ``'periodic'`` + + >>> lap = LaplacianNd(grid_shape, boundary_conditions='periodic') + >>> lap.tosparse() + + >>> lap.toarray() + array([[-4, 1, 1, 2, 0, 0], + [ 1, -4, 1, 0, 2, 0], + [ 1, 1, -4, 0, 0, 2], + [ 2, 0, 0, -4, 1, 1], + [ 0, 2, 0, 1, -4, 1], + [ 0, 0, 2, 1, 1, -4]], dtype=int8) + >>> np.array_equal(lap.matmat(np.eye(n)), lap.toarray()) + True + >>> np.array_equal(lap.tosparse().toarray(), lap.toarray()) + True + >>> lap.eigenvalues() + array([-7., -7., -4., -3., -3., 0.]) + >>> eigvals = eigvalsh(lap.toarray().astype(np.float64)) + >>> np.allclose(lap.eigenvalues(), eigvals) + True + >>> np.allclose(lap.toarray() @ lap.eigenvectors(), + ... lap.eigenvectors() @ np.diag(lap.eigenvalues())) + True + + and with ``'neumann'`` + + >>> lap = LaplacianNd(grid_shape, boundary_conditions='neumann') + >>> lap.tosparse() + + >>> lap.toarray() + array([[-2, 1, 0, 1, 0, 0], + [ 1, -3, 1, 0, 1, 0], + [ 0, 1, -2, 0, 0, 1], + [ 1, 0, 0, -2, 1, 0], + [ 0, 1, 0, 1, -3, 1], + [ 0, 0, 1, 0, 1, -2]], dtype=int8) + >>> np.array_equal(lap.matmat(np.eye(n)), lap.toarray()) + True + >>> np.array_equal(lap.tosparse().toarray(), lap.toarray()) + True + >>> lap.eigenvalues() + array([-5., -3., -3., -2., -1., 0.]) + >>> eigvals = eigvalsh(lap.toarray().astype(np.float64)) + >>> np.allclose(lap.eigenvalues(), eigvals) + True + >>> np.allclose(lap.toarray() @ lap.eigenvectors(), + ... lap.eigenvectors() @ np.diag(lap.eigenvalues())) + True + + """ + + def __init__(self, grid_shape, *, + boundary_conditions='neumann', + dtype=np.int8): + + if boundary_conditions not in ('dirichlet', 'neumann', 'periodic'): + raise ValueError( + f"Unknown value {boundary_conditions!r} is given for " + "'boundary_conditions' parameter. The valid options are " + "'dirichlet', 'periodic', and 'neumann' (default)." + ) + + self.grid_shape = grid_shape + self.boundary_conditions = boundary_conditions + # LaplacianNd folds all dimensions in `grid_shape` into a single one + N = np.prod(grid_shape) + super().__init__(dtype=dtype, shape=(N, N)) + + def _eigenvalue_ordering(self, m): + """Compute `m` largest eigenvalues in each of the ``N`` directions, + i.e., up to ``m * N`` total, order them and return `m` largest. + """ + grid_shape = self.grid_shape + if m is None: + indices = np.indices(grid_shape) + Leig = np.zeros(grid_shape) + else: + grid_shape_min = min(grid_shape, + tuple(np.ones_like(grid_shape) * m)) + indices = np.indices(grid_shape_min) + Leig = np.zeros(grid_shape_min) + + for j, n in zip(indices, grid_shape): + if self.boundary_conditions == 'dirichlet': + Leig += -4 * np.sin(np.pi * (j + 1) / (2 * (n + 1))) ** 2 + elif self.boundary_conditions == 'neumann': + Leig += -4 * np.sin(np.pi * j / (2 * n)) ** 2 + else: # boundary_conditions == 'periodic' + Leig += -4 * np.sin(np.pi * np.floor((j + 1) / 2) / n) ** 2 + + Leig_ravel = Leig.ravel() + ind = np.argsort(Leig_ravel) + eigenvalues = Leig_ravel[ind] + if m is not None: + eigenvalues = eigenvalues[-m:] + ind = ind[-m:] + + return eigenvalues, ind + + def eigenvalues(self, m=None): + """Return the requested number of eigenvalues. + + Parameters + ---------- + m : int, optional + The positive number of smallest eigenvalues to return. + If not provided, then all eigenvalues will be returned. + + Returns + ------- + eigenvalues : float array + The requested `m` smallest or all eigenvalues, in ascending order. + """ + eigenvalues, _ = self._eigenvalue_ordering(m) + return eigenvalues + + def _ev1d(self, j, n): + """Return 1 eigenvector in 1d with index `j` + and number of grid points `n` where ``j < n``. + """ + if self.boundary_conditions == 'dirichlet': + i = np.pi * (np.arange(n) + 1) / (n + 1) + ev = np.sqrt(2. / (n + 1.)) * np.sin(i * (j + 1)) + elif self.boundary_conditions == 'neumann': + i = np.pi * (np.arange(n) + 0.5) / n + ev = np.sqrt((1. if j == 0 else 2.) / n) * np.cos(i * j) + else: # boundary_conditions == 'periodic' + if j == 0: + ev = np.sqrt(1. / n) * np.ones(n) + elif j + 1 == n and n % 2 == 0: + ev = np.sqrt(1. / n) * np.tile([1, -1], n//2) + elif (j + 1) % 2 == 0: + i = np.pi * (np.arange(n) + 0.5) / n + ev = np.sqrt(2. / n) * np.sin(i * (j + 1)) + else: + i = np.pi * (np.arange(n) + 0.5) / n + ev = np.sqrt(2. / n) * np.cos(i * j) + # make small values exact zeros correcting round-off errors + # due to symmetry of eigenvectors the exact 0. is correct + ev[np.abs(ev) < np.finfo(np.float64).eps] = 0. + return ev + + def _one_eve(self, k): + """Return 1 eigenvector in Nd with multi-index `j` + as a tensor product of the corresponding 1d eigenvectors. + """ + phi = [self._ev1d(j, n) for j, n in zip(k, self.grid_shape)] + result = phi[0] + for phi in phi[1:]: + result = np.tensordot(result, phi, axes=0) + return np.asarray(result).ravel() + + def eigenvectors(self, m=None): + """Return the requested number of eigenvectors for ordered eigenvalues. + + Parameters + ---------- + m : int, optional + The positive number of eigenvectors to return. If not provided, + then all eigenvectors will be returned. + + Returns + ------- + eigenvectors : float array + An array with columns made of the requested `m` or all eigenvectors. + The columns are ordered according to the `m` ordered eigenvalues. + """ + _, ind = self._eigenvalue_ordering(m) + if m is None: + grid_shape_min = self.grid_shape + else: + grid_shape_min = min(self.grid_shape, + tuple(np.ones_like(self.grid_shape) * m)) + + N_indices = np.unravel_index(ind, grid_shape_min) + N_indices = [tuple(x) for x in zip(*N_indices)] + eigenvectors_list = [self._one_eve(k) for k in N_indices] + return np.column_stack(eigenvectors_list) + + def toarray(self): + """ + Converts the Laplacian data to a dense array. + + Returns + ------- + L : ndarray + The shape is ``(N, N)`` where ``N = np.prod(grid_shape)``. + + """ + grid_shape = self.grid_shape + n = np.prod(grid_shape) + L = np.zeros([n, n], dtype=np.int8) + # Scratch arrays + L_i = np.empty_like(L) + Ltemp = np.empty_like(L) + + for ind, dim in enumerate(grid_shape): + # Start zeroing out L_i + L_i[:] = 0 + # Allocate the top left corner with the kernel of L_i + # Einsum returns writable view of arrays + np.einsum("ii->i", L_i[:dim, :dim])[:] = -2 + np.einsum("ii->i", L_i[: dim - 1, 1:dim])[:] = 1 + np.einsum("ii->i", L_i[1:dim, : dim - 1])[:] = 1 + + if self.boundary_conditions == 'neumann': + L_i[0, 0] = -1 + L_i[dim - 1, dim - 1] = -1 + elif self.boundary_conditions == 'periodic': + if dim > 1: + L_i[0, dim - 1] += 1 + L_i[dim - 1, 0] += 1 + else: + L_i[0, 0] += 1 + + # kron is too slow for large matrices hence the next two tricks + # 1- kron(eye, mat) is block_diag(mat, mat, ...) + # 2- kron(mat, eye) can be performed by 4d stride trick + + # 1- + new_dim = dim + # for block_diag we tile the top left portion on the diagonal + if ind > 0: + tiles = np.prod(grid_shape[:ind]) + for j in range(1, tiles): + L_i[j*dim:(j+1)*dim, j*dim:(j+1)*dim] = L_i[:dim, :dim] + new_dim += dim + # 2- + # we need the keep L_i, but reset the array + Ltemp[:new_dim, :new_dim] = L_i[:new_dim, :new_dim] + tiles = int(np.prod(grid_shape[ind+1:])) + # Zero out the top left, the rest is already 0 + L_i[:new_dim, :new_dim] = 0 + idx = [x for x in range(tiles)] + L_i.reshape( + (new_dim, tiles, + new_dim, tiles) + )[:, idx, :, idx] = Ltemp[:new_dim, :new_dim] + + L += L_i + + return L.astype(self.dtype) + + def tosparse(self): + """ + Constructs a sparse array from the Laplacian data. The returned sparse + array format is dependent on the selected boundary conditions. + + Returns + ------- + L : scipy.sparse.sparray + The shape is ``(N, N)`` where ``N = np.prod(grid_shape)``. + + """ + N = len(self.grid_shape) + p = np.prod(self.grid_shape) + L = dia_array((p, p), dtype=np.int8) + + for i in range(N): + dim = self.grid_shape[i] + data = np.ones([3, dim], dtype=np.int8) + data[1, :] *= -2 + + if self.boundary_conditions == 'neumann': + data[1, 0] = -1 + data[1, -1] = -1 + + L_i = dia_array((data, [-1, 0, 1]), shape=(dim, dim), + dtype=np.int8 + ) + + if self.boundary_conditions == 'periodic': + t = dia_array((dim, dim), dtype=np.int8) + t.setdiag([1], k=-dim+1) + t.setdiag([1], k=dim-1) + L_i += t + + for j in range(i): + L_i = kron(eye_array(self.grid_shape[j], dtype=np.int8), L_i) + for j in range(i + 1, N): + L_i = kron(L_i, eye_array(self.grid_shape[j], dtype=np.int8)) + L += L_i + return L.astype(self.dtype) + + def _matvec(self, x): + grid_shape = self.grid_shape + N = len(grid_shape) + X = x.reshape(grid_shape + (-1,)) + Y = -2 * N * X + for i in range(N): + Y += np.roll(X, 1, axis=i) + Y += np.roll(X, -1, axis=i) + if self.boundary_conditions in ('neumann', 'dirichlet'): + Y[(slice(None),)*i + (0,) + (slice(None),)*(N-i-1) + ] -= np.roll(X, 1, axis=i)[ + (slice(None),) * i + (0,) + (slice(None),) * (N-i-1) + ] + Y[ + (slice(None),) * i + (-1,) + (slice(None),) * (N-i-1) + ] -= np.roll(X, -1, axis=i)[ + (slice(None),) * i + (-1,) + (slice(None),) * (N-i-1) + ] + + if self.boundary_conditions == 'neumann': + Y[ + (slice(None),) * i + (0,) + (slice(None),) * (N-i-1) + ] += np.roll(X, 0, axis=i)[ + (slice(None),) * i + (0,) + (slice(None),) * (N-i-1) + ] + Y[ + (slice(None),) * i + (-1,) + (slice(None),) * (N-i-1) + ] += np.roll(X, 0, axis=i)[ + (slice(None),) * i + (-1,) + (slice(None),) * (N-i-1) + ] + + return Y.reshape(-1, X.shape[-1]) + + def _matmat(self, x): + return self._matvec(x) + + def _adjoint(self): + return self + + def _transpose(self): + return self + + +class Sakurai(LinearOperator): + """ + Construct a Sakurai matrix in various formats and its eigenvalues. + + Constructs the "Sakurai" matrix motivated by reference [1]_: + square real symmetric positive definite and 5-diagonal + with the main diagonal ``[5, 6, 6, ..., 6, 6, 5], the ``+1`` and ``-1`` + diagonals filled with ``-4``, and the ``+2`` and ``-2`` diagonals + made of ``1``. Its eigenvalues are analytically known to be + ``16. * np.power(np.cos(0.5 * k * np.pi / (n + 1)), 4)``. + The matrix gets ill-conditioned with its size growing. + It is useful for testing and benchmarking sparse eigenvalue solvers + especially those taking advantage of its banded 5-diagonal structure. + See the notes below for details. + + Parameters + ---------- + n : int + The size of the matrix. + dtype : dtype + Numerical type of the array. Default is ``np.int8``. + + Methods + ------- + toarray() + Construct a dense array from Laplacian data + tosparse() + Construct a sparse array from Laplacian data + tobanded() + The Sakurai matrix in the format for banded symmetric matrices, + i.e., (3, n) ndarray with 3 upper diagonals + placing the main diagonal at the bottom. + eigenvalues + All eigenvalues of the Sakurai matrix ordered ascending. + + Notes + ----- + Reference [1]_ introduces a generalized eigenproblem for the matrix pair + `A` and `B` where `A` is the identity so we turn it into an eigenproblem + just for the matrix `B` that this function outputs in various formats + together with its eigenvalues. + + .. versionadded:: 1.12.0 + + References + ---------- + .. [1] T. Sakurai, H. Tadano, Y. Inadomi, and U. Nagashima, + "A moment-based method for large-scale generalized + eigenvalue problems", + Appl. Num. Anal. Comp. Math. Vol. 1 No. 2 (2004). + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse.linalg._special_sparse_arrays import Sakurai + >>> from scipy.linalg import eig_banded + >>> n = 6 + >>> sak = Sakurai(n) + + Since all matrix entries are small integers, ``'int8'`` is + the default dtype for storing matrix representations. + + >>> sak.toarray() + array([[ 5, -4, 1, 0, 0, 0], + [-4, 6, -4, 1, 0, 0], + [ 1, -4, 6, -4, 1, 0], + [ 0, 1, -4, 6, -4, 1], + [ 0, 0, 1, -4, 6, -4], + [ 0, 0, 0, 1, -4, 5]], dtype=int8) + >>> sak.tobanded() + array([[ 1, 1, 1, 1, 1, 1], + [-4, -4, -4, -4, -4, -4], + [ 5, 6, 6, 6, 6, 5]], dtype=int8) + >>> sak.tosparse() + + >>> np.array_equal(sak.dot(np.eye(n)), sak.tosparse().toarray()) + True + >>> sak.eigenvalues() + array([0.03922866, 0.56703972, 2.41789479, 5.97822974, + 10.54287655, 14.45473055]) + >>> sak.eigenvalues(2) + array([0.03922866, 0.56703972]) + + The banded form can be used in scipy functions for banded matrices, e.g., + + >>> e = eig_banded(sak.tobanded(), eigvals_only=True) + >>> np.allclose(sak.eigenvalues(), e, atol= n * n * n * np.finfo(float).eps) + True + + """ + def __init__(self, n, dtype=np.int8): + self.n = n + self.dtype = dtype + shape = (n, n) + super().__init__(dtype, shape) + + def eigenvalues(self, m=None): + """Return the requested number of eigenvalues. + + Parameters + ---------- + m : int, optional + The positive number of smallest eigenvalues to return. + If not provided, then all eigenvalues will be returned. + + Returns + ------- + eigenvalues : `np.float64` array + The requested `m` smallest or all eigenvalues, in ascending order. + """ + if m is None: + m = self.n + k = np.arange(self.n + 1 -m, self.n + 1) + return np.flip(16. * np.power(np.cos(0.5 * k * np.pi / (self.n + 1)), 4)) + + def tobanded(self): + """ + Construct the Sakurai matrix as a banded array. + """ + d0 = np.r_[5, 6 * np.ones(self.n - 2, dtype=self.dtype), 5] + d1 = -4 * np.ones(self.n, dtype=self.dtype) + d2 = np.ones(self.n, dtype=self.dtype) + return np.array([d2, d1, d0]).astype(self.dtype) + + def tosparse(self): + """ + Construct the Sakurai matrix in a sparse format. + """ + from scipy.sparse import diags_array + d = self.tobanded() + # the banded format has the main diagonal at the bottom + # `diags_array` inherits dtype from banded + return diags_array([d[0], d[1], d[2], d[1], d[0]], offsets=[-2, -1, 0, 1, 2], + shape=(self.n, self.n), dtype=d.dtype) + + def toarray(self): + return self.tosparse().toarray() + + def _matvec(self, x): + """ + Construct matrix-free callable banded-matrix-vector multiplication by + the Sakurai matrix without constructing or storing the matrix itself + using the knowledge of its entries and the 5-diagonal format. + """ + x = x.reshape(self.n, -1) + result_dtype = np.promote_types(x.dtype, self.dtype) + sx = np.zeros_like(x, dtype=result_dtype) + sx[0, :] = 5 * x[0, :] - 4 * x[1, :] + x[2, :] + sx[-1, :] = 5 * x[-1, :] - 4 * x[-2, :] + x[-3, :] + sx[1: -1, :] = (6 * x[1: -1, :] - 4 * (x[:-2, :] + x[2:, :]) + + np.pad(x[:-3, :], ((1, 0), (0, 0))) + + np.pad(x[3:, :], ((0, 1), (0, 0)))) + return sx + + def _matmat(self, x): + """ + Construct matrix-free callable matrix-matrix multiplication by + the Sakurai matrix without constructing or storing the matrix itself + by reusing the ``_matvec(x)`` that supports both 1D and 2D arrays ``x``. + """ + return self._matvec(x) + + def _adjoint(self): + return self + + def _transpose(self): + return self + + +class MikotaM(LinearOperator): + """ + Construct a mass matrix in various formats of Mikota pair. + + The mass matrix `M` is square real diagonal + positive definite with entries that are reciprocal to integers. + + Parameters + ---------- + shape : tuple of int + The shape of the matrix. + dtype : dtype + Numerical type of the array. Default is ``np.float64``. + + Methods + ------- + toarray() + Construct a dense array from Mikota data + tosparse() + Construct a sparse array from Mikota data + tobanded() + The format for banded symmetric matrices, + i.e., (1, n) ndarray with the main diagonal. + """ + def __init__(self, shape, dtype=np.float64): + self.shape = shape + self.dtype = dtype + super().__init__(dtype, shape) + + def _diag(self): + # The matrix is constructed from its diagonal 1 / [1, ..., N+1]; + # compute in a function to avoid duplicated code & storage footprint + return (1. / np.arange(1, self.shape[0] + 1)).astype(self.dtype) + + def tobanded(self): + return self._diag() + + def tosparse(self): + from scipy.sparse import diags_array + return diags_array([self._diag()], offsets=[0], + shape=self.shape, dtype=self.dtype) + + def toarray(self): + return np.diag(self._diag()).astype(self.dtype) + + def _matvec(self, x): + """ + Construct matrix-free callable banded-matrix-vector multiplication by + the Mikota mass matrix without constructing or storing the matrix itself + using the knowledge of its entries and the diagonal format. + """ + x = x.reshape(self.shape[0], -1) + return self._diag()[:, np.newaxis] * x + + def _matmat(self, x): + """ + Construct matrix-free callable matrix-matrix multiplication by + the Mikota mass matrix without constructing or storing the matrix itself + by reusing the ``_matvec(x)`` that supports both 1D and 2D arrays ``x``. + """ + return self._matvec(x) + + def _adjoint(self): + return self + + def _transpose(self): + return self + + +class MikotaK(LinearOperator): + """ + Construct a stiffness matrix in various formats of Mikota pair. + + The stiffness matrix `K` is square real tri-diagonal symmetric + positive definite with integer entries. + + Parameters + ---------- + shape : tuple of int + The shape of the matrix. + dtype : dtype + Numerical type of the array. Default is ``np.int32``. + + Methods + ------- + toarray() + Construct a dense array from Mikota data + tosparse() + Construct a sparse array from Mikota data + tobanded() + The format for banded symmetric matrices, + i.e., (2, n) ndarray with 2 upper diagonals + placing the main diagonal at the bottom. + """ + def __init__(self, shape, dtype=np.int32): + self.shape = shape + self.dtype = dtype + super().__init__(dtype, shape) + # The matrix is constructed from its diagonals; + # we precompute these to avoid duplicating the computation + n = shape[0] + self._diag0 = np.arange(2 * n - 1, 0, -2, dtype=self.dtype) + self._diag1 = - np.arange(n - 1, 0, -1, dtype=self.dtype) + + def tobanded(self): + return np.array([np.pad(self._diag1, (1, 0), 'constant'), self._diag0]) + + def tosparse(self): + from scipy.sparse import diags_array + return diags_array([self._diag1, self._diag0, self._diag1], offsets=[-1, 0, 1], + shape=self.shape, dtype=self.dtype) + + def toarray(self): + return self.tosparse().toarray() + + def _matvec(self, x): + """ + Construct matrix-free callable banded-matrix-vector multiplication by + the Mikota stiffness matrix without constructing or storing the matrix + itself using the knowledge of its entries and the 3-diagonal format. + """ + x = x.reshape(self.shape[0], -1) + result_dtype = np.promote_types(x.dtype, self.dtype) + kx = np.zeros_like(x, dtype=result_dtype) + d1 = self._diag1 + d0 = self._diag0 + kx[0, :] = d0[0] * x[0, :] + d1[0] * x[1, :] + kx[-1, :] = d1[-1] * x[-2, :] + d0[-1] * x[-1, :] + kx[1: -1, :] = (d1[:-1, None] * x[: -2, :] + + d0[1: -1, None] * x[1: -1, :] + + d1[1:, None] * x[2:, :]) + return kx + + def _matmat(self, x): + """ + Construct matrix-free callable matrix-matrix multiplication by + the Stiffness mass matrix without constructing or storing the matrix itself + by reusing the ``_matvec(x)`` that supports both 1D and 2D arrays ``x``. + """ + return self._matvec(x) + + def _adjoint(self): + return self + + def _transpose(self): + return self + + +class MikotaPair: + """ + Construct the Mikota pair of matrices in various formats and + eigenvalues of the generalized eigenproblem with them. + + The Mikota pair of matrices [1, 2]_ models a vibration problem + of a linear mass-spring system with the ends attached where + the stiffness of the springs and the masses increase along + the system length such that vibration frequencies are subsequent + integers 1, 2, ..., `n` where `n` is the number of the masses. Thus, + eigenvalues of the generalized eigenvalue problem for + the matrix pair `K` and `M` where `K` is the system stiffness matrix + and `M` is the system mass matrix are the squares of the integers, + i.e., 1, 4, 9, ..., ``n * n``. + + The stiffness matrix `K` is square real tri-diagonal symmetric + positive definite. The mass matrix `M` is diagonal with diagonal + entries 1, 1/2, 1/3, ...., ``1/n``. Both matrices get + ill-conditioned with `n` growing. + + Parameters + ---------- + n : int + The size of the matrices of the Mikota pair. + dtype : dtype + Numerical type of the array. Default is ``np.float64``. + + Attributes + ---------- + eigenvalues : 1D ndarray, ``np.uint64`` + All eigenvalues of the Mikota pair ordered ascending. + + Methods + ------- + MikotaK() + A `LinearOperator` custom object for the stiffness matrix. + MikotaM() + A `LinearOperator` custom object for the mass matrix. + + .. versionadded:: 1.12.0 + + References + ---------- + .. [1] J. Mikota, "Frequency tuning of chain structure multibody oscillators + to place the natural frequencies at omega1 and N-1 integer multiples + omega2,..., omegaN", Z. Angew. Math. Mech. 81 (2001), S2, S201-S202. + Appl. Num. Anal. Comp. Math. Vol. 1 No. 2 (2004). + .. [2] Peter C. Muller and Metin Gurgoze, + "Natural frequencies of a multi-degree-of-freedom vibration system", + Proc. Appl. Math. Mech. 6, 319-320 (2006). + http://dx.doi.org/10.1002/pamm.200610141. + + Examples + -------- + >>> import numpy as np + >>> from scipy.sparse.linalg._special_sparse_arrays import MikotaPair + >>> n = 6 + >>> mik = MikotaPair(n) + >>> mik_k = mik.k + >>> mik_m = mik.m + >>> mik_k.toarray() + array([[11., -5., 0., 0., 0., 0.], + [-5., 9., -4., 0., 0., 0.], + [ 0., -4., 7., -3., 0., 0.], + [ 0., 0., -3., 5., -2., 0.], + [ 0., 0., 0., -2., 3., -1.], + [ 0., 0., 0., 0., -1., 1.]]) + >>> mik_k.tobanded() + array([[ 0., -5., -4., -3., -2., -1.], + [11., 9., 7., 5., 3., 1.]]) + >>> mik_m.tobanded() + array([1. , 0.5 , 0.33333333, 0.25 , 0.2 , + 0.16666667]) + >>> mik_k.tosparse() + + >>> mik_m.tosparse() + + >>> np.array_equal(mik_k(np.eye(n)), mik_k.toarray()) + True + >>> np.array_equal(mik_m(np.eye(n)), mik_m.toarray()) + True + >>> mik.eigenvalues() + array([ 1, 4, 9, 16, 25, 36]) + >>> mik.eigenvalues(2) + array([ 1, 4]) + + """ + def __init__(self, n, dtype=np.float64): + self.n = n + self.dtype = dtype + self.shape = (n, n) + self.m = MikotaM(self.shape, self.dtype) + self.k = MikotaK(self.shape, self.dtype) + + def eigenvalues(self, m=None): + """Return the requested number of eigenvalues. + + Parameters + ---------- + m : int, optional + The positive number of smallest eigenvalues to return. + If not provided, then all eigenvalues will be returned. + + Returns + ------- + eigenvalues : `np.uint64` array + The requested `m` smallest or all eigenvalues, in ascending order. + """ + if m is None: + m = self.n + arange_plus1 = np.arange(1, m + 1, dtype=np.uint64) + return arange_plus1 * arange_plus1 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_svdp.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_svdp.py new file mode 100644 index 0000000000000000000000000000000000000000..ecdf339f77b8ec39fdf1c5a95e5299f98aa00e62 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/_svdp.py @@ -0,0 +1,291 @@ +__all__ = ['_svdp'] + +import numpy as np + +from scipy.sparse.linalg import aslinearoperator +from scipy.linalg import LinAlgError + +from . import _propack # type: ignore[attr-defined] + + +_lansvd_dict = { + 'f': _propack.slansvd, + 'd': _propack.dlansvd, + 'F': _propack.clansvd, + 'D': _propack.zlansvd, +} + + +_lansvd_irl_dict = { + 'f': _propack.slansvd_irl, + 'd': _propack.dlansvd_irl, + 'F': _propack.clansvd_irl, + 'D': _propack.zlansvd_irl, +} + + +_which_converter = { + 'LM': 1, + 'SM': 0, +} + + +class _AProd: + """ + Wrapper class for linear operator + + The call signature of the __call__ method matches the callback of + the PROPACK routines. + """ + def __init__(self, A): + try: + self.A = aslinearoperator(A) + except TypeError: + self.A = aslinearoperator(np.asarray(A)) + + def __call__(self, transa, m, n, x, y): + if transa == 0: + y[:] = self.A.matvec(x) + else: + y[:] = self.A.rmatvec(x) + + @property + def shape(self): + return self.A.shape + + @property + def dtype(self): + try: + return self.A.dtype + except AttributeError: + return self.A.matvec(np.zeros(self.A.shape[1])).dtype + + +def _svdp(A, k, which='LM', irl_mode=True, kmax=None, + compute_u=True, compute_v=True, v0=None, full_output=False, tol=0, + delta=None, eta=None, anorm=0, cgs=False, elr=True, + min_relgap=0.002, shifts=None, maxiter=None, rng=None): + """ + Compute the singular value decomposition of a linear operator using PROPACK + + Parameters + ---------- + A : array_like, sparse matrix, or LinearOperator + Operator for which SVD will be computed. If `A` is a LinearOperator + object, it must define both ``matvec`` and ``rmatvec`` methods. + k : int + Number of singular values/vectors to compute + which : {"LM", "SM"} + Which singular triplets to compute: + - 'LM': compute triplets corresponding to the `k` largest singular + values + - 'SM': compute triplets corresponding to the `k` smallest singular + values + `which='SM'` requires `irl_mode=True`. Computes largest singular + values by default. + irl_mode : bool, optional + If `True`, then compute SVD using IRL (implicitly restarted Lanczos) + mode. Default is `True`. + kmax : int, optional + Maximal number of iterations / maximal dimension of the Krylov + subspace. Default is ``10 * k``. + compute_u : bool, optional + If `True` (default) then compute left singular vectors, `u`. + compute_v : bool, optional + If `True` (default) then compute right singular vectors, `v`. + tol : float, optional + The desired relative accuracy for computed singular values. + If not specified, it will be set based on machine precision. + v0 : array_like, optional + Starting vector for iterations: must be of length ``A.shape[0]``. + If not specified, PROPACK will generate a starting vector. + full_output : bool, optional + If `True`, then return sigma_bound. Default is `False`. + delta : float, optional + Level of orthogonality to maintain between Lanczos vectors. + Default is set based on machine precision. + eta : float, optional + Orthogonality cutoff. During reorthogonalization, vectors with + component larger than `eta` along the Lanczos vector will be purged. + Default is set based on machine precision. + anorm : float, optional + Estimate of ``||A||``. Default is ``0``. + cgs : bool, optional + If `True`, reorthogonalization is done using classical Gram-Schmidt. + If `False` (default), it is done using modified Gram-Schmidt. + elr : bool, optional + If `True` (default), then extended local orthogonality is enforced + when obtaining singular vectors. + min_relgap : float, optional + The smallest relative gap allowed between any shift in IRL mode. + Default is ``0.001``. Accessed only if ``irl_mode=True``. + shifts : int, optional + Number of shifts per restart in IRL mode. Default is determined + to satisfy ``k <= min(kmax-shifts, m, n)``. Must be + >= 0, but choosing 0 might lead to performance degradation. + Accessed only if ``irl_mode=True``. + maxiter : int, optional + Maximum number of restarts in IRL mode. Default is ``1000``. + Accessed only if ``irl_mode=True``. + rng : `numpy.random.Generator`, optional + Pseudorandom number generator state. When `rng` is None, a new + `numpy.random.Generator` is created using entropy from the + operating system. Types other than `numpy.random.Generator` are + passed to `numpy.random.default_rng` to instantiate a ``Generator``. + + Returns + ------- + u : ndarray + The `k` largest (``which="LM"``) or smallest (``which="SM"``) left + singular vectors, ``shape == (A.shape[0], 3)``, returned only if + ``compute_u=True``. + sigma : ndarray + The top `k` singular values, ``shape == (k,)`` + vt : ndarray + The `k` largest (``which="LM"``) or smallest (``which="SM"``) right + singular vectors, ``shape == (3, A.shape[1])``, returned only if + ``compute_v=True``. + sigma_bound : ndarray + the error bounds on the singular values sigma, returned only if + ``full_output=True``. + + """ + if rng is None: + raise ValueError("`rng` must be a normalized numpy.random.Generator instance") + + which = which.upper() + if which not in {'LM', 'SM'}: + raise ValueError("`which` must be either 'LM' or 'SM'") + if not irl_mode and which == 'SM': + raise ValueError("`which`='SM' requires irl_mode=True") + + aprod = _AProd(A) + typ = aprod.dtype.char + + try: + lansvd_irl = _lansvd_irl_dict[typ] + lansvd = _lansvd_dict[typ] + except KeyError: + # work with non-supported types using native system precision + if np.iscomplexobj(np.empty(0, dtype=typ)): + typ = 'D' + else: + typ = 'd' + lansvd_irl = _lansvd_irl_dict[typ] + lansvd = _lansvd_dict[typ] + + m, n = aprod.shape + if (k < 1) or (k > min(m, n)): + raise ValueError("k must be positive and not greater than m or n") + + if kmax is None: + kmax = 10*k + if maxiter is None: + maxiter = 1000 + + # guard against unnecessarily large kmax + kmax = min(m + 1, n + 1, kmax) + if kmax < k: + raise ValueError( + "kmax must be greater than or equal to k, " + f"but kmax ({kmax}) < k ({k})") + + # convert python args to fortran args + jobu = 1 if compute_u else 0 + jobv = 1 if compute_v else 0 + + # these will be the output arrays + u = np.zeros((m, kmax + 1), order='F', dtype=typ) + v = np.zeros((n, kmax), order='F', dtype=typ) + sigma = np.zeros(k, order='F', dtype=typ.lower()) + bnd = np.zeros(k, order='F', dtype=typ.lower()) + + # Specify the starting vector. if v0 is all zero, PROPACK will generate + # a random starting vector: the random seed cannot be controlled in that + # case, so we'll instead use numpy to generate a random vector + if v0 is None: + u[:, 0] = rng.uniform(size=m) + if np.iscomplexobj(np.empty(0, dtype=typ)): # complex type + u[:, 0] += 1j * rng.uniform(size=m) + else: + try: + u[:, 0] = v0 + except ValueError: + raise ValueError(f"v0 must be of length {m}") + + # process options for the fit + if delta is None: + delta = np.sqrt(np.finfo(typ).eps) + if eta is None: + eta = np.finfo(typ).eps ** 0.75 + + if irl_mode: + doption = np.array((delta, eta, anorm, min_relgap), dtype=typ.lower()) + + # validate or find default shifts + if shifts is None: + shifts = kmax - k + if k > min(kmax - shifts, m, n): + raise ValueError('shifts must satisfy ' + 'k <= min(kmax-shifts, m, n)!') + elif shifts < 0: + raise ValueError('shifts must be >= 0!') + + else: + doption = np.array((delta, eta, anorm), dtype=typ.lower()) + + ioption = np.array((int(bool(cgs)), int(bool(elr))), dtype='i') + + # PROPACK uses a few LAPACK functions that require sufficiently large + # work arrays to utilize BLAS level 3 operations. In almost all relevant + # architectures, the blocksize is 32 or 64. We use 32 here to be on + # the conservative side. + NB = 32 + + # Determine lwork & liwork: + # the required lengths are specified in the PROPACK documentation + if compute_u or compute_v: + lwork = m + n + 5*kmax**2 + 9*kmax + 4 + lwork += max(3*kmax**2 + 4*kmax + 4, NB*max(m, n)) + liwork = 8*kmax + else: + lwork = m + n + 9*kmax + 2*kmax**2 + 4 + max(m + n, 4*kmax + 4) + liwork = 2*kmax + 2 + work = np.empty(lwork, dtype=typ.lower()) + iwork = np.empty(liwork, dtype=np.int32) + + # dummy arguments: these are passed to aprod, and not used in this wrapper + dparm = np.empty(1, dtype=typ.lower()) + iparm = np.empty(1, dtype=np.int32) + + if typ.isupper(): + zwork = np.empty(m + n + kmax, dtype=typ) + works = work, zwork, iwork + else: + works = work, iwork + + # Generate the seed for the PROPACK random float generator. + rng_state = rng.integers(low=0, high=np.iinfo(np.int64).max, + size=4, dtype=np.uint64) + + if irl_mode: + info = lansvd_irl(_which_converter[which], jobu, + jobv, m, n, shifts, k, maxiter, tol, + aprod, u, sigma, bnd, v, *works, doption, + ioption, dparm, iparm, rng_state) + else: + info = lansvd(jobu, jobv, m, n, k, kmax, tol, aprod, u, sigma, bnd, v, + *works, doption, ioption, dparm, iparm, rng_state) + + if info > 0: + raise LinAlgError( + f"An invariant subspace of dimension {info} was found.") + elif info < 0: + raise LinAlgError( + f"k={k} singular triplets did not converge within " + f"kmax={kmax} iterations") + + # info == 0: The K largest (or smallest) singular triplets were computed + # successfully! + + return u[:, :k], sigma, v[:, :k].conj().T, bnd diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/dsolve.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/dsolve.py new file mode 100644 index 0000000000000000000000000000000000000000..45139f6b280d047386652577d9e1c8d2aaeb7033 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/dsolve.py @@ -0,0 +1,22 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.sparse.linalg` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + + +__all__ = [ # noqa: F822 + 'MatrixRankWarning', 'SuperLU', 'factorized', + 'spilu', 'splu', 'spsolve', + 'spsolve_triangular', 'use_solver', 'test' +] + + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="sparse.linalg", module="dsolve", + private_modules=["_dsolve"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/eigen.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/eigen.py new file mode 100644 index 0000000000000000000000000000000000000000..588986d6650aad334e6a9a682ed76cef94295298 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/eigen.py @@ -0,0 +1,21 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.sparse.linalg` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + + +__all__ = [ # noqa: F822 + 'ArpackError', 'ArpackNoConvergence', 'ArpackError', + 'eigs', 'eigsh', 'lobpcg', 'svds', 'test' +] + + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="sparse.linalg", module="eigen", + private_modules=["_eigen"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/interface.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/interface.py new file mode 100644 index 0000000000000000000000000000000000000000..24f40f185b1328b16e7e239e5a165cc6b1ed4317 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/interface.py @@ -0,0 +1,20 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.sparse.linalg` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + + +__all__ = [ # noqa: F822 + 'LinearOperator', 'aslinearoperator', +] + + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="sparse.linalg", module="interface", + private_modules=["_interface"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/isolve.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/isolve.py new file mode 100644 index 0000000000000000000000000000000000000000..e032ddd9c673be3bc8790adad3bdae1839127050 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/isolve.py @@ -0,0 +1,22 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.sparse.linalg` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + + +__all__ = [ # noqa: F822 + 'bicg', 'bicgstab', 'cg', 'cgs', 'gcrotmk', 'gmres', + 'lgmres', 'lsmr', 'lsqr', + 'minres', 'qmr', 'tfqmr', 'test' +] + + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="sparse.linalg", module="isolve", + private_modules=["_isolve"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/matfuncs.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/matfuncs.py new file mode 100644 index 0000000000000000000000000000000000000000..8ed877ff1aa6f5a5466ce94729b9225dcce37b36 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/matfuncs.py @@ -0,0 +1,18 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.sparse.linalg` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + + +__all__ = ["expm", "inv", "spsolve", "LinearOperator"] # noqa: F822 + + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="sparse.linalg", module="matfuncs", + private_modules=["_matfuncs"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1c69f1050d196b5db5af8ae4f25bde10939bd55d Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_expm_multiply.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_expm_multiply.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd12909c1ef7c7f1d1a457d3acc0484b8cb896c2 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_expm_multiply.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_funm_multiply_krylov.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_funm_multiply_krylov.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3a149f4bcd99e1a37711999a127321ecc1d639b3 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_funm_multiply_krylov.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_interface.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_interface.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1a117cc3cce0c662c956e26a0e759a11fb2b1ac8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_interface.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_matfuncs.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_matfuncs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d50051f3aa370ddfcb389858fba331bd76c4a5c7 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_matfuncs.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_norm.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_norm.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4d51c1080adc840d24d0a63f643b7c74e4a01145 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_norm.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_onenormest.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_onenormest.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..30e3fc6b77913805b0b66d2203980a5124c90855 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_onenormest.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_propack.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_propack.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..699748aad211b6691012baab82e39c66438cd716 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_propack.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_pydata_sparse.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_pydata_sparse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..49f4561980a42ae30d66de924022f8da4eb9b5fd Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_pydata_sparse.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_special_sparse_arrays.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_special_sparse_arrays.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5f825059b23e75e0c74d7194d4f4789d03322842 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/__pycache__/test_special_sparse_arrays.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_expm_multiply.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_expm_multiply.py new file mode 100644 index 0000000000000000000000000000000000000000..a2b5d6d50e32feb532c8449c9ff463df0ed000b9 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_expm_multiply.py @@ -0,0 +1,370 @@ +"""Test functions for the sparse.linalg._expm_multiply module.""" +import warnings + +from functools import partial +from itertools import product + +import numpy as np +import pytest +from numpy.testing import (assert_allclose, assert_, assert_equal) +from scipy.sparse import SparseEfficiencyWarning +import scipy.sparse +from scipy.sparse.linalg import aslinearoperator +import scipy.linalg +from scipy.sparse.linalg import expm as sp_expm +from scipy.sparse.linalg._expm_multiply import (_theta, _compute_p_max, + _onenormest_matrix_power, expm_multiply, _expm_multiply_simple, + _expm_multiply_interval) +from scipy._lib._util import np_long + + +IMPRECISE = {np.single, np.csingle} +REAL_DTYPES = (np.intc, np_long, np.longlong, + np.float32, np.float64, np.longdouble) +COMPLEX_DTYPES = (np.complex64, np.complex128, np.clongdouble) +DTYPES = REAL_DTYPES + COMPLEX_DTYPES + + +def estimated_warns(): + """If trace is estimated, it should warn. + + We warn that estimation of trace might impact performance. + All result have to be correct nevertheless! + """ + return pytest.warns(UserWarning, match="Trace of LinearOperator not available") + + +def less_than_or_close(a, b): + return np.allclose(a, b) or (a < b) + + +class TestExpmActionSimple: + """ + These tests do not consider the case of multiple time steps in one call. + """ + + def test_theta_monotonicity(self): + pairs = sorted(_theta.items()) + for (m_a, theta_a), (m_b, theta_b) in zip(pairs[:-1], pairs[1:]): + assert_(theta_a < theta_b) + + def test_p_max_default(self): + m_max = 55 + expected_p_max = 8 + observed_p_max = _compute_p_max(m_max) + assert_equal(observed_p_max, expected_p_max) + + def test_p_max_range(self): + for m_max in range(1, 55+1): + p_max = _compute_p_max(m_max) + assert_(p_max*(p_max - 1) <= m_max + 1) + p_too_big = p_max + 1 + assert_(p_too_big*(p_too_big - 1) > m_max + 1) + + def test_onenormest_matrix_power(self): + rng = np.random.RandomState(1234) + n = 40 + nsamples = 10 + for i in range(nsamples): + A = scipy.linalg.inv(rng.randn(n, n)) + for p in range(4): + if not p: + M = np.identity(n) + else: + M = np.dot(M, A) + estimated = _onenormest_matrix_power(A, p) + exact = np.linalg.norm(M, 1) + assert_(less_than_or_close(estimated, exact)) + assert_(less_than_or_close(exact, 3*estimated)) + + def test_expm_multiply(self): + rng = np.random.default_rng(1234) + n = 40 + k = 3 + nsamples = 10 + for i in range(nsamples): + A = scipy.linalg.inv(rng.standard_normal((n, n))) + B = rng.standard_normal((n, k)) + observed = expm_multiply(A, B) + expected = np.dot(sp_expm(A), B) + assert_allclose(observed, expected) + with estimated_warns(): + observed = expm_multiply(aslinearoperator(A), B) + assert_allclose(observed, expected) + traceA = np.trace(A) + observed = expm_multiply(aslinearoperator(A), B, traceA=traceA) + assert_allclose(observed, expected) + + def test_matrix_vector_multiply(self): + rng = np.random.default_rng(1234) + n = 40 + nsamples = 10 + for i in range(nsamples): + A = scipy.linalg.inv(rng.standard_normal((n, n))) + v = rng.standard_normal(n) + observed = expm_multiply(A, v) + expected = np.dot(sp_expm(A), v) + assert_allclose(observed, expected) + with estimated_warns(): + observed = expm_multiply(aslinearoperator(A), v) + assert_allclose(observed, expected) + + def test_scaled_expm_multiply(self): + rng = np.random.default_rng(1234) + n = 40 + k = 3 + nsamples = 10 + for i, t in product(range(nsamples), [0.2, 1.0, 1.5]): + with np.errstate(invalid='ignore'): + A = scipy.linalg.inv(rng.standard_normal((n, n))) + B = rng.standard_normal((n, k)) + observed = _expm_multiply_simple(A, B, t=t) + expected = np.dot(sp_expm(t*A), B) + assert_allclose(observed, expected) + with estimated_warns(): + observed = _expm_multiply_simple(aslinearoperator(A), B, t=t) + assert_allclose(observed, expected) + + def test_scaled_expm_multiply_single_timepoint(self): + rng = np.random.default_rng(1234) + t = 0.1 + n = 5 + k = 2 + A = rng.standard_normal((n, n)) + B = rng.standard_normal((n, k)) + observed = _expm_multiply_simple(A, B, t=t) + expected = sp_expm(t*A).dot(B) + assert_allclose(observed, expected) + with estimated_warns(): + observed = _expm_multiply_simple(aslinearoperator(A), B, t=t) + assert_allclose(observed, expected) + + def test_sparse_expm_multiply(self): + rng = np.random.default_rng(1234) + n = 40 + k = 3 + nsamples = 10 + for i in range(nsamples): + A = scipy.sparse.random_array((n, n), density=0.05, rng=rng) + B = rng.standard_normal((n, k)) + observed = expm_multiply(A, B) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "splu converted its input to CSC format", + SparseEfficiencyWarning, + ) + warnings.filterwarnings( + "ignore", + "spsolve is more efficient when sparse b is in the " + "CSC matrix format", + SparseEfficiencyWarning, + ) + expected = sp_expm(A).dot(B) + assert_allclose(observed, expected) + with estimated_warns(): + observed = expm_multiply(aslinearoperator(A), B) + assert_allclose(observed, expected) + + def test_complex(self): + A = np.array([ + [1j, 1j], + [0, 1j]], dtype=complex) + B = np.array([1j, 1j]) + observed = expm_multiply(A, B) + expected = np.array([ + 1j * np.exp(1j) + 1j * (1j*np.cos(1) - np.sin(1)), + 1j * np.exp(1j)], dtype=complex) + assert_allclose(observed, expected) + with estimated_warns(): + observed = expm_multiply(aslinearoperator(A), B) + assert_allclose(observed, expected) + + +class TestExpmActionInterval: + + @pytest.mark.fail_slow(20) + def test_sparse_expm_multiply_interval(self): + rng = np.random.default_rng(1234) + start = 0.1 + stop = 3.2 + n = 40 + k = 3 + endpoint = True + for num in (14, 13, 2): + A = scipy.sparse.random_array((n, n), density=0.05, rng=rng) + B = rng.standard_normal((n, k)) + v = rng.standard_normal((n,)) + for target in (B, v): + X = expm_multiply(A, target, start=start, stop=stop, + num=num, endpoint=endpoint) + samples = np.linspace(start=start, stop=stop, + num=num, endpoint=endpoint) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "splu converted its input to CSC format", + SparseEfficiencyWarning, + ) + warnings.filterwarnings( + "ignore", + "spsolve is more efficient when sparse b is in" + " the CSC matrix format", + SparseEfficiencyWarning, + ) + for solution, t in zip(X, samples): + assert_allclose(solution, sp_expm(t*A).dot(target)) + + @pytest.mark.fail_slow(20) + def test_expm_multiply_interval_vector(self): + rng = np.random.default_rng(1234) + interval = {'start': 0.1, 'stop': 3.2, 'endpoint': True} + for num, n in product([14, 13, 2], [1, 2, 5, 20, 40]): + A = scipy.linalg.inv(rng.standard_normal((n, n))) + v = rng.standard_normal(n) + samples = np.linspace(num=num, **interval) + X = expm_multiply(A, v, num=num, **interval) + for solution, t in zip(X, samples): + assert_allclose(solution, sp_expm(t*A).dot(v)) + # test for linear operator with unknown trace -> estimate trace + with estimated_warns(): + Xguess = expm_multiply(aslinearoperator(A), v, num=num, **interval) + # test for linear operator with given trace + Xgiven = expm_multiply(aslinearoperator(A), v, num=num, **interval, + traceA=np.trace(A)) + # test robustness for linear operator with wrong trace + Xwrong = expm_multiply(aslinearoperator(A), v, num=num, **interval, + traceA=np.trace(A)*5) + for sol_guess, sol_given, sol_wrong, t in zip(Xguess, Xgiven, + Xwrong, samples): + correct = sp_expm(t*A).dot(v) + assert_allclose(sol_guess, correct) + assert_allclose(sol_given, correct) + assert_allclose(sol_wrong, correct) + + @pytest.mark.fail_slow(20) + def test_expm_multiply_interval_matrix(self): + rng = np.random.default_rng(1234) + interval = {'start': 0.1, 'stop': 3.2, 'endpoint': True} + for num, n, k in product([14, 13, 2], [1, 2, 5, 20, 40], [1, 2]): + A = scipy.linalg.inv(rng.standard_normal((n, n))) + B = rng.standard_normal((n, k)) + samples = np.linspace(num=num, **interval) + X = expm_multiply(A, B, num=num, **interval) + for solution, t in zip(X, samples): + assert_allclose(solution, sp_expm(t*A).dot(B)) + with estimated_warns(): + X = expm_multiply(aslinearoperator(A), B, num=num, **interval) + for solution, t in zip(X, samples): + assert_allclose(solution, sp_expm(t*A).dot(B)) + + def test_sparse_expm_multiply_interval_dtypes(self): + # Test A & B int + A = scipy.sparse.diags_array(np.arange(5),format='csr', dtype=int) + B = np.ones(5, dtype=int) + Aexpm = scipy.sparse.diags_array(np.exp(np.arange(5)),format='csr') + BI = np.identity(5, dtype=int) + BI_sparse = scipy.sparse.csr_array(BI) + assert_allclose(expm_multiply(A,B,0,1)[-1], Aexpm.dot(B)) + assert_allclose(np.diag(expm_multiply(A, BI_sparse, 0, 1)[-1]), Aexpm.dot(B)) + + # Test A complex, B int + A = scipy.sparse.diags_array(-1j*np.arange(5),format='csr', dtype=complex) + B = np.ones(5, dtype=int) + Aexpm = scipy.sparse.diags_array(np.exp(-1j*np.arange(5)),format='csr') + assert_allclose(expm_multiply(A,B,0,1)[-1], Aexpm.dot(B)) + assert_allclose(np.diag(expm_multiply(A, BI_sparse, 0, 1)[-1]), Aexpm.dot(B)) + + # Test A int, B complex + A = scipy.sparse.diags_array(np.arange(5),format='csr', dtype=int) + B = np.full(5, 1j, dtype=complex) + Aexpm = scipy.sparse.diags_array(np.exp(np.arange(5)),format='csr') + assert_allclose(expm_multiply(A,B,0,1)[-1], Aexpm.dot(B)) + BI = np.identity(5, dtype=complex)*1j + assert_allclose( + np.diag(expm_multiply(A, scipy.sparse.csr_array(BI), 0, 1)[-1]), + Aexpm.dot(B) + ) + + def test_expm_multiply_interval_status_0(self): + self._help_test_specific_expm_interval_status(0) + + def test_expm_multiply_interval_status_1(self): + self._help_test_specific_expm_interval_status(1) + + def test_expm_multiply_interval_status_2(self): + self._help_test_specific_expm_interval_status(2) + + def _help_test_specific_expm_interval_status(self, target_status): + rng = np.random.RandomState(1234) + start = 0.1 + stop = 3.2 + num = 13 + endpoint = True + n = 5 + k = 2 + nrepeats = 10 + nsuccesses = 0 + for num in [14, 13, 2] * nrepeats: + A = rng.randn(n, n) + B = rng.randn(n, k) + status = _expm_multiply_interval(A, B, + start=start, stop=stop, num=num, endpoint=endpoint, + status_only=True) + if status == target_status: + X, status = _expm_multiply_interval(A, B, + start=start, stop=stop, num=num, endpoint=endpoint, + status_only=False) + assert_equal(X.shape, (num, n, k)) + samples = np.linspace(start=start, stop=stop, + num=num, endpoint=endpoint) + for solution, t in zip(X, samples): + assert_allclose(solution, sp_expm(t*A).dot(B)) + nsuccesses += 1 + if not nsuccesses: + msg = 'failed to find a status-' + str(target_status) + ' interval' + raise Exception(msg) + + +@pytest.mark.parametrize("dtype_a", DTYPES) +@pytest.mark.parametrize("dtype_b", DTYPES) +@pytest.mark.parametrize("b_is_matrix", [False, True]) +def test_expm_multiply_dtype(dtype_a, dtype_b, b_is_matrix): + """Make sure `expm_multiply` handles all numerical dtypes correctly.""" + assert_allclose_ = (partial(assert_allclose, rtol=1.8e-3, atol=1e-5) + if {dtype_a, dtype_b} & IMPRECISE else assert_allclose) + rng = np.random.default_rng(1234) + # test data + n = 7 + b_shape = (n, 3) if b_is_matrix else (n, ) + if dtype_a in REAL_DTYPES: + A = scipy.linalg.inv(rng.random([n, n])).astype(dtype_a) + else: + A = scipy.linalg.inv( + rng.random([n, n]) + 1j*rng.random([n, n]) + ).astype(dtype_a) + if dtype_b in REAL_DTYPES: + B = (2*rng.random(b_shape)).astype(dtype_b) + else: + B = (rng.random(b_shape) + 1j*rng.random(b_shape)).astype(dtype_b) + + # single application + sol_mat = expm_multiply(A, B) + with estimated_warns(): + sol_op = expm_multiply(aslinearoperator(A), B) + direct_sol = np.dot(sp_expm(A), B) + assert_allclose_(sol_mat, direct_sol) + assert_allclose_(sol_op, direct_sol) + sol_op = expm_multiply(aslinearoperator(A), B, traceA=np.trace(A)) + assert_allclose_(sol_op, direct_sol) + + # for time points + interval = {'start': 0.1, 'stop': 3.2, 'num': 13, 'endpoint': True} + samples = np.linspace(**interval) + X_mat = expm_multiply(A, B, **interval) + with estimated_warns(): + X_op = expm_multiply(aslinearoperator(A), B, **interval) + for sol_mat, sol_op, t in zip(X_mat, X_op, samples): + direct_sol = sp_expm(t*A).dot(B) + assert_allclose_(sol_mat, direct_sol) + assert_allclose_(sol_op, direct_sol) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_funm_multiply_krylov.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_funm_multiply_krylov.py new file mode 100644 index 0000000000000000000000000000000000000000..7da2653a95b2ae57838eef980fb17b47013b9c96 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_funm_multiply_krylov.py @@ -0,0 +1,185 @@ +"""Test functions for the sparse.linalg._krylov_funm module.""" +from functools import partial + +import numpy as np +import pytest +from numpy.testing import (assert_allclose) +import scipy.sparse +import scipy.linalg +from scipy.sparse.linalg import aslinearoperator +from scipy.linalg import (expm, cosm, coshm, sinm, sinhm) + +from scipy.sparse.linalg._funm_multiply_krylov import funm_multiply_krylov + +REAL_DTYPES = (np.float32, np.float64) +COMPLEX_DTYPES = (np.complex64, np.complex128) +DTYPES = REAL_DTYPES + COMPLEX_DTYPES + +# This the phi_1 function from exponential integrators: phi_1 (z) = (e^z - 1) / z +def custom(X): + return scipy.linalg.solve(X, expm(X) - np.eye(X.shape[0])) + +FUNCS = (expm, cosm, coshm, sinm, sinhm, custom) + +class TestKrylovFunmv: + + def test_krylov_funm_zero_vector(self): + n = 20 + A = np.zeros((n, n)) + b = np.zeros(n) + observed = funm_multiply_krylov(expm, A, b) + expected = np.zeros(n) + assert_allclose(observed, expected) + + @pytest.mark.parametrize("f", FUNCS) + def test_funm_multiply_krylov_nonhermitian_dense(self, f): + rng = np.random.default_rng(1738151906092735) + n = 60 + nsamples = 10 + + for i in range(nsamples): + A = rng.standard_normal((n, n)) + b = rng.standard_normal(n) + + fA = f(A) + expected = fA @ b + observed = funm_multiply_krylov(f, A, b) + assert_allclose(observed, expected, rtol = 1E-6, atol = 1E-8) + observed = funm_multiply_krylov(f, aslinearoperator(A), b) + assert_allclose(observed, expected, rtol = 1E-6, atol = 1E-8) + + @pytest.mark.parametrize("f", FUNCS) + def test_funm_multiply_krylov_nonhermitian_sparse(self, f, num_parallel_threads): + + rng = np.random.default_rng(1738151906092735) + n = 100 + nsamples = 1 + 9 // num_parallel_threads # Very slow otherwise + + for i in range(nsamples): + D = scipy.sparse.diags(rng.standard_normal(n)) + A = scipy.sparse.random_array((n, n), density = 0.01, rng = rng) + D + denseA = A.todense() + b = rng.standard_normal(n) + + fA = f(denseA) + expected = fA @ b + observed = funm_multiply_krylov(f, A, b) + assert_allclose(observed, expected, rtol = 1E-6, atol = 1E-8) + observed = funm_multiply_krylov(f, aslinearoperator(A), b) + assert_allclose(observed, expected, rtol = 1E-6, atol = 1E-8) + + @pytest.mark.parametrize("f", FUNCS) + def test_funm_multiply_krylov_hermitian_dense(self, f): + + rng = np.random.default_rng(1738151906092735) + n = 60 + nsamples = 10 + + for i in range(nsamples): + R = np.triu(rng.standard_normal((n, n))) + A = R.T + R + b = rng.standard_normal(n) + + fA = f(A) + expected = fA @ b + observed = funm_multiply_krylov(f, A, b, assume_a = 'her') + assert_allclose(observed, expected, rtol = 1E-6, atol = 1E-8) + observed = funm_multiply_krylov(f, aslinearoperator(A), b, assume_a = 'her') + assert_allclose(observed, expected, rtol = 1E-6, atol = 1E-8) + + @pytest.mark.parametrize("f", FUNCS) + def test_funm_multiply_krylov_hermitian_sparse(self, f, num_parallel_threads): + + rng = np.random.default_rng(1738151906092735) + n = 100 + nsamples = 1 + 9 // num_parallel_threads # Very slow otherwise + + for i in range(nsamples): + D = scipy.sparse.diags(rng.standard_normal(n)) + A = scipy.sparse.random_array((n, n), density = 0.01, rng = rng) + R = scipy.sparse.triu(A) + A = R + R.T + D + denseA = A.todense() + b = rng.standard_normal(n) + + fA = f(denseA) + expected = fA @ b + observed = funm_multiply_krylov(f, A, b, assume_a = 'her') + assert_allclose(observed, expected, rtol = 1E-6, atol = 1E-8) + + observed = funm_multiply_krylov(f, aslinearoperator(A), b, assume_a = 'her') + assert_allclose(observed, expected, rtol = 1E-6, atol = 1E-8) + + def test_funm_multiply_krylov_breakdown(self): + rng = np.random.default_rng(1738151906092735) + + # From test_iterative + A = np.array([[0, 0, 0, 0, 0, 1, -1, -0, -0, -0, -0], + [0, 0, 0, 0, 0, 2, -0, -1, -0, -0, -0], + [0, 0, 0, 0, 0, 2, -0, -0, -1, -0, -0], + [0, 0, 0, 0, 0, 2, -0, -0, -0, -1, -0], + [0, 0, 0, 0, 0, 1, -0, -0, -0, -0, -1], + [1, 2, 2, 2, 1, 0, -0, -0, -0, -0, -0], + [-1, 0, 0, 0, 0, 0, -1, -0, -0, -0, -0], + [0, -1, 0, 0, 0, 0, -0, -1, -0, -0, -0], + [0, 0, -1, 0, 0, 0, -0, -0, -1, -0, -0], + [0, 0, 0, -1, 0, 0, -0, -0, -0, -1, -0], + [0, 0, 0, 0, -1, 0, -0, -0, -0, -0, -1]], dtype = float) + b = rng.standard_normal(A.shape[0]) + + fA = expm(A) + expected = fA @ b + observed = funm_multiply_krylov(expm, A, b, restart_every_m = 40) + assert_allclose(observed, expected) + + def test_funm_multiply_krylov_invalid_input(self): + A = np.array([[1, 2], [3, 4]]) # Non-hermitian matrix + b = np.array([1.0, 2.0]) # Ensure 'b' is a 1D array of floats + + # Test for invalid 'b' (not 1D) + b_invalid = np.array([[1.0], [2.0]]) # 2D array + with pytest.raises(ValueError, + match="argument 'b' must be a 1D array."): + funm_multiply_krylov(np.exp, A, b_invalid) + + # Test for invalid restart parameter + with pytest.raises(ValueError, + match="argument 'restart_every_m' must be positive."): + funm_multiply_krylov(np.exp, A, b, restart_every_m=0) + + # Test for invalid max_restarts + with pytest.raises(ValueError, + match="argument 'max_restarts' must be positive."): + funm_multiply_krylov(np.exp, A, b, max_restarts=0) + + # Test for invalid 'assume_a' string + with pytest.raises(ValueError, + match="is not a recognized matrix structure"): + funm_multiply_krylov(np.exp, A, b, assume_a='invalid') + + +@pytest.mark.parametrize("dtype_a", DTYPES) +@pytest.mark.parametrize("dtype_b", DTYPES) +def test_funm_multiply_krylov_types(dtype_a, dtype_b): + assert_allclose_ = (partial(assert_allclose, rtol = 1.8e-3, atol = 1e-5) + if {dtype_a, dtype_b} else assert_allclose) + + rng = np.random.default_rng(1738151906092735) + n = 50 + + if dtype_a in REAL_DTYPES: + A = rng.random([n, n]).astype(dtype_a) + else: + A = (rng.random([n, n]) + 1j * rng.random([n, n])).astype(dtype_a) + + if dtype_b in REAL_DTYPES: + b = (2 * rng.random(n)).astype(dtype_b) + else: + b = (rng.random(n) + 1j * rng.random(n)).astype(dtype_b) + + expA = expm(A) + expected = expA @ b + observed = funm_multiply_krylov(expm, A, b) + assert_allclose_(observed, expected) + observed = funm_multiply_krylov(expm, aslinearoperator(A), b) + assert_allclose_(observed, expected) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_interface.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_interface.py new file mode 100644 index 0000000000000000000000000000000000000000..bb9eca66e77128478100f64589f4f87f10bc8bc5 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_interface.py @@ -0,0 +1,560 @@ +"""Test functions for the sparse.linalg._interface module +""" + +from functools import partial +from itertools import product +import operator +import pytest +from pytest import raises as assert_raises, warns +from numpy.testing import assert_, assert_equal + +import numpy as np +import scipy.sparse as sparse + +import scipy.sparse.linalg._interface as interface +from scipy.sparse._sputils import matrix +from scipy._lib._gcutils import assert_deallocated, IS_PYPY + + +class TestLinearOperator: + def setup_method(self): + self.A = np.array([[1,2,3], + [4,5,6]]) + self.B = np.array([[1,2], + [3,4], + [5,6]]) + self.C = np.array([[1,2], + [3,4]]) + + def test_matvec(self): + def get_matvecs(A): + return [{ + 'shape': A.shape, + 'matvec': lambda x: np.dot(A, x).reshape(A.shape[0]), + 'rmatvec': lambda x: np.dot(A.T.conj(), + x).reshape(A.shape[1]) + }, + { + 'shape': A.shape, + 'matvec': lambda x: np.dot(A, x), + 'rmatvec': lambda x: np.dot(A.T.conj(), x), + 'rmatmat': lambda x: np.dot(A.T.conj(), x), + 'matmat': lambda x: np.dot(A, x) + }] + + for matvecs in get_matvecs(self.A): + A = interface.LinearOperator(**matvecs) + + assert_(A.args == ()) + + assert_equal(A.matvec(np.array([1,2,3])), [14,32]) + assert_equal(A.matvec(np.array([[1],[2],[3]])), [[14],[32]]) + assert_equal(A @ np.array([1,2,3]), [14,32]) + assert_equal(A @ np.array([[1],[2],[3]]), [[14],[32]]) + assert_equal(A.dot(np.array([1,2,3])), [14,32]) + assert_equal(A.dot(np.array([[1],[2],[3]])), [[14],[32]]) + + assert_equal(A.matvec(matrix([[1],[2],[3]])), [[14],[32]]) + assert_equal(A @ matrix([[1],[2],[3]]), [[14],[32]]) + assert_equal(A.dot(matrix([[1],[2],[3]])), [[14],[32]]) + + assert_equal((2*A)@[1,1,1], [12,30]) + assert_equal((2 * A).rmatvec([1, 1]), [10, 14, 18]) + assert_equal((2*A).H.matvec([1,1]), [10, 14, 18]) + assert_equal((2*A).adjoint().matvec([1,1]), [10, 14, 18]) + assert_equal((2*A)@[[1],[1],[1]], [[12],[30]]) + assert_equal((2 * A).matmat([[1], [1], [1]]), [[12], [30]]) + assert_equal((A*2)@[1,1,1], [12,30]) + assert_equal((A*2)@[[1],[1],[1]], [[12],[30]]) + assert_equal((2j*A)@[1,1,1], [12j,30j]) + assert_equal((A+A)@[1,1,1], [12, 30]) + assert_equal((A + A).rmatvec([1, 1]), [10, 14, 18]) + assert_equal((A+A).H.matvec([1,1]), [10, 14, 18]) + assert_equal((A+A).adjoint().matvec([1,1]), [10, 14, 18]) + assert_equal((A+A)@[[1],[1],[1]], [[12], [30]]) + assert_equal((A+A).matmat([[1],[1],[1]]), [[12], [30]]) + assert_equal((-A)@[1,1,1], [-6,-15]) + assert_equal((-A)@[[1],[1],[1]], [[-6],[-15]]) + assert_equal((A-A)@[1,1,1], [0,0]) + assert_equal((A - A) @ [[1], [1], [1]], [[0], [0]]) + + X = np.array([[1, 2], [3, 4]]) + # A_asarray = np.array([[1, 2, 3], [4, 5, 6]]) + assert_equal((2 * A).rmatmat(X), np.dot((2 * self.A).T, X)) + assert_equal((A * 2).rmatmat(X), np.dot((self.A * 2).T, X)) + assert_equal((2j * A).rmatmat(X), + np.dot((2j * self.A).T.conj(), X)) + assert_equal((A * 2j).rmatmat(X), + np.dot((self.A * 2j).T.conj(), X)) + assert_equal((A + A).rmatmat(X), + np.dot((self.A + self.A).T, X)) + assert_equal((A + 2j * A).rmatmat(X), + np.dot((self.A + 2j * self.A).T.conj(), X)) + assert_equal((-A).rmatmat(X), np.dot((-self.A).T, X)) + assert_equal((A - A).rmatmat(X), + np.dot((self.A - self.A).T, X)) + assert_equal((2j * A).rmatmat(2j * X), + np.dot((2j * self.A).T.conj(), 2j * X)) + + z = A+A + assert_(len(z.args) == 2 and z.args[0] is A and z.args[1] is A) + z = 2*A + assert_(len(z.args) == 2 and z.args[0] is A and z.args[1] == 2) + + assert_(isinstance(A.matvec([1, 2, 3]), np.ndarray)) + assert_(isinstance(A.matvec(np.array([[1],[2],[3]])), np.ndarray)) + assert_(isinstance(A @ np.array([1,2,3]), np.ndarray)) + assert_(isinstance(A @ np.array([[1],[2],[3]]), np.ndarray)) + assert_(isinstance(A.dot(np.array([1,2,3])), np.ndarray)) + assert_(isinstance(A.dot(np.array([[1],[2],[3]])), np.ndarray)) + + assert_(isinstance(A.matvec(matrix([[1],[2],[3]])), np.ndarray)) + assert_(isinstance(A @ matrix([[1],[2],[3]]), np.ndarray)) + assert_(isinstance(A.dot(matrix([[1],[2],[3]])), np.ndarray)) + + assert_(isinstance(2*A, interface._ScaledLinearOperator)) + assert_(isinstance(2j*A, interface._ScaledLinearOperator)) + assert_(isinstance(A+A, interface._SumLinearOperator)) + assert_(isinstance(-A, interface._ScaledLinearOperator)) + assert_(isinstance(A-A, interface._SumLinearOperator)) + assert_(isinstance(A/2, interface._ScaledLinearOperator)) + assert_(isinstance(A/2j, interface._ScaledLinearOperator)) + assert_(((A * 3) / 3).args[0] is A) # check for simplification + + # Test that prefactor is of _ScaledLinearOperator is not mutated + # when the operator is multiplied by a number + result = A @ np.array([1, 2, 3]) + B = A * 3 + C = A / 5 + assert_equal(A @ np.array([1, 2, 3]), result) + + assert_((2j*A).dtype == np.complex128) + + # Test division by non-scalar + msg = "Can only divide a linear operator by a scalar." + with assert_raises(ValueError, match=msg): + A / np.array([1, 2]) + + assert_raises(ValueError, A.matvec, np.array([1,2])) + assert_raises(ValueError, A.matvec, np.array([1,2,3,4])) + assert_raises(ValueError, A.matvec, np.array([[1],[2]])) + assert_raises(ValueError, A.matvec, np.array([[1],[2],[3],[4]])) + + assert_raises(ValueError, lambda: A@A) + assert_raises(ValueError, lambda: A**2) + + for matvecsA, matvecsB in product(get_matvecs(self.A), + get_matvecs(self.B)): + A = interface.LinearOperator(**matvecsA) + B = interface.LinearOperator(**matvecsB) + # AtimesB = np.array([[22, 28], [49, 64]]) + AtimesB = self.A.dot(self.B) + X = np.array([[1, 2], [3, 4]]) + + assert_equal((A @ B).rmatmat(X), np.dot((AtimesB).T, X)) + assert_equal((2j * A @ B).rmatmat(X), + np.dot((2j * AtimesB).T.conj(), X)) + + assert_equal((A@B)@[1,1], [50,113]) + assert_equal((A@B)@[[1],[1]], [[50],[113]]) + assert_equal((A@B).matmat([[1],[1]]), [[50],[113]]) + + assert_equal((A @ B).rmatvec([1, 1]), [71, 92]) + assert_equal((A @ B).H.matvec([1, 1]), [71, 92]) + assert_equal((A @ B).adjoint().matvec([1, 1]), [71, 92]) + + assert_(isinstance(A@B, interface._ProductLinearOperator)) + + assert_raises(ValueError, lambda: A+B) + assert_raises(ValueError, lambda: A**2) + + z = A@B + assert_(len(z.args) == 2 and z.args[0] is A and z.args[1] is B) + + for matvecsC in get_matvecs(self.C): + C = interface.LinearOperator(**matvecsC) + X = np.array([[1, 2], [3, 4]]) + + assert_equal(C.rmatmat(X), np.dot((self.C).T, X)) + assert_equal((C**2).rmatmat(X), + np.dot((np.dot(self.C, self.C)).T, X)) + + assert_equal((C**2)@[1,1], [17,37]) + assert_equal((C**2).rmatvec([1, 1]), [22, 32]) + assert_equal((C**2).H.matvec([1, 1]), [22, 32]) + assert_equal((C**2).adjoint().matvec([1, 1]), [22, 32]) + assert_equal((C**2).matmat([[1],[1]]), [[17],[37]]) + + assert_(isinstance(C**2, interface._PowerLinearOperator)) + + def test_matmul(self): + D = {'shape': self.A.shape, + 'matvec': lambda x: np.dot(self.A, x).reshape(self.A.shape[0]), + 'rmatvec': lambda x: np.dot(self.A.T.conj(), + x).reshape(self.A.shape[1]), + 'rmatmat': lambda x: np.dot(self.A.T.conj(), x), + 'matmat': lambda x: np.dot(self.A, x)} + A = interface.LinearOperator(**D) + B = np.array([[1 + 1j, 2, 3], + [4, 5, 6], + [7, 8, 9]]) + b = B[0] + + assert_equal(operator.matmul(A, b), A * b) + assert_equal(operator.matmul(A, b.reshape(-1, 1)), A * b.reshape(-1, 1)) + assert_equal(operator.matmul(A, B), A @ B) + assert_equal(operator.matmul(b, A.H), b * A.H) + assert_equal(operator.matmul(b, A.adjoint()), b * A.adjoint()) + assert_equal(operator.matmul(b.reshape(1, -1), A.H), b.reshape(1, -1) * A.H) + assert_equal(operator.matmul(b.reshape(1, -1), A.adjoint()), + b.reshape(1, -1) * A.adjoint()) + assert_equal(operator.matmul(B, A.H), B @ A.H) + assert_equal(operator.matmul(B, A.adjoint()), B @ A.adjoint()) + assert_raises(ValueError, operator.matmul, A, 2) + assert_raises(ValueError, operator.matmul, 2, A) + + +class TestAsLinearOperator: + def setup_method(self): + self.cases = [] + + def make_cases(original, dtype): + cases = [] + + cases.append((matrix(original, dtype=dtype), original)) + cases.append((np.array(original, dtype=dtype), original)) + cases.append((sparse.csr_array(original, dtype=dtype), original)) + + # Test default implementations of _adjoint and _rmatvec, which + # refer to each other. + def mv(x, dtype): + y = original.dot(x) + if len(x.shape) == 2: + y = y.reshape(-1, 1) + return y + + def rmv(x, dtype): + return original.T.conj().dot(x) + + class BaseMatlike(interface.LinearOperator): + args = () + + def __init__(self, dtype): + self.dtype = np.dtype(dtype) + self.shape = original.shape + + def _matvec(self, x): + return mv(x, self.dtype) + + class HasRmatvec(BaseMatlike): + args = () + + def _rmatvec(self,x): + return rmv(x, self.dtype) + + class HasAdjoint(BaseMatlike): + args = () + + def _adjoint(self): + shape = self.shape[1], self.shape[0] + matvec = partial(rmv, dtype=self.dtype) + rmatvec = partial(mv, dtype=self.dtype) + return interface.LinearOperator(matvec=matvec, + rmatvec=rmatvec, + dtype=self.dtype, + shape=shape) + + class HasRmatmat(HasRmatvec): + def _matmat(self, x): + return original.dot(x) + + def _rmatmat(self, x): + return original.T.conj().dot(x) + + cases.append((HasRmatvec(dtype), original)) + cases.append((HasAdjoint(dtype), original)) + cases.append((HasRmatmat(dtype), original)) + return cases + + original = np.array([[1,2,3], [4,5,6]]) + self.cases += make_cases(original, np.int32) + self.cases += make_cases(original, np.float32) + self.cases += make_cases(original, np.float64) + self.cases += [(interface.aslinearoperator(M).T, A.T) + for M, A in make_cases(original.T, np.float64)] + self.cases += [(interface.aslinearoperator(M).H, A.T.conj()) + for M, A in make_cases(original.T, np.float64)] + self.cases += [(interface.aslinearoperator(M).adjoint(), A.T.conj()) + for M, A in make_cases(original.T, np.float64)] + + original = np.array([[1, 2j, 3j], [4j, 5j, 6]]) + self.cases += make_cases(original, np.complex128) + self.cases += [(interface.aslinearoperator(M).T, A.T) + for M, A in make_cases(original.T, np.complex128)] + self.cases += [(interface.aslinearoperator(M).H, A.T.conj()) + for M, A in make_cases(original.T, np.complex128)] + self.cases += [(interface.aslinearoperator(M).adjoint(), A.T.conj()) + for M, A in make_cases(original.T, np.complex128)] + + def test_basic(self): + + for M, A_array in self.cases: + A = interface.aslinearoperator(M) + M,N = A.shape + + xs = [np.array([1, 2, 3]), + np.array([[1], [2], [3]])] + ys = [np.array([1, 2]), np.array([[1], [2]])] + + if A.dtype == np.complex128: + xs += [np.array([1, 2j, 3j]), + np.array([[1], [2j], [3j]])] + ys += [np.array([1, 2j]), np.array([[1], [2j]])] + + x2 = np.array([[1, 4], [2, 5], [3, 6]]) + + for x in xs: + assert_equal(A.matvec(x), A_array.dot(x)) + assert_equal(A @ x, A_array.dot(x)) + + assert_equal(A.matmat(x2), A_array.dot(x2)) + assert_equal(A @ x2, A_array.dot(x2)) + + for y in ys: + assert_equal(A.rmatvec(y), A_array.T.conj().dot(y)) + assert_equal(A.T.matvec(y), A_array.T.dot(y)) + assert_equal(A.H.matvec(y), A_array.T.conj().dot(y)) + assert_equal(A.adjoint().matvec(y), A_array.T.conj().dot(y)) + + for y in ys: + if y.ndim < 2: + continue + assert_equal(A.rmatmat(y), A_array.T.conj().dot(y)) + assert_equal(A.T.matmat(y), A_array.T.dot(y)) + assert_equal(A.H.matmat(y), A_array.T.conj().dot(y)) + assert_equal(A.adjoint().matmat(y), A_array.T.conj().dot(y)) + + if hasattr(M,'dtype'): + assert_equal(A.dtype, M.dtype) + + assert_(hasattr(A, 'args')) + + def test_dot(self): + + for M, A_array in self.cases: + A = interface.aslinearoperator(M) + M,N = A.shape + + x0 = np.array([1, 2, 3]) + x1 = np.array([[1], [2], [3]]) + x2 = np.array([[1, 4], [2, 5], [3, 6]]) + + assert_equal(A.dot(x0), A_array.dot(x0)) + assert_equal(A.dot(x1), A_array.dot(x1)) + assert_equal(A.dot(x2), A_array.dot(x2)) + + +def test_repr(): + A = interface.LinearOperator(shape=(1, 1), matvec=lambda x: 1) + repr_A = repr(A) + assert_('unspecified dtype' not in repr_A, repr_A) + + +def test_identity(): + ident = interface.IdentityOperator((3, 3)) + assert_equal(ident @ [1, 2, 3], [1, 2, 3]) + assert_equal(ident.dot(np.arange(9).reshape(3, 3)).ravel(), np.arange(9)) + + assert_raises(ValueError, ident.matvec, [1, 2, 3, 4]) + + +def test_attributes(): + A = interface.aslinearoperator(np.arange(16).reshape(4, 4)) + + def always_four_ones(x): + x = np.asarray(x) + assert_(x.shape == (3,) or x.shape == (3, 1)) + return np.ones(4) + + B = interface.LinearOperator(shape=(4, 3), matvec=always_four_ones) + + ops = [A, B, A * B, A @ B, A.H, A.adjoint(), A + A, B + B, A**4] + for op in ops: + assert_(hasattr(op, "dtype")) + assert_(hasattr(op, "shape")) + assert_(hasattr(op, "_matvec")) + +def matvec(x): + """ Needed for test_pickle as local functions are not pickleable """ + return np.zeros(3) + +def test_pickle(): + import pickle + + for protocol in range(pickle.HIGHEST_PROTOCOL + 1): + A = interface.LinearOperator((3, 3), matvec) + s = pickle.dumps(A, protocol=protocol) + B = pickle.loads(s) + + for k in A.__dict__: + assert_equal(getattr(A, k), getattr(B, k)) + + +def test_inheritance(): + class Empty(interface.LinearOperator): + pass + + with warns(RuntimeWarning, match="should implement at least"): + assert_raises(TypeError, Empty) + + class Identity(interface.LinearOperator): + def __init__(self, n): + super().__init__(dtype=None, shape=(n, n)) + + def _matvec(self, x): + return x + + id3 = Identity(3) + assert_equal(id3.matvec([1, 2, 3]), [1, 2, 3]) + assert_raises(NotImplementedError, id3.rmatvec, [4, 5, 6]) + + class MatmatOnly(interface.LinearOperator): + def __init__(self, A): + super().__init__(A.dtype, A.shape) + self.A = A + + def _matmat(self, x): + return self.A.dot(x) + + mm = MatmatOnly(np.random.randn(5, 3)) + assert_equal(mm.matvec(np.random.randn(3)).shape, (5,)) + +def test_dtypes_of_operator_sum(): + # gh-6078 + + mat_complex = np.random.rand(2,2) + 1j * np.random.rand(2,2) + mat_real = np.random.rand(2,2) + + complex_operator = interface.aslinearoperator(mat_complex) + real_operator = interface.aslinearoperator(mat_real) + + sum_complex = complex_operator + complex_operator + sum_real = real_operator + real_operator + + assert_equal(sum_real.dtype, np.float64) + assert_equal(sum_complex.dtype, np.complex128) + +def test_no_double_init(): + call_count = [0] + + def matvec(v): + call_count[0] += 1 + return v + + # It should call matvec exactly once (in order to determine the + # operator dtype) + interface.LinearOperator((2, 2), matvec=matvec) + assert_equal(call_count[0], 1) + +INT_DTYPES = (np.int8, np.int16, np.int32, np.int64) +REAL_DTYPES = (np.float32, np.float64, np.longdouble) +COMPLEX_DTYPES = (np.complex64, np.complex128, np.clongdouble) +INEXACTDTYPES = REAL_DTYPES + COMPLEX_DTYPES +ALLDTYPES = INT_DTYPES + INEXACTDTYPES + + +@pytest.mark.parametrize("test_dtype", ALLDTYPES) +def test_determine_lo_dtype_from_matvec(test_dtype): + # gh-19209 + scalar = np.array(1, dtype=test_dtype) + def mv(v): + return np.array([scalar * v[0], v[1]]) + + lo = interface.LinearOperator((2, 2), matvec=mv) + assert lo.dtype == np.dtype(test_dtype) + +def test_determine_lo_dtype_for_int(): + # gh-19209 + # test Python int larger than int8 max cast to some int + def mv(v): + return np.array([128 * v[0], v[1]]) + + lo = interface.LinearOperator((2, 2), matvec=mv) + assert lo.dtype in INT_DTYPES + +def test_adjoint_conjugate(): + X = np.array([[1j]]) + A = interface.aslinearoperator(X) + + B = 1j * A + Y = 1j * X + + v = np.array([1]) + + assert_equal(B.dot(v), Y.dot(v)) + assert_equal(B.H.dot(v), Y.T.conj().dot(v)) + assert_equal(B.adjoint().dot(v), Y.T.conj().dot(v)) + +def test_ndim(): + X = np.array([[1]]) + A = interface.aslinearoperator(X) + assert_equal(A.ndim, 2) + +def test_transpose_noconjugate(): + X = np.array([[1j]]) + A = interface.aslinearoperator(X) + + B = 1j * A + Y = 1j * X + + v = np.array([1]) + + assert_equal(B.dot(v), Y.dot(v)) + assert_equal(B.T.dot(v), Y.T.dot(v)) + +def test_transpose_multiplication(): + class MyMatrix(interface.LinearOperator): + def __init__(self, A): + super().__init__(A.dtype, A.shape) + self.A = A + def _matmat(self, other): return self.A @ other + def _rmatmat(self, other): return self.A.T @ other + + A = MyMatrix(np.array([[1, 2], [3, 4]])) + X = np.array([1, 2]) + B = np.array([[10, 20], [30, 40]]) + X2 = X.reshape(-1, 1) + Y = np.array([[1, 2], [3, 4]]) + + assert_equal(A @ B, Y @ B) + assert_equal(B.T @ A, B.T @ Y) + assert_equal(A.T @ B, Y.T @ B) + assert_equal(A @ X, Y @ X) + assert_equal(X.T @ A, X.T @ Y) + assert_equal(A.T @ X, Y.T @ X) + assert_equal(A @ X2, Y @ X2) + assert_equal(X2.T @ A, X2.T @ Y) + assert_equal(A.T @ X2, Y.T @ X2) + +def test_sparse_matmat_exception(): + A = interface.LinearOperator((2, 2), matvec=lambda x: x) + B = sparse.eye_array(2) + msg = "Unable to multiply a LinearOperator with a sparse matrix." + with assert_raises(TypeError, match=msg): + A @ B + with assert_raises(TypeError, match=msg): + B @ A + with assert_raises(ValueError): + A @ np.identity(4) + with assert_raises(ValueError): + np.identity(4) @ A + + +@pytest.mark.skipif(IS_PYPY, reason="Test not meaningful on PyPy") +def test_MatrixLinearOperator_refcycle(): + # gh-10634 + # Test that MatrixLinearOperator can be automatically garbage collected + A = np.eye(2) + with assert_deallocated(interface.MatrixLinearOperator, A) as op: + op.adjoint() + del op diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_matfuncs.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_matfuncs.py new file mode 100644 index 0000000000000000000000000000000000000000..d2aac18164f96062ef3b0b8f181a3357f4619d24 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_matfuncs.py @@ -0,0 +1,599 @@ +# +# Created by: Pearu Peterson, March 2002 +# +""" Test functions for scipy.linalg._matfuncs module + +""" +import math +import warnings + +import numpy as np +from numpy import array, eye, exp, random +from numpy.testing import ( + assert_allclose, assert_, assert_array_almost_equal, assert_equal, + assert_array_almost_equal_nulp) + +from scipy.sparse import csc_array, SparseEfficiencyWarning +from scipy.sparse._construct import eye_array +from scipy.sparse.linalg._matfuncs import (expm, _expm, + ProductOperator, MatrixPowerOperator, + _onenorm_matrix_power_nnm, matrix_power) +from scipy.sparse._sputils import matrix +from scipy.linalg import logm +from scipy.special import factorial, binom +import scipy.sparse +import scipy.sparse.linalg + + +def _burkardt_13_power(n, p): + """ + A helper function for testing matrix functions. + + Parameters + ---------- + n : integer greater than 1 + Order of the square matrix to be returned. + p : non-negative integer + Power of the matrix. + + Returns + ------- + out : ndarray representing a square matrix + A Forsythe matrix of order n, raised to the power p. + + """ + # Input validation. + if n != int(n) or n < 2: + raise ValueError('n must be an integer greater than 1') + n = int(n) + if p != int(p) or p < 0: + raise ValueError('p must be a non-negative integer') + p = int(p) + + # Construct the matrix explicitly. + a, b = divmod(p, n) + large = np.power(10.0, -n*a) + small = large * np.power(10.0, -n) + return np.diag([large]*(n-b), b) + np.diag([small]*b, b-n) + + +def test_onenorm_matrix_power_nnm(): + np.random.seed(1234) + for n in range(1, 5): + for p in range(5): + M = np.random.random((n, n)) + Mp = np.linalg.matrix_power(M, p) + observed = _onenorm_matrix_power_nnm(M, p) + expected = np.linalg.norm(Mp, 1) + assert_allclose(observed, expected) + +def test_matrix_power(): + np.random.seed(1234) + row, col = np.random.randint(0, 4, size=(2, 6)) + data = np.random.random(size=(6,)) + Amat = csc_array((data, (row, col)), shape=(4, 4)) + A = csc_array((data, (row, col)), shape=(4, 4)) + Adense = A.toarray() + for power in (2, 5, 6): + Apow = matrix_power(A, power).toarray() + Amat_pow = matrix_power(Amat, power).toarray() + Adense_pow = np.linalg.matrix_power(Adense, power) + assert_allclose(Apow, Adense_pow) + assert_allclose(Apow, Amat_pow) + + +class TestExpM: + def test_zero_ndarray(self): + a = array([[0.,0],[0,0]]) + assert_array_almost_equal(expm(a),[[1,0],[0,1]]) + + def test_zero_sparse(self): + a = csc_array([[0.,0],[0,0]]) + assert_array_almost_equal(expm(a).toarray(),[[1,0],[0,1]]) + + def test_zero_matrix(self): + a = matrix([[0.,0],[0,0]]) + assert_array_almost_equal(expm(a),[[1,0],[0,1]]) + + def test_misc_types(self): + A = expm(np.array([[1]])) + assert_allclose(expm(((1,),)), A) + assert_allclose(expm([[1]]), A) + assert_allclose(expm(matrix([[1]])), A) + assert_allclose(expm(np.array([[1]])), A) + assert_allclose(expm(csc_array([[1]])).toarray(), A) + B = expm(np.array([[1j]])) + assert_allclose(expm(((1j,),)), B) + assert_allclose(expm([[1j]]), B) + assert_allclose(expm(matrix([[1j]])), B) + assert_allclose(expm(csc_array([[1j]])).toarray(), B) + + def test_bidiagonal_sparse(self): + A = csc_array([ + [1, 3, 0], + [0, 1, 5], + [0, 0, 2]], dtype=float) + e1 = math.exp(1) + e2 = math.exp(2) + expected = np.array([ + [e1, 3*e1, 15*(e2 - 2*e1)], + [0, e1, 5*(e2 - e1)], + [0, 0, e2]], dtype=float) + observed = expm(A).toarray() + assert_array_almost_equal(observed, expected) + + def test_padecases_dtype_float(self): + for dtype in [np.float32, np.float64]: + for scale in [1e-2, 1e-1, 5e-1, 1, 10]: + A = scale * eye(3, dtype=dtype) + observed = expm(A) + expected = exp(scale, dtype=dtype) * eye(3, dtype=dtype) + assert_array_almost_equal_nulp(observed, expected, nulp=100) + + def test_padecases_dtype_complex(self): + for dtype in [np.complex64, np.complex128]: + for scale in [1e-2, 1e-1, 5e-1, 1, 10]: + A = scale * eye(3, dtype=dtype) + observed = expm(A) + expected = exp(scale, dtype=dtype) * eye(3, dtype=dtype) + assert_array_almost_equal_nulp(observed, expected, nulp=100) + + def test_padecases_dtype_sparse_float(self): + # float32 and complex64 lead to errors in spsolve/UMFpack + dtype = np.float64 + for scale in [1e-2, 1e-1, 5e-1, 1, 10]: + a = scale * eye_array(3, 3, dtype=dtype, format='csc') + e = exp(scale, dtype=dtype) * eye(3, dtype=dtype) + with warnings.catch_warnings(): + msg = "Changing the sparsity structure" + warnings.filterwarnings("ignore", msg, SparseEfficiencyWarning) + exact_onenorm = _expm(a, use_exact_onenorm=True).toarray() + inexact_onenorm = _expm(a, use_exact_onenorm=False).toarray() + assert_array_almost_equal_nulp(exact_onenorm, e, nulp=100) + assert_array_almost_equal_nulp(inexact_onenorm, e, nulp=100) + + def test_padecases_dtype_sparse_complex(self): + # float32 and complex64 lead to errors in spsolve/UMFpack + dtype = np.complex128 + for scale in [1e-2, 1e-1, 5e-1, 1, 10]: + a = scale * eye_array(3, 3, dtype=dtype, format='csc') + e = exp(scale) * eye(3, dtype=dtype) + with warnings.catch_warnings(): + msg = "Changing the sparsity structure" + warnings.filterwarnings("ignore", msg, SparseEfficiencyWarning) + assert_array_almost_equal_nulp(expm(a).toarray(), e, nulp=100) + + def test_logm_consistency(self): + random.seed(1234) + for dtype in [np.float64, np.complex128]: + for n in range(1, 10): + for scale in [1e-4, 1e-3, 1e-2, 1e-1, 1, 1e1, 1e2]: + # make logm(A) be of a given scale + A = (eye(n) + random.rand(n, n) * scale).astype(dtype) + if np.iscomplexobj(A): + A = A + 1j * random.rand(n, n) * scale + assert_array_almost_equal(expm(logm(A)), A) + + def test_integer_matrix(self): + Q = np.array([ + [-3, 1, 1, 1], + [1, -3, 1, 1], + [1, 1, -3, 1], + [1, 1, 1, -3]]) + assert_allclose(expm(Q), expm(1.0 * Q)) + + def test_integer_matrix_2(self): + # Check for integer overflows + Q = np.array([[-500, 500, 0, 0], + [0, -550, 360, 190], + [0, 630, -630, 0], + [0, 0, 0, 0]], dtype=np.int16) + assert_allclose(expm(Q), expm(1.0 * Q)) + + Q = csc_array(Q) + assert_allclose(expm(Q).toarray(), expm(1.0 * Q).toarray()) + + def test_triangularity_perturbation(self): + # Experiment (1) of + # Awad H. Al-Mohy and Nicholas J. Higham (2012) + # Improved Inverse Scaling and Squaring Algorithms + # for the Matrix Logarithm. + A = np.array([ + [3.2346e-1, 3e4, 3e4, 3e4], + [0, 3.0089e-1, 3e4, 3e4], + [0, 0, 3.221e-1, 3e4], + [0, 0, 0, 3.0744e-1]], + dtype=float) + A_logm = np.array([ + [-1.12867982029050462e+00, 9.61418377142025565e+04, + -4.52485573953179264e+09, 2.92496941103871812e+14], + [0.00000000000000000e+00, -1.20101052953082288e+00, + 9.63469687211303099e+04, -4.68104828911105442e+09], + [0.00000000000000000e+00, 0.00000000000000000e+00, + -1.13289322264498393e+00, 9.53249183094775653e+04], + [0.00000000000000000e+00, 0.00000000000000000e+00, + 0.00000000000000000e+00, -1.17947533272554850e+00]], + dtype=float) + assert_allclose(expm(A_logm), A, rtol=1e-4) + + # Perturb the upper triangular matrix by tiny amounts, + # so that it becomes technically not upper triangular. + random.seed(1234) + tiny = 1e-17 + A_logm_perturbed = A_logm.copy() + A_logm_perturbed[1, 0] = tiny + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", "Ill-conditioned.*", RuntimeWarning) + warnings.filterwarnings("ignore", "An ill-conditioned.*", RuntimeWarning) + + A_expm_logm_perturbed = expm(A_logm_perturbed) + rtol = 1e-4 + atol = 100 * tiny + assert_(not np.allclose(A_expm_logm_perturbed, A, rtol=rtol, atol=atol)) + + def test_burkardt_1(self): + # This matrix is diagonal. + # The calculation of the matrix exponential is simple. + # + # This is the first of a series of matrix exponential tests + # collected by John Burkardt from the following sources. + # + # Alan Laub, + # Review of "Linear System Theory" by Joao Hespanha, + # SIAM Review, + # Volume 52, Number 4, December 2010, pages 779--781. + # + # Cleve Moler and Charles Van Loan, + # Nineteen Dubious Ways to Compute the Exponential of a Matrix, + # Twenty-Five Years Later, + # SIAM Review, + # Volume 45, Number 1, March 2003, pages 3--49. + # + # Cleve Moler, + # Cleve's Corner: A Balancing Act for the Matrix Exponential, + # 23 July 2012. + # + # Robert Ward, + # Numerical computation of the matrix exponential + # with accuracy estimate, + # SIAM Journal on Numerical Analysis, + # Volume 14, Number 4, September 1977, pages 600--610. + exp1 = np.exp(1) + exp2 = np.exp(2) + A = np.array([ + [1, 0], + [0, 2], + ], dtype=float) + desired = np.array([ + [exp1, 0], + [0, exp2], + ], dtype=float) + actual = expm(A) + assert_allclose(actual, desired) + + def test_burkardt_2(self): + # This matrix is symmetric. + # The calculation of the matrix exponential is straightforward. + A = np.array([ + [1, 3], + [3, 2], + ], dtype=float) + desired = np.array([ + [39.322809708033859, 46.166301438885753], + [46.166301438885768, 54.711576854329110], + ], dtype=float) + actual = expm(A) + assert_allclose(actual, desired) + + def test_burkardt_3(self): + # This example is due to Laub. + # This matrix is ill-suited for the Taylor series approach. + # As powers of A are computed, the entries blow up too quickly. + exp1 = np.exp(1) + exp39 = np.exp(39) + A = np.array([ + [0, 1], + [-39, -40], + ], dtype=float) + desired = np.array([ + [ + 39/(38*exp1) - 1/(38*exp39), + -np.expm1(-38) / (38*exp1)], + [ + 39*np.expm1(-38) / (38*exp1), + -1/(38*exp1) + 39/(38*exp39)], + ], dtype=float) + actual = expm(A) + assert_allclose(actual, desired) + + def test_burkardt_4(self): + # This example is due to Moler and Van Loan. + # The example will cause problems for the series summation approach, + # as well as for diagonal Pade approximations. + A = np.array([ + [-49, 24], + [-64, 31], + ], dtype=float) + U = np.array([[3, 1], [4, 2]], dtype=float) + V = np.array([[1, -1/2], [-2, 3/2]], dtype=float) + w = np.array([-17, -1], dtype=float) + desired = np.dot(U * np.exp(w), V) + actual = expm(A) + assert_allclose(actual, desired) + + def test_burkardt_5(self): + # This example is due to Moler and Van Loan. + # This matrix is strictly upper triangular + # All powers of A are zero beyond some (low) limit. + # This example will cause problems for Pade approximations. + A = np.array([ + [0, 6, 0, 0], + [0, 0, 6, 0], + [0, 0, 0, 6], + [0, 0, 0, 0], + ], dtype=float) + desired = np.array([ + [1, 6, 18, 36], + [0, 1, 6, 18], + [0, 0, 1, 6], + [0, 0, 0, 1], + ], dtype=float) + actual = expm(A) + assert_allclose(actual, desired) + + def test_burkardt_6(self): + # This example is due to Moler and Van Loan. + # This matrix does not have a complete set of eigenvectors. + # That means the eigenvector approach will fail. + exp1 = np.exp(1) + A = np.array([ + [1, 1], + [0, 1], + ], dtype=float) + desired = np.array([ + [exp1, exp1], + [0, exp1], + ], dtype=float) + actual = expm(A) + assert_allclose(actual, desired) + + def test_burkardt_7(self): + # This example is due to Moler and Van Loan. + # This matrix is very close to example 5. + # Mathematically, it has a complete set of eigenvectors. + # Numerically, however, the calculation will be suspect. + exp1 = np.exp(1) + eps = np.spacing(1) + A = np.array([ + [1 + eps, 1], + [0, 1 - eps], + ], dtype=float) + desired = np.array([ + [exp1, exp1], + [0, exp1], + ], dtype=float) + actual = expm(A) + assert_allclose(actual, desired) + + def test_burkardt_8(self): + # This matrix was an example in Wikipedia. + exp4 = np.exp(4) + exp16 = np.exp(16) + A = np.array([ + [21, 17, 6], + [-5, -1, -6], + [4, 4, 16], + ], dtype=float) + desired = np.array([ + [13*exp16 - exp4, 13*exp16 - 5*exp4, 2*exp16 - 2*exp4], + [-9*exp16 + exp4, -9*exp16 + 5*exp4, -2*exp16 + 2*exp4], + [16*exp16, 16*exp16, 4*exp16], + ], dtype=float) * 0.25 + actual = expm(A) + assert_allclose(actual, desired) + + def test_burkardt_9(self): + # This matrix is due to the NAG Library. + # It is an example for function F01ECF. + A = np.array([ + [1, 2, 2, 2], + [3, 1, 1, 2], + [3, 2, 1, 2], + [3, 3, 3, 1], + ], dtype=float) + desired = np.array([ + [740.7038, 610.8500, 542.2743, 549.1753], + [731.2510, 603.5524, 535.0884, 542.2743], + [823.7630, 679.4257, 603.5524, 610.8500], + [998.4355, 823.7630, 731.2510, 740.7038], + ], dtype=float) + actual = expm(A) + assert_allclose(actual, desired) + + def test_burkardt_10(self): + # This is Ward's example #1. + # It is defective and nonderogatory. + A = np.array([ + [4, 2, 0], + [1, 4, 1], + [1, 1, 4], + ], dtype=float) + assert_allclose(sorted(scipy.linalg.eigvals(A)), (3, 3, 6)) + desired = np.array([ + [147.8666224463699, 183.7651386463682, 71.79703239999647], + [127.7810855231823, 183.7651386463682, 91.88256932318415], + [127.7810855231824, 163.6796017231806, 111.9681062463718], + ], dtype=float) + actual = expm(A) + assert_allclose(actual, desired) + + def test_burkardt_11(self): + # This is Ward's example #2. + # It is a symmetric matrix. + A = np.array([ + [29.87942128909879, 0.7815750847907159, -2.289519314033932], + [0.7815750847907159, 25.72656945571064, 8.680737820540137], + [-2.289519314033932, 8.680737820540137, 34.39400925519054], + ], dtype=float) + assert_allclose(scipy.linalg.eigvalsh(A), (20, 30, 40)) + desired = np.array([ + [ + 5.496313853692378E+15, + -1.823188097200898E+16, + -3.047577080858001E+16], + [ + -1.823188097200899E+16, + 6.060522870222108E+16, + 1.012918429302482E+17], + [ + -3.047577080858001E+16, + 1.012918429302482E+17, + 1.692944112408493E+17], + ], dtype=float) + actual = expm(A) + assert_allclose(actual, desired) + + def test_burkardt_12(self): + # This is Ward's example #3. + # Ward's algorithm has difficulty estimating the accuracy + # of its results. + A = np.array([ + [-131, 19, 18], + [-390, 56, 54], + [-387, 57, 52], + ], dtype=float) + assert_allclose(sorted(scipy.linalg.eigvals(A)), (-20, -2, -1)) + desired = np.array([ + [-1.509644158793135, 0.3678794391096522, 0.1353352811751005], + [-5.632570799891469, 1.471517758499875, 0.4060058435250609], + [-4.934938326088363, 1.103638317328798, 0.5413411267617766], + ], dtype=float) + actual = expm(A) + assert_allclose(actual, desired) + + def test_burkardt_13(self): + # This is Ward's example #4. + # This is a version of the Forsythe matrix. + # The eigenvector problem is badly conditioned. + # Ward's algorithm has difficulty estimating the accuracy + # of its results for this problem. + # + # Check the construction of one instance of this family of matrices. + A4_actual = _burkardt_13_power(4, 1) + A4_desired = [[0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1], + [1e-4, 0, 0, 0]] + assert_allclose(A4_actual, A4_desired) + # Check the expm for a few instances. + for n in (2, 3, 4, 10): + # Approximate expm using Taylor series. + # This works well for this matrix family + # because each matrix in the summation, + # even before dividing by the factorial, + # is entrywise positive with max entry 10**(-floor(p/n)*n). + k = max(1, int(np.ceil(16/n))) + desired = np.zeros((n, n), dtype=float) + for p in range(n*k): + Ap = _burkardt_13_power(n, p) + assert_equal(np.min(Ap), 0) + assert_allclose(np.max(Ap), np.power(10, -np.floor(p/n)*n)) + desired += Ap / factorial(p) + actual = expm(_burkardt_13_power(n, 1)) + assert_allclose(actual, desired) + + def test_burkardt_14(self): + # This is Moler's example. + # This badly scaled matrix caused problems for MATLAB's expm(). + A = np.array([ + [0, 1e-8, 0], + [-(2e10 + 4e8/6.), -3, 2e10], + [200./3., 0, -200./3.], + ], dtype=float) + desired = np.array([ + [0.446849468283175, 1.54044157383952e-09, 0.462811453558774], + [-5743067.77947947, -0.0152830038686819, -4526542.71278401], + [0.447722977849494, 1.54270484519591e-09, 0.463480648837651], + ], dtype=float) + actual = expm(A) + assert_allclose(actual, desired) + + def test_pascal(self): + # Test pascal triangle. + # Nilpotent exponential, used to trigger a failure (gh-8029) + + for scale in [1.0, 1e-3, 1e-6]: + for n in range(0, 80, 3): + sc = scale ** np.arange(n, -1, -1) + if np.any(sc < 1e-300): + break + + A = np.diag(np.arange(1, n + 1), -1) * scale + B = expm(A) + + got = B + expected = binom(np.arange(n + 1)[:,None], + np.arange(n + 1)[None,:]) * sc[None,:] / sc[:,None] + atol = 1e-13 * abs(expected).max() + assert_allclose(got, expected, atol=atol) + + def test_matrix_input(self): + # Large np.matrix inputs should work, gh-5546 + A = np.zeros((200, 200)) + A[-1,0] = 1 + B0 = expm(A) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "the matrix subclass.*", DeprecationWarning) + warnings.filterwarnings( + "ignore", "the matrix subclass.*", PendingDeprecationWarning) + B = expm(np.matrix(A)) + assert_allclose(B, B0) + + def test_exp_sinch_overflow(self): + # Check overflow in intermediate steps is fixed (gh-11839) + L = np.array([[1.0, -0.5, -0.5, 0.0, 0.0, 0.0, 0.0], + [0.0, 1.0, 0.0, -0.5, -0.5, 0.0, 0.0], + [0.0, 0.0, 1.0, 0.0, 0.0, -0.5, -0.5], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]) + + E0 = expm(-L) + E1 = expm(-2**11 * L) + E2 = E0 + for j in range(11): + E2 = E2 @ E2 + + assert_allclose(E1, E2) + + +class TestOperators: + + def test_product_operator(self): + random.seed(1234) + n = 5 + k = 2 + nsamples = 10 + for i in range(nsamples): + A = np.random.randn(n, n) + B = np.random.randn(n, n) + C = np.random.randn(n, n) + D = np.random.randn(n, k) + op = ProductOperator(A, B, C) + assert_allclose(op.matmat(D), A.dot(B).dot(C).dot(D)) + assert_allclose(op.T.matmat(D), (A.dot(B).dot(C)).T.dot(D)) + + def test_matrix_power_operator(self): + random.seed(1234) + n = 5 + k = 2 + p = 3 + nsamples = 10 + for i in range(nsamples): + A = np.random.randn(n, n) + B = np.random.randn(n, k) + op = MatrixPowerOperator(A, p) + assert_allclose(op.matmat(B), np.linalg.matrix_power(A, p).dot(B)) + assert_allclose(op.T.matmat(B), np.linalg.matrix_power(A, p).T.dot(B)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_norm.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_norm.py new file mode 100644 index 0000000000000000000000000000000000000000..be9072e24aad562d468f08e0bd111e6180460387 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_norm.py @@ -0,0 +1,149 @@ +"""Test functions for the sparse.linalg.norm module +""" + +import numpy as np +from numpy.linalg import norm as npnorm +from numpy.testing import assert_allclose, assert_equal +from pytest import raises as assert_raises + +import scipy.sparse +from scipy.sparse.linalg import norm as spnorm + + +# https://github.com/scipy/scipy/issues/16031 +# https://github.com/scipy/scipy/issues/21690 +def test_sparray_norm(): + row = np.array([0, 0, 1, 1]) + col = np.array([0, 1, 2, 3]) + data = np.array([4, 5, 7, 9]) + test_arr = scipy.sparse.coo_array((data, (row, col)), shape=(2, 4)) + test_mat = scipy.sparse.coo_matrix((data, (row, col)), shape=(2, 4)) + for ord in (1, np.inf, None): + for ax in [0, 1, None, (0, 1), (1, 0)]: + for A in (test_arr, test_mat): + expected = npnorm(A.toarray(), ord=ord, axis=ax) + actual = spnorm(A, ord=ord, axis=ax) + assert hasattr(actual, "dtype") + assert_equal(actual, expected) + # test 1d array and 1d-like (column) matrix + test_arr_1d = scipy.sparse.coo_array((data, (col,)), shape=(4,)) + test_mat_col = scipy.sparse.coo_matrix((data, (col, [0, 0, 0, 0])), shape=(4, 1)) + for ord in (1, np.inf, None): + for ax in [0, None]: + for A in (test_arr_1d, test_mat_col): + expected = npnorm(A.toarray(), ord=ord, axis=ax) + assert_equal(spnorm(A, ord=ord, axis=ax), expected) + + +class TestNorm: + def setup_method(self): + a = np.arange(9) - 4 + b = a.reshape((3, 3)) + self.b = scipy.sparse.csr_array(b) + + def test_matrix_norm(self): + + # Frobenius norm is the default + assert_allclose(spnorm(self.b), 7.745966692414834) + assert_allclose(spnorm(self.b, 'fro'), 7.745966692414834) + + assert_allclose(spnorm(self.b, np.inf), 9) + assert_allclose(spnorm(self.b, -np.inf), 2) + assert_allclose(spnorm(self.b, 1), 7) + assert_allclose(spnorm(self.b, -1), 6) + assert_allclose(spnorm(self.b.astype(np.float64), 2), 7.348469228349534) + + # _multi_svd_norm is not implemented for sparse array + assert_raises(NotImplementedError, spnorm, self.b, -2) + + def test_matrix_norm_axis(self): + for m, axis in ((self.b, None), (self.b, (0, 1)), (self.b.T, (1, 0))): + assert_allclose(spnorm(m, axis=axis), 7.745966692414834) + assert_allclose(spnorm(m, 'fro', axis=axis), 7.745966692414834) + assert_allclose(spnorm(m, np.inf, axis=axis), 9) + assert_allclose(spnorm(m, -np.inf, axis=axis), 2) + assert_allclose(spnorm(m, 1, axis=axis), 7) + assert_allclose(spnorm(m, -1, axis=axis), 6) + + def test_vector_norm(self): + v = [4.5825756949558398, 4.2426406871192848, 4.5825756949558398] + for m, a in (self.b, 0), (self.b.T, 1): + for axis in a, (a, ), a-2, (a-2, ): + assert_allclose(spnorm(m, 1, axis=axis), [7, 6, 7]) + assert_allclose(spnorm(m, np.inf, axis=axis), [4, 3, 4]) + assert_allclose(spnorm(m, axis=axis), v) + assert_allclose(spnorm(m, ord=2, axis=axis), v) + assert_allclose(spnorm(m, ord=None, axis=axis), v) + + def test_norm_exceptions(self): + m = self.b + assert_raises(TypeError, spnorm, m, None, 1.5) + assert_raises(TypeError, spnorm, m, None, [2]) + assert_raises(ValueError, spnorm, m, None, ()) + assert_raises(ValueError, spnorm, m, None, (0, 1, 2)) + assert_raises(ValueError, spnorm, m, None, (0, 0)) + assert_raises(ValueError, spnorm, m, None, (0, 2)) + assert_raises(ValueError, spnorm, m, None, (-3, 0)) + assert_raises(ValueError, spnorm, m, None, 2) + assert_raises(ValueError, spnorm, m, None, -3) + assert_raises(ValueError, spnorm, m, 'plate_of_shrimp', 0) + assert_raises(ValueError, spnorm, m, 'plate_of_shrimp', (0, 1)) + + +class TestVsNumpyNorm: + _sparse_types = ( + scipy.sparse.bsr_array, + scipy.sparse.coo_array, + scipy.sparse.csc_array, + scipy.sparse.csr_array, + scipy.sparse.dia_array, + scipy.sparse.dok_array, + scipy.sparse.lil_array, + ) + _test_matrices = ( + (np.arange(9) - 4).reshape((3, 3)), + [ + [1, 2, 3], + [-1, 1, 4]], + [ + [1, 0, 3], + [-1, 1, 4j]], + ) + + def test_sparse_matrix_norms(self): + for sparse_type in self._sparse_types: + for M in self._test_matrices: + S = sparse_type(M) + assert_allclose(spnorm(S), npnorm(M)) + assert_allclose(spnorm(S, 'fro'), npnorm(M, 'fro')) + assert_allclose(spnorm(S, np.inf), npnorm(M, np.inf)) + assert_allclose(spnorm(S, -np.inf), npnorm(M, -np.inf)) + assert_allclose(spnorm(S, 1), npnorm(M, 1)) + assert_allclose(spnorm(S, -1), npnorm(M, -1)) + + def test_sparse_matrix_norms_with_axis(self): + for sparse_type in self._sparse_types: + for M in self._test_matrices: + S = sparse_type(M) + for axis in None, (0, 1), (1, 0): + assert_allclose(spnorm(S, axis=axis), npnorm(M, axis=axis)) + for ord in 'fro', np.inf, -np.inf, 1, -1: + assert_allclose(spnorm(S, ord, axis=axis), + npnorm(M, ord, axis=axis)) + # Some numpy matrix norms are allergic to negative axes. + for axis in (-2, -1), (-1, -2), (1, -2): + assert_allclose(spnorm(S, axis=axis), npnorm(M, axis=axis)) + assert_allclose(spnorm(S, 'f', axis=axis), + npnorm(M, 'f', axis=axis)) + assert_allclose(spnorm(S, 'fro', axis=axis), + npnorm(M, 'fro', axis=axis)) + + def test_sparse_vector_norms(self): + for sparse_type in self._sparse_types: + for M in self._test_matrices: + S = sparse_type(M) + for axis in (0, 1, -1, -2, (0, ), (1, ), (-1, ), (-2, )): + assert_allclose(spnorm(S, axis=axis), npnorm(M, axis=axis)) + for ord in None, 2, np.inf, -np.inf, 1, 0.5, 0.42: + assert_allclose(spnorm(S, ord, axis=axis), + npnorm(M, ord, axis=axis)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_onenormest.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_onenormest.py new file mode 100644 index 0000000000000000000000000000000000000000..86e7207d6e119070c47c751c0e2e2df0a258bf8f --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_onenormest.py @@ -0,0 +1,252 @@ +"""Test functions for the sparse.linalg._onenormest module +""" + +import numpy as np +from numpy.testing import assert_allclose, assert_equal, assert_ +import pytest +import scipy.linalg +import scipy.sparse.linalg +from scipy.sparse.linalg._onenormest import _onenormest_core, _algorithm_2_2 + + +class MatrixProductOperator(scipy.sparse.linalg.LinearOperator): + """ + This is purely for onenormest testing. + """ + + def __init__(self, A, B): + if A.ndim != 2 or B.ndim != 2: + raise ValueError('expected ndarrays representing matrices') + if A.shape[1] != B.shape[0]: + raise ValueError('incompatible shapes') + self.A = A + self.B = B + self.ndim = 2 + self.shape = (A.shape[0], B.shape[1]) + + def _matvec(self, x): + return np.dot(self.A, np.dot(self.B, x)) + + def _rmatvec(self, x): + return np.dot(np.dot(x, self.A), self.B) + + def _matmat(self, X): + return np.dot(self.A, np.dot(self.B, X)) + + @property + def T(self): + return MatrixProductOperator(self.B.T, self.A.T) + + +class TestOnenormest: + + @pytest.mark.xslow + def test_onenormest_table_3_t_2(self): + # This will take multiple seconds if your computer is slow like mine. + # It is stochastic, so the tolerance could be too strict. + np.random.seed(1234) + t = 2 + n = 100 + itmax = 5 + nsamples = 5000 + observed = [] + expected = [] + nmult_list = [] + nresample_list = [] + for i in range(nsamples): + A = scipy.linalg.inv(np.random.randn(n, n)) + est, v, w, nmults, nresamples = _onenormest_core(A, A.T, t, itmax) + observed.append(est) + expected.append(scipy.linalg.norm(A, 1)) + nmult_list.append(nmults) + nresample_list.append(nresamples) + observed = np.array(observed, dtype=float) + expected = np.array(expected, dtype=float) + relative_errors = np.abs(observed - expected) / expected + + # check the mean underestimation ratio + underestimation_ratio = observed / expected + assert_(0.99 < np.mean(underestimation_ratio) < 1.0) + + # check the max and mean required column resamples + assert_equal(np.max(nresample_list), 2) + assert_(0.05 < np.mean(nresample_list) < 0.2) + + # check the proportion of norms computed exactly correctly + nexact = np.count_nonzero(relative_errors < 1e-14) + proportion_exact = nexact / float(nsamples) + assert_(0.9 < proportion_exact < 0.95) + + # check the average number of matrix*vector multiplications + assert_(3.5 < np.mean(nmult_list) < 4.5) + + @pytest.mark.xslow + def test_onenormest_table_4_t_7(self): + # This will take multiple seconds if your computer is slow like mine. + # It is stochastic, so the tolerance could be too strict. + np.random.seed(1234) + t = 7 + n = 100 + itmax = 5 + nsamples = 5000 + observed = [] + expected = [] + nmult_list = [] + nresample_list = [] + for i in range(nsamples): + A = np.random.randint(-1, 2, size=(n, n)) + est, v, w, nmults, nresamples = _onenormest_core(A, A.T, t, itmax) + observed.append(est) + expected.append(scipy.linalg.norm(A, 1)) + nmult_list.append(nmults) + nresample_list.append(nresamples) + observed = np.array(observed, dtype=float) + expected = np.array(expected, dtype=float) + relative_errors = np.abs(observed - expected) / expected + + # check the mean underestimation ratio + underestimation_ratio = observed / expected + assert_(0.90 < np.mean(underestimation_ratio) < 0.99) + + # check the required column resamples + assert_equal(np.max(nresample_list), 0) + + # check the proportion of norms computed exactly correctly + nexact = np.count_nonzero(relative_errors < 1e-14) + proportion_exact = nexact / float(nsamples) + assert_(0.15 < proportion_exact < 0.25) + + # check the average number of matrix*vector multiplications + assert_(3.5 < np.mean(nmult_list) < 4.5) + + def test_onenormest_table_5_t_1(self): + # "note that there is no randomness and hence only one estimate for t=1" + t = 1 + n = 100 + itmax = 5 + alpha = 1 - 1e-6 + A = -scipy.linalg.inv(np.identity(n) + alpha*np.eye(n, k=1)) + first_col = np.array([1] + [0]*(n-1)) + first_row = np.array([(-alpha)**i for i in range(n)]) + B = -scipy.linalg.toeplitz(first_col, first_row) + assert_allclose(A, B) + est, v, w, nmults, nresamples = _onenormest_core(B, B.T, t, itmax) + exact_value = scipy.linalg.norm(B, 1) + underest_ratio = est / exact_value + assert_allclose(underest_ratio, 0.05, rtol=1e-4) + assert_equal(nmults, 11) + assert_equal(nresamples, 0) + # check the non-underscored version of onenormest + est_plain = scipy.sparse.linalg.onenormest(B, t=t, itmax=itmax) + assert_allclose(est, est_plain) + + @pytest.mark.xslow + def test_onenormest_table_6_t_2(self): + #TODO this test seems to give estimates that match the table, + #TODO even though no attempt has been made to deal with + #TODO complex numbers in the one-norm estimation. + # This will take multiple seconds if your computer is slow like mine. + # It is stochastic, so the tolerance could be too strict. + np.random.seed(1234) + t = 2 + n = 100 + itmax = 5 + nsamples = 5000 + observed = [] + expected = [] + nmult_list = [] + nresample_list = [] + for i in range(nsamples): + A_inv = np.random.rand(n, n) + 1j * np.random.rand(n, n) + A = scipy.linalg.inv(A_inv) + est, v, w, nmults, nresamples = _onenormest_core(A, A.T, t, itmax) + observed.append(est) + expected.append(scipy.linalg.norm(A, 1)) + nmult_list.append(nmults) + nresample_list.append(nresamples) + observed = np.array(observed, dtype=float) + expected = np.array(expected, dtype=float) + relative_errors = np.abs(observed - expected) / expected + + # check the mean underestimation ratio + underestimation_ratio = observed / expected + underestimation_ratio_mean = np.mean(underestimation_ratio) + assert_(0.90 < underestimation_ratio_mean < 0.99) + + # check the required column resamples + max_nresamples = np.max(nresample_list) + assert_equal(max_nresamples, 0) + + # check the proportion of norms computed exactly correctly + nexact = np.count_nonzero(relative_errors < 1e-14) + proportion_exact = nexact / float(nsamples) + assert_(0.7 < proportion_exact < 0.8) + + # check the average number of matrix*vector multiplications + mean_nmult = np.mean(nmult_list) + assert_(4 < mean_nmult < 5) + + def _help_product_norm_slow(self, A, B): + # for profiling + C = np.dot(A, B) + return scipy.linalg.norm(C, 1) + + def _help_product_norm_fast(self, A, B): + # for profiling + t = 2 + itmax = 5 + D = MatrixProductOperator(A, B) + est, v, w, nmults, nresamples = _onenormest_core(D, D.T, t, itmax) + return est + + @pytest.mark.slow + def test_onenormest_linear_operator(self): + # Define a matrix through its product A B. + # Depending on the shapes of A and B, + # it could be easy to multiply this product by a small matrix, + # but it could be annoying to look at all of + # the entries of the product explicitly. + np.random.seed(1234) + n = 6000 + k = 3 + A = np.random.randn(n, k) + B = np.random.randn(k, n) + fast_estimate = self._help_product_norm_fast(A, B) + exact_value = self._help_product_norm_slow(A, B) + assert_(fast_estimate <= exact_value <= 3*fast_estimate, + f'fast: {fast_estimate:g}\nexact:{exact_value:g}') + + def test_returns(self): + np.random.seed(1234) + A = scipy.sparse.rand(50, 50, 0.1) + + s0 = scipy.linalg.norm(A.toarray(), 1) + s1, v = scipy.sparse.linalg.onenormest(A, compute_v=True) + s2, w = scipy.sparse.linalg.onenormest(A, compute_w=True) + s3, v2, w2 = scipy.sparse.linalg.onenormest(A, compute_w=True, compute_v=True) + + assert_allclose(s1, s0, rtol=1e-9) + assert_allclose(np.linalg.norm(A.dot(v), 1), s0*np.linalg.norm(v, 1), rtol=1e-9) + assert_allclose(A.dot(v), w, rtol=1e-9) + + +class TestAlgorithm_2_2: + + @pytest.mark.thread_unsafe(reason="Fails in parallel for unknown reasons") + def test_randn_inv(self): + rng = np.random.RandomState(1234) + n = 20 + nsamples = 100 + for i in range(nsamples): + + # Choose integer t uniformly between 1 and 3 inclusive. + t = rng.randint(1, 4) + + # Choose n uniformly between 10 and 40 inclusive. + n = rng.randint(10, 41) + + # Sample the inverse of a matrix with random normal entries. + A = scipy.linalg.inv(rng.randn(n, n)) + + # Compute the 1-norm bounds. + g, ind = _algorithm_2_2(A, A.T, t) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_propack.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_propack.py new file mode 100644 index 0000000000000000000000000000000000000000..4cdb235aef1407b9b5ec2c1c39acddb1f7090278 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_propack.py @@ -0,0 +1,203 @@ +import os +import pytest + +import numpy as np +from numpy.testing import assert_allclose +from pytest import raises as assert_raises +from scipy.sparse.linalg._svdp import _svdp +from scipy.sparse import csr_array, csc_array + + +# dtype_flavour to tolerance +TOLS = { + np.float32: 1e-4, + np.float64: 1e-8, + np.complex64: 1e-4, + np.complex128: 1e-8, +} + + +def is_complex_type(dtype): + return np.dtype(dtype).kind == "c" + + +_dtypes = [] +for dtype_flavour in TOLS.keys(): + marks = [] + if is_complex_type(dtype_flavour): + marks = [pytest.mark.slow] + _dtypes.append(pytest.param(dtype_flavour, marks=marks, + id=dtype_flavour.__name__)) +_dtypes = tuple(_dtypes) # type: ignore[assignment] + + +# The test function here is adapted from the original Fortran PROPACK tests. +# It is not very robust to arbitrary seeding since partial reorthogonalization +# does not have a predictable upperbound on the number of iterations. +def check_svdp(n, m, constructor, dtype, k, irl_mode, which, f=0.8, rng=None): + tol = TOLS[dtype] + + if rng is None: + rng = np.random.default_rng(0) + + # Legacy clamp for the generator + rng2 = np.random.default_rng(0) + if is_complex_type(dtype): + M = (- 5 + 10 * rng2.uniform(size=[n, m]) + - 5j + 10j * rng2.uniform(size=[n, m])).astype(dtype) + else: + M = (-5 + 10 * rng2.uniform(size=[n, m])).astype(dtype) + M[M.real > 10 * f - 5] = 0 + Msp = constructor(M) + + u1, sigma1, vt1 = np.linalg.svd(M, full_matrices=False) + u2, sigma2, vt2, _ = _svdp(Msp, k=k,which=which, irl_mode=irl_mode, + tol=tol, rng=rng) + + # check the which + if which.upper() == 'SM': + u1 = np.roll(u1, k, 1) + vt1 = np.roll(vt1, k, 0) + sigma1 = np.roll(sigma1, k) + + # check that singular values agree + assert_allclose(sigma1[:k], sigma2, rtol=tol, atol=tol) + + # check that singular vectors are orthogonal + assert_allclose(np.abs(u1.conj().T @ u2), np.eye(n, k), rtol=tol, atol=tol) + assert_allclose(np.abs(vt1.conj() @ vt2.T), np.eye(n, k), rtol=tol, atol=tol) + + +@pytest.mark.parametrize('ctor', (np.array, csr_array, csc_array)) +@pytest.mark.parametrize('dtype', [np.float32, np.float64, + np.complex64, np.complex128]) +@pytest.mark.parametrize('irl', (True, False)) +@pytest.mark.parametrize('which', ('LM', 'SM')) +def test_svdp(ctor, dtype, irl, which): + rng = np.random.default_rng(1757937293955503) + n, m, k = 10, 20, 3 + if which == 'SM' and not irl: + message = "`which`='SM' requires irl_mode=True" + with assert_raises(ValueError, match=message): + check_svdp(n, m, ctor, dtype, k, irl, which, rng=rng) + else: + check_svdp(n, m, ctor, dtype, k, irl, which, rng=rng) + + +@pytest.mark.xslow +@pytest.mark.parametrize('dtype', _dtypes) +@pytest.mark.parametrize('irl', (False, True)) +def test_examples(dtype, irl): + # Note: atol for complex64 bumped from 1e-4 to 1e-3 due to test failures + # with BLIS, Netlib, and MKL+AVX512 - see + # https://github.com/conda-forge/scipy-feedstock/pull/198#issuecomment-999180432 + atol = { + np.float32: 1.3e-4, + np.float64: 1e-9, + np.complex64: 1e-3, + np.complex128: 1e-9, + }[dtype] + + path_prefix = os.path.dirname(__file__) + # Test matrices from `illc1850.coord` and `mhd1280b.cua` distributed with + # PROPACK 2.1: http://sun.stanford.edu/~rmunk/PROPACK/ + relative_path = "propack_test_data.npz" + filename = os.path.join(path_prefix, relative_path) + with np.load(filename, allow_pickle=True) as data: + if is_complex_type(dtype): + A = data['A_complex'].item().astype(dtype) + else: + A = data['A_real'].item().astype(dtype) + + k = 200 + u, s, vh, _ = _svdp(A, k, irl_mode=irl, rng=np.random.default_rng(0)) + + # complex example matrix has many repeated singular values, so check only + # beginning non-repeated singular vectors to avoid permutations + sv_check = 27 if is_complex_type(dtype) else k + u = u[:, :sv_check] + vh = vh[:sv_check, :] + s = s[:sv_check] + + # Check orthogonality of singular vectors + assert_allclose(np.eye(u.shape[1]), u.conj().T @ u, atol=atol) + assert_allclose(np.eye(vh.shape[0]), vh @ vh.conj().T, atol=atol) + + # Ensure the norm of the difference between the np.linalg.svd and + # PROPACK reconstructed matrices is small + u3, s3, vh3 = np.linalg.svd(A.todense()) + u3 = u3[:, :sv_check] + s3 = s3[:sv_check] + vh3 = vh3[:sv_check, :] + A3 = u3 @ np.diag(s3) @ vh3 + recon = u @ np.diag(s) @ vh + assert_allclose(np.linalg.norm(A3 - recon), 0, atol=atol) + + +@pytest.mark.parametrize('shifts', (None, -10, 0, 1, 10, 70)) +@pytest.mark.parametrize('dtype', _dtypes[:2]) +def test_shifts(shifts, dtype): + rng = np.random.default_rng(0) + n, k = 70, 10 + A = rng.random((n, n)) + if shifts is not None and ((shifts < 0) or (k > min(n-1-shifts, n))): + with pytest.raises(ValueError): + _svdp(A, k, shifts=shifts, kmax=5*k, irl_mode=True, rng=rng) + else: + _svdp(A, k, shifts=shifts, kmax=5*k, irl_mode=True, rng=rng) + + +@pytest.mark.slow +@pytest.mark.xfail() +def test_shifts_accuracy(): + rng = np.random.default_rng(0) + n, k = 70, 10 + A = rng.random((n, n)).astype(np.float64) + u1, s1, vt1, _ = _svdp(A, k, shifts=None, which='SM', irl_mode=True, rng=rng) + u2, s2, vt2, _ = _svdp(A, k, shifts=32, which='SM', irl_mode=True, rng=rng) + # shifts <= 32 doesn't agree with shifts > 32 + # Does agree when which='LM' instead of 'SM' + assert_allclose(s1, s2) + + +@pytest.mark.parametrize('irl_mode', [False, True]) +@pytest.mark.parametrize('dtype', (np.float32, np.float64)) +def test_thin_hilbert(irl_mode, dtype): + rng = np.random.default_rng(1757951587606893) + m, n = 200, 4 + + # Generate a Hilbert matrix of size m x n + A = np.array([[1 / (i + j + 1) for j in range(n)] for i in range(m)], dtype=dtype) + uu, ss, vv = np.linalg.svd(A, full_matrices=False) + u, s, vt, _ = _svdp(A, k=4, which='LM', irl_mode=irl_mode, rng=rng) + assert_allclose(s, ss, atol=TOLS[dtype]) + + # Check orthogonality of singular vectors + assert_allclose(np.eye(u.shape[1]), u.T @ u, atol=TOLS[dtype]) + assert_allclose(np.eye(vt.shape[0]), vt @ vt.T, atol=TOLS[dtype]) + + # Check orthogonality against numpy svd results + assert_allclose(np.abs(uu.T @ u), np.eye(n), atol=TOLS[dtype]) + assert_allclose(np.abs(vv @ vt.T), np.eye(n), atol=TOLS[dtype]) + + +@pytest.mark.parametrize('dtype', (np.float32, np.float64, np.complex64, np.complex128)) +def test_fat_random(dtype): + rng = np.random.default_rng(1758046113948869) + m, n = 3, 100 + + A = rng.uniform(size=(m, n)).astype(dtype) + if dtype in (np.complex64, np.complex128): + A += dtype(1j) * rng.uniform(size=(m, n)).astype(dtype) + + uu, ss, vv = np.linalg.svd(A, full_matrices=False) + u, s, vt, _ = _svdp(A, k=3, which='LM', irl_mode=True, rng=rng) + assert_allclose(s, ss, atol=TOLS[dtype]) + + # Check orthogonality of singular vectors + assert_allclose(np.eye(u.shape[1]), u.conj().T @ u, atol=TOLS[dtype]) + assert_allclose(np.eye(vt.shape[0]), vt @ vt.conj().T, atol=TOLS[dtype]) + + # Check orthogonality against numpy svd results + assert_allclose(np.abs(uu.conj().T @ u), np.eye(m), atol=TOLS[dtype]) + assert_allclose(np.abs(vv @ vt.conj().T), np.eye(m), atol=TOLS[dtype]) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_pydata_sparse.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_pydata_sparse.py new file mode 100644 index 0000000000000000000000000000000000000000..0b6a304f4b7fce9761f9225ab538db53e72741be --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_pydata_sparse.py @@ -0,0 +1,272 @@ +import pytest + +import numpy as np +import scipy.sparse as sp +import scipy.sparse.linalg as splin + +from numpy.testing import assert_allclose, assert_equal + +try: + import sparse +except Exception: + sparse = None + +pytestmark = pytest.mark.skipif(sparse is None, + reason="pydata/sparse not installed") + + +msg = "pydata/sparse (0.15.1) does not implement necessary operations" + + +sparse_params = (pytest.param("COO"), + pytest.param("DOK", marks=[pytest.mark.xfail(reason=msg)])) + +scipy_sparse_classes = [ + sp.bsr_array, + sp.csr_array, + sp.coo_array, + sp.csc_array, + sp.dia_array, + sp.dok_array +] + + +@pytest.fixture(params=sparse_params) +def sparse_cls(request): + return getattr(sparse, request.param) + + +@pytest.fixture(params=scipy_sparse_classes) +def sp_sparse_cls(request): + return request.param + + +@pytest.fixture +def same_matrix(sparse_cls, sp_sparse_cls): + np.random.seed(1234) + A_dense = np.random.rand(9, 9) + return sp_sparse_cls(A_dense), sparse_cls(A_dense) + + +@pytest.fixture +def matrices(sparse_cls): + np.random.seed(1234) + A_dense = np.random.rand(9, 9) + A_dense = A_dense @ A_dense.T + A_sparse = sparse_cls(A_dense) + b = np.random.rand(9) + return A_dense, A_sparse, b + + +def test_isolve_gmres(matrices): + # Several of the iterative solvers use the same + # isolve.utils.make_system wrapper code, so test just one of them. + A_dense, A_sparse, b = matrices + x, info = splin.gmres(A_sparse, b, atol=1e-15) + assert info == 0 + assert isinstance(x, np.ndarray) + assert_allclose(A_sparse @ x, b) + + +def test_lsmr(matrices): + A_dense, A_sparse, b = matrices + res0 = splin.lsmr(A_dense, b) + res = splin.lsmr(A_sparse, b) + assert_allclose(res[0], res0[0], atol=1e-3) + + +# test issue 17012 +def test_lsmr_output_shape(): + x = splin.lsmr(A=np.ones((10, 1)), b=np.zeros(10), x0=np.ones(1))[0] + assert_equal(x.shape, (1,)) + + +def test_lsqr(matrices): + A_dense, A_sparse, b = matrices + res0 = splin.lsqr(A_dense, b) + res = splin.lsqr(A_sparse, b) + assert_allclose(res[0], res0[0], atol=1e-5) + + +def test_eigs(matrices): + A_dense, A_sparse, v0 = matrices + + M_dense = np.diag(v0**2) + M_sparse = A_sparse.__class__(M_dense) + + w_dense, v_dense = splin.eigs(A_dense, k=3, v0=v0) + w, v = splin.eigs(A_sparse, k=3, v0=v0) + + assert_allclose(w, w_dense) + assert_allclose(v, v_dense) + + for M in [M_sparse, M_dense]: + w_dense, v_dense = splin.eigs(A_dense, M=M_dense, k=3, v0=v0) + w, v = splin.eigs(A_sparse, M=M, k=3, v0=v0) + + assert_allclose(w, w_dense) + assert_allclose(v, v_dense) + + w_dense, v_dense = splin.eigsh(A_dense, M=M_dense, k=3, v0=v0) + w, v = splin.eigsh(A_sparse, M=M, k=3, v0=v0) + + assert_allclose(w, w_dense) + assert_allclose(v, v_dense) + + +def test_svds(matrices): + A_dense, A_sparse, v0 = matrices + + u0, s0, vt0 = splin.svds(A_dense, k=2, v0=v0) + u, s, vt = splin.svds(A_sparse, k=2, v0=v0) + + assert_allclose(s, s0) + assert_allclose(np.abs(u), np.abs(u0)) + assert_allclose(np.abs(vt), np.abs(vt0)) + + +def test_lobpcg(matrices): + A_dense, A_sparse, x = matrices + X = x[:,None] + + w_dense, v_dense = splin.lobpcg(A_dense, X) + w, v = splin.lobpcg(A_sparse, X) + + assert_allclose(w, w_dense) + assert_allclose(v, v_dense) + + +def test_spsolve(matrices): + A_dense, A_sparse, b = matrices + b2 = np.random.rand(len(b), 3) + + x0 = splin.spsolve(sp.csc_array(A_dense), b) + x = splin.spsolve(A_sparse, b) + assert isinstance(x, np.ndarray) + assert_allclose(x, x0) + + x0 = splin.spsolve(sp.csc_array(A_dense), b) + x = splin.spsolve(A_sparse, b, use_umfpack=True) + assert isinstance(x, np.ndarray) + assert_allclose(x, x0) + + x0 = splin.spsolve(sp.csc_array(A_dense), b2) + x = splin.spsolve(A_sparse, b2) + assert isinstance(x, np.ndarray) + assert_allclose(x, x0) + + x0 = splin.spsolve(sp.csc_array(A_dense), + sp.csc_array(A_dense)) + x = splin.spsolve(A_sparse, A_sparse) + assert isinstance(x, type(A_sparse)) + assert_allclose(x.todense(), x0.todense()) + + +def test_splu(matrices): + A_dense, A_sparse, b = matrices + n = len(b) + sparse_cls = type(A_sparse) + + lu = splin.splu(A_sparse) + + assert isinstance(lu.L, sparse_cls) + assert isinstance(lu.U, sparse_cls) + + _Pr_scipy = sp.csc_array((np.ones(n), (lu.perm_r, np.arange(n)))) + _Pc_scipy = sp.csc_array((np.ones(n), (np.arange(n), lu.perm_c))) + Pr = sparse_cls.from_scipy_sparse(_Pr_scipy) + Pc = sparse_cls.from_scipy_sparse(_Pc_scipy) + A2 = Pr.T @ lu.L @ lu.U @ Pc.T + + assert_allclose(A2.todense(), A_sparse.todense()) + + z = lu.solve(A_sparse.todense()) + assert_allclose(z, np.eye(n), atol=1e-10) + + +def test_spilu(matrices): + A_dense, A_sparse, b = matrices + sparse_cls = type(A_sparse) + + lu = splin.spilu(A_sparse) + + assert isinstance(lu.L, sparse_cls) + assert isinstance(lu.U, sparse_cls) + + z = lu.solve(A_sparse.todense()) + assert_allclose(z, np.eye(len(b)), atol=1e-3) + + +def test_spsolve_triangular(matrices): + A_dense, A_sparse, b = matrices + A_sparse = sparse.tril(A_sparse) + + x = splin.spsolve_triangular(A_sparse, b) + assert_allclose(A_sparse @ x, b) + + +def test_onenormest(matrices): + A_dense, A_sparse, b = matrices + est0 = splin.onenormest(A_dense) + est = splin.onenormest(A_sparse) + assert_allclose(est, est0) + + +def test_norm(matrices): + A_dense, A_sparse, b = matrices + norm0 = splin.norm(sp.csr_array(A_dense)) + norm = splin.norm(A_sparse) + assert_allclose(norm, norm0) + + +def test_inv(matrices): + A_dense, A_sparse, b = matrices + x0 = splin.inv(sp.csc_array(A_dense)) + x = splin.inv(A_sparse) + assert_allclose(x.todense(), x0.todense()) + + +def test_expm(matrices): + A_dense, A_sparse, b = matrices + x0 = splin.expm(sp.csc_array(A_dense)) + x = splin.expm(A_sparse) + assert_allclose(x.todense(), x0.todense()) + + +def test_expm_multiply(matrices): + A_dense, A_sparse, b = matrices + x0 = splin.expm_multiply(A_dense, b) + x = splin.expm_multiply(A_sparse, b) + assert_allclose(x, x0) + + x0 = splin.expm_multiply(A_dense, A_dense) + x = splin.expm_multiply(A_sparse, A_sparse) + assert_allclose(x.todense(), x0) + + +def test_eq(same_matrix): + sp_sparse, pd_sparse = same_matrix + # temporary splint until pydata sparse support sparray equality + sp_sparse = sp.coo_matrix(sp_sparse).asformat(sp_sparse.format) + assert (sp_sparse == pd_sparse).all() + + +def test_ne(same_matrix): + sp_sparse, pd_sparse = same_matrix + # temporary splint until pydata sparse support sparray equality + sp_sparse = sp.coo_matrix(sp_sparse).asformat(sp_sparse.format) + assert not (sp_sparse != pd_sparse).any() + + +def test_ge(same_matrix): + sp_sparse, pd_sparse = same_matrix + # temporary splint until pydata sparse support sparray equality + sp_sparse = sp.coo_matrix(sp_sparse).asformat(sp_sparse.format) + assert (sp_sparse >= pd_sparse).all() + + +def test_gt(same_matrix): + sp_sparse, pd_sparse = same_matrix + # temporary splint until pydata sparse support sparray equality + sp_sparse = sp.coo_matrix(sp_sparse).asformat(sp_sparse.format) + assert not (sp_sparse > pd_sparse).any() diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_special_sparse_arrays.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_special_sparse_arrays.py new file mode 100644 index 0000000000000000000000000000000000000000..ad502e8da63197f3cee1f8a507249e7433593c3a --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/linalg/tests/test_special_sparse_arrays.py @@ -0,0 +1,342 @@ +import pytest +import numpy as np +from numpy.testing import assert_array_equal, assert_allclose + +from scipy.sparse import diags, csgraph +from scipy.linalg import eigh + +from scipy.sparse.linalg import LaplacianNd +from scipy.sparse.linalg._special_sparse_arrays import Sakurai +from scipy.sparse.linalg._special_sparse_arrays import MikotaPair + +INT_DTYPES = [np.int8, np.int16, np.int32, np.int64] +REAL_DTYPES = [np.float32, np.float64] +COMPLEX_DTYPES = [np.complex64, np.complex128] +ALLDTYPES = INT_DTYPES + REAL_DTYPES + COMPLEX_DTYPES + + +class TestLaplacianNd: + """ + LaplacianNd tests + """ + + @pytest.mark.parametrize('bc', ['neumann', 'dirichlet', 'periodic']) + def test_1d_specific_shape(self, bc): + lap = LaplacianNd(grid_shape=(6, ), boundary_conditions=bc) + lapa = lap.toarray() + if bc == 'neumann': + a = np.array( + [ + [-1, 1, 0, 0, 0, 0], + [1, -2, 1, 0, 0, 0], + [0, 1, -2, 1, 0, 0], + [0, 0, 1, -2, 1, 0], + [0, 0, 0, 1, -2, 1], + [0, 0, 0, 0, 1, -1], + ] + ) + elif bc == 'dirichlet': + a = np.array( + [ + [-2, 1, 0, 0, 0, 0], + [1, -2, 1, 0, 0, 0], + [0, 1, -2, 1, 0, 0], + [0, 0, 1, -2, 1, 0], + [0, 0, 0, 1, -2, 1], + [0, 0, 0, 0, 1, -2], + ] + ) + else: + a = np.array( + [ + [-2, 1, 0, 0, 0, 1], + [1, -2, 1, 0, 0, 0], + [0, 1, -2, 1, 0, 0], + [0, 0, 1, -2, 1, 0], + [0, 0, 0, 1, -2, 1], + [1, 0, 0, 0, 1, -2], + ] + ) + assert_array_equal(a, lapa) + + def test_1d_with_graph_laplacian(self): + n = 6 + G = diags(np.ones(n - 1), 1, format='dia') + Lf = csgraph.laplacian(G, symmetrized=True, form='function') + La = csgraph.laplacian(G, symmetrized=True, form='array') + grid_shape = (n,) + bc = 'neumann' + lap = LaplacianNd(grid_shape, boundary_conditions=bc) + assert_array_equal(lap(np.eye(n)), -Lf(np.eye(n))) + assert_array_equal(lap.toarray(), -La.toarray()) + # https://github.com/numpy/numpy/issues/24351 + assert_array_equal(lap.tosparse().toarray(), -La.toarray()) + + @pytest.mark.parametrize('grid_shape', [(6, ), (2, 3), (2, 3, 4)]) + @pytest.mark.parametrize('bc', ['neumann', 'dirichlet', 'periodic']) + def test_eigenvalues(self, grid_shape, bc): + lap = LaplacianNd(grid_shape, boundary_conditions=bc, dtype=np.float64) + L = lap.toarray() + eigvals = eigh(L, eigvals_only=True) + n = np.prod(grid_shape) + eigenvalues = lap.eigenvalues() + dtype = eigenvalues.dtype + atol = n * n * np.finfo(dtype).eps + # test the default ``m = None`` + assert_allclose(eigenvalues, eigvals, atol=atol) + # test every ``m > 0`` + for m in np.arange(1, n + 1): + assert_array_equal(lap.eigenvalues(m), eigenvalues[-m:]) + + @pytest.mark.parametrize('grid_shape', [(6, ), (2, 3), (2, 3, 4)]) + @pytest.mark.parametrize('bc', ['neumann', 'dirichlet', 'periodic']) + def test_eigenvectors(self, grid_shape, bc): + lap = LaplacianNd(grid_shape, boundary_conditions=bc, dtype=np.float64) + n = np.prod(grid_shape) + eigenvalues = lap.eigenvalues() + eigenvectors = lap.eigenvectors() + dtype = eigenvectors.dtype + atol = n * n * max(np.finfo(dtype).eps, np.finfo(np.double).eps) + # test the default ``m = None`` every individual eigenvector + for i in np.arange(n): + r = lap.toarray() @ eigenvectors[:, i] - eigenvectors[:, i] * eigenvalues[i] + assert_allclose(r, np.zeros_like(r), atol=atol) + # test every ``m > 0`` + for m in np.arange(1, n + 1): + e = lap.eigenvalues(m) + ev = lap.eigenvectors(m) + r = lap.toarray() @ ev - ev @ np.diag(e) + assert_allclose(r, np.zeros_like(r), atol=atol) + # test orthogonality + assert_allclose(eigenvectors @ eigenvectors.T, np.eye(n), atol=atol) + # test full eigendecomposition + L = eigenvectors @ np.diag(eigenvalues) @ eigenvectors.T + assert_allclose(L, lap.toarray(), atol=atol) + + @pytest.mark.parametrize('grid_shape', [(6, ), (2, 3), (2, 3, 4)]) + @pytest.mark.parametrize('bc', ['neumann', 'dirichlet', 'periodic']) + def test_toarray_tosparse_consistency(self, grid_shape, bc): + lap = LaplacianNd(grid_shape, boundary_conditions=bc) + n = np.prod(grid_shape) + assert_array_equal(lap.toarray(), lap(np.eye(n))) + assert_array_equal(lap.tosparse().toarray(), lap.toarray()) + + @pytest.mark.parametrize('dtype', ALLDTYPES) + @pytest.mark.parametrize('grid_shape', [(6, ), (2, 3), (2, 3, 4)]) + @pytest.mark.parametrize('bc', ['neumann', 'dirichlet', 'periodic']) + def test_linearoperator_shape_dtype(self, grid_shape, bc, dtype): + lap = LaplacianNd(grid_shape, boundary_conditions=bc, dtype=dtype) + n = np.prod(grid_shape) + assert lap.shape == (n, n) + assert lap.dtype == dtype + assert_array_equal( + LaplacianNd( + grid_shape, boundary_conditions=bc, dtype=dtype + ).toarray(), + LaplacianNd(grid_shape, boundary_conditions=bc) + .toarray() + .astype(dtype), + ) + assert_array_equal( + LaplacianNd(grid_shape, boundary_conditions=bc, dtype=dtype) + .tosparse() + .toarray(), + LaplacianNd(grid_shape, boundary_conditions=bc) + .tosparse() + .toarray() + .astype(dtype), + ) + + @pytest.mark.parametrize('dtype', ALLDTYPES) + @pytest.mark.parametrize('grid_shape', [(6, ), (2, 3), (2, 3, 4)]) + @pytest.mark.parametrize('bc', ['neumann', 'dirichlet', 'periodic']) + def test_dot(self, grid_shape, bc, dtype): + """ Test the dot-product for type preservation and consistency. + """ + lap = LaplacianNd(grid_shape, boundary_conditions=bc) + n = np.prod(grid_shape) + x0 = np.arange(n) + x1 = x0.reshape((-1, 1)) + x2 = np.arange(2 * n).reshape((n, 2)) + input_set = [x0, x1, x2] + for x in input_set: + y = lap.dot(x.astype(dtype)) + assert x.shape == y.shape + assert y.dtype == dtype + if x.ndim == 2: + yy = lap.toarray() @ x.astype(dtype) + assert yy.dtype == dtype + np.array_equal(y, yy) + + def test_boundary_conditions_value_error(self): + with pytest.raises(ValueError, match="Unknown value 'robin'"): + LaplacianNd(grid_shape=(6, ), boundary_conditions='robin') + + +class TestSakurai: + """ + Sakurai tests + """ + + def test_specific_shape(self): + sak = Sakurai(6) + assert_array_equal(sak.toarray(), sak(np.eye(6))) + a = np.array( + [ + [ 5, -4, 1, 0, 0, 0], + [-4, 6, -4, 1, 0, 0], + [ 1, -4, 6, -4, 1, 0], + [ 0, 1, -4, 6, -4, 1], + [ 0, 0, 1, -4, 6, -4], + [ 0, 0, 0, 1, -4, 5] + ] + ) + + np.array_equal(a, sak.toarray()) + np.array_equal(sak.tosparse().toarray(), sak.toarray()) + ab = np.array( + [ + [ 1, 1, 1, 1, 1, 1], + [-4, -4, -4, -4, -4, -4], + [ 5, 6, 6, 6, 6, 5] + ] + ) + np.array_equal(ab, sak.tobanded()) + e = np.array( + [0.03922866, 0.56703972, 2.41789479, 5.97822974, + 10.54287655, 14.45473055] + ) + np.array_equal(e, sak.eigenvalues()) + np.array_equal(e[:2], sak.eigenvalues(2)) + + # `Sakurai` default `dtype` is `np.int8` as its entries are small integers + @pytest.mark.parametrize('dtype', ALLDTYPES) + def test_linearoperator_shape_dtype(self, dtype): + n = 7 + sak = Sakurai(n, dtype=dtype) + assert sak.shape == (n, n) + assert sak.dtype == dtype + assert_array_equal(sak.toarray(), Sakurai(n).toarray().astype(dtype)) + assert_array_equal(sak.tosparse().toarray(), + Sakurai(n).tosparse().toarray().astype(dtype)) + + @pytest.mark.parametrize('dtype', ALLDTYPES) + @pytest.mark.parametrize('argument_dtype', ALLDTYPES) + def test_dot(self, dtype, argument_dtype): + """ Test the dot-product for type preservation and consistency. + """ + result_dtype = np.promote_types(argument_dtype, dtype) + n = 5 + sak = Sakurai(n) + x0 = np.arange(n) + x1 = x0.reshape((-1, 1)) + x2 = np.arange(2 * n).reshape((n, 2)) + input_set = [x0, x1, x2] + for x in input_set: + y = sak.dot(x.astype(argument_dtype)) + assert x.shape == y.shape + assert np.can_cast(y.dtype, result_dtype) + if x.ndim == 2: + ya = sak.toarray() @ x.astype(argument_dtype) + np.array_equal(y, ya) + assert np.can_cast(ya.dtype, result_dtype) + ys = sak.tosparse() @ x.astype(argument_dtype) + np.array_equal(y, ys) + assert np.can_cast(ys.dtype, result_dtype) + +class TestMikotaPair: + """ + MikotaPair tests + """ + # both MikotaPair `LinearOperator`s share the same dtype + # while `MikotaK` `dtype` can be as small as its default `np.int32` + # since its entries are integers, the `MikotaM` involves inverses + # so its smallest still accurate `dtype` is `np.float32` + tested_types = REAL_DTYPES + COMPLEX_DTYPES + + def test_specific_shape(self): + n = 6 + mik = MikotaPair(n) + mik_k = mik.k + mik_m = mik.m + assert_array_equal(mik_k.toarray(), mik_k(np.eye(n))) + assert_array_equal(mik_m.toarray(), mik_m(np.eye(n))) + + k = np.array( + [ + [11, -5, 0, 0, 0, 0], + [-5, 9, -4, 0, 0, 0], + [ 0, -4, 7, -3, 0, 0], + [ 0, 0, -3, 5, -2, 0], + [ 0, 0, 0, -2, 3, -1], + [ 0, 0, 0, 0, -1, 1] + ] + ) + np.array_equal(k, mik_k.toarray()) + np.array_equal(mik_k.tosparse().toarray(), k) + kb = np.array( + [ + [ 0, -5, -4, -3, -2, -1], + [11, 9, 7, 5, 3, 1] + ] + ) + np.array_equal(kb, mik_k.tobanded()) + + minv = np.arange(1, n + 1) + np.array_equal(np.diag(1. / minv), mik_m.toarray()) + np.array_equal(mik_m.tosparse().toarray(), mik_m.toarray()) + np.array_equal(1. / minv, mik_m.tobanded()) + + e = np.array([ 1, 4, 9, 16, 25, 36]) + np.array_equal(e, mik.eigenvalues()) + np.array_equal(e[:2], mik.eigenvalues(2)) + + @pytest.mark.parametrize('dtype', tested_types) + def test_linearoperator_shape_dtype(self, dtype): + n = 7 + mik = MikotaPair(n, dtype=dtype) + mik_k = mik.k + mik_m = mik.m + assert mik_k.shape == (n, n) + assert mik_k.dtype == dtype + assert mik_m.shape == (n, n) + assert mik_m.dtype == dtype + mik_default_dtype = MikotaPair(n) + mikd_k = mik_default_dtype.k + mikd_m = mik_default_dtype.m + assert mikd_k.shape == (n, n) + assert mikd_k.dtype == np.float64 + assert mikd_m.shape == (n, n) + assert mikd_m.dtype == np.float64 + assert_array_equal(mik_k.toarray(), + mikd_k.toarray().astype(dtype)) + assert_array_equal(mik_k.tosparse().toarray(), + mikd_k.tosparse().toarray().astype(dtype)) + + @pytest.mark.parametrize('dtype', tested_types) + @pytest.mark.parametrize('argument_dtype', ALLDTYPES) + def test_dot(self, dtype, argument_dtype): + """ Test the dot-product for type preservation and consistency. + """ + result_dtype = np.promote_types(argument_dtype, dtype) + n = 5 + mik = MikotaPair(n, dtype=dtype) + mik_k = mik.k + mik_m = mik.m + x0 = np.arange(n) + x1 = x0.reshape((-1, 1)) + x2 = np.arange(2 * n).reshape((n, 2)) + lo_set = [mik_k, mik_m] + input_set = [x0, x1, x2] + for lo in lo_set: + for x in input_set: + y = lo.dot(x.astype(argument_dtype)) + assert x.shape == y.shape + assert np.can_cast(y.dtype, result_dtype) + if x.ndim == 2: + ya = lo.toarray() @ x.astype(argument_dtype) + np.array_equal(y, ya) + assert np.can_cast(ya.dtype, result_dtype) + ys = lo.tosparse() @ x.astype(argument_dtype) + np.array_equal(y, ys) + assert np.can_cast(ys.dtype, result_dtype) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cc2b65b6a1f72bf3cad248fba4260cc624800833 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_64bit.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_64bit.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..912bb1d43c14793ddbb22f3dbeaebf011959130b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_64bit.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_arithmetic1d.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_arithmetic1d.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2475855d8dddc08882a9e1909aeb7b008f224fe9 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_arithmetic1d.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_array_api.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_array_api.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..82fcce8708a8687ae6c1efdbd677194b98b7c441 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_array_api.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_common1d.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_common1d.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1bfd1138995481c3d15c6425e36e03af40e42581 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_common1d.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_construct.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_construct.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c2e677b8116e2b1e05f0b7a17b0860453daca0c8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_construct.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_coo.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_coo.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ad1b7501a5006f43507fb6632c0d0bec826d00cc Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_coo.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_csc.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_csc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5cdd51c56ede4edd37b8d6d3cca349e6d74a42bd Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_csc.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_csr.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_csr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..741ddf59d5e1aebe8137c5d62b803c23eb7bef44 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_csr.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_dok.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_dok.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2393f4172ead837f08d7bf2508f00fc981cf7393 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_dok.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_extract.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_extract.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..18797dc7ca54d9128c1320f612ebf8c2c4577776 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_extract.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_indexing1d.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_indexing1d.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6145085eccdda2b1a60aea2eae12509014ba7a8b Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_indexing1d.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_matrix_io.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_matrix_io.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6fa329201018a24561ae19ddf7d783910e1bc907 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_matrix_io.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_minmax1d.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_minmax1d.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8581b9091c653740bb20d52f47845f309b671b5f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_minmax1d.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_sparsetools.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_sparsetools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a64cd528071772d8460876f553f101a8aeb4c28 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_sparsetools.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_spfuncs.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_spfuncs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4669c54f17315b26fdf7dec2723ab129a803c7a1 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_spfuncs.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_sputils.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_sputils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c59912e418dea4987cb613a1c56d8ebdc7c435de Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/__pycache__/test_sputils.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_64bit.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_64bit.py new file mode 100644 index 0000000000000000000000000000000000000000..dd0faf7186f052a61ce14e042ec9603576628a47 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_64bit.py @@ -0,0 +1,303 @@ +""" Test functions involving 64bit or 32bit indexing """ +import pytest +import numpy as np +from scipy.sparse import ( + bsr_array, coo_array, csc_array, csr_array, dia_array, + bsr_matrix, coo_matrix, csc_matrix, csr_matrix, dia_matrix, +) + +# rename to avoid pytest collecting them in this module +from .test_base import ( + TestBSR as _TestBSR, + TestCOO as _TestCOO, + TestCSC as _TestCSC, + TestCSR as _TestCSR, + TestDIA as _TestDIA, + TestDOK as _TestDOK, + TestLIL as _TestLIL, + TestBSRMatrix as _TestBSRMatrix, + TestCOOMatrix as _TestCOOMatrix, + TestCSCMatrix as _TestCSCMatrix, + TestCSRMatrix as _TestCSRMatrix, + TestDIAMatrix as _TestDIAMatrix, + TestDOKMatrix as _TestDOKMatrix, + TestLILMatrix as _TestLILMatrix, + with_64bit_maxval_limit, +) + + +# name : reason not tested here +SKIP_TESTS = { + 'test_expm': 'expm for 64-bit indices not available', + 'test_inv': 'linsolve for 64-bit indices not available', + 'test_solve': 'linsolve for 64-bit indices not available', + 'test_scalar_idx_dtype': 'test implemented in base class', + 'test_large_dimensions_reshape': 'test actually requires 64-bit to work', + 'test_constructor_smallcol': 'test verifies int32 indexes', + 'test_constructor_largecol': 'test verifies int64 indexes', + 'test_tocoo_tocsr_tocsc_gh19245': 'test verifies int32 indexes', +} + + +def cases_64bit(sp_api): + """Yield all tests for all formats + + This is more than testing get_index_dtype. It allows checking whether upcasting + or downcasting the index dtypes affects test results. The approach used here + does not try to figure out which tests might fail due to 32/64-bit issues. + We just run them all. + So, each test method in that uses cases_64bit reruns most of the test suite! + """ + if sp_api == "sparray": + TEST_CLASSES = [_TestBSR, _TestCOO, _TestCSC, _TestCSR, _TestDIA] + elif sp_api == "sparray-extra": + # lil/dok->other conversion operations use get_index_dtype + # so we include lil & dok test suite even though they do not + # use get_index_dtype within the class. That means many of + # these tests are superfluous, but it's hard to pick which + TEST_CLASSES = [_TestDOK, _TestLIL] + elif sp_api == "spmatrix": + TEST_CLASSES = [_TestBSRMatrix, _TestCOOMatrix, _TestCSCMatrix, + _TestCSRMatrix, _TestDIAMatrix] + elif sp_api == "spmatrix-extra": + # lil/dok->other conversion operations use get_index_dtype + TEST_CLASSES = [_TestDOKMatrix, _TestLILMatrix] + else: + raise ValueError(f"parameter {sp_api=} is not valid") + + for cls in TEST_CLASSES: + for method_name in sorted(dir(cls)): + method = getattr(cls, method_name) + if (method_name.startswith('test_') and + not getattr(method, 'slow', False)): + marks = [] + + msg = SKIP_TESTS.get(method_name) + if msg: + marks.append(pytest.mark.skip(reason=msg)) + + markers = getattr(method, 'pytestmark', []) + for mark in markers: + if mark.name in ('skipif', 'skip', 'xfail', 'xslow'): + marks.append(mark) + + yield pytest.param(cls, method_name, marks=marks) + + +@pytest.mark.thread_unsafe(reason="fails in parallel") +class RunAll64Bit: + def _check_resiliency(self, cls, method_name, **kw): + # Resiliency test, to check that sparse matrices deal reasonably + # with varying index data types. + + @with_64bit_maxval_limit(**kw) + def check(cls, method_name): + instance = cls() + if hasattr(instance, 'setup_method'): + instance.setup_method() + try: + getattr(instance, method_name)() + finally: + if hasattr(instance, 'teardown_method'): + instance.teardown_method() + + check(cls, method_name) + + +class Test64BitArray(RunAll64Bit): + # inheritance of pytest test classes does not separate marks for subclasses. + # So we define these functions in both Array and Matrix versions. + @pytest.mark.parametrize('cls,method_name', cases_64bit("sparray")) + def test_resiliency_limit_10(self, cls, method_name): + self._check_resiliency(cls, method_name, maxval_limit=10) + + @pytest.mark.parametrize('cls,method_name', cases_64bit("sparray")) + def test_resiliency_all_32(self, cls, method_name): + self._check_resiliency(cls, method_name, fixed_dtype=np.int32) + + @pytest.mark.parametrize('cls,method_name', cases_64bit("sparray")) + def test_resiliency_all_64(self, cls, method_name): + self._check_resiliency(cls, method_name, fixed_dtype=np.int64) + + @pytest.mark.fail_slow(2) + @pytest.mark.parametrize('cls,method_name', cases_64bit("sparray")) + def test_resiliency_random(self, cls, method_name): + self._check_resiliency(cls, method_name) + + +class Test64BitMatrix(RunAll64Bit): + # assert_32bit=True only for spmatrix cuz sparray does not check index content + @pytest.mark.fail_slow(5) + @pytest.mark.parametrize('cls,method_name', cases_64bit("spmatrix")) + def test_no_64(self, cls, method_name): + self._check_resiliency(cls, method_name, assert_32bit=True) + + +class Test64BitMatrixSameAsArray(RunAll64Bit): + # inheritance of pytest test classes does not separate marks for subclasses. + # So we define these functions in both Array and Matrix versions. + @pytest.mark.parametrize('cls,method_name', cases_64bit("spmatrix")) + def test_resiliency_limit_10(self, cls, method_name): + self._check_resiliency(cls, method_name, maxval_limit=10) + + @pytest.mark.parametrize('cls,method_name', cases_64bit("spmatrix")) + def test_resiliency_all_32(self, cls, method_name): + self._check_resiliency(cls, method_name, fixed_dtype=np.int32) + + @pytest.mark.parametrize('cls,method_name', cases_64bit("spmatrix")) + def test_resiliency_all_64(self, cls, method_name): + self._check_resiliency(cls, method_name, fixed_dtype=np.int64) + + @pytest.mark.fail_slow(2) + @pytest.mark.parametrize('cls,method_name', cases_64bit("spmatrix")) + def test_resiliency_random(self, cls, method_name): + # Resiliency check that sparse deals with varying index data types. + self._check_resiliency(cls, method_name) + +# Extra: LIL and DOK classes. no direct get_index_dtype, but convert to classes that do +@pytest.mark.xslow +class Test64BitArrayExtra(RunAll64Bit): + # inheritance of pytest test classes does not separate marks for subclasses. + # So we define these functions in both Array and Matrix versions. + @pytest.mark.parametrize('cls,method_name', cases_64bit("sparray-extra")) + def test_resiliency_limit_10(self, cls, method_name): + self._check_resiliency(cls, method_name, maxval_limit=10) + + @pytest.mark.parametrize('cls,method_name', cases_64bit("sparray-extra")) + def test_resiliency_all_32(self, cls, method_name): + self._check_resiliency(cls, method_name, fixed_dtype=np.int32) + + @pytest.mark.parametrize('cls,method_name', cases_64bit("sparray-extra")) + def test_resiliency_all_64(self, cls, method_name): + self._check_resiliency(cls, method_name, fixed_dtype=np.int64) + + @pytest.mark.fail_slow(2) + @pytest.mark.parametrize('cls,method_name', cases_64bit("sparray-extra")) + def test_resiliency_random(self, cls, method_name): + # Resiliency check that sparse deals with varying index data types. + self._check_resiliency(cls, method_name) + + +# Extra: LIL and DOK classes. no direct get_index_dtype, but convert to classes that do +@pytest.mark.xslow +class Test64BitMatrixExtra(RunAll64Bit): + # assert_32bit=True only for spmatrix cuz sparray does not check index content + @pytest.mark.fail_slow(5) + @pytest.mark.parametrize('cls,method_name', cases_64bit("spmatrix-extra")) + def test_no_64(self, cls, method_name): + self._check_resiliency(cls, method_name, assert_32bit=True) + + # inheritance of pytest test classes does not separate marks for subclasses. + # So we define these functions in both Array and Matrix versions. + @pytest.mark.parametrize('cls,method_name', cases_64bit("spmatrix-extra")) + def test_resiliency_limit_10(self, cls, method_name): + self._check_resiliency(cls, method_name, maxval_limit=10) + + @pytest.mark.parametrize('cls,method_name', cases_64bit("spmatrix-extra")) + def test_resiliency_all_32(self, cls, method_name): + self._check_resiliency(cls, method_name, fixed_dtype=np.int32) + + @pytest.mark.parametrize('cls,method_name', cases_64bit("spmatrix-extra")) + def test_resiliency_all_64(self, cls, method_name): + self._check_resiliency(cls, method_name, fixed_dtype=np.int64) + + @pytest.mark.fail_slow(2) + @pytest.mark.parametrize('cls,method_name', cases_64bit("spmatrix-extra")) + def test_resiliency_random(self, cls, method_name): + # Resiliency check that sparse deals with varying index data types. + self._check_resiliency(cls, method_name) + + +@pytest.mark.thread_unsafe(reason="Fails in parallel for unknown reasons") +class Test64BitTools: + # classes that use get_index_dtype + MAT_CLASSES = [ + bsr_matrix, coo_matrix, csc_matrix, csr_matrix, dia_matrix, + bsr_array, coo_array, csc_array, csr_array, dia_array, + ] + + def _compare_index_dtype(self, m, dtype): + dtype = np.dtype(dtype) + if m.format in ['csc', 'csr', 'bsr']: + return (m.indices.dtype == dtype) and (m.indptr.dtype == dtype) + elif m.format == 'coo': + return (m.row.dtype == dtype) and (m.col.dtype == dtype) + elif m.format == 'dia': + return (m.offsets.dtype == dtype) + else: + raise ValueError(f"matrix {m!r} has no integer indices") + + def test_decorator_maxval_limit(self): + # Test that the with_64bit_maxval_limit decorator works + + @with_64bit_maxval_limit(maxval_limit=10) + def check(mat_cls): + m = mat_cls(np.random.rand(10, 1)) + assert self._compare_index_dtype(m, np.int32) + m = mat_cls(np.random.rand(11, 1)) + assert self._compare_index_dtype(m, np.int64) + + for mat_cls in self.MAT_CLASSES: + check(mat_cls) + + def test_decorator_maxval_random(self): + # Test that the with_64bit_maxval_limit decorator works (2) + + @with_64bit_maxval_limit(random=True) + def check(mat_cls): + seen_32 = False + seen_64 = False + for k in range(100): + m = mat_cls(np.random.rand(9, 9)) + seen_32 = seen_32 or self._compare_index_dtype(m, np.int32) + seen_64 = seen_64 or self._compare_index_dtype(m, np.int64) + if seen_32 and seen_64: + break + else: + raise AssertionError("both 32 and 64 bit indices not seen") + + for mat_cls in self.MAT_CLASSES: + check(mat_cls) + + def test_downcast_intp(self): + # Check that bincount and ufunc.reduceat intp downcasts are + # dealt with. The point here is to trigger points in the code + # that can fail on 32-bit systems when using 64-bit indices, + # due to use of functions that only work with intp-size indices. + + @with_64bit_maxval_limit(fixed_dtype=np.int64, downcast_maxval=1) + def check_limited(csc_container, csr_container, coo_container): + # These involve indices larger than `downcast_maxval` + a = csc_container([[1, 2], [3, 4], [5, 6]]) + pytest.raises(AssertionError, a.count_nonzero, axis=1) + pytest.raises(AssertionError, a.sum, axis=0) + + a = csr_container([[1, 2, 3], [3, 4, 6]]) + pytest.raises(AssertionError, a.count_nonzero, axis=0) + pytest.raises(AssertionError, a.sum, axis=1) + + a = coo_container([[1, 2, 3], [3, 4, 5]]) + pytest.raises(AssertionError, a.count_nonzero, axis=0) + a.has_canonical_format = False + pytest.raises(AssertionError, a.sum_duplicates) + + @with_64bit_maxval_limit(fixed_dtype=np.int64) + def check_unlimited(csc_container, csr_container, coo_container): + # These involve indices smaller than `downcast_maxval` + a = csc_container([[1, 2], [3, 4], [5, 6]]) + a.count_nonzero(axis=1) + a.sum(axis=0) + + a = csr_container([[1, 2, 3], [3, 4, 6]]) + a.count_nonzero(axis=0) + a.sum(axis=1) + + a = coo_container([[1, 2, 3], [3, 4, 5]]) + a.count_nonzero(axis=0) + a.has_canonical_format = False + a.sum_duplicates() + + check_limited(csc_array, csr_array, coo_array) + check_unlimited(csc_array, csr_array, coo_array) + check_limited(csc_matrix, csr_matrix, coo_matrix) + check_unlimited(csc_matrix, csr_matrix, coo_matrix) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_arithmetic1d.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_arithmetic1d.py new file mode 100644 index 0000000000000000000000000000000000000000..62b56f5fe2f69d9188d1c01cf02521f7dd2f1e9d --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_arithmetic1d.py @@ -0,0 +1,341 @@ +"""Test of 1D arithmetic operations""" + +import pytest + +import numpy as np +from numpy.testing import assert_equal, assert_allclose + +from scipy.sparse import coo_array, csr_array +from scipy.sparse._sputils import isscalarlike + + +spcreators = [coo_array, csr_array] +math_dtypes = [np.int64, np.float64, np.complex128] + + +def toarray(a): + if isinstance(a, np.ndarray) or isscalarlike(a): + return a + return a.toarray() + +@pytest.fixture +def dat1d(): + return np.array([3, 0, 1, 0], 'd') + + +@pytest.fixture +def datsp_math_dtypes(dat1d): + dat_dtypes = {dtype: dat1d.astype(dtype) for dtype in math_dtypes} + return { + sp: [(dtype, dat, sp(dat)) for dtype, dat in dat_dtypes.items()] + for sp in spcreators + } + + +@pytest.mark.parametrize("spcreator", spcreators) +class TestArithmetic1D: + def test_empty_arithmetic(self, spcreator): + shape = (5,) + for mytype in [ + np.dtype('int32'), + np.dtype('float32'), + np.dtype('float64'), + np.dtype('complex64'), + np.dtype('complex128'), + ]: + a = spcreator(shape, dtype=mytype) + b = a + a + c = 2 * a + assert isinstance(a @ a.tocsr(), np.ndarray) + assert isinstance(a @ a.tocoo(), np.ndarray) + for m in [a, b, c]: + assert m @ m == a.toarray() @ a.toarray() + assert m.dtype == mytype + assert toarray(m).dtype == mytype + + def test_abs(self, spcreator): + A = np.array([-1, 0, 17, 0, -5, 0, 1, -4, 0, 0, 0, 0], 'd') + assert_equal(abs(A), abs(spcreator(A)).toarray()) + + def test_round(self, spcreator): + A = np.array([-1.35, 0.56, 17.25, -5.98], 'd') + Asp = spcreator(A) + assert_equal(np.around(A, decimals=1), round(Asp, ndigits=1).toarray()) + + def test_elementwise_power(self, spcreator): + A = np.array([-4, -3, -2, -1, 0, 1, 2, 3, 4], 'd') + Asp = spcreator(A) + assert_equal(np.power(A, 2), Asp.power(2).toarray()) + + # element-wise power function needs a scalar power + with pytest.raises(NotImplementedError, match='input is not scalar'): + spcreator(A).power(A) + + def test_real(self, spcreator): + D = np.array([1 + 3j, 2 - 4j]) + A = spcreator(D) + assert_equal(A.real.toarray(), D.real) + + def test_imag(self, spcreator): + D = np.array([1 + 3j, 2 - 4j]) + A = spcreator(D) + assert_equal(A.imag.toarray(), D.imag) + + def test_mul_scalar(self, spcreator, datsp_math_dtypes): + for dtype, dat, datsp in datsp_math_dtypes[spcreator]: + assert_equal(dat * 2, (datsp * 2).toarray()) + assert_equal(dat * 17.3, (datsp * 17.3).toarray()) + + def test_rmul_scalar(self, spcreator, datsp_math_dtypes): + for dtype, dat, datsp in datsp_math_dtypes[spcreator]: + assert_equal(2 * dat, (2 * datsp).toarray()) + assert_equal(17.3 * dat, (17.3 * datsp).toarray()) + + def test_sub(self, spcreator, datsp_math_dtypes): + for dtype, dat, datsp in datsp_math_dtypes[spcreator]: + if dtype == np.dtype('bool'): + # boolean array subtraction deprecated in 1.9.0 + continue + + assert_equal((datsp - datsp).toarray(), np.zeros(4)) + assert_equal((datsp - 0).toarray(), dat) + + A = spcreator([1, -4, 0, 2], dtype='d') + assert_equal((datsp - A).toarray(), dat - A.toarray()) + assert_equal((A - datsp).toarray(), A.toarray() - dat) + + # test broadcasting + assert_equal(datsp.toarray() - dat[0], dat - dat[0]) + + def test_add0(self, spcreator, datsp_math_dtypes): + for dtype, dat, datsp in datsp_math_dtypes[spcreator]: + # Adding 0 to a sparse matrix + assert_equal((datsp + 0).toarray(), dat) + # use sum (which takes 0 as a starting value) + sumS = sum([k * datsp for k in range(1, 3)]) + sumD = sum([k * dat for k in range(1, 3)]) + assert_allclose(sumS.toarray(), sumD) + + def test_elementwise_multiply(self, spcreator): + # real/real + A = np.array([4, 0, 9]) + B = np.array([0, 7, -1]) + Asp = spcreator(A) + Bsp = spcreator(B) + assert_allclose(Asp.multiply(Bsp).toarray(), A * B) # sparse/sparse + assert_allclose(Asp.multiply(B).toarray(), A * B) # sparse/dense + + # complex/complex + C = np.array([1 - 2j, 0 + 5j, -1 + 0j]) + D = np.array([5 + 2j, 7 - 3j, -2 + 1j]) + Csp = spcreator(C) + Dsp = spcreator(D) + assert_allclose(Csp.multiply(Dsp).toarray(), C * D) # sparse/sparse + assert_allclose(Csp.multiply(D).toarray(), C * D) # sparse/dense + + # real/complex + assert_allclose(Asp.multiply(Dsp).toarray(), A * D) # sparse/sparse + assert_allclose(Asp.multiply(D).toarray(), A * D) # sparse/dense + + def test_elementwise_multiply_broadcast(self, spcreator): + A = np.array([4]) + B = np.array([[-9]]) + C = np.array([1, -1, 0]) + D = np.array([[7, 9, -9]]) + E = np.array([[3], [2], [1]]) + F = np.array([[8, 6, 3], [-4, 3, 2], [6, 6, 6]]) + G = [1, 2, 3] + H = np.ones((3, 4)) + J = H.T + K = np.array([[0]]) + L = np.array([[[1, 2], [0, 1]]]) + + # Some arrays can't be cast as spmatrices (A, C, L) so leave + # them out. + Asp = spcreator(A) + Csp = spcreator(C) + Gsp = spcreator(G) + # 2d arrays + Bsp = spcreator(B) + Dsp = spcreator(D) + Esp = spcreator(E) + Fsp = spcreator(F) + Hsp = spcreator(H) + Hspp = spcreator(H[0, None]) + Jsp = spcreator(J) + Jspp = spcreator(J[:, 0, None]) + Ksp = spcreator(K) + + matrices = [A, B, C, D, E, F, G, H, J, K, L] + spmatrices = [Asp, Bsp, Csp, Dsp, Esp, Fsp, Gsp, Hsp, Hspp, Jsp, Jspp, Ksp] + sp1dmatrices = [Asp, Csp, Gsp] + + # sparse/sparse + for i in sp1dmatrices: + for j in spmatrices: + try: + dense_mult = i.toarray() * j.toarray() + except ValueError: + with pytest.raises(ValueError, match='inconsistent shapes'): + i.multiply(j) + continue + sp_mult = i.multiply(j) + assert_allclose(sp_mult.toarray(), dense_mult) + + # sparse/dense + for i in sp1dmatrices: + for j in matrices: + try: + dense_mult = i.toarray() * j + except TypeError: + continue + except ValueError: + matchme = 'broadcast together|inconsistent shapes' + with pytest.raises(ValueError, match=matchme): + i.multiply(j) + continue + try: + sp_mult = i.multiply(j) + except ValueError: + continue + assert_allclose(toarray(sp_mult), dense_mult) + + def test_elementwise_divide(self, spcreator, dat1d): + datsp = spcreator(dat1d) + expected = np.array([1, np.nan, 1, np.nan]) + actual = datsp / datsp + # need assert_array_equal to handle nan values + np.testing.assert_array_equal(actual, expected) + + denom = spcreator([1, 0, 0, 4], dtype='d') + expected = [3, np.nan, np.inf, 0] + np.testing.assert_array_equal(datsp / denom, expected) + + # complex + A = np.array([1 - 2j, 0 + 5j, -1 + 0j]) + B = np.array([5 + 2j, 7 - 3j, -2 + 1j]) + Asp = spcreator(A) + Bsp = spcreator(B) + assert_allclose(Asp / Bsp, A / B) + + # integer + A = np.array([1, 2, 3]) + B = np.array([0, 1, 2]) + Asp = spcreator(A) + Bsp = spcreator(B) + with np.errstate(divide='ignore'): + assert_equal(Asp / Bsp, A / B) + + # mismatching sparsity patterns + A = np.array([0, 1]) + B = np.array([1, 0]) + Asp = spcreator(A) + Bsp = spcreator(B) + with np.errstate(divide='ignore', invalid='ignore'): + assert_equal(Asp / Bsp, A / B) + + def test_pow(self, spcreator): + A = np.array([1, 0, 2, 0]) + B = spcreator(A) + + # unusual exponents + with pytest.raises(ValueError, match='negative integer powers'): + B**-1 + with pytest.raises(NotImplementedError, match='zero power'): + B**0 + + for exponent in [1, 2, 3, 2.2]: + ret_sp = B**exponent + ret_np = A**exponent + assert_equal(ret_sp.toarray(), ret_np) + assert_equal(ret_sp.dtype, ret_np.dtype) + + def test_dot_scalar(self, spcreator, dat1d): + A = spcreator(dat1d) + scalar = 10 + actual = A.dot(scalar) + expected = A * scalar + + assert_allclose(actual.toarray(), expected.toarray()) + + def test_matmul(self, spcreator): + Msp = spcreator([2, 0, 3.0]) + B = spcreator(np.array([[0, 1], [1, 0], [0, 2]], 'd')) + col = np.array([[1, 2, 3]]).T + + # check sparse @ dense 2d column + assert_allclose(Msp @ col, Msp.toarray() @ col) + + # check sparse1d @ sparse2d, sparse1d @ dense2d, dense1d @ sparse2d + assert_allclose((Msp @ B).toarray(), (Msp @ B).toarray()) + assert_allclose(Msp.toarray() @ B, (Msp @ B).toarray()) + assert_allclose(Msp @ B.toarray(), (Msp @ B).toarray()) + + # check sparse1d @ dense1d, sparse1d @ sparse1d + V = np.array([0, 0, 1]) + assert_allclose(Msp @ V, Msp.toarray() @ V) + + Vsp = spcreator(V) + Msp_Vsp = Msp @ Vsp + assert isinstance(Msp_Vsp, np.ndarray) + assert Msp_Vsp.shape == () + + # output is 0-dim ndarray + assert_allclose(np.array(3), Msp_Vsp) + assert_allclose(np.array(3), Msp.toarray() @ Vsp) + assert_allclose(np.array(3), Msp @ Vsp.toarray()) + assert_allclose(np.array(3), Msp.toarray() @ Vsp.toarray()) + + # check error on matrix-scalar + with pytest.raises(ValueError, match='Scalar operands are not allowed'): + Msp @ 1 + with pytest.raises(ValueError, match='Scalar operands are not allowed'): + 1 @ Msp + + def test_sub_dense(self, spcreator, datsp_math_dtypes): + # subtracting a dense matrix to/from a sparse matrix + for dtype, dat, datsp in datsp_math_dtypes[spcreator]: + if dtype == np.dtype('bool'): + # boolean array subtraction deprecated in 1.9.0 + continue + + # Manually add to avoid upcasting from scalar + # multiplication. + sum1 = (dat + dat + dat) - datsp + assert_equal(sum1, dat + dat) + sum2 = (datsp + datsp + datsp) - dat + assert_equal(sum2, dat + dat) + + def test_size_zero_matrix_arithmetic(self, spcreator): + # Test basic matrix arithmetic with shapes like 0, (1, 0), (0, 3), etc. + mat = np.array([]) + a = mat.reshape(0) + d = mat.reshape((1, 0)) + f = np.ones([5, 5]) + + asp = spcreator(a) + dsp = spcreator(d) + # bad shape for addition + with pytest.raises(ValueError, match='inconsistent shapes'): + asp.__add__(dsp) + + # matrix product. + assert_equal(asp.dot(asp), np.dot(a, a)) + + # bad matrix products + with pytest.raises(ValueError, match='dimension mismatch|shapes.*not aligned'): + asp.dot(f) + + # elemente-wise multiplication + assert_equal(asp.multiply(asp).toarray(), np.multiply(a, a)) + + assert_equal(asp.multiply(a).toarray(), np.multiply(a, a)) + + assert_equal(asp.multiply(6).toarray(), np.multiply(a, 6)) + + # bad element-wise multiplication + with pytest.raises(ValueError, match='inconsistent shapes'): + asp.multiply(f) + + # Addition + assert_equal(asp.__add__(asp).toarray(), a.__add__(a)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_array_api.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_array_api.py new file mode 100644 index 0000000000000000000000000000000000000000..4dbf962a74182a0733139e51ed16b6de60d4e436 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_array_api.py @@ -0,0 +1,560 @@ +import pytest +import numpy as np +import numpy.testing as npt +import scipy.sparse +import scipy.sparse.linalg as spla + + +sparray_types = ('bsr', 'coo', 'csc', 'csr', 'dia', 'dok', 'lil') + +sparray_classes = [ + getattr(scipy.sparse, f'{T}_array') for T in sparray_types +] + +A = np.array([ + [0, 1, 2, 0], + [2, 0, 0, 3], + [1, 4, 0, 0] +]) + +B = np.array([ + [0, 1], + [2, 0] +]) + +X = np.array([ + [1, 0, 0, 1], + [2, 1, 2, 0], + [0, 2, 1, 0], + [0, 0, 1, 2] +], dtype=float) + + +sparrays = [sparray(A) for sparray in sparray_classes] +square_sparrays = [sparray(B) for sparray in sparray_classes] +eig_sparrays = [sparray(X) for sparray in sparray_classes] + +parametrize_sparrays = pytest.mark.parametrize( + "A", sparrays, ids=sparray_types +) +parametrize_square_sparrays = pytest.mark.parametrize( + "B", square_sparrays, ids=sparray_types +) +parametrize_eig_sparrays = pytest.mark.parametrize( + "X", eig_sparrays, ids=sparray_types +) + + +@parametrize_sparrays +def test_sum(A): + assert not isinstance(A.sum(axis=0), np.matrix), \ + "Expected array, got matrix" + assert A.sum(axis=0).shape == (4,) + assert A.sum(axis=1).shape == (3,) + + +@parametrize_sparrays +def test_mean(A): + assert not isinstance(A.mean(axis=1), np.matrix), \ + "Expected array, got matrix" + + +@parametrize_sparrays +def test_min_max(A): + # Some formats don't support min/max operations, so we skip those here. + if hasattr(A, 'min'): + assert not isinstance(A.min(axis=1), np.matrix), \ + "Expected array, got matrix" + if hasattr(A, 'max'): + assert not isinstance(A.max(axis=1), np.matrix), \ + "Expected array, got matrix" + if hasattr(A, 'argmin'): + assert not isinstance(A.argmin(axis=1), np.matrix), \ + "Expected array, got matrix" + if hasattr(A, 'argmax'): + assert not isinstance(A.argmax(axis=1), np.matrix), \ + "Expected array, got matrix" + + +@parametrize_sparrays +def test_todense(A): + assert not isinstance(A.todense(), np.matrix), \ + "Expected array, got matrix" + + +@parametrize_sparrays +def test_indexing(A): + if A.__class__.__name__[:3] in ('dia', 'coo', 'bsr'): + return + + all_res = ( + A[1, :], + A[:, 1], + A[1, [1, 2]], + A[[1, 2], 1], + A[[0]], + A[:, [1, 2]], + A[[1, 2], :], + A[1, [[1, 2]]], + A[[[1, 2]], 1], + ) + + for res in all_res: + assert isinstance(res, scipy.sparse.sparray), \ + f"Expected sparse array, got {res._class__.__name__}" + + +@parametrize_sparrays +def test_dense_addition(A): + X = np.random.random(A.shape) + assert not isinstance(A + X, np.matrix), "Expected array, got matrix" + + +@parametrize_sparrays +def test_sparse_addition(A): + assert isinstance((A + A), scipy.sparse.sparray), "Expected array, got matrix" + + +@parametrize_sparrays +def test_elementwise_mul(A): + assert np.all((A * A).todense() == A.power(2).todense()) + + +@parametrize_sparrays +def test_elementwise_rmul(A): + with pytest.raises(TypeError): + None * A + + with pytest.raises(ValueError): + np.eye(3) * scipy.sparse.csr_array(np.arange(6).reshape(2, 3)) + + assert np.all((2 * A) == (A.todense() * 2)) + + assert np.all((A.todense() * A) == (A.todense() ** 2)) + + +@parametrize_sparrays +def test_matmul(A): + assert np.all((A @ A.T).todense() == A.dot(A.T).todense()) + + +@parametrize_sparrays +def test_power_operator(A): + assert isinstance((A**2), scipy.sparse.sparray), "Expected array, got matrix" + + # https://github.com/scipy/scipy/issues/15948 + npt.assert_equal((A**2).todense(), (A.todense())**2) + + # power of zero is all ones (dense) so helpful msg exception + with pytest.raises(NotImplementedError, match="zero power"): + A**0 + + +@parametrize_sparrays +def test_sparse_divide(A): + assert isinstance(A / A, np.ndarray) + +@parametrize_sparrays +def test_sparse_dense_divide(A): + with pytest.warns(RuntimeWarning): + assert isinstance((A / A.todense()), scipy.sparse.sparray) + +@parametrize_sparrays +def test_dense_divide(A): + assert isinstance((A / 2), scipy.sparse.sparray), "Expected array, got matrix" + + +@parametrize_sparrays +def test_no_A_attr(A): + with pytest.raises(AttributeError): + A.A + + +@parametrize_sparrays +def test_no_H_attr(A): + with pytest.raises(AttributeError): + A.H + + +@parametrize_sparrays +def test_getrow_getcol(A): + assert isinstance(A._getcol(0), scipy.sparse.sparray) + assert isinstance(A._getrow(0), scipy.sparse.sparray) + + +# -- linalg -- + +@parametrize_sparrays +def test_as_linearoperator(A): + L = spla.aslinearoperator(A) + npt.assert_allclose(L * [1, 2, 3, 4], A @ [1, 2, 3, 4]) + + +@parametrize_square_sparrays +def test_inv(B): + if B.__class__.__name__[:3] != 'csc': + return + + C = spla.inv(B) + + assert isinstance(C, scipy.sparse.sparray) + npt.assert_allclose(C.todense(), np.linalg.inv(B.todense())) + + +@parametrize_square_sparrays +def test_expm(B): + if B.__class__.__name__[:3] != 'csc': + return + + Bmat = scipy.sparse.csc_matrix(B) + + C = spla.expm(B) + + assert isinstance(C, scipy.sparse.sparray) + npt.assert_allclose( + C.todense(), + spla.expm(Bmat).todense() + ) + + +@parametrize_square_sparrays +def test_expm_multiply(B): + if B.__class__.__name__[:3] != 'csc': + return + + npt.assert_allclose( + spla.expm_multiply(B, np.array([1, 2])), + spla.expm(B) @ [1, 2] + ) + + +@parametrize_sparrays +def test_norm(A): + C = spla.norm(A) + npt.assert_allclose(C, np.linalg.norm(A.todense())) + + +@parametrize_square_sparrays +def test_onenormest(B): + C = spla.onenormest(B) + npt.assert_allclose(C, np.linalg.norm(B.todense(), 1)) + + +@parametrize_square_sparrays +def test_spsolve(B): + if B.__class__.__name__[:3] not in ('csc', 'csr'): + return + + npt.assert_allclose( + spla.spsolve(B, [1, 2]), + np.linalg.solve(B.todense(), [1, 2]) + ) + + +@pytest.mark.parametrize("fmt",["csr","csc"]) +def test_spsolve_triangular(fmt): + arr = [ + [1, 0, 0, 0], + [2, 1, 0, 0], + [3, 2, 1, 0], + [4, 3, 2, 1], + ] + if fmt == "csr": + X = scipy.sparse.csr_array(arr) + else: + X = scipy.sparse.csc_array(arr) + spla.spsolve_triangular(X, [1, 2, 3, 4]) + + +@parametrize_square_sparrays +def test_factorized(B): + if B.__class__.__name__[:3] != 'csc': + return + + LU = spla.factorized(B) + npt.assert_allclose( + LU(np.array([1, 2])), + np.linalg.solve(B.todense(), [1, 2]) + ) + + +@parametrize_square_sparrays +@pytest.mark.parametrize( + "solver", + ["bicg", "bicgstab", "cg", "cgs", "gmres", "lgmres", "minres", "qmr", + "gcrotmk", "tfqmr"] +) +def test_solvers(B, solver): + if solver == "minres": + kwargs = {} + else: + kwargs = {'atol': 1e-5} + + x, info = getattr(spla, solver)(B, np.array([1, 2]), **kwargs) + assert info >= 0 # no errors, even if perhaps did not converge fully + npt.assert_allclose(x, [1, 1], atol=1e-1) + + +@parametrize_sparrays +@pytest.mark.parametrize( + "solver", + ["lsqr", "lsmr"] +) +def test_lstsqr(A, solver): + x, *_ = getattr(spla, solver)(A, [1, 2, 3]) + npt.assert_allclose(A @ x, [1, 2, 3]) + + +@parametrize_eig_sparrays +def test_eigs(X): + e, v = spla.eigs(X, k=1) + npt.assert_allclose( + X @ v, + e[0] * v + ) + + +@parametrize_eig_sparrays +def test_eigsh(X): + X = X + X.T + e, v = spla.eigsh(X, k=1) + npt.assert_allclose( + X @ v, + e[0] * v + ) + + +@parametrize_eig_sparrays +def test_svds(X): + u, s, vh = spla.svds(X, k=3) + u2, s2, vh2 = np.linalg.svd(X.todense()) + s = np.sort(s) + s2 = np.sort(s2[:3]) + npt.assert_allclose(s, s2, atol=1e-3) + + +def test_splu(): + X = scipy.sparse.csc_array([ + [1, 0, 0, 0], + [2, 1, 0, 0], + [3, 2, 1, 0], + [4, 3, 2, 1], + ]) + LU = spla.splu(X) + npt.assert_allclose( + LU.solve(np.array([1, 2, 3, 4])), + np.asarray([1, 0, 0, 0], dtype=np.float64), + rtol=1e-14, atol=3e-16 + ) + + +def test_spilu(): + X = scipy.sparse.csc_array([ + [1, 0, 0, 0], + [2, 1, 0, 0], + [3, 2, 1, 0], + [4, 3, 2, 1], + ]) + LU = spla.spilu(X) + npt.assert_allclose( + LU.solve(np.array([1, 2, 3, 4])), + np.asarray([1, 0, 0, 0], dtype=np.float64), + rtol=1e-14, atol=3e-16 + ) + + +@pytest.mark.parametrize( + "cls,indices_attrs", + [ + ( + scipy.sparse.csr_array, + ["indices", "indptr"], + ), + ( + scipy.sparse.csc_array, + ["indices", "indptr"], + ), + ( + scipy.sparse.coo_array, + ["row", "col"], + ), + ] +) +@pytest.mark.parametrize("expected_dtype", [np.int64, np.int32]) +def test_index_dtype_compressed(cls, indices_attrs, expected_dtype): + input_array = scipy.sparse.coo_array(np.arange(9).reshape(3, 3)) + coo_tuple = ( + input_array.data, + ( + input_array.row.astype(expected_dtype), + input_array.col.astype(expected_dtype), + ) + ) + + result = cls(coo_tuple) + for attr in indices_attrs: + assert getattr(result, attr).dtype == expected_dtype + + result = cls(coo_tuple, shape=(3, 3)) + for attr in indices_attrs: + assert getattr(result, attr).dtype == expected_dtype + + if issubclass(cls, scipy.sparse._compressed._cs_matrix): + input_array_csr = input_array.tocsr() + csr_tuple = ( + input_array_csr.data, + input_array_csr.indices.astype(expected_dtype), + input_array_csr.indptr.astype(expected_dtype), + ) + + result = cls(csr_tuple) + for attr in indices_attrs: + assert getattr(result, attr).dtype == expected_dtype + + result = cls(csr_tuple, shape=(3, 3)) + for attr in indices_attrs: + assert getattr(result, attr).dtype == expected_dtype + + +def test_default_is_matrix_diags(): + m = scipy.sparse.diags([0.0, 1.0, 2.0]) + assert not isinstance(m, scipy.sparse.sparray) + + +def test_default_is_matrix_eye(): + m = scipy.sparse.eye(3) + assert not isinstance(m, scipy.sparse.sparray) + + +def test_default_is_matrix_spdiags(): + m = scipy.sparse.spdiags([1.0, 2.0, 3.0], 0, 3, 3) + assert not isinstance(m, scipy.sparse.sparray) + + +def test_default_is_matrix_identity(): + m = scipy.sparse.identity(3) + assert not isinstance(m, scipy.sparse.sparray) + + +def test_default_is_matrix_kron_dense(): + m = scipy.sparse.kron( + np.array([[1, 2], [3, 4]]), np.array([[4, 3], [2, 1]]) + ) + assert not isinstance(m, scipy.sparse.sparray) + + +def test_default_is_matrix_kron_sparse(): + m = scipy.sparse.kron( + np.array([[1, 2], [3, 4]]), np.array([[1, 0], [0, 0]]) + ) + assert not isinstance(m, scipy.sparse.sparray) + + +def test_default_is_matrix_kronsum(): + m = scipy.sparse.kronsum( + np.array([[1, 0], [0, 1]]), np.array([[0, 1], [1, 0]]) + ) + assert not isinstance(m, scipy.sparse.sparray) + + +def test_default_is_matrix_random(): + m = scipy.sparse.random(3, 3) + assert not isinstance(m, scipy.sparse.sparray) + + +def test_default_is_matrix_rand(): + m = scipy.sparse.rand(3, 3) + assert not isinstance(m, scipy.sparse.sparray) + + +@pytest.mark.parametrize("fn", (scipy.sparse.hstack, scipy.sparse.vstack)) +def test_default_is_matrix_stacks(fn): + """Same idea as `test_default_construction_fn_matrices`, but for the + stacking creation functions.""" + A = scipy.sparse.coo_matrix(np.eye(2)) + B = scipy.sparse.coo_matrix([[0, 1], [1, 0]]) + m = fn([A, B]) + assert not isinstance(m, scipy.sparse.sparray) + + +def test_blocks_default_construction_fn_matrices(): + """Same idea as `test_default_construction_fn_matrices`, but for the block + creation function""" + A = scipy.sparse.coo_matrix(np.eye(2)) + B = scipy.sparse.coo_matrix([[2], [0]]) + C = scipy.sparse.coo_matrix([[3]]) + + # block diag + m = scipy.sparse.block_diag((A, B, C)) + assert not isinstance(m, scipy.sparse.sparray) + + # bmat + m = scipy.sparse.bmat([[A, None], [None, C]]) + assert not isinstance(m, scipy.sparse.sparray) + + +def test_format_property(): + for fmt in sparray_types: + arr_cls = getattr(scipy.sparse, f"{fmt}_array") + M = arr_cls([[1, 2]]) + assert M.format == fmt + assert M._format == fmt + with pytest.raises(AttributeError): + M.format = "qqq" + + +def test_issparse(): + m = scipy.sparse.eye(3) + a = scipy.sparse.csr_array(m) + assert not isinstance(m, scipy.sparse.sparray) + assert isinstance(a, scipy.sparse.sparray) + + # Both sparse arrays and sparse matrices should be sparse + assert scipy.sparse.issparse(a) + assert scipy.sparse.issparse(m) + + # ndarray and array_likes are not sparse + assert not scipy.sparse.issparse(a.todense()) + assert not scipy.sparse.issparse(m.todense()) + + +def test_isspmatrix(): + m = scipy.sparse.eye(3) + a = scipy.sparse.csr_array(m) + assert not isinstance(m, scipy.sparse.sparray) + assert isinstance(a, scipy.sparse.sparray) + + # Should only be true for sparse matrices, not sparse arrays + assert not scipy.sparse.isspmatrix(a) + assert scipy.sparse.isspmatrix(m) + + # ndarray and array_likes are not sparse + assert not scipy.sparse.isspmatrix(a.todense()) + assert not scipy.sparse.isspmatrix(m.todense()) + + +@pytest.mark.parametrize( + ("fmt", "fn"), + ( + ("bsr", scipy.sparse.isspmatrix_bsr), + ("coo", scipy.sparse.isspmatrix_coo), + ("csc", scipy.sparse.isspmatrix_csc), + ("csr", scipy.sparse.isspmatrix_csr), + ("dia", scipy.sparse.isspmatrix_dia), + ("dok", scipy.sparse.isspmatrix_dok), + ("lil", scipy.sparse.isspmatrix_lil), + ), +) +def test_isspmatrix_format(fmt, fn): + m = scipy.sparse.eye(3, format=fmt) + a = scipy.sparse.csr_array(m).asformat(fmt) + assert not isinstance(m, scipy.sparse.sparray) + assert isinstance(a, scipy.sparse.sparray) + + # Should only be true for sparse matrices, not sparse arrays + assert not fn(a) + assert fn(m) + + # ndarray and array_likes are not sparse + assert not fn(a.todense()) + assert not fn(m.todense()) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_base.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_base.py new file mode 100644 index 0000000000000000000000000000000000000000..160234c95c4933e53e00e6bc429b882a3c567916 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_base.py @@ -0,0 +1,5908 @@ +# +# Authors: Travis Oliphant, Ed Schofield, Robert Cimrman, Nathan Bell, and others + +""" Test functions for sparse matrices. Each class in the "Matrix class +based tests" section become subclasses of the classes in the "Generic +tests" section. This is done by the functions in the "Tailored base +class for generic tests" section. + +""" + + +import contextlib +import functools +import operator +import platform +import itertools +import sys +import warnings + +import pytest +from pytest import raises as assert_raises + +import numpy as np +from numpy import (arange, zeros, array, dot, asarray, + vstack, ndarray, transpose, diag, kron, inf, conjugate, + int8) + +import random +from numpy.testing import (assert_equal, assert_array_equal, + assert_array_almost_equal, assert_almost_equal, assert_, + assert_allclose) +from numpy.exceptions import ComplexWarning + +from types import GenericAlias + +import scipy.linalg + +import scipy.sparse as sparse +from scipy.sparse import (csc_matrix, csr_matrix, dok_matrix, + coo_matrix, lil_matrix, dia_matrix, bsr_matrix, + csc_array, csr_array, dok_array, + coo_array, lil_array, dia_array, bsr_array, + eye, issparse, SparseEfficiencyWarning, sparray, spmatrix) +from scipy.sparse._base import _formats +from scipy.sparse._sputils import (supported_dtypes, isscalarlike, + get_index_dtype, asmatrix, matrix) +from scipy.sparse.linalg import splu, expm, inv + +IS_COLAB = ('google.colab' in sys.modules) + + +def assert_in(member, collection, msg=None): + message = msg if msg is not None else f"{member!r} not found in {collection!r}" + assert_(member in collection, msg=message) + + +def assert_array_equal_dtype(x, y, **kwargs): + assert_(x.dtype == y.dtype) + assert_array_equal(x, y, **kwargs) + + +NON_ARRAY_BACKED_FORMATS = frozenset(['dok']) + +WMSG = "Changing the sparsity structure" + +def sparse_may_share_memory(A, B): + # Checks if A and B have any numpy array sharing memory. + + def _underlying_arrays(x): + # Given any object (e.g. a sparse array), returns all numpy arrays + # stored in any attribute. + + arrays = [] + for a in x.__dict__.values(): + if isinstance(a, np.ndarray | np.generic): + arrays.append(a) + return arrays + + for a in _underlying_arrays(A): + for b in _underlying_arrays(B): + if np.may_share_memory(a, b): + return True + return False + + +def with_64bit_maxval_limit(maxval_limit=None, random=False, fixed_dtype=None, + downcast_maxval=None, assert_32bit=False): + """ + Monkeypatch the maxval threshold at which scipy.sparse switches to + 64-bit index arrays, or make it (pseudo-)random. + + """ + if maxval_limit is None: + maxval_limit = np.int64(10) + else: + # Ensure we use numpy scalars rather than Python scalars (matters for + # NEP 50 casting rule changes) + maxval_limit = np.int64(maxval_limit) + + if assert_32bit: + def new_get_index_dtype(arrays=(), maxval=None, check_contents=False): + tp = get_index_dtype(arrays, maxval, check_contents) + assert_equal(np.iinfo(tp).max, np.iinfo(np.int32).max) + assert_(tp == np.int32 or tp == np.intc) + return tp + elif fixed_dtype is not None: + def new_get_index_dtype(arrays=(), maxval=None, check_contents=False): + return fixed_dtype + elif random: + rng = np.random.default_rng(1234) + def new_get_index_dtype(arrays=(), maxval=None, check_contents=False): + return (np.int32, np.int64)[rng.integers(2)] + else: + def new_get_index_dtype(arrays=(), maxval=None, check_contents=False): + dtype = np.int32 + if maxval is not None: + if maxval > maxval_limit: + dtype = np.int64 + for arr in arrays: + arr = np.asarray(arr) + if arr.dtype > np.int32: + if check_contents: + if arr.size == 0: + # a bigger type not needed + continue + elif np.issubdtype(arr.dtype, np.integer): + maxval = arr.max() + minval = arr.min() + if minval >= -maxval_limit and maxval <= maxval_limit: + # a bigger type not needed + continue + dtype = np.int64 + return dtype + + if downcast_maxval is not None: + def new_downcast_intp_index(arr): + if arr.max() > downcast_maxval: + raise AssertionError("downcast limited") + return arr.astype(np.intp) + + def decorator(func): + backup = [] + modules = [scipy.sparse._bsr, scipy.sparse._coo, scipy.sparse._csc, + scipy.sparse._csr, scipy.sparse._dia, scipy.sparse._dok, + scipy.sparse._lil, scipy.sparse._sputils, + scipy.sparse._compressed, scipy.sparse._construct] + + @functools.wraps(func) + def wrapper(*a, **kw): + try: + for mod in modules: + backup.append(( + mod, + 'get_index_dtype', + getattr(mod, 'get_index_dtype', None) + )) + setattr(mod, 'get_index_dtype', new_get_index_dtype) + + if downcast_maxval is not None: + backup.append(( + mod, + 'downcast_intp_index', + getattr(mod, 'downcast_intp_index', None) + )) + setattr(mod, 'downcast_intp_index', new_downcast_intp_index) + + return func(*a, **kw) + finally: + for mod, name, oldfunc in backup: + if oldfunc is not None: + setattr(mod, name, oldfunc) + return wrapper + return decorator + + +def toarray(a): + if isinstance(a, np.ndarray) or isscalarlike(a): + return a + return a.toarray() + + +class BinopTester: + # Custom type to test binary operations on sparse matrices. + + def __add__(self, mat): + return "matrix on the right" + + def __mul__(self, mat): + return "matrix on the right" + + def __sub__(self, mat): + return "matrix on the right" + + def __radd__(self, mat): + return "matrix on the left" + + def __rmul__(self, mat): + return "matrix on the left" + + def __rsub__(self, mat): + return "matrix on the left" + + def __matmul__(self, mat): + return "matrix on the right" + + def __rmatmul__(self, mat): + return "matrix on the left" + +class BinopTester_with_shape: + # Custom type to test binary operations on sparse matrices + # with object which has shape attribute. + def __init__(self,shape): + self._shape = shape + + def shape(self): + return self._shape + + def ndim(self): + return len(self._shape) + + def __add__(self, mat): + return "matrix on the right" + + def __mul__(self, mat): + return "matrix on the right" + + def __sub__(self, mat): + return "matrix on the right" + + def __radd__(self, mat): + return "matrix on the left" + + def __rmul__(self, mat): + return "matrix on the left" + + def __rsub__(self, mat): + return "matrix on the left" + + def __matmul__(self, mat): + return "matrix on the right" + + def __rmatmul__(self, mat): + return "matrix on the left" + +class ComparisonTester: + # Custom type to test comparison operations on sparse matrices. + def __eq__(self, other): + return "eq" + + def __ne__(self, other): + return "ne" + + def __lt__(self, other): + return "lt" + + def __le__(self, other): + return "le" + + def __gt__(self, other): + return "gt" + + def __ge__(self, other): + return "ge" + + +#------------------------------------------------------------------------------ +# Generic tests +#------------------------------------------------------------------------------ + + +class _MatrixMixin: + """mixin to easily allow tests of both sparray and spmatrix""" + bsr_container = bsr_matrix + coo_container = coo_matrix + csc_container = csc_matrix + csr_container = csr_matrix + dia_container = dia_matrix + dok_container = dok_matrix + lil_container = lil_matrix + asdense = staticmethod(asmatrix) + + def test_getrow(self): + assert_array_equal(self.datsp.getrow(1).toarray(), self.dat[[1], :]) + assert_array_equal(self.datsp.getrow(-1).toarray(), self.dat[[-1], :]) + + def test_getcol(self): + assert_array_equal(self.datsp.getcol(1).toarray(), self.dat[:, [1]]) + assert_array_equal(self.datsp.getcol(-1).toarray(), self.dat[:, [-1]]) + + def test_asfptype(self): + A = self.spcreator(arange(6,dtype='int32').reshape(2,3)) + + assert_equal(A.asfptype().dtype, np.dtype('float64')) + assert_equal(A.asfptype().format, A.format) + assert_equal(A.astype('int16').asfptype().dtype, np.dtype('float32')) + assert_equal(A.astype('complex128').asfptype().dtype, np.dtype('complex128')) + + B = A.asfptype() + C = B.asfptype() + assert_(B is C) + + +# TODO test prune +# TODO test has_sorted_indices +class _TestCommon: + """test common functionality shared by all sparse formats""" + math_dtypes = supported_dtypes + + bsr_container = bsr_array + coo_container = coo_array + csc_container = csc_array + csr_container = csr_array + dia_container = dia_array + dok_container = dok_array + lil_container = lil_array + asdense = array + + @classmethod + def init_class(cls): + # Canonical data. + cls.dat = array([[1, 0, 0, 2], [3, 0, 1, 0], [0, 2, 0, 0]], 'd') + cls.datsp = cls.spcreator(cls.dat) + + # Some sparse and dense matrices with data for every supported dtype. + # This set union is a workaround for numpy#6295, which means that + # two np.int64 dtypes don't hash to the same value. + cls.checked_dtypes = set(supported_dtypes).union(cls.math_dtypes) + cls.dat_dtypes = {} + cls.datsp_dtypes = {} + for dtype in cls.checked_dtypes: + cls.dat_dtypes[dtype] = cls.dat.astype(dtype) + cls.datsp_dtypes[dtype] = cls.spcreator(cls.dat.astype(dtype)) + + # Check that the original data is equivalent to the + # corresponding dat_dtypes & datsp_dtypes. + assert_equal(cls.dat, cls.dat_dtypes[np.float64]) + assert_equal(cls.datsp.toarray(), + cls.datsp_dtypes[np.float64].toarray()) + + cls.is_array_test = isinstance(cls.datsp, sparray) + + def test_bool(self): + def check(dtype): + datsp = self.datsp_dtypes[dtype] + + assert_raises(ValueError, bool, datsp) + assert_(self.spcreator([[1]])) + assert_(not self.spcreator([[0]])) + + if isinstance(self, TestDOK): + pytest.skip("Cannot create a rank <= 2 DOK matrix.") + for dtype in self.checked_dtypes: + check(dtype) + + def test_bool_rollover(self): + # bool's underlying dtype is 1 byte, check that it does not + # rollover True -> False at 256. + dat = array([[True, False]]) + datsp = self.spcreator(dat) + + for _ in range(10): + datsp = datsp + datsp + dat = dat + dat + assert_array_equal(dat, datsp.toarray()) + + def test_eq(self): + + def check(dtype): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + warnings.simplefilter("ignore", ComplexWarning) + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + dat2 = dat.copy() + dat2[:,0] = 0 + datsp2 = self.spcreator(dat2) + datbsr = self.bsr_container(dat) + datcsr = self.csr_container(dat) + datcsc = self.csc_container(dat) + datlil = self.lil_container(dat) + + # sparse/sparse + assert_array_equal_dtype(dat == dat2, (datsp == datsp2).toarray()) + # mix sparse types + assert_array_equal_dtype(dat == dat2, (datbsr == datsp2).toarray()) + assert_array_equal_dtype(dat == dat2, (datcsr == datsp2).toarray()) + assert_array_equal_dtype(dat == dat2, (datcsc == datsp2).toarray()) + assert_array_equal_dtype(dat == dat2, (datlil == datsp2).toarray()) + # sparse/dense + assert_array_equal_dtype(dat == datsp2, datsp2 == dat) + # sparse/scalar + assert_array_equal_dtype(dat == 0, (datsp == 0).toarray()) + assert_array_equal_dtype(dat == 1, (datsp == 1).toarray()) + assert_array_equal_dtype(dat == np.nan, + (datsp == np.nan).toarray()) + + if self.datsp.format not in ['bsr', 'csc', 'csr']: + pytest.skip("Bool comparisons only implemented for BSR, CSC, and CSR.") + for dtype in self.checked_dtypes: + check(dtype) + + def test_ne(self): + def check(dtype): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + warnings.simplefilter("ignore", ComplexWarning) + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + dat2 = dat.copy() + dat2[:,0] = 0 + datsp2 = self.spcreator(dat2) + datbsr = self.bsr_container(dat) + datcsc = self.csc_container(dat) + datcsr = self.csr_container(dat) + datlil = self.lil_container(dat) + + # sparse/sparse + assert_array_equal_dtype(dat != dat2, (datsp != datsp2).toarray()) + # mix sparse types + assert_array_equal_dtype(dat != dat2, (datbsr != datsp2).toarray()) + assert_array_equal_dtype(dat != dat2, (datcsc != datsp2).toarray()) + assert_array_equal_dtype(dat != dat2, (datcsr != datsp2).toarray()) + assert_array_equal_dtype(dat != dat2, (datlil != datsp2).toarray()) + # sparse/dense + assert_array_equal_dtype(dat != datsp2, datsp2 != dat) + # sparse/scalar + assert_array_equal_dtype(dat != 0, (datsp != 0).toarray()) + assert_array_equal_dtype(dat != 1, (datsp != 1).toarray()) + assert_array_equal_dtype(0 != dat, (0 != datsp).toarray()) + assert_array_equal_dtype(1 != dat, (1 != datsp).toarray()) + assert_array_equal_dtype(dat != np.nan, + (datsp != np.nan).toarray()) + + if self.datsp.format not in ['bsr', 'csc', 'csr']: + pytest.skip("Bool comparisons only implemented for BSR, CSC, and CSR.") + for dtype in self.checked_dtypes: + check(dtype) + + def test_eq_ne_different_shapes(self): + if self.datsp.format not in ['bsr', 'csc', 'csr']: + pytest.skip("Bool comparisons only implemented for BSR, CSC, and CSR.") + # Is this what we want? numpy raises when shape differs. we return False. + assert (self.datsp == self.datsp.T) is False + assert (self.datsp != self.datsp.T) is True + + def test_lt(self): + def check(dtype): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + warnings.simplefilter("ignore", ComplexWarning) + # data + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + dat2 = dat.copy() + dat2[:,0] = 0 + datsp2 = self.spcreator(dat2) + datcomplex = dat.astype(complex) + datcomplex[:,0] = 1 + 1j + datspcomplex = self.spcreator(datcomplex) + datbsr = self.bsr_container(dat) + datcsc = self.csc_container(dat) + datcsr = self.csr_container(dat) + datlil = self.lil_container(dat) + + # sparse/sparse + assert_array_equal_dtype(dat < dat2, (datsp < datsp2).toarray()) + assert_array_equal_dtype(datcomplex < dat2, + (datspcomplex < datsp2).toarray()) + # mix sparse types + assert_array_equal_dtype(dat < dat2, (datbsr < datsp2).toarray()) + assert_array_equal_dtype(dat < dat2, (datcsc < datsp2).toarray()) + assert_array_equal_dtype(dat < dat2, (datcsr < datsp2).toarray()) + assert_array_equal_dtype(dat < dat2, (datlil < datsp2).toarray()) + + assert_array_equal_dtype(dat2 < dat, (datsp2 < datbsr).toarray()) + assert_array_equal_dtype(dat2 < dat, (datsp2 < datcsc).toarray()) + assert_array_equal_dtype(dat2 < dat, (datsp2 < datcsr).toarray()) + assert_array_equal_dtype(dat2 < dat, (datsp2 < datlil).toarray()) + # sparse/dense + assert_array_equal_dtype(dat < dat2, datsp < dat2) + assert_array_equal_dtype(datcomplex < dat2, datspcomplex < dat2) + # sparse/scalar + for val in [2, 1, 0, -1, -2]: + val = np.int64(val) # avoid Python scalar (due to NEP 50 changes) + assert_array_equal_dtype((datsp < val).toarray(), dat < val) + assert_array_equal_dtype((val < datsp).toarray(), val < dat) + + with np.errstate(invalid='ignore'): + assert_array_equal_dtype((datsp < np.nan).toarray(), + dat < np.nan) + + # data + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + dat2 = dat.copy() + dat2[:,0] = 0 + datsp2 = self.spcreator(dat2) + + # dense rhs + assert_array_equal_dtype(dat < datsp2, datsp < dat2) + + if self.datsp.format not in ['bsr', 'csc', 'csr']: + pytest.skip("Bool comparisons only implemented for BSR, CSC, and CSR.") + for dtype in self.checked_dtypes: + check(dtype) + + def test_gt(self): + def check(dtype): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + warnings.simplefilter("ignore", ComplexWarning) + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + dat2 = dat.copy() + dat2[:,0] = 0 + datsp2 = self.spcreator(dat2) + datcomplex = dat.astype(complex) + datcomplex[:,0] = 1 + 1j + datspcomplex = self.spcreator(datcomplex) + datbsr = self.bsr_container(dat) + datcsc = self.csc_container(dat) + datcsr = self.csr_container(dat) + datlil = self.lil_container(dat) + + # sparse/sparse + assert_array_equal_dtype(dat > dat2, (datsp > datsp2).toarray()) + assert_array_equal_dtype(datcomplex > dat2, + (datspcomplex > datsp2).toarray()) + # mix sparse types + assert_array_equal_dtype(dat > dat2, (datbsr > datsp2).toarray()) + assert_array_equal_dtype(dat > dat2, (datcsc > datsp2).toarray()) + assert_array_equal_dtype(dat > dat2, (datcsr > datsp2).toarray()) + assert_array_equal_dtype(dat > dat2, (datlil > datsp2).toarray()) + + assert_array_equal_dtype(dat2 > dat, (datsp2 > datbsr).toarray()) + assert_array_equal_dtype(dat2 > dat, (datsp2 > datcsc).toarray()) + assert_array_equal_dtype(dat2 > dat, (datsp2 > datcsr).toarray()) + assert_array_equal_dtype(dat2 > dat, (datsp2 > datlil).toarray()) + # sparse/dense + assert_array_equal_dtype(dat > dat2, datsp > dat2) + assert_array_equal_dtype(datcomplex > dat2, datspcomplex > dat2) + # sparse/scalar + for val in [2, 1, 0, -1, -2]: + val = np.int64(val) # avoid Python scalar (due to NEP 50 changes) + assert_array_equal_dtype((datsp > val).toarray(), dat > val) + assert_array_equal_dtype((val > datsp).toarray(), val > dat) + + with np.errstate(invalid='ignore'): + assert_array_equal_dtype((datsp > np.nan).toarray(), + dat > np.nan) + + # data + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + dat2 = dat.copy() + dat2[:,0] = 0 + datsp2 = self.spcreator(dat2) + + # dense rhs + assert_array_equal_dtype(dat > datsp2, datsp > dat2) + + if self.datsp.format not in ['bsr', 'csc', 'csr']: + pytest.skip("Bool comparisons only implemented for BSR, CSC, and CSR.") + for dtype in self.checked_dtypes: + check(dtype) + + def test_le(self): + def check(dtype): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + warnings.simplefilter("ignore", ComplexWarning) + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + dat2 = dat.copy() + dat2[:,0] = 0 + datsp2 = self.spcreator(dat2) + datcomplex = dat.astype(complex) + datcomplex[:,0] = 1 + 1j + datspcomplex = self.spcreator(datcomplex) + datbsr = self.bsr_container(dat) + datcsc = self.csc_container(dat) + datcsr = self.csr_container(dat) + datlil = self.lil_container(dat) + + # sparse/sparse + assert_array_equal_dtype(dat <= dat2, (datsp <= datsp2).toarray()) + assert_array_equal_dtype(datcomplex <= dat2, + (datspcomplex <= datsp2).toarray()) + # mix sparse types + assert_array_equal_dtype((datbsr <= datsp2).toarray(), dat <= dat2) + assert_array_equal_dtype((datcsc <= datsp2).toarray(), dat <= dat2) + assert_array_equal_dtype((datcsr <= datsp2).toarray(), dat <= dat2) + assert_array_equal_dtype((datlil <= datsp2).toarray(), dat <= dat2) + + assert_array_equal_dtype((datsp2 <= datbsr).toarray(), dat2 <= dat) + assert_array_equal_dtype((datsp2 <= datcsc).toarray(), dat2 <= dat) + assert_array_equal_dtype((datsp2 <= datcsr).toarray(), dat2 <= dat) + assert_array_equal_dtype((datsp2 <= datlil).toarray(), dat2 <= dat) + # sparse/dense + assert_array_equal_dtype(datsp <= dat2, dat <= dat2) + assert_array_equal_dtype(datspcomplex <= dat2, datcomplex <= dat2) + # sparse/scalar + for val in [2, 1, -1, -2]: + val = np.int64(val) # avoid Python scalar (due to NEP 50 changes) + assert_array_equal_dtype((datsp <= val).toarray(), dat <= val) + assert_array_equal_dtype((val <= datsp).toarray(), val <= dat) + + # data + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + dat2 = dat.copy() + dat2[:,0] = 0 + datsp2 = self.spcreator(dat2) + + # dense rhs + assert_array_equal_dtype(dat <= datsp2, datsp <= dat2) + + if self.datsp.format not in ['bsr', 'csc', 'csr']: + pytest.skip("Bool comparisons only implemented for BSR, CSC, and CSR.") + for dtype in self.checked_dtypes: + check(dtype) + + def test_ge(self): + def check(dtype): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + warnings.simplefilter("ignore", ComplexWarning) + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + dat2 = dat.copy() + dat2[:,0] = 0 + datsp2 = self.spcreator(dat2) + datcomplex = dat.astype(complex) + datcomplex[:,0] = 1 + 1j + datspcomplex = self.spcreator(datcomplex) + datbsr = self.bsr_container(dat) + datcsc = self.csc_container(dat) + datcsr = self.csr_container(dat) + datlil = self.lil_container(dat) + + # sparse/sparse + assert_array_equal_dtype(dat >= dat2, (datsp >= datsp2).toarray()) + assert_array_equal_dtype(datcomplex >= dat2, + (datspcomplex >= datsp2).toarray()) + # mix sparse types + assert_array_equal_dtype((datbsr >= datsp2).toarray(), dat >= dat2) + assert_array_equal_dtype((datcsc >= datsp2).toarray(), dat >= dat2) + assert_array_equal_dtype((datcsr >= datsp2).toarray(), dat >= dat2) + assert_array_equal_dtype((datlil >= datsp2).toarray(), dat >= dat2) + + assert_array_equal_dtype((datsp2 >= datbsr).toarray(), dat2 >= dat) + assert_array_equal_dtype((datsp2 >= datcsc).toarray(), dat2 >= dat) + assert_array_equal_dtype((datsp2 >= datcsr).toarray(), dat2 >= dat) + assert_array_equal_dtype((datsp2 >= datlil).toarray(), dat2 >= dat) + # sparse/dense + assert_array_equal_dtype(datsp >= dat2, dat >= dat2) + assert_array_equal_dtype(datspcomplex >= dat2, datcomplex >= dat2) + # sparse/scalar + for val in [2, 1, -1, -2]: + val = np.int64(val) # avoid Python scalar (due to NEP 50 changes) + assert_array_equal_dtype((datsp >= val).toarray(), dat >= val) + assert_array_equal_dtype((val >= datsp).toarray(), val >= dat) + + # dense data + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + dat2 = dat.copy() + dat2[:,0] = 0 + datsp2 = self.spcreator(dat2) + + # dense rhs + assert_array_equal_dtype(dat >= datsp2, datsp >= dat2) + + if self.datsp.format not in ['bsr', 'csc', 'csr']: + pytest.skip("Bool comparisons only implemented for BSR, CSC, and CSR.") + for dtype in self.checked_dtypes: + check(dtype) + + def test_empty(self): + # create empty matrices + assert_equal(self.spcreator((3, 3)).toarray(), zeros((3, 3))) + assert_equal(self.spcreator((3, 3)).nnz, 0) + assert_equal(self.spcreator((3, 3)).count_nonzero(), 0) + if self.datsp.format in ["coo", "csr", "csc", "lil"]: + assert_equal(self.spcreator((3, 3)).count_nonzero(axis=0), array([0, 0, 0])) + + def test_count_nonzero(self): + axis_support = self.datsp.format in ["coo", "csr", "csc", "lil"] + axes = [None, 0, 1, -1, -2] if axis_support else [None] + + for A in (self.datsp, self.datsp.T): + for ax in axes: + expected = np.count_nonzero(A.toarray(), axis=ax) + assert_equal(A.count_nonzero(axis=ax), expected) + + if not axis_support: + with assert_raises(NotImplementedError, match="not implemented .* format"): + self.datsp.count_nonzero(axis=0) + + def test_invalid_shapes(self): + assert_raises(ValueError, self.spcreator, (-1,3)) + assert_raises(ValueError, self.spcreator, (3,-1)) + assert_raises(ValueError, self.spcreator, (-1,-1)) + + def test_repr(self): + datsp = self.spcreator([[1, 0, 0], [0, 0, 0], [0, 0, -2]]) + extra = ( + "(1 diagonals) " if datsp.format == "dia" + else "(blocksize=1x1) " if datsp.format == "bsr" + else "" + ) + _, fmt = _formats[datsp.format] + sparse_cls = "array" if self.is_array_test else "matrix" + expected = ( + f"<{fmt} sparse {sparse_cls} of dtype '{datsp.dtype}'\n" + f"\twith {datsp.nnz} stored elements {extra}and shape {datsp.shape}>" + ) + assert repr(datsp) == expected + + def test_str_maxprint(self): + datsp = self.spcreator(np.arange(75).reshape(5, 15)) + assert datsp.maxprint == 50 + assert len(str(datsp).split('\n')) == 51 + 3 + + dat = np.arange(15).reshape(5,3) + datsp = self.spcreator(dat) + # format dia reports nnz=15, but we want 14 + nnz_small = 14 if datsp.format == 'dia' else datsp.nnz + datsp_mp6 = self.spcreator(dat, maxprint=6) + + assert len(str(datsp).split('\n')) == nnz_small + 3 + assert len(str(datsp_mp6).split('\n')) == 6 + 4 + + # Check parameter `maxprint` is keyword only + datsp = self.spcreator(dat, shape=(5, 3), dtype='i', copy=False, maxprint=4) + datsp = self.spcreator(dat, (5, 3), 'i', False, maxprint=4) + with pytest.raises(TypeError, match="positional argument|unpack non-iterable"): + self.spcreator(dat, (5, 3), 'i', False, 4) + + def test_str(self): + datsp = self.spcreator([[1, 0, 0], [0, 0, 0], [0, 0, -2]]) + if datsp.nnz != 2: + return + extra = ( + "(1 diagonals) " if datsp.format == "dia" + else "(blocksize=1x1) " if datsp.format == "bsr" + else "" + ) + _, fmt = _formats[datsp.format] + sparse_cls = "array" if self.is_array_test else "matrix" + expected = ( + f"<{fmt} sparse {sparse_cls} of dtype '{datsp.dtype}'\n" + f"\twith {datsp.nnz} stored elements {extra}and shape {datsp.shape}>" + "\n Coords\tValues" + "\n (0, 0)\t1" + "\n (2, 2)\t-2" + ) + assert str(datsp) == expected + + def test_empty_arithmetic(self): + # Test manipulating empty matrices. Fails in SciPy SVN <= r1768 + shape = (5, 5) + for mytype in [np.dtype('int32'), np.dtype('float32'), + np.dtype('float64'), np.dtype('complex64'), + np.dtype('complex128')]: + a = self.spcreator(shape, dtype=mytype) + b = a + a + c = 2 * a + d = a @ a.tocsc() + e = a @ a.tocsr() + f = a @ a.tocoo() + for m in [a,b,c,d,e,f]: + assert_equal(m.toarray(), a.toarray()@a.toarray()) + # These fail in all revisions <= r1768: + assert_equal(m.dtype,mytype) + assert_equal(m.toarray().dtype,mytype) + + def test_abs(self): + A = array([[-1, 0, 17], [0, -5, 0], [1, -4, 0], [0, 0, 0]], 'd') + assert_equal(abs(A), abs(self.spcreator(A)).toarray()) + + def test_round(self): + decimal = 1 + A = array([[-1.35, 0.56], [17.25, -5.98]], 'd') + assert_equal(np.around(A, decimals=decimal), + round(self.spcreator(A), ndigits=decimal).toarray()) + + def test_elementwise_power(self): + A = array([[-4, -3, -2], [-1, 0, 1], [2, 3, 4]], 'd') + assert_equal(np.power(A, 2), self.spcreator(A).power(2).toarray()) + + #it's element-wise power function, input has to be a scalar + assert_raises(NotImplementedError, self.spcreator(A).power, A) + + def test_neg(self): + A = array([[-1, 0, 17], [0, -5, 0], [1, -4, 0], [0, 0, 0]], 'd') + assert_equal(-A, (-self.spcreator(A)).toarray()) + + # see gh-5843 + A = array([[True, False, False], [False, False, True]]) + assert_raises(NotImplementedError, self.spcreator(A).__neg__) + + def test_real(self): + D = array([[1 + 3j, 2 - 4j]]) + A = self.spcreator(D) + assert_equal(A.real.toarray(), D.real) + + def test_imag(self): + D = array([[1 + 3j, 2 - 4j]]) + A = self.spcreator(D) + assert_equal(A.imag.toarray(), D.imag) + + def test_diagonal(self): + # Does the matrix's .diagonal() method work? + mats = [] + mats.append([[1,0,2]]) + mats.append([[1],[0],[2]]) + mats.append([[0,1],[0,2],[0,3]]) + mats.append([[0,0,1],[0,0,2],[0,3,0]]) + mats.append([[1,0],[0,0]]) + + mats.append(kron(mats[0],[[1,2]])) + mats.append(kron(mats[0],[[1],[2]])) + mats.append(kron(mats[1],[[1,2],[3,4]])) + mats.append(kron(mats[2],[[1,2],[3,4]])) + mats.append(kron(mats[3],[[1,2],[3,4]])) + mats.append(kron(mats[3],[[1,2,3,4]])) + + for m in mats: + rows, cols = array(m).shape + sparse_mat = self.spcreator(m) + for k in range(-rows-1, cols+2): + assert_equal(sparse_mat.diagonal(k=k), diag(m, k=k)) + # Test for k beyond boundaries(issue #11949) + assert_equal(sparse_mat.diagonal(k=10), diag(m, k=10)) + assert_equal(sparse_mat.diagonal(k=-99), diag(m, k=-99)) + + # Test all-zero matrix. + assert_equal(self.spcreator((40, 16130)).diagonal(), np.zeros(40)) + # Test empty matrix + # https://github.com/scipy/scipy/issues/11949 + assert_equal(self.spcreator((0, 0)).diagonal(), np.empty(0)) + assert_equal(self.spcreator((15, 0)).diagonal(), np.empty(0)) + assert_equal(self.spcreator((0, 5)).diagonal(10), np.empty(0)) + + def test_trace(self): + # For square matrix + A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + B = self.spcreator(A) + for k in range(-2, 3): + assert_equal(A.trace(offset=k), B.trace(offset=k)) + + # For rectangular matrix + A = np.array([[1, 2, 3], [4, 5, 6]]) + B = self.spcreator(A) + for k in range(-1, 3): + assert_equal(A.trace(offset=k), B.trace(offset=k)) + + def test_reshape(self): + x = self.spcreator([[1, 0, 7], [0, 0, 0], [0, 3, 0], [0, 0, 5]]) + for order in ['C', 'F']: + for s in [(12, 1), (1, 12)]: + assert_array_equal(x.reshape(s, order=order).toarray(), + x.toarray().reshape(s, order=order)) + + # This example is taken from the stackoverflow answer at + # https://stackoverflow.com/q/16511879 + x = self.spcreator([[0, 10, 0, 0], [0, 0, 0, 0], [0, 20, 30, 40]]) + y = x.reshape((2, 6)) # Default order is 'C' + desired = [[0, 10, 0, 0, 0, 0], [0, 0, 0, 20, 30, 40]] + assert_array_equal(y.toarray(), desired) + + # Reshape with negative indexes + y = x.reshape((2, -1)) + assert_array_equal(y.toarray(), desired) + y = x.reshape((-1, 6)) + assert_array_equal(y.toarray(), desired) + assert_raises(ValueError, x.reshape, (-1, -1)) + + # Reshape with star args + y = x.reshape(2, 6) + assert_array_equal(y.toarray(), desired) + assert_raises(TypeError, x.reshape, 2, 6, not_an_arg=1) + + # Reshape with same size is noop unless copy=True + y = x.reshape((3, 4)) + assert_(y is x) + y = x.reshape((3, 4), copy=True) + assert_(y is not x) + + # Ensure reshape did not alter original size + assert_array_equal(x.shape, (3, 4)) + + if self.is_array_test: + with assert_raises(AttributeError, match="has no setter|n't set attribute"): + x.shape = (2, 6) + else: # spmatrix test + # Reshape in place + x.shape = (2, 6) + assert_array_equal(x.toarray(), desired) + + # Reshape to bad ndim + assert_raises(ValueError, x.reshape, (x.size,)) + assert_raises(ValueError, x.reshape, (1, x.size, 1)) + + @pytest.mark.slow + def test_setdiag_comprehensive(self): + def dense_setdiag(a, v, k): + v = np.asarray(v) + if k >= 0: + n = min(a.shape[0], a.shape[1] - k) + if v.ndim != 0: + n = min(n, len(v)) + v = v[:n] + i = np.arange(0, n) + j = np.arange(k, k + n) + a[i,j] = v + elif k < 0: + dense_setdiag(a.T, v, -k) + + def check_setdiag(a, b, k): + # Check setting diagonal using a scalar, a vector of + # correct length, and too short or too long vectors + for r in [-1, len(np.diag(a, k)), 2, 30]: + if r < 0: + v = np.random.choice(range(1, 20)) + else: + v = np.random.randint(1, 20, size=r) + + dense_setdiag(a, v, k) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + b.setdiag(v, k) + + # check that dense_setdiag worked + d = np.diag(a, k) + if np.asarray(v).ndim == 0: + assert_array_equal(d, v, err_msg="{msg} {r}") + else: + n = min(len(d), len(v)) + assert_array_equal(d[:n], v[:n], err_msg="{msg} {r}") + # check that sparse setdiag worked + assert_array_equal(b.toarray(), a, err_msg="{msg} {r}") + + # comprehensive test + np.random.seed(1234) + shapes = [(0,5), (5,0), (1,5), (5,1), (5,5)] + for dtype in [np.int8, np.float64]: + for m,n in shapes: + ks = np.arange(-m+1, n-1) + for k in ks: + a = np.zeros((m, n), dtype=dtype) + b = self.spcreator((m, n), dtype=dtype) + + check_setdiag(a, b, k) + + # check overwriting etc + for k2 in np.random.choice(ks, size=min(len(ks), 5)): + check_setdiag(a, b, k2) + + def test_setdiag(self): + # simple test cases + m = self.spcreator(np.eye(3)) + m2 = self.spcreator((4, 4)) + values = [3, 2, 1] + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + assert_raises(ValueError, m.setdiag, values, k=4) + m.setdiag(values) + assert_array_equal(m.diagonal(), values) + m.setdiag(values, k=1) + assert_array_equal(m.toarray(), np.array([[3, 3, 0], + [0, 2, 2], + [0, 0, 1]])) + m.setdiag(values, k=-2) + assert_array_equal(m.toarray(), np.array([[3, 3, 0], + [0, 2, 2], + [3, 0, 1]])) + m.setdiag((9,), k=2) + assert_array_equal(m.toarray()[0,2], 9) + m.setdiag((9,), k=-2) + assert_array_equal(m.toarray()[2,0], 9) + # test short values on an empty matrix + m2.setdiag([1], k=2) + assert_array_equal(m2.toarray()[0], [0, 0, 1, 0]) + # test overwriting that same diagonal + m2.setdiag([1, 1], k=2) + assert_array_equal(m2.toarray()[:2], [[0, 0, 1, 0], + [0, 0, 0, 1]]) + + def test_nonzero(self): + A = array([[1, 0, 1],[0, 1, 1],[0, 0, 1]]) + Asp = self.spcreator(A) + + A_nz = {tuple(ij) for ij in transpose(A.nonzero())} + Asp_nz = {tuple(ij) for ij in transpose(Asp.nonzero())} + + assert_equal(A_nz, Asp_nz) + + def test_numpy_nonzero(self): + # See gh-5987 + A = array([[1, 0, 1], [0, 1, 1], [0, 0, 1]]) + Asp = self.spcreator(A) + + A_nz = {tuple(ij) for ij in transpose(np.nonzero(A))} + Asp_nz = {tuple(ij) for ij in transpose(np.nonzero(Asp))} + + assert_equal(A_nz, Asp_nz) + + def test_sum(self): + np.random.seed(1234) + dat_1 = np.array([[0, 1, 2], + [3, -4, 5], + [-6, 7, 9]]) + dat_2 = np.random.rand(5, 5) + dat_3 = np.array([[]]) + dat_4 = np.zeros((40, 40)) + dat_5 = sparse.rand(5, 5, density=1e-2).toarray() + matrices = [dat_1, dat_2, dat_3, dat_4, dat_5] + + def check(dtype, j): + dat = self.asdense(matrices[j], dtype=dtype) + datsp = self.spcreator(dat, dtype=dtype) + with np.errstate(over='ignore'): + assert_array_almost_equal(dat.sum(), datsp.sum()) + assert_equal(dat.sum().dtype, datsp.sum().dtype) + assert_(np.isscalar(datsp.sum(axis=None))) + assert_array_almost_equal(dat.sum(axis=None), datsp.sum(axis=None)) + assert_equal(dat.sum(axis=None).dtype, datsp.sum(axis=None).dtype) + assert_array_almost_equal(dat.sum(axis=0), datsp.sum(axis=0)) + assert_equal(dat.sum(axis=0).dtype, datsp.sum(axis=0).dtype) + assert_array_almost_equal(dat.sum(axis=1), datsp.sum(axis=1)) + assert_equal(dat.sum(axis=1).dtype, datsp.sum(axis=1).dtype) + assert_array_almost_equal(dat.sum(axis=-2), datsp.sum(axis=-2)) + assert_equal(dat.sum(axis=-2).dtype, datsp.sum(axis=-2).dtype) + assert_array_almost_equal(dat.sum(axis=-1), datsp.sum(axis=-1)) + assert_equal(dat.sum(axis=-1).dtype, datsp.sum(axis=-1).dtype) + assert_array_almost_equal(dat.sum(axis=(0, 1)), datsp.sum(axis=(0, 1))) + assert_equal(dat.sum(axis=(0, 1)).dtype, datsp.sum(axis=(0, 1)).dtype) + + for dtype in self.checked_dtypes: + for j in range(len(matrices)): + check(dtype, j) + + def test_sum_invalid_params(self): + out = np.zeros((1, 3)) + dat = array([[0, 1, 2], + [3, -4, 5], + [-6, 7, 9]]) + datsp = self.spcreator(dat) + + with assert_raises(ValueError, match="axis out of range"): + datsp.sum(axis=3) + with assert_raises(ValueError, match="axis out of range"): + datsp.sum(axis=(0, 3)) + with assert_raises(TypeError, match="axis must be an integer"): + datsp.sum(axis=1.5) + # error msg varies by sparray (1d result) or spmatrix (2d result) + with assert_raises(ValueError, match="do.*n.t match.*shape|wrong.*dimensions"): + datsp.mean(axis=1, out=out) + + def test_sum_dtype(self): + dat = array([[0, 1, 2], + [3, -4, 5], + [-6, 7, 9]]) + datsp = self.spcreator(dat) + + def check(dtype): + dat_sum = dat.sum(dtype=dtype) + datsp_sum = datsp.sum(dtype=dtype) + + assert_array_almost_equal(dat_sum, datsp_sum) + assert_equal(dat_sum.dtype, datsp_sum.dtype) + + for dtype in self.checked_dtypes: + check(dtype) + + def test_sum_out(self): + keep = not self.is_array_test + dat = array([[0, 1, 2], + [3, -4, 5], + [-6, 7, 9]]) + datsp = self.spcreator(dat) + + dat_out = array(0) if self.is_array_test else array([[0]]) + datsp_out = array(0) if self.is_array_test else matrix([[0]]) + + dat.sum(out=dat_out, keepdims=keep) + datsp.sum(out=datsp_out) + assert_array_almost_equal(dat_out, datsp_out) + + dat_out = np.zeros((3,)) if self.is_array_test else np.zeros((3, 1)) + datsp_out = np.zeros((3,)) if self.is_array_test else matrix(np.zeros((3, 1))) + + dat.sum(axis=1, out=dat_out, keepdims=keep) + datsp.sum(axis=1, out=datsp_out) + assert_array_almost_equal(dat_out, datsp_out) + + # check that wrong shape out parameter raises + with assert_raises(ValueError, match="output parameter"): + datsp.sum(out=array([0])) + with assert_raises(ValueError, match="output parameter"): + datsp.sum(out=array([[0]] if self.is_array_test else 0)) + + def test_numpy_sum(self): + # See gh-5987 + dat = array([[0, 1, 2], + [3, -4, 5], + [-6, 7, 9]]) + datsp = self.spcreator(dat) + + dat_sum = np.sum(dat) + datsp_sum = np.sum(datsp) + + assert_array_almost_equal(dat_sum, datsp_sum) + assert_equal(dat_sum.dtype, datsp_sum.dtype) + + def test_sum_mean_container_type(self): + dat = array([[0, 1, 2], + [3, -4, 5], + [-6, 7, 9]]) + datsp = self.spcreator(dat) + + assert isscalarlike(datsp.sum()) + matrix_or_array = ndarray if self.is_array_test else np.matrix + assert isinstance(datsp.sum(axis=0), matrix_or_array) + assert isinstance(datsp.sum(axis=1), matrix_or_array) + + assert isscalarlike(datsp.mean()) + assert isinstance(datsp.mean(axis=0), matrix_or_array) + assert isinstance(datsp.mean(axis=1), matrix_or_array) + + def test_mean(self): + keep = not self.is_array_test + def check(dtype): + dat = array([[0, 1, 2], + [3, 4, 5], + [6, 7, 9]], dtype=dtype) + datsp = self.spcreator(dat, dtype=dtype) + + assert_array_almost_equal(dat.mean(), datsp.mean()) + assert_equal(dat.mean().dtype, datsp.mean().dtype) + assert_(np.isscalar(datsp.mean(axis=None))) + assert_array_almost_equal( + dat.mean(axis=None, keepdims=keep), datsp.mean(axis=None) + ) + assert_equal(dat.mean(axis=None).dtype, datsp.mean(axis=None).dtype) + assert_array_almost_equal( + dat.mean(axis=0, keepdims=keep), datsp.mean(axis=0) + ) + assert_equal(dat.mean(axis=0).dtype, datsp.mean(axis=0).dtype) + assert_array_almost_equal( + dat.mean(axis=1, keepdims=keep), datsp.mean(axis=1) + ) + assert_equal(dat.mean(axis=1).dtype, datsp.mean(axis=1).dtype) + assert_array_almost_equal( + dat.mean(axis=-2, keepdims=keep), datsp.mean(axis=-2) + ) + assert_equal(dat.mean(axis=-2).dtype, datsp.mean(axis=-2).dtype) + assert_array_almost_equal( + dat.mean(axis=-1, keepdims=keep), datsp.mean(axis=-1) + ) + assert_equal(dat.mean(axis=-1).dtype, datsp.mean(axis=-1).dtype) + assert_array_almost_equal( + dat.mean(axis=(0, 1), keepdims=keep), datsp.mean(axis=(0, 1)) + ) + assert_equal(dat.mean(axis=(0, 1)).dtype, datsp.mean(axis=(0, 1)).dtype) + + + for dtype in self.checked_dtypes: + check(dtype) + + def test_mean_invalid_param(self): + out = self.asdense(np.zeros((1, 3))) + dat = array([[0, 1, 2], + [3, -4, 5], + [-6, 7, 9]]) + datsp = self.spcreator(dat) + + with assert_raises(ValueError, match="axis out of range"): + datsp.mean(axis=3) + with assert_raises(ValueError, match="axis out of range"): + datsp.mean(axis=(0, 3)) + with assert_raises(TypeError, match="axis must be an integer"): + datsp.mean(axis=1.5) + # error msg varies by sparray (1d result) or spmatrix (2d result) + with assert_raises(ValueError, match="do.*n.t match.*shape|wrong.*dimensions"): + datsp.mean(axis=1, out=out) + + def test_mean_dtype(self): + dat = array([[0, 1, 2], + [3, -4, 5], + [-6, 7, 9]]) + datsp = self.spcreator(dat) + + def check(dtype): + dat_mean = dat.mean(dtype=dtype) + datsp_mean = datsp.mean(dtype=dtype) + + assert_array_almost_equal(dat_mean, datsp_mean) + assert_equal(dat_mean.dtype, datsp_mean.dtype) + + for dtype in self.checked_dtypes: + check(dtype) + + def test_mean_out(self): + keep = not self.is_array_test + dat = array([[0, 1, 2], + [3, -4, 5], + [-6, 7, 9]]) + datsp = self.spcreator(dat) + + dat_out = array(0) if self.is_array_test else array([[0]]) + datsp_out = array(0) if self.is_array_test else matrix([[0]]) + + dat.mean(out=dat_out, keepdims=keep) + datsp.mean(out=datsp_out) + assert_array_almost_equal(dat_out, datsp_out) + + dat_out = np.zeros((3,)) if self.is_array_test else np.zeros((3, 1)) + datsp_out = np.zeros((3,)) if self.is_array_test else matrix(np.zeros((3, 1))) + + dat.mean(axis=1, out=dat_out, keepdims=keep) + datsp.mean(axis=1, out=datsp_out) + assert_array_almost_equal(dat_out, datsp_out) + + # check that wrong shape out parameter raises + with assert_raises(ValueError, match="output parameter.*wrong.*dimension"): + datsp.mean(out=array([0])) + with assert_raises(ValueError, match="output parameter.*wrong.*dimension"): + datsp.mean(out=array([[0]] if self.is_array_test else 0)) + + def test_numpy_mean(self): + # See gh-5987 + dat = array([[0, 1, 2], + [3, -4, 5], + [-6, 7, 9]]) + datsp = self.spcreator(dat) + + dat_mean = np.mean(dat) + datsp_mean = np.mean(datsp) + + assert_array_almost_equal(dat_mean, datsp_mean) + assert_equal(dat_mean.dtype, datsp_mean.dtype) + + def test_expm(self): + M = array([[1, 0, 2], [0, 0, 3], [-4, 5, 6]], float) + sM = self.spcreator(M, shape=(3,3), dtype=float) + Mexp = scipy.linalg.expm(M) + + N = array([[3., 0., 1.], [0., 2., 0.], [0., 0., 0.]]) + sN = self.spcreator(N, shape=(3,3), dtype=float) + Nexp = scipy.linalg.expm(N) + + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "splu converted its input to CSC format", + SparseEfficiencyWarning, + ) + warnings.filterwarnings( + "ignore", + "spsolve is more efficient when sparse b is in the CSC matrix format", + SparseEfficiencyWarning, + ) + warnings.filterwarnings( + "ignore", + "spsolve requires A be CSC or CSR matrix format", + SparseEfficiencyWarning, + ) + sMexp = expm(sM).toarray() + sNexp = expm(sN).toarray() + + assert_array_almost_equal((sMexp - Mexp), zeros((3, 3))) + assert_array_almost_equal((sNexp - Nexp), zeros((3, 3))) + + def test_inv(self): + def check(dtype): + M = array([[1, 0, 2], [0, 0, 3], [-4, 5, 6]], dtype) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "spsolve requires A be CSC or CSR matrix format", + SparseEfficiencyWarning, + ) + warnings.filterwarnings( + "ignore", + "spsolve is more efficient when sparse b " + "is in the CSC matrix format", + SparseEfficiencyWarning, + ) + warnings.filterwarnings( + "ignore", + "splu converted its input to CSC format", + SparseEfficiencyWarning, + ) + sM = self.spcreator(M, shape=(3,3), dtype=dtype) + sMinv = inv(sM) + assert_array_almost_equal(sMinv.dot(sM).toarray(), np.eye(3)) + assert_raises(TypeError, inv, M) + for dtype in [float]: + check(dtype) + + def test_from_array(self): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", ComplexWarning) + A = array([[1,0,0],[2,3,4],[0,5,0],[0,0,0]]) + assert_array_equal(self.spcreator(A).toarray(), A) + + A = array([[1.0 + 3j, 0, 0], + [0, 2.0 + 5, 0], + [0, 0, 0]]) + assert_array_equal(self.spcreator(A).toarray(), A) + assert_array_equal( + self.spcreator(A, dtype='int16').toarray(),A.astype('int16')) + + + def test_from_matrix(self): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", ComplexWarning) + A = self.asdense([[1, 0, 0], [2, 3, 4], [0, 5, 0], [0, 0, 0]]) + assert_array_equal(self.spcreator(A).todense(), A) + + A = self.asdense([[1.0 + 3j, 0, 0], + [0, 2.0 + 5, 0], + [0, 0, 0]]) + assert_array_equal(self.spcreator(A).todense(), A) + assert_array_equal( + self.spcreator(A, dtype='int16').todense(), A.astype('int16') + ) + + def test_from_list(self): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", ComplexWarning) + A = [[1,0,0],[2,3,4],[0,5,0],[0,0,0]] + assert_array_equal(self.spcreator(A).toarray(), A) + + A = [[1.0 + 3j, 0, 0], + [0, 2.0 + 5, 0], + [0, 0, 0]] + assert_array_equal(self.spcreator(A).toarray(), array(A)) + assert_array_equal( + self.spcreator(A, dtype='int16').toarray(), array(A).astype('int16') + ) + + def test_from_sparse(self): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", ComplexWarning) + D = array([[1,0,0],[2,3,4],[0,5,0],[0,0,0]]) + S = self.csr_container(D) + assert_array_equal(self.spcreator(S).toarray(), D) + S = self.spcreator(D) + assert_array_equal(self.spcreator(S).toarray(), D) + + D = array([[1.0 + 3j, 0, 0], + [0, 2.0 + 5, 0], + [0, 0, 0]]) + S = self.csr_container(D) + assert_array_equal(self.spcreator(S).toarray(), D) + assert_array_equal(self.spcreator(S, dtype='int16').toarray(), + D.astype('int16')) + S = self.spcreator(D) + assert_array_equal(self.spcreator(S).toarray(), D) + assert_array_equal(self.spcreator(S, dtype='int16').toarray(), + D.astype('int16')) + + # def test_array(self): + # """test array(A) where A is in sparse format""" + # assert_equal( array(self.datsp), self.dat ) + + def test_todense(self): + # Check C- or F-contiguous (default). + chk = self.datsp.todense() + assert isinstance(chk, np.ndarray if self.is_array_test else np.matrix) + assert_array_equal(chk, self.dat) + assert_(chk.flags.c_contiguous != chk.flags.f_contiguous) + # Check C-contiguous (with arg). + chk = self.datsp.todense(order='C') + assert_array_equal(chk, self.dat) + assert_(chk.flags.c_contiguous) + assert_(not chk.flags.f_contiguous) + # Check F-contiguous (with arg). + chk = self.datsp.todense(order='F') + assert_array_equal(chk, self.dat) + assert_(not chk.flags.c_contiguous) + assert_(chk.flags.f_contiguous) + # Check with out argument (array). + out = np.zeros(self.datsp.shape, dtype=self.datsp.dtype) + chk = self.datsp.todense(out=out) + assert_array_equal(self.dat, out) + assert_array_equal(self.dat, chk) + assert np.may_share_memory(chk, out) + # Check with out array (matrix). + out = self.asdense(np.zeros(self.datsp.shape, dtype=self.datsp.dtype)) + chk = self.datsp.todense(out=out) + assert_array_equal(self.dat, out) + assert_array_equal(self.dat, chk) + assert np.may_share_memory(chk, out) + a = array([[1.,2.,3.]]) + dense_dot_dense = a @ self.dat + check = a @ self.datsp.todense() + assert_array_equal(dense_dot_dense, check) + b = array([[1.,2.,3.,4.]]).T + dense_dot_dense = self.dat @ b + check2 = self.datsp.todense() @ b + assert_array_equal(dense_dot_dense, check2) + # Check bool data works. + spbool = self.spcreator(self.dat, dtype=bool) + matbool = self.dat.astype(bool) + assert_array_equal(spbool.todense(), matbool) + + def test_toarray(self): + # Check C- or F-contiguous (default). + dat = asarray(self.dat) + chk = self.datsp.toarray() + assert_array_equal(chk, dat) + assert_(chk.flags.c_contiguous != chk.flags.f_contiguous) + # Check C-contiguous (with arg). + chk = self.datsp.toarray(order='C') + assert_array_equal(chk, dat) + assert_(chk.flags.c_contiguous) + assert_(not chk.flags.f_contiguous) + # Check F-contiguous (with arg). + chk = self.datsp.toarray(order='F') + assert_array_equal(chk, dat) + assert_(not chk.flags.c_contiguous) + assert_(chk.flags.f_contiguous) + # Check with output arg. + out = np.zeros(self.datsp.shape, dtype=self.datsp.dtype) + self.datsp.toarray(out=out) + assert_array_equal(chk, dat) + # Check that things are fine when we don't initialize with zeros. + out[...] = 1. + self.datsp.toarray(out=out) + assert_array_equal(chk, dat) + a = array([1.,2.,3.]) + dense_dot_dense = dot(a, dat) + check = dot(a, self.datsp.toarray()) + assert_array_equal(dense_dot_dense, check) + b = array([1.,2.,3.,4.]) + dense_dot_dense = dot(dat, b) + check2 = dot(self.datsp.toarray(), b) + assert_array_equal(dense_dot_dense, check2) + # Check bool data works. + spbool = self.spcreator(self.dat, dtype=bool) + arrbool = dat.astype(bool) + assert_array_equal(spbool.toarray(), arrbool) + + def test_astype(self): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", ComplexWarning) + D = array([[2.0 + 3j, 0, 0], + [0, 4.0 + 5j, 0], + [0, 0, 0]]) + S = self.spcreator(D) + + for x in supported_dtypes: + # Check correctly casted + D_casted = D.astype(x) + for copy in (True, False): + S_casted = S.astype(x, copy=copy) + assert_equal(S_casted.dtype, D_casted.dtype) # correct type + assert_equal(S_casted.toarray(), D_casted) # correct values + assert_equal(S_casted.format, S.format) # format preserved + # Check correctly copied + assert_(S_casted.astype(x, copy=False) is S_casted) + S_copied = S_casted.astype(x, copy=True) + assert_(S_copied is not S_casted) + + def check_equal_but_not_same_array_attribute(attribute): + a = getattr(S_casted, attribute) + b = getattr(S_copied, attribute) + assert_array_equal(a, b) + assert_(a is not b) + i = (0,) * b.ndim + b_i = b[i] + b[i] = not b[i] + assert_(a[i] != b[i]) + b[i] = b_i + + if S_casted.format in ('csr', 'csc', 'bsr'): + for attribute in ('indices', 'indptr', 'data'): + check_equal_but_not_same_array_attribute(attribute) + elif S_casted.format == 'coo': + for attribute in ('row', 'col', 'data'): + check_equal_but_not_same_array_attribute(attribute) + elif S_casted.format == 'dia': + for attribute in ('offsets', 'data'): + check_equal_but_not_same_array_attribute(attribute) + + def test_astype_immutable(self): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", ComplexWarning) + D = array([[2.0 + 3j, 0, 0], + [0, 4.0 + 5j, 0], + [0, 0, 0]]) + S = self.spcreator(D) + if hasattr(S, 'data'): + S.data.flags.writeable = False + if S.format in ('csr', 'csc', 'bsr'): + S.indptr.flags.writeable = False + S.indices.flags.writeable = False + for x in supported_dtypes: + D_casted = D.astype(x) + S_casted = S.astype(x) + assert_equal(S_casted.dtype, D_casted.dtype) + + def test_mul_scalar(self): + def check(dtype): + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + + assert_array_equal(dat*2, (datsp*2).toarray()) + assert_array_equal(dat*17.3, (datsp*17.3).toarray()) + + for dtype in self.math_dtypes: + check(dtype) + + def test_rmul_scalar(self): + def check(dtype): + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + + assert_array_equal(2*dat, (2*datsp).toarray()) + assert_array_equal(17.3*dat, (17.3*datsp).toarray()) + + for dtype in self.math_dtypes: + check(dtype) + + # GitHub issue #15210 + def test_rmul_scalar_type_error(self): + datsp = self.datsp_dtypes[np.float64] + with assert_raises(TypeError): + None * datsp + + def test_add(self): + def check(dtype): + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + + a = dat.copy() + a[0,2] = 2.0 + b = datsp + c = b + a + assert_array_equal(c, b.toarray() + a) + + c = b + b.tocsr() + assert_array_equal(c.toarray(), + b.toarray() + b.toarray()) + + # test broadcasting + c = b + a[0] + assert_array_equal(c, b.toarray() + a[0]) + + for dtype in self.math_dtypes: + check(dtype) + + def test_radd(self): + def check(dtype): + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + + a = dat.copy() + a[0,2] = 2.0 + b = datsp + c = a + b + assert_array_equal(c, a + b.toarray()) + + for dtype in self.math_dtypes: + check(dtype) + + def test_sub(self): + def check(dtype): + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + + assert_array_equal((datsp - datsp).toarray(), np.zeros((3, 4))) + assert_array_equal((datsp - 0).toarray(), dat) + + A = self.spcreator( + np.array([[1, 0, 0, 4], [-1, 0, 0, 0], [0, 8, 0, -5]], 'd') + ) + assert_array_equal((datsp - A).toarray(), dat - A.toarray()) + assert_array_equal((A - datsp).toarray(), A.toarray() - dat) + + # test broadcasting + assert_array_equal(datsp - dat[0], dat - dat[0]) + + for dtype in self.math_dtypes: + if dtype == np.dtype('bool'): + # boolean array subtraction deprecated in 1.9.0 + continue + + check(dtype) + + def test_rsub(self): + def check(dtype): + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + + assert_array_equal((dat - datsp),[[0,0,0,0],[0,0,0,0],[0,0,0,0]]) + assert_array_equal((datsp - dat),[[0,0,0,0],[0,0,0,0],[0,0,0,0]]) + assert_array_equal((0 - datsp).toarray(), -dat) + + A = self.spcreator([[1,0,0,4],[-1,0,0,0],[0,8,0,-5]],dtype='d') + assert_array_equal((dat - A), dat - A.toarray()) + assert_array_equal((A - dat), A.toarray() - dat) + assert_array_equal(A.toarray() - datsp, A.toarray() - dat) + assert_array_equal(datsp - A.toarray(), dat - A.toarray()) + + # test broadcasting + assert_array_equal(dat[0] - datsp, dat[0] - dat) + + for dtype in self.math_dtypes: + if dtype == np.dtype('bool'): + # boolean array subtraction deprecated in 1.9.0 + continue + + check(dtype) + + def test_add0(self): + def check(dtype): + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + + # Adding 0 to a sparse matrix + assert_array_equal((datsp + 0).toarray(), dat) + # use sum (which takes 0 as a starting value) + sumS = sum([k * datsp for k in range(1, 3)]) + sumD = sum([k * dat for k in range(1, 3)]) + assert_almost_equal(sumS.toarray(), sumD) + + for dtype in self.math_dtypes: + check(dtype) + + def test_elementwise_multiply(self): + # real/real + A = array([[4,0,9],[2,-3,5]]) + B = array([[0,7,0],[0,-4,0]]) + Asp = self.spcreator(A) + Bsp = self.spcreator(B) + # check output format + out_fmt = Asp.format if Asp.format in ('csc', 'dia', 'bsr') else 'csr' + assert (Asp.multiply(Bsp)).format == out_fmt + assert_almost_equal(Asp.multiply(Bsp).toarray(), A*B) # sparse/sparse + assert_almost_equal(Asp.multiply(B).toarray(), A*B) # sparse/dense + + # complex/complex + C = array([[1-2j,0+5j,-1+0j],[4-3j,-3+6j,5]]) + D = array([[5+2j,7-3j,-2+1j],[0-1j,-4+2j,9]]) + Csp = self.spcreator(C) + Dsp = self.spcreator(D) + assert_almost_equal(Csp.multiply(Dsp).toarray(), C*D) # sparse/sparse + assert_almost_equal(Csp.multiply(D).toarray(), C*D) # sparse/dense + + # real/complex + assert_almost_equal(Asp.multiply(Dsp).toarray(), A*D) # sparse/sparse + assert_almost_equal(Asp.multiply(D).toarray(), A*D) # sparse/dense + + def test_elementwise_multiply_broadcast(self): + A = array([4]) + B = array([[-9]]) + C = array([1,-1,0]) + D = array([[7,9,-9]]) + E = array([[3],[2],[1]]) + F = array([[8,6,3],[-4,3,2],[6,6,6]]) + G = [1, 2, 3] + H = np.ones((3, 4)) + J = H.T + K = array([[0]]) + L = array([[[1,2],[0,1]]]) + + # Some arrays can't be cast as spmatrices (A,C,L) so leave + # them out. + Bsp = self.spcreator(B) + Dsp = self.spcreator(D) + Esp = self.spcreator(E) + Fsp = self.spcreator(F) + Hsp = self.spcreator(H) + Hspp = self.spcreator(H[0,None]) + Jsp = self.spcreator(J) + Jspp = self.spcreator(J[:,0,None]) + Ksp = self.spcreator(K) + + matrices = [A, B, C, D, E, F, G, H, J, K, L] + spmatrices = [Bsp, Dsp, Esp, Fsp, Hsp, Hspp, Jsp, Jspp, Ksp] + + # sparse/sparse + for i in spmatrices: + for j in spmatrices: + try: + dense_mult = i.toarray() * j.toarray() + except ValueError: + assert_raises(ValueError, i.multiply, j) + continue + sp_mult = i.multiply(j) + assert_almost_equal(sp_mult.toarray(), dense_mult) + + # sparse/dense + for i in spmatrices: + for j in matrices: + try: + dense_mult = i.toarray() * j + except TypeError: + continue + except ValueError: + assert_raises(ValueError, i.multiply, j) + continue + try: + sp_mult = i.multiply(j) + except ValueError: + continue + if issparse(sp_mult): + assert_almost_equal(sp_mult.toarray(), dense_mult) + else: + assert_almost_equal(sp_mult, dense_mult) + + def test_elementwise_divide(self): + expected = [[1,np.nan,np.nan,1], + [1,np.nan,1,np.nan], + [np.nan,1,np.nan,np.nan]] + assert_array_equal(toarray(self.datsp / self.datsp), expected) + + denom = self.spcreator([[1,0,0,4],[-1,0,0,0],[0,8,0,-5]],dtype='d') + expected = [[1,np.nan,np.nan,0.5], + [-3,np.nan,inf,np.nan], + [np.nan,0.25,np.nan,0]] + assert_array_equal(toarray(self.datsp / denom), expected) + + # complex + A = array([[1-2j,0+5j,-1+0j],[4-3j,-3+6j,5]]) + B = array([[5+2j,7-3j,-2+1j],[0-1j,-4+2j,9]]) + Asp = self.spcreator(A) + Bsp = self.spcreator(B) + assert_almost_equal(toarray(Asp / Bsp), A/B) + + # integer + A = array([[1,2,3],[-3,2,1]]) + B = array([[0,1,2],[0,-2,3]]) + Asp = self.spcreator(A) + Bsp = self.spcreator(B) + with np.errstate(divide='ignore'): + assert_array_equal(toarray(Asp / Bsp), A / B) + + # mismatching sparsity patterns + A = array([[0,1],[1,0]]) + B = array([[1,0],[1,0]]) + Asp = self.spcreator(A) + Bsp = self.spcreator(B) + with np.errstate(divide='ignore', invalid='ignore'): + assert_array_equal(np.array(toarray(Asp / Bsp)), A / B) + + def test_pow(self): + A = array([[1, 0, 2, 0], [0, 3, 4, 0], [0, 5, 0, 0], [0, 6, 7, 8]]) + B = self.spcreator(A) + + if self.is_array_test: # sparrays use element-wise power + for exponent in [1, 2, 2.2, 3, 1+3j]: + ret_sp = B**exponent + ret_np = A**exponent + assert_array_equal(ret_sp.toarray(), ret_np) + assert_equal(ret_sp.dtype, ret_np.dtype) + + # invalid exponents + assert_raises(NotImplementedError, B.__pow__, 0) + assert_raises(ValueError, B.__pow__, -1) + + # nonsquare matrix + B = self.spcreator(A[:3,:]) + assert_equal((B**1).toarray(), B.toarray()) + else: # test sparse matrix. spmatrices use matrix multiplicative power + for exponent in [0,1,2,3]: + ret_sp = B**exponent + ret_np = np.linalg.matrix_power(A, exponent) + assert_array_equal(ret_sp.toarray(), ret_np) + assert_equal(ret_sp.dtype, ret_np.dtype) + + # invalid exponents + for exponent in [-1, 2.2, 1 + 3j]: + assert_raises(ValueError, B.__pow__, exponent) + + # nonsquare matrix + B = self.spcreator(A[:3,:]) + assert_raises(TypeError, B.__pow__, 1) + + def test_rmatvec(self): + M = self.spcreator([[3,0,0],[0,1,0],[2,0,3.0],[2,3,0]]) + assert_array_almost_equal([1,2,3,4] @ M, dot([1,2,3,4], M.toarray())) + row = array([[1,2,3,4]]) + assert_array_almost_equal(row @ M, row @ M.toarray()) + + def test_small_multiplication(self): + # test that A*x works for x with shape () (1,) (1,1) and (1,0) + A = self.spcreator([[1],[2],[3]]) + + assert_(issparse(A * array(1))) + assert_equal((A * array(1)).toarray(), [[1], [2], [3]]) + + assert_equal(A @ array([1]), array([1, 2, 3])) + assert_equal(A @ array([[1]]), array([[1], [2], [3]])) + assert_equal(A @ np.ones((1, 1)), array([[1], [2], [3]])) + assert_equal(A @ np.ones((1, 0)), np.ones((3, 0))) + + def test_star_vs_at_sign_for_sparray_and_spmatrix(self): + # test that * is matmul for spmatrix and mul for sparray + A = np.array([[1], [2], [3]]) + Asp = self.spcreator(A) + + if self.is_array_test: + assert_array_almost_equal((Asp * np.ones((3, 1))).toarray(), A) + assert_array_almost_equal((Asp * array([[1]])).toarray(), A) + else: + assert_equal(Asp * array([1]), array([1, 2, 3])) + assert_equal(Asp * array([[1]]), array([[1], [2], [3]])) + assert_equal(Asp * np.ones((1, 0)), np.ones((3, 0))) + + def test_binop_custom_type(self): + # Non-regression test: previously, binary operations would raise + # NotImplementedError instead of returning NotImplemented + # (https://docs.python.org/library/constants.html#NotImplemented) + # so overloading Custom + matrix etc. didn't work. + A = self.spcreator([[1], [2], [3]]) + B = BinopTester() + assert_equal(A + B, "matrix on the left") + assert_equal(A - B, "matrix on the left") + assert_equal(A * B, "matrix on the left") + assert_equal(B + A, "matrix on the right") + assert_equal(B - A, "matrix on the right") + assert_equal(B * A, "matrix on the right") + + assert_equal(A @ B, "matrix on the left") + assert_equal(B @ A, "matrix on the right") + + def test_binop_custom_type_with_shape(self): + A = self.spcreator([[1], [2], [3]]) + B = BinopTester_with_shape((3,1)) + assert_equal(A + B, "matrix on the left") + assert_equal(A - B, "matrix on the left") + assert_equal(A * B, "matrix on the left") + assert_equal(B + A, "matrix on the right") + assert_equal(B - A, "matrix on the right") + assert_equal(B * A, "matrix on the right") + + assert_equal(A @ B, "matrix on the left") + assert_equal(B @ A, "matrix on the right") + + def test_mul_custom_type(self): + class Custom: + def __init__(self, scalar): + self.scalar = scalar + + def __rmul__(self, other): + return other * self.scalar + + scalar = 2 + A = self.spcreator([[1],[2],[3]]) + c = Custom(scalar) + A_scalar = A * scalar + A_c = A * c + assert_array_equal_dtype(A_scalar.toarray(), A_c.toarray()) + assert_equal(A_scalar.format, A_c.format) + + def test_comparisons_custom_type(self): + A = self.spcreator([[1], [2], [3]]) + B = ComparisonTester() + assert_equal(A == B, "eq") + assert_equal(A != B, "ne") + assert_equal(A > B, "lt") + assert_equal(A >= B, "le") + assert_equal(A < B, "gt") + assert_equal(A <= B, "ge") + + def test_dot_scalar(self): + M = self.spcreator(array([[3,0,0],[0,1,0],[2,0,3.0],[2,3,0]])) + scalar = 10 + actual = M.dot(scalar) + expected = M * scalar + + assert_allclose(actual.toarray(), expected.toarray()) + + def test_matmul(self): + M = self.spcreator(array([[3,0,0],[0,1,0],[2,0,3.0],[2,3,0]])) + B = self.spcreator(array([[0,1],[1,0],[0,2]],'d')) + col = array([[1,2,3]]).T + + matmul = operator.matmul + # check matrix-vector + assert_array_almost_equal(matmul(M, col), M.toarray() @ col) + + # check matrix-matrix + assert_array_almost_equal(matmul(M, B).toarray(), (M @ B).toarray()) + assert_array_almost_equal(matmul(M.toarray(), B), (M @ B).toarray()) + assert_array_almost_equal(matmul(M, B.toarray()), (M @ B).toarray()) + + # check error on matrix-scalar + assert_raises(ValueError, matmul, M, 1) + assert_raises(ValueError, matmul, 1, M) + + def test_matvec(self): + M = self.spcreator([[3,0,0],[0,1,0],[2,0,3.0],[2,3,0]]) + col = array([[1,2,3]]).T + + assert_array_almost_equal(M @ col, M.toarray() @ col) + + # check result dimensions (ticket #514) + assert_equal((M @ array([1,2,3])).shape,(4,)) + assert_equal((M @ array([[1],[2],[3]])).shape,(4,1)) + assert_equal((M @ matrix([[1],[2],[3]])).shape,(4,1)) + + # check result type + assert_(isinstance(M @ array([1,2,3]), ndarray)) + matrix_or_array = ndarray if self.is_array_test else np.matrix + assert_(isinstance(M @ matrix([1,2,3]).T, matrix_or_array)) + + # ensure exception is raised for improper dimensions + bad_vecs = [array([1,2]), array([1,2,3,4]), array([[1],[2]]), + matrix([1,2,3]), matrix([[1],[2]])] + for x in bad_vecs: + assert_raises(ValueError, M.__matmul__, x) + + # The current relationship between sparse matrix products and array + # products is as follows: + assert_almost_equal(M@array([1,2,3]), dot(M.toarray(),[1,2,3])) + assert_almost_equal(M@[[1],[2],[3]], np.atleast_2d(dot(M.toarray(),[1,2,3])).T) + # Note that the result of M * x is dense if x has a singleton dimension. + + # Currently M.matvec(asarray(col)) is rank-1, whereas M.matvec(col) + # is rank-2. Is this desirable? + + def test_matmat_sparse(self): + a = matrix([[3,0,0],[0,1,0],[2,0,3.0],[2,3,0]]) + a2 = array([[3,0,0],[0,1,0],[2,0,3.0],[2,3,0]]) + b = matrix([[0,1],[1,0],[0,2]],'d') + asp = self.spcreator(a) + bsp = self.spcreator(b) + assert_array_almost_equal((asp @ bsp).toarray(), a @ b) + assert_array_almost_equal(asp @ b, a @ b) + assert_array_almost_equal(a @ bsp, a @ b) + assert_array_almost_equal(a2 @ bsp, a @ b) + + # Now try performing cross-type multiplication: + csp = bsp.tocsc() + c = b + want = a @ c + assert_array_almost_equal((asp @ csp).toarray(), want) + assert_array_almost_equal(asp @ c, want) + + assert_array_almost_equal(a @ csp, want) + assert_array_almost_equal(a2 @ csp, want) + csp = bsp.tocsr() + assert_array_almost_equal((asp @ csp).toarray(), want) + assert_array_almost_equal(asp @ c, want) + + assert_array_almost_equal(a @ csp, want) + assert_array_almost_equal(a2 @ csp, want) + csp = bsp.tocoo() + assert_array_almost_equal((asp @ csp).toarray(), want) + assert_array_almost_equal(asp @ c, want) + + assert_array_almost_equal(a @ csp, want) + assert_array_almost_equal(a2 @ csp, want) + + # Test provided by Andy Fraser, 2006-03-26 + L = 30 + frac = .3 + random.seed(0) # make runs repeatable + A = zeros((L,2)) + for i in range(L): + for j in range(2): + r = random.random() + if r < frac: + A[i,j] = r/frac + + A = self.spcreator(A) + B = A @ A.T + assert_array_almost_equal(B.toarray(), A.toarray() @ A.T.toarray()) + assert_array_almost_equal(B.toarray(), A.toarray() @ A.toarray().T) + + # check dimension mismatch 2x2 times 3x2 + A = self.spcreator([[1,2],[3,4]]) + B = self.spcreator([[1,2],[3,4],[5,6]]) + assert_raises(ValueError, A.__matmul__, B) + if self.is_array_test: + assert_raises(ValueError, A.__mul__, B) + + def test_matmat_dense(self): + a = [[3,0,0],[0,1,0],[2,0,3.0],[2,3,0]] + asp = self.spcreator(a) + + # check both array and matrix types + bs = [array([[1,2],[3,4],[5,6]]), matrix([[1,2],[3,4],[5,6]])] + + for b in bs: + result = asp @ b + assert_(isinstance(result, ndarray if self.is_array_test else type(b))) + assert_equal(result.shape, (4,2)) + assert_equal(result, dot(a,b)) + + def test_sparse_format_conversions(self): + A = sparse.kron([[1,0,2],[0,3,4],[5,0,0]], [[1,2],[0,3]]) + D = A.toarray() + A = self.spcreator(A) + + for format in ['bsr','coo','csc','csr','dia','dok','lil']: + a = A.asformat(format) + assert_equal(a.format,format) + assert_array_equal(a.toarray(), D) + + b = self.spcreator(D+3j).asformat(format) + assert_equal(b.format,format) + assert_array_equal(b.toarray(), D+3j) + + c = self.spcreator(D).asformat(format) + assert_equal(c.format,format) + assert_array_equal(c.toarray(), D) + + for format in ['array', 'dense']: + a = A.asformat(format) + assert_array_equal(a, D) + + b = self.spcreator(D+3j).asformat(format) + assert_array_equal(b, D+3j) + + def test_tobsr(self): + x = array([[1,0,2,0],[0,0,0,0],[0,0,4,5]]) + y = array([[0,1,2],[3,0,5]]) + A = kron(x,y) + Asp = self.spcreator(A) + for format in ['bsr']: + fn = getattr(Asp, 'to' + format) + + for X in [1, 2, 3, 6]: + for Y in [1, 2, 3, 4, 6, 12]: + assert_equal(fn(blocksize=(X, Y)).toarray(), A) + + def test_transpose(self): + dat_1 = self.dat + dat_2 = np.array([[]]) + matrices = [dat_1, dat_2] + + def check(dtype, j): + dat = array(matrices[j], dtype=dtype) + datsp = self.spcreator(dat) + + a = datsp.transpose() + b = dat.transpose() + + assert_array_equal(a.toarray(), b) + assert_array_equal(a.transpose().toarray(), dat) + assert_array_equal(datsp.transpose(axes=(1, 0)).toarray(), b) + assert_equal(a.dtype, b.dtype) + + # See gh-5987 + empty = self.spcreator((3, 4)) + assert_array_equal(np.transpose(empty).toarray(), + np.transpose(zeros((3, 4)))) + assert_array_equal(empty.T.toarray(), zeros((4, 3))) + assert_raises(ValueError, empty.transpose, axes=0) + + for dtype in self.checked_dtypes: + for j in range(len(matrices)): + check(dtype, j) + + def test_add_dense(self): + def check(dtype): + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + + # adding a dense matrix to a sparse matrix + sum1 = dat + datsp + assert_array_equal(sum1, dat + dat) + sum2 = datsp + dat + assert_array_equal(sum2, dat + dat) + + for dtype in self.math_dtypes: + check(dtype) + + def test_sub_dense(self): + # subtracting a dense matrix to/from a sparse matrix + def check(dtype): + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + + # Behavior is different for bool. + if dat.dtype == bool: + sum1 = dat - datsp + assert_array_equal(sum1, dat - dat) + sum2 = datsp - dat + assert_array_equal(sum2, dat - dat) + else: + # Manually add to avoid upcasting from scalar + # multiplication. + sum1 = (dat + dat + dat) - datsp + assert_array_equal(sum1, dat + dat) + sum2 = (datsp + datsp + datsp) - dat + assert_array_equal(sum2, dat + dat) + + for dtype in self.math_dtypes: + if dtype == np.dtype('bool'): + # boolean array subtraction deprecated in 1.9.0 + continue + + check(dtype) + + def test_maximum_minimum(self): + A_dense = np.array([[1, 0, 3], [0, 4, 5], [0, 0, 0]]) + B_dense = np.array([[1, 1, 2], [0, 3, 6], [1, -1, 0]]) + + A_dense_cpx = np.array([[1, 0, 3], [0, 4+2j, 5], [0, 1j, -1j]]) + + def check(dtype, dtype2, btype): + if np.issubdtype(dtype, np.complexfloating): + A = self.spcreator(A_dense_cpx.astype(dtype)) + else: + A = self.spcreator(A_dense.astype(dtype)) + if btype == 'scalar': + B = dtype2.type(1) + elif btype == 'scalar2': + B = dtype2.type(-1) + elif btype == 'dense': + B = B_dense.astype(dtype2) + elif btype == 'sparse': + B = self.spcreator(B_dense.astype(dtype2)) + else: + raise ValueError() + + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "Taking (maximum|minimum) with a (positive|negative) number " + "results in a dense matrix", + SparseEfficiencyWarning, + ) + + max_s = A.maximum(B) + min_s = A.minimum(B) + + max_d = np.maximum(toarray(A), toarray(B)) + assert_array_equal(toarray(max_s), max_d) + assert_equal(max_s.dtype, max_d.dtype) + + min_d = np.minimum(toarray(A), toarray(B)) + assert_array_equal(toarray(min_s), min_d) + assert_equal(min_s.dtype, min_d.dtype) + + for dtype in self.math_dtypes: + for dtype2 in [np.int8, np.float64, np.complex128]: + for btype in ['scalar', 'scalar2', 'dense', 'sparse']: + check(np.dtype(dtype), np.dtype(dtype2), btype) + + def test_copy(self): + # Check whether the copy=True and copy=False keywords work + A = self.datsp + + # check that copy preserves format + assert_equal(A.copy().format, A.format) + assert_equal(A.__class__(A,copy=True).format, A.format) + assert_equal(A.__class__(A,copy=False).format, A.format) + + assert_equal(A.copy().toarray(), A.toarray()) + assert_equal(A.__class__(A, copy=True).toarray(), A.toarray()) + assert_equal(A.__class__(A, copy=False).toarray(), A.toarray()) + + # check that XXX_array.toXXX() works + toself = getattr(A,'to' + A.format) + assert_(toself() is A) + assert_(toself(copy=False) is A) + assert_equal(toself(copy=True).format, A.format) + assert_equal(toself(copy=True).toarray(), A.toarray()) + + # check whether the data is copied? + assert_(not sparse_may_share_memory(A.copy(), A)) + + # test that __iter__ is compatible with NumPy matrix + def test_iterator(self): + B = self.asdense(np.arange(50).reshape(5, 10)) + A = self.spcreator(B) + + for x, y in zip(A, B): + assert_equal(x.toarray(), y) + + def test_size_zero_matrix_arithmetic(self): + # Test basic matrix arithmetic with shapes like (0,0), (10,0), + # (0, 3), etc. + mat = array([]) + a = mat.reshape((0, 0)) + b = mat.reshape((0, 1)) + c = mat.reshape((0, 5)) + d = mat.reshape((1, 0)) + e = mat.reshape((5, 0)) + f = np.ones([5, 5]) + + asp = self.spcreator(a) + bsp = self.spcreator(b) + csp = self.spcreator(c) + dsp = self.spcreator(d) + esp = self.spcreator(e) + fsp = self.spcreator(f) + + # matrix product. + assert_array_equal(asp.dot(asp).toarray(), np.dot(a, a)) + assert_array_equal(bsp.dot(dsp).toarray(), np.dot(b, d)) + assert_array_equal(dsp.dot(bsp).toarray(), np.dot(d, b)) + assert_array_equal(csp.dot(esp).toarray(), np.dot(c, e)) + assert_array_equal(csp.dot(fsp).toarray(), np.dot(c, f)) + assert_array_equal(esp.dot(csp).toarray(), np.dot(e, c)) + assert_array_equal(dsp.dot(csp).toarray(), np.dot(d, c)) + assert_array_equal(fsp.dot(esp).toarray(), np.dot(f, e)) + + # bad matrix products + assert_raises(ValueError, dsp.dot, e) + assert_raises(ValueError, asp.dot, d) + + # elemente-wise multiplication + assert_array_equal(asp.multiply(asp).toarray(), np.multiply(a, a)) + assert_array_equal(bsp.multiply(bsp).toarray(), np.multiply(b, b)) + assert_array_equal(dsp.multiply(dsp).toarray(), np.multiply(d, d)) + + assert_array_equal(asp.multiply(a).toarray(), np.multiply(a, a)) + assert_array_equal(bsp.multiply(b).toarray(), np.multiply(b, b)) + assert_array_equal(dsp.multiply(d).toarray(), np.multiply(d, d)) + + assert_array_equal(asp.multiply(6).toarray(), np.multiply(a, 6)) + assert_array_equal(bsp.multiply(6).toarray(), np.multiply(b, 6)) + assert_array_equal(dsp.multiply(6).toarray(), np.multiply(d, 6)) + + # bad element-wise multiplication + assert_raises(ValueError, asp.multiply, c) + assert_raises(ValueError, esp.multiply, c) + + # Addition + assert_array_equal(asp.__add__(asp).toarray(), a.__add__(a)) + assert_array_equal(bsp.__add__(bsp).toarray(), b.__add__(b)) + assert_array_equal(dsp.__add__(dsp).toarray(), d.__add__(d)) + + # bad addition + assert_raises(ValueError, asp.__add__, dsp) + assert_raises(ValueError, bsp.__add__, asp) + + def test_size_zero_conversions(self): + mat = array([]) + a = mat.reshape((0, 0)) + b = mat.reshape((0, 5)) + c = mat.reshape((5, 0)) + + for m in [a, b, c]: + spm = self.spcreator(m) + assert_array_equal(spm.tocoo().toarray(), m) + assert_array_equal(spm.tocsr().toarray(), m) + assert_array_equal(spm.tocsc().toarray(), m) + assert_array_equal(spm.tolil().toarray(), m) + assert_array_equal(spm.todok().toarray(), m) + assert_array_equal(spm.tobsr().toarray(), m) + + def test_dtype_check(self): + a = np.array([[3.5, 0, 1.1], [0, 0, 0]], dtype=np.float16) + with assert_raises(ValueError, match="does not support dtype"): + self.spcreator(a) + + A32 = self.spcreator(a.astype(np.float32)) + with assert_raises(ValueError, match="does not support dtype"): + self.spcreator(A32, dtype=np.float16) + + def test_pickle(self): + import pickle + def check(): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + datsp = self.datsp.copy() + for protocol in range(pickle.HIGHEST_PROTOCOL): + sploaded = pickle.loads(pickle.dumps(datsp, protocol=protocol)) + assert_equal(datsp.shape, sploaded.shape) + assert_array_equal(datsp.toarray(), sploaded.toarray()) + assert_equal(datsp.format, sploaded.format) + # Hacky check for class member equality. This assumes that + # all instance variables are one of: + # 1. Plain numpy ndarrays + # 2. Tuples of ndarrays + # 3. Types that support equality comparison with == + for key, val in datsp.__dict__.items(): + if isinstance(val, np.ndarray): + assert_array_equal(val, sploaded.__dict__[key]) + elif (isinstance(val, tuple) and val + and isinstance(val[0], np.ndarray)): + assert_array_equal(val, sploaded.__dict__[key]) + else: + assert_(val == sploaded.__dict__[key]) + check() + + def test_unary_ufunc_overrides(self): + def check(name): + if name == "sign": + pytest.skip("sign conflicts with comparison op " + "support on Numpy") + if self.datsp.format in ["dok", "lil"]: + pytest.skip("Unary ops not implemented for dok/lil") + ufunc = getattr(np, name) + + X = self.spcreator(np.arange(20).reshape(4, 5) / 20.) + X0 = ufunc(X.toarray()) + + X2 = ufunc(X) + assert_array_equal(X2.toarray(), X0) + + for name in ["sin", "tan", "arcsin", "arctan", "sinh", "tanh", + "arcsinh", "arctanh", "rint", "sign", "expm1", "log1p", + "deg2rad", "rad2deg", "floor", "ceil", "trunc", "sqrt", + "abs"]: + check(name) + + def test_resize(self): + # resize(shape) resizes the matrix in-place + D = np.array([[1, 0, 3, 4], + [2, 0, 0, 0], + [3, 0, 0, 0]]) + S = self.spcreator(D) + assert_(S.resize((3, 2)) is None) + assert_array_equal(S.toarray(), [[1, 0], + [2, 0], + [3, 0]]) + S.resize((2, 2)) + assert_array_equal(S.toarray(), [[1, 0], + [2, 0]]) + S.resize((3, 2)) + assert_array_equal(S.toarray(), [[1, 0], + [2, 0], + [0, 0]]) + S.resize((3, 3)) + assert_array_equal(S.toarray(), [[1, 0, 0], + [2, 0, 0], + [0, 0, 0]]) + # test no-op + S.resize((3, 3)) + assert_array_equal(S.toarray(), [[1, 0, 0], + [2, 0, 0], + [0, 0, 0]]) + + # test *args + S.resize(3, 2) + assert_array_equal(S.toarray(), [[1, 0], + [2, 0], + [0, 0]]) + + if self.is_array_test and S.format in ["coo", "csr"]: + S.resize(1) + else: + assert_raises((ValueError, NotImplementedError, IndexError), S.resize, 1) + + for bad_shape in [(-1, 2), (2, -1), (1, 2, 3)]: + assert_raises(ValueError, S.resize, bad_shape) + + def test_constructor1_base(self): + A = self.datsp + + self_format = A.format + + C = A.__class__(A, copy=False) + assert_array_equal_dtype(A.toarray(), C.toarray()) + if self_format not in NON_ARRAY_BACKED_FORMATS: + assert_(sparse_may_share_memory(A, C)) + + C = A.__class__(A, dtype=A.dtype, copy=False) + assert_array_equal_dtype(A.toarray(), C.toarray()) + if self_format not in NON_ARRAY_BACKED_FORMATS: + assert_(sparse_may_share_memory(A, C)) + + C = A.__class__(A, dtype=np.float32, copy=False) + assert_array_equal(A.toarray(), C.toarray()) + + C = A.__class__(A, copy=True) + assert_array_equal_dtype(A.toarray(), C.toarray()) + assert_(not sparse_may_share_memory(A, C)) + + for other_format in ['csr', 'csc', 'coo', 'dia', 'dok', 'lil']: + if other_format == self_format: + continue + B = A.asformat(other_format) + C = A.__class__(B, copy=False) + assert_array_equal_dtype(A.toarray(), C.toarray()) + + C = A.__class__(B, copy=True) + assert_array_equal_dtype(A.toarray(), C.toarray()) + assert_(not sparse_may_share_memory(B, C)) + + +class _TestInplaceArithmetic: + def test_inplace_dense(self): + a = np.ones((3, 4)) + b = self.spcreator(a) + + x = a.copy() + y = a.copy() + x += a + y += b + assert_array_equal(x, y) + + x = a.copy() + y = a.copy() + x -= a + y -= b + assert_array_equal(x, y) + + if self.is_array_test: + # Elementwise multiply from sparray.__rmul__ + x = a.copy() + y = a.copy() + with assert_raises(ValueError, match="inconsistent shapes"): + x *= b.T + x = x * a + y *= b + assert_array_equal(x, y.toarray()) + else: + # Matrix multiply from spmatrix.__rmul__ + x = a.copy() + y = a.copy() + with assert_raises(ValueError, match="dimension mismatch"): + x *= b + x = x.dot(a.T) + y *= b.T + assert_array_equal(x, y) + + # Matrix multiply from __rmatmul__ + y = a.copy() + y @= b.T + x = a.copy() + y = a.copy() + with assert_raises(ValueError, match="dimension mismatch"): + x @= b + x = x.dot(a.T) + y @= b.T + assert_array_equal(x, y) + + # Floor division is not supported + with assert_raises(TypeError, match="unsupported operand"): + x //= b + + def test_imul_scalar(self): + def check(dtype): + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + + # Avoid implicit casting. + if np.can_cast(int, dtype, casting='same_kind'): + a = datsp.copy() + a *= 2 + b = dat.copy() + b *= 2 + assert_array_equal(b, a.toarray()) + + if np.can_cast(float, dtype, casting='same_kind'): + a = datsp.copy() + a *= 17.3 + b = dat.copy() + b *= 17.3 + assert_array_equal(b, a.toarray()) + + for dtype in self.math_dtypes: + check(dtype) + + def test_idiv_scalar(self): + def check(dtype): + dat = self.dat_dtypes[dtype] + datsp = self.datsp_dtypes[dtype] + + if np.can_cast(int, dtype, casting='same_kind'): + a = datsp.copy() + a /= 2 + b = dat.copy() + b /= 2 + assert_array_equal(b, a.toarray()) + + if np.can_cast(float, dtype, casting='same_kind'): + a = datsp.copy() + a /= 17.3 + b = dat.copy() + b /= 17.3 + assert_array_equal(b, a.toarray()) + + for dtype in self.math_dtypes: + # /= should only be used with float dtypes to avoid implicit + # casting. + if not np.can_cast(dtype, np.dtype(int)): + check(dtype) + + def test_inplace_success(self): + # Inplace ops should work even if a specialized version is not + # implemented, falling back to x = x y + a = self.spcreator(np.eye(5)) + b = self.spcreator(np.eye(5)) + bp = self.spcreator(np.eye(5)) + + b += a + bp = bp + a + assert_allclose(b.toarray(), bp.toarray()) + + if self.is_array_test: + b *= a + bp = bp * a + assert_allclose(b.toarray(), bp.toarray()) + + b @= a + bp = bp @ a + assert_allclose(b.toarray(), bp.toarray()) + + b -= a + bp = bp - a + assert_allclose(b.toarray(), bp.toarray()) + + with assert_raises(TypeError, match="unsupported operand"): + a //= b + + +class _TestGetSet: + def test_getelement(self): + def check(dtype): + D = array([[1,0,0], + [4,3,0], + [0,2,0], + [0,0,0]], dtype=dtype) + A = self.spcreator(D) + + M,N = D.shape + + for i in range(-M, M): + for j in range(-N, N): + assert_equal(A[i,j], D[i,j]) + + assert_equal(type(A[1,1]), dtype) + + for ij in [(0,3),(-1,3),(4,0),(4,3),(4,-1), (1, 2, 3)]: + assert_raises((IndexError, TypeError), A.__getitem__, ij) + + for dtype in supported_dtypes: + check(np.dtype(dtype)) + + def test_setelement(self): + def check(dtype, scalar_container): + A = self.spcreator((3, 4), dtype=dtype) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + A[0, 0] = scalar_container(dtype.type(0)) # bug 870 + A[1, 2] = scalar_container(dtype.type(4.0)) + A[0, 1] = scalar_container(dtype.type(3)) + A[2, 0] = scalar_container(dtype.type(2.0)) + A[0, -1] = scalar_container(dtype.type(8)) + A[-1, -2] = scalar_container(dtype.type(7)) + A[0, 1] = scalar_container(dtype.type(5)) + + if dtype != np.bool_: + assert_array_equal( + A.toarray(), [[0, 5, 0, 8], [0, 0, 4, 0], [2, 0, 7, 0]] + ) + + for ij in [(0, 4), (-1, 4), (3, 0), (3, 4), (3, -1)]: + assert_raises(IndexError, A.__setitem__, ij, 123.0) + + for v in [[1, 2, 3], array([1, 2, 3])]: + assert_raises(ValueError, A.__setitem__, (0, 0), v) + + if not np.issubdtype(dtype, np.complexfloating) and dtype != np.bool_: + for v in [3j]: + assert_raises(TypeError, A.__setitem__, (0, 0), v) + + scalar_containers = [ + lambda x: csr_array(np.array([[x]])), np.array, lambda x: x + ] + for scalar_container in scalar_containers: + for dtype in supported_dtypes: + check(np.dtype(dtype), scalar_container) + + def test_negative_index_assignment(self): + # Regression test for GitHub issue 4428. + + def check(dtype): + A = self.spcreator((3, 10), dtype=dtype) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + A[0, -4] = 1 + assert_equal(A[0, -4], 1) + + for dtype in self.math_dtypes: + check(np.dtype(dtype)) + + def test_scalar_assign_2(self): + n, m = (5, 10) + + def _test_set(i, j, nitems): + msg = f"{i!r} ; {j!r} ; {nitems!r}" + A = self.spcreator((n, m)) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + A[i, j] = 1 + assert_almost_equal(A.sum(), nitems, err_msg=msg) + assert_almost_equal(A[i, j], 1, err_msg=msg) + + # [i,j] + for i, j in [(2, 3), (-1, 8), (-1, -2), (array(-1), -2), (-1, array(-2)), + (array(-1), array(-2))]: + _test_set(i, j, 1) + + def test_index_scalar_assign(self): + A = self.spcreator((5, 5)) + B = np.zeros((5, 5)) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + for C in [A, B]: + C[0,1] = 1 + C[3,0] = 4 + C[3,0] = 9 + assert_array_equal(A.toarray(), B) + + +@pytest.mark.thread_unsafe(reason="fails in parallel") +class _TestSolve: + def test_solve(self): + # Test whether the lu_solve command segfaults, as reported by Nils + # Wagner for a 64-bit machine, 02 March 2005 (EJS) + n = 20 + np.random.seed(0) # make tests repeatable + A = zeros((n,n), dtype=complex) + x = np.random.rand(n) + y = np.random.rand(n-1)+1j*np.random.rand(n-1) + r = np.random.rand(n) + for i in range(len(x)): + A[i,i] = x[i] + for i in range(len(y)): + A[i,i+1] = y[i] + A[i+1,i] = conjugate(y[i]) + A = self.spcreator(A) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", "splu converted its input to CSC format", + SparseEfficiencyWarning) + x = splu(A).solve(r) + assert_almost_equal(A @ x,r) + + +class _TestSlicing: + def test_dtype_preservation(self): + assert_equal(self.spcreator((1,10), dtype=np.int16)[0,1:5].dtype, np.int16) + assert_equal(self.spcreator((1,10), dtype=np.int32)[0,1:5].dtype, np.int32) + assert_equal(self.spcreator((1,10), dtype=np.float32)[0,1:5].dtype, np.float32) + assert_equal(self.spcreator((1,10), dtype=np.float64)[0,1:5].dtype, np.float64) + + def test_dtype_preservation_empty_slice(self): + # This should be parametrized with pytest, but something in the parent + # class creation used in this file breaks pytest.mark.parametrize. + for dt in [np.int16, np.int32, np.float32, np.float64]: + A = self.spcreator((3, 2), dtype=dt) + assert_equal(A[:, 0:0:2].dtype, dt) + assert_equal(A[0:0:2, :].dtype, dt) + assert_equal(A[0, 0:0:2].dtype, dt) + assert_equal(A[0:0:2, 0].dtype, dt) + + def test_get_horiz_slice(self): + B = self.asdense(arange(50.).reshape(5,10)) + A = self.spcreator(B) + r0, r1, r2 = (0, 1, 2) if self.is_array_test else ([0], [1], [2]) + assert_array_equal(B[r1, :], A[1, :].toarray()) + assert_array_equal(B[r1, 2:5], A[1, 2:5].toarray()) + + C = self.asdense([[1, 2, 1], [4, 0, 6], [0, 0, 0], [0, 0, 1]]) + D = self.spcreator(C) + assert_array_equal(C[r1, 1:3], D[1, 1:3].toarray()) + + # Now test slicing when a row contains only zeros + E = self.asdense([[1, 2, 1], [4, 0, 0], [0, 0, 0], [0, 0, 1]]) + F = self.spcreator(E) + assert_array_equal(E[r1, 1:3], F[1, 1:3].toarray()) + assert_array_equal(E[r2, -2:], F[2, -2:].toarray()) + + # The following should raise exceptions: + assert_raises(IndexError, A.__getitem__, (slice(None), 11)) + assert_raises(IndexError, A.__getitem__, (6, slice(3, 7))) + + def test_get_vert_slice(self): + B = arange(50.).reshape(5, 10) + A = self.spcreator(B) + c0, c1, c2 = (0, 1, 2) if self.is_array_test else ([0], [1], [2]) + assert_array_equal(B[2:5, c0], A[2:5, 0].toarray()) + assert_array_equal(B[:, c1], A[:, 1].toarray()) + + C = array([[1, 2, 1], [4, 0, 6], [0, 0, 0], [0, 0, 1]]) + D = self.spcreator(C) + assert_array_equal(C[1:3, c1], D[1:3, 1].toarray()) + assert_array_equal(C[:, c2], D[:, 2].toarray()) + + # Now test slicing when a column contains only zeros + E = array([[1, 0, 1], [4, 0, 0], [0, 0, 0], [0, 0, 1]]) + F = self.spcreator(E) + assert_array_equal(E[:, c1], F[:, 1].toarray()) + assert_array_equal(E[-2:, c2], F[-2:, 2].toarray()) + + # The following should raise exceptions: + assert_raises(IndexError, A.__getitem__, (slice(None), 11)) + assert_raises(IndexError, A.__getitem__, (6, slice(3, 7))) + + def test_get_slices(self): + B = arange(50.).reshape(5, 10) + A = self.spcreator(B) + assert_array_equal(A[2:5, 0:3].toarray(), B[2:5, 0:3]) + assert_array_equal(A[1:, :-1].toarray(), B[1:, :-1]) + assert_array_equal(A[:-1, 1:].toarray(), B[:-1, 1:]) + + # Now test slicing when a column contains only zeros + E = array([[1, 0, 1], [4, 0, 0], [0, 0, 0], [0, 0, 1]]) + F = self.spcreator(E) + assert_array_equal(E[1:2, 1:2], F[1:2, 1:2].toarray()) + assert_array_equal(E[:, 1:], F[:, 1:].toarray()) + + def test_non_unit_stride_2d_indexing(self): + # Regression test -- used to silently ignore the stride. + v0 = np.random.rand(50, 50) + try: + v = self.spcreator(v0)[0:25:2, 2:30:3] + except ValueError: + # if unsupported + raise pytest.skip("feature not implemented") + + assert_array_equal(v.toarray(), v0[0:25:2, 2:30:3]) + + def test_slicing_2(self): + B = self.asdense(arange(50).reshape(5,10)) + A = self.spcreator(B) + + # [i,j] + assert_equal(A[2,3], B[2,3]) + assert_equal(A[-1,8], B[-1,8]) + assert_equal(A[-1,-2],B[-1,-2]) + assert_equal(A[array(-1),-2],B[-1,-2]) + assert_equal(A[-1,array(-2)],B[-1,-2]) + assert_equal(A[array(-1),array(-2)],B[-1,-2]) + + # [i,1:2] + assert_equal(A[2, :].toarray(), B[2, :]) + assert_equal(A[2, 5:-2].toarray(), B[2, 5:-2]) + assert_equal(A[array(2), 5:-2].toarray(), B[2, 5:-2]) + + # [1:2,j] + assert_equal(A[:, 2].toarray(), B[:, 2]) + assert_equal(A[3:4, 9].toarray(), B[3:4, 9]) + assert_equal(A[1:4, -5].toarray(), B[1:4, -5]) + assert_equal(A[2:-1, 3].toarray(), B[2:-1, 3]) + assert_equal(A[2:-1, array(3)].toarray(), B[2:-1, 3]) + + # [1:2,1:2] + assert_equal(A[1:2, 1:2].toarray(), B[1:2, 1:2]) + assert_equal(A[4:, 3:].toarray(), B[4:, 3:]) + assert_equal(A[:4, :5].toarray(), B[:4, :5]) + assert_equal(A[2:-1, :5].toarray(), B[2:-1, :5]) + + # [i] + assert_equal(A[1, :].toarray(), B[1, :]) + assert_equal(A[-2, :].toarray(), B[-2, :]) + assert_equal(A[array(-2), :].toarray(), B[-2, :]) + + # [1:2] + assert_equal(A[1:4].toarray(), B[1:4]) + assert_equal(A[1:-2].toarray(), B[1:-2]) + + # Check bug reported by Robert Cimrman: + # http://thread.gmane.org/gmane.comp.python.scientific.devel/7986 (dead link) + s = slice(int8(2),int8(4),None) + assert_equal(A[s, :].toarray(), B[2:4, :]) + assert_equal(A[:, s].toarray(), B[:, 2:4]) + + @pytest.mark.fail_slow(2) + def test_slicing_3(self): + B = self.asdense(arange(50).reshape(5,10)) + A = self.spcreator(B) + + s_ = np.s_ + slices = [s_[:2], s_[1:2], s_[3:], s_[3::2], + s_[15:20], s_[3:2], + s_[8:3:-1], s_[4::-2], s_[:5:-1], + 0, 1, s_[:], s_[1:5], -1, -2, -5, + array(-1), np.int8(-3)] + + def check_1(a): + x = A[a] + y = B[a] + if y.shape == (): + assert_equal(x, y, repr(a)) + else: + if x.size == 0 and y.size == 0: + pass + else: + assert_array_equal(x.toarray(), y, repr(a)) + + for j, a in enumerate(slices): + check_1(a) + + def check_2(a, b): + # Indexing np.matrix with 0-d arrays seems to be broken, + # as they seem not to be treated as scalars. + # https://github.com/numpy/numpy/issues/3110 + if isinstance(a, np.ndarray): + ai = int(a) + else: + ai = a + if isinstance(b, np.ndarray): + bi = int(b) + else: + bi = b + + x = A[a, b] + y = B[ai, bi] + + if y.shape == (): + assert_equal(x, y, repr((a, b))) + else: + if x.size == 0 and y.size == 0: + pass + else: + assert_array_equal(x.toarray(), y, repr((a, b))) + + for i, a in enumerate(slices): + for j, b in enumerate(slices): + check_2(a, b) + + # Check out of bounds etc. systematically + extra_slices = [] + for a, b, c in itertools.product(*([(None, 0, 1, 2, 5, 15, + -1, -2, 5, -15)]*3)): + if c == 0: + continue + extra_slices.append(slice(a, b, c)) + + for a in extra_slices: + check_2(a, a) + check_2(a, -2) + check_2(-2, a) + + def test_None_slicing(self): + B = self.asdense(arange(50).reshape(5,10)) + A = self.spcreator(B) + + assert A[1, 2].ndim == 0 + assert A[None, 1, 2:4].shape == (1, 2) + assert A[None, 1, 2, None].shape == (1, 1) + + # see gh-22458 + assert A[None, 1].shape == (1, 10) + assert A[1, None].shape == (1, 10) + assert A[None, 1, :].shape == (1, 10) + assert A[1, None, :].shape == (1, 10) + assert A[1, :, None].shape == (10, 1) + + assert A[None, 1:3, 2].shape == B[None, 1:3, 2].shape == (1, 2) + assert A[1:3, None, 2].shape == B[1:3, None, 2].shape == (2, 1) + assert A[1:3, 2, None].shape == B[1:3, 2, None].shape == (2, 1) + assert A[None, 1, 2:4].shape == B[None, 1, 2:4].shape == (1, 2) + assert A[1, None, 2:4].shape == B[1, None, 2:4].shape == (1, 2) + assert A[1, 2:4, None].shape == B[1, 2:4, None].shape == (2, 1) + + # different for spmatrix + if self.is_array_test: + assert A[1:3, 2].shape == B[1:3, 2].shape == (2,) + assert A[1, 2:4].shape == B[1, 2:4].shape == (2,) + assert A[None, 1, 2].shape == B[None, 1, 2].shape == (1,) + assert A[1, None, 2].shape == B[1, None, 2].shape == (1,) + assert A[1, 2, None].shape == B[1, 2, None].shape == (1,) + else: + assert A[1, 2:4].shape == B[1, 2:4].shape == (1, 2) + assert A[1:3, 2].shape == B[1:3, 2].shape == (2, 1) + assert A[None, 1, 2].shape == B[None, 1, 2].shape == (1, 1) + assert A[1, None, 2].shape == B[1, None, 2].shape == (1, 1) + assert A[1, 2, None].shape == B[1, 2, None].shape == (1, 1) + + def test_ellipsis_slicing(self): + b = self.asdense(arange(50).reshape(5,10)) + a = self.spcreator(b) + + assert_array_equal(a[...].toarray(), b[...]) + assert_array_equal(a[...,].toarray(), b[...,]) + + assert_array_equal(a[4, ...].toarray(), b[4, ...]) + assert_array_equal(a[..., 4].toarray(), b[..., 4]) + assert_array_equal(a[..., 5].toarray(), b[..., 5]) + with pytest.raises(IndexError, match='index .5. out of range'): + a[5, ...] + with pytest.raises(IndexError, match='index .10. out of range'): + a[..., 10] + with pytest.raises(IndexError, match='index .5. out of range'): + a.T[..., 5] + + assert_array_equal(a[1:, ...].toarray(), b[1:, ...]) + assert_array_equal(a[..., 1:].toarray(), b[..., 1:]) + assert_array_equal(a[:2, ...].toarray(), b[:2, ...]) + assert_array_equal(a[..., :2].toarray(), b[..., :2]) + + # check slice limit outside range + assert_array_equal(a[:5, ...].toarray(), b[:5, ...]) + assert_array_equal(a[..., :5].toarray(), b[..., :5]) + assert_array_equal(a[5:, ...].toarray(), b[5:, ...]) + assert_array_equal(a[..., 5:].toarray(), b[..., 5:]) + assert_array_equal(a[10:, ...].toarray(), b[10:, ...]) + assert_array_equal(a[..., 10:].toarray(), b[..., 10:]) + + # ellipsis should be ignored + assert_array_equal(a[1:, 1, ...].toarray(), b[1:, 1, ...]) + assert_array_equal(a[1, ..., 1:].toarray(), b[1, ..., 1:]) + assert_array_equal(a[..., 1, 1:].toarray(), b[1, ..., 1:]) + assert_array_equal(a[:2, 1, ...].toarray(), b[:2, 1, ...]) + assert_array_equal(a[1, ..., :2].toarray(), b[1, ..., :2]) + assert_array_equal(a[..., 1, :2].toarray(), b[1, ..., :2]) + # These return ints + assert_equal(a[1, 1, ...], b[1, 1, ...]) + assert_equal(a[1, ..., 1], b[1, ..., 1]) + + def test_ellipsis_fancy_bool(self): + numpy_a = self.asdense(arange(50).reshape(5, 10)) + a = self.spcreator(numpy_a) + + ix5 = [True, False, True, False, True] + ix10 = [False] * 5 + ix5 # same number of True values as ix5 + ix10_6True = ix5 + ix5 # not same number of True values as ix5 + full_ix = [ix10] * 5 + + assert_array_equal(toarray(a[full_ix, ...]), numpy_a[full_ix, ...]) + assert_array_equal(toarray(a[..., full_ix]), numpy_a[..., full_ix]) + + assert_array_equal(toarray(a[ix5, ...]), numpy_a[ix5, ...]) + assert_array_equal(toarray(a[..., ix10]), numpy_a[..., ix10]) + + assert_array_equal(toarray(a[ix5, ..., ix10]), numpy_a[ix5, ..., ix10]) + assert_array_equal(toarray(a[..., ix5, ix10]), numpy_a[..., ix5, ix10]) + assert_array_equal(toarray(a[ix5, ix10, ...]), numpy_a[ix5, ix10, ...]) + + with assert_raises(IndexError, match="shape mismatch"): + a[ix5, ix10_6True] + + def test_ellipsis_fancy_slicing(self): + b = self.asdense(arange(50).reshape(5, 10)) + a = self.spcreator(b) + + assert_array_equal(a[[4], ...].toarray(), b[[4], ...]) + assert_array_equal(a[[2, 4], ...].toarray(), b[[2, 4], ...]) + assert_array_equal(a[..., [4]].toarray(), b[..., [4]]) + assert_array_equal(a[..., [2, 4]].toarray(), b[..., [2, 4]]) + + assert_array_equal(a[[4], 1, ...].toarray(), b[[4], 1, ...]) + assert_array_equal(a[[2, 4], 1, ...].toarray(), b[[2, 4], 1, ...]) + assert_array_equal(a[[4], ..., 1].toarray(), b[[4], ..., 1]) + assert_array_equal(a[..., [4], 1].toarray(), b[..., [4], 1]) + # fancy index gives dense + assert_array_equal(toarray(a[[2, 4], ..., [2, 4]]), b[[2, 4], ..., [2, 4]]) + assert_array_equal(toarray(a[..., [2, 4], [2, 4]]), b[..., [2, 4], [2, 4]]) + + def test_multiple_ellipsis_slicing(self): + a = self.spcreator(arange(6).reshape(3, 2)) + + with pytest.raises(IndexError, + match='an index can only have a single ellipsis'): + a[..., ...] + with pytest.raises(IndexError, + match='an index can only have a single ellipsis'): + a[..., 1, ...] + + +class _TestSlicingAssign: + def test_slice_scalar_assign(self): + A = self.spcreator((5, 5)) + B = np.zeros((5, 5)) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + for C in [A, B]: + C[0:1,1] = 1 + C[3:0,0] = 4 + C[3:4,0] = 9 + C[0,4:] = 1 + C[3::-1,4:] = 9 + assert_array_equal(A.toarray(), B) + + def test_slice_assign_2(self): + n, m = (5, 10) + + def _test_set(i, j): + msg = f"i={i!r}; j={j!r}" + A = self.spcreator((n, m)) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + A[i, j] = 1 + B = np.zeros((n, m)) + B[i, j] = 1 + assert_array_almost_equal(A.toarray(), B, err_msg=msg) + # [i,1:2] + for i, j in [(2, slice(3)), (2, slice(None, 10, 4)), (2, slice(5, -2)), + (array(2), slice(5, -2))]: + _test_set(i, j) + + def test_self_self_assignment(self): + # Tests whether a row of one sparse array can be assigned to another. + B = self.spcreator((4,3)) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + B[0,0] = 2 + B[1,2] = 7 + B[2,1] = 3 + B[3,0] = 10 + + A = B / 10 + B[0,:] = A[0,:] + assert_array_equal(A[0,:].toarray(), B[0,:].toarray()) + + A = B / 10 + B[:,:] = A[:1,:1] + assert_array_equal(np.zeros((4,3)) + A[0,0], B.toarray()) + + A = B / 10 + B[:-1,0] = A[None,0,:].T + assert_array_equal(A[0,:].toarray().T, B[:-1,0].toarray()) + + def test_slice_assignment(self): + B = self.spcreator((4,3)) + expected = array([[10,0,0], + [0,0,6], + [0,14,0], + [0,0,0]]) + block = [[1,0],[0,4]] + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + B[0,0] = 5 + B[1,2] = 3 + B[2,1] = 7 + B[:,:] = B+B + assert_array_equal(B.toarray(), expected) + + B[:2,:2] = self.csc_container(array(block)) + assert_array_equal(B.toarray()[:2, :2], block) + + def test_sparsity_modifying_assignment(self): + B = self.spcreator((4,3)) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + B[0,0] = 5 + B[1,2] = 3 + B[2,1] = 7 + B[3,0] = 10 + B[:3] = self.csr_container(np.eye(3)) + + expected = array([[1,0,0],[0,1,0],[0,0,1],[10,0,0]]) + assert_array_equal(B.toarray(), expected) + + def test_set_slice(self): + A = self.spcreator((5,10)) + B = array(zeros((5, 10), float)) + s_ = np.s_ + slices = [s_[:2], s_[1:2], s_[3:], s_[3::2], + s_[8:3:-1], s_[4::-2], s_[:5:-1], + 0, 1, s_[:], s_[1:5], -1, -2, -5, + array(-1), np.int8(-3)] + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + for j, a in enumerate(slices): + A[a] = j + B[a] = j + assert_array_equal(A.toarray(), B, repr(a)) + + for i, a in enumerate(slices): + for j, b in enumerate(slices): + A[a,b] = 10*i + 1000*(j+1) + B[a,b] = 10*i + 1000*(j+1) + assert_array_equal(A.toarray(), B, repr((a, b))) + + A[0, 1:10:2] = range(1, 10, 2) + B[0, 1:10:2] = range(1, 10, 2) + assert_array_equal(A.toarray(), B) + A[1:5:2, 0] = np.arange(1, 5, 2)[:, None] + B[1:5:2, 0] = np.arange(1, 5, 2)[:] + assert_array_equal(A.toarray(), B) + + # The next commands should raise exceptions + assert_raises(ValueError, A.__setitem__, (0, 0), list(range(100))) + assert_raises(ValueError, A.__setitem__, (0, 0), arange(100)) + assert_raises(ValueError, A.__setitem__, (0, slice(None)), + list(range(100))) + assert_raises(ValueError, A.__setitem__, (slice(None), 1), + list(range(100))) + assert_raises(ValueError, A.__setitem__, (slice(None), 1), A.copy()) + assert_raises(ValueError, A.__setitem__, + ([[1, 2, 3], [0, 3, 4]], [1, 2, 3]), [1, 2, 3, 4]) + assert_raises(IndexError, A.__setitem__, + ([[1, 2, 3], [0, 3, 4], [4, 1, 3]], + [[1, 2, 4], [0, 1, 3]]), [2, 3, 4]) + assert_raises(ValueError, A.__setitem__, (slice(4), 0), + [[1, 2], [3, 4]]) + + def test_assign_empty(self): + A = self.spcreator(np.ones((2, 3))) + B = self.spcreator((1, 2)) + # Note: This is not like NumPy!! Incoming shape needs to be (2,) for NumPy + # we are more lenient to accommodate vectors in 2d format as input + A[1, :2] = B + assert_array_equal(A.toarray(), [[1, 1, 1], [0, 0, 1]]) + + def test_assign_1d_slice(self): + A = self.spcreator(np.ones((3, 3))) + x = np.zeros(3) + A[:, 0] = x + A[1, :] = x + assert_array_equal(A.toarray(), [[0, 1, 1], [0, 0, 0], [0, 1, 1]]) + + +class _TestFancyIndexing: + """Tests fancy indexing features. The tests for any matrix formats + that implement these features should derive from this class. + """ + + def test_dtype_preservation_empty_index(self): + # This should be parametrized with pytest, but something in the parent + # class creation used in this file breaks pytest.mark.parametrize. + for dt in [np.int16, np.int32, np.float32, np.float64]: + A = self.spcreator((3, 2), dtype=dt) + assert_equal(A[:, [False, False]].dtype, dt) + assert_equal(A[[False, False, False], :].dtype, dt) + assert_equal(A[:, []].dtype, dt) + assert_equal(A[[], :].dtype, dt) + + def test_bad_index(self): + A = self.spcreator(np.zeros([5, 5])) + assert_raises(IndexError, A.__getitem__, "foo").match('Index dimension') + assert_raises(IndexError, A.__getitem__, (2, "foo")).match('Index dimension') + idx = ([1, 2, 3], [1, 2, 3, 4]) + assert_raises(IndexError, A.__getitem__, idx).match('shape mismatch') + + def test_fancy_indexing(self): + B = self.asdense(arange(50).reshape(5,10)) + A = self.spcreator(B) + + # [i] + assert_equal(A[[3]].toarray(), B[[3]]) + assert_equal(A[[1, 3]].toarray(), B[[1, 3]]) + + # [i,[1,2]] + assert_equal(A[3, [3]].toarray(), B[3, [3]]) + assert_equal(A[3, [1, 3]].toarray(), B[3, [1, 3]]) + assert_equal(A[-1, [2, -5]].toarray(), B[-1, [2, -5]]) + assert_equal(A[array(-1), [2, -5]].toarray(), B[-1, [2, -5]]) + assert_equal(A[-1, array([2, -5])].toarray(), B[-1, [2, -5]]) + assert_equal(A[array(-1), array([2, -5])].toarray(), B[-1, [2, -5]]) + + # [1:2,[1,2]] + assert_equal(A[:, [2, 8, 3, -1]].toarray(), B[:, [2, 8, 3, -1]]) + assert_equal(A[3:4, [9]].toarray(), B[3:4, [9]]) + assert_equal(A[1:4, [-1, -5]].toarray(), B[1:4, [-1, -5]]) + assert_equal(A[1:4, array([-1, -5])].toarray(), B[1:4, [-1, -5]]) + + # [[1,2],j] + assert_equal(A[[3], 3].toarray(), B[[3], 3]) + assert_equal(A[[1, 3], 3].toarray(), B[[1, 3], 3]) + assert_equal(A[[2, -5], -4].toarray(), B[[2, -5], -4]) + assert_equal(A[array([2, -5]), -4].toarray(), B[[2, -5], -4]) + assert_equal(A[[2, -5], array(-4)].toarray(), B[[2, -5], -4]) + assert_equal(A[array([2, -5]), array(-4)].toarray(), B[[2, -5], -4]) + + # [[1,2],1:2] + assert_equal(A[[3], :].toarray(), B[[3], :]) + assert_equal(A[[1, 3], :].toarray(), B[[1, 3], :]) + assert_equal(A[[2, -5], 8:-1].toarray(), B[[2, -5], 8:-1]) + assert_equal(A[array([2, -5]), 8:-1].toarray(), B[[2, -5], 8:-1]) + + # [[1,2],[1,2]] + assert_equal(toarray(A[[3], [4]]), B[[3], [4]]) + assert_equal(toarray(A[[1, 3], [2, 4]]), B[[1, 3], [2, 4]]) + assert_equal(toarray(A[[-1, -3], [2, -4]]), B[[-1, -3], [2, -4]]) + assert_equal( + toarray(A[array([-1, -3]), [2, -4]]), B[[-1, -3], [2, -4]] + ) + assert_equal( + toarray(A[[-1, -3], array([2, -4])]), B[[-1, -3], [2, -4]] + ) + assert_equal( + toarray(A[array([-1, -3]), array([2, -4])]), B[[-1, -3], [2, -4]] + ) + + # [[[1],[2]],[1,2]] + assert_equal(A[[[1], [3]], [2, 4]].toarray(), B[[[1], [3]], [2, 4]]) + assert_equal( + A[[[-1], [-3], [-2]], [2, -4]].toarray(), + B[[[-1], [-3], [-2]], [2, -4]] + ) + assert_equal( + A[array([[-1], [-3], [-2]]), [2, -4]].toarray(), + B[[[-1], [-3], [-2]], [2, -4]] + ) + assert_equal( + A[[[-1], [-3], [-2]], array([2, -4])].toarray(), + B[[[-1], [-3], [-2]], [2, -4]] + ) + assert_equal( + A[array([[-1], [-3], [-2]]), array([2, -4])].toarray(), + B[[[-1], [-3], [-2]], [2, -4]] + ) + + # [[1,2]] + assert_equal(A[[1, 3]].toarray(), B[[1, 3]]) + assert_equal(A[[-1, -3]].toarray(), B[[-1, -3]]) + assert_equal(A[array([-1, -3])].toarray(), B[[-1, -3]]) + + # [[1,2],:][:,[1,2]] + assert_equal(A[[3], :][:, [4]].toarray(), B[[3], :][:, [4]]) + assert_equal( + A[[1, 3], :][:, [2, 4]].toarray(), B[[1, 3], :][:, [2, 4]] + ) + assert_equal( + A[[-1, -3], :][:, [2, -4]].toarray(), B[[-1, -3], :][:, [2, -4]] + ) + assert_equal( + A[array([-1, -3]), :][:, array([2, -4])].toarray(), + B[[-1, -3], :][:, [2, -4]] + ) + + assert_equal( + A[1, [[1, 3]]][[[0, 0]], 1].toarray(), B[1, [[1, 3]]][[[0, 0]], 1] + ) + assert_equal( + A[1, [[-1, -3]]][[[0, -1]], 1].toarray(), B[1, [[-1, -3]]][[[0, -1]], 1] + ) + # leads to 3D result + if A.format == "coo": + assert_equal(A[:1, [[1, 3]]].toarray(), B[:1, [[1, 3]]]) + assert_equal(A[[[0, 0]], :1].toarray(), B[[[0, 0]], :1]) + else: + with pytest.raises(IndexError, match="Only 1D or 2D|>2D is not supported"): + A[:1, [[1, 3]]] + with pytest.raises(IndexError, match="Only 1D or 2D|>2D is not supported"): + A[[[0, 0]], :1] + + + assert_equal( + A[:, [1, 3]][[2, 4], :].toarray(), B[:, [1, 3]][[2, 4], :] + ) + assert_equal( + A[:, [-1, -3]][[2, -4], :].toarray(), B[:, [-1, -3]][[2, -4], :] + ) + assert_equal( + A[:, array([-1, -3])][array([2, -4]), :].toarray(), + B[:, [-1, -3]][[2, -4], :] + ) + + # Check bug reported by Robert Cimrman: + # http://thread.gmane.org/gmane.comp.python.scientific.devel/7986 (dead link) + s = slice(int8(2),int8(4),None) + assert_equal(A[s, :].toarray(), B[2:4, :]) + assert_equal(A[:, s].toarray(), B[:, 2:4]) + + # Regression for gh-4917: index with tuple of 2D arrays + i = np.array([[1]], dtype=int) + assert_equal(A[i, i].toarray(), B[i, i]) + + # Regression for gh-4917: index with tuple of empty nested lists + assert_equal(A[[[]], [[]]].toarray(), B[[[]], [[]]]) + + def test_fancy_indexing_randomized(self): + np.random.seed(1234) # make runs repeatable + + NUM_SAMPLES = 50 + M = 6 + N = 4 + + D = self.asdense(np.random.rand(M,N)) + D = np.multiply(D, D > 0.5) + + I = np.random.randint(-M + 1, M, size=NUM_SAMPLES) + J = np.random.randint(-N + 1, N, size=NUM_SAMPLES) + + S = self.spcreator(D) + + SIJ = S[I,J] + if issparse(SIJ): + SIJ = SIJ.toarray() + assert_equal(SIJ, D[I,J]) + + I_bad = I + M + J_bad = J - N + + assert_raises(IndexError, S.__getitem__, (I_bad,J)) + assert_raises(IndexError, S.__getitem__, (I,J_bad)) + + def test_missized_masking(self): + M, N = 5, 10 + + B = self.asdense(arange(M * N).reshape(M, N)) + A = self.spcreator(B) + + # Content of mask shouldn't matter, only its size + row_long = np.ones(M + 1, dtype=bool) + row_short = np.ones(M - 1, dtype=bool) + col_long = np.ones(N + 2, dtype=bool) + col_short = np.ones(N - 2, dtype=bool) + + match="bool index .* has shape .* instead of .*" + for i, j in itertools.product( + (row_long, row_short, slice(None)), + (col_long, col_short, slice(None)), + ): + if isinstance(i, slice) and isinstance(j, slice): + continue + with pytest.raises(IndexError, match=match): + _ = A[i, j] + + def test_fancy_indexing_boolean(self): + np.random.seed(1234) # make runs repeatable + + B = self.asdense(arange(50).reshape(5,10)) + A = self.spcreator(B) + + I = np.array(np.random.randint(0, 2, size=5), dtype=bool) + J = np.array(np.random.randint(0, 2, size=10), dtype=bool) + X = np.array(np.random.randint(0, 2, size=(5, 10)), dtype=bool) + + assert_equal(toarray(A[I]), B[I]) + assert_equal(toarray(A[:, J]), B[:, J]) + assert_equal(toarray(A[X]), B[X]) + assert_equal(toarray(A[B > 9]), B[B > 9]) + + I = np.array([True, False, True, True, False]) + J = np.array([False, True, True, False, True, + False, False, False, False, False]) + + assert_equal(toarray(A[I, J]), B[I, J]) + + Z1 = np.zeros((6, 11), dtype=bool) + Z2 = np.zeros((6, 11), dtype=bool) + Z2[0,-1] = True + Z3 = np.zeros((6, 11), dtype=bool) + Z3[-1,0] = True + + assert_raises(IndexError, A.__getitem__, Z1) + assert_raises(IndexError, A.__getitem__, Z2) + assert_raises(IndexError, A.__getitem__, Z3) + assert_raises((IndexError, ValueError), A.__getitem__, (X, 1)) + + def test_fancy_indexing_sparse_boolean(self): + np.random.seed(1234) # make runs repeatable + + B = self.asdense(arange(50).reshape(5,10)) + A = self.spcreator(B) + + X = np.array(np.random.randint(0, 2, size=(5, 10)), dtype=bool) + + Xsp = self.csr_container(X) + + assert_equal(toarray(A[Xsp]), B[X]) + assert_equal(toarray(A[A > 9]), B[B > 9]) + + Z = np.array(np.random.randint(0, 2, size=(5, 11)), dtype=bool) + Y = np.array(np.random.randint(0, 2, size=(6, 10)), dtype=bool) + + Zsp = self.csr_container(Z) + Ysp = self.csr_container(Y) + + assert_raises(IndexError, A.__getitem__, Zsp) + assert_raises(IndexError, A.__getitem__, Ysp) + assert_raises((IndexError, ValueError), A.__getitem__, (Xsp, 1)) + + def test_fancy_indexing_regression_3087(self): + mat = self.spcreator(array([[1, 0, 0], [0,1,0], [1,0,0]])) + desired_cols = np.ravel(mat.sum(0)) > 0 + assert_equal(mat[:, desired_cols].toarray(), [[1, 0], [0, 1], [1, 0]]) + + def test_fancy_indexing_seq_assign(self): + mat = self.spcreator(array([[1, 0], [0, 1]])) + assert_raises(ValueError, mat.__setitem__, (0, 0), np.array([1,2])) + + def test_fancy_indexing_2d_assign(self): + # regression test for gh-10695 + mat = self.spcreator(array([[1, 0], [2, 3]])) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + mat[[0, 1], [1, 1]] = mat[[1, 0], [0, 0]] + assert_equal(toarray(mat), array([[1, 2], [2, 1]])) + + def test_fancy_indexing_empty(self): + B = self.asdense(arange(50).reshape(5,10)) + B[1,:] = 0 + B[:,2] = 0 + B[3,6] = 0 + A = self.spcreator(B) + + K = np.array([False, False, False, False, False]) + assert_equal(toarray(A[K]), B[K]) + K = np.array([], dtype=int) + assert_equal(toarray(A[K]), B[K]) + assert_equal(toarray(A[K, K]), B[K, K]) + J = np.array([0, 1, 2, 3, 4], dtype=int)[:,None] + assert_equal(toarray(A[K, J]), B[K, J]) + assert_equal(toarray(A[J, K]), B[J, K]) + + +@contextlib.contextmanager +def check_remains_sorted(X): + """Checks that sorted indices property is retained through an operation + """ + if not hasattr(X, 'has_sorted_indices') or not X.has_sorted_indices: + yield + return + yield + indices = X.indices.copy() + X.has_sorted_indices = False + X.sort_indices() + assert_array_equal(indices, X.indices, + 'Expected sorted indices, found unsorted') + + +class _TestFancyIndexingAssign: + def test_bad_index_assign(self): + A = self.spcreator(np.zeros([5, 5])) + assert_raises((IndexError, ValueError, TypeError), A.__setitem__, "foo", 2) + assert_raises((IndexError, ValueError, TypeError), A.__setitem__, (2, "foo"), 5) + + def test_fancy_indexing_set(self): + n, m = (5, 10) + + def _test_set_slice(i, j): + A = self.spcreator((n, m)) + B = self.asdense(np.zeros((n, m))) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + B[i, j] = 1 + with check_remains_sorted(A): + A[i, j] = 1 + assert_array_almost_equal(A.toarray(), B) + # [1:2,1:2] + for i, j in [((2, 3, 4), slice(None, 10, 4)), + (np.arange(3), slice(5, -2)), + (slice(2, 5), slice(5, -2))]: + _test_set_slice(i, j) + for i, j in [(np.arange(3), np.arange(3)), ((0, 3, 4), (1, 2, 4))]: + _test_set_slice(i, j) + + def test_fancy_assignment_dtypes(self): + def check(dtype): + A = self.spcreator((5, 5), dtype=dtype) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + A[[0,1],[0,1]] = dtype.type(1) + assert_equal(A.sum(), dtype.type(1)*2) + A[0:2,0:2] = dtype.type(1.0) + assert_equal(A.sum(), dtype.type(1)*4) + A[2,2] = dtype.type(1.0) + assert_equal(A.sum(), dtype.type(1)*4 + dtype.type(1)) + + for dtype in supported_dtypes: + check(np.dtype(dtype)) + + def test_sequence_assignment(self): + A = self.spcreator((4,3)) + B = self.spcreator(eye(3,4)) + + i0 = [0,1,2] + i1 = (0,1,2) + i2 = array(i0) + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + with check_remains_sorted(A): + A[0,i0] = B[i0,0].T + A[1,i1] = B[i1,1].T + A[2,i2] = B[i2,2].T + assert_array_equal(A.toarray(), B.T.toarray()) + + # column slice + A = self.spcreator((2,3)) + with check_remains_sorted(A): + A[1,1:3] = [10,20] + assert_array_equal(A.toarray(), [[0, 0, 0], [0, 10, 20]]) + + # row slice + A = self.spcreator((3,2)) + with check_remains_sorted(A): + A[1:3,1] = [[10],[20]] + assert_array_equal(A.toarray(), [[0, 0], [0, 10], [0, 20]]) + + # both slices + A = self.spcreator((3,3)) + B = self.asdense(np.zeros((3,3))) + with check_remains_sorted(A): + for C in [A, B]: + C[[0,1,2], [0,1,2]] = [4,5,6] + assert_array_equal(A.toarray(), B) + + # both slices (2) + A = self.spcreator((4, 3)) + with check_remains_sorted(A): + A[(1, 2, 3), (0, 1, 2)] = [1, 2, 3] + assert_almost_equal(A.sum(), 6) + B = self.asdense(np.zeros((4, 3))) + B[(1, 2, 3), (0, 1, 2)] = [1, 2, 3] + assert_array_equal(A.toarray(), B) + + def test_fancy_assign_empty(self): + B = self.asdense(arange(50).reshape(5,10)) + B[1,:] = 0 + B[:,2] = 0 + B[3,6] = 0 + A = self.spcreator(B) + + K = np.array([False, False, False, False, False]) + A[K] = 42 + assert_equal(toarray(A), B) + + K = np.array([], dtype=int) + A[K] = 42 + assert_equal(toarray(A), B) + A[K,K] = 42 + assert_equal(toarray(A), B) + + J = np.array([0, 1, 2, 3, 4], dtype=int)[:,None] + A[K,J] = 42 + assert_equal(toarray(A), B) + A[J,K] = 42 + assert_equal(toarray(A), B) + + +class _TestFancyMultidim: + def test_fancy_indexing_ndarray(self): + IandJ = [ + (np.array([[1], [2], [3]]), np.array([3, 4, 2])), + (np.array([[1], [2], [3]]), np.array([[3, 4, 2]])), + (np.array([[1, 2, 3]]), np.array([[3], [4], [2]])), + (np.array([1, 2, 3]), np.array([[3], [4], [2]])), + (np.array([[1, 2, 3], [3, 4, 2]]), np.array([[5, 6, 3], [2, 3, 1]])), + ] + + np.random.seed(1234) + D = self.asdense(np.random.rand(5, 7)) + S = self.spcreator(D) + + # These inputs generate 3-D outputs + if S.format == 'coo': + IandJ.append( + (np.array([[[1], [2], [3]], [[3], [4], [2]]]), + np.array([[[5], [6], [3]], [[2], [3], [1]]])) + ) + + for I, J in IandJ: + SIJ = S[I, J] + DIJ = D[I, J] + assert_equal(toarray(SIJ), DIJ) + + I_bad = I + 5 + J_bad = J + 7 + + assert_raises(IndexError, S.__getitem__, (I_bad, J)) + assert_raises(IndexError, S.__getitem__, (I, J_bad)) + + if S.format != 'coo': + assert_raises(IndexError, S.__getitem__, ([I, I], slice(None))) + assert_raises(IndexError, S.__getitem__, (slice(None), [J, J])) + else: + assert_equal(S[[I, I], :].toarray(), D[[I, I], :]) + assert_equal(S[:, [J, J]].toarray(), D[:, [J, J]]) + + +class _TestFancyMultidimAssign: + def test_fancy_assign_ndarray(self): + np.random.seed(1234) + + D = self.asdense(np.random.rand(5, 7)) + S = self.spcreator(D) + X = np.random.rand(2, 3) + + I = np.array([[1, 2, 3], [3, 4, 2]]) + J = np.array([[5, 6, 3], [2, 3, 1]]) + + with check_remains_sorted(S): + S[I,J] = X + D[I,J] = X + assert_equal(S.toarray(), D) + + I_bad = I + 5 + J_bad = J + 7 + + C = [1, 2, 3] + + with check_remains_sorted(S): + S[I,J] = C + D[I,J] = C + assert_equal(S.toarray(), D) + + with check_remains_sorted(S): + S[I,J] = 3 + D[I,J] = 3 + assert_equal(S.toarray(), D) + + assert_raises(IndexError, S.__setitem__, (I_bad,J), C) + assert_raises(IndexError, S.__setitem__, (I,J_bad), C) + + def test_fancy_indexing_multidim_set(self): + n, m = (5, 10) + + def _test_set_slice(i, j): + A = self.spcreator((n, m)) + with check_remains_sorted(A), warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + A[i, j] = 1 + B = self.asdense(np.zeros((n, m))) + B[i, j] = 1 + assert_array_almost_equal(A.toarray(), B) + # [[[1, 2], [1, 2]], [1, 2]] + for i, j in [(np.array([[1, 2], [1, 3]]), [1, 3]), + (np.array([0, 4]), [[0, 3], [1, 2]]), + ([[1, 2, 3], [0, 2, 4]], [[0, 4, 3], [4, 1, 2]])]: + _test_set_slice(i, j) + + def test_fancy_assign_list(self): + np.random.seed(1234) + + D = self.asdense(np.random.rand(5, 7)) + S = self.spcreator(D) + X = np.random.rand(2, 3) + + I = [[1, 2, 3], [3, 4, 2]] + J = [[5, 6, 3], [2, 3, 1]] + + S[I,J] = X + D[I,J] = X + assert_equal(S.toarray(), D) + + I_bad = [[ii + 5 for ii in i] for i in I] + J_bad = [[jj + 7 for jj in j] for j in J] + C = [1, 2, 3] + + S[I,J] = C + D[I,J] = C + assert_equal(S.toarray(), D) + + S[I,J] = 3 + D[I,J] = 3 + assert_equal(S.toarray(), D) + + assert_raises(IndexError, S.__setitem__, (I_bad,J), C) + assert_raises(IndexError, S.__setitem__, (I,J_bad), C) + + def test_fancy_assign_slice(self): + np.random.seed(1234) + + D = self.asdense(np.random.rand(5, 7)) + S = self.spcreator(D) + + I = [1, 2, 3, 3, 4, 2] + J = [5, 6, 3, 2, 3, 1] + + I_bad = [ii + 5 for ii in I] + J_bad = [jj + 7 for jj in J] + + C1 = [1, 2, 3, 4, 5, 6, 7] + C2 = np.arange(5)[:, None] + assert_raises(IndexError, S.__setitem__, (I_bad, slice(None)), C1) + assert_raises(IndexError, S.__setitem__, (slice(None), J_bad), C2) + + +class _TestArithmetic: + """ + Test real/complex arithmetic + """ + def __arith_init(self): + # these can be represented exactly in FP (so arithmetic should be exact) + __A = array([[-1.5, 6.5, 0, 2.25, 0, 0], + [3.125, -7.875, 0.625, 0, 0, 0], + [0, 0, -0.125, 1.0, 0, 0], + [0, 0, 8.375, 0, 0, 0]], 'float64') + __B = array([[0.375, 0, 0, 0, -5, 2.5], + [14.25, -3.75, 0, 0, -0.125, 0], + [0, 7.25, 0, 0, 0, 0], + [18.5, -0.0625, 0, 0, 0, 0]], 'complex128') + __B.imag = array([[1.25, 0, 0, 0, 6, -3.875], + [2.25, 4.125, 0, 0, 0, 2.75], + [0, 4.125, 0, 0, 0, 0], + [-0.0625, 0, 0, 0, 0, 0]], 'float64') + + # fractions are all x/16ths + assert_array_equal((__A*16).astype('int32'),16*__A) + assert_array_equal((__B.real*16).astype('int32'),16*__B.real) + assert_array_equal((__B.imag*16).astype('int32'),16*__B.imag) + + __Asp = self.spcreator(__A) + __Bsp = self.spcreator(__B) + return __A, __B, __Asp, __Bsp + + @pytest.mark.fail_slow(20) + def test_add_sub(self): + __A, __B, __Asp, __Bsp = self.__arith_init() + + # basic tests + assert_array_equal( + (__Asp + __Bsp).toarray(), __A + __B + ) + + # check conversions + for x in supported_dtypes: + with np.errstate(invalid="ignore"): + A = __A.astype(x) + Asp = self.spcreator(A) + for y in supported_dtypes: + if not np.issubdtype(y, np.complexfloating): + with np.errstate(invalid="ignore"): + B = __B.real.astype(y) + else: + B = __B.astype(y) + Bsp = self.spcreator(B) + + # addition + D1 = A + B + S1 = Asp + Bsp + + assert_equal(S1.dtype,D1.dtype) + assert_array_equal(S1.toarray(), D1) + assert_array_equal(Asp + B,D1) # check sparse + dense + assert_array_equal(A + Bsp,D1) # check dense + sparse + + # subtraction + if np.dtype('bool') in [x, y]: + # boolean array subtraction deprecated in 1.9.0 + continue + + D1 = A - B + S1 = Asp - Bsp + + assert_equal(S1.dtype,D1.dtype) + assert_array_equal(S1.toarray(), D1) + assert_array_equal(Asp - B,D1) # check sparse - dense + assert_array_equal(A - Bsp,D1) # check dense - sparse + + def test_mu(self): + __A, __B, __Asp, __Bsp = self.__arith_init() + + # basic tests + assert_array_equal((__Asp @ __Bsp.T).toarray(), + __A @ __B.T) + + for x in supported_dtypes: + with np.errstate(invalid="ignore"): + A = __A.astype(x) + Asp = self.spcreator(A) + for y in supported_dtypes: + if np.issubdtype(y, np.complexfloating): + B = __B.astype(y) + else: + with np.errstate(invalid="ignore"): + B = __B.real.astype(y) + Bsp = self.spcreator(B) + + D1 = A @ B.T + S1 = Asp @ Bsp.T + + assert_allclose(S1.toarray(), D1, + atol=1e-14*abs(D1).max()) + assert_equal(S1.dtype,D1.dtype) + + +class _TestMinMax: + def test_minmax(self): + for dtype in [np.float32, np.float64, np.int32, np.int64, np.complex128]: + D = np.arange(20, dtype=dtype).reshape(5,4) + + X = self.spcreator(D) + assert_equal(X.min(), 0) + assert_equal(X.max(), 19) + assert_equal(X.min().dtype, dtype) + assert_equal(X.max().dtype, dtype) + + D *= -1 + X = self.spcreator(D) + assert_equal(X.min(), -19) + assert_equal(X.max(), 0) + + D += 5 + X = self.spcreator(D) + assert_equal(X.min(), -14) + assert_equal(X.max(), 5) + + # try a fully dense matrix + X = self.spcreator(np.arange(1, 10).reshape(3, 3)) + assert_equal(X.min(), 1) + assert_equal(X.min().dtype, X.dtype) + assert_equal(X.min(explicit=True), 1) + + X = -X + assert_equal(X.max(), -1) + assert_equal(X.max(explicit=True), -1) + + # and a fully sparse matrix + Z = self.spcreator(np.zeros((1, 1))) + assert_equal(Z.min(), 0) + assert_equal(Z.max(), 0) + assert_equal(Z.max().dtype, Z.dtype) + + # another test + D = np.arange(20, dtype=float).reshape(5,4) + D[0:2, :] = 0 + X = self.spcreator(D) + assert_equal(X.min(), 0) + assert_equal(X.max(), 19) + + # zero-size matrices + for D in [np.zeros((0, 0)), np.zeros((0, 10)), np.zeros((10, 0))]: + X = self.spcreator(D) + assert_raises(ValueError, X.min) + assert_raises(ValueError, X.max) + + def test_minmax_axis(self): + keep = not self.is_array_test + D = np.arange(50).reshape(5, 10) + # completely empty rows, leaving some completely full: + D[1, :] = 0 + # empty at end for reduceat: + D[:, 9] = 0 + # partial rows/cols: + D[3, 3] = 0 + # entries on either side of 0: + D[2, 2] = -1 + X = self.spcreator(D) + + axes_even = [0, -2] + axes_odd = [1, -1] + for axis in axes_odd + axes_even: + assert_array_equal( + X.max(axis=axis).toarray(), D.max(axis=axis, keepdims=keep) + ) + assert_array_equal( + X.min(axis=axis).toarray(), D.min(axis=axis, keepdims=keep) + ) + + for axis in axes_even: + assert_equal( + X.max(axis=axis, explicit=True).toarray(), + self.asdense([40, 41, 42, 43, 44, 45, 46, 47, 48, 0]) + ) + if np.any(X.data == 0): + # Noncanonical case + expected = self.asdense([20, 1, -1, 3, 4, 5, 0, 7, 8, 0]) + else: + expected = self.asdense([20, 1, -1, 3, 4, 5, 6, 7, 8, 0]) + assert_equal(X.min(axis=axis, explicit=True).toarray(), expected) + + for axis in axes_odd: + expected_max = np.array([8, 0, 28, 38, 48]) + expected_min = np.array([1, 0, -1, 30, 40]) + if not self.is_array_test: + expected_max = expected_max.reshape((5, 1)) + expected_min = expected_min.reshape((5, 1)) + assert_equal(X.max(axis=axis, explicit=True).toarray(), expected_max) + assert_equal(X.min(axis=axis, explicit=True).toarray(), expected_min) + + # full matrix + D = np.arange(1, 51).reshape(10, 5) + X = self.spcreator(D) + for axis in axes_odd + axes_even: + assert_array_equal( + X.max(axis=axis).toarray(), D.max(axis=axis, keepdims=keep) + ) + assert_array_equal( + X.min(axis=axis).toarray(), D.min(axis=axis, keepdims=keep) + ) + assert_equal(X.max(axis=(0, 1)), D.max(axis=(0, 1), keepdims=keep)) + + for axis in axes_even: + expected_max = D[-1, :] + expected_min = D[0, :] + if not self.is_array_test: + expected_max = D[None, -1, :] + expected_min = D[None, 0, :] + assert_equal(X.max(axis=axis, explicit=True).toarray(), expected_max) + assert_equal(X.min(axis=axis, explicit=True).toarray(), expected_min) + for axis in axes_odd: + expected_max = D[:, -1] + expected_min = D[:, 0] + if not self.is_array_test: + expected_max = D[:, -1, None] + expected_min = D[:, 0, None] + assert_equal(X.max(axis=axis, explicit=True).toarray(), expected_max) + assert_equal(X.min(axis=axis, explicit=True).toarray(), expected_min) + + # empty matrix + D = self.asdense(np.zeros((10, 5))) + X = self.spcreator(D) + for axis in axes_even + axes_odd: + assert_equal(X.max(axis=axis, explicit=True).toarray(), D.max(axis=axis)) + assert_equal(X.min(axis=axis, explicit=True).toarray(), D.min(axis=axis)) + + # zero-size matrices + D = self.asdense(np.zeros((0, 10))) + X = self.spcreator(D) + explicit_values = [True, False] + even_explicit_pairs = list(itertools.product(axes_even, explicit_values)) + odd_explicit_pairs = list(itertools.product(axes_odd, explicit_values)) + for axis, ex in even_explicit_pairs: + assert_raises(ValueError, X.min, axis=axis, explicit=ex) + assert_raises(ValueError, X.max, axis=axis, explicit=ex) + for axis, ex in odd_explicit_pairs: + assert_equal(X.max(axis=axis, explicit=ex).toarray(), D.max(axis=axis)) + assert_equal(X.min(axis=axis, explicit=ex).toarray(), D.min(axis=axis)) + + D = self.asdense(np.zeros((10, 0))) + X = self.spcreator(D) + for axis, ex in odd_explicit_pairs: + assert_raises(ValueError, X.min, axis=axis, explicit=ex) + assert_raises(ValueError, X.max, axis=axis, explicit=ex) + for axis, ex in even_explicit_pairs: + assert_equal(X.max(axis=axis, explicit=ex).toarray(), D.max(axis=axis)) + assert_equal(X.min(axis=axis, explicit=ex).toarray(), D.min(axis=axis)) + + def test_minmax_container_type(self): + dat = array([[0, 1, 2], + [3, -4, 5], + [-6, 7, 9]]) + datsp = self.spcreator(dat) + matrix_or_array = ndarray if self.is_array_test else np.matrix + spmatrix_or_sparray = sparray if self.is_array_test else spmatrix + + assert isscalarlike(datsp.min()) + assert isinstance(datsp.min(axis=0), spmatrix_or_sparray) + assert isinstance(datsp.min(axis=1), spmatrix_or_sparray) + + assert isscalarlike(datsp.max()) + assert isinstance(datsp.max(axis=0), spmatrix_or_sparray) + assert isinstance(datsp.max(axis=1), spmatrix_or_sparray) + + assert isscalarlike(datsp.nanmin()) + assert isinstance(datsp.nanmin(axis=0), spmatrix_or_sparray) + assert isinstance(datsp.nanmin(axis=1), spmatrix_or_sparray) + + assert isscalarlike(datsp.nanmax()) + assert isinstance(datsp.nanmax(axis=0), spmatrix_or_sparray) + assert isinstance(datsp.nanmax(axis=1), spmatrix_or_sparray) + + assert isscalarlike(datsp.argmin()) + assert isinstance(datsp.argmin(axis=0), matrix_or_array) + assert isinstance(datsp.argmin(axis=1), matrix_or_array) + + assert isscalarlike(datsp.argmax()) + assert isinstance(datsp.argmax(axis=0), matrix_or_array) + assert isinstance(datsp.argmax(axis=1), matrix_or_array) + + def test_nanminmax(self): + D = self.asdense(np.arange(50).reshape(5,10), dtype=float) + D[1, :] = 0 + D[:, 9] = 0 + D[3, 3] = 0 + D[2, 2] = -1 + D[4, 2] = np.nan + D[1, 4] = np.nan + X = self.spcreator(D) + + X_nan_maximum = X.nanmax() + assert np.isscalar(X_nan_maximum) + assert X_nan_maximum == np.nanmax(D) + + X_nan_minimum = X.nanmin() + assert np.isscalar(X_nan_minimum) + assert X_nan_minimum == np.nanmin(D) + + X_nan_minimum = X.nanmin(axis=(0, 1)) + assert np.isscalar(X_nan_minimum) + assert X_nan_minimum == np.nanmin(D, axis=(0, 1)) + + axes = [-2, -1, 0, 1] + for axis in axes: + X_nan_maxima = X.nanmax(axis=axis) + assert_allclose(X_nan_maxima.toarray(), np.nanmax(D, axis=axis)) + assert isinstance(X_nan_maxima, self.coo_container) + + X_nan_minima = X.nanmin(axis=axis) + assert_allclose(X_nan_minima.toarray(), np.nanmin(D, axis=axis)) + assert isinstance(X_nan_minima, self.coo_container) + + def test_minmax_invalid_params(self): + dat = array([[0, 1, 2], + [3, -4, 5], + [-6, 7, 9]]) + datsp = self.spcreator(dat) + + for fname in ('min', 'max'): + datfunc = getattr(dat, fname) + func = getattr(datsp, fname) + assert_raises(ValueError, func, axis=3) + assert_raises(TypeError, func, axis=1.5) + assert_raises(ValueError, func, axis=1, out=1) + assert_equal(func(axis=(0, 1)), datfunc(axis=(0, 1))) + + def test_numpy_minmax(self): + # See gh-5987 + # xref gh-7460 in 'numpy' + from scipy.sparse import _data + + dat = array([[0, 1, 2], + [3, -4, 5], + [-6, 7, 9]]) + datsp = self.spcreator(dat) + + # We are only testing sparse matrices who have + # implemented 'min' and 'max' because they are + # the ones with the compatibility issues with + # the 'numpy' implementation. + if isinstance(datsp, _data._minmax_mixin): + assert_array_equal(np.min(datsp), np.min(dat)) + assert_array_equal(np.max(datsp), np.max(dat)) + + def test_argmax(self): + from scipy.sparse import _data + D1 = np.array([ + [-1, 5, 2, 3], + [0, 0, -1, -2], + [-1, -2, -3, -4], + [1, 2, 3, 4], + [1, 2, 0, 0], + ]) + D2 = D1.transpose() + # Non-regression test cases for gh-16929. + D3 = np.array([[4, 3], [7, 5]]) + D4 = np.array([[4, 3], [7, 0]]) + D5 = np.array([[5, 5, 3], [4, 9, 10], [3, 4, 9]]) + + for D in [D1, D2, D3, D4, D5]: + D = self.asdense(D) + mat = self.spcreator(D) + if not isinstance(mat, _data._minmax_mixin): + continue + + assert_equal(mat.argmax(), np.argmax(D)) + assert_equal(mat.argmin(), np.argmin(D)) + + assert_equal(mat.argmax(axis=0), np.argmax(D, axis=0)) + assert_equal(mat.argmin(axis=0), np.argmin(D, axis=0)) + + assert_equal(mat.argmax(axis=1), np.argmax(D, axis=1)) + assert_equal(mat.argmin(axis=1), np.argmin(D, axis=1)) + + # full matrix with explicit=True + mat = self.spcreator(self.asdense(D5)) + assert_equal(mat.argmax(explicit=True), 5) + assert_equal((-mat).argmax(explicit=True), 2) + assert_equal(mat.argmin(explicit=True), 2) + assert_equal((-mat).argmin(explicit=True), 5) + + # zero-size matrices + D6 = self.spcreator(np.empty((0, 5))) + D7 = self.spcreator(np.empty((5, 0))) + explicits = [True, False] + + for mat, axis, ex in itertools.product([D6, D7], [None, 0, 1], explicits): + if axis is None or mat.shape[axis] == 0: + with pytest.raises(ValueError, match="Cannot apply"): + mat.argmax(axis=axis, explicit=ex) + with pytest.raises(ValueError, match="Cannot apply"): + mat.argmin(axis=axis, explicit=ex) + else: + if self.is_array_test: + expected = np.zeros(0) + else: + expected = np.zeros((0, 1) if axis == 1 else (1, 0)) + assert_equal(mat.argmin(axis=axis, explicit=ex), expected) + assert_equal(mat.argmax(axis=axis, explicit=ex), expected) + + mat = self.spcreator(D1) + assert_equal(mat.argmax(axis=0, explicit=True), self.asdense([3, 0, 3, 3])) + assert_equal(mat.argmin(axis=0, explicit=True), self.asdense([0, 2, 2, 2])) + + expected_max = np.array([1, 2, 0, 3, 1]) + expected_min = np.array([0, 3, 3, 0, 0]) + if mat.nnz != 16: + # Noncanonical case + expected_min[-1] = 2 + if not self.is_array_test: + expected_max = expected_max.reshape((5, 1)) + expected_min = expected_min.reshape((5, 1)) + + assert_equal(mat.argmax(axis=1, explicit=True), expected_max) + assert_equal(asarray(mat.argmin(axis=1, explicit=True)), expected_min) + + # all zeros + D = np.zeros((2, 2)) + mat = self.spcreator(D) + if mat.nnz != 0: + # Noncanonical case + assert_equal(mat.argmin(axis=None, explicit=True), 0) + assert_equal(mat.argmax(axis=None, explicit=True), 0) + else: + # Canonical case + with pytest.raises(ValueError, match="Cannot apply"): + mat.argmin(axis=None, explicit=True) + with pytest.raises(ValueError, match="Cannot apply"): + mat.argmax(axis=None, explicit=True) + + +class _TestGetNnzAxis: + def test_getnnz_axis(self): + dat = array([[0, 2], + [3, 5], + [-6, 9]]) + bool_dat = dat.astype(bool) + datsp = self.spcreator(dat) + + accepted_return_dtypes = (np.int32, np.int64) + + getnnz = datsp.count_nonzero if self.is_array_test else datsp.getnnz + assert_array_equal(bool_dat.sum(axis=None), getnnz(axis=None)) + assert_array_equal(bool_dat.sum(), getnnz()) + assert_array_equal(bool_dat.sum(axis=0), getnnz(axis=0)) + assert_in(getnnz(axis=0).dtype, accepted_return_dtypes) + assert_array_equal(bool_dat.sum(axis=1), getnnz(axis=1)) + assert_in(getnnz(axis=1).dtype, accepted_return_dtypes) + assert_array_equal(bool_dat.sum(axis=-2), getnnz(axis=-2)) + assert_in(getnnz(axis=-2).dtype, accepted_return_dtypes) + assert_array_equal(bool_dat.sum(axis=-1), getnnz(axis=-1)) + assert_in(getnnz(axis=-1).dtype, accepted_return_dtypes) + + assert_raises(ValueError, getnnz, axis=2) + + +#------------------------------------------------------------------------------ +# Tailored base class for generic tests +#------------------------------------------------------------------------------ + +def _possibly_unimplemented(cls, require=True): + """ + Construct a class that either runs tests as usual (require=True), + or each method skips if it encounters a common error. + """ + if require: + return cls + else: + def wrap(fc): + @functools.wraps(fc) + def wrapper(*a, **kw): + try: + return fc(*a, **kw) + except (NotImplementedError, TypeError, ValueError, + IndexError, AttributeError): + raise pytest.skip("feature not implemented") + + return wrapper + + new_dict = dict(cls.__dict__) + for name, func in cls.__dict__.items(): + if name.startswith('test_'): + new_dict[name] = wrap(func) + return type(cls.__name__ + "NotImplemented", + cls.__bases__, + new_dict) + + +def sparse_test_class(getset=True, slicing=True, slicing_assign=True, + fancy_indexing=True, fancy_assign=True, + fancy_multidim_indexing=True, fancy_multidim_assign=True, + minmax=True, nnz_axis=True): + """ + Construct a base class, optionally converting some of the tests in + the suite to check that the feature is not implemented. + """ + bases = (_TestCommon, + _possibly_unimplemented(_TestGetSet, getset), + _TestSolve, + _TestInplaceArithmetic, + _TestArithmetic, + _possibly_unimplemented(_TestSlicing, slicing), + _possibly_unimplemented(_TestSlicingAssign, slicing_assign), + _possibly_unimplemented(_TestFancyIndexing, fancy_indexing), + _possibly_unimplemented(_TestFancyIndexingAssign, + fancy_assign), + _possibly_unimplemented(_TestFancyMultidim, + fancy_indexing and fancy_multidim_indexing), + _possibly_unimplemented(_TestFancyMultidimAssign, + fancy_multidim_assign and fancy_assign), + _possibly_unimplemented(_TestMinMax, minmax), + _possibly_unimplemented(_TestGetNnzAxis, nnz_axis)) + + # check that test names do not clash + names = {} + for cls in bases: + for name in cls.__dict__: + if not name.startswith('test_'): + continue + old_cls = names.get(name) + if old_cls is not None: + raise ValueError(f"Test class {cls.__name__} overloads test " + f"{name} defined in {old_cls.__name__}") + names[name] = cls + + return type("TestBase", bases, {}) + + +#------------------------------------------------------------------------------ +# Matrix class based tests +#------------------------------------------------------------------------------ + +class _CompressedMixin: + def _test_setdiag_sorted(self, D): + A = self.spcreator(D) + # Force sorted indices + A.has_sorted_indices = False + A.sort_indices() + assert A.has_sorted_indices + # Set the diagonal (only 1 new entry / 1002, so _insert_many is used) + with check_remains_sorted(A): + A.setdiag(5) + assert np.all(A.diagonal() == 5) + + def test_setdiag_noconvert(self): + # Test small ratio of new elements + # see gh-21791 setting mixture of existing and not when new_values < 0.001*nnz + # see gh-23644 + # Create off-main-diagonal elements so that we have multiple elements + # per column to see if the indices are sorted or not + N = 1002 + vals = np.arange(1, N + 1) + diags = np.c_[[-1, 2, 1]] * vals # rows are diagonal entries + # Remove a small number of diagonal elements so we have a small ratio + # of new ones to force _cs_matrix._setdiag to remain in CSC/CSR format + N_new = 3 + diags[1, -N_new:] = 0.0 + offsets = [-1, 0, 1] + D = self.dia_container((diags, offsets), shape=(N, N)) + return self._test_setdiag_sorted(D) + + def test_setdiag_cooconvert(self): + # Test large ratio of new elements + # see gh-23644 + # Create off-main-diagonal elements so that we have multiple elements + # per column to see if the indices are sorted or not + N = 1002 + vals = np.arange(1, N + 1) # only a few non-zeros + diags = np.c_[[-1, 2, 1]] * vals + # Remove many entries so we have a large ratio of new entries + diags[1, 5:] = 0.0 + offsets = [-1, 0, 1] + D = self.dia_container((diags, offsets), shape=(N, N)) + return self._test_setdiag_sorted(D) + + +class TestCSR(_CompressedMixin, sparse_test_class()): + @classmethod + def spcreator(cls, *args, **kwargs): + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + return csr_array(*args, **kwargs) + math_dtypes = [np.bool_, np.int_, np.float64, np.complex128] + + def test_constructor1(self): + b = array([[0, 4, 0], + [3, 0, 0], + [0, 2, 0]], 'd') + bsp = self.csr_container(b) + assert_array_almost_equal(bsp.data,[4,3,2]) + assert_array_equal(bsp.indices,[1,0,1]) + assert_array_equal(bsp.indptr,[0,1,2,3]) + assert_equal(bsp.nnz,3) + assert_equal(bsp.format,'csr') + assert_array_equal(bsp.toarray(), b) + + def test_constructor2(self): + b = zeros((6,6),'d') + b[3,4] = 5 + bsp = self.csr_container(b) + assert_array_almost_equal(bsp.data,[5]) + assert_array_equal(bsp.indices,[4]) + assert_array_equal(bsp.indptr,[0,0,0,0,1,1,1]) + assert_array_almost_equal(bsp.toarray(), b) + + def test_constructor3(self): + b = array([[1, 0], + [0, 2], + [3, 0]], 'd') + bsp = self.csr_container(b) + assert_array_almost_equal(bsp.data,[1,2,3]) + assert_array_equal(bsp.indices,[0,1,0]) + assert_array_equal(bsp.indptr,[0,1,2,3]) + assert_array_almost_equal(bsp.toarray(), b) + + def test_constructor4(self): + # using (data, ij) format + row = array([2, 3, 1, 3, 0, 1, 3, 0, 2, 1, 2]) + col = array([0, 1, 0, 0, 1, 1, 2, 2, 2, 2, 1]) + data = array([6., 10., 3., 9., 1., 4., + 11., 2., 8., 5., 7.]) + + ij = vstack((row,col)) + csr = self.csr_container((data,ij),(4,3)) + assert_array_equal(arange(12).reshape(4, 3), csr.toarray()) + + # using Python lists and a specified dtype + csr = self.csr_container(([2**63 + 1, 1], ([0, 1], [0, 1])), dtype=np.uint64) + dense = array([[2**63 + 1, 0], [0, 1]], dtype=np.uint64) + assert_array_equal(dense, csr.toarray()) + + # with duplicates (should sum the duplicates) + csr = self.csr_container(([1,1,1,1], ([0,2,2,0], [0,1,1,0]))) + assert csr.nnz == 2 + + def test_constructor5(self): + # infer dimensions from arrays + indptr = array([0,1,3,3]) + indices = array([0,5,1,2]) + data = array([1,2,3,4]) + csr = self.csr_container((data, indices, indptr)) + assert_array_equal(csr.shape,(3,6)) + + def test_constructor6(self): + # infer dimensions and dtype from lists + indptr = [0, 1, 3, 3] + indices = [0, 5, 1, 2] + data = [1, 2, 3, 4] + csr = self.csr_container((data, indices, indptr)) + assert_array_equal(csr.shape, (3,6)) + assert_(np.issubdtype(csr.dtype, np.signedinteger)) + + def test_constructor_smallcol(self): + # int64 indices not required + data = arange(6) + 1 + col = array([1, 2, 1, 0, 0, 2], dtype=np.int64) + ptr = array([0, 2, 4, 6], dtype=np.int64) + + a = self.csr_container((data, col, ptr), shape=(3, 3)) + + b = array([[0, 1, 2], + [4, 3, 0], + [5, 0, 6]], 'd') + + # sparray is less aggressive in downcasting indices to int32 than spmatrix + expected_dtype = np.dtype(np.int64 if self.is_array_test else np.int32) + assert_equal(a.indptr.dtype, expected_dtype) + assert_equal(a.indices.dtype, expected_dtype) + assert_array_equal(a.toarray(), b) + + def test_constructor_largecol(self): + # int64 indices required + data = arange(6) + 1 + large = np.iinfo(np.int32).max + 100 + col = array([0, 1, 2, large, large+1, large+2], dtype=np.int64) + ptr = array([0, 2, 4, 6], dtype=np.int64) + + a = self.csr_container((data, col, ptr)) + + assert_equal(a.indptr.dtype, np.dtype(np.int64)) + assert_equal(a.indices.dtype, np.dtype(np.int64)) + assert_array_equal(a.shape, (3, max(col)+1)) + + def test_sort_indices(self): + data = arange(5) + indices = array([7, 2, 1, 5, 4]) + indptr = array([0, 3, 5]) + asp = self.csr_container((data, indices, indptr), shape=(2,10)) + bsp = asp.copy() + asp.sort_indices() + assert_array_equal(asp.indices,[1, 2, 7, 4, 5]) + assert_array_equal(asp.toarray(), bsp.toarray()) + + def test_eliminate_zeros(self): + data = array([1, 0, 0, 0, 2, 0, 3, 0]) + indices = array([1, 2, 3, 4, 5, 6, 7, 8]) + indptr = array([0, 3, 8]) + asp = self.csr_container((data, indices, indptr), shape=(2,10)) + bsp = asp.copy() + asp.eliminate_zeros() + assert_array_equal(asp.nnz, 3) + assert_array_equal(asp.data,[1, 2, 3]) + assert_array_equal(asp.toarray(), bsp.toarray()) + + def test_ufuncs(self): + X = self.csr_container(np.arange(20).reshape(4, 5) / 20.) + for f in ["sin", "tan", "arcsin", "arctan", "sinh", "tanh", + "arcsinh", "arctanh", "rint", "sign", "expm1", "log1p", + "deg2rad", "rad2deg", "floor", "ceil", "trunc", "sqrt"]: + assert_equal(hasattr(self.datsp, f), True) + X2 = getattr(X, f)() + assert_equal(X.shape, X2.shape) + assert_array_equal(X.indices, X2.indices) + assert_array_equal(X.indptr, X2.indptr) + assert_array_equal(X2.toarray(), getattr(np, f)(X.toarray())) + + def test_unsorted_arithmetic(self): + data = arange(5) + indices = array([7, 2, 1, 5, 4]) + indptr = array([0, 3, 5]) + asp = self.csr_container((data, indices, indptr), shape=(2,10)) + data = arange(6) + indices = array([8, 1, 5, 7, 2, 4]) + indptr = array([0, 2, 6]) + bsp = self.csr_container((data, indices, indptr), shape=(2,10)) + assert_equal((asp + bsp).toarray(), asp.toarray() + bsp.toarray()) + + def test_fancy_indexing_broadcast(self): + # broadcasting indexing mode is supported + I = np.array([[1], [2], [3]]) + J = np.array([3, 4, 2]) + + np.random.seed(1234) + D = self.asdense(np.random.rand(5, 7)) + S = self.spcreator(D) + + SIJ = S[I,J] + if issparse(SIJ): + SIJ = SIJ.toarray() + assert_equal(SIJ, D[I,J]) + + def test_has_sorted_indices(self): + "Ensure has_sorted_indices memoizes sorted state for sort_indices" + sorted_inds = np.array([0, 1]) + unsorted_inds = np.array([1, 0]) + data = np.array([1, 1]) + indptr = np.array([0, 2]) + M = self.csr_container((data, sorted_inds, indptr)).copy() + assert_equal(True, M.has_sorted_indices) + assert isinstance(M.has_sorted_indices, bool) + + M = self.csr_container((data, unsorted_inds, indptr)).copy() + assert_equal(False, M.has_sorted_indices) + + # set by sorting + M.sort_indices() + assert_equal(True, M.has_sorted_indices) + assert_array_equal(M.indices, sorted_inds) + + M = self.csr_container((data, unsorted_inds, indptr)).copy() + # set manually (although underlyingly unsorted) + M.has_sorted_indices = True + assert_equal(True, M.has_sorted_indices) + assert_array_equal(M.indices, unsorted_inds) + + # ensure sort bypassed when has_sorted_indices == True + M.sort_indices() + assert_array_equal(M.indices, unsorted_inds) + + def test_has_canonical_format(self): + "Ensure has_canonical_format memoizes state for sum_duplicates" + + info_no_dups = (np.array([2]), np.array([0]), np.array([0, 1])) + info_with_dups = (np.array([1, 1]), np.array([0, 0]), np.array([0, 2])) + + M = self.csr_container(info_no_dups) + assert_equal(True, M.has_canonical_format) + + M = self.csr_container(info_with_dups).copy() + assert_equal(False, M.has_canonical_format) + assert isinstance(M.has_canonical_format, bool) + + # set flag by deduplicating + M.sum_duplicates() + assert_equal(True, M.has_canonical_format) + assert_equal(1, len(M.indices)) + + # manually set flag True (although underlyingly duplicated) + M = self.csr_container(info_with_dups).copy() + M.has_canonical_format = True + assert_equal(True, M.has_canonical_format) + assert_equal(2, len(M.indices)) # unaffected content + # ensure deduplication bypassed when has_canonical_format == True + M.sum_duplicates() + assert_equal(2, len(M.indices)) # still has duplicates!!!! + # ensure deduplication reenabled when has_canonical_format == False + M.has_canonical_format = False + M.sum_duplicates() + assert_equal(1, len(M.indices)) + assert_equal(True, M.has_canonical_format) + + # manually set flag False (although underlyingly canonical) + M.has_canonical_format = False + assert_equal(False, M.has_canonical_format) + Mcheck = self.csr_container((M.data, M.indices, M.indptr)) + assert_equal(True, Mcheck.has_canonical_format) + # sum_duplicates does not complain when no work to do + M.sum_duplicates() + assert_equal(True, M.has_canonical_format) + + # check assignments maintain canonical format + M = self.csr_container((np.array([2]), np.array([2]), np.array([0, 1, 1, 1]))) + assert_equal(M.shape, (3, 3)) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + M[0, 1] = 2 + M[1, :] *= 5 + M[0, 2] = 3 + assert_equal(True, M.has_canonical_format) + Mcheck = self.csr_container((M.data, M.indices, M.indptr)) + assert_equal(True, Mcheck.has_canonical_format) + + # resetting index arrays before accessing M.has_canonical_format is OK + M = self.csr_container(info_no_dups) + M.data, M.indices, M.indptr = info_with_dups + assert_equal(False, M.has_canonical_format) + assert_equal(2, len(M.indices)) # dups and has_canonical_format is False + + # but reset after accessing M.has_canonical_format can break flag + M = self.csr_container(info_no_dups) + M.has_canonical_format # underlying attr is set here + M.data, M.indices, M.indptr = info_with_dups + assert_equal(True, M.has_canonical_format) + assert_equal(2, len(M.indices)) # dups but has_canonical_format is True + M.sum_duplicates() + assert_equal(2, len(M.indices)) # still has duplicates!!!! + + def test_scalar_idx_dtype(self): + # Check that index dtype takes into account all parameters + # passed to sparsetools, including the scalar ones + indptr = np.zeros(2, dtype=np.int32) + indices = np.zeros(0, dtype=np.int32) + vals = np.zeros(0) + a = self.csr_container((vals, indices, indptr), shape=(1, 2**31-1)) + b = self.csr_container((vals, indices, indptr), shape=(1, 2**31)) + ij = np.zeros((2, 0), dtype=np.int32) + c = self.csr_container((vals, ij), shape=(1, 2**31-1)) + d = self.csr_container((vals, ij), shape=(1, 2**31)) + e = self.csr_container((1, 2**31-1)) + f = self.csr_container((1, 2**31)) + assert_equal(a.indptr.dtype, np.int32) + assert_equal(b.indptr.dtype, np.int64) + assert_equal(c.indptr.dtype, np.int32) + assert_equal(d.indptr.dtype, np.int64) + assert_equal(e.indptr.dtype, np.int32) + assert_equal(f.indptr.dtype, np.int64) + + # These shouldn't fail + for x in [a, b, c, d, e, f]: + x + x + + def test_binop_explicit_zeros(self): + # Check that binary ops don't introduce spurious explicit zeros. + # See gh-9619 for context. + a = self.csr_container([[0, 1, 0]]) + b = self.csr_container([[1, 1, 0]]) + assert (a + b).nnz == 2 + assert a.multiply(b).nnz == 1 + + +TestCSR.init_class() + + +class TestCSRMatrix(_MatrixMixin, TestCSR): + @classmethod + def spcreator(cls, *args, **kwargs): + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + return csr_matrix(*args, **kwargs) + +def test_spmatrix_subscriptable(): + result = csr_matrix[np.int8] + assert isinstance(result, GenericAlias) + assert result.__origin__ is csr_matrix + assert result.__args__ == (np.int8,) + + +TestCSRMatrix.init_class() + + +class TestCSC(_CompressedMixin, sparse_test_class()): + @classmethod + def spcreator(cls, *args, **kwargs): + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + return csc_array(*args, **kwargs) + math_dtypes = [np.bool_, np.int_, np.float64, np.complex128] + + def test_constructor1(self): + b = array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 2, 0, 3]], 'd') + bsp = self.csc_container(b) + assert_array_almost_equal(bsp.data,[1,2,1,3]) + assert_array_equal(bsp.indices,[0,2,1,2]) + assert_array_equal(bsp.indptr,[0,1,2,3,4]) + assert_equal(bsp.nnz,4) + assert_equal(bsp.shape,b.shape) + assert_equal(bsp.format,'csc') + + def test_constructor2(self): + b = zeros((6,6),'d') + b[2,4] = 5 + bsp = self.csc_container(b) + assert_array_almost_equal(bsp.data,[5]) + assert_array_equal(bsp.indices,[2]) + assert_array_equal(bsp.indptr,[0,0,0,0,0,1,1]) + + def test_constructor3(self): + b = array([[1, 0], [0, 0], [0, 2]], 'd') + bsp = self.csc_container(b) + assert_array_almost_equal(bsp.data,[1,2]) + assert_array_equal(bsp.indices,[0,2]) + assert_array_equal(bsp.indptr,[0,1,2]) + + def test_constructor4(self): + # using (data, ij) format + row = array([2, 3, 1, 3, 0, 1, 3, 0, 2, 1, 2]) + col = array([0, 1, 0, 0, 1, 1, 2, 2, 2, 2, 1]) + data = array([6., 10., 3., 9., 1., 4., 11., 2., 8., 5., 7.]) + + ij = vstack((row,col)) + csc = self.csc_container((data,ij),(4,3)) + assert_array_equal(arange(12).reshape(4, 3), csc.toarray()) + + # with duplicates (should sum the duplicates) + csc = self.csc_container(([1,1,1,1], ([0,2,2,0], [0,1,1,0]))) + assert csc.nnz == 2 + + def test_constructor5(self): + # infer dimensions from arrays + indptr = array([0,1,3,3]) + indices = array([0,5,1,2]) + data = array([1,2,3,4]) + csc = self.csc_container((data, indices, indptr)) + assert_array_equal(csc.shape,(6,3)) + + def test_constructor6(self): + # infer dimensions and dtype from lists + indptr = [0, 1, 3, 3] + indices = [0, 5, 1, 2] + data = [1, 2, 3, 4] + csc = self.csc_container((data, indices, indptr)) + assert_array_equal(csc.shape,(6,3)) + assert_(np.issubdtype(csc.dtype, np.signedinteger)) + + def test_eliminate_zeros(self): + data = array([1, 0, 0, 0, 2, 0, 3, 0]) + indices = array([1, 2, 3, 4, 5, 6, 7, 8]) + indptr = array([0, 3, 8]) + asp = self.csc_container((data, indices, indptr), shape=(10,2)) + bsp = asp.copy() + asp.eliminate_zeros() + assert_array_equal(asp.nnz, 3) + assert_array_equal(asp.data,[1, 2, 3]) + assert_array_equal(asp.toarray(), bsp.toarray()) + + def test_sort_indices(self): + data = arange(5) + row = array([7, 2, 1, 5, 4]) + ptr = [0, 3, 5] + asp = self.csc_container((data, row, ptr), shape=(10,2)) + bsp = asp.copy() + asp.sort_indices() + assert_array_equal(asp.indices,[1, 2, 7, 4, 5]) + assert_array_equal(asp.toarray(), bsp.toarray()) + + def test_ufuncs(self): + X = self.csc_container(np.arange(21).reshape(7, 3) / 21.) + for f in ["sin", "tan", "arcsin", "arctan", "sinh", "tanh", + "arcsinh", "arctanh", "rint", "sign", "expm1", "log1p", + "deg2rad", "rad2deg", "floor", "ceil", "trunc", "sqrt"]: + assert_equal(hasattr(self.datsp, f), True) + X2 = getattr(X, f)() + assert_equal(X.shape, X2.shape) + assert_array_equal(X.indices, X2.indices) + assert_array_equal(X.indptr, X2.indptr) + assert_array_equal(X2.toarray(), getattr(np, f)(X.toarray())) + + def test_unsorted_arithmetic(self): + data = arange(5) + indices = array([7, 2, 1, 5, 4]) + indptr = array([0, 3, 5]) + asp = self.csc_container((data, indices, indptr), shape=(10,2)) + data = arange(6) + indices = array([8, 1, 5, 7, 2, 4]) + indptr = array([0, 2, 6]) + bsp = self.csc_container((data, indices, indptr), shape=(10,2)) + assert_equal((asp + bsp).toarray(), asp.toarray() + bsp.toarray()) + + def test_fancy_indexing_broadcast(self): + # broadcasting indexing mode is supported + I = np.array([[1], [2], [3]]) + J = np.array([3, 4, 2]) + + np.random.seed(1234) + D = self.asdense(np.random.rand(5, 7)) + S = self.spcreator(D) + + SIJ = S[I,J] + if issparse(SIJ): + SIJ = SIJ.toarray() + assert_equal(SIJ, D[I,J]) + + def test_scalar_idx_dtype(self): + # Check that index dtype takes into account all parameters + # passed to sparsetools, including the scalar ones + indptr = np.zeros(2, dtype=np.int32) + indices = np.zeros(0, dtype=np.int32) + vals = np.zeros(0) + a = self.csc_container((vals, indices, indptr), shape=(2**31-1, 1)) + b = self.csc_container((vals, indices, indptr), shape=(2**31, 1)) + ij = np.zeros((2, 0), dtype=np.int32) + c = self.csc_container((vals, ij), shape=(2**31-1, 1)) + d = self.csc_container((vals, ij), shape=(2**31, 1)) + e = self.csr_container((1, 2**31-1)) + f = self.csr_container((1, 2**31)) + assert_equal(a.indptr.dtype, np.int32) + assert_equal(b.indptr.dtype, np.int64) + assert_equal(c.indptr.dtype, np.int32) + assert_equal(d.indptr.dtype, np.int64) + assert_equal(e.indptr.dtype, np.int32) + assert_equal(f.indptr.dtype, np.int64) + + # These shouldn't fail + for x in [a, b, c, d, e, f]: + x + x + + +TestCSC.init_class() + + +class TestCSCMatrix(_MatrixMixin, TestCSC): + @classmethod + def spcreator(cls, *args, **kwargs): + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + return csc_matrix(*args, **kwargs) + + +TestCSCMatrix.init_class() + + +class TestDOK(sparse_test_class(minmax=False, nnz_axis=False)): + spcreator = dok_array + math_dtypes = [np.int_, np.float64, np.complex128] + + def test_mult(self): + A = self.dok_container((10, 12)) + A[0, 3] = 10 + A[5, 6] = 20 + D = A @ A.T + E = A @ A.T.conjugate() + assert_array_equal(D.toarray(), E.toarray()) + + def test_add_nonzero(self): + A = self.spcreator((3,2)) + A[0,1] = -10 + A[2,0] = 20 + A = A + 10 + B = array([[10, 0], [10, 10], [30, 10]]) + assert_array_equal(A.toarray(), B) + + A = A + 1j + B = B + 1j + assert_array_equal(A.toarray(), B) + + def test_dok_divide_scalar(self): + A = self.spcreator((3,2)) + A[0,1] = -10 + A[2,0] = 20 + + assert_array_equal((A/1j).toarray(), A.toarray()/1j) + assert_array_equal((A/9).toarray(), A.toarray()/9) + + def test_convert(self): + # Test provided by Andrew Straw. Fails in SciPy <= r1477. + (m, n) = (6, 7) + a = self.dok_container((m, n)) + + # set a few elements, but none in the last column + a[2,1] = 1 + a[0,2] = 2 + a[3,1] = 3 + a[1,5] = 4 + a[4,3] = 5 + a[4,2] = 6 + + # assert that the last column is all zeros + assert_array_equal(a.toarray()[:,n-1], zeros(m,)) + + # make sure it still works for CSC format + csc = a.tocsc() + assert_array_equal(csc.toarray()[:,n-1], zeros(m,)) + + # now test CSR + (m, n) = (n, m) + b = a.transpose() + assert_equal(b.shape, (m, n)) + # assert that the last row is all zeros + assert_array_equal(b.toarray()[m-1,:], zeros(n,)) + + # make sure it still works for CSR format + csr = b.tocsr() + assert_array_equal(csr.toarray()[m-1,:], zeros(n,)) + + def test_ctor(self): + # Empty ctor + assert_raises(TypeError, self.dok_container) + + # Dense ctor + b = array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 2, 0, 3]], 'd') + A = self.dok_container(b) + assert_equal(b.dtype, A.dtype) + assert_equal(A.toarray(), b) + + # Sparse ctor + c = self.csr_container(b) + assert_equal(A.toarray(), c.toarray()) + + data = [[0, 1, 2], [3, 0, 0]] + d = self.dok_container(data, dtype=np.float32) + assert_equal(d.dtype, np.float32) + da = d.toarray() + assert_equal(da.dtype, np.float32) + assert_array_equal(da, data) + + def test_ticket1160(self): + # Regression test for ticket #1160. + a = self.dok_container((3,3)) + a[0,0] = 0 + # This assert would fail, because the above assignment would + # incorrectly call __set_item__ even though the value was 0. + assert_((0,0) not in a.keys(), "Unexpected entry (0,0) in keys") + + # Slice assignments were also affected. + b = self.dok_container((3,3)) + b[:,0] = 0 + assert_(len(b.keys()) == 0, "Unexpected entries in keys") + + +class TestDOKMatrix(_MatrixMixin, TestDOK): + spcreator = dok_matrix + + +TestDOK.init_class() +TestDOKMatrix.init_class() + + +class TestLIL(sparse_test_class(minmax=False)): + spcreator = lil_array + math_dtypes = [np.int_, np.float64, np.complex128] + + def test_dot(self): + A = zeros((10, 10), np.complex128) + A[0, 3] = 10 + A[5, 6] = 20j + + B = self.lil_container((10, 10), dtype=np.complex128) + B[0, 3] = 10 + B[5, 6] = 20j + + # TODO: properly handle this assertion on ppc64le + if platform.machine() != 'ppc64le': + assert_array_equal(A @ A.T, (B @ B.T).toarray()) + + assert_array_equal(A @ A.conjugate().T, (B @ B.conjugate().T).toarray()) + + def test_scalar_mul(self): + x = self.lil_container((3, 3)) + x[0, 0] = 2 + + x = x*2 + assert_equal(x[0, 0], 4) + + x = x*0 + assert_equal(x[0, 0], 0) + + def test_truediv_scalar(self): + A = self.spcreator((3, 2)) + A[0, 1] = -10 + A[2, 0] = 20 + + assert_array_equal((A / 1j).toarray(), A.toarray() / 1j) + assert_array_equal((A / 9).toarray(), A.toarray() / 9) + + def test_inplace_ops(self): + A = self.lil_container([[0, 2, 3], [4, 0, 6]]) + B = self.lil_container([[0, 1, 0], [0, 2, 3]]) + + data = {'add': (B, A + B), + 'sub': (B, A - B), + 'mul': (3, A * 3)} + + for op, (other, expected) in data.items(): + result = A.copy() + getattr(result, f'__i{op}__')(other) + + assert_array_equal(result.toarray(), expected.toarray()) + + # Ticket 1604. + A = self.lil_container((1, 3), dtype=np.dtype('float64')) + B = self.asdense([0.1, 0.1, 0.1]) + A[0, :] += B + assert_array_equal(A[0, :].toarray(), B) + + def test_lil_iteration(self): + row_data = [[1, 2, 3], [4, 5, 6]] + B = self.lil_container(array(row_data)) + for r, row in enumerate(B): + assert_array_equal(row.toarray(), array(row_data[r], ndmin=row.ndim)) + + def test_lil_from_csr(self): + # Tests whether a LIL can be constructed from a CSR. + B = self.lil_container((10, 10)) + B[0, 3] = 10 + B[5, 6] = 20 + B[8, 3] = 30 + B[3, 8] = 40 + B[8, 9] = 50 + C = B.tocsr() + D = self.lil_container(C) + assert_array_equal(C.toarray(), D.toarray()) + + def test_fancy_indexing_lil(self): + M = self.asdense(arange(25).reshape(5, 5)) + A = self.lil_container(M) + + assert_equal(A[array([1, 2, 3]), 2:3].toarray(), + M[array([1, 2, 3]), 2:3]) + + def test_point_wise_multiply(self): + l = self.lil_container((4, 3)) + l[0, 0] = 1 + l[1, 1] = 2 + l[2, 2] = 3 + l[3, 1] = 4 + + m = self.lil_container((4, 3)) + m[0, 0] = 1 + m[0, 1] = 2 + m[2, 2] = 3 + m[3, 1] = 4 + m[3, 2] = 4 + + assert_array_equal(l.multiply(m).toarray(), + m.multiply(l).toarray()) + + assert_array_equal(l.multiply(m).toarray(), + [[1, 0, 0], + [0, 0, 0], + [0, 0, 9], + [0, 16, 0]]) + + def test_lil_multiply_removal(self): + # Ticket #1427. + a = self.lil_container(np.ones((3, 3))) + a *= 2. + a[0, :] = 0 + + +class TestLILMatrix(_MatrixMixin, TestLIL): + spcreator = lil_matrix + + +TestLIL.init_class() +TestLILMatrix.init_class() + + +class BaseTestCOO: + math_dtypes = [np.int_, np.float64, np.complex128] + + def test_constructor1(self): + # unsorted triplet format + row = array([2, 3, 1, 3, 0, 1, 3, 0, 2, 1, 2]) + col = array([0, 1, 0, 0, 1, 1, 2, 2, 2, 2, 1]) + data = array([6., 10., 3., 9., 1., 4., 11., 2., 8., 5., 7.]) + + coo = self.coo_container((data,(row,col)),(4,3)) + assert_array_equal(arange(12).reshape(4, 3), coo.toarray()) + + # using Python lists and a specified dtype + coo = self.coo_container(([2**63 + 1, 1], ([0, 1], [0, 1])), dtype=np.uint64) + dense = array([[2**63 + 1, 0], [0, 1]], dtype=np.uint64) + assert_array_equal(dense, coo.toarray()) + + def test_constructor2(self): + # unsorted triplet format with duplicates (which are summed) + row = array([0,1,2,2,2,2,0,0,2,2]) + col = array([0,2,0,2,1,1,1,0,0,2]) + data = array([2,9,-4,5,7,0,-1,2,1,-5]) + coo = self.coo_container((data,(row,col)),(3,3)) + + mat = array([[4, -1, 0], [0, 0, 9], [-3, 7, 0]]) + + assert_array_equal(mat, coo.toarray()) + + def test_constructor3(self): + # empty matrix + coo = self.coo_container((4,3)) + + assert_array_equal(coo.shape,(4,3)) + assert_array_equal(coo.row,[]) + assert_array_equal(coo.col,[]) + assert_array_equal(coo.data,[]) + assert_array_equal(coo.toarray(), zeros((4, 3))) + + def test_constructor4(self): + # from dense matrix + mat = array([[0,1,0,0], + [7,0,3,0], + [0,4,0,0]]) + coo = self.coo_container(mat) + assert_array_equal(coo.toarray(), mat) + + # upgrade rank 1 arrays to row matrix + mat = array([0,1,0,0]) + coo = self.coo_container(mat) + expected = mat if self.is_array_test else mat.reshape(1, -1) + assert_array_equal(coo.toarray(), expected) + + # error if second arg interpreted as shape (gh-9919) + with pytest.raises(TypeError, match=r'object cannot be interpreted'): + self.coo_container([0, 11, 22, 33], ([0, 1, 2, 3], [0, 0, 0, 0])) + + # error if explicit shape arg doesn't match the dense matrix + with pytest.raises(ValueError, match=r'inconsistent shapes'): + self.coo_container([0, 11, 22, 33], shape=(4, 4)) + + def test_constructor_data_ij_dtypeNone(self): + data = [1] + coo = self.coo_container((data, ([0], [0])), dtype=None) + assert coo.dtype == np.array(data).dtype + + @pytest.mark.xfail(run=False, reason='COO does not have a __getitem__') + def test_iterator(self): + pass + + def test_todia_all_zeros(self): + zeros = [[0, 0]] + dia = self.coo_container(zeros).todia() + assert_array_equal(dia.toarray(), zeros) + + def test_sum_duplicates(self): + coo = self.coo_container((4,3)) + coo.sum_duplicates() + coo = self.coo_container(([1,2], ([1,0], [1,0]))) + coo.sum_duplicates() + assert_array_equal(coo.toarray(), [[2,0],[0,1]]) + coo = self.coo_container(([1,2], ([1,1], [1,1]))) + coo.sum_duplicates() + assert_array_equal(coo.toarray(), [[0,0],[0,3]]) + assert_array_equal(coo.row, [1]) + assert_array_equal(coo.col, [1]) + assert_array_equal(coo.data, [3]) + + def test_todok_duplicates(self): + coo = self.coo_container(([1,1,1,1], ([0,2,2,0], [0,1,1,0]))) + dok = coo.todok() + assert_array_equal(dok.toarray(), coo.toarray()) + + def test_tocompressed_duplicates(self): + coo = self.coo_container(([1,1,1,1], ([0,2,2,0], [0,1,1,0]))) + csr = coo.tocsr() + assert_equal(csr.nnz + 2, coo.nnz) + csc = coo.tocsc() + assert_equal(csc.nnz + 2, coo.nnz) + + def test_has_canonical_format(self): + "Ensure has_canonical_format memoizes state for sum_duplicates" + + A = self.coo_container((2, 3)) + assert_equal(A.has_canonical_format, True) + + A_array = np.array([[0, 2, 0]]) + A_coords_form = (np.array([2]), (np.array([0]), np.array([1]))) + A_coords_dups = (np.array([1, 1]), (np.array([0, 0]), np.array([1, 1]))) + + A = self.coo_container(A_array) + assert A.has_canonical_format is True + A = self.coo_container(A_coords_form) + assert A.has_canonical_format is False + A.sum_duplicates() + assert A.has_canonical_format is True + + A = self.coo_container(A, copy=True) + assert A.has_canonical_format is True + A = self.coo_container(A, copy=False) + assert A.has_canonical_format is False + A.sum_duplicates() + assert A.has_canonical_format is True + + A = self.coo_container(A_coords_dups) + assert A.has_canonical_format is False + assert_equal(A.nnz, 2) # duplicates + A.sum_duplicates() + assert A.has_canonical_format is True + assert_equal(A.nnz, 1) + + # manually set + A.has_canonical_format = False + assert_equal(A.has_canonical_format, False) + assert_equal(A.nnz, 1) # incorrectly False + A.sum_duplicates() # check flag updated + assert_equal(A.has_canonical_format, True) + + A = self.coo_container(A_coords_dups) + A.has_canonical_format = True + assert_equal(A.has_canonical_format, True) + assert_equal(A.nnz, 2) # incorrectly True + A.sum_duplicates() # check dups not removed due to flag + assert_equal(A.nnz, 2) # still has duplicates!!!! + + def test_eliminate_zeros(self): + data = array([1, 0, 0, 0, 2, 0, 3, 0]) + row = array([0, 0, 0, 1, 1, 1, 1, 1]) + col = array([1, 2, 3, 4, 5, 6, 7, 8]) + asp = self.coo_container((data, (row, col)), shape=(2,10)) + bsp = asp.copy() + asp.eliminate_zeros() + assert_((asp.data != 0).all()) + assert_array_equal(asp.toarray(), bsp.toarray()) + + def test_reshape_copy(self): + arr = [[0, 10, 0, 0], [0, 0, 0, 0], [0, 20, 30, 40]] + new_shape = (2, 6) + x = self.coo_container(arr) + + y = x.reshape(new_shape) + assert_(y.data is x.data) + + y = x.reshape(new_shape, copy=False) + assert_(y.data is x.data) + + y = x.reshape(new_shape, copy=True) + assert_(not np.may_share_memory(y.data, x.data)) + + def test_large_dimensions_reshape(self): + # Test that reshape is immune to integer overflow when number of elements + # exceeds 2^31-1 + mat1 = self.coo_container(([1], ([3000000], [1000])), (3000001, 1001)) + mat2 = self.coo_container(([1], ([1000], [3000000])), (1001, 3000001)) + + # assert_array_equal is slow for big matrices because it expects dense + # Using __ne__ and nnz instead + assert_((mat1.reshape((1001, 3000001), order='C') != mat2).nnz == 0) + assert_((mat2.reshape((3000001, 1001), order='F') != mat1).nnz == 0) + +class TestCOO(BaseTestCOO, + sparse_test_class(getset=True, + slicing=True, slicing_assign=True, + fancy_indexing=True, fancy_assign=True)): + spcreator = coo_array + +class TestCOOMatrix(_MatrixMixin, + BaseTestCOO, + sparse_test_class(getset=False, + slicing=False, slicing_assign=False, + fancy_indexing=False, fancy_assign=False)): + spcreator = coo_matrix + + +TestCOO.init_class() +TestCOOMatrix.init_class() + + +def test_sparray_subscriptable(): + result = coo_array[np.int8, tuple[int]] + assert isinstance(result, GenericAlias) + assert result.__origin__ is coo_array + assert result.__args__ == (np.int8, tuple[int]) + + result = coo_array[np.int8] + assert isinstance(result, GenericAlias) + assert result.__origin__ is coo_array + assert result.__args__ == (np.int8,) + + +class TestDIA(sparse_test_class(getset=False, slicing=False, slicing_assign=False, + fancy_indexing=False, fancy_assign=False, + minmax=False, nnz_axis=False)): + spcreator = dia_array + math_dtypes = [np.int_, np.float64, np.complex128] + + def test_constructor1(self): + D = array([[1, 0, 3, 0], + [1, 2, 0, 4], + [0, 2, 3, 0], + [0, 0, 3, 4]]) + data = np.array([[1,2,3,4]]).repeat(3,axis=0) + offsets = np.array([0,-1,2]) + assert_equal(self.dia_container((data, offsets), shape=(4, 4)).toarray(), D) + + @pytest.mark.xfail(run=False, reason='DIA does not have a __getitem__') + def test_iterator(self): + pass + + @with_64bit_maxval_limit(3) + def test_setdiag_dtype(self): + m = self.dia_container(np.eye(3)) + assert_equal(m.offsets.dtype, np.int32) + m.setdiag((3,), k=2) + assert_equal(m.offsets.dtype, np.int32) + + m = self.dia_container(np.eye(4)) + assert_equal(m.offsets.dtype, np.int64) + m.setdiag((3,), k=3) + assert_equal(m.offsets.dtype, np.int64) + + def ill_cases(self): + # Ill-formed inputs and reference 2 x 2 outputs for testing _getnnz() + # and tocsr(): list of tuples + # (data, offsets, nnz, dense array, case description) + + d1 = [[1]] # diagonal shorter than width + d3 = [[1, 2, 3]] # diagonal longer than width + + return [(d1, [-1], 1, [[0, 0], [1, 0]], + 'shorter diagonal within'), + (d1, [1], 0, [[0, 0], [0, 0]], + 'shorter diagonal above (but within if full)'), + (d1, [3], 0, [[0, 0], [0, 0]], + 'shorter diagonal, all elements above'), + (d1, [-3], 0, [[0, 0], [0, 0]], + 'shorter diagonal, all elements below'), + (d3, [-1], 1, [[0, 0], [1, 0]], + 'longer diagonal within (only head)'), + (d3, [1], 1, [[0, 2], [0, 0]], + 'longer diagonal within (only tail)'), + (d3, [3], 0, [[0, 0], [0, 0]], + 'longer diagonal, all elements above'), + (d3, [-3], 0, [[0, 0], [0, 0]], + 'longer diagonal, all elements below'), + (None, None, 0, [[0, 0], [0, 0]], + 'empty input'), + ([[0, 0]], [0], 2, [[0, 0], [0, 0]], + 'explicit zeros'), + (np.arange(1, 1 + 7).reshape((7, 1)), + [0, 1, 2, 3, -1, -2, -3], + 2, [[1, 0], [5, 0]], + 'overfilled shorter-diagonal, out of order'), + (np.arange(1, 1 + 7 * 3).reshape((7, 3)), + [0, 1, 2, 3, -1, -2, -3], + 4, [[1, 5], [13, 2]], + 'overfilled longer-diagonal, out of order')] + + def test_getnnz(self): + for data, ofsets, nnz, ref, case in self.ill_cases(): + for shape in [(2, 2), (0, 2), (2, 0)]: + if data is None: + A = self.dia_container(shape) + else: + A = self.dia_container((data, ofsets), shape=shape) + if 0 in shape: + nnz = 0 + assert A._getnnz() == nnz, 'case: ' + case + + @pytest.mark.skip(reason='DIA stores extra zeros') + def test_getnnz_axis(self): + pass + + def test_tocsr(self): + # test bound checks (other pathological cases are tested by + # TestConstructUtils::test_spdiags, and normal operation is ensured by + # many other tests here using .toarray()) + for data, ofsets, _, r, case in self.ill_cases(): + for shape in [(2, 2), (0, 2), (2, 0)]: + if data is None: + A = self.dia_container(shape) + else: + A = self.dia_container((data, ofsets), shape=shape) + B = A.tocsr() + ref = np.array(r)[:shape[0], :shape[1]] + nnz = np.count_nonzero(ref) + assert B.nnz == nnz + assert_array_equal(B.toarray(), ref, err_msg='case: ' + case) + + def test_convert_gh14555(self): + # regression test for gh-14555 + m = self.dia_container(([[1, 1, 0]], [-1]), shape=(4, 2)) + expected = m.toarray() + assert_array_equal(m.tocsc().toarray(), expected) + assert_array_equal(m.tocsr().toarray(), expected) + + def test_tocoo_gh10050(self): + # regression test for gh-10050 + m = self.dia_container([[1, 2], [3, 4]]).tocoo() + flat_inds = np.ravel_multi_index((m.row, m.col), m.shape) + inds_are_sorted = np.all(np.diff(flat_inds) > 0) + assert m.has_canonical_format == inds_are_sorted + + def test_tocoo_tocsr_tocsc_gh19245(self): + # test index_dtype with tocoo, tocsr, tocsc + data = np.array([[1, 2, 3, 4]]).repeat(3, axis=0) + offsets = np.array([0, -1, 2], dtype=np.int32) + dia = sparse.dia_array((data, offsets), shape=(4, 4)) + + coo = dia.tocoo() + assert coo.col.dtype == np.int32 + csr = dia.tocsr() + assert csr.indices.dtype == np.int32 + csc = dia.tocsc() + assert csc.indices.dtype == np.int32 + + def test_add_sparse(self): + # test format and cases not covered by common add tests + A = diag([1, 2]) + B = A + diag([3], 1) + Asp = self.dia_container(A) + Bsp = self.dia_container(B) + + Csp = Asp + Bsp + assert isinstance(Csp, self.dia_container) + assert_array_equal(Csp.toarray(), A + B) + + Csp = Bsp + Asp + assert isinstance(Csp, self.dia_container) + assert_array_equal(Csp.toarray(), B + A) + + def test_sub_sparse(self): + # test format and cases not covered by common sub tests + A = diag([1, 2]) + B = A + diag([3], 1) + Asp = self.dia_container(A) + Bsp = self.dia_container(B) + + Csp = Asp - Bsp + assert isinstance(Csp, self.dia_container) + assert_array_equal(Csp.toarray(), A - B) + + Csp = Bsp - Asp + assert isinstance(Csp, self.dia_container) + assert_array_equal(Csp.toarray(), B - A) + + Bsp = Bsp.asformat('csr') + assert_array_equal((Asp - Bsp).toarray(), A - B) + assert_array_equal((Bsp - Asp).toarray(), B - A) + + def test_mul_scalar(self): + # repro for gh-20434 + m = self.dia_container([[1, 2], [0, 4]]) + res = m * 3 + assert isinstance(res, m.__class__) + assert_array_equal(res.toarray(), [[3, 6], [0, 12]]) + + res2 = m.multiply(3) + assert isinstance(res2, m.__class__) + assert_array_equal(res2.toarray(), [[3, 6], [0, 12]]) + + def test_matmul_dia(self): + # test DIA structure of DIA @ DIA: + + # that all and only needed elements are used and produced + A = array([[1, 2, 3], + [4, 5, 6]]) + B = array([[11, 12], + [13, 14], + [15, 16]]) + Asp = self.dia_container(A) + Bsp = self.dia_container(B) + Asp.data[Asp.data == 0] = -1 # poison outside elements + Bsp.data[Bsp.data == 0] = -1 + assert_array_equal(Asp.toarray(), A) + assert_array_equal(Bsp.toarray(), B) + + C = A @ B + Csp = Asp @ Bsp + assert isinstance(Csp, self.dia_container) + assert_array_equal(Csp.toarray(), C) + assert_array_equal(Csp.offsets, [-1, 0, 1]) + assert_array_equal(Csp.data, self.dia_container(C).data) + + C = B @ A + Csp = Bsp @ Asp + assert isinstance(Csp, self.dia_container) + assert_array_equal(Csp.toarray(), C) + assert_array_equal(Csp.offsets, [-2, -1, 0, 1, 2]) + assert_array_equal(Csp.data, self.dia_container(C).data) + + # short data and that order of input offsets doesn't matter + Asp = self.dia_container(([[0., 1., 2.], [3., 4., 5.]], [1, -2]), (5, 5)) + Bsp = self.dia_container(([[6., 7., 8.], [0., 0., 9.]], [-1, 2]), (5, 5)) + + Csp = Asp @ Bsp + assert_array_equal(Csp.offsets, array([-3, 0])) + assert_array_equal(Csp.data, [[24., 35., 0.], + [6., 14., 27.]]) + + Csp = Bsp @ Asp + assert_array_equal(Csp.offsets, array([-3, 0])) + assert_array_equal(Csp.data, [[24., 0., 0.], + [27., 6., 14.]]) + + +class TestDIAMatrix(_MatrixMixin, TestDIA): + spcreator = dia_matrix + + +TestDIA.init_class() +TestDIAMatrix.init_class() + + +class TestBSR(sparse_test_class(getset=False, + slicing=False, slicing_assign=False, + fancy_indexing=False, fancy_assign=False, + nnz_axis=False)): + spcreator = bsr_array + math_dtypes = [np.int_, np.float64, np.complex128] + + def test_constructor1(self): + # check native BSR format constructor + indptr = array([0,2,2,4]) + indices = array([0,2,2,3]) + data = zeros((4,2,3)) + + data[0] = array([[0, 1, 2], + [3, 0, 5]]) + data[1] = array([[0, 2, 4], + [6, 0, 10]]) + data[2] = array([[0, 4, 8], + [12, 0, 20]]) + data[3] = array([[0, 5, 10], + [15, 0, 25]]) + + A = kron([[1,0,2,0],[0,0,0,0],[0,0,4,5]], [[0,1,2],[3,0,5]]) + Asp = self.bsr_container((data,indices,indptr),shape=(6,12)) + assert_equal(Asp.toarray(), A) + + # infer shape from arrays + Asp = self.bsr_container((data,indices,indptr)) + assert_equal(Asp.toarray(), A) + + def test_constructor2(self): + # construct from dense + + # test zero mats + for shape in [(1,1), (5,1), (1,10), (10,4), (3,7), (2,1)]: + A = zeros(shape) + assert_equal(self.bsr_container(A).toarray(), A) + A = zeros((4,6)) + assert_equal(self.bsr_container(A, blocksize=(2, 2)).toarray(), A) + assert_equal(self.bsr_container(A, blocksize=(2, 3)).toarray(), A) + + A = kron([[1,0,2,0],[0,0,0,0],[0,0,4,5]], [[0,1,2],[3,0,5]]) + assert_equal(self.bsr_container(A).toarray(), A) + assert_equal(self.bsr_container(A, shape=(6, 12)).toarray(), A) + assert_equal(self.bsr_container(A, blocksize=(1, 1)).toarray(), A) + assert_equal(self.bsr_container(A, blocksize=(2, 3)).toarray(), A) + assert_equal(self.bsr_container(A, blocksize=(2, 6)).toarray(), A) + assert_equal(self.bsr_container(A, blocksize=(2, 12)).toarray(), A) + assert_equal(self.bsr_container(A, blocksize=(3, 12)).toarray(), A) + assert_equal(self.bsr_container(A, blocksize=(6, 12)).toarray(), A) + + A = kron([[1,0,2,0],[0,1,0,0],[0,0,0,0]], [[0,1,2],[3,0,5]]) + assert_equal(self.bsr_container(A, blocksize=(2, 3)).toarray(), A) + + def test_constructor3(self): + # construct from coo-like (data,(row,col)) format + arg = ([1,2,3], ([0,1,1], [0,0,1])) + A = array([[1,0],[2,3]]) + assert_equal(self.bsr_container(arg, blocksize=(2, 2)).toarray(), A) + + def test_constructor4(self): + # regression test for gh-6292: self.bsr_matrix((data, indices, indptr)) was + # trying to compare an int to a None + n = 8 + data = np.ones((n, n, 1), dtype=np.int8) + indptr = np.array([0, n], dtype=np.int32) + indices = np.arange(n, dtype=np.int32) + self.bsr_container((data, indices, indptr), blocksize=(n, 1), copy=False) + + def test_constructor5(self): + # check for validations introduced in gh-13400 + n = 8 + data_1dim = np.ones(n) + data = np.ones((n, n, n)) + indptr = np.array([0, n]) + indices = np.arange(n) + + with assert_raises(ValueError): + # data ndim check + self.bsr_container((data_1dim, indices, indptr)) + + with assert_raises(ValueError): + # invalid blocksize + self.bsr_container((data, indices, indptr), blocksize=(1, 1, 1)) + + with assert_raises(ValueError): + # mismatching blocksize + self.bsr_container((data, indices, indptr), blocksize=(1, 1)) + + def test_default_dtype(self): + # As a numpy array, `values` has shape (2, 2, 1). + values = [[[1], [1]], [[1], [1]]] + indptr = np.array([0, 2], dtype=np.int32) + indices = np.array([0, 1], dtype=np.int32) + b = self.bsr_container((values, indices, indptr), blocksize=(2, 1)) + assert b.dtype == np.array(values).dtype + + def test_bsr_tocsr(self): + # check native conversion from BSR to CSR + indptr = array([0, 2, 2, 4]) + indices = array([0, 2, 2, 3]) + data = zeros((4, 2, 3)) + + data[0] = array([[0, 1, 2], + [3, 0, 5]]) + data[1] = array([[0, 2, 4], + [6, 0, 10]]) + data[2] = array([[0, 4, 8], + [12, 0, 20]]) + data[3] = array([[0, 5, 10], + [15, 0, 25]]) + + A = kron([[1, 0, 2, 0], [0, 0, 0, 0], [0, 0, 4, 5]], + [[0, 1, 2], [3, 0, 5]]) + Absr = self.bsr_container((data, indices, indptr), shape=(6, 12)) + Acsr = Absr.tocsr() + Acsr_via_coo = Absr.tocoo().tocsr() + assert_equal(Acsr.toarray(), A) + assert_equal(Acsr.toarray(), Acsr_via_coo.toarray()) + + def test_eliminate_zeros(self): + data = kron([1, 0, 0, 0, 2, 0, 3, 0], [[1,1],[1,1]]).T + data = data.reshape(-1,2,2) + indices = array([1, 2, 3, 4, 5, 6, 7, 8]) + indptr = array([0, 3, 8]) + asp = self.bsr_container((data, indices, indptr), shape=(4,20)) + bsp = asp.copy() + asp.eliminate_zeros() + assert_array_equal(asp.nnz, 3*4) + assert_array_equal(asp.toarray(), bsp.toarray()) + + # GitHub issue #9687 + def test_eliminate_zeros_all_zero(self): + np.random.seed(0) + m = self.bsr_container(np.random.random((12, 12)), blocksize=(2, 3)) + + # eliminate some blocks, but not all + m.data[m.data <= 0.9] = 0 + m.eliminate_zeros() + assert_equal(m.nnz, 66) + assert_array_equal(m.data.shape, (11, 2, 3)) + + # eliminate all remaining blocks + m.data[m.data <= 1.0] = 0 + m.eliminate_zeros() + assert_equal(m.nnz, 0) + assert_array_equal(m.data.shape, (0, 2, 3)) + assert_array_equal(m.toarray(), np.zeros((12, 12))) + + # test fast path + m.eliminate_zeros() + assert_equal(m.nnz, 0) + assert_array_equal(m.data.shape, (0, 2, 3)) + assert_array_equal(m.toarray(), np.zeros((12, 12))) + + def test_has_canonical_format(self): + "Ensure has_canonical_format memoizes state for sum_duplicates" + + A = np.array([[2, 3, 2], [0, 2, 1], [-4, 0, 2]]) + M = self.bsr_container(A) + assert_equal(True, M.has_canonical_format) + + indices = np.array([0, 0]) # contains duplicate + data = np.array([A, A*0]) + indptr = np.array([0, 2]) + + M = self.bsr_container((data, indices, indptr)).copy() + assert_equal(False, M.has_canonical_format) + assert isinstance(M.has_canonical_format, bool) + # set flag by deduplicating + M.sum_duplicates() + assert_equal(True, M.has_canonical_format) + assert_equal(1, len(M.indices)) + + # manually set flag True (although underlyingly duplicated) + M = self.bsr_container((data, indices, indptr)).copy() + M.has_canonical_format = True + assert_equal(True, M.has_canonical_format) + assert_equal(2, len(M.indices)) # unaffected content + # ensure deduplication bypassed when has_canonical_format == True + M.sum_duplicates() + assert_equal(2, len(M.indices)) # still has duplicates!!!! + # ensure deduplication reenabled when has_canonical_format == False + M.has_canonical_format = False + M.sum_duplicates() + assert_equal(1, len(M.indices)) + assert_equal(True, M.has_canonical_format) + + # manually set flag False (although underlyingly canonical) + M = self.bsr_container(A) + M.has_canonical_format = False + assert_equal(False, M.has_canonical_format) + assert_equal(1, len(M.indices)) + # sum_duplicates does not complain when no work to do + M.sum_duplicates() + assert_equal(True, M.has_canonical_format) + + # manually reset index arrays before accessing M.has_canonical_format is OK + M = self.bsr_container(A) + M.data, M.indices, M.indptr = data, indices, indptr + assert_equal(False, M.has_canonical_format) + assert_equal(2, len(M.indices)) # dups and has_canonical_format is False + + # but reset after accessing M.has_canonical_format can break flag + M = self.bsr_container(A) + M.has_canonical_format # underlying attr is set here + M.data, M.indices, M.indptr = data, indices, indptr + assert_equal(True, M.has_canonical_format) + assert_equal(2, len(M.indices)) # dups but has_canonical_format is True + M.sum_duplicates() + assert_equal(2, len(M.indices)) # still has duplicates!!!! + + def test_bsr_matvec(self): + A = self.bsr_container(arange(2*3*4*5).reshape(2*4,3*5), blocksize=(4,5)) + x = arange(A.shape[1]).reshape(-1,1) + assert_equal(A @ x, A.toarray() @ x) + + def test_bsr_matvecs(self): + A = self.bsr_container(arange(2*3*4*5).reshape(2*4,3*5), blocksize=(4,5)) + x = arange(A.shape[1]*6).reshape(-1,6) + assert_equal(A @ x, A.toarray() @ x) + + @pytest.mark.xfail(run=False, reason='BSR does not have a __getitem__') + def test_iterator(self): + pass + + @pytest.mark.xfail(run=False, reason='BSR does not have a __setitem__') + def test_setdiag(self): + pass + + def test_resize_blocked(self): + # test resize() with non-(1,1) blocksize + D = np.array([[1, 0, 3, 4], + [2, 0, 0, 0], + [3, 0, 0, 0]]) + S = self.spcreator(D, blocksize=(1, 2)) + assert_(S.resize((3, 2)) is None) + assert_array_equal(S.toarray(), [[1, 0], + [2, 0], + [3, 0]]) + S.resize((2, 2)) + assert_array_equal(S.toarray(), [[1, 0], + [2, 0]]) + S.resize((3, 2)) + assert_array_equal(S.toarray(), [[1, 0], + [2, 0], + [0, 0]]) + S.resize((3, 4)) + assert_array_equal(S.toarray(), [[1, 0, 0, 0], + [2, 0, 0, 0], + [0, 0, 0, 0]]) + assert_raises(ValueError, S.resize, (2, 3)) + + @pytest.mark.xfail(run=False, reason='BSR does not have a __setitem__') + def test_setdiag_comprehensive(self): + pass + + @pytest.mark.skipif(IS_COLAB, reason="exceeds memory limit") + def test_scalar_idx_dtype(self): + # Check that index dtype takes into account all parameters + # passed to sparsetools, including the scalar ones + indptr = np.zeros(2, dtype=np.int32) + indices = np.zeros(0, dtype=np.int32) + vals = np.zeros((0, 1, 1)) + a = self.bsr_container((vals, indices, indptr), shape=(1, 2**31-1)) + b = self.bsr_container((vals, indices, indptr), shape=(1, 2**31)) + c = self.bsr_container((1, 2**31-1)) + d = self.bsr_container((1, 2**31)) + assert_equal(a.indptr.dtype, np.int32) + assert_equal(b.indptr.dtype, np.int64) + assert_equal(c.indptr.dtype, np.int32) + assert_equal(d.indptr.dtype, np.int64) + + try: + vals2 = np.zeros((0, 1, 2**31-1)) + vals3 = np.zeros((0, 1, 2**31)) + e = self.bsr_container((vals2, indices, indptr), shape=(1, 2**31-1)) + f = self.bsr_container((vals3, indices, indptr), shape=(1, 2**31)) + assert_equal(e.indptr.dtype, np.int32) + assert_equal(f.indptr.dtype, np.int64) + except (MemoryError, ValueError): + # May fail on 32-bit Python + e = 0 + f = 0 + + # These shouldn't fail + for x in [a, b, c, d, e, f]: + x + x + + +class TestBSRMatrix(_MatrixMixin, TestBSR): + spcreator = bsr_matrix + + +TestBSR.init_class() +TestBSRMatrix.init_class() + + +#------------------------------------------------------------------------------ +# Tests for non-canonical representations (with duplicates, unsorted indices) +#------------------------------------------------------------------------------ + +def _same_sum_duplicate(data, *inds, **kwargs): + """Duplicates entries to produce the same matrix""" + indptr = kwargs.pop('indptr', None) + if np.issubdtype(data.dtype, np.bool_) or \ + np.issubdtype(data.dtype, np.unsignedinteger): + if indptr is None: + return (data,) + inds + else: + return (data,) + inds + (indptr,) + + zeros_pos = (data == 0).nonzero() + + # duplicate data + data = data.repeat(2, axis=0) + data[::2] -= 1 + data[1::2] = 1 + + # don't spoil all explicit zeros + if zeros_pos[0].size > 0: + pos = tuple(p[0] for p in zeros_pos) + pos1 = (2*pos[0],) + pos[1:] + pos2 = (2*pos[0]+1,) + pos[1:] + data[pos1] = 0 + data[pos2] = 0 + + inds = tuple(indices.repeat(2) for indices in inds) + + if indptr is None: + return (data,) + inds + else: + return (data,) + inds + (indptr * 2,) + + +class _NonCanonicalMixin: + def spcreator(self, D, *args, sorted_indices=False, **kwargs): + """Replace D with a non-canonical equivalent: containing + duplicate elements and explicit zeros""" + construct = super().spcreator + M = construct(D, *args, **kwargs) + + zero_pos = (M.toarray() == 0).nonzero() + has_zeros = (zero_pos[0].size > 0) + if has_zeros: + k = zero_pos[0].size//2 + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + M = self._insert_explicit_zero(M, zero_pos[0][k], zero_pos[1][k]) + + arg1 = self._arg1_for_noncanonical(M, sorted_indices) + if 'shape' not in kwargs: + kwargs['shape'] = M.shape + NC = construct(arg1, **kwargs) + + # check that result is valid + if NC.dtype in [np.float32, np.complex64]: + # For single-precision floats, the differences between M and NC + # that are introduced by the extra operations involved in the + # construction of NC necessitate a more lenient tolerance level + # than the default. + rtol = 1e-05 + else: + rtol = 1e-07 + assert_allclose(NC.toarray(), M.toarray(), rtol=rtol) + + # check that at least one explicit zero + if has_zeros: + assert_((NC.data == 0).any()) + # TODO check that NC has duplicates (which are not explicit zeros) + + return NC + + @pytest.mark.skip(reason='bool(matrix) counts explicit zeros') + def test_bool(self): + pass + + @pytest.mark.skip(reason='getnnz-axis counts explicit zeros') + def test_getnnz_axis(self): + pass + + @pytest.mark.skip(reason='nnz counts explicit zeros') + def test_empty(self): + pass + + +class _NonCanonicalCompressedMixin(_NonCanonicalMixin): + def _arg1_for_noncanonical(self, M, sorted_indices=False): + """Return non-canonical constructor arg1 equivalent to M""" + data, indices, indptr = _same_sum_duplicate(M.data, M.indices, + indptr=M.indptr) + if not sorted_indices: + for start, stop in zip(indptr, indptr[1:]): + indices[start:stop] = indices[start:stop][::-1].copy() + data[start:stop] = data[start:stop][::-1].copy() + return data, indices, indptr + + def _insert_explicit_zero(self, M, i, j): + M[i,j] = 0 + return M + + +class _NonCanonicalCSMixin(_NonCanonicalCompressedMixin): + def test_getelement(self): + def check(dtype, sorted_indices): + D = array([[1,0,0], + [4,3,0], + [0,2,0], + [0,0,0]], dtype=dtype) + A = self.spcreator(D, sorted_indices=sorted_indices) + + M,N = D.shape + + for i in range(-M, M): + for j in range(-N, N): + assert_equal(A[i,j], D[i,j]) + + for ij in [(0,3),(-1,3),(4,0),(4,3),(4,-1), (1, 2, 3)]: + assert_raises((IndexError, TypeError), A.__getitem__, ij) + + for dtype in supported_dtypes: + for sorted_indices in [False, True]: + check(np.dtype(dtype), sorted_indices) + + def test_setitem_sparse(self): + D = np.eye(3) + A = self.spcreator(D) + B = self.spcreator([[1,2,3]]) + + D[1,:] = B.toarray() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + A[1,:] = B + assert_array_equal(A.toarray(), D) + + D[:,2] = B.toarray().ravel() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", WMSG, SparseEfficiencyWarning) + A[:,2] = B.T + assert_array_equal(A.toarray(), D) + + @pytest.mark.xfail(run=False, reason='inverse broken with non-canonical matrix') + def test_inv(self): + pass + + @pytest.mark.xfail(run=False, reason='solve broken with non-canonical matrix') + def test_solve(self): + pass + + +class TestCSRNonCanonical(_NonCanonicalCSMixin, TestCSR): + pass + + +class TestCSRNonCanonicalMatrix(TestCSRNonCanonical, TestCSRMatrix): + pass + + +class TestCSCNonCanonical(_NonCanonicalCSMixin, TestCSC): + pass + + +class TestCSCNonCanonicalMatrix(TestCSCNonCanonical, TestCSCMatrix): + pass + + +class TestBSRNonCanonical(_NonCanonicalCompressedMixin, TestBSR): + def _insert_explicit_zero(self, M, i, j): + x = M.tocsr() + x[i,j] = 0 + return x.tobsr(blocksize=M.blocksize) + + @pytest.mark.xfail(run=False, reason='diagonal broken with non-canonical BSR') + def test_diagonal(self): + pass + + @pytest.mark.xfail(run=False, reason='expm broken with non-canonical BSR') + def test_expm(self): + pass + + +class TestBSRNonCanonicalMatrix(TestBSRNonCanonical, TestBSRMatrix): + pass + + +class COONonCanonicalMixin(_NonCanonicalMixin): + def _arg1_for_noncanonical(self, M, sorted_indices=None): + """Return non-canonical constructor arg1 equivalent to M""" + data, row, col = _same_sum_duplicate(M.data, M.row, M.col) + return data, (row, col) + + def _insert_explicit_zero(self, M, i, j): + M.data = np.r_[M.data.dtype.type(0), M.data] + M.row = np.r_[M.row.dtype.type(i), M.row] + M.col = np.r_[M.col.dtype.type(j), M.col] + return M + + def test_setdiag_noncanonical(self): + m = self.spcreator(np.eye(3)) + m.sum_duplicates() + m.setdiag([3, 2], k=1) + m.sum_duplicates() + assert_(np.all(np.diff(m.col) >= 0)) + + +class TestCOONonCanonical(COONonCanonicalMixin, TestCOO): + pass + + +class TestCOONonCanonicalMatrix(COONonCanonicalMixin, TestCOOMatrix): + pass + + +def test_broadcast_to(): + a = np.array([[1, 0, 2]]) + b = np.array([[1], [0], [2]]) + c = np.array([[1, 0, 2], [0, 3, 0]]) + d = np.array([[7]]) + e = np.array([[0]]) + f = np.array([[0,0,0,0]]) + for container in (csc_matrix, csc_array, csr_matrix, csr_array): + res_a = container(a)._broadcast_to((2,3)) + res_b = container(b)._broadcast_to((3,4)) + res_c = container(c)._broadcast_to((2,3)) + res_d = container(d)._broadcast_to((4,4)) + res_e = container(e)._broadcast_to((5,6)) + res_f = container(f)._broadcast_to((2,4)) + assert_array_equal(res_a.toarray(), np.broadcast_to(a, (2,3))) + assert_array_equal(res_b.toarray(), np.broadcast_to(b, (3,4))) + assert_array_equal(res_c.toarray(), c) + assert_array_equal(res_d.toarray(), np.broadcast_to(d, (4,4))) + assert_array_equal(res_e.toarray(), np.broadcast_to(e, (5,6))) + assert_array_equal(res_f.toarray(), np.broadcast_to(f, (2,4))) + + with pytest.raises(ValueError, match="cannot be broadcast"): + container([[1, 2, 0], [3, 0, 1]])._broadcast_to(shape=(2, 1)) + + with pytest.raises(ValueError, match="cannot be broadcast"): + container([[0, 1, 2]])._broadcast_to(shape=(3, 2)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_common1d.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_common1d.py new file mode 100644 index 0000000000000000000000000000000000000000..437af3d839c29d8131672a1e593ddb283608e7e8 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_common1d.py @@ -0,0 +1,444 @@ +"""Test of 1D aspects of sparse array classes""" +import warnings + +import pytest + +import numpy as np +from numpy.testing import assert_equal, assert_allclose +from numpy.exceptions import ComplexWarning + +from scipy.sparse import ( + bsr_array, csc_array, dia_array, lil_array, + coo_array, csr_array, dok_array, + ) +from scipy.sparse._sputils import supported_dtypes, matrix + + +spcreators = [coo_array, csr_array, dok_array] +math_dtypes = [np.int64, np.float64, np.complex128] + + +@pytest.fixture +def dat1d(): + return np.array([3, 0, 1, 0], 'd') + + +@pytest.fixture +def datsp_math_dtypes(dat1d): + dat_dtypes = {dtype: dat1d.astype(dtype) for dtype in math_dtypes} + return { + spcreator: [(dtype, dat, spcreator(dat)) for dtype, dat in dat_dtypes.items()] + for spcreator in spcreators + } + + +# Test init with 1D dense input +# sparrays which do not plan to support 1D +@pytest.mark.parametrize("spcreator", [bsr_array, csc_array, dia_array, lil_array]) +def test_no_1d_support_in_init(spcreator): + with pytest.raises(ValueError, match="arrays don't support 1D input"): + spcreator([0, 1, 2, 3]) + + +# Test init with nD dense input +# sparrays which do not yet support nD +@pytest.mark.parametrize( + "spcreator", [csr_array, dok_array, bsr_array, csc_array, dia_array, lil_array] +) +def test_no_nd_support_in_init(spcreator): + with pytest.raises(ValueError, match="arrays don't.*support 3D"): + spcreator(np.ones((3, 2, 4))) + + +# Main tests class +@pytest.mark.parametrize("spcreator", spcreators) +class TestCommon1D: + """test common functionality shared by 1D sparse formats""" + + def test_create_empty(self, spcreator): + assert_equal(spcreator((3,)).toarray(), np.zeros(3)) + assert_equal(spcreator((3,)).nnz, 0) + assert_equal(spcreator((3,)).count_nonzero(), 0) + + def test_invalid_shapes(self, spcreator): + with pytest.raises(ValueError, match='elements cannot be negative'): + spcreator((-3,)) + + def test_repr(self, spcreator, dat1d): + repr(spcreator(dat1d)) + + def test_str(self, spcreator, dat1d): + str(spcreator(dat1d)) + + def test_neg(self, spcreator): + A = np.array([-1, 0, 17, 0, -5, 0, 1, -4, 0, 0, 0, 0], 'd') + assert_equal(-A, (-spcreator(A)).toarray()) + + def test_1d_supported_init(self, spcreator): + A = spcreator([0, 1, 2, 3]) + assert A.ndim == 1 + + def test_reshape_1d_tofrom_row_or_column(self, spcreator): + # add a dimension 1d->2d + x = spcreator([1, 0, 7, 0, 0, 0, 0, -3, 0, 0, 0, 5]) + y = x.reshape(1, 12) + desired = [[1, 0, 7, 0, 0, 0, 0, -3, 0, 0, 0, 5]] + assert_equal(y.toarray(), desired) + + # remove a size-1 dimension 2d->1d + x = spcreator(desired) + y = x.reshape(12) + assert_equal(y.toarray(), desired[0]) + y2 = x.reshape((12,)) + assert y.shape == y2.shape + + # make a 2d column into 1d. 2d->1d + y = x.T.reshape(12) + assert_equal(y.toarray(), desired[0]) + + def test_reshape(self, spcreator): + x = spcreator([1, 0, 7, 0, 0, 0, 0, -3, 0, 0, 0, 5]) + y = x.reshape((4, 3)) + desired = [[1, 0, 7], [0, 0, 0], [0, -3, 0], [0, 0, 5]] + assert_equal(y.toarray(), desired) + + y = x.reshape((12,)) + assert y is x + + y = x.reshape(12) + assert_equal(y.toarray(), x.toarray()) + + def test_sum(self, spcreator): + np.random.seed(1234) + dat_1 = np.array([0, 1, 2, 3, -4, 5, -6, 7, 9]) + dat_2 = np.random.rand(5) + dat_3 = np.array([]) + dat_4 = np.zeros((40,)) + arrays = [dat_1, dat_2, dat_3, dat_4] + + for dat in arrays: + datsp = spcreator(dat) + with np.errstate(over='ignore'): + assert np.isscalar(datsp.sum()) + assert_allclose(dat.sum(), datsp.sum()) + assert_allclose(dat.sum(axis=None), datsp.sum(axis=None)) + assert_allclose(dat.sum(axis=0), datsp.sum(axis=0)) + assert_allclose(dat.sum(axis=-1), datsp.sum(axis=-1)) + + # test `out` parameter + datsp.sum(axis=0, out=np.zeros(())) + + def test_sum_invalid_params(self, spcreator): + out = np.zeros((3,)) # wrong size for out + dat = np.array([0, 1, 2]) + datsp = spcreator(dat) + + with pytest.raises(ValueError, match='axis out of range'): + datsp.sum(axis=1) + with pytest.raises(ValueError, match='axis out of range'): + datsp.sum(axis=(0, 3)) + with pytest.raises(TypeError, match='axis must be an integer'): + datsp.sum(axis=1.5) + with pytest.raises(ValueError, match='output parameter.*wrong.*dimension'): + datsp.sum(axis=0, out=out) + + def test_numpy_sum(self, spcreator): + dat = np.array([0, 1, 2]) + datsp = spcreator(dat) + + dat_sum = np.sum(dat) + datsp_sum = np.sum(datsp) + + assert_allclose(dat_sum, datsp_sum) + + def test_mean(self, spcreator): + dat = np.array([0, 1, 2]) + datsp = spcreator(dat) + + assert_allclose(dat.mean(), datsp.mean()) + assert np.isscalar(datsp.mean(axis=None)) + assert_allclose(dat.mean(axis=None), datsp.mean(axis=None)) + assert_allclose(dat.mean(axis=0), datsp.mean(axis=0)) + assert_allclose(dat.mean(axis=-1), datsp.mean(axis=-1)) + + with pytest.raises(ValueError, match='axis'): + datsp.mean(axis=1) + with pytest.raises(ValueError, match='axis'): + datsp.mean(axis=-2) + + def test_mean_invalid_params(self, spcreator): + out = np.asarray(np.zeros((1, 3))) + dat = np.array([[0, 1, 2], [3, -4, 5], [-6, 7, 9]]) + + datsp = spcreator(dat) + with pytest.raises(ValueError, match='axis out of range'): + datsp.mean(axis=3) + with pytest.raises(ValueError, match='axis out of range'): + datsp.mean(axis=(0, 3)) + with pytest.raises(TypeError, match='axis must be an integer'): + datsp.mean(axis=1.5) + with pytest.raises(ValueError, match='out.*not match shape'): + datsp.mean(axis=1, out=out) + + def test_sum_dtype(self, spcreator): + dat = np.array([0, 1, 2]) + datsp = spcreator(dat) + + for dtype in supported_dtypes: + dat_sum = dat.sum(dtype=dtype) + datsp_sum = datsp.sum(dtype=dtype) + + assert_allclose(dat_sum, datsp_sum) + assert_equal(dat_sum.dtype, datsp_sum.dtype) + + def test_mean_dtype(self, spcreator): + dat = np.array([0, 1, 2]) + datsp = spcreator(dat) + + for dtype in supported_dtypes: + dat_mean = dat.mean(dtype=dtype) + datsp_mean = datsp.mean(dtype=dtype) + + assert_allclose(dat_mean, datsp_mean) + assert_equal(dat_mean.dtype, datsp_mean.dtype) + + def test_mean_out(self, spcreator): + dat = np.array([0, 1, 2]) + datsp = spcreator(dat) + + dat_out = np.array(0) + datsp_out = np.array(0) + + dat.mean(out=dat_out) + datsp.mean(out=datsp_out) + assert_allclose(dat_out, datsp_out) + + dat.mean(axis=0, out=dat_out) + datsp.mean(axis=0, out=datsp_out) + assert_allclose(dat_out, datsp_out) + + with pytest.raises(ValueError, match="output parameter.*dimension"): + datsp.mean(out=np.array([0])) + with pytest.raises(ValueError, match="output parameter.*dimension"): + datsp.mean(out=np.array([[0]])) + + def test_numpy_mean(self, spcreator): + dat = np.array([0, 1, 2]) + datsp = spcreator(dat) + + dat_mean = np.mean(dat) + datsp_mean = np.mean(datsp) + + assert_allclose(dat_mean, datsp_mean) + assert_equal(dat_mean.dtype, datsp_mean.dtype) + + def test_from_array(self, spcreator): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", ComplexWarning) + A = np.array([2, 3, 4]) + assert_equal(spcreator(A).toarray(), A) + + A = np.array([1.0 + 3j, 0, -1]) + assert_equal(spcreator(A).toarray(), A) + assert_equal(spcreator(A, dtype='int16').toarray(), A.astype('int16')) + + def test_from_list(self, spcreator): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", ComplexWarning) + A = [2, 3, 4] + assert_equal(spcreator(A).toarray(), A) + + A = [1.0 + 3j, 0, -1] + assert_equal(spcreator(A).toarray(), np.array(A)) + assert_equal( + spcreator(A, dtype='int16').toarray(), np.array(A).astype('int16') + ) + + def test_from_sparse(self, spcreator): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", ComplexWarning) + D = np.array([1, 0, 0]) + S = coo_array(D) + assert_equal(spcreator(S).toarray(), D) + S = spcreator(D) + assert_equal(spcreator(S).toarray(), D) + + D = np.array([1.0 + 3j, 0, -1]) + S = coo_array(D) + assert_equal(spcreator(S).toarray(), D) + assert_equal(spcreator(S, dtype='int16').toarray(), D.astype('int16')) + S = spcreator(D) + assert_equal(spcreator(S).toarray(), D) + assert_equal(spcreator(S, dtype='int16').toarray(), D.astype('int16')) + + def test_toarray(self, spcreator, dat1d): + datsp = spcreator(dat1d) + # Check C- or F-contiguous (default). + chk = datsp.toarray() + assert_equal(chk, dat1d) + assert chk.flags.c_contiguous == chk.flags.f_contiguous + + # Check C-contiguous (with arg). + chk = datsp.toarray(order='C') + assert_equal(chk, dat1d) + assert chk.flags.c_contiguous + assert chk.flags.f_contiguous + + # Check F-contiguous (with arg). + chk = datsp.toarray(order='F') + assert_equal(chk, dat1d) + assert chk.flags.c_contiguous + assert chk.flags.f_contiguous + + # Check with output arg. + out = np.zeros(datsp.shape, dtype=datsp.dtype) + datsp.toarray(out=out) + assert_equal(out, dat1d) + + # Check that things are fine when we don't initialize with zeros. + out[...] = 1.0 + datsp.toarray(out=out) + assert_equal(out, dat1d) + + # np.dot does not work with sparse matrices (unless scalars) + # so this is testing whether dat1d matches datsp.toarray() + a = np.array([1.0, 2.0, 3.0, 4.0]) + dense_dot_dense = np.dot(a, dat1d) + check = np.dot(a, datsp.toarray()) + assert_equal(dense_dot_dense, check) + + b = np.array([1.0, 2.0, 3.0, 4.0]) + dense_dot_dense = np.dot(dat1d, b) + check = np.dot(datsp.toarray(), b) + assert_equal(dense_dot_dense, check) + + # Check bool data works. + spbool = spcreator(dat1d, dtype=bool) + arrbool = dat1d.astype(bool) + assert_equal(spbool.toarray(), arrbool) + + def test_add(self, spcreator, datsp_math_dtypes): + for dtype, dat, datsp in datsp_math_dtypes[spcreator]: + a = dat.copy() + a[0] = 2.0 + b = datsp + c = b + a + assert_equal(c, b.toarray() + a) + + # test broadcasting + # Note: cant add nonzero scalar to sparray. Can add len 1 array + c = b + a[0:1] + assert_equal(c, b.toarray() + a[0]) + + def test_radd(self, spcreator, datsp_math_dtypes): + for dtype, dat, datsp in datsp_math_dtypes[spcreator]: + a = dat.copy() + a[0] = 2.0 + b = datsp + c = a + b + assert_equal(c, a + b.toarray()) + + def test_rsub(self, spcreator, datsp_math_dtypes): + for dtype, dat, datsp in datsp_math_dtypes[spcreator]: + if dtype == np.dtype('bool'): + # boolean array subtraction deprecated in 1.9.0 + continue + + assert_equal((dat - datsp), [0, 0, 0, 0]) + assert_equal((datsp - dat), [0, 0, 0, 0]) + assert_equal((0 - datsp).toarray(), -dat) + + A = spcreator([1, -4, 0, 2], dtype='d') + assert_equal((dat - A), dat - A.toarray()) + assert_equal((A - dat), A.toarray() - dat) + assert_equal(A.toarray() - datsp, A.toarray() - dat) + assert_equal(datsp - A.toarray(), dat - A.toarray()) + + # test broadcasting + assert_equal(dat[:1] - datsp, dat[:1] - dat) + + def test_matmul_basic(self, spcreator): + A = np.array([[2, 0, 3.0], [0, 0, 0], [0, 1, 2]]) + v = np.array([1, 0, 3]) + Asp = spcreator(A) + vsp = spcreator(v) + + # sparse result when both args are sparse and result not scalar + assert_equal((Asp @ vsp).toarray(), A @ v) + assert_equal(A @ vsp, A @ v) + assert_equal(Asp @ v, A @ v) + assert_equal((vsp @ Asp).toarray(), v @ A) + assert_equal(vsp @ A, v @ A) + assert_equal(v @ Asp, v @ A) + + assert_equal(vsp @ vsp, v @ v) + assert_equal(v @ vsp, v @ v) + assert_equal(vsp @ v, v @ v) + assert_equal((Asp @ Asp).toarray(), A @ A) + assert_equal(A @ Asp, A @ A) + assert_equal(Asp @ A, A @ A) + + def test_matvec(self, spcreator): + A = np.array([2, 0, 3.0]) + Asp = spcreator(A) + col = np.array([[1, 2, 3]]).T + + assert_allclose(Asp @ col, Asp.toarray() @ col) + + assert (A @ np.array([1, 2, 3])).shape == () + assert Asp @ np.array([1, 2, 3]) == 11 + assert (Asp @ np.array([1, 2, 3])).shape == () + assert (Asp @ np.array([[1], [2], [3]])).shape == (1,) + # check result type + assert isinstance(Asp @ matrix([[1, 2, 3]]).T, np.ndarray) + + # ensure exception is raised for improper dimensions + bad_vecs = [np.array([1, 2]), np.array([1, 2, 3, 4]), np.array([[1], [2]])] + for x in bad_vecs: + with pytest.raises(ValueError, match='dimension mismatch'): + Asp @ x + + # The current relationship between sparse matrix products and array + # products is as follows: + dot_result = np.dot(Asp.toarray(), [1, 2, 3]) + assert_allclose(Asp @ np.array([1, 2, 3]), dot_result) + assert_allclose(Asp @ [[1], [2], [3]], dot_result.T) + # Note that the result of Asp @ x is dense if x has a singleton dimension. + + def test_rmatvec(self, spcreator, dat1d): + M = spcreator(dat1d) + assert_allclose([1, 2, 3, 4] @ M, np.dot([1, 2, 3, 4], M.toarray())) + row = np.array([[1, 2, 3, 4]]) + assert_allclose(row @ M, row @ M.toarray()) + + def test_transpose(self, spcreator, dat1d): + for A in [dat1d, np.array([])]: + B = spcreator(A) + assert_equal(B.toarray(), A) + assert_equal(B.transpose().toarray(), A) + assert_equal(B.dtype, A.dtype) + + def test_add_dense_to_sparse(self, spcreator, datsp_math_dtypes): + for dtype, dat, datsp in datsp_math_dtypes[spcreator]: + sum1 = dat + datsp + assert_equal(sum1, dat + dat) + sum2 = datsp + dat + assert_equal(sum2, dat + dat) + + def test_iterator(self, spcreator): + # test that __iter__ is compatible with NumPy + B = np.arange(5) + A = spcreator(B) + + if A.format not in ['coo', 'dia', 'bsr']: + for x, y in zip(A, B): + assert_equal(x, y) + + def test_resize(self, spcreator): + # resize(shape) resizes the matrix in-place + D = np.array([1, 0, 3, 4]) + S = spcreator(D) + assert S.resize((3,)) is None + assert_equal(S.toarray(), [1, 0, 3]) + S.resize((5,)) + assert_equal(S.toarray(), [1, 0, 3, 0, 0]) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_construct.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_construct.py new file mode 100644 index 0000000000000000000000000000000000000000..6d37dc62fdaf6ea709876b969e7e659b0de07cd5 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_construct.py @@ -0,0 +1,1154 @@ +"""test sparse matrix construction functions""" + +import numpy as np +from numpy import array +from numpy.testing import (assert_equal, assert_, + assert_array_equal, assert_array_almost_equal_nulp) +import pytest +from pytest import raises as assert_raises +from scipy._lib._testutils import check_free_memory + +from scipy.sparse import (csr_matrix, coo_matrix, + csr_array, coo_array, + csc_array, bsr_array, + dia_array, dok_array, + lil_array, csc_matrix, + bsr_matrix, dia_matrix, + lil_matrix, sparray, spmatrix, + _construct as construct) +from scipy.sparse._construct import rand as sprand + +sparse_formats = ['csr','csc','coo','bsr','dia','lil','dok'] + +#TODO check whether format=XXX is respected + + +def _sprandn(m, n, density=0.01, format="coo", dtype=None, rng=None): + # Helper function for testing. + rng = np.random.default_rng(rng) + data_rvs = rng.standard_normal + return construct.random(m, n, density, format, dtype, rng, data_rvs) + + +def _sprandn_array(m, n, density=0.01, format="coo", dtype=None, rng=None): + # Helper function for testing. + rng = np.random.default_rng(rng) + data_sampler = rng.standard_normal + return construct.random_array((m, n), density=density, format=format, dtype=dtype, + rng=rng, data_sampler=data_sampler) + + +class TestConstructUtils: + + @pytest.mark.parametrize("cls", [ + csc_array, csr_array, coo_array, bsr_array, + dia_array, dok_array, lil_array + ]) + def test_singleton_array_constructor(self, cls): + with pytest.raises( + ValueError, + match=( + 'scipy sparse array classes do not support ' + 'instantiation from a scalar' + ) + ): + cls(0) + + @pytest.mark.parametrize("cls", [ + csc_matrix, csr_matrix, coo_matrix, + bsr_matrix, dia_matrix, lil_matrix + ]) + def test_singleton_matrix_constructor(self, cls): + """ + This test is for backwards compatibility post scipy 1.13. + The behavior observed here is what is to be expected + with the older matrix classes. This test comes with the + exception of dok_matrix, which was not working pre scipy1.12 + (unlike the rest of these). + """ + assert cls(0).shape == (1, 1) + + def test_spdiags(self): + diags1 = array([[1, 2, 3, 4, 5]]) + diags2 = array([[1, 2, 3, 4, 5], + [6, 7, 8, 9,10]]) + diags3 = array([[1, 2, 3, 4, 5], + [6, 7, 8, 9,10], + [11,12,13,14,15]]) + + cases = [] + cases.append((diags1, 0, 1, 1, [[1]])) + cases.append((diags1, [0], 1, 1, [[1]])) + cases.append((diags1, [0], 2, 1, [[1],[0]])) + cases.append((diags1, [0], 1, 2, [[1,0]])) + cases.append((diags1, [1], 1, 2, [[0,2]])) + cases.append((diags1,[-1], 1, 2, [[0,0]])) + cases.append((diags1, [0], 2, 2, [[1,0],[0,2]])) + cases.append((diags1,[-1], 2, 2, [[0,0],[1,0]])) + cases.append((diags1, [3], 2, 2, [[0,0],[0,0]])) + cases.append((diags1, [0], 3, 4, [[1,0,0,0],[0,2,0,0],[0,0,3,0]])) + cases.append((diags1, [1], 3, 4, [[0,2,0,0],[0,0,3,0],[0,0,0,4]])) + cases.append((diags1, [2], 3, 5, [[0,0,3,0,0],[0,0,0,4,0],[0,0,0,0,5]])) + + cases.append((diags2, [0,2], 3, 3, [[1,0,8],[0,2,0],[0,0,3]])) + cases.append((diags2, [-1,0], 3, 4, [[6,0,0,0],[1,7,0,0],[0,2,8,0]])) + cases.append((diags2, [2,-3], 6, 6, [[0,0,3,0,0,0], + [0,0,0,4,0,0], + [0,0,0,0,5,0], + [6,0,0,0,0,0], + [0,7,0,0,0,0], + [0,0,8,0,0,0]])) + + cases.append((diags3, [-1,0,1], 6, 6, [[6,12, 0, 0, 0, 0], + [1, 7,13, 0, 0, 0], + [0, 2, 8,14, 0, 0], + [0, 0, 3, 9,15, 0], + [0, 0, 0, 4,10, 0], + [0, 0, 0, 0, 5, 0]])) + cases.append((diags3, [-4,2,-1], 6, 5, [[0, 0, 8, 0, 0], + [11, 0, 0, 9, 0], + [0,12, 0, 0,10], + [0, 0,13, 0, 0], + [1, 0, 0,14, 0], + [0, 2, 0, 0,15]])) + cases.append((diags3, [-1, 1, 2], len(diags3[0]), len(diags3[0]), + [[0, 7, 13, 0, 0], + [1, 0, 8, 14, 0], + [0, 2, 0, 9, 15], + [0, 0, 3, 0, 10], + [0, 0, 0, 4, 0]])) + + for d, o, m, n, result in cases: + if len(d[0]) == m and m == n: + assert_equal(construct.spdiags(d, o).toarray(), result) + assert_equal(construct.spdiags(d, o, m, n).toarray(), result) + assert_equal(construct.spdiags(d, o, (m, n)).toarray(), result) + + def test_diags(self): + a = array([1.0, 2.0, 3.0, 4.0, 5.0]) + b = array([6.0, 7.0, 8.0, 9.0, 10.0]) + c = array([11.0, 12.0, 13.0, 14.0, 15.0]) + + cases = [] + cases.append((a[:1], 0, (1, 1), [[1]])) + cases.append(([a[:1]], [0], (1, 1), [[1]])) + cases.append(([a[:1]], [0], (2, 1), [[1],[0]])) + cases.append(([a[:1]], [0], (1, 2), [[1,0]])) + cases.append(([a[:1]], [1], (1, 2), [[0,1]])) + cases.append(([a[:2]], [0], (2, 2), [[1,0],[0,2]])) + cases.append(([a[:1]],[-1], (2, 2), [[0,0],[1,0]])) + cases.append(([a[:3]], [0], (3, 4), [[1,0,0,0],[0,2,0,0],[0,0,3,0]])) + cases.append(([a[:3]], [1], (3, 4), [[0,1,0,0],[0,0,2,0],[0,0,0,3]])) + cases.append(([a[:1]], [-2], (3, 5), [[0,0,0,0,0],[0,0,0,0,0],[1,0,0,0,0]])) + cases.append(([a[:2]], [-1], (3, 5), [[0,0,0,0,0],[1,0,0,0,0],[0,2,0,0,0]])) + cases.append(([a[:3]], [0], (3, 5), [[1,0,0,0,0],[0,2,0,0,0],[0,0,3,0,0]])) + cases.append(([a[:3]], [1], (3, 5), [[0,1,0,0,0],[0,0,2,0,0],[0,0,0,3,0]])) + cases.append(([a[:3]], [2], (3, 5), [[0,0,1,0,0],[0,0,0,2,0],[0,0,0,0,3]])) + cases.append(([a[:2]], [3], (3, 5), [[0,0,0,1,0],[0,0,0,0,2],[0,0,0,0,0]])) + cases.append(([a[:1]], [4], (3, 5), [[0,0,0,0,1],[0,0,0,0,0],[0,0,0,0,0]])) + cases.append(([a[:1]], [-4], (5, 3), [[0,0,0],[0,0,0],[0,0,0],[0,0,0],[1,0,0]])) + cases.append(([a[:2]], [-3], (5, 3), [[0,0,0],[0,0,0],[0,0,0],[1,0,0],[0,2,0]])) + cases.append(([a[:3]], [-2], (5, 3), [[0,0,0],[0,0,0],[1,0,0],[0,2,0],[0,0,3]])) + cases.append(([a[:3]], [-1], (5, 3), [[0,0,0],[1,0,0],[0,2,0],[0,0,3],[0,0,0]])) + cases.append(([a[:3]], [0], (5, 3), [[1,0,0],[0,2,0],[0,0,3],[0,0,0],[0,0,0]])) + cases.append(([a[:2]], [1], (5, 3), [[0,1,0],[0,0,2],[0,0,0],[0,0,0],[0,0,0]])) + cases.append(([a[:1]], [2], (5, 3), [[0,0,1],[0,0,0],[0,0,0],[0,0,0],[0,0,0]])) + + cases.append(([a[:3],b[:1]], [0,2], (3, 3), [[1,0,6],[0,2,0],[0,0,3]])) + cases.append(([a[:2],b[:3]], [-1,0], (3, 4), [[6,0,0,0],[1,7,0,0],[0,2,8,0]])) + cases.append(([a[:4],b[:3]], [2,-3], (6, 6), [[0,0,1,0,0,0], + [0,0,0,2,0,0], + [0,0,0,0,3,0], + [6,0,0,0,0,4], + [0,7,0,0,0,0], + [0,0,8,0,0,0]])) + + cases.append(([a[:4],b,c[:4]], [-1,0,1], (5, 5), [[6,11, 0, 0, 0], + [1, 7,12, 0, 0], + [0, 2, 8,13, 0], + [0, 0, 3, 9,14], + [0, 0, 0, 4,10]])) + cases.append(([a[:2],b[:3],c], [-4,2,-1], (6, 5), [[0, 0, 6, 0, 0], + [11, 0, 0, 7, 0], + [0,12, 0, 0, 8], + [0, 0,13, 0, 0], + [1, 0, 0,14, 0], + [0, 2, 0, 0,15]])) + + # too long arrays are OK + cases.append(([a], [0], (1, 1), [[1]])) + cases.append(([a[:3],b], [0,2], (3, 3), [[1, 0, 6], [0, 2, 0], [0, 0, 3]])) + cases.append(( + np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), + [0,-1], + (3, 3), + [[1, 0, 0], [4, 2, 0], [0, 5, 3]] + )) + + # scalar case: broadcasting + cases.append(([1.0,-2.0,1.0], [1,0,-1], (3, 3), [[-2, 1, 0], + [1, -2, 1], + [0, 1, -2]])) + + for d, o, shape, result in cases: + err_msg = f"{d!r} {o!r} {shape!r} {result!r}" + assert_equal(construct.diags(d, offsets=o, shape=shape).toarray(), + result, err_msg=err_msg) + + if (shape[0] == shape[1] + and hasattr(d[0], '__len__') + and len(d[0]) <= max(shape)): + # should be able to find the shape automatically + assert_equal(construct.diags(d, offsets=o).toarray(), + result, err_msg=err_msg) + + def test_diags_default(self): + a = array([1.0, 2.0, 3.0, 4.0, 5.0]) + assert_equal(construct.diags(a).toarray(), np.diag(a)) + + def test_diags_default_bad(self): + a = array([[1, 2, 3, 4, 5], [2, 3, 4, 5, 6]]) + assert_raises(ValueError, construct.diags, a) + + def test_diags_bad(self): + a = array([1.0, 2.0, 3.0, 4.0, 5.0]) + b = array([6.0, 7.0, 8.0, 9.0, 10.0]) + c = array([11.0, 12.0, 13.0, 14.0, 15.0]) + + cases = [] + cases.append(([a[:0]], 0, (1, 1))) + cases.append(([a[:4],b,c[:3]], [-1,0,1], (5, 5))) + cases.append(([a[:2],c,b[:3]], [-4,2,-1], (6, 5))) + cases.append(([a[:2],c,b[:3]], [-4,2,-1], None)) + cases.append(([], [-4,2,-1], None)) + cases.append(([1.0], [-5], (4, 4))) + cases.append(([a], 0, None)) + + for d, o, shape in cases: + assert_raises(ValueError, construct.diags, d, offsets=o, shape=shape) + + assert_raises(TypeError, construct.diags, [[None]], offsets=[0]) + + def test_diags_vs_diag(self): + # Check that + # + # diags([a, b, ...], [i, j, ...]) == diag(a, i) + diag(b, j) + ... + # + + rng = np.random.RandomState(1234) + + for n_diags in [1, 2, 3, 4, 5, 10]: + n = 1 + n_diags//2 + rng.randint(0, 10) + + offsets = np.arange(-n+1, n-1) + rng.shuffle(offsets) + offsets = offsets[:n_diags] + + diagonals = [rng.rand(n - abs(q)) for q in offsets] + + mat = construct.diags(diagonals, offsets=offsets) + dense_mat = sum([np.diag(x, j) for x, j in zip(diagonals, offsets)]) + + assert_array_almost_equal_nulp(mat.toarray(), dense_mat) + + if len(offsets) == 1: + mat = construct.diags(diagonals[0], offsets=offsets[0]) + dense_mat = np.diag(diagonals[0], offsets[0]) + assert_array_almost_equal_nulp(mat.toarray(), dense_mat) + + def test_diags_dtype(self): + x = construct.diags([2.2], offsets=[0], shape=(2, 2), dtype=int) + assert_equal(x.dtype, int) + assert_equal(x.toarray(), [[2, 0], [0, 2]]) + + def test_diags_one_diagonal(self): + d = [0.0, 1.0, 2.0, 3.0, 4.0] + for k in range(-5, 6): + assert_equal(construct.diags(d, offsets=k).toarray(), + construct.diags([d], offsets=[k]).toarray()) + + def test_diags_empty(self): + x = construct.diags([]) + assert_equal(x.shape, (0, 0)) + + @pytest.mark.parametrize("identity", [construct.identity, construct.eye_array]) + def test_identity(self, identity): + assert_equal(identity(1).toarray(), [[1]]) + assert_equal(identity(2).toarray(), [[1,0],[0,1]]) + + I = identity(3, dtype='int8', format='dia') + assert_equal(I.dtype, np.dtype('int8')) + assert_equal(I.format, 'dia') + + for fmt in sparse_formats: + I = identity(3, format=fmt) + assert_equal(I.format, fmt) + assert_equal(I.toarray(), [[1,0,0],[0,1,0],[0,0,1]]) + + @pytest.mark.parametrize("eye", [construct.eye, construct.eye_array]) + def test_eye(self, eye): + assert_equal(eye(1,1).toarray(), [[1]]) + assert_equal(eye(2,3).toarray(), [[1,0,0],[0,1,0]]) + assert_equal(eye(3,2).toarray(), [[1,0],[0,1],[0,0]]) + assert_equal(eye(3,3).toarray(), [[1,0,0],[0,1,0],[0,0,1]]) + + assert_equal(eye(3,3,dtype='int16').dtype, np.dtype('int16')) + + for m in [3, 5]: + for n in [3, 5]: + for k in range(-5,6): + # scipy.sparse.eye deviates from np.eye here. np.eye will + # create arrays of all 0's when the diagonal offset is + # greater than the size of the array. For sparse arrays + # this makes less sense, especially as it results in dia + # arrays with negative diagonals. Therefore sp.sparse.eye + # validates that diagonal offsets fall within the shape of + # the array. See gh-18555. + if (k > 0 and k > n) or (k < 0 and abs(k) > m): + with pytest.raises( + ValueError, match="Offset.*out of bounds" + ): + eye(m, n, k=k) + + else: + assert_equal( + eye(m, n, k=k).toarray(), + np.eye(m, n, k=k) + ) + if m == n: + assert_equal( + eye(m, k=k).toarray(), + np.eye(m, n, k=k) + ) + + @pytest.mark.parametrize("eye", [construct.eye, construct.eye_array]) + def test_eye_one(self, eye): + assert_equal(eye(1).toarray(), [[1]]) + assert_equal(eye(2).toarray(), [[1,0],[0,1]]) + + I = eye(3, dtype='int8', format='dia') + assert_equal(I.dtype, np.dtype('int8')) + assert_equal(I.format, 'dia') + + for fmt in sparse_formats: + I = eye(3, format=fmt) + assert_equal(I.format, fmt) + assert_equal(I.toarray(), [[1,0,0],[0,1,0],[0,0,1]]) + + def test_eye_array_vs_matrix(self): + assert isinstance(construct.eye_array(3), sparray) + assert not isinstance(construct.eye(3), sparray) + + @pytest.mark.parametrize("arr,kw_format,out_format", [ + ([[0, 0], [0, 1]], None, 'coo'), # 2D sparse + ([[1, 0], [1, 1]], None, 'bsr'), # 2D dense + ([[[1, 0], [1, 1]]], None, 'coo'), # 3D dense + ]) + def test_kron_output_format(self, arr, kw_format, out_format): + sparr = coo_array(arr) + assert construct.kron(sparr, sparr, format=kw_format).format == out_format + assert construct.kron(sparr, arr, format=kw_format).format == out_format + assert construct.kron(arr, sparr, format=kw_format).format == out_format + + def test_kron(self): + cases = [] + + cases.append(array([[0]])) + cases.append(array([[-1]])) + cases.append(array([[4]])) + cases.append(array([[10]])) + cases.append(array([[0], [0]])) + cases.append(array([[0, 0]])) + cases.append(array([[1, 2], [3, 4]])) + cases.append(array([[0, 2], [5, 0]])) + cases.append(array([[0, 2, -6], [8, 0, 14]])) + cases.append(array([[5, 4], [0, 0], [6, 0]])) + cases.append(array([[5, 4, 4], [1, 0, 0], [6, 0, 8]])) + cases.append(array([[0, 1, 0, 2, 0, 5, 8]])) + cases.append(array([[0.5, 0.125, 0, 3.25], [0, 2.5, 0, 0]])) + + # test all cases with some formats + for a in cases: + ca = csr_array(a) + for b in cases: + cb = csr_array(b) + expected = np.kron(a, b) + for fmt in sparse_formats[1:4]: + result = construct.kron(ca, cb, format=fmt) + assert_equal(result.format, fmt) + assert_array_equal(result.toarray(), expected) + assert isinstance(result, sparray) + + # nD cases + cases.append(array([0, 1, 2])) + cases.append(array([[[0, 1, 2], [0, 1, 0]]])) + cases.append(array([[[0, 1]], [[2, 2]], [[1, 0]], [[2, 0]]])) + + for a in cases: + ca = coo_array(a) + for b in cases: + cb = coo_array(b) + expected = np.kron(a, b) + result = construct.kron(ca, cb, format="coo") + assert_array_equal(result.toarray(), expected) + + # test one case with all formats + a = array([[0.5, 0.125, 0, 3.25], [0, 2.5, 0, 0]]) + b = array([[5, 4, 4], [1, 0, 0], [6, 0, 8]]) + ca = csr_array(a) + cb = csr_array(b) + + expected = np.kron(a, b) + for fmt in sparse_formats: + result = construct.kron(ca, cb, format=fmt) + assert_equal(result.format, fmt) + assert_array_equal(result.toarray(), expected) + assert isinstance(result, sparray) + + # check that spmatrix returned when both inputs are spmatrix + result = construct.kron(csr_matrix(a), csr_matrix(b), format=fmt) + assert_equal(result.format, fmt) + assert_array_equal(result.toarray(), expected) + assert isinstance(result, spmatrix) + + def test_kron_ndim_exceptions(self): + # spmatrix is default, so exceptions with 3D unless sparse arrays are input + with pytest.raises(TypeError, match='expected 2D array or matrix'): + construct.kron([[0], [1]], [[[0, 1]]]) + with pytest.raises(TypeError, match="expected 2D array or matrix"): + construct.kron([[[1, 1]]], [[1], [1]]) + + # no exception for 3D if any sparse arrays input + construct.kron(coo_array([[[0, 1]]]), [[[0], [1]]]) + construct.kron([[[0, 1]]], coo_array([[[0], [1]]])) + + # no exception for 1D if either sparray or spmatrix + construct.kron([[0], [1]], [0, 1, 0]) # spmatrix b/c lists; 1d-list -> 2d + construct.kron([1, 1], [[1], [1]]) + construct.kron([[0], [1]], coo_array([0, 1, 0])) # sparray 1d-list -> 1d + construct.kron(coo_array([1, 1]), [[1], [1]]) + + def test_kron_large(self): + n = 2**16 + a = construct.diags_array([1], shape=(1, n), offsets=n-1, dtype=None) + b = construct.diags_array([1], shape=(n, 1), offsets=1-n, dtype=None) + + construct.kron(a, a) + construct.kron(b, b) + + def test_kronsum(self): + cases = [] + + cases.append(array([[0]])) + cases.append(array([[-1]])) + cases.append(array([[4]])) + cases.append(array([[10]])) + cases.append(array([[1,2],[3,4]])) + cases.append(array([[0,2],[5,0]])) + cases.append(array([[0,2,-6],[8,0,14],[0,3,0]])) + cases.append(array([[1,0,0],[0,5,-1],[4,-2,8]])) + + # test all cases with default format + for a in cases: + for b in cases: + result = construct.kronsum(csr_array(a), csr_array(b)).toarray() + expected = (np.kron(np.eye(b.shape[0]), a) + + np.kron(b, np.eye(a.shape[0]))) + assert_array_equal(result, expected) + + # check that spmatrix returned when both inputs are spmatrix + result = construct.kronsum(csr_matrix(a), csr_matrix(b)).toarray() + assert_array_equal(result, expected) + + def test_kronsum_ndim_exceptions(self): + with pytest.raises(ValueError, match='requires 2D input'): + construct.kronsum([[0], [1]], csr_array([0, 1])) + with pytest.raises(ValueError, match='requires 2D input'): + construct.kronsum(csr_array([0, 1]), [[0], [1]]) + # no exception if sparse arrays are not input (spmatrix inferred) + construct.kronsum([[0, 1], [1, 0]], [2]) + + @pytest.mark.parametrize("coo_cls", [coo_matrix, coo_array]) + def test_vstack(self, coo_cls): + A = coo_cls([[1,2],[3,4]]) + B = coo_cls([[5,6]]) + + expected = array([[1, 2], + [3, 4], + [5, 6]]) + assert_equal(construct.vstack([A, B]).toarray(), expected) + assert_equal(construct.vstack([A, B], dtype=np.float32).dtype, + np.float32) + + assert_equal(construct.vstack([A.todok(), B.todok()]).toarray(), expected) + + assert_equal(construct.vstack([A.tocsr(), B.tocsr()]).toarray(), + expected) + result = construct.vstack([A.tocsr(), B.tocsr()], + format="csr", dtype=np.float32) + assert_equal(result.dtype, np.float32) + assert_equal(result.indices.dtype, np.int32) + assert_equal(result.indptr.dtype, np.int32) + + assert_equal(construct.vstack([A.tocsc(), B.tocsc()]).toarray(), + expected) + result = construct.vstack([A.tocsc(), B.tocsc()], + format="csc", dtype=np.float32) + assert_equal(result.dtype, np.float32) + assert_equal(result.indices.dtype, np.int32) + assert_equal(result.indptr.dtype, np.int32) + + def test_vstack_maintain64bit_idx_dtype(self): + # see gh-20389 v/hstack returns int32 idx_dtype with input int64 idx_dtype + X = csr_array([[1, 0, 0], [0, 1, 0], [0, 1, 0]]) + X.indptr = X.indptr.astype(np.int64) + X.indices = X.indices.astype(np.int64) + assert construct.vstack([X, X]).indptr.dtype == np.int64 + assert construct.hstack([X, X]).indptr.dtype == np.int64 + + X = csc_array([[1, 0, 0], [0, 1, 0], [0, 1, 0]]) + X.indptr = X.indptr.astype(np.int64) + X.indices = X.indices.astype(np.int64) + assert construct.vstack([X, X]).indptr.dtype == np.int64 + assert construct.hstack([X, X]).indptr.dtype == np.int64 + + X = coo_array([[1, 0, 0], [0, 1, 0], [0, 1, 0]]) + X.coords = tuple(co.astype(np.int64) for co in X.coords) + assert construct.vstack([X, X]).coords[0].dtype == np.int64 + assert construct.hstack([X, X]).coords[0].dtype == np.int64 + + def test_vstack_matrix_or_array(self): + A = [[1,2],[3,4]] + B = [[5,6]] + assert isinstance(construct.vstack([coo_array(A), coo_array(B)]), sparray) + assert isinstance(construct.vstack([coo_array(A), coo_matrix(B)]), sparray) + assert isinstance(construct.vstack([coo_matrix(A), coo_array(B)]), sparray) + assert isinstance(construct.vstack([coo_matrix(A), coo_matrix(B)]), spmatrix) + + def test_vstack_1d_with_2d(self): + # fixes gh-21064 + arr = csr_array([[1, 0, 0], [0, 1, 0]]) + arr1d = csr_array([1, 0, 0]) + arr1dcoo = coo_array([1, 0, 0]) + assert construct.vstack([arr, np.array([0, 0, 0])]).shape == (3, 3) + assert construct.hstack([arr1d, np.array([[0]])]).shape == (1, 4) + assert construct.hstack([arr1d, arr1d]).shape == (1, 6) + assert construct.vstack([arr1d, arr1d]).shape == (2, 3) + + # check csr specialty stacking code like _stack_along_minor_axis + assert construct.hstack([arr, arr]).shape == (2, 6) + assert construct.hstack([arr1d, arr1d]).shape == (1, 6) + + assert construct.hstack([arr1d, arr1dcoo]).shape == (1, 6) + assert construct.vstack([arr, arr1dcoo]).shape == (3, 3) + assert construct.vstack([arr1d, arr1dcoo]).shape == (2, 3) + + with pytest.raises(ValueError, match="incompatible row dimensions"): + construct.hstack([arr, np.array([0, 0])]) + with pytest.raises(ValueError, match="incompatible column dimensions"): + construct.vstack([arr, np.array([0, 0])]) + + @pytest.mark.parametrize("coo_cls", [coo_matrix, coo_array]) + def test_hstack(self, coo_cls): + A = coo_cls([[1,2],[3,4]]) + B = coo_cls([[5],[6]]) + + expected = array([[1, 2, 5], + [3, 4, 6]]) + assert_equal(construct.hstack([A, B]).toarray(), expected) + assert_equal(construct.hstack([A, B], dtype=np.float32).dtype, + np.float32) + + assert_equal(construct.hstack([A.todok(), B.todok()]).toarray(), expected) + + assert_equal(construct.hstack([A.tocsc(), B.tocsc()]).toarray(), + expected) + assert_equal(construct.hstack([A.tocsc(), B.tocsc()], + dtype=np.float32).dtype, + np.float32) + assert_equal(construct.hstack([A.tocsr(), B.tocsr()]).toarray(), + expected) + assert_equal(construct.hstack([A.tocsr(), B.tocsr()], + dtype=np.float32).dtype, + np.float32) + + def test_hstack_matrix_or_array(self): + A = [[1,2],[3,4]] + B = [[5],[6]] + assert isinstance(construct.hstack([coo_array(A), coo_array(B)]), sparray) + assert isinstance(construct.hstack([coo_array(A), coo_matrix(B)]), sparray) + assert isinstance(construct.hstack([coo_matrix(A), coo_array(B)]), sparray) + assert isinstance(construct.hstack([coo_matrix(A), coo_matrix(B)]), spmatrix) + + @pytest.mark.parametrize("block_array", (construct.bmat, construct.block_array)) + def test_block_creation(self, block_array): + + A = coo_array([[1, 2], [3, 4]]) + B = coo_array([[5],[6]]) + C = coo_array([[7]]) + D = coo_array((0, 0)) + + expected = array([[1, 2, 5], + [3, 4, 6], + [0, 0, 7]]) + assert_equal(block_array([[A, B], [None, C]]).toarray(), expected) + E = csr_array((1, 2), dtype=np.int32) + assert_equal(block_array([[A.tocsr(), B.tocsr()], + [E, C.tocsr()]]).toarray(), + expected) + assert_equal(block_array([[A.tocsc(), B.tocsc()], + [E.tocsc(), C.tocsc()]]).toarray(), + expected) + + expected = array([[1, 2, 0], + [3, 4, 0], + [0, 0, 7]]) + assert_equal(block_array([[A, None], [None, C]]).toarray(), expected) + assert_equal(block_array([[A.tocsr(), E.T.tocsr()], + [E, C.tocsr()]]).toarray(), + expected) + assert_equal(block_array([[A.tocsc(), E.T.tocsc()], + [E.tocsc(), C.tocsc()]]).toarray(), + expected) + + Z = csr_array((1, 1), dtype=np.int32) + expected = array([[0, 5], + [0, 6], + [7, 0]]) + assert_equal(block_array([[None, B], [C, None]]).toarray(), expected) + assert_equal(block_array([[E.T.tocsr(), B.tocsr()], + [C.tocsr(), Z]]).toarray(), + expected) + assert_equal(block_array([[E.T.tocsc(), B.tocsc()], + [C.tocsc(), Z.tocsc()]]).toarray(), + expected) + + expected = np.empty((0, 0)) + assert_equal(block_array([[None, None]]).toarray(), expected) + assert_equal(block_array([[None, D], [D, None]]).toarray(), + expected) + + # test bug reported in gh-5976 + expected = array([[7]]) + assert_equal(block_array([[None, D], [C, None]]).toarray(), + expected) + + # test failure cases + with assert_raises(ValueError) as excinfo: + block_array([[A], [B]]) + excinfo.match(r'Got blocks\[1,0\]\.shape\[1\] == 1, expected 2') + + with assert_raises(ValueError) as excinfo: + block_array([[A.tocsr()], [B.tocsr()]]) + excinfo.match(r'incompatible dimensions for axis 1') + + with assert_raises(ValueError) as excinfo: + block_array([[A.tocsc()], [B.tocsc()]]) + excinfo.match(r'Mismatching dimensions along axis 1: ({1, 2}|{2, 1})') + + with assert_raises(ValueError) as excinfo: + block_array([[A, C]]) + excinfo.match(r'Got blocks\[0,1\]\.shape\[0\] == 1, expected 2') + + with assert_raises(ValueError) as excinfo: + block_array([[A.tocsr(), C.tocsr()]]) + excinfo.match(r'Mismatching dimensions along axis 0: ({1, 2}|{2, 1})') + + with assert_raises(ValueError) as excinfo: + block_array([[A.tocsc(), C.tocsc()]]) + excinfo.match(r'incompatible dimensions for axis 0') + + def test_block_return_type(self): + block = construct.block_array + + # csr format ensures we hit _compressed_sparse_stack + # shape of F,G ensure we hit _stack_along_minor_axis + # list version ensure we hit the path with neither helper function + Fl, Gl = [[1, 2],[3, 4]], [[7], [5]] + Fm, Gm = csr_matrix(Fl), csr_matrix(Gl) + assert isinstance(block([[None, Fl], [Gl, None]], format="csr"), sparray) + assert isinstance(block([[None, Fm], [Gm, None]], format="csr"), sparray) + assert isinstance(block([[Fm, Gm]], format="csr"), sparray) + + def test_bmat_return_type(self): + """This can be removed after sparse matrix is removed""" + bmat = construct.bmat + # check return type. if any input _is_array output array, else matrix + Fl, Gl = [[1, 2],[3, 4]], [[7], [5]] + Fm, Gm = csr_matrix(Fl), csr_matrix(Gl) + Fa, Ga = csr_array(Fl), csr_array(Gl) + assert isinstance(bmat([[Fa, Ga]], format="csr"), sparray) + assert isinstance(bmat([[Fm, Gm]], format="csr"), spmatrix) + assert isinstance(bmat([[None, Fa], [Ga, None]], format="csr"), sparray) + assert isinstance(bmat([[None, Fm], [Ga, None]], format="csr"), sparray) + assert isinstance(bmat([[None, Fm], [Gm, None]], format="csr"), spmatrix) + assert isinstance(bmat([[None, Fl], [Gl, None]], format="csr"), spmatrix) + + # type returned by _compressed_sparse_stack (all csr) + assert isinstance(bmat([[Ga, Ga]], format="csr"), sparray) + assert isinstance(bmat([[Gm, Ga]], format="csr"), sparray) + assert isinstance(bmat([[Ga, Gm]], format="csr"), sparray) + assert isinstance(bmat([[Gm, Gm]], format="csr"), spmatrix) + # shape is 2x2 so no _stack_along_minor_axis + assert isinstance(bmat([[Fa, Fm]], format="csr"), sparray) + assert isinstance(bmat([[Fm, Fm]], format="csr"), spmatrix) + + # type returned by _compressed_sparse_stack (all csc) + assert isinstance(bmat([[Gm.tocsc(), Ga.tocsc()]], format="csc"), sparray) + assert isinstance(bmat([[Gm.tocsc(), Gm.tocsc()]], format="csc"), spmatrix) + # shape is 2x2 so no _stack_along_minor_axis + assert isinstance(bmat([[Fa.tocsc(), Fm.tocsc()]], format="csr"), sparray) + assert isinstance(bmat([[Fm.tocsc(), Fm.tocsc()]], format="csr"), spmatrix) + + # type returned when mixed input + assert isinstance(bmat([[Gl, Ga]], format="csr"), sparray) + assert isinstance(bmat([[Gm.tocsc(), Ga]], format="csr"), sparray) + assert isinstance(bmat([[Gm.tocsc(), Gm]], format="csr"), spmatrix) + assert isinstance(bmat([[Gm, Gm]], format="csc"), spmatrix) + + @pytest.mark.xslow + @pytest.mark.xfail_on_32bit("Can't create large array for test") + def test_concatenate_int32_overflow(self): + """ test for indptr overflow when concatenating matrices """ + check_free_memory(30000) + + n = 33000 + A = csr_array(np.ones((n, n), dtype=bool)) + B = A.copy() + C = construct._compressed_sparse_stack((A, B), axis=0, + return_spmatrix=False) + + assert_(np.all(np.equal(np.diff(C.indptr), n))) + assert_equal(C.indices.dtype, np.int64) + assert_equal(C.indptr.dtype, np.int64) + + def test_block_diag_basic(self): + """ basic test for block_diag """ + A = coo_array([[1,2],[3,4]]) + B = coo_array([[5],[6]]) + C = coo_array([[7]]) + + expected = array([[1, 2, 0, 0], + [3, 4, 0, 0], + [0, 0, 5, 0], + [0, 0, 6, 0], + [0, 0, 0, 7]]) + + ABC = construct.block_diag((A, B, C)) + assert_equal(ABC.toarray(), expected) + assert ABC.coords[0].dtype == np.int32 + + def test_block_diag_idx_dtype(self): + X = coo_array([[1, 0, 0], [0, 1, 0], [0, 1, 0]]) + X.coords = tuple(co.astype(np.int64) for co in X.coords) + assert construct.block_diag([X, X]).coords[0].dtype == np.int64 + + def test_block_diag_scalar_1d_args(self): + """ block_diag with scalar and 1d arguments """ + # one 1d matrix and a scalar + assert_array_equal(construct.block_diag([[2,3], 4]).toarray(), + [[2, 3, 0], [0, 0, 4]]) + # 1d sparse arrays + A = coo_array([1,0,3]) + B = coo_array([0,4]) + assert_array_equal(construct.block_diag([A, B]).toarray(), + [[1, 0, 3, 0, 0], [0, 0, 0, 0, 4]]) + + def test_block_diag_1(self): + """ block_diag with one matrix """ + assert_equal(construct.block_diag([[1, 0]]).toarray(), + array([[1, 0]])) + assert_equal(construct.block_diag([[[1, 0]]]).toarray(), + array([[1, 0]])) + assert_equal(construct.block_diag([[[1], [0]]]).toarray(), + array([[1], [0]])) + # just on scalar + assert_equal(construct.block_diag([1]).toarray(), + array([[1]])) + + def test_block_diag_sparse_arrays(self): + """ block_diag with sparse arrays """ + + A = coo_array([[1, 2, 3]], shape=(1, 3)) + B = coo_array([[4, 5]], shape=(1, 2)) + assert_equal(construct.block_diag([A, B]).toarray(), + array([[1, 2, 3, 0, 0], [0, 0, 0, 4, 5]])) + + A = coo_array([[1], [2], [3]], shape=(3, 1)) + B = coo_array([[4], [5]], shape=(2, 1)) + assert_equal(construct.block_diag([A, B]).toarray(), + array([[1, 0], [2, 0], [3, 0], [0, 4], [0, 5]])) + + def test_block_diag_return_type(self): + A, B = coo_array([[1, 2, 3]]), coo_matrix([[2, 3, 4]]) + assert isinstance(construct.block_diag([A, A]), sparray) + assert isinstance(construct.block_diag([A, B]), sparray) + assert isinstance(construct.block_diag([B, A]), sparray) + assert isinstance(construct.block_diag([B, B]), spmatrix) + + def test_random_sampling(self): + # Simple sanity checks for sparse random sampling. + for f in sprand, _sprandn: + for t in [np.float32, np.float64, np.longdouble, + np.int32, np.int64, np.complex64, np.complex128]: + x = f(5, 10, density=0.1, dtype=t) + assert_equal(x.dtype, t) + assert_equal(x.shape, (5, 10)) + assert_equal(x.nnz, 5) + + x1 = f(5, 10, density=0.1, rng=4321) + assert_equal(x1.dtype, np.float64) + + x2 = f(5, 10, density=0.1, rng=np.random.default_rng(4321)) + + assert_array_equal(x1.data, x2.data) + assert_array_equal(x1.row, x2.row) + assert_array_equal(x1.col, x2.col) + + for density in [0.0, 0.1, 0.5, 1.0]: + x = f(5, 10, density=density) + assert_equal(x.nnz, int(density * np.prod(x.shape))) + + for fmt in ['coo', 'csc', 'csr', 'lil']: + x = f(5, 10, format=fmt) + assert_equal(x.format, fmt) + + assert_raises(ValueError, lambda: f(5, 10, 1.1)) + assert_raises(ValueError, lambda: f(5, 10, -0.1)) + + @pytest.mark.parametrize("rng", [None, 4321, np.random.default_rng(4321)]) + def test_rand(self, rng): + # Simple distributional checks for sparse.rand. + x = sprand(10, 20, density=0.5, dtype=np.float64, rng=rng) + assert_(np.all(np.less_equal(0, x.data))) + assert_(np.all(np.less_equal(x.data, 1))) + + @pytest.mark.parametrize("rng", [None, 4321, np.random.default_rng(4321)]) + def test_randn(self, rng): + # Simple distributional checks for sparse.randn. + # Statistically, some of these should be negative + # and some should be greater than 1. + x = _sprandn(10, 20, density=0.5, dtype=np.float64, rng=rng) + assert_(np.any(np.less(x.data, 0))) + assert_(np.any(np.less(1, x.data))) + x = _sprandn_array(10, 20, density=0.5, dtype=np.float64, rng=rng) + assert_(np.any(np.less(x.data, 0))) + assert_(np.any(np.less(1, x.data))) + + def test_random_accept_str_dtype(self): + # anything that np.dtype can convert to a dtype should be accepted + # for the dtype + construct.random(10, 10, dtype='d') + construct.random_array((10, 10), dtype='d') + construct.random_array((10, 10, 10), dtype='d') + construct.random_array((10, 10, 10, 10, 10), dtype='d') + + def test_random_array_maintains_array_shape(self): + # preserve use of old random_state during SPEC 7 transition + arr = construct.random_array((0, 4), density=0.3, dtype=int, random_state=0) + assert arr.shape == (0, 4) + + arr = construct.random_array((10, 10, 10), density=0.3, dtype=int, rng=0) + assert arr.shape == (10, 10, 10) + + arr = construct.random_array((10, 10, 10, 10, 10), density=0.3, dtype=int, + rng=0) + assert arr.shape == (10, 10, 10, 10, 10) + + def test_random_array_idx_dtype(self): + A = construct.random_array((10, 10)) + assert A.coords[0].dtype == np.int32 + + def test_random_sparse_matrix_returns_correct_number_of_non_zero_elements(self): + # A 10 x 10 matrix, with density of 12.65%, should have 13 nonzero elements. + # 10 x 10 x 0.1265 = 12.65, which should be rounded up to 13, not 12. + sparse_matrix = construct.random(10, 10, density=0.1265) + assert_equal(sparse_matrix.count_nonzero(),13) + # check random_array + sparse_array = construct.random_array((10, 10), density=0.1265) + assert_equal(sparse_array.count_nonzero(),13) + assert isinstance(sparse_array, sparray) + # check big size + shape = (2**33, 2**33) + sparse_array = construct.random_array(shape, density=2.7105e-17) + assert_equal(sparse_array.count_nonzero(),2000) + + # for n-D + # check random_array + sparse_array = construct.random_array((10, 10, 10, 10), density=0.12658) + assert_equal(sparse_array.count_nonzero(),1266) + assert isinstance(sparse_array, sparray) + # check big size + shape = (2**33, 2**33, 2**33) + sparse_array = construct.random_array(shape, density=2.7105e-28) + assert_equal(sparse_array.count_nonzero(),172) + + +def test_diags_array(): + """Tests of diags_array that do not rely on diags wrapper.""" + diag = np.arange(1.0, 5.0) + + assert_array_equal(construct.diags_array(diag, dtype=None).toarray(), np.diag(diag)) + + assert_array_equal( + construct.diags_array(diag, offsets=2, dtype=None).toarray(), np.diag(diag, k=2) + ) + + assert_array_equal( + construct.diags_array(diag, offsets=2, shape=(4, 4), dtype=None).toarray(), + np.diag(diag, k=2)[:4, :4] + ) + + # Offset outside bounds when shape specified + with pytest.raises(ValueError, match=".*out of bounds"): + construct.diags(np.arange(1.0, 5.0), 5, shape=(4, 4)) + + +@pytest.mark.parametrize('func', [construct.diags_array, construct.diags]) +def test_diags_int(func): + d = [[3], [1, 2], [4]] + offsets = [-1, 0, 1] + # Until the deprecation period is over, `dtype=None` must be given + # explicitly to avoid the warning and the cast to an inexact type + # in diags_array() (gh-23102). + arr = func(d, offsets=offsets, dtype=None) + expected = np.array([[1, 4], [3, 2]]) + assert_array_equal(arr.toarray(), expected, strict=True) + + +@pytest.mark.parametrize('func', [construct.diags_array, construct.diags]) +def test_diags_int_to_float64(func): + d = [[3], [1, 2], [4]] + offsets = [-1, 0, 1] + # Until the deprecation period is over, diags and diag_array will cast + # integer inputs to float64 by default. A warning will be generated + # that indicates this behavior is deprecated. + # See gh-23102. + with pytest.warns(FutureWarning, match="output has been cast to"): + arr = func(d, offsets=offsets) + expected = np.array([[1.0, 4.0], [3.0, 2.0]]) + assert_array_equal(arr.toarray(), expected, strict=True) + + +def test_swapaxes(): + # Borrowed from Numpy swapaxes tests + x = np.array([8.375, 7.545, 8.828, 8.5, 1.757, 5.928, + 8.43, 7.78, 9.865, 5.878, 8.979, 4.732, + 3.012, 6.022, 5.095, 3.116, 5.238, 3.957, + 6.04, 9.63, 7.712, 3.382, 4.489, 6.479, + 7.189, 9.645, 5.395, 4.961, 9.894, 2.893, + 7.357, 9.828, 6.272, 3.758, 6.693, 0.993]) + sX = coo_array(x).reshape(6, 6) + sXswapped = construct.swapaxes(sX, 0, 1) + assert_equal(sXswapped[-1].toarray(), sX[:, -1].toarray()) + + sXX = sX.reshape(3, 2, 2, 3) + sXXswapped = construct.swapaxes(sXX, 0, 2) + assert_equal(sXXswapped.shape, (2, 2, 3, 3)) + + +def test_3d_swapaxes(): + tgt = [[[0, 0], [2, 6]], [[1, 5], [0, 7]]] + x = np.array([[[0, 1], [2, 0]], [[0, 5], [6, 7]]]) + A = coo_array(x) #[[[0, 1], [2, 0]], [[0, 5], [6, 7]]]) + out = construct.swapaxes(A, 0, 2) + assert_equal(out.toarray(), tgt) + assert_equal(out.toarray(), np.swapaxes(x, 0, 2)) + + +@pytest.mark.parametrize("format", sparse_formats) +def test_sparse_format_swapaxes(format): + A = np.array([[2, 0, 1], [3, 5, 0]]) + SA = coo_array(A).asformat(format) + + out = construct.swapaxes(SA, 1, 0) + assert out.format == "coo" + assert out.shape == (3, 2) + assert_equal(out.toarray(), np.swapaxes(A, 1, 0)) + assert not out.has_canonical_format + + +def test_axis_swapaxes(): + A = coo_array([[2, 0], [3, 5]]) + with assert_raises(ValueError, match="Invalid axis"): + construct.swapaxes(A, -4, 0) + with assert_raises(ValueError, match="Invalid axis"): + construct.swapaxes(A, 0, -4) + with assert_raises(ValueError, match="Invalid axis"): + construct.swapaxes(A, 3, 0) + with assert_raises(ValueError, match="Invalid axis"): + construct.swapaxes(A, 0, 3) + with assert_raises(ValueError, match="Invalid axis"): + construct.swapaxes(A, 1.2, 1) + with assert_raises(ValueError, match="Invalid axis"): + construct.swapaxes(A, 1, 1.2) + assert_equal(construct.swapaxes(A, 0, 0).toarray(), A.toarray()) + for i in range(2): + assert_equal( + construct.swapaxes(A, i, 1 - i).toarray(), + construct.swapaxes(A, i - 2, -1 - i).toarray() + ) + + +def test_permute_dims(): + # Borrowed from Numpy tests. + x = np.array([8.375, 7.545, 8.828, 8.5, 1.757, 5.928, + 8.43, 7.78, 9.865, 5.878, 8.979, 4.732, + 3.012, 6.022, 5.095, 3.116, 5.238, 3.957, + 6.04, 9.63, 7.712, 3.382, 4.489, 6.479, + 7.189, 9.645, 5.395, 4.961, 9.894, 2.893, + 7.357, 9.828, 6.272, 3.758, 6.693, 0.993]) + npx = x.reshape(6, 6) + sX = coo_array(x).reshape(6, 6) + + sXpermuted = construct.permute_dims(sX, axes=(1, 0), copy=True) + sXtransposed = sX.transpose(axes=(1, 0)) + assert_equal(sXpermuted.toarray(), sXtransposed.toarray()) + assert_equal(sXpermuted[-1].toarray(), sX[:, -1].toarray()) + + npxx = npx.reshape(3, 2, 2, 3) + sXX = sX.reshape(3, 2, 2, 3) + sXXpermuted = construct.permute_dims(sXX, axes=(0, 2, 1, 3), copy=True) + assert_equal(sXXpermuted.shape, (3, 2, 2, 3)) + sXXtransposed = sXX.transpose(axes=(0, 2, 1, 3)) + assert_equal(sXXtransposed.shape, (3, 2, 2, 3)) + assert_equal(sXXpermuted.toarray(), sXXtransposed.toarray()) + # TODO change np.transpose to np.permute_dims when numpy 2 is min supported version + assert_equal(sXXpermuted.toarray(), np.transpose(npxx, axes=(0, 2, 1, 3))) + + +def test_3d_permute_dims(): + tgt = [[[0], [2], [0], [6]], [[1], [0], [5], [7]]] + x = np.array([[[0, 1], [2, 0], [0, 5], [6, 7]]]) + A = coo_array(x) + + out = construct.permute_dims(A, axes=(2, 1, 0)) + assert_equal(out.shape, (2, 4, 1)) + assert_equal(out.toarray(), tgt) + # TODO change np.transpose to np.permute_dims when numpy 2 is min supported version + assert_equal(out.toarray(), np.transpose(x, axes=(2, 1, 0))) + + +def test_canonical_format_permute_dims(): + A = coo_array([[2, 0, 1], [3, 5, 0]]) + # identity axes keep has_canoncial_format True after permute_dims. + assert construct.permute_dims(A, axes=(0, 1)).has_canonical_format is True + assert construct.permute_dims(A, axes=[0, 1]).has_canonical_format is True + # order changes set has_canonical_format to False + assert construct.permute_dims(A, axes=[1, 0]).has_canonical_format is False + + +def test_axis_permute_dims(): + A = coo_array([[2, 0, 1], [3, 5, 0]]) + + with assert_raises(ValueError, match="Incorrect number of axes"): + construct.permute_dims(A, axes=(2, 0, 1)) + with assert_raises(ValueError, match="duplicate value in axis"): + construct.permute_dims(A, axes=(0, 0)) + with assert_raises(TypeError, match="axis must be an integer/tuple"): + construct.permute_dims(A, axes={1, 0}) + + with assert_raises(ValueError, match="axis out of range"): + construct.permute_dims(A, axes=(-3, 0)) + with assert_raises(ValueError, match="axis out of range"): + construct.permute_dims(A, axes=(0, -3)) + with assert_raises(ValueError, match="axis out of range"): + construct.permute_dims(A, axes=(2, 0)) + with assert_raises(ValueError, match="axis out of range"): + construct.permute_dims(A, axes=(0, 2)) + with assert_raises(TypeError, match="axis must be an integer"): + construct.permute_dims(A, axes=(1.2, 0)) + + assert_equal( + construct.permute_dims(A, axes=(1, 0), copy=True).toarray(), + A.transpose(axes=(1, 0), copy=True).toarray() + ) + # use lists for axes + assert_equal( + construct.permute_dims(A, axes=[1, 0], copy=True).toarray(), + A.transpose(axes=[1, 0], copy=True).toarray() + ) + assert_equal( + construct.permute_dims(A, axes=None, copy=True).toarray(), + A.transpose(axes=(1, 0), copy=True).toarray() + ) + assert_equal( + construct.permute_dims(A, axes=(0, 1), copy=True).toarray(), A.toarray() + ) + + +@pytest.mark.parametrize("format", sparse_formats) +def test_sparse_format_permute_dims(format): + A = np.array([[2, 0, 1], [3, 5, 0]]) + SA = coo_array(A).asformat(format) + + out = construct.permute_dims(SA, axes=(1, 0)) + assert out.format == "coo" + assert out.shape == (3, 2) + # TODO change np.transpose to np.permute_dims when numpy 2 is min supported version + assert_equal(out.toarray(), np.transpose(A, axes=(1, 0))) + assert not out.has_canonical_format + + +def test_expand_dims(): + # Borrowed from Numpy tests. + x = np.array([8.375, 7.545, 8.828, 8.5, 1.757, 5.928, + 8.43, 7.78, 9.865, 5.878, 8.979, 4.732, + 3.012, 6.022, 5.095, 3.116, 5.238, 3.957, + 6.04, 9.63, 7.712, 3.382, 4.489, 6.479, + 7.189, 9.645, 5.395, 4.961, 9.894, 2.893, + 7.357, 9.828, 6.272, 3.758, 6.693, 0.993]) + npx = x.reshape(6, 6) + sX = coo_array(npx) + + npx_expanded = np.expand_dims(npx, axis=1) + sXexpanded = construct.expand_dims(sX, axis=1) + assert_equal(sXexpanded[-1].toarray(), sX[-1, np.newaxis, :].toarray()) + assert_equal(sXexpanded.toarray(), npx_expanded) + + npxx = npx.reshape(3, 2, 2, 3) + sXX = sX.reshape(3, 2, 2, 3) + + npxx_expanded = np.expand_dims(npxx, axis=2) + sXXexpanded = construct.expand_dims(sXX, axis=2) + assert_equal(sXXexpanded.shape, (3, 2, 1, 2, 3)) + assert_equal(sXXexpanded.toarray(), npxx_expanded) + + npxx_expanded = np.expand_dims(npxx, axis=-2) + sXXexpanded = construct.expand_dims(sXX, axis=-2) + assert_equal(sXXexpanded.shape, (3, 2, 2, 1, 3)) + assert_equal(sXXexpanded.toarray(), npxx_expanded) + + +def test_3d_expand_dims(): + tgt = [[[[0, 0], [2, 6]]], [[[1, 5], [0, 7]]]] + A = coo_array([[[0, 0], [2, 6]], [[1, 5], [0, 7]]]) + out = construct.expand_dims(A, axis=1) + assert_equal(out.toarray(), tgt) + + +@pytest.mark.parametrize("format", sparse_formats) +def test_sparse_format_expand_dims(format): + A = np.array([[2, 0], [3, 5]]) + SA = coo_array(A).asformat(format) + + out = construct.expand_dims(SA, axis=1) + assert out.format == "coo" + assert out.shape == (2, 1, 2) + assert_equal(out.toarray(), np.expand_dims(A, axis=1)) + assert SA.tocoo().has_canonical_format == out.has_canonical_format + + +def test_axis_expand_dims(): + A = coo_array([[2, 0], [3, 5]]) + with assert_raises(ValueError, match="Invalid axis"): + construct.expand_dims(A, axis=-4) + with assert_raises(ValueError, match="Invalid axis"): + construct.expand_dims(A, axis=3) + with assert_raises(ValueError, match="Invalid axis"): + construct.expand_dims(A, axis=1.2) + for i in range(3): + assert_equal( + construct.expand_dims(A, axis=i).toarray(), + construct.expand_dims(A, axis=i - 3).toarray() + ) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_coo.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_coo.py new file mode 100644 index 0000000000000000000000000000000000000000..ce009240ba1f1ca64644061497243d91e53248ce --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_coo.py @@ -0,0 +1,1387 @@ +import math +import warnings + +import numpy as np +from numpy.testing import assert_equal, assert_allclose +import pytest +from scipy.linalg import block_diag +from scipy.sparse import coo_array, random_array, SparseEfficiencyWarning +from scipy.sparse._csr import csr_array +from .._coo import _block_diag, _extract_block_diag + + +def test_shape_constructor(): + empty1d = coo_array((3,)) + assert empty1d.shape == (3,) + assert_equal(empty1d.toarray(), np.zeros((3,))) + + empty2d = coo_array((3, 2)) + assert empty2d.shape == (3, 2) + assert_equal(empty2d.toarray(), np.zeros((3, 2))) + + empty_nd = coo_array((2,3,4,6,7)) + assert empty_nd.shape == (2,3,4,6,7) + assert_equal(empty_nd.toarray(), np.zeros((2,3,4,6,7))) + + +def test_dense_constructor(): + # 1d + res1d = coo_array([1, 2, 3]) + assert res1d.shape == (3,) + assert_equal(res1d.toarray(), np.array([1, 2, 3])) + + # 2d + res2d = coo_array([[1, 2, 3], [4, 5, 6]]) + assert res2d.shape == (2, 3) + assert_equal(res2d.toarray(), np.array([[1, 2, 3], [4, 5, 6]])) + + # 4d + arr4d = np.array([[[[3, 7], [1, 0]], [[6, 5], [9, 2]]], + [[[4, 3], [2, 8]], [[7, 5], [1, 6]]], + [[[0, 9], [4, 3]], [[2, 1], [7, 8]]]]) + res4d = coo_array(arr4d) + assert res4d.shape == (3, 2, 2, 2) + assert_equal(res4d.toarray(), arr4d) + + # 9d + np.random.seed(12) + arr9d = np.random.randn(2,3,4,7,6,5,3,2,4) + res9d = coo_array(arr9d) + assert res9d.shape == (2,3,4,7,6,5,3,2,4) + assert_equal(res9d.toarray(), arr9d) + + # storing nan as element of sparse array + nan_3d = coo_array([[[1, np.nan]], [[3, 4]], [[5, 6]]]) + assert nan_3d.shape == (3, 1, 2) + assert_equal(nan_3d.toarray(), np.array([[[1, np.nan]], [[3, 4]], [[5, 6]]])) + + +def test_dense_constructor_with_shape(): + res1d = coo_array([1, 2, 3], shape=(3,)) + assert res1d.shape == (3,) + assert_equal(res1d.toarray(), np.array([1, 2, 3])) + + res2d = coo_array([[1, 2, 3], [4, 5, 6]], shape=(2, 3)) + assert res2d.shape == (2, 3) + assert_equal(res2d.toarray(), np.array([[1, 2, 3], [4, 5, 6]])) + + res3d = coo_array([[[3]], [[4]]], shape=(2, 1, 1)) + assert res3d.shape == (2, 1, 1) + assert_equal(res3d.toarray(), np.array([[[3]], [[4]]])) + + np.random.seed(12) + arr7d = np.random.randn(2,4,1,6,5,3,2) + res7d = coo_array((arr7d), shape=(2,4,1,6,5,3,2)) + assert res7d.shape == (2,4,1,6,5,3,2) + assert_equal(res7d.toarray(), arr7d) + + +def test_dense_constructor_with_inconsistent_shape(): + with pytest.raises(ValueError, match='inconsistent shapes'): + coo_array([1, 2, 3], shape=(4,)) + + with pytest.raises(ValueError, match='inconsistent shapes'): + coo_array([1, 2, 3], shape=(3, 1)) + + with pytest.raises(ValueError, match='inconsistent shapes'): + coo_array([[1, 2, 3]], shape=(3,)) + + with pytest.raises(ValueError, match='inconsistent shapes'): + coo_array([[[3]], [[4]]], shape=(1, 1, 1)) + + with pytest.raises(ValueError, + match='axis 0 index 2 exceeds matrix dimension 2'): + coo_array(([1], ([2],)), shape=(2,)) + + with pytest.raises(ValueError, + match='axis 1 index 3 exceeds matrix dimension 3'): + coo_array(([1,3], ([0, 1], [0, 3], [1, 1])), shape=(2, 3, 2)) + + with pytest.raises(ValueError, match='negative axis 0 index: -1'): + coo_array(([1], ([-1],))) + + with pytest.raises(ValueError, match='negative axis 2 index: -1'): + coo_array(([1], ([0], [2], [-1]))) + + +def test_1d_sparse_constructor(): + empty1d = coo_array((3,)) + res = coo_array(empty1d) + assert res.shape == (3,) + assert_equal(res.toarray(), np.zeros((3,))) + + +def test_1d_tuple_constructor(): + res = coo_array(([9,8], ([1,2],))) + assert res.shape == (3,) + assert_equal(res.toarray(), np.array([0, 9, 8])) + + +def test_1d_tuple_constructor_with_shape(): + res = coo_array(([9,8], ([1,2],)), shape=(4,)) + assert res.shape == (4,) + assert_equal(res.toarray(), np.array([0, 9, 8, 0])) + +def test_reshape_overflow(): + # see gh-22353 : new idx_dtype can need to be int64 instead of int32 + M, N = (1045507, 523266) + coords = (np.array([M - 1], dtype='int32'), np.array([N - 1], dtype='int32')) + A = coo_array(([3.3], coords), shape=(M, N)) + + # need new idx_dtype to not overflow + B = A.reshape((M * N, 1)) + assert B.coords[0].dtype == np.dtype('int64') + assert B.coords[0][0] == (M * N) - 1 + + # need idx_dtype to stay int32 if before and after can be int32 + C = A.reshape(N, M) + assert C.coords[0].dtype == np.dtype('int32') + assert C.coords[0][0] == N - 1 + +def test_reshape(): + arr1d = coo_array([1, 0, 3]) + assert arr1d.shape == (3,) + + col_vec = arr1d.reshape((3, 1)) + assert col_vec.shape == (3, 1) + assert_equal(col_vec.toarray(), np.array([[1], [0], [3]])) + + row_vec = arr1d.reshape((1, 3)) + assert row_vec.shape == (1, 3) + assert_equal(row_vec.toarray(), np.array([[1, 0, 3]])) + + # attempting invalid reshape + with pytest.raises(ValueError, match="cannot reshape array"): + arr1d.reshape((3,3)) + + # attempting reshape with a size 0 dimension + with pytest.raises(ValueError, match="cannot reshape array"): + arr1d.reshape((3,0)) + + arr2d = coo_array([[1, 2, 0], [0, 0, 3]]) + assert arr2d.shape == (2, 3) + + flat = arr2d.reshape((6,)) + assert flat.shape == (6,) + assert_equal(flat.toarray(), np.array([1, 2, 0, 0, 0, 3])) + + # 2d to 3d + to_3d_arr = arr2d.reshape((2, 3, 1)) + assert to_3d_arr.shape == (2, 3, 1) + assert_equal(to_3d_arr.toarray(), np.array([[[1], [2], [0]], [[0], [0], [3]]])) + + # attempting invalid reshape + with pytest.raises(ValueError, match="cannot reshape array"): + arr2d.reshape((1,3)) + + +def test_nnz(): + arr1d = coo_array([1, 0, 3]) + assert arr1d.shape == (3,) + assert arr1d.nnz == 2 + + arr2d = coo_array([[1, 2, 0], [0, 0, 3]]) + assert arr2d.shape == (2, 3) + assert arr2d.nnz == 3 + + +def test_transpose(): + arr1d = coo_array([1, 0, 3]).T + assert arr1d.shape == (3,) + assert_equal(arr1d.toarray(), np.array([1, 0, 3])) + + arr2d = coo_array([[1, 2, 0], [0, 0, 3]]).T + assert arr2d.shape == (3, 2) + assert_equal(arr2d.toarray(), np.array([[1, 0], [2, 0], [0, 3]])) + + +def test_transpose_with_axis(): + arr1d = coo_array([1, 0, 3]).transpose(axes=(0,)) + assert arr1d.shape == (3,) + assert_equal(arr1d.toarray(), np.array([1, 0, 3])) + + arr2d = coo_array([[1, 2, 0], [0, 0, 3]]).transpose(axes=(0, 1)) + assert arr2d.shape == (2, 3) + assert_equal(arr2d.toarray(), np.array([[1, 2, 0], [0, 0, 3]])) + + with pytest.raises(ValueError, match="axes don't match matrix dimensions"): + coo_array([1, 0, 3]).transpose(axes=(0, 1)) + + with pytest.raises(ValueError, match="repeated axis in transpose"): + coo_array([[1, 2, 0], [0, 0, 3]]).transpose(axes=(1, 1)) + + +def test_1d_row_and_col(): + res = coo_array([1, -2, -3]) + assert_equal(res.col, np.array([0, 1, 2])) + assert_equal(res.row, np.zeros_like(res.col)) + assert res.row.dtype == res.col.dtype + assert res.row.flags.writeable is False + + res.col = [1, 2, 3] + assert len(res.coords) == 1 + assert_equal(res.col, np.array([1, 2, 3])) + assert res.row.dtype == res.col.dtype + + with pytest.raises(ValueError, match="cannot set row attribute"): + res.row = [1, 2, 3] + + +def test_1d_toformats(): + res = coo_array([1, -2, -3]) + for f in [res.tobsr, res.tocsc, res.todia, res.tolil]: + with pytest.raises(ValueError, match='Cannot convert'): + f() + for f in [res.tocoo, res.tocsr, res.todok]: + assert_equal(f().toarray(), res.toarray()) + + +@pytest.mark.parametrize('arg', [1, 2, 4, 5, 8]) +def test_1d_resize(arg: int): + den = np.array([1, -2, -3]) + res = coo_array(den) + den.resize(arg, refcheck=False) + res.resize(arg) + assert res.shape == den.shape + assert_equal(res.toarray(), den) + + +@pytest.mark.parametrize('arg', zip([1, 2, 3, 4], [1, 2, 3, 4])) +def test_1d_to_2d_resize(arg: tuple[int, int]): + den = np.array([1, 0, 3]) + res = coo_array(den) + + den.resize(arg, refcheck=False) + res.resize(arg) + assert res.shape == den.shape + assert_equal(res.toarray(), den) + + +@pytest.mark.parametrize('arg', [1, 4, 6, 8]) +def test_2d_to_1d_resize(arg: int): + den = np.array([[1, 0, 3], [4, 0, 0]]) + res = coo_array(den) + den.resize(arg, refcheck=False) + res.resize(arg) + assert res.shape == den.shape + assert_equal(res.toarray(), den) + + +def test_sum_duplicates(): + # 1d case + arr1d = coo_array(([2, 2, 2], ([1, 0, 1],))) + assert arr1d.nnz == 3 + assert_equal(arr1d.toarray(), np.array([2, 4])) + arr1d.sum_duplicates() + assert arr1d.nnz == 2 + assert_equal(arr1d.toarray(), np.array([2, 4])) + + # 4d case + arr4d = coo_array(([2, 3, 7], ([1, 0, 1], [0, 2, 0], [1, 2, 1], [1, 0, 1]))) + assert arr4d.nnz == 3 + expected = np.array( # noqa: E501 + [[[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [3, 0]]], + [[[0, 0], [0, 9], [0, 0]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]] + ) + assert_equal(arr4d.toarray(), expected) + arr4d.sum_duplicates() + assert arr4d.nnz == 2 + assert_equal(arr4d.toarray(), expected) + + # when there are no duplicates + arr_nodups = coo_array(([1, 2, 3, 4], ([0, 1, 2, 3],))) + assert arr_nodups.nnz == 4 + arr_nodups.sum_duplicates() + assert arr_nodups.nnz == 4 + + +def test_eliminate_zeros(): + arr1d = coo_array(([0, 0, 1], ([1, 0, 1],))) + assert arr1d.nnz == 3 + assert arr1d.count_nonzero() == 1 + assert_equal(arr1d.toarray(), np.array([0, 1])) + arr1d.eliminate_zeros() + assert arr1d.nnz == 1 + assert arr1d.count_nonzero() == 1 + assert_equal(arr1d.toarray(), np.array([0, 1])) + assert_equal(arr1d.col, np.array([1])) + assert_equal(arr1d.row, np.array([0])) + + +def test_1d_add_dense(): + den_a = np.array([0, -2, -3, 0]) + den_b = np.array([0, 1, 2, 3]) + exp = den_a + den_b + res = coo_array(den_a) + den_b + assert type(res) is type(exp) + assert_equal(res, exp) + + +def test_1d_add_sparse(): + den_a = np.array([0, -2, -3, 0]) + den_b = np.array([0, 1, 2, 3]) + dense_sum = den_a + den_b + # this routes through CSR format + sparse_sum = coo_array(den_a) + coo_array(den_b) + assert_equal(dense_sum, sparse_sum.toarray()) + + +def test_1d_matmul_vector(): + den_a = np.array([0, -2, -3, 0]) + den_b = np.array([0, 1, 2, 3]) + exp = den_a @ den_b + res = coo_array(den_a) @ den_b + assert np.ndim(res) == 0 + assert_equal(res, exp) + + +def test_1d_matmul_multivector(): + den = np.array([0, -2, -3, 0]) + other = np.array([[0, 1, 2, 3], [3, 2, 1, 0]]).T + exp = den @ other + res = coo_array(den) @ other + assert type(res) is type(exp) + assert_equal(res, exp) + + +def test_2d_matmul_multivector(): + # sparse-sparse matmul + den = np.array([[0, 1, 2, 3], [3, 2, 1, 0]]) + arr2d = coo_array(den) + exp = den @ den.T + res = arr2d @ arr2d.T + assert_equal(res.toarray(), exp) + + # sparse-dense matmul for self.ndim = 2 + den = np.array([[0, 4, 3, 0, 5], [1, 0, 7, 3, 4]]) + arr2d = coo_array(den) + exp = den @ den.T + res = arr2d @ den.T + assert_equal(res, exp) + + # sparse-dense matmul for self.ndim = 1 + den_a = np.array([[0, 4, 3, 0, 5], [1, 0, 7, 3, 4]]) + den_b = np.array([0, 1, 6, 0, 4]) + arr1d = coo_array(den_b) + exp = den_b @ den_a.T + res = arr1d @ den_a.T + assert_equal(res, exp) + + # sparse-dense matmul for self.ndim = 1 and other.ndim = 2 + den_a = np.array([1, 0, 2]) + den_b = np.array([[3], [4], [0]]) + exp = den_a @ den_b + res = coo_array(den_a) @ den_b + assert_equal(res, exp) + res = coo_array(den_a) @ list(den_b) + assert_equal(res, exp) + + +def test_1d_diagonal(): + den = np.array([0, -2, -3, 0]) + with pytest.raises(ValueError, match='diagonal requires two dimensions'): + coo_array(den).diagonal() + + +@pytest.mark.parametrize('shape', [(0,), (7,), (4,7), (0,0,0), (3,6,2), + (1,0,3), (7,9,3,2,4,5)]) +def test_nd_todense(shape): + np.random.seed(12) + arr = np.random.randint(low=0, high=5, size=shape) + assert_equal(coo_array(arr).todense(), arr) + + +@pytest.mark.parametrize('shape', [(0,), (7,), (4,7), (0,0,0), (3,6,2), + (1,0,3), (7,9,3,2,4,5)]) +def test_nd_sparse_constructor(shape): + empty_arr = coo_array(shape) + res = coo_array(empty_arr) + assert res.shape == (shape) + assert_equal(res.toarray(), np.zeros(shape)) + + +@pytest.mark.parametrize('shape', [(0,), (7,), (4,7), (0,0,0), (3,6,2), + (1,0,3), (7,9,3,2,4,5)]) +def test_nd_tuple_constructor(shape): + np.random.seed(12) + arr = np.random.randn(*shape) + res = coo_array(arr) + assert res.shape == shape + assert_equal(res.toarray(), arr) + + +@pytest.mark.parametrize('shape', [(0,), (7,), (4,7), (0,0,0), (3,6,2), + (1,0,3), (7,9,3,2,4,5)]) +def test_nd_tuple_constructor_with_shape(shape): + np.random.seed(12) + arr = np.random.randn(*shape) + res = coo_array(arr, shape=shape) + assert res.shape == shape + assert_equal(res.toarray(), arr) + + +def test_tuple_constructor_for_dim_size_zero(): + # arrays with a dimension of size 0 + with pytest.raises(ValueError, match='exceeds matrix dimension'): + coo_array(([9, 8], ([1, 2], [1, 0], [2, 1])), shape=(3,4,0)) + + empty_arr = coo_array(([], ([], [], [], [])), shape=(4,0,2,3)) + assert_equal(empty_arr.toarray(), np.empty((4,0,2,3))) + + +@pytest.mark.parametrize(('shape', 'new_shape'), [((4,9,6,5), (3,6,15,4)), + ((4,9,6,5), (36,30)), + ((4,9,6,5), (1080,)), + ((4,9,6,5), (2,3,2,2,3,5,3)),]) +def test_nd_reshape(shape, new_shape): + # reshaping a 4d sparse array + rng = np.random.default_rng(23409823) + + arr4d = random_array(shape, density=0.6, rng=rng, dtype=int) + assert arr4d.shape == shape + den4d = arr4d.toarray() + + exp_arr = den4d.reshape(new_shape) + res_arr = arr4d.reshape(new_shape) + assert res_arr.shape == new_shape + assert_equal(res_arr.toarray(), exp_arr) + + +@pytest.mark.parametrize('shape', [(0,), (7,), (4,7), (0,0,0), (3,6,2), + (1,0,3), (7,9,3,2,4,5)]) +def test_nd_nnz(shape): + rng = np.random.default_rng(23409823) + + arr = random_array(shape, density=0.6, rng=rng, dtype=int) + assert arr.nnz == np.count_nonzero(arr.toarray()) + + +@pytest.mark.parametrize('shape', [(0,), (7,), (4,7), (0,0,0), (3,6,2), + (1,0,3), (7,9,3,2,4,5)]) +def test_nd_transpose(shape): + rng = np.random.default_rng(23409823) + + arr = random_array(shape, density=0.6, rng=rng, dtype=int) + exp_arr = arr.toarray().T + trans_arr = arr.transpose() + assert trans_arr.shape == shape[::-1] + assert_equal(exp_arr, trans_arr.toarray()) + + +@pytest.mark.parametrize(('shape', 'axis_perm'), [((3,), (0,)), + ((2,3), (0,1)), + ((2,4,3,6,5,3), (1,2,0,5,3,4)),]) +def test_nd_transpose_with_axis(shape, axis_perm): + rng = np.random.default_rng(23409823) + + arr = random_array(shape, density=0.6, rng=rng, dtype=int) + trans_arr = arr.transpose(axes=axis_perm) + assert_equal(trans_arr.toarray(), np.transpose(arr.toarray(), axes=axis_perm)) + + +def test_transpose_with_inconsistent_axis(): + with pytest.raises(ValueError, match="axes don't match matrix dimensions"): + coo_array([1, 0, 3]).transpose(axes=(0, 1)) + + with pytest.raises(ValueError, match="repeated axis in transpose"): + coo_array([[1, 2, 0], [0, 0, 3]]).transpose(axes=(1, 1)) + + +def test_nd_eliminate_zeros(): + # for 3d sparse arrays + arr3d = coo_array(([1, 0, 0, 4], ([0, 1, 1, 2], [0, 1, 0, 1], [1, 1, 2, 0]))) + assert arr3d.nnz == 4 + assert arr3d.count_nonzero() == 2 + assert_equal(arr3d.toarray(), np.array([[[0, 1, 0], [0, 0, 0]], + [[0, 0, 0], [0, 0, 0]], [[0, 0, 0], [4, 0, 0]]])) + arr3d.eliminate_zeros() + assert arr3d.nnz == 2 + assert arr3d.count_nonzero() == 2 + assert_equal(arr3d.toarray(), np.array([[[0, 1, 0], [0, 0, 0]], + [[0, 0, 0], [0, 0, 0]], [[0, 0, 0], [4, 0, 0]]])) + + # for a 5d sparse array when all elements of data array are 0 + coords = ([0, 1, 1, 2], [0, 1, 0, 1], [1, 1, 2, 0], [0, 0, 2, 3], [1, 0, 0, 2]) + arr5d = coo_array(([0, 0, 0, 0], coords)) + assert arr5d.nnz == 4 + assert arr5d.count_nonzero() == 0 + arr5d.eliminate_zeros() + assert arr5d.nnz == 0 + assert arr5d.count_nonzero() == 0 + assert_equal(arr5d.col, np.array([])) + assert_equal(arr5d.row, np.array([])) + assert_equal(arr5d.coords, ([], [], [], [], [])) + + +@pytest.mark.parametrize('shape', [(0,), (7,), (4,7), (0,0,0), (3,6,2), + (1,0,3), (7,9,3,2,4,5)]) +def test_nd_add_dense(shape): + rng = np.random.default_rng(23409823) + sp_x = random_array(shape, density=0.6, rng=rng, dtype=int) + sp_y = random_array(shape, density=0.6, rng=rng, dtype=int) + den_x, den_y = sp_x.toarray(), sp_y.toarray() + exp = den_x + den_y + res = sp_x + den_y + assert type(res) is type(exp) + assert_equal(res, exp) + + +@pytest.mark.parametrize('shape', [(0,), (7,), (4,7), (0,0,0), (3,6,2), + (1,0,3), (7,9,3,2,4,5)]) +def test_nd_add_sparse(shape): + rng = np.random.default_rng(23409823) + sp_x = random_array((shape), density=0.6, rng=rng, dtype=int) + sp_y = random_array((shape), density=0.6, rng=rng, dtype=int) + den_x, den_y = sp_x.toarray(), sp_y.toarray() + + dense_sum = den_x + den_y + sparse_sum = sp_x + sp_y + assert_equal(dense_sum, sparse_sum.toarray()) + + +def test_add_sparse_with_inf(): + # addition of sparse arrays with an inf element + den_a = np.array([[[0], [np.inf]], [[-3], [0]]]) + den_b = np.array([[[0], [1]], [[2], [3]]]) + dense_sum = den_a + den_b + sparse_sum = coo_array(den_a) + coo_array(den_b) + assert_equal(dense_sum, sparse_sum.toarray()) + + +@pytest.mark.parametrize(('a_shape', 'b_shape'), [((7,), (12,)), + ((6,4), (6,5)), + ((5,9,3,2), (9,5,2,3)),]) +def test_nd_add_sparse_with_inconsistent_shapes(a_shape, b_shape): + rng = np.random.default_rng(23409823) + + arr_a = random_array((a_shape), density=0.6, rng=rng, dtype=int) + arr_b = random_array((b_shape), density=0.6, rng=rng, dtype=int) + with pytest.raises(ValueError, match="inconsistent shapes"): + arr_a + arr_b + + +@pytest.mark.parametrize('shape', [(0,), (7,), (4,7), (0,0,0), (3,6,2), + (1,0,3), (7,9,3,2,4,5)]) +def test_nd_sub_dense(shape): + rng = np.random.default_rng(23409823) + sp_x = random_array(shape, density=0.6, rng=rng, dtype=int) + sp_y = random_array(shape, density=0.6, rng=rng, dtype=int) + den_x, den_y = sp_x.toarray(), sp_y.toarray() + exp = den_x - den_y + res = sp_x - den_y + assert type(res) is type(exp) + assert_equal(res, exp) + + +@pytest.mark.parametrize('shape', [(0,), (7,), (4,7), (0,0,0), (3,6,2), + (1,0,3), (7,9,3,2,4,5)]) +def test_nd_sub_sparse(shape): + rng = np.random.default_rng(23409823) + + sp_x = random_array(shape, density=0.6, rng=rng, dtype=int) + sp_y = random_array(shape, density=0.6, rng=rng, dtype=int) + den_x, den_y = sp_x.toarray(), sp_y.toarray() + + dense_sum = den_x - den_y + sparse_sum = sp_x - sp_y + assert_equal(dense_sum, sparse_sum.toarray()) + + +def test_nd_sub_sparse_with_nan(): + # subtraction of sparse arrays with a nan element + den_a = np.array([[[0], [np.nan]], [[-3], [0]]]) + den_b = np.array([[[0], [1]], [[2], [3]]]) + dense_sum = den_a - den_b + sparse_sum = coo_array(den_a) - coo_array(den_b) + assert_equal(dense_sum, sparse_sum.toarray()) + + +@pytest.mark.parametrize(('a_shape', 'b_shape'), [((7,), (12,)), + ((6,4), (6,5)), + ((5,9,3,2), (9,5,2,3)),]) +def test_nd_sub_sparse_with_inconsistent_shapes(a_shape, b_shape): + rng = np.random.default_rng(23409823) + + arr_a = random_array((a_shape), density=0.6, rng=rng, dtype=int) + arr_b = random_array((b_shape), density=0.6, rng=rng, dtype=int) + with pytest.raises(ValueError, match="inconsistent shapes"): + arr_a - arr_b + + +mat_vec_shapes = [ + ((2, 3, 4, 5), (5,)), + ((0, 0), (0,)), + ((2, 3, 4, 7, 8), (8,)), + ((4, 4, 2, 0), (0,)), + ((6, 5, 3, 2, 4), (4, 1)), + ((2,5), (5,)), + ((2, 5), (5, 1)), + ((3,), (3, 1)), + ((4,), (4,)) +] +@pytest.mark.parametrize(('mat_shape', 'vec_shape'), mat_vec_shapes) +def test_nd_matmul_vector(mat_shape, vec_shape): + rng = np.random.default_rng(23409823) + + sp_x = random_array(mat_shape, density=0.6, rng=rng, dtype=int) + sp_y = random_array(vec_shape, density=0.6, rng=rng, dtype=int) + den_x, den_y = sp_x.toarray(), sp_y.toarray() + exp = den_x @ den_y + res = sp_x @ den_y + assert_equal(res,exp) + res = sp_x @ list(den_y) + assert_equal(res,exp) + + +mat_mat_shapes = [ + ((2, 3, 4, 5), (2, 3, 5, 7)), + ((0, 0), (0,)), + ((4, 4, 2, 0), (0,)), + ((7, 8, 3), (3,)), + ((7, 8, 3), (3, 1)), + ((6, 5, 3, 2, 4), (4, 3)), + ((1, 3, 2, 4), (6, 5, 1, 4, 3)), + ((6, 1, 1, 2, 4), (1, 3, 4, 3)), + ((4,), (2, 4, 3)), + ((3,), (5, 6, 7, 3, 2)), + ((4,), (4, 3)), + ((2, 5), (5, 1)), +] +@pytest.mark.parametrize(('mat_shape1', 'mat_shape2'), mat_mat_shapes) +def test_nd_matmul(mat_shape1, mat_shape2): + rng = np.random.default_rng(23409823) + + sp_x = random_array(mat_shape1, density=0.6, random_state=rng, dtype=int) + sp_y = random_array(mat_shape2, density=0.6, random_state=rng, dtype=int) + den_x, den_y = sp_x.toarray(), sp_y.toarray() + exp = den_x @ den_y + # sparse-sparse + res = sp_x @ sp_y + assert_equal(res.toarray(), exp) + # sparse-dense + res = sp_x @ den_y + assert_equal(res, exp) + res = sp_x @ list(den_y) + assert_equal(res, exp) + + # dense-sparse + res = den_x @ sp_y + assert_equal(res, exp) + + +def test_nd_matmul_sparse_with_inconsistent_arrays(): + rng = np.random.default_rng(23409823) + + sp_x = random_array((4,5,7,6,3), density=0.6, random_state=rng, dtype=int) + sp_y = random_array((1,5,3,2,5), density=0.6, random_state=rng, dtype=int) + with pytest.raises(ValueError, match="matmul: dimension mismatch with signature"): + sp_x @ sp_y + with pytest.raises(ValueError, match="matmul: dimension mismatch with signature"): + sp_x @ (sp_y.toarray()) + + sp_z = random_array((1,5,3,2), density=0.6, random_state=rng, dtype=int) + with pytest.raises(ValueError, match="Batch dimensions are not broadcastable"): + sp_x @ sp_z + with pytest.raises(ValueError, match="Batch dimensions are not broadcastable"): + sp_x @ (sp_z.toarray()) + + +def test_dot_1d_1d(): # 1-D inner product + a = coo_array([1,2,3]) + b = coo_array([4,5,6]) + exp = np.dot(a.toarray(), b.toarray()) + res = a.dot(b) + assert_equal(res, exp) + res = a.dot(b.toarray()) + assert_equal(res, exp) + + +def test_dot_sparse_scalar(): + a = coo_array([[1, 2], [3, 4], [5, 6]]) + b = 3 + res = a.dot(b) + exp = np.dot(a.toarray(), b) + assert_equal(res.toarray(), exp) + + +def test_dot_with_inconsistent_shapes(): + arr_a = coo_array([[[1, 2]], [[3, 4]]]) + arr_b = coo_array([4, 5, 6]) + with pytest.raises(ValueError, match="not aligned for n-D dot"): + arr_a.dot(arr_b) + + +def test_matmul_dot_not_implemented(): + arr_a = coo_array([[1, 2], [3, 4]]) + with pytest.raises(TypeError, match="argument not supported type"): + arr_a.dot(None) + with pytest.raises(TypeError, match="arg not supported type"): + arr_a.tensordot(None) + with pytest.raises(TypeError, match="unsupported operand type"): + arr_a @ None + with pytest.raises(TypeError, match="unsupported operand type"): + None @ arr_a + + +dot_shapes = [ + ((3,3), (3,3)), ((4,6), (6,7)), ((1,4), (4,1)), # matrix multiplication 2-D + ((3,2,4,7), (7,)), ((5,), (6,3,5,2)), # dot of n-D and 1-D arrays + ((3,2,4,7), (7,1)), ((1,5,), (6,3,5,2)), + ((4,6), (3,2,6,4)), ((2,8,7), (4,5,7,7,2)), # dot of n-D and m-D arrays + ((4,5,7,6), (3,2,6,4)), +] +@pytest.mark.parametrize(('a_shape', 'b_shape'), dot_shapes) +def test_dot_nd(a_shape, b_shape): + rng = np.random.default_rng(23409823) + + arr_a = random_array(a_shape, density=0.6, random_state=rng, dtype=int) + arr_b = random_array(b_shape, density=0.6, random_state=rng, dtype=int) + + exp = np.dot(arr_a.toarray(), arr_b.toarray()) + # sparse-dense + res = arr_a.dot(arr_b.toarray()) + assert_equal(res, exp) + res = arr_a.dot(list(arr_b.toarray())) + assert_equal(res, exp) + # sparse-sparse + res = arr_a.dot(arr_b) + assert_equal(res.toarray(), exp) + + +tensordot_shapes_and_axes = [ + ((4,6), (6,7), ([1], [0])), + ((3,2,4,7), (7,), ([3], [0])), + ((5,), (6,3,5,2), ([0], [2])), + ((4,5,7,6), (3,2,6,4), ([0, 3], [3, 2])), + ((2,8,7), (4,5,7,8,2), ([0, 1, 2], [4, 3, 2])), + ((4,5,3,2,6), (3,2,6,7,8), 3), + ((4,5,7), (7,3,7), 1), + ((2,3,4), (2,3,4), ([0, 1, 2], [0, 1, 2])), +] +@pytest.mark.parametrize(('a_shape', 'b_shape', 'axes'), tensordot_shapes_and_axes) +def test_tensordot(a_shape, b_shape, axes): + rng = np.random.default_rng(23409823) + + arr_a = random_array(a_shape, density=0.6, random_state=rng, dtype=int) + arr_b = random_array(b_shape, density=0.6, random_state=rng, dtype=int) + + exp = np.tensordot(arr_a.toarray(), arr_b.toarray(), axes=axes) + + # sparse-dense + res = arr_a.tensordot(arr_b.toarray(), axes=axes) + assert_equal(res, exp) + res = arr_a.tensordot(list(arr_b.toarray()), axes=axes) + assert_equal(res, exp) + + # sparse-sparse + res = arr_a.tensordot(arr_b, axes=axes) + if type(res) is coo_array: + assert_equal(res.toarray(), exp) + else: + assert_equal(res, exp) + + +def test_tensordot_with_invalid_args(): + rng = np.random.default_rng(23409823) + + arr_a = random_array((3,4,5), density=0.6, random_state=rng, dtype=int) + arr_b = random_array((3,4,6), density=0.6, random_state=rng, dtype=int) + + axes = ([2], [2]) # sizes of 2nd axes of both shapes do not match + with pytest.raises(ValueError, match="sizes of the corresponding axes must match"): + arr_a.tensordot(arr_b, axes=axes) + + arr_a = random_array((5,4,2,3,7), density=0.6, random_state=rng, dtype=int) + arr_b = random_array((4,6,3,2), density=0.6, random_state=rng, dtype=int) + + axes = ([2,0,1], [1,3]) # lists have different lengths + with pytest.raises(ValueError, match="axes lists/tuples must be of the" + " same length"): + arr_a.tensordot(arr_b, axes=axes) + + +@pytest.mark.parametrize(('actual_shape', 'broadcast_shape'), + [((1,3,5,4), (2,3,5,4)), ((2,1,5,4), (6,2,3,5,4)), + ((1,1,7,8,9), (4,5,6,7,8,9)), ((1,3), (4,5,3)), + ((7,8,1), (7,8,5)), ((3,1), (3,4)), ((1,), (5,)), + ((1,1,1), (4,5,6)), ((1,3,1,5,4), (8,2,3,9,5,4)),]) +def test_broadcast_to(actual_shape, broadcast_shape): + rng = np.random.default_rng(23409823) + + arr = random_array(actual_shape, density=0.6, random_state=rng, dtype=int) + res = arr._broadcast_to(broadcast_shape) + exp = np.broadcast_to(arr.toarray(), broadcast_shape) + assert_equal(res.toarray(), exp) + + +@pytest.mark.parametrize(('shape'), [(4,5,6,7,8), (6,4), + (5,9,3,2), (9,5,2,3,4),]) +def test_block_diag(shape): + rng = np.random.default_rng(23409823) + sp_x = random_array(shape, density=0.6, random_state=rng, dtype=int) + den_x = sp_x.toarray() + + # converting n-d numpy array to an array of slices of 2-D matrices, + # to pass as argument into scipy.linalg.block_diag + num_slices = int(np.prod(den_x.shape[:-2])) + reshaped_array = den_x.reshape((num_slices,) + den_x.shape[-2:]) + matrices = [reshaped_array[i, :, :] for i in range(num_slices)] + exp = block_diag(*matrices) + + res = _block_diag(sp_x) + + assert_equal(res.toarray(), exp) + + +@pytest.mark.parametrize(('shape'), [(4,5,6,7,8), (6,4), + (5,9,3,2), (9,5,2,3,4),]) +def test_extract_block_diag(shape): + rng = np.random.default_rng(23409823) + sp_x = random_array(shape, density=0.6, random_state=rng, dtype=int) + res = _extract_block_diag(_block_diag(sp_x), shape) + + assert_equal(res.toarray(), sp_x.toarray()) + + +add_sub_shapes = [ + ((3,4), (3,4)), ((3,4,6), (3,4,6)), ((3,7,5), (3,7,5)) +] +@pytest.mark.parametrize(('a_shape', 'b_shape'), add_sub_shapes) +def test_add_no_broadcasting(a_shape, b_shape): + rng = np.random.default_rng(23409823) + a = random_array(a_shape, density=0.6, random_state=rng, dtype=int) + b = random_array(b_shape, density=0.6, random_state=rng, dtype=int) + + res = a + b + exp = np.add(a.toarray(), b.toarray()) + assert_equal(res.toarray(), exp) + res = a + b.toarray() + assert_equal(res, exp) + + +@pytest.mark.parametrize(('a_shape', 'b_shape'), add_sub_shapes) +def test_sub_no_broadcasting(a_shape, b_shape): + rng = np.random.default_rng(23409823) + a = random_array(a_shape, density=0.6, random_state=rng, dtype=int) + b = random_array(b_shape, density=0.6, random_state=rng, dtype=int) + + res = a - b + exp = np.subtract(a.toarray(), b.toarray()) + assert_equal(res.toarray(), exp) + + res = a - b.toarray() + assert_equal(res, exp) + + +argmax_argmin_shapes_axis = [ + ((3,), None), ((3,), 0), + ((4,6), 1), ((7,3), 0), ((3,5), None), + ((2,8,7), 2), ((2,8,7), 0), + ((2,0), 0), ((3,0,0,2), 0), + ((3,2,4,7), None), ((3,2,4,7), 1), ((3,2,4,7), 0), ((3,2,4,7), 2), + ((3,2,4,7), -2), ((4,5,7,8,2), 4), ((4,5,7,8,2), -3), +] + + +@pytest.mark.parametrize(('shape', 'axis'), argmax_argmin_shapes_axis) +def test_argmax_argmin(shape, axis): + rng = np.random.default_rng(23409823) + a = random_array(shape, density=0.6, random_state=rng, dtype=int) + + res = a.argmax(axis=axis) + exp = np.argmax(a.toarray(), axis=axis) + assert_equal(res, exp) + + res = a.argmin(axis=axis) + exp = np.argmin(a.toarray(), axis=axis) + assert_equal(res, exp) + + +max_min_shapes_axis = [ + ((3,), None), ((3,), 0), + ((4,6), 1), ((7,3), 0), ((3,5), None), + ((2,8,7), 2), ((2,8,7), 0), + ((3,2,4,7), None), ((3,2,4,7), 1), ((3,2,4,7), 0), ((3,2,4,7), 2), + ((4,5,7,8,2), 4), ((4,5,8,1), 3), ((4,6), (0,)), ((4,6), (0,1)), + ((3,0,2), 2), ((3,0,2), (0,2)), ((3,0), 0), + ((3,7,8,5), (0,1)), ((3,7,8,5), (2,1)), ((3,7,8,5), (2,0)), + ((3,7,8,5), (0,-2)), ((3,7,8,5), (-1,2)), ((3,7,8,5), (3)), + ((3,7,8,5), (0,1,2)), ((3,7,8,5), (0,1,2,3)), +] +@pytest.mark.parametrize(('shape', 'axis'), max_min_shapes_axis) +def test_min_max(shape, axis): + rng = np.random.default_rng(23409823) + a = random_array(shape, density=0.6, random_state=rng, dtype=int) + + res_min = a.min(axis=axis) + exp_min = np.min(a.toarray(), axis=axis) + res_max = a.max(axis=axis) + exp_max = np.max(a.toarray(), axis=axis) + res_nanmin = a.nanmin(axis=axis) + exp_nanmin = np.nanmin(a.toarray(), axis=axis) + res_nanmax = a.nanmax(axis=axis) + exp_nanmax = np.nanmax(a.toarray(), axis=axis) + + for res, exp in [(res_min, exp_min), (res_max, exp_max), + (res_nanmin, exp_nanmin), (res_nanmax, exp_nanmax)]: + if np.issubdtype(type(res), np.number): + assert_equal(res, exp) + else: + assert_equal(res.toarray(), exp) + + +def test_min_max_full(): + for a in (coo_array([[[1, 2, 3, 4]]]), coo_array([[1, 2, 3, 4]])): + assert a.min() == 1 + assert (-a).max() == -1 + + +sum_mean_params = [ + ((3,), None, None), ((3,), 0, None), + ((4,6), 1, None), ((7,3), 0, None), ((3,5), None, None), + ((2,8,7), 2, None), ((2,8,7), 0, np.zeros((8,7))), + ((3,2,4,7), None, None), ((3,2,4,7), 1, np.zeros((3,4,7))), + ((3,2,4,7), 0, None), ((4,5,7,8,2), 4, None), + ((4,5,8,1), 3, None), ((4,6), (0,), None), ((4,6), (0,1), None), + ((3,0,2), 2, None), ((3,0,2), (0,2), None), ((3,0), 0, None), + ((3,7,8,5), (0,1), np.zeros((8,5))), ((3,7,8,5), (2,1), None), + ((3,7,8,5), (0,-2), None), ((3,7,8,5), (-1,2), np.zeros((3,7))), + ((3,7,8,5), (3), None), ((3,7,8,5), (0,1,2), np.zeros((5,))), + ((3,7,8,5), (0,1,2,3), None), +] +@pytest.mark.parametrize(('shape', 'axis', 'out'), sum_mean_params) +def test_sum(shape, axis, out): + rng = np.random.default_rng(23409823) + a = random_array(shape, density=0.6, random_state=rng, dtype=int) + + res = a.sum(axis=axis, out=out) + exp = np.sum(a.toarray(), axis=axis) + assert_equal(res, exp) + if out is not None: + assert_equal(out, exp) + assert id(res) == id(out) + + +@pytest.mark.parametrize(('shape', 'axis', 'out'), sum_mean_params) +def test_mean(shape, axis, out): + rng = np.random.default_rng(23409823) + a = random_array(shape, density=0.6, random_state=rng, dtype=int) + + res = a.mean(axis=axis, out=out) + exp = np.mean(a.toarray(), axis=axis) + assert_allclose(res, exp) + if out is not None: + assert id(res) == id(out) + assert_allclose(out, exp) + + +def test_pow_abs_round(): + rng = np.random.default_rng(23409823) + a = random_array((3,6,5,2,4), density=0.6, random_state=rng, dtype=int) + assert_allclose((a**3).toarray(), np.power(a.toarray(), 3)) + assert_allclose((a**7).toarray(), np.power(a.toarray(), 7)) + assert_allclose(round(a).toarray(), np.round(a.toarray())) + assert_allclose(abs(a).toarray(), np.abs(a.toarray())) + + +#bitwise_op_and_compare_broadcast_shapes = [ +# ((3,4), (3,4)), ((1,4), (2,1)), ((3,5), (1,)), ((1,), (7,8)), +# ((3,4,6), (3,4,6)), ((4,3), (2,1,3)), ((2,1,3), (4,3)), +# ((3,5,4), (1,)), ((1,), (7,8,4)), ((16,1,6), (2,6)), ((3,7,5), (3,7,5)), +# ((16,2,6), (1,2,6)), ((7,8), (5,7,8)), ((4,5,1), (5,1)), +# ((6,8,3), (4,1,1,3)), ((1,1,1), (3,4,2)), ((3,4,2), (1,1,1,1,1)), +bitwise_op_and_compare_shapes = [ + ((3,4), (3,4)), ((3,4,6), (3,4,6)), ((3,7,5), (3,7,5)), +] +@pytest.mark.parametrize(('a_shape', 'b_shape'), bitwise_op_and_compare_shapes) +def test_boolean_comparisons(a_shape, b_shape): + rng = np.random.default_rng(23409823) + a = random_array(a_shape, density=0.6, random_state=rng, dtype=int) + b = random_array(b_shape, density=0.6, random_state=rng, dtype=int) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + assert_equal((a==b).toarray(), a.toarray()==b.toarray()) + assert_equal((a!=b).toarray(), a.toarray()!=b.toarray()) + assert_equal((a>=b).toarray(), a.toarray()>=b.toarray()) + assert_equal((a<=b).toarray(), a.toarray()<=b.toarray()) + assert_equal((a>b).toarray(), a.toarray()>b.toarray()) + assert_equal((a=b).toarray(), np.bitwise_not((ab).toarray())) + + +def test_boolean_comparisons_with_scalar(): + rng = np.random.default_rng(23409823) + a = random_array((5,4,8,7), density=0.6, random_state=rng, dtype=int) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + assert_equal((a==0).toarray(), a.toarray()==0) + assert_equal((a!=0).toarray(), a.toarray()!=0) + assert_equal((a>=1).toarray(), a.toarray()>=1) + assert_equal((a<=1).toarray(), a.toarray()<=1) + assert_equal((a>0).toarray(), a.toarray()>0) + assert_equal((a<0).toarray(), a.toarray()<0) + + +@pytest.mark.parametrize(('a_shape', 'b_shape'), bitwise_op_and_compare_shapes) +def test_multiply(a_shape, b_shape): + rng = np.random.default_rng(23409823) + a = random_array(a_shape, density=0.6, random_state=rng, dtype=int) + b = random_array(b_shape, density=0.6, random_state=rng, dtype=int) + res = a * b + exp = np.multiply(a.toarray(), b.toarray()) + assert_equal(res.toarray(), exp) + + +def test_multiply_with_scalar(): + rng = np.random.default_rng(23409823) + a = random_array((3,5,4), density=0.6, random_state=rng, dtype=int) + res = a * 7 + exp = np.multiply(a.toarray(), 7) + assert_equal(res.toarray(), exp) + + +@pytest.mark.parametrize(('a_shape', 'b_shape'), bitwise_op_and_compare_shapes) +def test_divide(a_shape, b_shape): + rng = np.random.default_rng(23409823) + a = random_array(a_shape, density=0.6, random_state=rng, dtype=int) + b = np.arange(1, 1 + math.prod(b_shape)).reshape(b_shape) + res = a / b + exp = a.toarray() / b + assert_allclose(res.toarray(), exp) + + res = a / b + assert_allclose(res.toarray(), exp) + + +def test_divide_with_scalar(): + rng = np.random.default_rng(23409823) + a = random_array((3,5,4), density=0.6, random_state=rng, dtype=int) + res = a / 7 + exp = a.toarray() / 7 + assert_allclose(res.toarray(), exp) + + +@pytest.mark.parametrize(('a_shape', 'b_shape'), bitwise_op_and_compare_shapes) +def test_maximum(a_shape, b_shape): + rng = np.random.default_rng(23409823) + a = random_array(a_shape, density=0.6, random_state=rng, dtype=int) + b = random_array(b_shape, density=0.6, random_state=rng, dtype=int) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + res = a.maximum(b) + exp = np.maximum(a.toarray(), b.toarray()) + assert_equal(res.toarray(), exp) + + +@pytest.mark.parametrize(('a_shape', 'b_shape'), bitwise_op_and_compare_shapes) +def test_minimum(a_shape, b_shape): + rng = np.random.default_rng(23409823) + a = random_array(a_shape, density=0.6, random_state=rng, dtype=int) + b = random_array(b_shape, density=0.6, random_state=rng, dtype=int) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + res = a.minimum(b) + exp = np.minimum(a.toarray(), b.toarray()) + assert_equal(res.toarray(), exp) + + +def test_maximum_with_scalar(): + a = coo_array([0,1,6]) + b = coo_array([[15, 0], [14, 5], [0, -12]]) + c = coo_array([[[[3,0], [2,4]], [[8,9], [-3,12]]], + [[[5,2], [3,0]], [[0,7], [0,-6]]]]) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + assert_equal(a.maximum(5).toarray(), np.maximum(a.toarray(), 5)) + assert_equal(b.maximum(9).toarray(), np.maximum(b.toarray(), 9)) + assert_equal(c.maximum(5).toarray(), np.maximum(c.toarray(), 5)) + + +def test_minimum_with_scalar(): + a = coo_array([0,1,6]) + b = coo_array([[15, 0], [14, 5], [0, -12]]) + c = coo_array([[[[3,0], [2,4]], [[8,9], [-3,12]]], + [[[5,2], [3,0]], [[0,7], [0,-6]]]]) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SparseEfficiencyWarning) + assert_equal(a.minimum(5).toarray(), np.minimum(a.toarray(), 5)) + assert_equal(b.minimum(9).toarray(), np.minimum(b.toarray(), 9)) + assert_equal(c.minimum(5).toarray(), np.minimum(c.toarray(), 5)) + + +def test_1d_coo_get(): + B = coo_array(np.arange(9)) + + assert B[0] == 0 + assert B[4] == 4 + + assert_equal(B[1:3].toarray(), B.toarray()[1:3]) + assert_equal(B[:3].toarray(), B.toarray()[:3]) + assert_equal(B[1:].toarray(), B.toarray()[1:]) + assert_equal(B[1:5:2].toarray(), B.toarray()[1:5:2]) + + assert_equal(B[[1, 3, 4]].toarray(), B.toarray()[[1, 3, 4]]) + assert_equal(B[[3, 4, 1]].toarray(), B.toarray()[[3, 4, 1]]) + + +def test_2d_coo_get(): + B = coo_array(np.arange(4 * 5).reshape((4, 5))) + + assert B[0, 0] == 0 + assert B[3, 4] == 19 + + assert_equal(B[1:3, 0].toarray(), B.toarray()[1:3, 0]) + assert_equal(B[2, 1:3].toarray(), B.toarray()[2, 1:3]) + assert_equal(B[:2, 1:5:3].toarray(), B.toarray()[:2, 1:5:3]) + + assert_equal(B[[1, 3], 0].toarray(), B.toarray()[[1,3], 0]) + assert_equal(B[2:, [1, 3]].toarray(), B.toarray()[2:, [1,3]]) + assert_equal(B[np.array([1, 3]), 0].toarray(), B.toarray()[[1,3], 0]) + assert_equal(B[2:, np.array([1, 3])].toarray(), B.toarray()[2:, [1,3]]) + + assert_equal(B[:, 0].toarray(), B.toarray()[:, 0]) + assert_equal(B[0, :].toarray(), B.toarray()[0, :]) + + +def test_3d_coo_get(): + A = coo_array(np.arange(4 * 5 * 6).reshape((4, 5, 6))) + assert A[0, 0, 0] == 0 + assert A[3, 4, 5] == 119 + + assert_equal(A[0, 1:3, 0].toarray(), A.toarray()[0, 1:3, 0]) + assert_equal(A[0, 1:3, 3].toarray(), A.toarray()[0, 1:3, 3]) + assert_equal(A[:3, 1:5:2, 2:].toarray(), A.toarray()[:3, 1:5:2, 2:]) + + assert_equal(A[[1, 3], 0, 0].toarray(), A.toarray()[[1, 3], 0, 0]) + assert_equal(A[:2, 1:3, [1, 3]].toarray(), A.toarray()[:2, 1:3, [1, 3]]) + + assert_equal(A[0, :, 0].toarray(), A.toarray()[0, :, 0]) + assert_equal(A[:, :, 0].toarray(), A.toarray()[:, :, 0]) + + +def test_newaxis_get(): + A = coo_array(np.arange(4 * 5 * 6).reshape((4, 5, 6))) + D = A.toarray() + assert_equal(A[:5, 3:, 1].toarray(), D[:5, 3:, 1]) + assert_equal(A[None, :5, 1:3, None, 1].toarray(), D[None, :5, 1:3, None, 1]) + assert_equal(A[None, :5, 3:, 1, None].toarray(), D[None, :5, 3:, 1, None]) + assert_equal(A[None, :5, ..., None].toarray(), D[None, :5, ..., None]) + + +def test_newaxis_set(): + D = np.arange(4 * 5 * 6).reshape((4, 5, 6)) + A = coo_array(D) + + A[None, 3:, 1] = D[None, 3:, 1] = 5 + assert_equal(A.toarray(), D) + A[3:, 1, None] = D[3:, 1, None] = 7 + assert_equal(A.toarray(), D) + A[3:, None, 1] = D[3:, None, 1] = 3 + assert_equal(A.toarray(), D) + + +def test_1d_coo_set(): + D = np.arange(9) + A = coo_array(D) + + A[0] = D[0] = -1 + assert_equal(A.toarray(), D) + A[4] = D[4] = -2 + assert_equal(A.toarray(), D) + + A[1:3] = D[1:3] = [-2, -3] + assert_equal(A.toarray(), D) + A[:3] = D[:3] = [-7, -8, -9] + assert_equal(A.toarray(), D) + A[1:] = D[1:] = -D[1:] + assert_equal(A.toarray(), D) + A[1:5:2] = D[1:5:2] = -D[1:5:2] + assert_equal(A.toarray(), D) + + A[[1, 3, 4]] = D[[1, 3, 4]] = -D[[1, 3, 4]] + assert_equal(A.toarray(), D) + A[[3, 4, 1]] = D[[3, 4, 1]] = -D[[1, 2, 3]] + assert_equal(A.toarray(), D) + + +D = np.arange(4 * 5).reshape((4, 5)) +A = coo_array(D) + +keys = [ + # all int + (1, 3), + (-1, -3), + # slices and ints + (slice(1, 3, None), 0), + (2, slice(1, 3, None)), + (slice(1, 3, None), slice(1, 5, 3)), + (slice(None, None, -1), 2), + (1, slice(None)), + (Ellipsis,), + # array indexing + ([1, 3], 0), + (2, [1, 2]), + (np.array([1, 3]), slice(1, None)), + (slice(2), np.array([1, 2, 3])), + # fancy array indexing + (np.array([1, 3]), np.array([0, 2])), +] + +@pytest.mark.parametrize(["A", "D", "idx"], [(A, D, idx) for idx in keys]) +@pytest.mark.thread_unsafe +def test_2d_coo_set(A, D, idx): + D[idx] = A[idx] = -D[idx] + assert_equal(A.toarray(), D) + + +D = np.arange(4 * 5 * 6).reshape((4, 5, 6)) +A = coo_array(D) + +keys = [ + # all ints + (0, 0, 0), + (3, -4, 5), + # slices and ints + (0, slice(1, 3), 0), + (slice(3, None), 3, slice(2)), + (slice(2), slice(1, 5, 2), slice(1, None)), + (slice(None, None, -1), slice(None), slice(1, 5, 2)), + (Ellipsis), + # array indexing + (2, [1, 2], slice(3)), + (np.array([1, 3]), slice(1, None), 0), + (np.array([1, 3]), slice(1, None), [0]), + # fancy array indexing + (np.array([1, 3]), slice(1, None), np.array([2, 4])), + (2, np.array([1, 3]), np.array([2, 4])), + (np.array([1, 3]), np.array([2, 4]), 1), + (np.array([1, 3]), np.array([2, 4]), [2]), +] + +@pytest.mark.parametrize(["A", "D", "idx"], [(A, D, idx) for idx in keys]) +@pytest.mark.thread_unsafe +def test_3d_coo_set(A, D, idx): + D[idx] = A[idx] = -99 + assert_equal(A.toarray(), D) + + +@pytest.mark.parametrize( + "scalar_container", + [lambda x: csr_array(np.array([[x]])), np.array, lambda x: x], + ids=["sparse", "dense", "scalar"], +) +@pytest.mark.thread_unsafe(reason="fails in parallel") +def test_3d_coo_singleton(scalar_container): + A[(0, 0, 0)] = scalar_container(-99) + D[(0, 0, 0)] = -99 + assert_equal(A.toarray(), D) + + +#D = np.arange(4 * 5 * 6 * 4 * 6).reshape((4, 5, 6, 4, 6)) +D = np.arange(4 * 6 * 6 * 3 * 4).reshape((4, 6, 6, 3, 4)) +A = coo_array(D) + +keys = [ + # multidimensional + ("all-ints", (1, 2, 1)), + ("ellipsis-first", (..., 0)), + ("ellipsis-last", (1, ...)), + ("ellipsis-middle", (1, ..., 0)), + # slices and ints + ("split-ints", (slice(None, 4, None), 2, 1, slice(None, None, None), 1)), + ("contiguous-ints-last", (slice(4, None, None), slice(None, None, None), 2, 1, 1)), + ("contiguous-ints-first", (2, 1, 1, slice(4, None, None), slice(None, None, None))), + ("empty-slice", (slice(4, 4, None), slice(None, None, None), 2, 1, 1)), + # slices and arrays and ints + ("split-2d-arrays-and-ints", + (slice(None, 4, None), [[2, 1, 1], [2, 1, 2]], [[2, 1, 0], [3, 4, 0]], + slice(None, None, None), 0) + ), + ("contiguous-2d-arrays-and-ints", + (slice(None, 4, None), [[2, 1, 0], [2, 1, 2]], [[2, 1, 0], [3, 4, 0]], + 1, slice(None, None, None)) + ), + ("split-1d-arrays-and-ints", + (slice(None, 4, None), [2, 1, 0], [2, 1, 0], slice(None, None, None), 1) + ), + ("split-ints-broadcast-arrays-slice-step-not-1", + (0, slice(1, 4, 2), 1, [[2, 1, 0]], [[2], [1], [0]]) + ), + ("contiguous-broadcast-arrays", + (slice(None, 3, None), slice(1, 4, 2), 1, [[2, 1, 0]], [[2], [1], [0]]) + ), + ("contiguous-arrays-first", + ([[2, 1, 0]], [[2], [1], [0]], 0, slice(1, 4, 2), slice(None, 3, None)) + ), + ("split-arrays-some-first-some-last", + ([[2, 1, 0]], slice(1, 4, 2), slice(None, 3, None), 0, [[2], [1], [0]]) + ), + # test we are not creating duplicate entries for duplicate values in array index + ("duplicate-array-entries-split-arrays", + (slice(None, 4, None), [[2, 1, 0], [2, 1, 1]], [[2, 1, 0], [3, 4, 4]], + slice(None, None, None), 1) + ), + ("duplicate-array-entries-contiguous-broadcast-arrays", + (slice(1, 4, 2), 0, 1, [[2, 1, 1]], [[2], [1], [1]]) + ), + ] + +@pytest.mark.parametrize(["A", "D", "ix", "msg"], [(A, D, ix, msg) for msg, ix in keys]) +@pytest.mark.thread_unsafe +def test_5d_coo_set(A, D, ix, msg): + D[ix] = A[ix] = -99 + assert_equal(A.toarray(), D, err_msg=f"\nTest of: {msg}\n") + + +def test_bool_get(): + D = np.arange(4 * 6 * 6 * 3 * 4).reshape((4, 6, 6, 3, 4)) + A = coo_array(D) + + assert_equal(A[D > 500].toarray(), D[D > 500]) + assert_equal(A[D > 5000].toarray(), D[D > 5000]) + assert_equal(A[D > -1].toarray(), D[D > -1]) + + assert_equal(A[A > 500].toarray(), D[D > 500]) + assert_equal(A[A > 5000].toarray(), D[D > 5000]) + assert_equal(A[A < -1].toarray(), D[D < -1]) + + bi0 = A[:, 0, 0, 0, 0] > 50 + bi1 = A[0, :, 0, 0, 0] > 50 + + idx = (bi0, slice(2, 3, None), [1], slice(None, 2, 2), bi0) + idxnp = (bi0.toarray(), slice(2, 3, 1), [1], slice(0, 2, 2), bi0.toarray()) + result = D[idxnp] + assert_equal(A[idx].toarray(), result) + assert_equal(A[idxnp].toarray(), result) + + idx = (slice(2, 3, None), bi1, bi1, slice(None, 2, 2), [1]) + idxnp = (slice(2, 3, None), bi1.toarray(), bi1.toarray(), slice(None, 2, 2), [1]) + result = D[idxnp] + assert_equal(A[idx].toarray(), result) + + +def test_bool_set(): + D_orig = np.arange(4 * 6 * 6 * 3 * 4).reshape((4, 6, 6, 3, 4)) + A_orig = coo_array(D_orig) + + A, D = A_orig.copy(), D_orig.copy() + D[D > 500] = A[A > 500] = -33 + assert_equal(A.toarray(), D) + + A, D = A_orig.copy(), D_orig.copy() + D[D > 500] = A[A > 500] = -77 + assert_equal(A.toarray(), D) + + A, D = A_orig.copy(), D_orig.copy() + bool0 = A[:, 0, 0, 0, 0] > 50 + idx = (bool0, slice(2, 3, None), [1], slice(None, 2, 2), bool0) + idxnp = (bool0.toarray(), slice(2, 3, 1), [1], slice(0, 2, 2), bool0.toarray()) + + D[idxnp] = A[idx] = -55 + assert_equal(A.toarray(), D) + + A, D = A_orig.copy(), D_orig.copy() + D[idxnp] = A[idxnp] = -88 + assert_equal(A.toarray(), D) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_csc.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_csc.py new file mode 100644 index 0000000000000000000000000000000000000000..7093a8f1b0dd6b00a554d8df94bf40c0c9e77b86 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_csc.py @@ -0,0 +1,131 @@ +import operator +import sys +import platform + +import numpy as np +from numpy.testing import assert_array_almost_equal, assert_ +from scipy.sparse import csr_matrix, csc_matrix, lil_matrix, csr_array, csc_array + +import pytest + + +LINUX_INTEL = (sys.platform == 'linux') and (platform.machine() == 'x86_64') + + + +def test_csc_getrow(): + N = 10 + np.random.seed(0) + X = np.random.random((N, N)) + X[X > 0.7] = 0 + Xcsc = csc_matrix(X) + + for i in range(N): + arr_row = X[i:i + 1, :] + csc_row = Xcsc.getrow(i) + + assert_array_almost_equal(arr_row, csc_row.toarray()) + assert_(type(csc_row) is csr_matrix) + + +def test_csc_getcol(): + N = 10 + np.random.seed(0) + X = np.random.random((N, N)) + X[X > 0.7] = 0 + Xcsc = csc_matrix(X) + + for i in range(N): + arr_col = X[:, i:i + 1] + csc_col = Xcsc.getcol(i) + + assert_array_almost_equal(arr_col, csc_col.toarray()) + assert_(type(csc_col) is csc_matrix) + +@pytest.mark.parametrize("matrix_input, axis, expected_shape", + [(csc_matrix([[1, 0], + [0, 0], + [0, 2]]), + 0, (0, 2)), + (csc_matrix([[1, 0], + [0, 0], + [0, 2]]), + 1, (3, 0)), + (csc_matrix([[1, 0], + [0, 0], + [0, 2]]), + 'both', (0, 0)), + (csc_matrix([[0, 1, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0], + [0, 0, 2, 3, 0, 1]]), + 0, (0, 6))]) +def test_csc_empty_slices(matrix_input, axis, expected_shape): + # see gh-11127 for related discussion + slice_1 = matrix_input.toarray().shape[0] - 1 + slice_2 = slice_1 + slice_3 = slice_2 - 1 + + if axis == 0: + actual_shape_1 = matrix_input[slice_1:slice_2, :].toarray().shape + actual_shape_2 = matrix_input[slice_1:slice_3, :].toarray().shape + elif axis == 1: + actual_shape_1 = matrix_input[:, slice_1:slice_2].toarray().shape + actual_shape_2 = matrix_input[:, slice_1:slice_3].toarray().shape + elif axis == 'both': + actual_shape_1 = matrix_input[slice_1:slice_2, slice_1:slice_2].toarray().shape + actual_shape_2 = matrix_input[slice_1:slice_3, slice_1:slice_3].toarray().shape + + assert actual_shape_1 == expected_shape + assert actual_shape_1 == actual_shape_2 + + +@pytest.mark.parametrize('ax', (-2, -1, 0, 1, None)) +def test_argmax_overflow(ax): + # See gh-13646: Windows integer overflow for large sparse matrices. + dim = (100000, 100000) + A = lil_matrix(dim) + A[-2, -2] = 42 + A[-3, -3] = 0.1234 + A = csc_matrix(A) + idx = A.argmax(axis=ax) + + if ax is None: + # idx is a single flattened index + # that we need to convert to a 2d index pair; + # can't do this with np.unravel_index because + # the dimensions are too large + ii = idx % dim[0] + jj = idx // dim[0] + else: + # idx is an array of size of A.shape[ax]; + # check the max index to make sure no overflows + # we encountered + assert np.count_nonzero(idx) == A.nnz + ii, jj = np.max(idx), np.argmax(idx) + + assert A[ii, jj] == A[-2, -2] + + +@pytest.mark.skipif(not LINUX_INTEL, reason="avoid variations due to OS, see gh-23826") +@pytest.mark.timeout(2) # only slow when broken (when spurious conversion occurs) +@pytest.mark.parametrize("op", (operator.ne, operator.lt, operator.gt, + operator.add, operator.sub, operator.mul, + # truediv, eq, ge, le make dense output so not tested + lambda x, y: x.minimum(y), lambda x, y: x.maximum(y))) +def test_compressed_rc_conversion_mixup(op): + # see gh-23826 for related discussion + num_minor_axis = np.iinfo(np.uint32).max + 1 + minor_axis_index = np.array([num_minor_axis - 1]) + major_axis_index = np.array([10]) + row_cols = (minor_axis_index, major_axis_index) + col_rows = (major_axis_index, minor_axis_index) + + X = csc_array((np.array([10]), row_cols), shape=(num_minor_axis, 20)) + X_2 = X.copy() + # causes timeout error upon large memory alloc only if conversion to CSR occurs + op(X_2, X) + + Z = csr_array((np.array([10]), col_rows), shape=(20, num_minor_axis)) + Z_2 = Z.copy() + # causes timeout error upon large memory alloc only if conversion to CSC occurs + op(Z_2, Z) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_csr.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_csr.py new file mode 100644 index 0000000000000000000000000000000000000000..ef6838bb01543ae33c18f4b22943d04a9b5888be --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_csr.py @@ -0,0 +1,227 @@ +import numpy as np +from numpy.testing import assert_array_almost_equal, assert_, assert_array_equal +from scipy.sparse import csr_matrix, csc_matrix, csr_array, csc_array, hstack +from scipy import sparse +import pytest + + +def _check_csr_rowslice(i, sl, X, Xcsr): + np_slice = X[i, sl] + csr_slice = Xcsr[i, sl] + assert_array_almost_equal(np_slice, csr_slice.toarray()[0]) + assert_(type(csr_slice) is csr_matrix) + + +def test_csr_rowslice(): + N = 10 + np.random.seed(0) + X = np.random.random((N, N)) + X[X > 0.7] = 0 + Xcsr = csr_matrix(X) + + slices = [slice(None, None, None), + slice(None, None, -1), + slice(1, -2, 2), + slice(-2, 1, -2)] + + for i in range(N): + for sl in slices: + _check_csr_rowslice(i, sl, X, Xcsr) + + +def test_csr_getrow(): + N = 10 + np.random.seed(0) + X = np.random.random((N, N)) + X[X > 0.7] = 0 + Xcsr = csr_matrix(X) + + for i in range(N): + arr_row = X[i:i + 1, :] + csr_row = Xcsr.getrow(i) + + assert_array_almost_equal(arr_row, csr_row.toarray()) + assert_(type(csr_row) is csr_matrix) + + +def test_csr_getcol(): + N = 10 + np.random.seed(0) + X = np.random.random((N, N)) + X[X > 0.7] = 0 + Xcsr = csr_matrix(X) + + for i in range(N): + arr_col = X[:, i:i + 1] + csr_col = Xcsr.getcol(i) + + assert_array_almost_equal(arr_col, csr_col.toarray()) + assert_(type(csr_col) is csr_matrix) + +@pytest.mark.parametrize("matrix_input, axis, expected_shape", + [(csr_matrix([[1, 0, 0, 0], + [0, 0, 0, 0], + [0, 2, 3, 0]]), + 0, (0, 4)), + (csr_matrix([[1, 0, 0, 0], + [0, 0, 0, 0], + [0, 2, 3, 0]]), + 1, (3, 0)), + (csr_matrix([[1, 0, 0, 0], + [0, 0, 0, 0], + [0, 2, 3, 0]]), + 'both', (0, 0)), + (csr_matrix([[0, 1, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 2, 3, 0]]), + 0, (0, 5))]) +def test_csr_empty_slices(matrix_input, axis, expected_shape): + # see gh-11127 for related discussion + slice_1 = matrix_input.toarray().shape[0] - 1 + slice_2 = slice_1 + slice_3 = slice_2 - 1 + + if axis == 0: + actual_shape_1 = matrix_input[slice_1:slice_2, :].toarray().shape + actual_shape_2 = matrix_input[slice_1:slice_3, :].toarray().shape + elif axis == 1: + actual_shape_1 = matrix_input[:, slice_1:slice_2].toarray().shape + actual_shape_2 = matrix_input[:, slice_1:slice_3].toarray().shape + elif axis == 'both': + actual_shape_1 = matrix_input[slice_1:slice_2, slice_1:slice_2].toarray().shape + actual_shape_2 = matrix_input[slice_1:slice_3, slice_1:slice_3].toarray().shape + + assert actual_shape_1 == expected_shape + assert actual_shape_1 == actual_shape_2 + + +def test_csr_bool_indexing(): + data = csr_matrix([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) + list_indices1 = [False, True, False] + array_indices1 = np.array(list_indices1) + list_indices2 = [[False, True, False], [False, True, False], [False, True, False]] + array_indices2 = np.array(list_indices2) + list_indices3 = ([False, True, False], [False, True, False]) + array_indices3 = (np.array(list_indices3[0]), np.array(list_indices3[1])) + slice_list1 = data[list_indices1].toarray() + slice_array1 = data[array_indices1].toarray() + slice_list2 = data[list_indices2] + slice_array2 = data[array_indices2] + slice_list3 = data[list_indices3] + slice_array3 = data[array_indices3] + assert (slice_list1 == slice_array1).all() + assert (slice_list2 == slice_array2).all() + assert (slice_list3 == slice_array3).all() + + +@pytest.mark.xfail_on_32bit("Can't create large array for test") +@pytest.mark.timeout(2) # only slow when broken (conversion to 2d index arrays) +@pytest.mark.parametrize("cls", [csr_matrix, csr_array, csc_matrix, csc_array]) +def test_fancy_indexing_broadcasts_without_making_dense_2d(cls): + # Fixes Issue gh-24339 + J = np.arange(100_000) + I = J.reshape((100_000, 1)) + S = cls((100_000, 100_000)) + # checking nnz, but really testing indexing. + assert S[I, J].nnz == 0 # 1D row array for columns -> broadcasts to 2D + assert S[I, J.reshape(1, -1)].nnz == 0 # 2D row array as index for columns + + +def test_csr_hstack_int64(): + """ + Tests if hstack properly promotes to indices and indptr arrays to np.int64 + when using np.int32 during concatenation would result in either array + overflowing. + """ + max_int32 = np.iinfo(np.int32).max + + # First case: indices would overflow with int32 + data = [1.0] + row = [0] + + max_indices_1 = max_int32 - 1 + max_indices_2 = 3 + + # Individual indices arrays are representable with int32 + col_1 = [max_indices_1 - 1] + col_2 = [max_indices_2 - 1] + + X_1 = csr_matrix((data, (row, col_1))) + X_2 = csr_matrix((data, (row, col_2))) + + assert max(max_indices_1 - 1, max_indices_2 - 1) < max_int32 + assert X_1.indices.dtype == X_1.indptr.dtype == np.int32 + assert X_2.indices.dtype == X_2.indptr.dtype == np.int32 + + # ... but when concatenating their CSR matrices, the resulting indices + # array can't be represented with int32 and must be promoted to int64. + X_hs = hstack([X_1, X_2], format="csr") + + assert X_hs.indices.max() == max_indices_1 + max_indices_2 - 1 + assert max_indices_1 + max_indices_2 - 1 > max_int32 + assert X_hs.indices.dtype == X_hs.indptr.dtype == np.int64 + + # Even if the matrices are empty, we must account for their size + # contribution so that we may safely set the final elements. + X_1_empty = csr_matrix(X_1.shape) + X_2_empty = csr_matrix(X_2.shape) + X_hs_empty = hstack([X_1_empty, X_2_empty], format="csr") + + assert X_hs_empty.shape == X_hs.shape + assert X_hs_empty.indices.dtype == np.int64 + + # Should be just small enough to stay in int32 after stack. Note that + # we theoretically could support indices.max() == max_int32, but due to an + # edge-case in the underlying sparsetools code + # (namely the `coo_tocsr` routine), + # we require that max(X_hs_32.shape) < max_int32 as well. + # Hence we can only support max_int32 - 1. + col_3 = [max_int32 - max_indices_1 - 1] + X_3 = csr_matrix((data, (row, col_3))) + X_hs_32 = hstack([X_1, X_3], format="csr") + assert X_hs_32.indices.dtype == np.int32 + assert X_hs_32.indices.max() == max_int32 - 1 + +@pytest.mark.parametrize("cls", [csr_matrix, csr_array, csc_matrix, csc_array]) +def test_mixed_index_dtype_int_indexing(cls): + # https://github.com/scipy/scipy/issues/20182 + rng = np.random.default_rng(0) + base_mtx = cls(sparse.random(50, 50, random_state=rng, density=0.1)) + indptr_64bit = base_mtx.copy() + indices_64bit = base_mtx.copy() + indptr_64bit.indptr = base_mtx.indptr.astype(np.int64) + indices_64bit.indices = base_mtx.indices.astype(np.int64) + + for mtx in [base_mtx, indptr_64bit, indices_64bit]: + np.testing.assert_array_equal( + mtx[[1,2], :].toarray(), + base_mtx[[1, 2], :].toarray() + ) + np.testing.assert_array_equal( + mtx[:, [1, 2]].toarray(), + base_mtx[:, [1, 2]].toarray() + ) + +def test_broadcast_to(): + a = np.array([1, 0, 2]) + b = np.array([3]) + e = np.zeros((0,)) + res_a = csr_array(a)._broadcast_to((2,3)) + res_b = csr_array(b)._broadcast_to((4,)) + res_c = csr_array(b)._broadcast_to((2,4)) + res_d = csr_array(b)._broadcast_to((1,)) + res_e = csr_array(e)._broadcast_to((4,0)) + assert_array_equal(res_a.toarray(), np.broadcast_to(a, (2,3))) + assert_array_equal(res_b.toarray(), np.broadcast_to(b, (4,))) + assert_array_equal(res_c.toarray(), np.broadcast_to(b, (2,4))) + assert_array_equal(res_d.toarray(), np.broadcast_to(b, (1,))) + assert_array_equal(res_e.toarray(), np.broadcast_to(e, (4,0))) + + with pytest.raises(ValueError, match="cannot be broadcast"): + csr_matrix([[1, 2, 0], [3, 0, 1]])._broadcast_to(shape=(2, 1)) + + with pytest.raises(ValueError, match="cannot be broadcast"): + csr_matrix([[0, 1, 2]])._broadcast_to(shape=(3, 2)) + + with pytest.raises(ValueError, match="cannot be broadcast"): + csr_array([0, 1, 2])._broadcast_to(shape=(3, 2)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_dok.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_dok.py new file mode 100644 index 0000000000000000000000000000000000000000..bca98ebc353e4a4e2f38322f0d5033aec1ffcc7e --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_dok.py @@ -0,0 +1,224 @@ +import warnings + +import pytest +import numpy as np +from numpy.testing import assert_equal +import scipy as sp +from scipy.sparse import dok_array, dok_matrix + + +pytestmark = pytest.mark.thread_unsafe + + +@pytest.fixture +def d(): + return {(0, 1): 1, (0, 2): 2} + +@pytest.fixture +def A(): + return np.array([[0, 1, 2], [0, 0, 0], [0, 0, 0]]) + +@pytest.fixture(params=[dok_array, dok_matrix]) +def Asp(request): + A = request.param((3, 3)) + A[(0, 1)] = 1 + A[(0, 2)] = 2 + yield A + +# Note: __iter__ and comparison dunders act like ndarrays for DOK, not dict. +# Dunders reversed, or, ror, ior work as dict for dok_matrix, raise for dok_array +# All other dict methods on DOK format act like dict methods (with extra checks). + +# Start of tests +################ +def test_dict_methods_covered(d, Asp): + d_methods = set(dir(d)) - {"__class_getitem__"} + asp_methods = set(dir(Asp)) + assert d_methods < asp_methods + +def test_clear(d, Asp): + assert d.items() == Asp.items() + d.clear() + Asp.clear() + assert d.items() == Asp.items() + +def test_copy(d, Asp): + assert d.items() == Asp.items() + dd = d.copy() + asp = Asp.copy() + assert dd.items() == asp.items() + assert asp.items() == Asp.items() + asp[(0, 1)] = 3 + assert Asp[(0, 1)] == 1 + +def test_fromkeys_default(): + # test with default value + edges = [(0, 2), (1, 0), (2, 1)] + Xdok = dok_array.fromkeys(edges) + X = [[0, 0, 1], [1, 0, 0], [0, 1, 0]] + assert_equal(Xdok.toarray(), X) + +def test_fromkeys_positional(): + # test with positional value + edges = [(0, 2), (1, 0), (2, 1)] + Xdok = dok_array.fromkeys(edges, -1) + X = [[0, 0, -1], [-1, 0, 0], [0, -1, 0]] + assert_equal(Xdok.toarray(), X) + +def test_fromkeys_iterator(): + it = ((a, a % 2) for a in range(4)) + Xdok = dok_array.fromkeys(it) + X = [[1, 0], [0, 1], [1, 0], [0, 1]] + assert_equal(Xdok.toarray(), X) + +def test_get(d, Asp): + assert Asp.get((0, 1)) == d.get((0, 1)) + assert Asp.get((0, 0), 99) == d.get((0, 0), 99) + with pytest.raises(IndexError, match="out of bounds"): + Asp.get((0, 4), 99) + +def test_items(d, Asp): + assert Asp.items() == d.items() + +def test_keys(d, Asp): + assert Asp.keys() == d.keys() + +def test_pop(d, Asp): + assert d.pop((0, 1)) == 1 + assert Asp.pop((0, 1)) == 1 + assert d.items() == Asp.items() + + assert Asp.pop((22, 21), None) is None + assert Asp.pop((22, 21), "other") == "other" + with pytest.raises(KeyError, match="(22, 21)"): + Asp.pop((22, 21)) + with pytest.raises(TypeError, match="got an unexpected keyword argument"): + Asp.pop((22, 21), default=5) + +def test_popitem(d, Asp): + assert d.popitem() == Asp.popitem() + assert d.items() == Asp.items() + +def test_setdefault(d, Asp): + assert Asp.setdefault((0, 1), 4) == 1 + assert Asp.setdefault((2, 2), 4) == 4 + d.setdefault((0, 1), 4) + d.setdefault((2, 2), 4) + assert d.items() == Asp.items() + +def test_update(d, Asp): + for input in [Asp, Asp._dict, Asp._dict.items()]: + Bsp = dok_array(Asp.shape) + Bsp.update(input) + assert_equal(Bsp.toarray(), Asp.toarray()) + + with pytest.raises(ValueError, match="Inexact indices .* not allowed"): + Asp.update(np.zeros((2,2))) + with pytest.raises(IndexError, match="length needs to match self.shape"): + Asp.update({(3, 2, 1, 0): 1.2}) + with pytest.raises(IndexError, match="integer keys required"): + Asp.update({(0.2, 1): 1.2}) + with pytest.raises(IndexError, match="negative index"): + Asp.update({(0, -1): 1.2}) + with pytest.raises(IndexError, match="index .* is too large"): + Asp.update({(0, 3): 1.2}) + +def test_values(d, Asp): + # Note: dict.values are strange: d={1: 1}; d.values() == d.values() is False + # Using list(d.values()) makes them comparable. + assert list(Asp.values()) == list(d.values()) + +def test_dunder_getitem(d, Asp): + assert Asp[(0, 1)] == d[(0, 1)] + +def test_dunder_setitem(d, Asp): + Asp[(1, 1)] = 5 + d[(1, 1)] = 5 + assert d.items() == Asp.items() + +def test_dunder_delitem(d, Asp): + del Asp[(0, 1)] + del d[(0, 1)] + assert d.items() == Asp.items() + +def test_dunder_contains(d, Asp): + assert ((0, 1) in d) == ((0, 1) in Asp) + assert ((0, 0) in d) == ((0, 0) in Asp) + +def test_dunder_len(d, Asp): + assert len(d) == len(Asp) + +# Note: dunders reversed, or, ror, ior work as dict for dok_matrix, raise for dok_array +def test_dunder_reversed(d, Asp): + if isinstance(Asp, dok_array): + with pytest.raises(TypeError): + list(reversed(Asp)) + else: + assert list(reversed(Asp)) == list(reversed(d)) + +def test_dunder_ior(d, Asp): + if isinstance(Asp, dok_array): + with pytest.raises(TypeError): + Asp |= Asp + else: + dd = {(0, 0): 5} + Asp |= dd + assert Asp[(0, 0)] == 5 + d |= dd + assert d.items() == Asp.items() + dd |= Asp + assert dd.items() == Asp.items() + +def test_dunder_or(d, Asp): + if isinstance(Asp, dok_array): + with pytest.raises(TypeError): + Asp | Asp + else: + assert d | d == Asp | d + assert d | d == Asp | Asp + +def test_dunder_ror(d, Asp): + if isinstance(Asp, dok_array): + with pytest.raises(TypeError): + Asp | Asp + with pytest.raises(TypeError): + d | Asp + else: + assert Asp.__ror__(d) == Asp.__ror__(Asp) + assert d.__ror__(d) == Asp.__ror__(d) + assert d | Asp + +# Note: comparison dunders, e.g. ==, >=, etc follow np.array not dict +def test_dunder_eq(A, Asp): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", sp.sparse.SparseEfficiencyWarning) + assert (Asp == Asp).toarray().all() + assert (A == Asp).all() + +def test_dunder_ne(A, Asp): + assert not (Asp != Asp).toarray().any() + assert not (A != Asp).any() + +def test_dunder_lt(A, Asp): + assert not (Asp < Asp).toarray().any() + assert not (A < Asp).any() + +def test_dunder_gt(A, Asp): + assert not (Asp > Asp).toarray().any() + assert not (A > Asp).any() + +def test_dunder_le(A, Asp): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", sp.sparse.SparseEfficiencyWarning) + assert (Asp <= Asp).toarray().all() + assert (A <= Asp).all() + +def test_dunder_ge(A, Asp): + with warnings.catch_warnings(): + warnings.simplefilter("ignore", sp.sparse.SparseEfficiencyWarning) + assert (Asp >= Asp).toarray().all() + assert (A >= Asp).all() + +# Note: iter dunder follows np.array not dict +def test_dunder_iter(A, Asp): + assert all((a == asp).all() for a, asp in zip(A, Asp)) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_extract.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_extract.py new file mode 100644 index 0000000000000000000000000000000000000000..a7c9f68bb2bde76d74ca767abba3c99b89d6e771 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_extract.py @@ -0,0 +1,51 @@ +"""test sparse matrix construction functions""" + +from numpy.testing import assert_equal +from scipy.sparse import csr_matrix, csr_array, sparray + +import numpy as np +from scipy.sparse import _extract + + +class TestExtract: + def setup_method(self): + self.cases = [ + csr_array([[1,2]]), + csr_array([[1,0]]), + csr_array([[0,0]]), + csr_array([[1],[2]]), + csr_array([[1],[0]]), + csr_array([[0],[0]]), + csr_array([[1,2],[3,4]]), + csr_array([[0,1],[0,0]]), + csr_array([[0,0],[1,0]]), + csr_array([[0,0],[0,0]]), + csr_array([[1,2,0,0,3],[4,5,0,6,7],[0,0,8,9,0]]), + csr_array([[1,2,0,0,3],[4,5,0,6,7],[0,0,8,9,0]]).T, + ] + + def test_find(self): + for A in self.cases: + I,J,V = _extract.find(A) + B = csr_array((V,(I,J)), shape=A.shape) + assert_equal(A.toarray(), B.toarray()) + + def test_tril(self): + for A in self.cases: + B = A.toarray() + for k in [-3,-2,-1,0,1,2,3]: + assert_equal(_extract.tril(A,k=k).toarray(), np.tril(B,k=k)) + + def test_triu(self): + for A in self.cases: + B = A.toarray() + for k in [-3,-2,-1,0,1,2,3]: + assert_equal(_extract.triu(A,k=k).toarray(), np.triu(B,k=k)) + + def test_array_vs_matrix(self): + for A in self.cases: + assert isinstance(_extract.tril(A), sparray) + assert isinstance(_extract.triu(A), sparray) + M = csr_matrix(A) + assert not isinstance(_extract.tril(M), sparray) + assert not isinstance(_extract.triu(M), sparray) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_indexing1d.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_indexing1d.py new file mode 100644 index 0000000000000000000000000000000000000000..6b41adc59df59594587b92179e905ebc5bfd9510 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_indexing1d.py @@ -0,0 +1,611 @@ +import contextlib +import warnings + +import pytest +import numpy as np +from numpy.testing import assert_allclose, assert_equal + +from scipy.sparse import csr_array, dok_array, SparseEfficiencyWarning +from .test_arithmetic1d import toarray + + +formats_for_index1d = [csr_array, dok_array] + + +@contextlib.contextmanager +def check_remains_sorted(X): + """Checks that sorted indices property is retained through an operation""" + yield + if not hasattr(X, 'has_sorted_indices') or not X.has_sorted_indices: + return + indices = X.indices.copy() + X.has_sorted_indices = False + X.sort_indices() + assert_equal(indices, X.indices, 'Expected sorted indices, found unsorted') + + +@pytest.mark.parametrize("spcreator", formats_for_index1d) +class TestGetSet1D: + def test_None_index(self, spcreator): + D = np.array([4, 3, 0]) + A = spcreator(D) + + N = D.shape[0] + for j in range(-N, N): + assert_equal(A[j, None].toarray(), D[j, None]) + assert_equal(A[None, j].toarray(), D[None, j]) + assert_equal(A[None, None, j].toarray(), D[None, None, j]) + + def test_getitem_shape(self, spcreator): + A = spcreator(np.arange(3 * 4).reshape(3, 4)) + assert A[1, 2].ndim == 0 + assert A[1, 2:3].shape == (1,) + assert A[None, 1, 2:3].shape == (1, 1) + assert A[None, 1, 2].shape == (1,) + assert A[None, 1, 2, None].shape == (1, 1) + + # see gh-22458 + assert A[None, 1].shape == (1, 4) + assert A[1, None].shape == (1, 4) + assert A[None, 1, :].shape == (1, 4) + assert A[1, None, :].shape == (1, 4) + assert A[1, :, None].shape == (4, 1) + + # output is >2D + if A.format == "coo": + assert A[None, 2, 1, None, None].shape == (1, 1, 1) + assert A[None, 0:2, None, 1].shape == (1,2,1) + assert A[0:1, 1:, None].shape == (1,3,1) + assert A[1:, 1, None, None].shape == (3,1,1) + + def test_getelement(self, spcreator): + D = np.array([4, 3, 0]) + A = spcreator(D) + + N = D.shape[0] + for j in range(-N, N): + assert_equal(A[j], D[j]) + + for ij in [3, -4]: + with pytest.raises(IndexError, match='index (.*) out of (range|bounds)'): + A.__getitem__(ij) + + # single element tuples unwrapped + assert A[(0,)] == 4 + + with pytest.raises(IndexError, match='index (.*) out of (range|bounds)'): + A.__getitem__((4,)) + + @pytest.mark.parametrize( + "scalar_container", + [lambda x: csr_array(np.array([[x]])), np.array, lambda x: x], + ids=["sparse", "dense", "scalar"] + ) + def test_setelement(self, spcreator, scalar_container): + dtype = np.float64 + A = spcreator((12,), dtype=dtype) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "Changing the sparsity structure of .* is expensive", + SparseEfficiencyWarning, + ) + A[0] = scalar_container(dtype(0)) + A[1] = scalar_container(dtype(3)) + A[8] = scalar_container(dtype(9.0)) + A[-2] = scalar_container(dtype(7)) + A[5] = scalar_container(9) + + A[-9,] = scalar_container(dtype(8)) + A[1,] = scalar_container(dtype(5)) # overwrite using 1-tuple index + + for ij in [13, -14, (13,), (14,)]: + with pytest.raises(IndexError, match='out of (range|bounds)'): + A.__setitem__(ij, 123.0) + + +@pytest.mark.parametrize("spcreator", formats_for_index1d) +class TestSlicingAndFancy1D: + ####################### + # Int-like Array Index + ####################### + def test_get_array_index(self, spcreator): + D = np.array([4, 3, 0]) + A = spcreator(D) + + assert_equal(A[()].toarray(), D[()]) + for ij in [(0, 3), (3,)]: + with pytest.raises(IndexError, match='out of (range|bounds)|many indices'): + A.__getitem__(ij) + + def test_set_array_index(self, spcreator): + dtype = np.float64 + A = spcreator((12,), dtype=dtype) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "Changing the sparsity structure of .* is expensive", + SparseEfficiencyWarning, + ) + A[np.array(6)] = dtype(4.0) # scalar index + A[np.array(6)] = dtype(2.0) # overwrite with scalar index + assert_equal(A.toarray(), [0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0]) + + for ij in [(13,), (-14,)]: + with pytest.raises(IndexError, match='index .* out of (range|bounds)'): + A.__setitem__(ij, 123.0) + + for v in [(), (0, 3), [1, 2, 3], np.array([1, 2, 3])]: + msg = 'Trying to assign a sequence to an item' + with pytest.raises(ValueError, match=msg): + A.__setitem__(0, v) + + #################### + # 1d Slice as index + #################### + def test_dtype_preservation(self, spcreator): + assert_equal(spcreator((10,), dtype=np.int16)[1:5].dtype, np.int16) + assert_equal(spcreator((6,), dtype=np.int32)[0:0:2].dtype, np.int32) + assert_equal(spcreator((6,), dtype=np.int64)[:].dtype, np.int64) + + def test_get_1d_slice(self, spcreator): + B = np.arange(50.) + A = spcreator(B) + assert_equal(B[:], A[:].toarray()) + assert_equal(B[2:5], A[2:5].toarray()) + + C = np.array([4, 0, 6, 0, 0, 0, 0, 0, 1]) + D = spcreator(C) + assert_equal(C[1:3], D[1:3].toarray()) + + # Now test slicing when a row contains only zeros + E = np.array([0, 0, 0, 0, 0]) + F = spcreator(E) + assert_equal(E[1:3], F[1:3].toarray()) + assert_equal(E[-2:], F[-2:].toarray()) + assert_equal(E[:], F[:].toarray()) + assert_equal(E[slice(None)], F[slice(None)].toarray()) + + def test_slicing_idx_slice(self, spcreator): + B = np.arange(50) + A = spcreator(B) + + # [i] + assert_equal(A[2], B[2]) + assert_equal(A[-1], B[-1]) + assert_equal(A[np.array(-2)], B[-2]) + + # [1:2] + assert_equal(A[:].toarray(), B[:]) + assert_equal(A[5:-2].toarray(), B[5:-2]) + assert_equal(A[5:12:3].toarray(), B[5:12:3]) + + # int8 slice + s = slice(np.int8(2), np.int8(4), None) + assert_equal(A[s].toarray(), B[2:4]) + + # np.s_ + s_ = np.s_ + slices = [s_[:2], s_[1:2], s_[3:], s_[3::2], + s_[15:20], s_[3:2], + s_[8:3:-1], s_[4::-2], s_[:5:-1], + 0, 1, s_[:], s_[1:5], -1, -2, -5, + np.array(-1), np.int8(-3)] + + for j, a in enumerate(slices): + x = A[a] + y = B[a] + if y.shape == (): + assert_equal(x, y, repr(a)) + else: + if x.size == 0 and y.size == 0: + pass + else: + assert_equal(x.toarray(), y, repr(a)) + + def test_ellipsis_1d_slicing(self, spcreator): + B = np.arange(50) + A = spcreator(B) + assert_equal(A[...].toarray(), B[...]) + assert_equal(A[...,].toarray(), B[...,]) + + ########################## + # Assignment with Slicing + ########################## + def test_slice_scalar_assign(self, spcreator): + A = spcreator((5,)) + B = np.zeros((5,)) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "Changing the sparsity structure of .* is expensive", + SparseEfficiencyWarning, + ) + for C in [A, B]: + C[0:1] = 1 + C[2:0] = 4 + C[2:3] = 9 + C[3:] = 1 + C[3::-1] = 9 + assert_equal(A.toarray(), B) + + def test_slice_assign_2(self, spcreator): + shape = (10,) + + for idx in [slice(3), slice(None, 10, 4), slice(5, -2)]: + A = spcreator(shape) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "Changing the sparsity structure of .* is expensive", + SparseEfficiencyWarning, + ) + A[idx] = 1 + B = np.zeros(shape) + B[idx] = 1 + msg = f"idx={idx!r}" + assert_allclose(A.toarray(), B, err_msg=msg) + + def test_self_self_assignment(self, spcreator): + # Tests whether a row of one lil_matrix can be assigned to another. + B = spcreator((5,)) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "Changing the sparsity structure of .* is expensive", + SparseEfficiencyWarning, + ) + B[0] = 2 + B[1] = 0 + B[2] = 3 + B[3] = 10 + + A = B / 10 + B[:] = A[:] + assert_equal(A[:].toarray(), B[:].toarray()) + + A = B / 10 + B[:] = A[:1] + assert_equal(np.zeros((5,)) + A[0], B.toarray()) + + A = B / 10 + B[:-1] = A[1:] + assert_equal(A[1:].toarray(), B[:-1].toarray()) + + def test_slice_assignment(self, spcreator): + B = spcreator((4,)) + expected = np.array([10, 0, 14, 0]) + block = [2, 1] + + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "Changing the sparsity structure of .* is expensive", + SparseEfficiencyWarning, + ) + B[0] = 5 + B[2] = 7 + B[:] = B + B + assert_equal(B.toarray(), expected) + + B[:2] = csr_array(block) + assert_equal(B.toarray()[:2], block) + + def test_set_slice(self, spcreator): + A = spcreator((5,)) + B = np.zeros(5, float) + s_ = np.s_ + slices = [s_[:2], s_[1:2], s_[3:], s_[3::2], + s_[8:3:-1], s_[4::-2], s_[:5:-1], + 0, 1, s_[:], s_[1:5], -1, -2, -5, + np.array(-1), np.int8(-3)] + + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "Changing the sparsity structure of .* is expensive", + SparseEfficiencyWarning, + ) + for j, a in enumerate(slices): + A[a] = j + B[a] = j + assert_equal(A.toarray(), B, repr(a)) + + A[1:10:2] = range(1, 5, 2) + B[1:10:2] = range(1, 5, 2) + assert_equal(A.toarray(), B) + + # The next commands should raise exceptions + toobig = list(range(100)) + with pytest.raises(ValueError, match='Trying to assign a sequence to an item'): + A.__setitem__(0, toobig) + with pytest.raises(ValueError, match='could not be broadcast together'): + A.__setitem__(slice(None), toobig) + + def test_assign_empty(self, spcreator): + A = spcreator(np.ones(3)) + B = spcreator((2,)) + A[:2] = B + assert_equal(A.toarray(), [0, 0, 1]) + + #################### + # 1d Fancy Indexing + #################### + def test_dtype_preservation_empty_index(self, spcreator): + A = spcreator((2,), dtype=np.int16) + assert_equal(A[[False, False]].dtype, np.int16) + assert_equal(A[[]].dtype, np.int16) + + def test_bad_index(self, spcreator): + A = spcreator(np.zeros(5)) + with pytest.raises(IndexError, match='Index dimension must be 1 or 2'): + A.__getitem__("foo") + with pytest.raises(IndexError, match='tuple index out of range'): + A.__getitem__((2, "foo")) + + def test_fancy_indexing_2darray(self, spcreator): + B = np.arange(50).reshape((5, 10)) + A = spcreator(B) + + # [i] + assert_equal(A[[1, 3]].toarray(), B[[1, 3]]) + + # [i,[1,2]] + assert_equal(A[3, [1, 3]].toarray(), B[3, [1, 3]]) + assert_equal(A[-1, [2, -5]].toarray(), B[-1, [2, -5]]) + assert_equal(A[np.array(-1), [2, -5]].toarray(), B[-1, [2, -5]]) + assert_equal(A[-1, np.array([2, -5])].toarray(), B[-1, [2, -5]]) + assert_equal(A[np.array(-1), np.array([2, -5])].toarray(), B[-1, [2, -5]]) + + # [1:2,[1,2]] + assert_equal(A[:, [2, 8, 3, -1]].toarray(), B[:, [2, 8, 3, -1]]) + assert_equal(A[3:4, [9]].toarray(), B[3:4, [9]]) + assert_equal(A[1:4, [-1, -5]].toarray(), B[1:4, [-1, -5]]) + assert_equal(A[1:4, np.array([-1, -5])].toarray(), B[1:4, [-1, -5]]) + + # [[1,2],j] + assert_equal(A[[1, 3], 3].toarray(), B[[1, 3], 3]) + assert_equal(A[[2, -5], -4].toarray(), B[[2, -5], -4]) + assert_equal(A[np.array([2, -5]), -4].toarray(), B[[2, -5], -4]) + assert_equal(A[[2, -5], np.array(-4)].toarray(), B[[2, -5], -4]) + assert_equal(A[np.array([2, -5]), np.array(-4)].toarray(), B[[2, -5], -4]) + + # [[1,2],1:2] + assert_equal(A[[1, 3], :].toarray(), B[[1, 3], :]) + assert_equal(A[[2, -5], 8:-1].toarray(), B[[2, -5], 8:-1]) + assert_equal(A[np.array([2, -5]), 8:-1].toarray(), B[[2, -5], 8:-1]) + + # [[1,2],[1,2]] + assert_equal(toarray(A[[1, 3], [2, 4]]), B[[1, 3], [2, 4]]) + assert_equal(toarray(A[[-1, -3], [2, -4]]), B[[-1, -3], [2, -4]]) + assert_equal( + toarray(A[np.array([-1, -3]), [2, -4]]), B[[-1, -3], [2, -4]] + ) + assert_equal( + toarray(A[[-1, -3], np.array([2, -4])]), B[[-1, -3], [2, -4]] + ) + assert_equal( + toarray(A[np.array([-1, -3]), np.array([2, -4])]), B[[-1, -3], [2, -4]] + ) + + # [[[1],[2]],[1,2]] + assert_equal(A[[[1], [3]], [2, 4]].toarray(), B[[[1], [3]], [2, 4]]) + assert_equal( + A[[[-1], [-3], [-2]], [2, -4]].toarray(), + B[[[-1], [-3], [-2]], [2, -4]] + ) + assert_equal( + A[np.array([[-1], [-3], [-2]]), [2, -4]].toarray(), + B[[[-1], [-3], [-2]], [2, -4]] + ) + assert_equal( + A[[[-1], [-3], [-2]], np.array([2, -4])].toarray(), + B[[[-1], [-3], [-2]], [2, -4]] + ) + assert_equal( + A[np.array([[-1], [-3], [-2]]), np.array([2, -4])].toarray(), + B[[[-1], [-3], [-2]], [2, -4]] + ) + + # [[1,2]] + assert_equal(A[[1, 3]].toarray(), B[[1, 3]]) + assert_equal(A[[-1, -3]].toarray(), B[[-1, -3]]) + assert_equal(A[np.array([-1, -3])].toarray(), B[[-1, -3]]) + + # [[1,2],:][:,[1,2]] + assert_equal( + A[[1, 3], :][:, [2, 4]].toarray(), B[[1, 3], :][:, [2, 4]] + ) + assert_equal( + A[[-1, -3], :][:, [2, -4]].toarray(), B[[-1, -3], :][:, [2, -4]] + ) + assert_equal( + A[np.array([-1, -3]), :][:, np.array([2, -4])].toarray(), + B[[-1, -3], :][:, [2, -4]] + ) + + # [:,[1,2]][[1,2],:] + assert_equal( + A[:, [1, 3]][[2, 4], :].toarray(), B[:, [1, 3]][[2, 4], :] + ) + assert_equal( + A[:, [-1, -3]][[2, -4], :].toarray(), B[:, [-1, -3]][[2, -4], :] + ) + assert_equal( + A[:, np.array([-1, -3])][np.array([2, -4]), :].toarray(), + B[:, [-1, -3]][[2, -4], :] + ) + + def test_fancy_indexing(self, spcreator): + B = np.arange(50) + A = spcreator(B) + + # [i] + assert_equal(A[[3]].toarray(), B[[3]]) + + # [np.array] + assert_equal(A[[1, 3]].toarray(), B[[1, 3]]) + assert_equal(A[[2, -5]].toarray(), B[[2, -5]]) + assert_equal(A[np.array(-1)], B[-1]) + assert_equal(A[np.array([-1, 2])].toarray(), B[[-1, 2]]) + assert_equal(A[np.array(5)], B[np.array(5)]) + + # [[[1],[2]]] + ind = np.array([[1], [3]]) + assert_equal(A[ind].toarray(), B[ind]) + ind = np.array([[-1], [-3], [-2]]) + assert_equal(A[ind].toarray(), B[ind]) + + # [[1, 2]] + assert_equal(A[[1, 3]].toarray(), B[[1, 3]]) + assert_equal(A[[-1, -3]].toarray(), B[[-1, -3]]) + assert_equal(A[np.array([-1, -3])].toarray(), B[[-1, -3]]) + + # [[1, 2]][[1, 2]] + assert_equal(A[[1, 5, 2, 8]][[1, 3]].toarray(), + B[[1, 5, 2, 8]][[1, 3]]) + assert_equal(A[[-1, -5, 2, 8]][[1, -4]].toarray(), + B[[-1, -5, 2, 8]][[1, -4]]) + + def test_fancy_indexing_boolean(self, spcreator): + np.random.seed(1234) # make runs repeatable + + B = np.arange(50) + A = spcreator(B) + + I = np.array(np.random.randint(0, 2, size=50), dtype=bool) + + assert_equal(toarray(A[I]), B[I]) + assert_equal(toarray(A[B > 9]), B[B > 9]) + + Z1 = np.zeros(51, dtype=bool) + Z2 = np.zeros(51, dtype=bool) + Z2[-1] = True + Z3 = np.zeros(51, dtype=bool) + Z3[0] = True + + msg = 'bool index .* has shape|boolean index did not match' + with pytest.raises(IndexError, match=msg): + A.__getitem__(Z1) + with pytest.raises(IndexError, match=msg): + A.__getitem__(Z2) + with pytest.raises(IndexError, match=msg): + A.__getitem__(Z3) + + def test_fancy_indexing_sparse_boolean(self, spcreator): + np.random.seed(1234) # make runs repeatable + + B = np.arange(20) + A = spcreator(B) + + X = np.array(np.random.randint(0, 2, size=20), dtype=bool) + Xsp = csr_array(X) + + assert_equal(toarray(A[Xsp]), B[X]) + assert_equal(toarray(A[A > 9]), B[B > 9]) + + Y = np.array(np.random.randint(0, 2, size=60), dtype=bool) + + Ysp = csr_array(Y) + + with pytest.raises(IndexError, match='bool index .* has shape|only integers'): + A.__getitem__(Ysp) + with pytest.raises(IndexError, match='tuple index out of range|only integers'): + A.__getitem__((Xsp, 1)) + + def test_fancy_indexing_seq_assign(self, spcreator): + mat = spcreator(np.array([1, 0])) + with pytest.raises(ValueError, match='Trying to assign a sequence to an item'): + mat.__setitem__(0, np.array([1, 2])) + + def test_fancy_indexing_empty(self, spcreator): + B = np.arange(50) + B[3:9] = 0 + B[30] = 0 + A = spcreator(B) + + K = np.array([False] * 50) + assert_equal(toarray(A[K]), B[K]) + K = np.array([], dtype=int) + assert_equal(toarray(A[K]), B[K]) + J = np.array([0, 1, 2, 3, 4], dtype=int) + assert_equal(toarray(A[J]), B[J]) + + ############################ + # 1d Fancy Index Assignment + ############################ + def test_bad_index_assign(self, spcreator): + A = spcreator(np.zeros(5)) + msg = 'Index dimension must be 1 or 2|only integers' + with pytest.raises((IndexError, ValueError, TypeError), match=msg): + A.__setitem__("foo", 2) + + def test_fancy_indexing_set(self, spcreator): + M = (5,) + + # [1:2] + for j in [[2, 3, 4], slice(None, 10, 4), np.arange(3), + slice(5, -2), slice(2, 5)]: + A = spcreator(M) + B = np.zeros(M) + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "Changing the sparsity structure of .* is expensive", + SparseEfficiencyWarning, + ) + B[j] = 1 + with check_remains_sorted(A): + A[j] = 1 + assert_allclose(A.toarray(), B) + + def test_sequence_assignment(self, spcreator): + A = spcreator((4,)) + B = spcreator((3,)) + + i0 = [0, 1, 2] + i1 = (0, 1, 2) + i2 = np.array(i0) + + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + "Changing the sparsity structure of .* is expensive", + SparseEfficiencyWarning, + ) + with check_remains_sorted(A): + A[i0] = B[i0] + msg = "Too many indices for array|tuple index out of range" + with pytest.raises(IndexError, match=msg): + B.__getitem__(i1) + A[i2] = B[i2] + assert_equal(A[:3].toarray(), B.toarray()) + assert A.shape == (4,) + + # slice + A = spcreator((4,)) + with check_remains_sorted(A): + A[1:3] = [10, 20] + assert_equal(A.toarray(), [0, 10, 20, 0]) + + # array + A = spcreator((4,)) + B = np.zeros(4) + with check_remains_sorted(A): + for C in [A, B]: + C[[0, 1, 2]] = [4, 5, 6] + assert_equal(A.toarray(), B) + + def test_fancy_assign_empty(self, spcreator): + B = np.arange(50) + B[2] = 0 + B[[3, 6]] = 0 + A = spcreator(B) + + K = np.array([False] * 50) + A[K] = 42 + assert_equal(A.toarray(), B) + + K = np.array([], dtype=int) + A[K] = 42 + assert_equal(A.toarray(), B) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_matrix_io.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_matrix_io.py new file mode 100644 index 0000000000000000000000000000000000000000..c615846785eb3fe267739b3ede0e7209c6da39b0 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_matrix_io.py @@ -0,0 +1,129 @@ +import os +import numpy as np +import tempfile + +import pytest +from pytest import raises as assert_raises +from numpy.testing import assert_equal, assert_ + +from scipy.sparse import (sparray, csr_array, coo_array, save_npz, load_npz, + csc_matrix, csr_matrix, bsr_matrix, dia_matrix, + coo_matrix, dok_matrix) + + +DATA_DIR = os.path.join(os.path.dirname(__file__), 'data') + + +def _save_and_load(matrix): + fd, tmpfile = tempfile.mkstemp(suffix='.npz') + os.close(fd) + try: + save_npz(tmpfile, matrix) + loaded_matrix = load_npz(tmpfile) + finally: + os.remove(tmpfile) + return loaded_matrix + +def _check_save_and_load(dense_matrix): + for matrix_class in [csc_matrix, csr_matrix, bsr_matrix, dia_matrix, coo_matrix]: + matrix = matrix_class(dense_matrix) + loaded_matrix = _save_and_load(matrix) + assert_(type(loaded_matrix) is matrix_class) + assert_(loaded_matrix.shape == dense_matrix.shape) + assert_(loaded_matrix.dtype == dense_matrix.dtype) + assert_equal(loaded_matrix.toarray(), dense_matrix) + +def test_save_and_load_random(): + N = 10 + np.random.seed(0) + dense_matrix = np.random.random((N, N)) + dense_matrix[dense_matrix > 0.7] = 0 + _check_save_and_load(dense_matrix) + +def test_save_and_load_empty(): + dense_matrix = np.zeros((4,6)) + _check_save_and_load(dense_matrix) + +def test_save_and_load_one_entry(): + dense_matrix = np.zeros((4,6)) + dense_matrix[1,2] = 1 + _check_save_and_load(dense_matrix) + +def test_sparray_vs_spmatrix(): + #save/load matrix + fd, tmpfile = tempfile.mkstemp(suffix='.npz') + os.close(fd) + try: + save_npz(tmpfile, csr_matrix([[1.2, 0, 0.9], [0, 0.3, 0]])) + loaded_matrix = load_npz(tmpfile) + finally: + os.remove(tmpfile) + + #save/load array + fd, tmpfile = tempfile.mkstemp(suffix='.npz') + os.close(fd) + try: + save_npz(tmpfile, csr_array([[1.2, 0, 0.9], [0, 0.3, 0]])) + loaded_array = load_npz(tmpfile) + finally: + os.remove(tmpfile) + + assert not isinstance(loaded_matrix, sparray) + assert isinstance(loaded_array, sparray) + assert_(loaded_matrix.dtype == loaded_array.dtype) + assert_equal(loaded_matrix.toarray(), loaded_array.toarray()) + +@pytest.mark.parametrize("value", [0, 1.2]) +@pytest.mark.parametrize("ndim", [1, 2, 3]) +def test_nd_coo_format(ndim, value): + A = coo_array([value]).reshape((1,) * ndim) + + #save/load array + fd, tmpfile = tempfile.mkstemp(suffix='.npz') + os.close(fd) + try: + save_npz(tmpfile, A) + loaded_A = load_npz(tmpfile) + finally: + os.remove(tmpfile) + + assert isinstance(loaded_A, coo_array) + assert_(loaded_A.shape == A.shape) + assert_equal(A.toarray(), loaded_A.toarray()) + +def test_malicious_load(): + class Executor: + def __reduce__(self): + return (assert_, (False, 'unexpected code execution')) + + fd, tmpfile = tempfile.mkstemp(suffix='.npz') + os.close(fd) + try: + np.savez(tmpfile, format=Executor()) + + # Should raise a ValueError, not execute code + assert_raises(ValueError, load_npz, tmpfile) + finally: + os.remove(tmpfile) + + +def test_py23_compatibility(): + # Try loading files saved on Python 2 and Python 3. They are not + # the same, since files saved with SciPy versions < 1.0.0 may + # contain unicode. + + a = load_npz(os.path.join(DATA_DIR, 'csc_py2.npz')) + b = load_npz(os.path.join(DATA_DIR, 'csc_py3.npz')) + c = csc_matrix([[0]]) + + assert_equal(a.toarray(), c.toarray()) + assert_equal(b.toarray(), c.toarray()) + +def test_implemented_error(): + # Attempts to save an unsupported type and checks that an + # NotImplementedError is raised. + + x = dok_matrix((2,3)) + x[0,1] = 1 + + assert_raises(NotImplementedError, save_npz, 'x.npz', x) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_minmax1d.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_minmax1d.py new file mode 100644 index 0000000000000000000000000000000000000000..dca3f44fa485070805995c2f76c0c511123ce355 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_minmax1d.py @@ -0,0 +1,128 @@ +"""Test of min-max 1D features of sparse array classes""" + +import pytest + +import numpy as np + +from numpy.testing import assert_equal, assert_array_equal + +from scipy.sparse import coo_array, csr_array, csc_array, bsr_array +from scipy.sparse import coo_matrix, csr_matrix, csc_matrix, bsr_matrix +from scipy.sparse._sputils import isscalarlike + + +def toarray(a): + if isinstance(a, np.ndarray) or isscalarlike(a): + return a + return a.toarray() + + +formats_for_minmax = [bsr_array, coo_array, csc_array, csr_array] +formats_for_minmax_supporting_1d = [coo_array, csr_array] + + +@pytest.mark.parametrize("spcreator", formats_for_minmax_supporting_1d) +class Test_MinMaxMixin1D: + def test_minmax(self, spcreator): + D = np.arange(5) + X = spcreator(D) + + assert_equal(X.min(), 0) + assert_equal(X.max(), 4) + assert_equal((-X).min(), -4) + assert_equal((-X).max(), 0) + + def test_minmax_axis(self, spcreator): + D = np.arange(50) + X = spcreator(D) + + for axis in [0, -1]: + assert_array_equal( + toarray(X.max(axis=axis)), D.max(axis=axis, keepdims=True) + ) + assert_array_equal( + toarray(X.min(axis=axis)), D.min(axis=axis, keepdims=True) + ) + for axis in [-2, 1]: + with pytest.raises(ValueError, match="axis out of range"): + X.min(axis=axis) + with pytest.raises(ValueError, match="axis out of range"): + X.max(axis=axis) + + def test_numpy_minmax(self, spcreator): + dat = np.array([0, 1, 2]) + datsp = spcreator(dat) + assert_array_equal(np.min(datsp), np.min(dat)) + assert_array_equal(np.max(datsp), np.max(dat)) + + + def test_argmax(self, spcreator): + D1 = np.array([-1, 5, 2, 3]) + D2 = np.array([0, 0, -1, -2]) + D3 = np.array([-1, -2, -3, -4]) + D4 = np.array([1, 2, 3, 4]) + D5 = np.array([1, 2, 0, 0]) + + for D in [D1, D2, D3, D4, D5]: + mat = spcreator(D) + + assert_equal(mat.argmax(), np.argmax(D)) + assert_equal(mat.argmin(), np.argmin(D)) + + assert_equal(mat.argmax(axis=0), np.argmax(D, axis=0)) + assert_equal(mat.argmin(axis=0), np.argmin(D, axis=0)) + + D6 = np.empty((0,)) + + for axis in [None, 0]: + mat = spcreator(D6) + with pytest.raises(ValueError, match="to an empty matrix"): + mat.argmin(axis=axis) + with pytest.raises(ValueError, match="to an empty matrix"): + mat.argmax(axis=axis) + + +@pytest.mark.parametrize("spcreator", formats_for_minmax) +class Test_ShapeMinMax2DWithAxis: + def test_minmax(self, spcreator): + dat = np.array([[-1, 5, 0, 3], [0, 0, -1, -2], [0, 0, 1, 2]]) + datsp = spcreator(dat) + + for (spminmax, npminmax) in [ + (datsp.min, np.min), + (datsp.max, np.max), + (datsp.nanmin, np.nanmin), + (datsp.nanmax, np.nanmax), + ]: + for ax, result_shape in [(0, (4,)), (1, (3,))]: + assert_equal(toarray(spminmax(axis=ax)), npminmax(dat, axis=ax)) + assert_equal(spminmax(axis=ax).shape, result_shape) + assert spminmax(axis=ax).format == "coo" + + for spminmax in [datsp.argmin, datsp.argmax]: + for ax in [0, 1]: + assert isinstance(spminmax(axis=ax), np.ndarray) + + # verify spmatrix behavior + spmat_form = { + 'coo': coo_matrix, + 'csr': csr_matrix, + 'csc': csc_matrix, + 'bsr': bsr_matrix, + } + datspm = spmat_form[datsp.format](dat) + + for spm, npm in [ + (datspm.min, np.min), + (datspm.max, np.max), + (datspm.nanmin, np.nanmin), + (datspm.nanmax, np.nanmax), + ]: + for ax, result_shape in [(0, (1, 4)), (1, (3, 1))]: + assert_equal(toarray(spm(axis=ax)), npm(dat, axis=ax, keepdims=True)) + assert_equal(spm(axis=ax).shape, result_shape) + assert spm(axis=ax).format == "coo" + + for spminmax in [datspm.argmin, datspm.argmax]: + for ax in [0, 1]: + assert isinstance(spminmax(axis=ax), np.ndarray) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_sparsetools.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_sparsetools.py new file mode 100644 index 0000000000000000000000000000000000000000..6ac2f2b0efd4de1d9b947dc0bc28b14881bc9db2 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_sparsetools.py @@ -0,0 +1,340 @@ +import sys +import os +import gc +import threading + +import numpy as np +from numpy.testing import assert_equal, assert_, assert_allclose +from scipy.sparse import (_sparsetools, coo_matrix, csr_matrix, csc_matrix, + bsr_matrix, dia_matrix) +from scipy.sparse._sputils import supported_dtypes +from scipy._lib._testutils import check_free_memory + +import pytest +from pytest import raises as assert_raises + + +def int_to_int8(n): + """ + Wrap an integer to the interval [-128, 127]. + """ + return (n + 128) % 256 - 128 + + +def test_exception(): + assert_raises(MemoryError, _sparsetools.test_throw_error) + + +def test_threads(): + # Smoke test for parallel threaded execution; doesn't actually + # check that code runs in parallel, but just that it produces + # expected results. + nthreads = 10 + niter = 100 + + n = 20 + a = csr_matrix(np.ones([n, n])) + bres = [] + + class Worker(threading.Thread): + def run(self): + b = a.copy() + for j in range(niter): + _sparsetools.csr_plus_csr(n, n, + a.indptr, a.indices, a.data, + a.indptr, a.indices, a.data, + b.indptr, b.indices, b.data) + bres.append(b) + + threads = [Worker() for _ in range(nthreads)] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + + for b in bres: + assert_(np.all(b.toarray() == 2)) + + +def test_regression_std_vector_dtypes(): + # Regression test for gh-3780, checking the std::vector typemaps + # in sparsetools.cxx are complete. + for dtype in supported_dtypes: + ad = np.array([[1, 2], [3, 4]]).astype(dtype) + a = csr_matrix(ad, dtype=dtype) + + # getcol is one function using std::vector typemaps, and should not fail + assert_equal(a.getcol(0).toarray(), ad[:, :1]) + + +@pytest.mark.slow +@pytest.mark.xfail_on_32bit("Can't create large array for test") +def test_nnz_overflow(): + # Regression test for gh-7230 / gh-7871, checking that coo_toarray + # with nnz > int32max doesn't overflow. + nnz = np.iinfo(np.int32).max + 1 + # Ensure ~20 GB of RAM is free to run this test. + check_free_memory((4 + 4 + 1) * nnz / 1e6 + 0.5) + + # Use nnz duplicate entries to keep the dense version small. + row = np.zeros(nnz, dtype=np.int32) + col = np.zeros(nnz, dtype=np.int32) + data = np.zeros(nnz, dtype=np.int8) + data[-1] = 4 + s = coo_matrix((data, (row, col)), shape=(1, 1), copy=False) + # Sums nnz duplicates to produce a 1x1 array containing 4. + d = s.toarray() + + assert_allclose(d, [[4]]) + + +@pytest.mark.skipif( + not (sys.platform.startswith('linux') and np.dtype(np.intp).itemsize >= 8), + reason="test requires 64-bit Linux" +) +class TestInt32Overflow: + """ + Some of the sparsetools routines use dense 2D matrices whose + total size is not bounded by the nnz of the sparse matrix. These + routines used to suffer from int32 wraparounds; here, we try to + check that the wraparounds don't occur any more. + """ + # choose n large enough + n = 50000 + + def setup_method(self): + assert self.n**2 > np.iinfo(np.int32).max + + # check there's enough memory even if everything is run at the + # same time + try: + parallel_count = int(os.environ.get('PYTEST_XDIST_WORKER_COUNT', '1')) + except ValueError: + parallel_count = np.inf + + check_free_memory(3000 * parallel_count) + + def teardown_method(self): + gc.collect() + + @pytest.mark.fail_slow(2) # keep in fast set, only non-slow test + def test_coo_todense(self): + # Check *_todense routines (cf. gh-2179) + # + # All of them in the end call coo_matrix.todense + + n = self.n + + i = np.array([0, n-1]) + j = np.array([0, n-1]) + data = np.array([1, 2], dtype=np.int8) + m = coo_matrix((data, (i, j))) + + r = m.todense() + assert_equal(r[0,0], 1) + assert_equal(r[-1,-1], 2) + del r + gc.collect() + + @pytest.mark.slow + def test_matvecs(self): + # Check *_matvecs routines + n = self.n + + i = np.array([0, n-1]) + j = np.array([0, n-1]) + data = np.array([1, 2], dtype=np.int8) + m = coo_matrix((data, (i, j))) + + b = np.ones((n, n), dtype=np.int8) + for sptype in (csr_matrix, csc_matrix, bsr_matrix): + m2 = sptype(m) + r = m2.dot(b) + assert_equal(r[0,0], 1) + assert_equal(r[-1,-1], 2) + del r + gc.collect() + + del b + gc.collect() + + @pytest.mark.slow + def test_dia_matvec(self): + # Check: huge dia_matrix _matvec + n = self.n + data = np.ones((n, n), dtype=np.int8) + offsets = np.arange(n) + m = dia_matrix((data, offsets), shape=(n, n)) + v = np.ones(m.shape[1], dtype=np.int8) + r = m.dot(v) + assert_equal(r[0], int_to_int8(n)) + del data, offsets, m, v, r + gc.collect() + + _bsr_ops = [pytest.param("matmat", marks=pytest.mark.xslow), + pytest.param("matvecs", marks=pytest.mark.xslow), + "matvec", + "diagonal", + "sort_indices", + pytest.param("transpose", marks=pytest.mark.xslow)] + + @pytest.mark.slow + @pytest.mark.parametrize("op", _bsr_ops) + def test_bsr_1_block(self, op): + # Check: huge bsr_matrix (1-block) + # + # The point here is that indices inside a block may overflow. + + def get_matrix(): + n = self.n + data = np.ones((1, n, n), dtype=np.int8) + indptr = np.array([0, 1], dtype=np.int32) + indices = np.array([0], dtype=np.int32) + m = bsr_matrix((data, indices, indptr), blocksize=(n, n), copy=False) + del data, indptr, indices + return m + + gc.collect() + try: + getattr(self, "_check_bsr_" + op)(get_matrix) + finally: + gc.collect() + + @pytest.mark.slow + @pytest.mark.parametrize("op", _bsr_ops) + def test_bsr_n_block(self, op): + # Check: huge bsr_matrix (n-block) + # + # The point here is that while indices within a block don't + # overflow, accumulators across many block may. + + def get_matrix(): + n = self.n + data = np.ones((n, n, 1), dtype=np.int8) + indptr = np.array([0, n], dtype=np.int32) + indices = np.arange(n, dtype=np.int32) + m = bsr_matrix((data, indices, indptr), blocksize=(n, 1), copy=False) + del data, indptr, indices + return m + + gc.collect() + try: + getattr(self, "_check_bsr_" + op)(get_matrix) + finally: + gc.collect() + + def _check_bsr_matvecs(self, m): # skip name check + m = m() + n = self.n + + # _matvecs + r = m.dot(np.ones((n, 2), dtype=np.int8)) + assert_equal(r[0, 0], int_to_int8(n)) + + def _check_bsr_matvec(self, m): # skip name check + m = m() + n = self.n + + # _matvec + r = m.dot(np.ones((n,), dtype=np.int8)) + assert_equal(r[0], int_to_int8(n)) + + def _check_bsr_diagonal(self, m): # skip name check + m = m() + n = self.n + + # _diagonal + r = m.diagonal() + assert_equal(r, np.ones(n)) + + def _check_bsr_sort_indices(self, m): # skip name check + # _sort_indices + m = m() + m.sort_indices() + + def _check_bsr_transpose(self, m): # skip name check + # _transpose + m = m() + m.transpose() + + def _check_bsr_matmat(self, m): # skip name check + m = m() + n = self.n + + # _bsr_matmat + m2 = bsr_matrix(np.ones((n, 2), dtype=np.int8), blocksize=(m.blocksize[1], 2)) + m.dot(m2) # shouldn't SIGSEGV + del m2 + + # _bsr_matmat + m2 = bsr_matrix(np.ones((2, n), dtype=np.int8), blocksize=(2, m.blocksize[0])) + m2.dot(m) # shouldn't SIGSEGV + + +@pytest.mark.skip(reason="64-bit indices in sparse matrices not available") +def test_csr_matmat_int64_overflow(): + n = 3037000500 + assert n**2 > np.iinfo(np.int64).max + + # the test would take crazy amounts of memory + check_free_memory(n * (8*2 + 1) * 3 / 1e6) + + # int64 overflow + data = np.ones((n,), dtype=np.int8) + indptr = np.arange(n+1, dtype=np.int64) + indices = np.zeros(n, dtype=np.int64) + a = csr_matrix((data, indices, indptr)) + b = a.T + + assert_raises(RuntimeError, a.dot, b) + + +def test_upcast(): + a0 = csr_matrix([[np.pi, np.pi*1j], [3, 4]], dtype=complex) + b0 = np.array([256+1j, 2**32], dtype=complex) + + for a_dtype in supported_dtypes: + for b_dtype in supported_dtypes: + msg = f"({a_dtype!r}, {b_dtype!r})" + + if np.issubdtype(a_dtype, np.complexfloating): + a = a0.copy().astype(a_dtype) + else: + a = a0.real.copy().astype(a_dtype) + + if np.issubdtype(b_dtype, np.complexfloating): + b = b0.copy().astype(b_dtype) + else: + with np.errstate(invalid="ignore"): + # Casting a large value (2**32) to int8 causes a warning in + # numpy >1.23 + b = b0.real.copy().astype(b_dtype) + + if not (a_dtype == np.bool_ and b_dtype == np.bool_): + c = np.zeros((2,), dtype=np.bool_) + assert_raises(ValueError, _sparsetools.csr_matvec, + 2, 2, a.indptr, a.indices, a.data, b, c) + + if ((np.issubdtype(a_dtype, np.complexfloating) and + not np.issubdtype(b_dtype, np.complexfloating)) or + (not np.issubdtype(a_dtype, np.complexfloating) and + np.issubdtype(b_dtype, np.complexfloating))): + c = np.zeros((2,), dtype=np.float64) + assert_raises(ValueError, _sparsetools.csr_matvec, + 2, 2, a.indptr, a.indices, a.data, b, c) + + c = np.zeros((2,), dtype=np.result_type(a_dtype, b_dtype)) + _sparsetools.csr_matvec(2, 2, a.indptr, a.indices, a.data, b, c) + assert_allclose(c, np.dot(a.toarray(), b), err_msg=msg) + + +def test_endianness(): + d = np.ones((3,4)) + offsets = [-1,0,1] + + a = dia_matrix((d.astype('f8'), offsets), (4, 4)) + v = np.arange(4) + + assert_allclose(a.dot(v), [1, 3, 6, 5]) + assert_allclose(b.dot(v), [1, 3, 6, 5]) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_spfuncs.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_spfuncs.py new file mode 100644 index 0000000000000000000000000000000000000000..75bc2d92c369be5799a904bc0938617f30321f12 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_spfuncs.py @@ -0,0 +1,97 @@ +from numpy import array, kron, diag +from numpy.testing import assert_, assert_equal + +from scipy.sparse import _spfuncs as spfuncs +from scipy.sparse import csr_matrix, csc_matrix, bsr_matrix +from scipy.sparse._sparsetools import (csr_scale_rows, csr_scale_columns, + bsr_scale_rows, bsr_scale_columns) + + +class TestSparseFunctions: + def test_scale_rows_and_cols(self): + D = array([[1, 0, 0, 2, 3], + [0, 4, 0, 5, 0], + [0, 0, 6, 7, 0]]) + + #TODO expose through function + S = csr_matrix(D) + v = array([1,2,3]) + csr_scale_rows(3,5,S.indptr,S.indices,S.data,v) + assert_equal(S.toarray(), diag(v)@D) + + S = csr_matrix(D) + v = array([1,2,3,4,5]) + csr_scale_columns(3,5,S.indptr,S.indices,S.data,v) + assert_equal(S.toarray(), D@diag(v)) + + # blocks + E = kron(D,[[1,2],[3,4]]) + S = bsr_matrix(E,blocksize=(2,2)) + v = array([1,2,3,4,5,6]) + bsr_scale_rows(3,5,2,2,S.indptr,S.indices,S.data,v) + assert_equal(S.toarray(), diag(v)@E) + + S = bsr_matrix(E,blocksize=(2,2)) + v = array([1,2,3,4,5,6,7,8,9,10]) + bsr_scale_columns(3,5,2,2,S.indptr,S.indices,S.data,v) + assert_equal(S.toarray(), E@diag(v)) + + E = kron(D,[[1,2,3],[4,5,6]]) + S = bsr_matrix(E,blocksize=(2,3)) + v = array([1,2,3,4,5,6]) + bsr_scale_rows(3,5,2,3,S.indptr,S.indices,S.data,v) + assert_equal(S.toarray(), diag(v)@E) + + S = bsr_matrix(E,blocksize=(2,3)) + v = array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]) + bsr_scale_columns(3,5,2,3,S.indptr,S.indices,S.data,v) + assert_equal(S.toarray(), E@diag(v)) + + def test_estimate_blocksize(self): + mats = [] + mats.append([[0,1],[1,0]]) + mats.append([[1,1,0],[0,0,1],[1,0,1]]) + mats.append([[0],[0],[1]]) + mats = [array(x) for x in mats] + + blks = [] + blks.append([[1]]) + blks.append([[1,1],[1,1]]) + blks.append([[1,1],[0,1]]) + blks.append([[1,1,0],[1,0,1],[1,1,1]]) + blks = [array(x) for x in blks] + + for A in mats: + for B in blks: + X = kron(A,B) + r,c = spfuncs.estimate_blocksize(X) + assert_(r >= B.shape[0]) + assert_(c >= B.shape[1]) + + def test_count_blocks(self): + def gold(A,bs): + R,C = bs + I,J = A.nonzero() + return len(set(zip(I//R,J//C))) + + mats = [] + mats.append([[0]]) + mats.append([[1]]) + mats.append([[1,0]]) + mats.append([[1,1]]) + mats.append([[0,1],[1,0]]) + mats.append([[1,1,0],[0,0,1],[1,0,1]]) + mats.append([[0],[0],[1]]) + + for A in mats: + for B in mats: + X = kron(A,B) + Y = csr_matrix(X) + for R in range(1,6): + for C in range(1,6): + assert_equal(spfuncs.count_blocks(Y, (R, C)), gold(X, (R, C))) + + X = kron([[1,1,0],[0,0,1],[1,0,1]],[[1,1]]) + Y = csc_matrix(X) + assert_equal(spfuncs.count_blocks(X, (1, 2)), gold(X, (1, 2))) + assert_equal(spfuncs.count_blocks(Y, (1, 2)), gold(X, (1, 2))) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_sputils.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_sputils.py new file mode 100644 index 0000000000000000000000000000000000000000..345f89f8585cb6906794220ae74e172cf1f45cba --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/sparse/tests/test_sputils.py @@ -0,0 +1,424 @@ +"""unit tests for sparse utility functions""" + +import numpy as np +from numpy.testing import assert_equal +import pytest +from pytest import raises as assert_raises +from scipy.sparse import _sputils as sputils, csr_array, bsr_array, dia_array, coo_array +from scipy.sparse._sputils import matrix + + +class TestSparseUtils: + + def test_upcast(self): + assert_equal(sputils.upcast('intc'), np.intc) + assert_equal(sputils.upcast('int32', 'float32'), np.float64) + assert_equal(sputils.upcast('bool', complex, float), np.complex128) + assert_equal(sputils.upcast('i', 'd'), np.float64) + + def test_getdtype(self): + A = np.array([1], dtype='int8') + + assert_equal(sputils.getdtype(None, default=float), float) + assert_equal(sputils.getdtype(None, a=A), np.int8) + + with assert_raises( + ValueError, + match="scipy.sparse does not support dtype object. .*", + ): + sputils.getdtype("O") + + with assert_raises( + ValueError, + match="scipy.sparse does not support dtype float16. .*", + ): + sputils.getdtype(None, default=np.float16) + + def test_isscalarlike(self): + assert_equal(sputils.isscalarlike(3.0), True) + assert_equal(sputils.isscalarlike(-4), True) + assert_equal(sputils.isscalarlike(2.5), True) + assert_equal(sputils.isscalarlike(1 + 3j), True) + assert_equal(sputils.isscalarlike(np.array(3)), True) + assert_equal(sputils.isscalarlike("16"), True) + + assert_equal(sputils.isscalarlike(np.array([3])), False) + assert_equal(sputils.isscalarlike([[3]]), False) + assert_equal(sputils.isscalarlike((1,)), False) + assert_equal(sputils.isscalarlike((1, 2)), False) + + def test_isintlike(self): + assert_equal(sputils.isintlike(-4), True) + assert_equal(sputils.isintlike(np.array(3)), True) + assert_equal(sputils.isintlike(np.array([3])), False) + with assert_raises( + ValueError, + match="Inexact indices into sparse matrices are not allowed" + ): + sputils.isintlike(3.0) + + assert_equal(sputils.isintlike(2.5), False) + assert_equal(sputils.isintlike(1 + 3j), False) + assert_equal(sputils.isintlike((1,)), False) + assert_equal(sputils.isintlike((1, 2)), False) + + def test_isshape(self): + assert_equal(sputils.isshape((1, 2)), True) + assert_equal(sputils.isshape((5, 2)), True) + + assert_equal(sputils.isshape((1.5, 2)), False) + assert_equal(sputils.isshape((2, 2, 2)), False) + assert_equal(sputils.isshape(([2], 2)), False) + assert_equal(sputils.isshape((-1, 2), nonneg=False),True) + assert_equal(sputils.isshape((2, -1), nonneg=False),True) + assert_equal(sputils.isshape((-1, 2), nonneg=True),False) + assert_equal(sputils.isshape((2, -1), nonneg=True),False) + + assert_equal(sputils.isshape((1.5, 2), allow_nd=(1, 2)), False) + assert_equal(sputils.isshape(([2], 2), allow_nd=(1, 2)), False) + assert_equal(sputils.isshape((2, 2, -2), nonneg=True, allow_nd=(1, 2)), + False) + assert_equal(sputils.isshape((2,), allow_nd=(1, 2)), True) + assert_equal(sputils.isshape((2, 2,), allow_nd=(1, 2)), True) + assert_equal(sputils.isshape((2, 2, 2), allow_nd=(1, 2)), False) + + def test_issequence(self): + assert_equal(sputils.issequence((1,)), True) + assert_equal(sputils.issequence((1, 2, 3)), True) + assert_equal(sputils.issequence([1]), True) + assert_equal(sputils.issequence([1, 2, 3]), True) + assert_equal(sputils.issequence(np.array([1, 2, 3])), True) + + assert_equal(sputils.issequence(np.array([[1], [2], [3]])), False) + assert_equal(sputils.issequence(3), False) + + def test_ismatrix(self): + assert_equal(sputils.ismatrix(((),)), True) + assert_equal(sputils.ismatrix([[1], [2]]), True) + assert_equal(sputils.ismatrix(np.arange(3)[None]), True) + + assert_equal(sputils.ismatrix([1, 2]), False) + assert_equal(sputils.ismatrix(np.arange(3)), False) + assert_equal(sputils.ismatrix([[[1]]]), False) + assert_equal(sputils.ismatrix(3), False) + + def test_isdense(self): + assert_equal(sputils.isdense(np.array([1])), True) + assert_equal(sputils.isdense(matrix([1])), True) + + def test_validateaxis(self): + with assert_raises(ValueError, match="does not accept 0D axis"): + sputils.validateaxis(()) + + for ax in [1.5, (0, 1.5), (1.5, 0)]: + with assert_raises(TypeError, match="must be an integer"): + sputils.validateaxis(ax) + for ax in [(1, 1), (1, -1), (0, -2)]: + with assert_raises(ValueError, match="duplicate value in axis"): + sputils.validateaxis(ax) + + # ndim 1 + for ax in [1, -2, (0, 1), (1, -1)]: + with assert_raises(ValueError, match="out of range"): + sputils.validateaxis(ax, ndim=1) + with assert_raises(ValueError, match="duplicate value in axis"): + sputils.validateaxis((0, -1), ndim=1) + # all valid axis values lead to None when canonical + for axis in (0, -1, None, (0,), (-1,)): + assert sputils.validateaxis(axis, ndim=1) is None + + # ndim 2 + for ax in [5, -5, (0, 5), (-5, 0)]: + with assert_raises(ValueError, match="out of range"): + sputils.validateaxis(ax, ndim=2) + for axis in ((0,), (1,), None): + assert sputils.validateaxis(axis, ndim=2) == axis + axis_2d = {-2: (0,), -1: (1,), 0: (0,), 1: (1,), (0, 1): None, (0, -1): None} + for axis, canonical_axis in axis_2d.items(): + assert sputils.validateaxis(axis, ndim=2) == canonical_axis + + # ndim 4 + for axis in ((2,), (3,), (2, 3), (2, 1), (0, 3)): + assert sputils.validateaxis(axis, ndim=4) == axis + axis_4d = {-4: (0,), -3: (1,), 2: (2,), 3: (3,), (3, -4): (3, 0)} + for axis, canonical_axis in axis_4d.items(): + sputils.validateaxis(axis, ndim=4) == canonical_axis + + @pytest.mark.parametrize("container", [csr_array, bsr_array]) + def test_safely_cast_index_compressed(self, container): + # This is slow to test completely as nnz > imax is big + # and indptr is big for some shapes + # So we don't test large nnz, nor csc_array (same code as csr_array) + imax = np.int64(np.iinfo(np.int32).max) + + # Shape 32bit + A32 = container((1, imax)) + # indices big type, small values + B32 = A32.copy() + B32.indices = B32.indices.astype(np.int64) + B32.indptr = B32.indptr.astype(np.int64) + + # Shape 64bit + # indices big type, small values + A64 = csr_array((1, imax + 1)) + # indices small type, small values + B64 = A64.copy() + B64.indices = B64.indices.astype(np.int32) + B64.indptr = B64.indptr.astype(np.int32) + # indices big type, big values + C64 = A64.copy() + C64.indices = np.array([imax + 1], dtype=np.int64) + C64.indptr = np.array([0, 1], dtype=np.int64) + C64.data = np.array([2.2]) + + assert (A32.indices.dtype, A32.indptr.dtype) == (np.int32, np.int32) + assert (B32.indices.dtype, B32.indptr.dtype) == (np.int64, np.int64) + assert (A64.indices.dtype, A64.indptr.dtype) == (np.int64, np.int64) + assert (B64.indices.dtype, B64.indptr.dtype) == (np.int32, np.int32) + assert (C64.indices.dtype, C64.indptr.dtype) == (np.int64, np.int64) + + for A in [A32, B32, A64, B64]: + indices, indptr = sputils.safely_cast_index_arrays(A, np.int32) + assert (indices.dtype, indptr.dtype) == (np.int32, np.int32) + indices, indptr = sputils.safely_cast_index_arrays(A, np.int64) + assert (indices.dtype, indptr.dtype) == (np.int64, np.int64) + + indices, indptr = sputils.safely_cast_index_arrays(A, A.indices.dtype) + assert indices is A.indices + assert indptr is A.indptr + + with assert_raises(ValueError): + sputils.safely_cast_index_arrays(C64, np.int32) + indices, indptr = sputils.safely_cast_index_arrays(C64, np.int64) + assert indices is C64.indices + assert indptr is C64.indptr + + def test_safely_cast_index_coo(self): + # This is slow to test completely as nnz > imax is big + # So we don't test large nnz + imax = np.int64(np.iinfo(np.int32).max) + + # Shape 32bit + A32 = coo_array((1, imax)) + # coords big type, small values + B32 = A32.copy() + B32.coords = tuple(co.astype(np.int64) for co in B32.coords) + + # Shape 64bit + # coords big type, small values + A64 = coo_array((1, imax + 1)) + # coords small type, small values + B64 = A64.copy() + B64.coords = tuple(co.astype(np.int32) for co in B64.coords) + # coords big type, big values + C64 = A64.copy() + C64.coords = (np.array([imax + 1]), np.array([0])) + C64.data = np.array([2.2]) + + assert A32.coords[0].dtype == np.int32 + assert B32.coords[0].dtype == np.int64 + assert A64.coords[0].dtype == np.int64 + assert B64.coords[0].dtype == np.int32 + assert C64.coords[0].dtype == np.int64 + + for A in [A32, B32, A64, B64]: + coords = sputils.safely_cast_index_arrays(A, np.int32) + assert coords[0].dtype == np.int32 + coords = sputils.safely_cast_index_arrays(A, np.int64) + assert coords[0].dtype == np.int64 + + coords = sputils.safely_cast_index_arrays(A, A.coords[0].dtype) + assert coords[0] is A.coords[0] + + with assert_raises(ValueError): + sputils.safely_cast_index_arrays(C64, np.int32) + coords = sputils.safely_cast_index_arrays(C64, np.int64) + assert coords[0] is C64.coords[0] + + def test_safely_cast_index_dia(self): + # This is slow to test completely as nnz > imax is big + # So we don't test large nnz + imax = np.int64(np.iinfo(np.int32).max) + + # Shape 32bit + A32 = dia_array((1, imax)) + # offsets big type, small values + B32 = A32.copy() + B32.offsets = B32.offsets.astype(np.int64) + + # Shape 64bit + # offsets big type, small values + A64 = dia_array((1, imax + 2)) + # offsets small type, small values + B64 = A64.copy() + B64.offsets = B64.offsets.astype(np.int32) + # offsets big type, big values + C64 = A64.copy() + C64.offsets = np.array([imax + 1]) + C64.data = np.array([2.2]) + + assert A32.offsets.dtype == np.int32 + assert B32.offsets.dtype == np.int64 + assert A64.offsets.dtype == np.int64 + assert B64.offsets.dtype == np.int32 + assert C64.offsets.dtype == np.int64 + + for A in [A32, B32, A64, B64]: + offsets = sputils.safely_cast_index_arrays(A, np.int32) + assert offsets.dtype == np.int32 + offsets = sputils.safely_cast_index_arrays(A, np.int64) + assert offsets.dtype == np.int64 + + offsets = sputils.safely_cast_index_arrays(A, A.offsets.dtype) + assert offsets is A.offsets + + with assert_raises(ValueError): + sputils.safely_cast_index_arrays(C64, np.int32) + offsets = sputils.safely_cast_index_arrays(C64, np.int64) + assert offsets is C64.offsets + + def test_get_index_dtype(self): + imax = np.int64(np.iinfo(np.int32).max) + too_big = imax + 1 + + # Check that uint32's with no values too large doesn't return + # int64 + a1 = np.ones(90, dtype='uint32') + a2 = np.ones(90, dtype='uint32') + assert_equal( + np.dtype(sputils.get_index_dtype((a1, a2), check_contents=True)), + np.dtype('int32') + ) + + # Check that if we can not convert but all values are less than or + # equal to max that we can just convert to int32 + a1[-1] = imax + assert_equal( + np.dtype(sputils.get_index_dtype((a1, a2), check_contents=True)), + np.dtype('int32') + ) + + # Check that if it can not convert directly and the contents are + # too large that we return int64 + a1[-1] = too_big + assert_equal( + np.dtype(sputils.get_index_dtype((a1, a2), check_contents=True)), + np.dtype('int64') + ) + + # test that if can not convert and didn't specify to check_contents + # we return int64 + a1 = np.ones(89, dtype='uint32') + a2 = np.ones(89, dtype='uint32') + assert_equal( + np.dtype(sputils.get_index_dtype((a1, a2))), + np.dtype('int64') + ) + + # Check that even if we have arrays that can be converted directly + # that if we specify a maxval directly it takes precedence + a1 = np.ones(12, dtype='uint32') + a2 = np.ones(12, dtype='uint32') + assert_equal( + np.dtype(sputils.get_index_dtype( + (a1, a2), maxval=too_big, check_contents=True + )), + np.dtype('int64') + ) + + # Check that an array with a too max size and maxval set + # still returns int64 + a1[-1] = too_big + assert_equal( + np.dtype(sputils.get_index_dtype((a1, a2), maxval=too_big)), + np.dtype('int64') + ) + + # tests public broadcast_shapes largely from + # numpy/numpy/lib/tests/test_stride_tricks.py + # first 3 cause np.broadcast to raise index too large, but not sputils + @pytest.mark.parametrize("input_shapes,target_shape", [ + [((6, 5, 1, 4, 1, 1), (1, 2**32), (2**32, 1)), (6, 5, 1, 4, 2**32, 2**32)], + [((6, 5, 1, 4, 1, 1), (1, 2**32)), (6, 5, 1, 4, 1, 2**32)], + [((1, 2**32), (2**32, 1)), (2**32, 2**32)], + [[2, 2, 2], (2,)], + [[], ()], + [[()], ()], + [[(7,)], (7,)], + [[(1, 2), (2,)], (1, 2)], + [[(2,), (1, 2)], (1, 2)], + [[(1, 1)], (1, 1)], + [[(1, 1), (3, 4)], (3, 4)], + [[(6, 7), (5, 6, 1), (7,), (5, 1, 7)], (5, 6, 7)], + [[(5, 6, 1)], (5, 6, 1)], + [[(1, 3), (3, 1)], (3, 3)], + [[(1, 0), (0, 0)], (0, 0)], + [[(0, 1), (0, 0)], (0, 0)], + [[(1, 0), (0, 1)], (0, 0)], + [[(1, 1), (0, 0)], (0, 0)], + [[(1, 1), (1, 0)], (1, 0)], + [[(1, 1), (0, 1)], (0, 1)], + [[(), (0,)], (0,)], + [[(0,), (0, 0)], (0, 0)], + [[(0,), (0, 1)], (0, 0)], + [[(1,), (0, 0)], (0, 0)], + [[(), (0, 0)], (0, 0)], + [[(1, 1), (0,)], (1, 0)], + [[(1,), (0, 1)], (0, 1)], + [[(1,), (1, 0)], (1, 0)], + [[(), (1, 0)], (1, 0)], + [[(), (0, 1)], (0, 1)], + [[(1,), (3,)], (3,)], + [[2, (3, 2)], (3, 2)], + [[(1, 2)] * 32, (1, 2)], + [[(1, 2)] * 100, (1, 2)], + [[(2,)] * 32, (2,)], + ]) + def test_broadcast_shapes_successes(self, input_shapes, target_shape): + assert_equal(sputils.broadcast_shapes(*input_shapes), target_shape) + + # tests public broadcast_shapes failures + @pytest.mark.parametrize("input_shapes", [ + [(3,), (4,)], + [(2, 3), (2,)], + [2, (2, 3)], + [(3,), (3,), (4,)], + [(2, 5), (3, 5)], + [(2, 4), (2, 5)], + [(1, 3, 4), (2, 3, 3)], + [(1, 2), (3, 1), (3, 2), (10, 5)], + [(2,)] * 32 + [(3,)] * 32, + ]) + def test_broadcast_shapes_failures(self, input_shapes): + with assert_raises(ValueError, match="cannot be broadcast"): + sputils.broadcast_shapes(*input_shapes) + + def test_check_shape_overflow(self): + new_shape = sputils.check_shape([(10, -1)], (65535, 131070)) + assert_equal(new_shape, (10, 858967245)) + + def test_matrix(self): + a = [[1, 2, 3]] + b = np.array(a) + + assert isinstance(sputils.matrix(a), np.matrix) + assert isinstance(sputils.matrix(b), np.matrix) + + c = sputils.matrix(b) + c[:, :] = 123 + assert_equal(b, a) + + c = sputils.matrix(b, copy=False) + c[:, :] = 123 + assert_equal(b, [[123, 123, 123]]) + + def test_asmatrix(self): + a = [[1, 2, 3]] + b = np.array(a) + + assert isinstance(sputils.asmatrix(a), np.matrix) + assert isinstance(sputils.asmatrix(b), np.matrix) + + c = sputils.asmatrix(b) + c[:, :] = 123 + assert_equal(b, [[123, 123, 123]]) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a3f87fe7d1b955dd140e59972fa4b6db56ac5e57 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/_geometric_slerp.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/_geometric_slerp.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d377a9da93d62d184fe9d8e78e41d72d35867615 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/_geometric_slerp.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/_kdtree.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/_kdtree.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3a804bb56132224a8df93ed27ba40b8145cc616c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/_kdtree.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/_plotutils.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/_plotutils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b6babfedaf5cc283e261a0dd4e637a4d3d1449dc Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/_plotutils.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/_procrustes.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/_procrustes.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..edb7042447e575b954982689d1b380238a52ff7c Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/_procrustes.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/_spherical_voronoi.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/_spherical_voronoi.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21191ec2ebfcb8485e7ee67434f7c940c4b43d7f Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/_spherical_voronoi.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/ckdtree.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/ckdtree.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dcd125d4e2507350ed68c6e1f81334c280234be8 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/ckdtree.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/kdtree.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/kdtree.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ecdaaef44bf91a85019d271e9f872923d5d22231 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/kdtree.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/qhull.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/qhull.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..620e38902d86feda48d9db7a26cea7443aed6f35 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/__pycache__/qhull.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/qhull_src/COPYING_QHULL.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/qhull_src/COPYING_QHULL.txt new file mode 100644 index 0000000000000000000000000000000000000000..122a00a4fa9933794601dca8bff713b4ea1459dc --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/qhull_src/COPYING_QHULL.txt @@ -0,0 +1,39 @@ + Qhull, Copyright (c) 1993-2020 + + C.B. Barber + Arlington, MA + + and + + The National Science and Technology Research Center for + Computation and Visualization of Geometric Structures + (The Geometry Center) + University of Minnesota + + email: qhull@qhull.org + +This software includes Qhull from C.B. Barber and The Geometry Center. +Files derived from Qhull 1.0 are copyrighted by the Geometry Center. The +remaining files are copyrighted by C.B. Barber. Qhull is free software +and may be obtained via http from www.qhull.org. It may be freely copied, +modified, and redistributed under the following conditions: + +1. All copyright notices must remain intact in all files. + +2. A copy of this text file must be distributed along with any copies + of Qhull that you redistribute; this includes copies that you have + modified, or copies of programs or other software products that + include Qhull. + +3. If you modify Qhull, you must include a notice giving the + name of the person performing the modification, the date of + modification, and the reason for such modification. + +4. When distributing modified versions of Qhull, or other software + products that include Qhull, you must provide notice that the original + source code may be obtained as noted above. + +5. There is no warranty or other guarantee of fitness for Qhull, it is + provided solely "as is". Bug reports or fixes may be sent to + qhull_bug@qhull.org; the authors may or may not act on them as + they desire. diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/__init__.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..31ca69ba8b748758869d3dcf282d7bd5d8fff67a Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test__plotutils.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test__plotutils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac067cdafa18bbb86e207752650243cb4da4ba43 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test__plotutils.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test__procrustes.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test__procrustes.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7c676b0358817d0772d8345feb862aaf37908bcb Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test__procrustes.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test_hausdorff.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test_hausdorff.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fe57f67aa747c791d389cc13afb903fcef24fd56 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test_hausdorff.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test_kdtree.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test_kdtree.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9768b742b0c7862d355be6d85dff39d27a2270ec Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test_kdtree.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test_qhull.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test_qhull.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..127d7021a83cd4ed2e0836719610d77f3e797770 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test_qhull.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test_slerp.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test_slerp.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..711d6a8f3b98da313b67dec65cbb25d9148c6953 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test_slerp.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test_spherical_voronoi.cpython-312.pyc b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test_spherical_voronoi.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..adbad6b67cdb332764515690e87731916cbc4664 Binary files /dev/null and b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/__pycache__/test_spherical_voronoi.cpython-312.pyc differ diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/cdist-X1.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/cdist-X1.txt new file mode 100644 index 0000000000000000000000000000000000000000..833d5bdf2a344f585c5f34faa3e22716b1aa363c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/cdist-X1.txt @@ -0,0 +1,10 @@ +1.147593763490969421e-01 8.926156143344999849e-01 1.437758624645746330e-02 1.803435962879929022e-02 5.533046214065578949e-01 5.554315640747428118e-01 4.497546637814608950e-02 4.438089247948049376e-01 7.984582810220538507e-01 2.752880789161644692e-01 1.344667112315823809e-01 9.230479561452992199e-01 6.040471462941819913e-01 3.797251652770228247e-01 4.316042735592399149e-01 5.312356915348823705e-01 4.348143005129563310e-01 3.111531488508799681e-01 9.531194313908697424e-04 8.212995023500069269e-02 6.689953269869852726e-01 9.914864535288493430e-01 8.037556036341153565e-01 +9.608925123801395074e-01 2.974451233678974127e-01 9.001110330654185088e-01 5.824163330415995654e-01 7.308574928293812834e-01 2.276154562412870952e-01 7.306791076039623745e-01 8.677244866905511333e-01 9.160806456176984192e-01 6.157216959991280714e-01 5.149053524695440531e-01 3.056427344890983999e-01 9.790557366933895223e-01 4.484995861076724877e-01 4.776550391081165747e-01 7.210436977670631187e-01 9.136399501661039979e-01 4.260275733550000776e-02 5.943900041968954717e-01 3.864571606342745991e-01 9.442027665110838131e-01 4.779949058608601309e-02 6.107551944250865228e-01 +3.297286578103622023e-01 5.980207401936733502e-01 3.673301293561567205e-01 2.585830520887681949e-01 4.660558746104259686e-01 6.083795956610364986e-01 4.535206368070313632e-01 6.873989778785424276e-01 5.130152688495458468e-01 7.665877846542720198e-01 3.444402973525138023e-01 3.583658123644906102e-02 7.924818220986856732e-01 8.746685720522412444e-01 3.010105569182431884e-01 6.012239357385538163e-01 6.233737362204671006e-01 4.830438698668915176e-01 2.317286885842551047e-02 7.585989958123050547e-01 7.108257632278830451e-01 1.551024884178199281e-01 2.665485998155288083e-01 +2.456278068903017253e-02 4.148739837711815648e-01 1.986372227934196655e-01 6.920408530298168825e-01 1.003067576685774398e-01 7.421560456480125190e-01 1.808453980608998313e-01 4.251297882537475870e-01 6.773002683522370004e-01 4.084108792570182445e-01 7.462888013191590897e-01 8.069930220529277776e-01 9.211110587681808903e-01 4.141491046181076108e-01 7.486318689260342829e-01 9.515405507589296263e-01 4.634288892577109742e-03 8.027593488166355762e-01 3.010346805217798405e-01 8.663248877242523127e-01 2.479968181181605447e-01 5.619851096054278017e-01 3.903886764590250857e-01 +7.122019976035700584e-01 6.188878051047785878e-01 7.290897087051201320e-01 6.334802157757637442e-01 5.523084734954342156e-01 5.614937129563645213e-01 2.496741051791574462e-01 5.972227939599233926e-01 1.786590597761109622e-01 2.609525984850900038e-01 7.210438943286010538e-01 2.211429064605652250e-01 9.140497572472672250e-02 1.430242193668443962e-01 7.856446942916397447e-01 4.635256358156553125e-01 5.278744289813760426e-01 3.702808015407184072e-01 5.527073830480792038e-01 6.370732917599846168e-01 9.953487928925482953e-01 3.021789770611936765e-01 3.354901923998221402e-02 +6.509638560895427695e-01 8.387598220902757751e-01 7.761375971745763103e-01 1.481627639227802717e-01 3.529474982902305324e-01 4.883093646287851586e-01 9.652923033658690199e-01 9.500680513565308294e-01 3.061885005078281985e-01 7.271902818906019750e-01 2.358962978196710303e-03 7.359889703223099211e-01 8.988893768074724955e-01 4.135279653937307121e-02 8.516441856688283796e-01 4.889597623270667270e-01 5.575909822114655245e-01 9.010853652261575641e-01 2.912844516556202246e-01 9.088759383368658629e-01 8.104351227460024898e-01 8.080695436776826890e-01 1.430530913253185155e-01 +8.048001196608134400e-01 3.066089444418462762e-02 9.021887554292090661e-01 6.154331491807940591e-02 1.378912575206647784e-02 5.775720193142440673e-01 1.219298963069791464e-01 1.883270243412101808e-01 5.569262398688379356e-02 8.964817777510125651e-02 7.977092785346929782e-01 4.878149375226197293e-01 4.511973131518809410e-02 1.858690046801604323e-01 6.947686471083162063e-01 5.884058794291086025e-01 8.638884676612634816e-01 3.855470871341656336e-01 3.495049047300468059e-01 2.767740932353948136e-01 4.731087031714035218e-01 6.679001673437914288e-01 7.502944200696660682e-01 +6.527328264244687261e-01 8.289483383553154505e-01 9.179741348282299818e-01 1.065639864466713105e-01 6.253616929058514184e-01 5.927750325266062381e-01 3.039157425463192563e-01 2.452766763359194302e-01 6.514027700704632107e-01 5.529218485487964463e-01 4.941158239308394151e-01 6.605306467722642516e-01 2.273688037050677346e-01 4.282616592244774534e-01 2.956128257930247250e-01 1.154803628237965896e-01 9.228220410235263849e-01 6.663525307676617659e-01 1.908852615936970087e-01 9.921383408926374159e-01 4.988716450388516188e-01 1.014900352736023414e-01 3.363930180244284474e-01 +2.914369076275757919e-01 5.196673601143533272e-01 7.420144907858341465e-01 1.768984185504740569e-01 5.296766993228564369e-01 5.922023566159900776e-01 5.965161262020234334e-01 3.810272333046110793e-01 8.368797246118340194e-01 7.896422363801189892e-01 9.655797561098209414e-01 4.430034032346981121e-01 2.780869795706976122e-01 3.047310845416009162e-01 8.051138863500326703e-01 6.731468634690835895e-01 4.743383036815584930e-01 9.530709614322225853e-01 7.753587619850917934e-01 2.801137109357491051e-01 6.182543660889736614e-01 5.005218857766725593e-01 9.071447804755052857e-01 +2.075071644012620453e-01 4.834950086973934802e-01 3.037011473860764532e-01 6.476084284887700937e-01 8.107195771564194020e-01 7.869075869075803364e-01 6.851234019375299633e-01 3.544187468104398331e-02 4.847673235908021017e-01 5.690262846164507726e-01 1.663354142616256803e-01 9.692796809752548537e-01 4.133441725866372485e-01 6.729167604487583665e-01 3.998813427407297283e-01 8.272617414104491695e-01 2.129248316324727774e-01 6.517004761357130249e-01 7.363013506605019520e-01 4.072375306356985636e-01 4.463336683526665238e-01 5.485059309728204102e-01 1.981745754527846071e-01 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/cdist-X2.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/cdist-X2.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc3ea19674ee36856446c75df98b8c17c53ca51f --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/cdist-X2.txt @@ -0,0 +1,20 @@ +7.680465556300619667e-02 4.675022344069014180e-01 8.955498989131543963e-01 3.816236071436276411e-01 1.109030077070989329e-01 2.318928815459808668e-02 7.477394240984251983e-01 1.202289789304434864e-01 8.007290497575981769e-01 6.795195698871731027e-01 6.568225762396605605e-01 2.231475263228478445e-01 7.064624077661341151e-02 1.081656666815267176e-02 1.592069359090128033e-01 1.363392203645097389e-01 9.277020735447568667e-01 8.103136564528209407e-01 5.229467676276455812e-02 7.708020259874025504e-01 6.527954747473352359e-02 5.516397414886525796e-01 3.653371861367954443e-01 +8.144399106025798085e-01 7.731852525462976633e-01 6.909477620673205589e-01 9.696063817000286633e-01 4.297887511677249694e-01 6.989600553425188156e-01 7.310201335033380543e-01 3.135256147868910048e-01 5.715578037275241829e-01 3.935000744675094531e-01 2.057715781268398825e-01 5.892508589665171881e-01 8.512951599236765476e-01 9.569808799061578775e-01 6.164885878024699561e-01 4.714185430004367294e-01 6.128831737628155363e-01 6.641799309623502845e-01 6.001985185338730711e-01 4.231922889723856995e-01 7.605249308075449077e-01 1.064530958018087281e-01 6.306470691957204444e-01 +4.265470127256254518e-01 5.933766716280767239e-01 3.698589270536845053e-02 2.173799740537294412e-01 3.032679325475639009e-01 4.271831790058847611e-01 1.828944535901013690e-01 4.772333422710156592e-01 2.564773455194128138e-01 7.120329875362141347e-01 8.952243430110462530e-01 1.808777012183288013e-01 3.612151871458374464e-01 3.960999167923041631e-01 1.821669970670747318e-02 8.835474857189200559e-01 1.353104648821573663e-01 3.457291739160937016e-01 1.126467375304566199e-01 4.107293162402323450e-01 4.051719311053743056e-01 4.007382985250427243e-01 1.286905671428811848e-01 +2.910657003883979632e-01 9.616259180685315933e-03 2.033032441536681834e-01 1.096599110293863255e-01 4.191101704605176836e-01 5.462131536027151624e-01 8.393047907010142694e-01 9.046805198676335369e-01 7.009863472176891541e-01 2.508215985039629059e-01 6.754410796667598138e-01 6.740895474032024826e-01 1.358993708621679675e-01 8.219861775211464439e-01 6.322220445623235596e-01 2.766813559002430090e-01 6.575983861590951607e-01 9.515869708336625044e-01 8.654526462353933081e-01 3.450245117834797037e-01 5.649032890631299209e-01 4.717687914789682191e-01 3.296483580510030098e-01 +9.172477457635394016e-01 3.057396583041891436e-01 7.335332344225760082e-01 8.370236206345178509e-01 3.765464253115927695e-01 5.089680319287778199e-01 1.202325719268168003e-01 9.717771065272349240e-01 5.907820104019682050e-01 9.809211614977710880e-01 9.064285003671219698e-01 8.848841466121748489e-01 2.043407730734815297e-01 9.157600394927275511e-01 4.532260315147775831e-01 4.241077335005828397e-01 1.751730149568804240e-01 4.090412146081819911e-01 3.632197861847064058e-02 5.832539334970230360e-01 4.041848151536805434e-01 3.603643989086504629e-01 1.838411383882069261e-01 +2.508806403290032572e-01 4.381403985282813496e-01 4.694787405018008286e-02 6.353900562024634713e-01 1.200813444244532846e-01 6.072397042913001419e-01 9.937255904754030977e-01 4.916670237677555066e-01 3.473845913923001572e-01 3.526875922864345370e-01 5.448595548197197047e-01 2.245096010156972799e-01 9.003258279804994269e-01 3.534560469735994470e-01 2.989266066346342177e-01 4.621024982808636938e-01 9.626538866576676012e-01 9.791401720716153001e-01 7.138514287330390840e-01 9.832862333928654719e-01 3.233999591031431198e-01 5.406467224926423398e-01 9.581890295057201579e-01 +5.210583601680578436e-01 4.598159993059653949e-01 2.111497132057748027e-01 5.949977700916546652e-01 6.342618461422359077e-01 9.888228769705599275e-01 6.096770711536318998e-01 7.548431368960863974e-01 7.490858664860100546e-01 3.186213496546415058e-01 7.895687083231245351e-01 4.178326793268141159e-01 8.095818334534051752e-01 7.886271673523481684e-01 4.038905626506847923e-01 3.652649247094948981e-01 8.267205959224892542e-01 6.433617243328785262e-01 3.117681563249452559e-01 9.675995575054980868e-01 3.675673836358472890e-01 5.863757289184046151e-01 9.099029857959717305e-02 +4.024573981231733821e-01 3.578997554002771864e-01 3.519299868071553705e-01 7.417747693762357653e-01 2.963713903285800644e-01 9.602967989298948348e-01 3.811392331739601458e-01 5.493237898295448840e-01 6.835113342793640578e-01 2.304506220807415184e-01 3.727299857731285471e-01 5.450263991912108752e-01 6.951521210987908761e-01 6.474582745861203747e-01 6.316089475403589004e-01 5.672043967425510758e-02 9.034937506977609445e-01 2.332567550780038079e-01 1.096955741449157085e-02 8.870663813493575578e-01 4.384385452180562526e-01 7.100898998169548060e-01 3.245358176196319056e-01 +9.162009194452818139e-01 5.572224742426723498e-02 3.445910686865658601e-01 9.683564008127462097e-01 9.375063149031520604e-01 9.128188852869822956e-02 9.613605414326487075e-01 5.298598697556915482e-01 6.724799695520149445e-01 1.269103938571825019e-02 1.008406153387807480e-01 8.951105272379104028e-01 1.585460318853607609e-01 6.739986455059543413e-01 5.345419321702655768e-01 6.248843899572337213e-01 3.050288488994817859e-01 1.423645553465189284e-01 1.802121190541096096e-01 9.474646822694763326e-01 2.345716438587298613e-01 9.688281784764296578e-01 1.845165243240991515e-01 +2.548297646910531178e-01 2.580877375379494465e-01 1.355482532666937301e-01 6.478812986505504412e-01 9.971695982152032345e-01 2.606721082477282403e-01 5.483439686378906996e-01 4.409612606704470528e-01 4.396442074915688503e-01 7.414262832597111608e-01 7.308840725375539416e-01 8.072095530497225280e-02 6.829509968656330976e-01 5.700030854230387911e-01 3.801845336730320657e-01 2.481059916867158766e-01 3.977295094395927322e-03 5.749480512407895150e-01 4.112033136603401307e-01 8.676159710377848722e-01 9.062646588480167686e-01 3.326691167317923359e-01 8.498307982774666591e-01 +4.464338109330643345e-01 8.546516760817471914e-01 7.384800352329814466e-01 3.692485164984804502e-02 2.915662689505471583e-02 9.010049994217171898e-01 8.622900253010918892e-01 9.786230638032608065e-01 6.546824077297251909e-01 6.342297560006789903e-01 2.230339826582647955e-01 7.658846744185553446e-01 4.603043831539479491e-01 2.017100469861691225e-01 4.891590639893540482e-01 1.937140918314912419e-01 8.161582138652878626e-01 5.597293607114051106e-02 8.423261093326828153e-02 5.105392204475533990e-02 8.234193902673621057e-01 1.784268309975372002e-01 9.118997881986501408e-02 +8.588746913421980711e-01 1.479641118621310980e-02 1.375875301146138874e-01 7.533888774725254756e-01 5.782592791549248101e-01 9.128573037619659436e-01 1.831275762880391067e-01 3.471382864827737835e-01 4.859524740929310749e-02 8.955146541561730400e-01 4.787220791101074457e-01 4.222803577759057791e-01 8.469923964908064873e-01 6.300290047587608910e-02 1.020873237837905956e-01 3.585612487182909813e-02 6.320107119904569970e-01 5.891245970008752719e-01 1.104698053665007507e-01 4.233226558073774903e-01 4.432217054386708988e-01 2.864765416628194394e-01 2.489777211814803159e-02 +5.343810659756068615e-01 4.829076396403546578e-01 8.364480888953172988e-01 8.931374995414760321e-01 6.034161442354715188e-01 3.578336000768178593e-03 4.100579775972763574e-01 3.968667908067096128e-01 5.897163653686778861e-01 3.003241263928478899e-01 2.520935203143799264e-01 3.112129371563532310e-02 9.052865295974613646e-01 1.172285124002711010e-01 4.840001666149388315e-01 3.424620676348436588e-01 5.526057133826853818e-01 6.346139530261846184e-01 5.747945930485597321e-01 1.389915612177697879e-01 2.413801217666421417e-01 7.829900796662081497e-01 7.213528084845653998e-01 +9.384509283406079483e-01 6.303019601671526750e-01 1.787921522728125323e-01 1.556003868047917127e-02 5.662397078816850948e-01 3.437473614806091371e-01 8.615844972800188462e-01 7.624380237306396246e-01 1.096468347898514883e-01 1.276566836610887323e-01 8.479188493443535757e-01 3.634713454428405432e-01 7.478112314318967613e-01 9.856395696968375253e-01 6.250293654177319080e-02 1.919327272501809567e-01 1.415594476031050153e-01 7.224057351041784925e-01 8.452145259310355208e-01 5.434318833772002755e-01 5.177620959731277228e-02 3.358977598185840518e-01 2.542654881527960375e-01 +4.800909104006243489e-01 3.651345393613150137e-01 3.657093052788148446e-01 8.579662326651369408e-01 5.787694361240260932e-01 6.491966196891312268e-01 3.252508517294879775e-01 8.639694334693422961e-01 3.028097078756678551e-01 6.295814666338699350e-01 7.305627351548695803e-01 6.975931849120264872e-03 8.321205159004851915e-01 2.681809305821257761e-01 3.628869474597150591e-01 9.598981434716586936e-01 5.947913523332928332e-01 7.794864238003402779e-01 2.819511239444029149e-01 5.134200958476284882e-01 7.284684743064278045e-01 3.099571109539331903e-01 1.502222882866774967e-01 +2.463382654375219083e-01 4.465700737264240994e-01 7.180855317941433613e-01 5.056099420785193921e-01 6.182117344332578313e-01 2.370453793561340117e-01 9.831748018047525850e-01 6.397098184531551102e-01 8.260469782208745837e-02 7.474671691560941245e-01 9.963429983418570224e-02 5.450078811081275898e-01 5.370188678062637333e-02 2.774024442708808991e-01 2.082643088545442778e-01 2.704155352788065736e-01 7.225035580445194894e-01 4.866791976239246420e-01 1.357043111201584606e-01 7.911335827987711067e-01 7.278977102006007893e-01 6.880892094410231419e-01 1.029231496520791600e-01 +6.901796117735281566e-01 1.558248977395644275e-01 4.241818789360329855e-01 5.055658246392458199e-01 1.756288758075611467e-01 4.215083703818177652e-01 7.809231602323289945e-01 1.170053878686481141e-01 6.497026323614403243e-01 5.733120641440232479e-01 4.407703406152092551e-01 5.608677124532297498e-01 7.471045703286000039e-01 3.334604336022076732e-01 8.927208811415126011e-01 9.794565286182396191e-01 9.621542824973521313e-01 3.945825239405253981e-01 8.338963875792834157e-01 9.310552325082104286e-01 7.688283033784242271e-01 3.798823731047119567e-01 1.459993613028365278e-02 +7.848623555505630511e-01 2.681039365355797344e-03 7.833208051794043891e-01 8.184381915171493604e-01 4.682581645582317709e-01 2.391069309436419932e-01 1.765377537168698607e-01 9.863494676539893424e-01 4.378412300863872009e-01 7.494505491149090481e-01 1.942180356195394308e-01 9.981402467222395547e-01 7.992190944052800505e-01 1.350875702852057936e-01 4.950149186748543650e-01 7.243422481248201761e-01 3.544596746353472216e-01 8.320192561472177228e-01 9.776840296475269865e-01 7.733852731914863110e-01 2.305732998099923048e-01 9.746878189802981041e-01 7.747723331200035979e-01 +6.521099013127149568e-01 5.452399443648201505e-01 8.146707517183656710e-01 3.827256063695345656e-01 7.954832091744263867e-01 7.834427643148527132e-01 9.661317930643520402e-02 9.215673965718058636e-01 4.914305728788055383e-01 4.105628408027649501e-01 9.844647830893304974e-02 3.974831165301851987e-01 3.857608898053827007e-01 5.520210781401946321e-01 3.445787541654143915e-03 4.552922057017416702e-01 7.456544561760444223e-01 4.753985092154335845e-01 2.821385239833401615e-01 7.560136035104459973e-01 8.453142510471420845e-01 6.679627143276523071e-01 6.910882868284401459e-01 +8.526493480446283302e-01 1.183917973068240315e-01 6.163988861865119517e-01 5.751899460059114455e-01 1.638797964925038375e-01 8.214597298784013235e-01 5.424670654187370156e-01 1.806631819658732763e-01 9.268107278221827672e-01 4.127397378597359445e-01 7.529877485901653733e-01 1.714251090083847018e-01 2.601487784245806179e-01 2.028326156742237263e-01 5.299879450122358948e-01 7.587877062981395193e-01 4.070738595375062996e-01 3.546903049793261875e-01 8.695365138547607176e-01 1.447085661525142619e-01 3.193366245820845606e-01 8.797841086211429795e-01 2.666562188639977071e-01 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/iris.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/iris.txt new file mode 100644 index 0000000000000000000000000000000000000000..4d78390c2596beb41b1abff651a729e4e964c36e --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/iris.txt @@ -0,0 +1,150 @@ +5.099999999999999645e+00 3.500000000000000000e+00 1.399999999999999911e+00 2.000000000000000111e-01 +4.900000000000000355e+00 3.000000000000000000e+00 1.399999999999999911e+00 2.000000000000000111e-01 +4.700000000000000178e+00 3.200000000000000178e+00 1.300000000000000044e+00 2.000000000000000111e-01 +4.599999999999999645e+00 3.100000000000000089e+00 1.500000000000000000e+00 2.000000000000000111e-01 +5.000000000000000000e+00 3.600000000000000089e+00 1.399999999999999911e+00 2.000000000000000111e-01 +5.400000000000000355e+00 3.899999999999999911e+00 1.699999999999999956e+00 4.000000000000000222e-01 +4.599999999999999645e+00 3.399999999999999911e+00 1.399999999999999911e+00 2.999999999999999889e-01 +5.000000000000000000e+00 3.399999999999999911e+00 1.500000000000000000e+00 2.000000000000000111e-01 +4.400000000000000355e+00 2.899999999999999911e+00 1.399999999999999911e+00 2.000000000000000111e-01 +4.900000000000000355e+00 3.100000000000000089e+00 1.500000000000000000e+00 1.000000000000000056e-01 +5.400000000000000355e+00 3.700000000000000178e+00 1.500000000000000000e+00 2.000000000000000111e-01 +4.799999999999999822e+00 3.399999999999999911e+00 1.600000000000000089e+00 2.000000000000000111e-01 +4.799999999999999822e+00 3.000000000000000000e+00 1.399999999999999911e+00 1.000000000000000056e-01 +4.299999999999999822e+00 3.000000000000000000e+00 1.100000000000000089e+00 1.000000000000000056e-01 +5.799999999999999822e+00 4.000000000000000000e+00 1.199999999999999956e+00 2.000000000000000111e-01 +5.700000000000000178e+00 4.400000000000000355e+00 1.500000000000000000e+00 4.000000000000000222e-01 +5.400000000000000355e+00 3.899999999999999911e+00 1.300000000000000044e+00 4.000000000000000222e-01 +5.099999999999999645e+00 3.500000000000000000e+00 1.399999999999999911e+00 2.999999999999999889e-01 +5.700000000000000178e+00 3.799999999999999822e+00 1.699999999999999956e+00 2.999999999999999889e-01 +5.099999999999999645e+00 3.799999999999999822e+00 1.500000000000000000e+00 2.999999999999999889e-01 +5.400000000000000355e+00 3.399999999999999911e+00 1.699999999999999956e+00 2.000000000000000111e-01 +5.099999999999999645e+00 3.700000000000000178e+00 1.500000000000000000e+00 4.000000000000000222e-01 +4.599999999999999645e+00 3.600000000000000089e+00 1.000000000000000000e+00 2.000000000000000111e-01 +5.099999999999999645e+00 3.299999999999999822e+00 1.699999999999999956e+00 5.000000000000000000e-01 +4.799999999999999822e+00 3.399999999999999911e+00 1.899999999999999911e+00 2.000000000000000111e-01 +5.000000000000000000e+00 3.000000000000000000e+00 1.600000000000000089e+00 2.000000000000000111e-01 +5.000000000000000000e+00 3.399999999999999911e+00 1.600000000000000089e+00 4.000000000000000222e-01 +5.200000000000000178e+00 3.500000000000000000e+00 1.500000000000000000e+00 2.000000000000000111e-01 +5.200000000000000178e+00 3.399999999999999911e+00 1.399999999999999911e+00 2.000000000000000111e-01 +4.700000000000000178e+00 3.200000000000000178e+00 1.600000000000000089e+00 2.000000000000000111e-01 +4.799999999999999822e+00 3.100000000000000089e+00 1.600000000000000089e+00 2.000000000000000111e-01 +5.400000000000000355e+00 3.399999999999999911e+00 1.500000000000000000e+00 4.000000000000000222e-01 +5.200000000000000178e+00 4.099999999999999645e+00 1.500000000000000000e+00 1.000000000000000056e-01 +5.500000000000000000e+00 4.200000000000000178e+00 1.399999999999999911e+00 2.000000000000000111e-01 +4.900000000000000355e+00 3.100000000000000089e+00 1.500000000000000000e+00 1.000000000000000056e-01 +5.000000000000000000e+00 3.200000000000000178e+00 1.199999999999999956e+00 2.000000000000000111e-01 +5.500000000000000000e+00 3.500000000000000000e+00 1.300000000000000044e+00 2.000000000000000111e-01 +4.900000000000000355e+00 3.100000000000000089e+00 1.500000000000000000e+00 1.000000000000000056e-01 +4.400000000000000355e+00 3.000000000000000000e+00 1.300000000000000044e+00 2.000000000000000111e-01 +5.099999999999999645e+00 3.399999999999999911e+00 1.500000000000000000e+00 2.000000000000000111e-01 +5.000000000000000000e+00 3.500000000000000000e+00 1.300000000000000044e+00 2.999999999999999889e-01 +4.500000000000000000e+00 2.299999999999999822e+00 1.300000000000000044e+00 2.999999999999999889e-01 +4.400000000000000355e+00 3.200000000000000178e+00 1.300000000000000044e+00 2.000000000000000111e-01 +5.000000000000000000e+00 3.500000000000000000e+00 1.600000000000000089e+00 5.999999999999999778e-01 +5.099999999999999645e+00 3.799999999999999822e+00 1.899999999999999911e+00 4.000000000000000222e-01 +4.799999999999999822e+00 3.000000000000000000e+00 1.399999999999999911e+00 2.999999999999999889e-01 +5.099999999999999645e+00 3.799999999999999822e+00 1.600000000000000089e+00 2.000000000000000111e-01 +4.599999999999999645e+00 3.200000000000000178e+00 1.399999999999999911e+00 2.000000000000000111e-01 +5.299999999999999822e+00 3.700000000000000178e+00 1.500000000000000000e+00 2.000000000000000111e-01 +5.000000000000000000e+00 3.299999999999999822e+00 1.399999999999999911e+00 2.000000000000000111e-01 +7.000000000000000000e+00 3.200000000000000178e+00 4.700000000000000178e+00 1.399999999999999911e+00 +6.400000000000000355e+00 3.200000000000000178e+00 4.500000000000000000e+00 1.500000000000000000e+00 +6.900000000000000355e+00 3.100000000000000089e+00 4.900000000000000355e+00 1.500000000000000000e+00 +5.500000000000000000e+00 2.299999999999999822e+00 4.000000000000000000e+00 1.300000000000000044e+00 +6.500000000000000000e+00 2.799999999999999822e+00 4.599999999999999645e+00 1.500000000000000000e+00 +5.700000000000000178e+00 2.799999999999999822e+00 4.500000000000000000e+00 1.300000000000000044e+00 +6.299999999999999822e+00 3.299999999999999822e+00 4.700000000000000178e+00 1.600000000000000089e+00 +4.900000000000000355e+00 2.399999999999999911e+00 3.299999999999999822e+00 1.000000000000000000e+00 +6.599999999999999645e+00 2.899999999999999911e+00 4.599999999999999645e+00 1.300000000000000044e+00 +5.200000000000000178e+00 2.700000000000000178e+00 3.899999999999999911e+00 1.399999999999999911e+00 +5.000000000000000000e+00 2.000000000000000000e+00 3.500000000000000000e+00 1.000000000000000000e+00 +5.900000000000000355e+00 3.000000000000000000e+00 4.200000000000000178e+00 1.500000000000000000e+00 +6.000000000000000000e+00 2.200000000000000178e+00 4.000000000000000000e+00 1.000000000000000000e+00 +6.099999999999999645e+00 2.899999999999999911e+00 4.700000000000000178e+00 1.399999999999999911e+00 +5.599999999999999645e+00 2.899999999999999911e+00 3.600000000000000089e+00 1.300000000000000044e+00 +6.700000000000000178e+00 3.100000000000000089e+00 4.400000000000000355e+00 1.399999999999999911e+00 +5.599999999999999645e+00 3.000000000000000000e+00 4.500000000000000000e+00 1.500000000000000000e+00 +5.799999999999999822e+00 2.700000000000000178e+00 4.099999999999999645e+00 1.000000000000000000e+00 +6.200000000000000178e+00 2.200000000000000178e+00 4.500000000000000000e+00 1.500000000000000000e+00 +5.599999999999999645e+00 2.500000000000000000e+00 3.899999999999999911e+00 1.100000000000000089e+00 +5.900000000000000355e+00 3.200000000000000178e+00 4.799999999999999822e+00 1.800000000000000044e+00 +6.099999999999999645e+00 2.799999999999999822e+00 4.000000000000000000e+00 1.300000000000000044e+00 +6.299999999999999822e+00 2.500000000000000000e+00 4.900000000000000355e+00 1.500000000000000000e+00 +6.099999999999999645e+00 2.799999999999999822e+00 4.700000000000000178e+00 1.199999999999999956e+00 +6.400000000000000355e+00 2.899999999999999911e+00 4.299999999999999822e+00 1.300000000000000044e+00 +6.599999999999999645e+00 3.000000000000000000e+00 4.400000000000000355e+00 1.399999999999999911e+00 +6.799999999999999822e+00 2.799999999999999822e+00 4.799999999999999822e+00 1.399999999999999911e+00 +6.700000000000000178e+00 3.000000000000000000e+00 5.000000000000000000e+00 1.699999999999999956e+00 +6.000000000000000000e+00 2.899999999999999911e+00 4.500000000000000000e+00 1.500000000000000000e+00 +5.700000000000000178e+00 2.600000000000000089e+00 3.500000000000000000e+00 1.000000000000000000e+00 +5.500000000000000000e+00 2.399999999999999911e+00 3.799999999999999822e+00 1.100000000000000089e+00 +5.500000000000000000e+00 2.399999999999999911e+00 3.700000000000000178e+00 1.000000000000000000e+00 +5.799999999999999822e+00 2.700000000000000178e+00 3.899999999999999911e+00 1.199999999999999956e+00 +6.000000000000000000e+00 2.700000000000000178e+00 5.099999999999999645e+00 1.600000000000000089e+00 +5.400000000000000355e+00 3.000000000000000000e+00 4.500000000000000000e+00 1.500000000000000000e+00 +6.000000000000000000e+00 3.399999999999999911e+00 4.500000000000000000e+00 1.600000000000000089e+00 +6.700000000000000178e+00 3.100000000000000089e+00 4.700000000000000178e+00 1.500000000000000000e+00 +6.299999999999999822e+00 2.299999999999999822e+00 4.400000000000000355e+00 1.300000000000000044e+00 +5.599999999999999645e+00 3.000000000000000000e+00 4.099999999999999645e+00 1.300000000000000044e+00 +5.500000000000000000e+00 2.500000000000000000e+00 4.000000000000000000e+00 1.300000000000000044e+00 +5.500000000000000000e+00 2.600000000000000089e+00 4.400000000000000355e+00 1.199999999999999956e+00 +6.099999999999999645e+00 3.000000000000000000e+00 4.599999999999999645e+00 1.399999999999999911e+00 +5.799999999999999822e+00 2.600000000000000089e+00 4.000000000000000000e+00 1.199999999999999956e+00 +5.000000000000000000e+00 2.299999999999999822e+00 3.299999999999999822e+00 1.000000000000000000e+00 +5.599999999999999645e+00 2.700000000000000178e+00 4.200000000000000178e+00 1.300000000000000044e+00 +5.700000000000000178e+00 3.000000000000000000e+00 4.200000000000000178e+00 1.199999999999999956e+00 +5.700000000000000178e+00 2.899999999999999911e+00 4.200000000000000178e+00 1.300000000000000044e+00 +6.200000000000000178e+00 2.899999999999999911e+00 4.299999999999999822e+00 1.300000000000000044e+00 +5.099999999999999645e+00 2.500000000000000000e+00 3.000000000000000000e+00 1.100000000000000089e+00 +5.700000000000000178e+00 2.799999999999999822e+00 4.099999999999999645e+00 1.300000000000000044e+00 +6.299999999999999822e+00 3.299999999999999822e+00 6.000000000000000000e+00 2.500000000000000000e+00 +5.799999999999999822e+00 2.700000000000000178e+00 5.099999999999999645e+00 1.899999999999999911e+00 +7.099999999999999645e+00 3.000000000000000000e+00 5.900000000000000355e+00 2.100000000000000089e+00 +6.299999999999999822e+00 2.899999999999999911e+00 5.599999999999999645e+00 1.800000000000000044e+00 +6.500000000000000000e+00 3.000000000000000000e+00 5.799999999999999822e+00 2.200000000000000178e+00 +7.599999999999999645e+00 3.000000000000000000e+00 6.599999999999999645e+00 2.100000000000000089e+00 +4.900000000000000355e+00 2.500000000000000000e+00 4.500000000000000000e+00 1.699999999999999956e+00 +7.299999999999999822e+00 2.899999999999999911e+00 6.299999999999999822e+00 1.800000000000000044e+00 +6.700000000000000178e+00 2.500000000000000000e+00 5.799999999999999822e+00 1.800000000000000044e+00 +7.200000000000000178e+00 3.600000000000000089e+00 6.099999999999999645e+00 2.500000000000000000e+00 +6.500000000000000000e+00 3.200000000000000178e+00 5.099999999999999645e+00 2.000000000000000000e+00 +6.400000000000000355e+00 2.700000000000000178e+00 5.299999999999999822e+00 1.899999999999999911e+00 +6.799999999999999822e+00 3.000000000000000000e+00 5.500000000000000000e+00 2.100000000000000089e+00 +5.700000000000000178e+00 2.500000000000000000e+00 5.000000000000000000e+00 2.000000000000000000e+00 +5.799999999999999822e+00 2.799999999999999822e+00 5.099999999999999645e+00 2.399999999999999911e+00 +6.400000000000000355e+00 3.200000000000000178e+00 5.299999999999999822e+00 2.299999999999999822e+00 +6.500000000000000000e+00 3.000000000000000000e+00 5.500000000000000000e+00 1.800000000000000044e+00 +7.700000000000000178e+00 3.799999999999999822e+00 6.700000000000000178e+00 2.200000000000000178e+00 +7.700000000000000178e+00 2.600000000000000089e+00 6.900000000000000355e+00 2.299999999999999822e+00 +6.000000000000000000e+00 2.200000000000000178e+00 5.000000000000000000e+00 1.500000000000000000e+00 +6.900000000000000355e+00 3.200000000000000178e+00 5.700000000000000178e+00 2.299999999999999822e+00 +5.599999999999999645e+00 2.799999999999999822e+00 4.900000000000000355e+00 2.000000000000000000e+00 +7.700000000000000178e+00 2.799999999999999822e+00 6.700000000000000178e+00 2.000000000000000000e+00 +6.299999999999999822e+00 2.700000000000000178e+00 4.900000000000000355e+00 1.800000000000000044e+00 +6.700000000000000178e+00 3.299999999999999822e+00 5.700000000000000178e+00 2.100000000000000089e+00 +7.200000000000000178e+00 3.200000000000000178e+00 6.000000000000000000e+00 1.800000000000000044e+00 +6.200000000000000178e+00 2.799999999999999822e+00 4.799999999999999822e+00 1.800000000000000044e+00 +6.099999999999999645e+00 3.000000000000000000e+00 4.900000000000000355e+00 1.800000000000000044e+00 +6.400000000000000355e+00 2.799999999999999822e+00 5.599999999999999645e+00 2.100000000000000089e+00 +7.200000000000000178e+00 3.000000000000000000e+00 5.799999999999999822e+00 1.600000000000000089e+00 +7.400000000000000355e+00 2.799999999999999822e+00 6.099999999999999645e+00 1.899999999999999911e+00 +7.900000000000000355e+00 3.799999999999999822e+00 6.400000000000000355e+00 2.000000000000000000e+00 +6.400000000000000355e+00 2.799999999999999822e+00 5.599999999999999645e+00 2.200000000000000178e+00 +6.299999999999999822e+00 2.799999999999999822e+00 5.099999999999999645e+00 1.500000000000000000e+00 +6.099999999999999645e+00 2.600000000000000089e+00 5.599999999999999645e+00 1.399999999999999911e+00 +7.700000000000000178e+00 3.000000000000000000e+00 6.099999999999999645e+00 2.299999999999999822e+00 +6.299999999999999822e+00 3.399999999999999911e+00 5.599999999999999645e+00 2.399999999999999911e+00 +6.400000000000000355e+00 3.100000000000000089e+00 5.500000000000000000e+00 1.800000000000000044e+00 +6.000000000000000000e+00 3.000000000000000000e+00 4.799999999999999822e+00 1.800000000000000044e+00 +6.900000000000000355e+00 3.100000000000000089e+00 5.400000000000000355e+00 2.100000000000000089e+00 +6.700000000000000178e+00 3.100000000000000089e+00 5.599999999999999645e+00 2.399999999999999911e+00 +6.900000000000000355e+00 3.100000000000000089e+00 5.099999999999999645e+00 2.299999999999999822e+00 +5.799999999999999822e+00 2.700000000000000178e+00 5.099999999999999645e+00 1.899999999999999911e+00 +6.799999999999999822e+00 3.200000000000000178e+00 5.900000000000000355e+00 2.299999999999999822e+00 +6.700000000000000178e+00 3.299999999999999822e+00 5.700000000000000178e+00 2.500000000000000000e+00 +6.700000000000000178e+00 3.000000000000000000e+00 5.200000000000000178e+00 2.299999999999999822e+00 +6.299999999999999822e+00 2.500000000000000000e+00 5.000000000000000000e+00 1.899999999999999911e+00 +6.500000000000000000e+00 3.000000000000000000e+00 5.200000000000000178e+00 2.000000000000000000e+00 +6.200000000000000178e+00 3.399999999999999911e+00 5.400000000000000355e+00 2.299999999999999822e+00 +5.900000000000000355e+00 3.000000000000000000e+00 5.099999999999999645e+00 1.800000000000000044e+00 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-boolean-inp.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-boolean-inp.txt new file mode 100644 index 0000000000000000000000000000000000000000..0636cc9f4590f2e960f7136d83a5d2cb07c56536 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-boolean-inp.txt @@ -0,0 +1,20 @@ +1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 +1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 +1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 +0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 +1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 +1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 +1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 +1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 +1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 +1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 +0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 +1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 +1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 +1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 +0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 +1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 +1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 +0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 +1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 +1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 1.000000000000000000e+00 0.000000000000000000e+00 0.000000000000000000e+00 1.000000000000000000e+00 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-chebyshev-ml-iris.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-chebyshev-ml-iris.txt new file mode 100644 index 0000000000000000000000000000000000000000..0aff1267ca7fd6f41d38c2273540bb771e9cbd0c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-chebyshev-ml-iris.txt @@ -0,0 +1 @@ + 5.0000000e-01 4.0000000e-01 5.0000000e-01 1.0000000e-01 4.0000000e-01 5.0000000e-01 1.0000000e-01 7.0000000e-01 4.0000000e-01 3.0000000e-01 3.0000000e-01 5.0000000e-01 8.0000000e-01 7.0000000e-01 9.0000000e-01 4.0000000e-01 1.0000000e-01 6.0000000e-01 3.0000000e-01 3.0000000e-01 2.0000000e-01 5.0000000e-01 3.0000000e-01 5.0000000e-01 5.0000000e-01 2.0000000e-01 1.0000000e-01 1.0000000e-01 4.0000000e-01 4.0000000e-01 3.0000000e-01 6.0000000e-01 7.0000000e-01 4.0000000e-01 3.0000000e-01 4.0000000e-01 4.0000000e-01 7.0000000e-01 1.0000000e-01 1.0000000e-01 1.2000000e+00 7.0000000e-01 4.0000000e-01 5.0000000e-01 5.0000000e-01 3.0000000e-01 5.0000000e-01 2.0000000e-01 2.0000000e-01 3.3000000e+00 3.1000000e+00 3.5000000e+00 2.6000000e+00 3.2000000e+00 3.1000000e+00 3.3000000e+00 1.9000000e+00 3.2000000e+00 2.5000000e+00 2.1000000e+00 2.8000000e+00 2.6000000e+00 3.3000000e+00 2.2000000e+00 3.0000000e+00 3.1000000e+00 2.7000000e+00 3.1000000e+00 2.5000000e+00 3.4000000e+00 2.6000000e+00 3.5000000e+00 3.3000000e+00 2.9000000e+00 3.0000000e+00 3.4000000e+00 3.6000000e+00 3.1000000e+00 2.1000000e+00 2.4000000e+00 2.3000000e+00 2.5000000e+00 3.7000000e+00 3.1000000e+00 3.1000000e+00 3.3000000e+00 3.0000000e+00 2.7000000e+00 2.6000000e+00 3.0000000e+00 3.2000000e+00 2.6000000e+00 1.9000000e+00 2.8000000e+00 2.8000000e+00 2.8000000e+00 2.9000000e+00 1.6000000e+00 2.7000000e+00 4.6000000e+00 3.7000000e+00 4.5000000e+00 4.2000000e+00 4.4000000e+00 5.2000000e+00 3.1000000e+00 4.9000000e+00 4.4000000e+00 4.7000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 5.3000000e+00 5.5000000e+00 3.6000000e+00 4.3000000e+00 3.5000000e+00 5.3000000e+00 3.5000000e+00 4.3000000e+00 4.6000000e+00 3.4000000e+00 3.5000000e+00 4.2000000e+00 4.4000000e+00 4.7000000e+00 5.0000000e+00 4.2000000e+00 3.7000000e+00 4.2000000e+00 4.7000000e+00 4.2000000e+00 4.1000000e+00 3.4000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.7000000e+00 4.5000000e+00 4.3000000e+00 3.8000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.7000000e+00 2.0000000e-01 3.0000000e-01 6.0000000e-01 9.0000000e-01 4.0000000e-01 4.0000000e-01 5.0000000e-01 1.0000000e-01 7.0000000e-01 4.0000000e-01 1.0000000e-01 6.0000000e-01 1.0000000e+00 1.4000000e+00 9.0000000e-01 5.0000000e-01 8.0000000e-01 8.0000000e-01 5.0000000e-01 7.0000000e-01 6.0000000e-01 3.0000000e-01 5.0000000e-01 2.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 2.0000000e-01 2.0000000e-01 5.0000000e-01 1.1000000e+00 1.2000000e+00 1.0000000e-01 2.0000000e-01 6.0000000e-01 1.0000000e-01 5.0000000e-01 4.0000000e-01 5.0000000e-01 7.0000000e-01 5.0000000e-01 5.0000000e-01 8.0000000e-01 1.0000000e-01 8.0000000e-01 3.0000000e-01 7.0000000e-01 3.0000000e-01 3.3000000e+00 3.1000000e+00 3.5000000e+00 2.6000000e+00 3.2000000e+00 3.1000000e+00 3.3000000e+00 1.9000000e+00 3.2000000e+00 2.5000000e+00 2.1000000e+00 2.8000000e+00 2.6000000e+00 3.3000000e+00 2.2000000e+00 3.0000000e+00 3.1000000e+00 2.7000000e+00 3.1000000e+00 2.5000000e+00 3.4000000e+00 2.6000000e+00 3.5000000e+00 3.3000000e+00 2.9000000e+00 3.0000000e+00 3.4000000e+00 3.6000000e+00 3.1000000e+00 2.1000000e+00 2.4000000e+00 2.3000000e+00 2.5000000e+00 3.7000000e+00 3.1000000e+00 3.1000000e+00 3.3000000e+00 3.0000000e+00 2.7000000e+00 2.6000000e+00 3.0000000e+00 3.2000000e+00 2.6000000e+00 1.9000000e+00 2.8000000e+00 2.8000000e+00 2.8000000e+00 2.9000000e+00 1.6000000e+00 2.7000000e+00 4.6000000e+00 3.7000000e+00 4.5000000e+00 4.2000000e+00 4.4000000e+00 5.2000000e+00 3.1000000e+00 4.9000000e+00 4.4000000e+00 4.7000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 5.3000000e+00 5.5000000e+00 3.6000000e+00 4.3000000e+00 3.5000000e+00 5.3000000e+00 3.5000000e+00 4.3000000e+00 4.6000000e+00 3.4000000e+00 3.5000000e+00 4.2000000e+00 4.4000000e+00 4.7000000e+00 5.0000000e+00 4.2000000e+00 3.7000000e+00 4.2000000e+00 4.7000000e+00 4.2000000e+00 4.1000000e+00 3.4000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.7000000e+00 4.5000000e+00 4.3000000e+00 3.8000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.7000000e+00 2.0000000e-01 4.0000000e-01 7.0000000e-01 2.0000000e-01 3.0000000e-01 3.0000000e-01 2.0000000e-01 7.0000000e-01 3.0000000e-01 2.0000000e-01 4.0000000e-01 1.1000000e+00 1.2000000e+00 7.0000000e-01 4.0000000e-01 1.0000000e+00 6.0000000e-01 7.0000000e-01 5.0000000e-01 4.0000000e-01 4.0000000e-01 6.0000000e-01 3.0000000e-01 3.0000000e-01 5.0000000e-01 5.0000000e-01 3.0000000e-01 3.0000000e-01 7.0000000e-01 9.0000000e-01 1.0000000e+00 2.0000000e-01 3.0000000e-01 8.0000000e-01 2.0000000e-01 3.0000000e-01 4.0000000e-01 3.0000000e-01 9.0000000e-01 3.0000000e-01 4.0000000e-01 6.0000000e-01 2.0000000e-01 6.0000000e-01 1.0000000e-01 6.0000000e-01 3.0000000e-01 3.4000000e+00 3.2000000e+00 3.6000000e+00 2.7000000e+00 3.3000000e+00 3.2000000e+00 3.4000000e+00 2.0000000e+00 3.3000000e+00 2.6000000e+00 2.2000000e+00 2.9000000e+00 2.7000000e+00 3.4000000e+00 2.3000000e+00 3.1000000e+00 3.2000000e+00 2.8000000e+00 3.2000000e+00 2.6000000e+00 3.5000000e+00 2.7000000e+00 3.6000000e+00 3.4000000e+00 3.0000000e+00 3.1000000e+00 3.5000000e+00 3.7000000e+00 3.2000000e+00 2.2000000e+00 2.5000000e+00 2.4000000e+00 2.6000000e+00 3.8000000e+00 3.2000000e+00 3.2000000e+00 3.4000000e+00 3.1000000e+00 2.8000000e+00 2.7000000e+00 3.1000000e+00 3.3000000e+00 2.7000000e+00 2.0000000e+00 2.9000000e+00 2.9000000e+00 2.9000000e+00 3.0000000e+00 1.7000000e+00 2.8000000e+00 4.7000000e+00 3.8000000e+00 4.6000000e+00 4.3000000e+00 4.5000000e+00 5.3000000e+00 3.2000000e+00 5.0000000e+00 4.5000000e+00 4.8000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 5.4000000e+00 5.6000000e+00 3.7000000e+00 4.4000000e+00 3.6000000e+00 5.4000000e+00 3.6000000e+00 4.4000000e+00 4.7000000e+00 3.5000000e+00 3.6000000e+00 4.3000000e+00 4.5000000e+00 4.8000000e+00 5.1000000e+00 4.3000000e+00 3.8000000e+00 4.3000000e+00 4.8000000e+00 4.3000000e+00 4.2000000e+00 3.5000000e+00 4.1000000e+00 4.3000000e+00 3.8000000e+00 3.8000000e+00 4.6000000e+00 4.4000000e+00 3.9000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.8000000e+00 5.0000000e-01 8.0000000e-01 3.0000000e-01 4.0000000e-01 2.0000000e-01 3.0000000e-01 8.0000000e-01 3.0000000e-01 2.0000000e-01 4.0000000e-01 1.2000000e+00 1.3000000e+00 8.0000000e-01 5.0000000e-01 1.1000000e+00 7.0000000e-01 8.0000000e-01 6.0000000e-01 5.0000000e-01 5.0000000e-01 4.0000000e-01 4.0000000e-01 4.0000000e-01 6.0000000e-01 6.0000000e-01 1.0000000e-01 2.0000000e-01 8.0000000e-01 1.0000000e+00 1.1000000e+00 3.0000000e-01 4.0000000e-01 9.0000000e-01 3.0000000e-01 2.0000000e-01 5.0000000e-01 4.0000000e-01 8.0000000e-01 2.0000000e-01 4.0000000e-01 7.0000000e-01 2.0000000e-01 7.0000000e-01 1.0000000e-01 7.0000000e-01 4.0000000e-01 3.2000000e+00 3.0000000e+00 3.4000000e+00 2.5000000e+00 3.1000000e+00 3.0000000e+00 3.2000000e+00 1.8000000e+00 3.1000000e+00 2.4000000e+00 2.0000000e+00 2.7000000e+00 2.5000000e+00 3.2000000e+00 2.1000000e+00 2.9000000e+00 3.0000000e+00 2.6000000e+00 3.0000000e+00 2.4000000e+00 3.3000000e+00 2.5000000e+00 3.4000000e+00 3.2000000e+00 2.8000000e+00 2.9000000e+00 3.3000000e+00 3.5000000e+00 3.0000000e+00 2.0000000e+00 2.3000000e+00 2.2000000e+00 2.4000000e+00 3.6000000e+00 3.0000000e+00 3.0000000e+00 3.2000000e+00 2.9000000e+00 2.6000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.5000000e+00 1.8000000e+00 2.7000000e+00 2.7000000e+00 2.7000000e+00 2.8000000e+00 1.5000000e+00 2.6000000e+00 4.5000000e+00 3.6000000e+00 4.4000000e+00 4.1000000e+00 4.3000000e+00 5.1000000e+00 3.0000000e+00 4.8000000e+00 4.3000000e+00 4.6000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 5.2000000e+00 5.4000000e+00 3.5000000e+00 4.2000000e+00 3.4000000e+00 5.2000000e+00 3.4000000e+00 4.2000000e+00 4.5000000e+00 3.3000000e+00 3.4000000e+00 4.1000000e+00 4.3000000e+00 4.6000000e+00 4.9000000e+00 4.1000000e+00 3.6000000e+00 4.1000000e+00 4.6000000e+00 4.1000000e+00 4.0000000e+00 3.3000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.6000000e+00 4.4000000e+00 4.2000000e+00 3.7000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.6000000e+00 4.0000000e-01 4.0000000e-01 2.0000000e-01 7.0000000e-01 5.0000000e-01 4.0000000e-01 2.0000000e-01 6.0000000e-01 7.0000000e-01 8.0000000e-01 8.0000000e-01 4.0000000e-01 1.0000000e-01 7.0000000e-01 2.0000000e-01 4.0000000e-01 2.0000000e-01 4.0000000e-01 3.0000000e-01 5.0000000e-01 6.0000000e-01 2.0000000e-01 2.0000000e-01 2.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 5.0000000e-01 6.0000000e-01 5.0000000e-01 4.0000000e-01 5.0000000e-01 5.0000000e-01 6.0000000e-01 2.0000000e-01 1.0000000e-01 1.3000000e+00 6.0000000e-01 4.0000000e-01 5.0000000e-01 6.0000000e-01 2.0000000e-01 4.0000000e-01 3.0000000e-01 3.0000000e-01 3.3000000e+00 3.1000000e+00 3.5000000e+00 2.6000000e+00 3.2000000e+00 3.1000000e+00 3.3000000e+00 1.9000000e+00 3.2000000e+00 2.5000000e+00 2.1000000e+00 2.8000000e+00 2.6000000e+00 3.3000000e+00 2.2000000e+00 3.0000000e+00 3.1000000e+00 2.7000000e+00 3.1000000e+00 2.5000000e+00 3.4000000e+00 2.6000000e+00 3.5000000e+00 3.3000000e+00 2.9000000e+00 3.0000000e+00 3.4000000e+00 3.6000000e+00 3.1000000e+00 2.1000000e+00 2.4000000e+00 2.3000000e+00 2.5000000e+00 3.7000000e+00 3.1000000e+00 3.1000000e+00 3.3000000e+00 3.0000000e+00 2.7000000e+00 2.6000000e+00 3.0000000e+00 3.2000000e+00 2.6000000e+00 1.9000000e+00 2.8000000e+00 2.8000000e+00 2.8000000e+00 2.9000000e+00 1.6000000e+00 2.7000000e+00 4.6000000e+00 3.7000000e+00 4.5000000e+00 4.2000000e+00 4.4000000e+00 5.2000000e+00 3.1000000e+00 4.9000000e+00 4.4000000e+00 4.7000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 5.3000000e+00 5.5000000e+00 3.6000000e+00 4.3000000e+00 3.5000000e+00 5.3000000e+00 3.5000000e+00 4.3000000e+00 4.6000000e+00 3.4000000e+00 3.5000000e+00 4.2000000e+00 4.4000000e+00 4.7000000e+00 5.0000000e+00 4.2000000e+00 3.7000000e+00 4.2000000e+00 4.7000000e+00 4.2000000e+00 4.1000000e+00 3.4000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.7000000e+00 4.5000000e+00 4.3000000e+00 3.8000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.7000000e+00 8.0000000e-01 5.0000000e-01 1.0000000e+00 8.0000000e-01 2.0000000e-01 6.0000000e-01 9.0000000e-01 1.1000000e+00 5.0000000e-01 5.0000000e-01 4.0000000e-01 4.0000000e-01 3.0000000e-01 3.0000000e-01 5.0000000e-01 3.0000000e-01 8.0000000e-01 6.0000000e-01 6.0000000e-01 9.0000000e-01 5.0000000e-01 4.0000000e-01 5.0000000e-01 7.0000000e-01 8.0000000e-01 5.0000000e-01 3.0000000e-01 3.0000000e-01 8.0000000e-01 7.0000000e-01 4.0000000e-01 8.0000000e-01 1.0000000e+00 5.0000000e-01 4.0000000e-01 1.6000000e+00 1.0000000e+00 4.0000000e-01 3.0000000e-01 9.0000000e-01 3.0000000e-01 8.0000000e-01 2.0000000e-01 6.0000000e-01 3.0000000e+00 2.8000000e+00 3.2000000e+00 2.3000000e+00 2.9000000e+00 2.8000000e+00 3.0000000e+00 1.6000000e+00 2.9000000e+00 2.2000000e+00 1.9000000e+00 2.5000000e+00 2.3000000e+00 3.0000000e+00 1.9000000e+00 2.7000000e+00 2.8000000e+00 2.4000000e+00 2.8000000e+00 2.2000000e+00 3.1000000e+00 2.3000000e+00 3.2000000e+00 3.0000000e+00 2.6000000e+00 2.7000000e+00 3.1000000e+00 3.3000000e+00 2.8000000e+00 1.8000000e+00 2.1000000e+00 2.0000000e+00 2.2000000e+00 3.4000000e+00 2.8000000e+00 2.8000000e+00 3.0000000e+00 2.7000000e+00 2.4000000e+00 2.3000000e+00 2.7000000e+00 2.9000000e+00 2.3000000e+00 1.6000000e+00 2.5000000e+00 2.5000000e+00 2.5000000e+00 2.6000000e+00 1.4000000e+00 2.4000000e+00 4.3000000e+00 3.4000000e+00 4.2000000e+00 3.9000000e+00 4.1000000e+00 4.9000000e+00 2.8000000e+00 4.6000000e+00 4.1000000e+00 4.4000000e+00 3.4000000e+00 3.6000000e+00 3.8000000e+00 3.3000000e+00 3.4000000e+00 3.6000000e+00 3.8000000e+00 5.0000000e+00 5.2000000e+00 3.3000000e+00 4.0000000e+00 3.2000000e+00 5.0000000e+00 3.2000000e+00 4.0000000e+00 4.3000000e+00 3.1000000e+00 3.2000000e+00 3.9000000e+00 4.1000000e+00 4.4000000e+00 4.7000000e+00 3.9000000e+00 3.4000000e+00 3.9000000e+00 4.4000000e+00 3.9000000e+00 3.8000000e+00 3.1000000e+00 3.7000000e+00 3.9000000e+00 3.4000000e+00 3.4000000e+00 4.2000000e+00 4.0000000e+00 3.5000000e+00 3.3000000e+00 3.5000000e+00 3.7000000e+00 3.4000000e+00 4.0000000e-01 5.0000000e-01 3.0000000e-01 8.0000000e-01 2.0000000e-01 4.0000000e-01 4.0000000e-01 1.2000000e+00 1.1000000e+00 8.0000000e-01 5.0000000e-01 1.1000000e+00 5.0000000e-01 8.0000000e-01 5.0000000e-01 4.0000000e-01 5.0000000e-01 5.0000000e-01 4.0000000e-01 4.0000000e-01 6.0000000e-01 6.0000000e-01 2.0000000e-01 3.0000000e-01 8.0000000e-01 7.0000000e-01 9.0000000e-01 3.0000000e-01 4.0000000e-01 9.0000000e-01 3.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 1.1000000e+00 2.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 5.0000000e-01 2.0000000e-01 7.0000000e-01 4.0000000e-01 3.3000000e+00 3.1000000e+00 3.5000000e+00 2.6000000e+00 3.2000000e+00 3.1000000e+00 3.3000000e+00 1.9000000e+00 3.2000000e+00 2.5000000e+00 2.1000000e+00 2.8000000e+00 2.6000000e+00 3.3000000e+00 2.2000000e+00 3.0000000e+00 3.1000000e+00 2.7000000e+00 3.1000000e+00 2.5000000e+00 3.4000000e+00 2.6000000e+00 3.5000000e+00 3.3000000e+00 2.9000000e+00 3.0000000e+00 3.4000000e+00 3.6000000e+00 3.1000000e+00 2.1000000e+00 2.4000000e+00 2.3000000e+00 2.5000000e+00 3.7000000e+00 3.1000000e+00 3.1000000e+00 3.3000000e+00 3.0000000e+00 2.7000000e+00 2.6000000e+00 3.0000000e+00 3.2000000e+00 2.6000000e+00 1.9000000e+00 2.8000000e+00 2.8000000e+00 2.8000000e+00 2.9000000e+00 1.6000000e+00 2.7000000e+00 4.6000000e+00 3.7000000e+00 4.5000000e+00 4.2000000e+00 4.4000000e+00 5.2000000e+00 3.1000000e+00 4.9000000e+00 4.4000000e+00 4.7000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 5.3000000e+00 5.5000000e+00 3.6000000e+00 4.3000000e+00 3.5000000e+00 5.3000000e+00 3.5000000e+00 4.3000000e+00 4.6000000e+00 3.4000000e+00 3.5000000e+00 4.2000000e+00 4.4000000e+00 4.7000000e+00 5.0000000e+00 4.2000000e+00 3.7000000e+00 4.2000000e+00 4.7000000e+00 4.2000000e+00 4.1000000e+00 3.4000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.7000000e+00 4.5000000e+00 4.3000000e+00 3.8000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.7000000e+00 6.0000000e-01 3.0000000e-01 4.0000000e-01 2.0000000e-01 4.0000000e-01 7.0000000e-01 8.0000000e-01 1.0000000e+00 5.0000000e-01 1.0000000e-01 7.0000000e-01 4.0000000e-01 4.0000000e-01 3.0000000e-01 5.0000000e-01 3.0000000e-01 4.0000000e-01 4.0000000e-01 2.0000000e-01 2.0000000e-01 2.0000000e-01 3.0000000e-01 3.0000000e-01 4.0000000e-01 7.0000000e-01 8.0000000e-01 3.0000000e-01 3.0000000e-01 5.0000000e-01 3.0000000e-01 6.0000000e-01 1.0000000e-01 2.0000000e-01 1.1000000e+00 6.0000000e-01 4.0000000e-01 4.0000000e-01 4.0000000e-01 4.0000000e-01 4.0000000e-01 3.0000000e-01 1.0000000e-01 3.2000000e+00 3.0000000e+00 3.4000000e+00 2.5000000e+00 3.1000000e+00 3.0000000e+00 3.2000000e+00 1.8000000e+00 3.1000000e+00 2.4000000e+00 2.0000000e+00 2.7000000e+00 2.5000000e+00 3.2000000e+00 2.1000000e+00 2.9000000e+00 3.0000000e+00 2.6000000e+00 3.0000000e+00 2.4000000e+00 3.3000000e+00 2.5000000e+00 3.4000000e+00 3.2000000e+00 2.8000000e+00 2.9000000e+00 3.3000000e+00 3.5000000e+00 3.0000000e+00 2.0000000e+00 2.3000000e+00 2.2000000e+00 2.4000000e+00 3.6000000e+00 3.0000000e+00 3.0000000e+00 3.2000000e+00 2.9000000e+00 2.6000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.5000000e+00 1.8000000e+00 2.7000000e+00 2.7000000e+00 2.7000000e+00 2.8000000e+00 1.5000000e+00 2.6000000e+00 4.5000000e+00 3.6000000e+00 4.4000000e+00 4.1000000e+00 4.3000000e+00 5.1000000e+00 3.0000000e+00 4.8000000e+00 4.3000000e+00 4.6000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 5.2000000e+00 5.4000000e+00 3.5000000e+00 4.2000000e+00 3.4000000e+00 5.2000000e+00 3.4000000e+00 4.2000000e+00 4.5000000e+00 3.3000000e+00 3.4000000e+00 4.1000000e+00 4.3000000e+00 4.6000000e+00 4.9000000e+00 4.1000000e+00 3.6000000e+00 4.1000000e+00 4.6000000e+00 4.1000000e+00 4.0000000e+00 3.3000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.6000000e+00 4.4000000e+00 4.2000000e+00 3.7000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.6000000e+00 5.0000000e-01 1.0000000e+00 5.0000000e-01 4.0000000e-01 3.0000000e-01 1.4000000e+00 1.5000000e+00 1.0000000e+00 7.0000000e-01 1.3000000e+00 9.0000000e-01 1.0000000e+00 8.0000000e-01 7.0000000e-01 7.0000000e-01 5.0000000e-01 6.0000000e-01 6.0000000e-01 8.0000000e-01 8.0000000e-01 3.0000000e-01 4.0000000e-01 1.0000000e+00 1.2000000e+00 1.3000000e+00 5.0000000e-01 6.0000000e-01 1.1000000e+00 5.0000000e-01 1.0000000e-01 7.0000000e-01 6.0000000e-01 6.0000000e-01 3.0000000e-01 6.0000000e-01 9.0000000e-01 4.0000000e-01 9.0000000e-01 3.0000000e-01 9.0000000e-01 6.0000000e-01 3.3000000e+00 3.1000000e+00 3.5000000e+00 2.6000000e+00 3.2000000e+00 3.1000000e+00 3.3000000e+00 1.9000000e+00 3.2000000e+00 2.5000000e+00 2.1000000e+00 2.8000000e+00 2.6000000e+00 3.3000000e+00 2.2000000e+00 3.0000000e+00 3.1000000e+00 2.7000000e+00 3.1000000e+00 2.5000000e+00 3.4000000e+00 2.6000000e+00 3.5000000e+00 3.3000000e+00 2.9000000e+00 3.0000000e+00 3.4000000e+00 3.6000000e+00 3.1000000e+00 2.1000000e+00 2.4000000e+00 2.3000000e+00 2.5000000e+00 3.7000000e+00 3.1000000e+00 3.1000000e+00 3.3000000e+00 3.0000000e+00 2.7000000e+00 2.6000000e+00 3.0000000e+00 3.2000000e+00 2.6000000e+00 1.9000000e+00 2.8000000e+00 2.8000000e+00 2.8000000e+00 2.9000000e+00 1.6000000e+00 2.7000000e+00 4.6000000e+00 3.7000000e+00 4.5000000e+00 4.2000000e+00 4.4000000e+00 5.2000000e+00 3.1000000e+00 4.9000000e+00 4.4000000e+00 4.7000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 5.3000000e+00 5.5000000e+00 3.6000000e+00 4.3000000e+00 3.5000000e+00 5.3000000e+00 3.5000000e+00 4.3000000e+00 4.6000000e+00 3.4000000e+00 3.5000000e+00 4.2000000e+00 4.4000000e+00 4.7000000e+00 5.0000000e+00 4.2000000e+00 3.7000000e+00 4.2000000e+00 4.7000000e+00 4.2000000e+00 4.1000000e+00 3.4000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.7000000e+00 4.5000000e+00 4.3000000e+00 3.8000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.7000000e+00 6.0000000e-01 3.0000000e-01 1.0000000e-01 6.0000000e-01 9.0000000e-01 1.3000000e+00 8.0000000e-01 4.0000000e-01 8.0000000e-01 7.0000000e-01 5.0000000e-01 6.0000000e-01 5.0000000e-01 4.0000000e-01 4.0000000e-01 1.0000000e-01 3.0000000e-01 4.0000000e-01 3.0000000e-01 2.0000000e-01 1.0000000e-01 5.0000000e-01 1.0000000e+00 1.1000000e+00 0.0000000e+00 3.0000000e-01 6.0000000e-01 0.0000000e+00 5.0000000e-01 3.0000000e-01 4.0000000e-01 8.0000000e-01 5.0000000e-01 5.0000000e-01 7.0000000e-01 2.0000000e-01 7.0000000e-01 3.0000000e-01 6.0000000e-01 2.0000000e-01 3.2000000e+00 3.0000000e+00 3.4000000e+00 2.5000000e+00 3.1000000e+00 3.0000000e+00 3.2000000e+00 1.8000000e+00 3.1000000e+00 2.4000000e+00 2.0000000e+00 2.7000000e+00 2.5000000e+00 3.2000000e+00 2.1000000e+00 2.9000000e+00 3.0000000e+00 2.6000000e+00 3.0000000e+00 2.4000000e+00 3.3000000e+00 2.5000000e+00 3.4000000e+00 3.2000000e+00 2.8000000e+00 2.9000000e+00 3.3000000e+00 3.5000000e+00 3.0000000e+00 2.0000000e+00 2.3000000e+00 2.2000000e+00 2.4000000e+00 3.6000000e+00 3.0000000e+00 3.0000000e+00 3.2000000e+00 2.9000000e+00 2.6000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.5000000e+00 1.8000000e+00 2.7000000e+00 2.7000000e+00 2.7000000e+00 2.8000000e+00 1.5000000e+00 2.6000000e+00 4.5000000e+00 3.6000000e+00 4.4000000e+00 4.1000000e+00 4.3000000e+00 5.1000000e+00 3.0000000e+00 4.8000000e+00 4.3000000e+00 4.6000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 5.2000000e+00 5.4000000e+00 3.5000000e+00 4.2000000e+00 3.4000000e+00 5.2000000e+00 3.4000000e+00 4.2000000e+00 4.5000000e+00 3.3000000e+00 3.4000000e+00 4.1000000e+00 4.3000000e+00 4.6000000e+00 4.9000000e+00 4.1000000e+00 3.6000000e+00 4.1000000e+00 4.6000000e+00 4.1000000e+00 4.0000000e+00 3.3000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.6000000e+00 4.4000000e+00 4.2000000e+00 3.7000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.6000000e+00 6.0000000e-01 7.0000000e-01 1.1000000e+00 4.0000000e-01 7.0000000e-01 2.0000000e-01 3.0000000e-01 3.0000000e-01 3.0000000e-01 3.0000000e-01 3.0000000e-01 8.0000000e-01 4.0000000e-01 6.0000000e-01 7.0000000e-01 4.0000000e-01 2.0000000e-01 3.0000000e-01 7.0000000e-01 6.0000000e-01 3.0000000e-01 4.0000000e-01 5.0000000e-01 6.0000000e-01 5.0000000e-01 2.0000000e-01 6.0000000e-01 1.0000000e+00 3.0000000e-01 4.0000000e-01 1.4000000e+00 1.0000000e+00 4.0000000e-01 4.0000000e-01 7.0000000e-01 3.0000000e-01 8.0000000e-01 1.0000000e-01 4.0000000e-01 3.2000000e+00 3.0000000e+00 3.4000000e+00 2.5000000e+00 3.1000000e+00 3.0000000e+00 3.2000000e+00 1.8000000e+00 3.1000000e+00 2.4000000e+00 2.0000000e+00 2.7000000e+00 2.5000000e+00 3.2000000e+00 2.1000000e+00 2.9000000e+00 3.0000000e+00 2.6000000e+00 3.0000000e+00 2.4000000e+00 3.3000000e+00 2.5000000e+00 3.4000000e+00 3.2000000e+00 2.8000000e+00 2.9000000e+00 3.3000000e+00 3.5000000e+00 3.0000000e+00 2.0000000e+00 2.3000000e+00 2.2000000e+00 2.4000000e+00 3.6000000e+00 3.0000000e+00 3.0000000e+00 3.2000000e+00 2.9000000e+00 2.6000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.5000000e+00 1.8000000e+00 2.7000000e+00 2.7000000e+00 2.7000000e+00 2.8000000e+00 1.5000000e+00 2.6000000e+00 4.5000000e+00 3.6000000e+00 4.4000000e+00 4.1000000e+00 4.3000000e+00 5.1000000e+00 3.0000000e+00 4.8000000e+00 4.3000000e+00 4.6000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 5.2000000e+00 5.4000000e+00 3.5000000e+00 4.2000000e+00 3.4000000e+00 5.2000000e+00 3.4000000e+00 4.2000000e+00 4.5000000e+00 3.3000000e+00 3.4000000e+00 4.1000000e+00 4.3000000e+00 4.6000000e+00 4.9000000e+00 4.1000000e+00 3.6000000e+00 4.1000000e+00 4.6000000e+00 4.1000000e+00 4.0000000e+00 3.3000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.6000000e+00 4.4000000e+00 4.2000000e+00 3.7000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.6000000e+00 4.0000000e-01 5.0000000e-01 1.0000000e+00 1.0000000e+00 6.0000000e-01 3.0000000e-01 9.0000000e-01 4.0000000e-01 6.0000000e-01 3.0000000e-01 6.0000000e-01 3.0000000e-01 3.0000000e-01 4.0000000e-01 2.0000000e-01 4.0000000e-01 4.0000000e-01 2.0000000e-01 3.0000000e-01 6.0000000e-01 7.0000000e-01 8.0000000e-01 3.0000000e-01 4.0000000e-01 7.0000000e-01 3.0000000e-01 4.0000000e-01 3.0000000e-01 3.0000000e-01 1.1000000e+00 4.0000000e-01 4.0000000e-01 4.0000000e-01 4.0000000e-01 4.0000000e-01 2.0000000e-01 5.0000000e-01 2.0000000e-01 3.1000000e+00 2.9000000e+00 3.3000000e+00 2.4000000e+00 3.0000000e+00 2.9000000e+00 3.1000000e+00 1.7000000e+00 3.0000000e+00 2.3000000e+00 1.9000000e+00 2.6000000e+00 2.4000000e+00 3.1000000e+00 2.0000000e+00 2.8000000e+00 2.9000000e+00 2.5000000e+00 2.9000000e+00 2.3000000e+00 3.2000000e+00 2.4000000e+00 3.3000000e+00 3.1000000e+00 2.7000000e+00 2.8000000e+00 3.2000000e+00 3.4000000e+00 2.9000000e+00 1.9000000e+00 2.2000000e+00 2.1000000e+00 2.3000000e+00 3.5000000e+00 2.9000000e+00 2.9000000e+00 3.1000000e+00 2.8000000e+00 2.5000000e+00 2.4000000e+00 2.8000000e+00 3.0000000e+00 2.4000000e+00 1.7000000e+00 2.6000000e+00 2.6000000e+00 2.6000000e+00 2.7000000e+00 1.4000000e+00 2.5000000e+00 4.4000000e+00 3.5000000e+00 4.3000000e+00 4.0000000e+00 4.2000000e+00 5.0000000e+00 2.9000000e+00 4.7000000e+00 4.2000000e+00 4.5000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.4000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 5.1000000e+00 5.3000000e+00 3.4000000e+00 4.1000000e+00 3.3000000e+00 5.1000000e+00 3.3000000e+00 4.1000000e+00 4.4000000e+00 3.2000000e+00 3.3000000e+00 4.0000000e+00 4.2000000e+00 4.5000000e+00 4.8000000e+00 4.0000000e+00 3.5000000e+00 4.0000000e+00 4.5000000e+00 4.0000000e+00 3.9000000e+00 3.2000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.5000000e+00 4.3000000e+00 4.1000000e+00 3.6000000e+00 3.4000000e+00 3.6000000e+00 3.8000000e+00 3.5000000e+00 5.0000000e-01 1.0000000e+00 1.4000000e+00 9.0000000e-01 5.0000000e-01 9.0000000e-01 8.0000000e-01 6.0000000e-01 7.0000000e-01 6.0000000e-01 4.0000000e-01 5.0000000e-01 2.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 2.0000000e-01 2.0000000e-01 6.0000000e-01 1.1000000e+00 1.2000000e+00 1.0000000e-01 2.0000000e-01 7.0000000e-01 1.0000000e-01 4.0000000e-01 4.0000000e-01 5.0000000e-01 7.0000000e-01 4.0000000e-01 5.0000000e-01 8.0000000e-01 2.0000000e-01 8.0000000e-01 2.0000000e-01 7.0000000e-01 3.0000000e-01 3.3000000e+00 3.1000000e+00 3.5000000e+00 2.6000000e+00 3.2000000e+00 3.1000000e+00 3.3000000e+00 1.9000000e+00 3.2000000e+00 2.5000000e+00 2.1000000e+00 2.8000000e+00 2.6000000e+00 3.3000000e+00 2.2000000e+00 3.0000000e+00 3.1000000e+00 2.7000000e+00 3.1000000e+00 2.5000000e+00 3.4000000e+00 2.6000000e+00 3.5000000e+00 3.3000000e+00 2.9000000e+00 3.0000000e+00 3.4000000e+00 3.6000000e+00 3.1000000e+00 2.1000000e+00 2.4000000e+00 2.3000000e+00 2.5000000e+00 3.7000000e+00 3.1000000e+00 3.1000000e+00 3.3000000e+00 3.0000000e+00 2.7000000e+00 2.6000000e+00 3.0000000e+00 3.2000000e+00 2.6000000e+00 1.9000000e+00 2.8000000e+00 2.8000000e+00 2.8000000e+00 2.9000000e+00 1.6000000e+00 2.7000000e+00 4.6000000e+00 3.7000000e+00 4.5000000e+00 4.2000000e+00 4.4000000e+00 5.2000000e+00 3.1000000e+00 4.9000000e+00 4.4000000e+00 4.7000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 5.3000000e+00 5.5000000e+00 3.6000000e+00 4.3000000e+00 3.5000000e+00 5.3000000e+00 3.5000000e+00 4.3000000e+00 4.6000000e+00 3.4000000e+00 3.5000000e+00 4.2000000e+00 4.4000000e+00 4.7000000e+00 5.0000000e+00 4.2000000e+00 3.7000000e+00 4.2000000e+00 4.7000000e+00 4.2000000e+00 4.1000000e+00 3.4000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.7000000e+00 4.5000000e+00 4.3000000e+00 3.8000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.7000000e+00 1.5000000e+00 1.4000000e+00 1.1000000e+00 8.0000000e-01 1.4000000e+00 8.0000000e-01 1.1000000e+00 8.0000000e-01 6.0000000e-01 8.0000000e-01 8.0000000e-01 7.0000000e-01 7.0000000e-01 9.0000000e-01 9.0000000e-01 5.0000000e-01 5.0000000e-01 1.1000000e+00 1.1000000e+00 1.2000000e+00 6.0000000e-01 7.0000000e-01 1.2000000e+00 6.0000000e-01 2.0000000e-01 8.0000000e-01 7.0000000e-01 7.0000000e-01 2.0000000e-01 7.0000000e-01 8.0000000e-01 5.0000000e-01 8.0000000e-01 3.0000000e-01 1.0000000e+00 7.0000000e-01 3.6000000e+00 3.4000000e+00 3.8000000e+00 2.9000000e+00 3.5000000e+00 3.4000000e+00 3.6000000e+00 2.2000000e+00 3.5000000e+00 2.8000000e+00 2.4000000e+00 3.1000000e+00 2.9000000e+00 3.6000000e+00 2.5000000e+00 3.3000000e+00 3.4000000e+00 3.0000000e+00 3.4000000e+00 2.8000000e+00 3.7000000e+00 2.9000000e+00 3.8000000e+00 3.6000000e+00 3.2000000e+00 3.3000000e+00 3.7000000e+00 3.9000000e+00 3.4000000e+00 2.4000000e+00 2.7000000e+00 2.6000000e+00 2.8000000e+00 4.0000000e+00 3.4000000e+00 3.4000000e+00 3.6000000e+00 3.3000000e+00 3.0000000e+00 2.9000000e+00 3.3000000e+00 3.5000000e+00 2.9000000e+00 2.2000000e+00 3.1000000e+00 3.1000000e+00 3.1000000e+00 3.2000000e+00 1.9000000e+00 3.0000000e+00 4.9000000e+00 4.0000000e+00 4.8000000e+00 4.5000000e+00 4.7000000e+00 5.5000000e+00 3.4000000e+00 5.2000000e+00 4.7000000e+00 5.0000000e+00 4.0000000e+00 4.2000000e+00 4.4000000e+00 3.9000000e+00 4.0000000e+00 4.2000000e+00 4.4000000e+00 5.6000000e+00 5.8000000e+00 3.9000000e+00 4.6000000e+00 3.8000000e+00 5.6000000e+00 3.8000000e+00 4.6000000e+00 4.9000000e+00 3.7000000e+00 3.8000000e+00 4.5000000e+00 4.7000000e+00 5.0000000e+00 5.3000000e+00 4.5000000e+00 4.0000000e+00 4.5000000e+00 5.0000000e+00 4.5000000e+00 4.4000000e+00 3.7000000e+00 4.3000000e+00 4.5000000e+00 4.0000000e+00 4.0000000e+00 4.8000000e+00 4.6000000e+00 4.1000000e+00 3.9000000e+00 4.1000000e+00 4.3000000e+00 4.0000000e+00 4.0000000e-01 4.0000000e-01 7.0000000e-01 5.0000000e-01 7.0000000e-01 6.0000000e-01 7.0000000e-01 1.2000000e+00 7.0000000e-01 1.0000000e+00 1.0000000e+00 8.0000000e-01 6.0000000e-01 6.0000000e-01 1.1000000e+00 1.0000000e+00 6.0000000e-01 6.0000000e-01 3.0000000e-01 9.0000000e-01 8.0000000e-01 5.0000000e-01 9.0000000e-01 1.4000000e+00 7.0000000e-01 8.0000000e-01 1.7000000e+00 1.4000000e+00 8.0000000e-01 7.0000000e-01 1.0000000e+00 7.0000000e-01 1.2000000e+00 5.0000000e-01 8.0000000e-01 3.5000000e+00 3.3000000e+00 3.7000000e+00 2.8000000e+00 3.4000000e+00 3.3000000e+00 3.5000000e+00 2.1000000e+00 3.4000000e+00 2.7000000e+00 2.3000000e+00 3.0000000e+00 2.8000000e+00 3.5000000e+00 2.4000000e+00 3.2000000e+00 3.3000000e+00 2.9000000e+00 3.3000000e+00 2.7000000e+00 3.6000000e+00 2.8000000e+00 3.7000000e+00 3.5000000e+00 3.1000000e+00 3.2000000e+00 3.6000000e+00 3.8000000e+00 3.3000000e+00 2.3000000e+00 2.6000000e+00 2.5000000e+00 2.7000000e+00 3.9000000e+00 3.3000000e+00 3.3000000e+00 3.5000000e+00 3.2000000e+00 2.9000000e+00 2.8000000e+00 3.2000000e+00 3.4000000e+00 2.8000000e+00 2.1000000e+00 3.0000000e+00 3.0000000e+00 3.0000000e+00 3.1000000e+00 1.8000000e+00 2.9000000e+00 4.8000000e+00 3.9000000e+00 4.7000000e+00 4.4000000e+00 4.6000000e+00 5.4000000e+00 3.3000000e+00 5.1000000e+00 4.6000000e+00 4.9000000e+00 3.9000000e+00 4.1000000e+00 4.3000000e+00 3.8000000e+00 3.9000000e+00 4.1000000e+00 4.3000000e+00 5.5000000e+00 5.7000000e+00 3.8000000e+00 4.5000000e+00 3.7000000e+00 5.5000000e+00 3.7000000e+00 4.5000000e+00 4.8000000e+00 3.6000000e+00 3.7000000e+00 4.4000000e+00 4.6000000e+00 4.9000000e+00 5.2000000e+00 4.4000000e+00 3.9000000e+00 4.4000000e+00 4.9000000e+00 4.4000000e+00 4.3000000e+00 3.6000000e+00 4.2000000e+00 4.4000000e+00 3.9000000e+00 3.9000000e+00 4.7000000e+00 4.5000000e+00 4.0000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 3.9000000e+00 5.0000000e-01 9.0000000e-01 6.0000000e-01 6.0000000e-01 1.0000000e+00 7.0000000e-01 1.1000000e+00 1.1000000e+00 1.0000000e+00 1.4000000e+00 1.0000000e+00 9.0000000e-01 1.0000000e+00 1.2000000e+00 1.3000000e+00 1.0000000e+00 5.0000000e-01 2.0000000e-01 1.3000000e+00 1.2000000e+00 9.0000000e-01 1.3000000e+00 1.4000000e+00 1.0000000e+00 9.0000000e-01 2.1000000e+00 1.3000000e+00 9.0000000e-01 6.0000000e-01 1.4000000e+00 6.0000000e-01 1.2000000e+00 7.0000000e-01 1.1000000e+00 3.2000000e+00 3.0000000e+00 3.4000000e+00 2.5000000e+00 3.1000000e+00 3.0000000e+00 3.2000000e+00 2.0000000e+00 3.1000000e+00 2.4000000e+00 2.4000000e+00 2.7000000e+00 2.5000000e+00 3.2000000e+00 2.1000000e+00 2.9000000e+00 3.0000000e+00 2.6000000e+00 3.0000000e+00 2.4000000e+00 3.3000000e+00 2.5000000e+00 3.4000000e+00 3.2000000e+00 2.8000000e+00 2.9000000e+00 3.3000000e+00 3.5000000e+00 3.0000000e+00 2.0000000e+00 2.3000000e+00 2.2000000e+00 2.4000000e+00 3.6000000e+00 3.0000000e+00 3.0000000e+00 3.2000000e+00 2.9000000e+00 2.6000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.5000000e+00 2.1000000e+00 2.7000000e+00 2.7000000e+00 2.7000000e+00 2.8000000e+00 1.9000000e+00 2.6000000e+00 4.5000000e+00 3.6000000e+00 4.4000000e+00 4.1000000e+00 4.3000000e+00 5.1000000e+00 3.0000000e+00 4.8000000e+00 4.3000000e+00 4.6000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 5.2000000e+00 5.4000000e+00 3.5000000e+00 4.2000000e+00 3.4000000e+00 5.2000000e+00 3.4000000e+00 4.2000000e+00 4.5000000e+00 3.3000000e+00 3.4000000e+00 4.1000000e+00 4.3000000e+00 4.6000000e+00 4.9000000e+00 4.1000000e+00 3.6000000e+00 4.1000000e+00 4.6000000e+00 4.1000000e+00 4.0000000e+00 3.3000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.6000000e+00 4.4000000e+00 4.2000000e+00 3.7000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.6000000e+00 4.0000000e-01 4.0000000e-01 3.0000000e-01 5.0000000e-01 3.0000000e-01 8.0000000e-01 6.0000000e-01 6.0000000e-01 9.0000000e-01 5.0000000e-01 4.0000000e-01 5.0000000e-01 7.0000000e-01 8.0000000e-01 5.0000000e-01 3.0000000e-01 3.0000000e-01 8.0000000e-01 7.0000000e-01 4.0000000e-01 8.0000000e-01 1.0000000e+00 5.0000000e-01 4.0000000e-01 1.6000000e+00 1.0000000e+00 4.0000000e-01 6.0000000e-01 9.0000000e-01 3.0000000e-01 8.0000000e-01 2.0000000e-01 6.0000000e-01 3.4000000e+00 3.2000000e+00 3.6000000e+00 2.7000000e+00 3.3000000e+00 3.2000000e+00 3.4000000e+00 2.0000000e+00 3.3000000e+00 2.6000000e+00 2.2000000e+00 2.9000000e+00 2.7000000e+00 3.4000000e+00 2.3000000e+00 3.1000000e+00 3.2000000e+00 2.8000000e+00 3.2000000e+00 2.6000000e+00 3.5000000e+00 2.7000000e+00 3.6000000e+00 3.4000000e+00 3.0000000e+00 3.1000000e+00 3.5000000e+00 3.7000000e+00 3.2000000e+00 2.2000000e+00 2.5000000e+00 2.4000000e+00 2.6000000e+00 3.8000000e+00 3.2000000e+00 3.2000000e+00 3.4000000e+00 3.1000000e+00 2.8000000e+00 2.7000000e+00 3.1000000e+00 3.3000000e+00 2.7000000e+00 2.0000000e+00 2.9000000e+00 2.9000000e+00 2.9000000e+00 3.0000000e+00 1.7000000e+00 2.8000000e+00 4.7000000e+00 3.8000000e+00 4.6000000e+00 4.3000000e+00 4.5000000e+00 5.3000000e+00 3.2000000e+00 5.0000000e+00 4.5000000e+00 4.8000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 5.4000000e+00 5.6000000e+00 3.7000000e+00 4.4000000e+00 3.6000000e+00 5.4000000e+00 3.6000000e+00 4.4000000e+00 4.7000000e+00 3.5000000e+00 3.6000000e+00 4.3000000e+00 4.5000000e+00 4.8000000e+00 5.1000000e+00 4.3000000e+00 3.8000000e+00 4.3000000e+00 4.8000000e+00 4.3000000e+00 4.2000000e+00 3.5000000e+00 4.1000000e+00 4.3000000e+00 3.8000000e+00 3.8000000e+00 4.6000000e+00 4.4000000e+00 3.9000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.8000000e+00 6.0000000e-01 3.0000000e-01 3.0000000e-01 2.0000000e-01 5.0000000e-01 3.0000000e-01 5.0000000e-01 5.0000000e-01 2.0000000e-01 1.0000000e-01 1.0000000e-01 4.0000000e-01 4.0000000e-01 3.0000000e-01 6.0000000e-01 7.0000000e-01 4.0000000e-01 3.0000000e-01 4.0000000e-01 4.0000000e-01 7.0000000e-01 1.0000000e-01 1.0000000e-01 1.2000000e+00 7.0000000e-01 3.0000000e-01 5.0000000e-01 5.0000000e-01 3.0000000e-01 5.0000000e-01 2.0000000e-01 2.0000000e-01 3.3000000e+00 3.1000000e+00 3.5000000e+00 2.6000000e+00 3.2000000e+00 3.1000000e+00 3.3000000e+00 1.9000000e+00 3.2000000e+00 2.5000000e+00 2.1000000e+00 2.8000000e+00 2.6000000e+00 3.3000000e+00 2.2000000e+00 3.0000000e+00 3.1000000e+00 2.7000000e+00 3.1000000e+00 2.5000000e+00 3.4000000e+00 2.6000000e+00 3.5000000e+00 3.3000000e+00 2.9000000e+00 3.0000000e+00 3.4000000e+00 3.6000000e+00 3.1000000e+00 2.1000000e+00 2.4000000e+00 2.3000000e+00 2.5000000e+00 3.7000000e+00 3.1000000e+00 3.1000000e+00 3.3000000e+00 3.0000000e+00 2.7000000e+00 2.6000000e+00 3.0000000e+00 3.2000000e+00 2.6000000e+00 1.9000000e+00 2.8000000e+00 2.8000000e+00 2.8000000e+00 2.9000000e+00 1.6000000e+00 2.7000000e+00 4.6000000e+00 3.7000000e+00 4.5000000e+00 4.2000000e+00 4.4000000e+00 5.2000000e+00 3.1000000e+00 4.9000000e+00 4.4000000e+00 4.7000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 5.3000000e+00 5.5000000e+00 3.6000000e+00 4.3000000e+00 3.5000000e+00 5.3000000e+00 3.5000000e+00 4.3000000e+00 4.6000000e+00 3.4000000e+00 3.5000000e+00 4.2000000e+00 4.4000000e+00 4.7000000e+00 5.0000000e+00 4.2000000e+00 3.7000000e+00 4.2000000e+00 4.7000000e+00 4.2000000e+00 4.1000000e+00 3.4000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.7000000e+00 4.5000000e+00 4.3000000e+00 3.8000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.7000000e+00 6.0000000e-01 4.0000000e-01 6.0000000e-01 1.1000000e+00 6.0000000e-01 9.0000000e-01 8.0000000e-01 7.0000000e-01 5.0000000e-01 5.0000000e-01 1.0000000e+00 9.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 8.0000000e-01 7.0000000e-01 4.0000000e-01 8.0000000e-01 1.3000000e+00 6.0000000e-01 7.0000000e-01 1.5000000e+00 1.3000000e+00 7.0000000e-01 6.0000000e-01 9.0000000e-01 6.0000000e-01 1.1000000e+00 4.0000000e-01 7.0000000e-01 3.0000000e+00 2.8000000e+00 3.2000000e+00 2.3000000e+00 2.9000000e+00 2.8000000e+00 3.0000000e+00 1.6000000e+00 2.9000000e+00 2.2000000e+00 1.8000000e+00 2.5000000e+00 2.3000000e+00 3.0000000e+00 1.9000000e+00 2.7000000e+00 2.8000000e+00 2.4000000e+00 2.8000000e+00 2.2000000e+00 3.1000000e+00 2.3000000e+00 3.2000000e+00 3.0000000e+00 2.6000000e+00 2.7000000e+00 3.1000000e+00 3.3000000e+00 2.8000000e+00 1.8000000e+00 2.1000000e+00 2.0000000e+00 2.2000000e+00 3.4000000e+00 2.8000000e+00 2.8000000e+00 3.0000000e+00 2.7000000e+00 2.4000000e+00 2.3000000e+00 2.7000000e+00 2.9000000e+00 2.3000000e+00 1.6000000e+00 2.5000000e+00 2.5000000e+00 2.5000000e+00 2.6000000e+00 1.3000000e+00 2.4000000e+00 4.3000000e+00 3.4000000e+00 4.2000000e+00 3.9000000e+00 4.1000000e+00 4.9000000e+00 2.8000000e+00 4.6000000e+00 4.1000000e+00 4.4000000e+00 3.4000000e+00 3.6000000e+00 3.8000000e+00 3.3000000e+00 3.4000000e+00 3.6000000e+00 3.8000000e+00 5.0000000e+00 5.2000000e+00 3.3000000e+00 4.0000000e+00 3.2000000e+00 5.0000000e+00 3.2000000e+00 4.0000000e+00 4.3000000e+00 3.1000000e+00 3.2000000e+00 3.9000000e+00 4.1000000e+00 4.4000000e+00 4.7000000e+00 3.9000000e+00 3.4000000e+00 3.9000000e+00 4.4000000e+00 3.9000000e+00 3.8000000e+00 3.1000000e+00 3.7000000e+00 3.9000000e+00 3.4000000e+00 3.4000000e+00 4.2000000e+00 4.0000000e+00 3.5000000e+00 3.3000000e+00 3.5000000e+00 3.7000000e+00 3.4000000e+00 4.0000000e-01 1.0000000e-01 5.0000000e-01 5.0000000e-01 4.0000000e-01 8.0000000e-01 4.0000000e-01 3.0000000e-01 4.0000000e-01 6.0000000e-01 7.0000000e-01 4.0000000e-01 3.0000000e-01 4.0000000e-01 7.0000000e-01 6.0000000e-01 4.0000000e-01 7.0000000e-01 8.0000000e-01 4.0000000e-01 3.0000000e-01 1.5000000e+00 7.0000000e-01 3.0000000e-01 4.0000000e-01 8.0000000e-01 1.0000000e-01 6.0000000e-01 2.0000000e-01 5.0000000e-01 3.2000000e+00 3.0000000e+00 3.4000000e+00 2.5000000e+00 3.1000000e+00 3.0000000e+00 3.2000000e+00 1.8000000e+00 3.1000000e+00 2.4000000e+00 2.0000000e+00 2.7000000e+00 2.5000000e+00 3.2000000e+00 2.1000000e+00 2.9000000e+00 3.0000000e+00 2.6000000e+00 3.0000000e+00 2.4000000e+00 3.3000000e+00 2.5000000e+00 3.4000000e+00 3.2000000e+00 2.8000000e+00 2.9000000e+00 3.3000000e+00 3.5000000e+00 3.0000000e+00 2.0000000e+00 2.3000000e+00 2.2000000e+00 2.4000000e+00 3.6000000e+00 3.0000000e+00 3.0000000e+00 3.2000000e+00 2.9000000e+00 2.6000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.5000000e+00 1.8000000e+00 2.7000000e+00 2.7000000e+00 2.7000000e+00 2.8000000e+00 1.5000000e+00 2.6000000e+00 4.5000000e+00 3.6000000e+00 4.4000000e+00 4.1000000e+00 4.3000000e+00 5.1000000e+00 3.0000000e+00 4.8000000e+00 4.3000000e+00 4.6000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 5.2000000e+00 5.4000000e+00 3.5000000e+00 4.2000000e+00 3.4000000e+00 5.2000000e+00 3.4000000e+00 4.2000000e+00 4.5000000e+00 3.3000000e+00 3.4000000e+00 4.1000000e+00 4.3000000e+00 4.6000000e+00 4.9000000e+00 4.1000000e+00 3.6000000e+00 4.1000000e+00 4.6000000e+00 4.1000000e+00 4.0000000e+00 3.3000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.6000000e+00 4.4000000e+00 4.2000000e+00 3.7000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.6000000e+00 3.0000000e-01 8.0000000e-01 3.0000000e-01 6.0000000e-01 4.0000000e-01 4.0000000e-01 2.0000000e-01 3.0000000e-01 7.0000000e-01 6.0000000e-01 2.0000000e-01 7.0000000e-01 8.0000000e-01 5.0000000e-01 5.0000000e-01 4.0000000e-01 5.0000000e-01 1.0000000e+00 3.0000000e-01 4.0000000e-01 1.1000000e+00 1.0000000e+00 4.0000000e-01 4.0000000e-01 6.0000000e-01 4.0000000e-01 8.0000000e-01 3.0000000e-01 4.0000000e-01 3.0000000e+00 2.8000000e+00 3.2000000e+00 2.3000000e+00 2.9000000e+00 2.8000000e+00 3.0000000e+00 1.6000000e+00 2.9000000e+00 2.2000000e+00 1.8000000e+00 2.5000000e+00 2.3000000e+00 3.0000000e+00 1.9000000e+00 2.7000000e+00 2.8000000e+00 2.4000000e+00 2.8000000e+00 2.2000000e+00 3.1000000e+00 2.3000000e+00 3.2000000e+00 3.0000000e+00 2.6000000e+00 2.7000000e+00 3.1000000e+00 3.3000000e+00 2.8000000e+00 1.8000000e+00 2.1000000e+00 2.0000000e+00 2.2000000e+00 3.4000000e+00 2.8000000e+00 2.8000000e+00 3.0000000e+00 2.7000000e+00 2.4000000e+00 2.3000000e+00 2.7000000e+00 2.9000000e+00 2.3000000e+00 1.6000000e+00 2.5000000e+00 2.5000000e+00 2.5000000e+00 2.6000000e+00 1.3000000e+00 2.4000000e+00 4.3000000e+00 3.4000000e+00 4.2000000e+00 3.9000000e+00 4.1000000e+00 4.9000000e+00 2.8000000e+00 4.6000000e+00 4.1000000e+00 4.4000000e+00 3.4000000e+00 3.6000000e+00 3.8000000e+00 3.3000000e+00 3.4000000e+00 3.6000000e+00 3.8000000e+00 5.0000000e+00 5.2000000e+00 3.3000000e+00 4.0000000e+00 3.2000000e+00 5.0000000e+00 3.2000000e+00 4.0000000e+00 4.3000000e+00 3.1000000e+00 3.2000000e+00 3.9000000e+00 4.1000000e+00 4.4000000e+00 4.7000000e+00 3.9000000e+00 3.4000000e+00 3.9000000e+00 4.4000000e+00 3.9000000e+00 3.8000000e+00 3.1000000e+00 3.7000000e+00 3.9000000e+00 3.4000000e+00 3.4000000e+00 4.2000000e+00 4.0000000e+00 3.5000000e+00 3.3000000e+00 3.5000000e+00 3.7000000e+00 3.4000000e+00 5.0000000e-01 4.0000000e-01 4.0000000e-01 7.0000000e-01 3.0000000e-01 2.0000000e-01 3.0000000e-01 5.0000000e-01 6.0000000e-01 3.0000000e-01 4.0000000e-01 5.0000000e-01 6.0000000e-01 5.0000000e-01 4.0000000e-01 6.0000000e-01 7.0000000e-01 3.0000000e-01 2.0000000e-01 1.4000000e+00 7.0000000e-01 2.0000000e-01 4.0000000e-01 7.0000000e-01 2.0000000e-01 5.0000000e-01 2.0000000e-01 4.0000000e-01 3.2000000e+00 3.0000000e+00 3.4000000e+00 2.5000000e+00 3.1000000e+00 3.0000000e+00 3.2000000e+00 1.8000000e+00 3.1000000e+00 2.4000000e+00 2.0000000e+00 2.7000000e+00 2.5000000e+00 3.2000000e+00 2.1000000e+00 2.9000000e+00 3.0000000e+00 2.6000000e+00 3.0000000e+00 2.4000000e+00 3.3000000e+00 2.5000000e+00 3.4000000e+00 3.2000000e+00 2.8000000e+00 2.9000000e+00 3.3000000e+00 3.5000000e+00 3.0000000e+00 2.0000000e+00 2.3000000e+00 2.2000000e+00 2.4000000e+00 3.6000000e+00 3.0000000e+00 3.0000000e+00 3.2000000e+00 2.9000000e+00 2.6000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.5000000e+00 1.8000000e+00 2.7000000e+00 2.7000000e+00 2.7000000e+00 2.8000000e+00 1.5000000e+00 2.6000000e+00 4.5000000e+00 3.6000000e+00 4.4000000e+00 4.1000000e+00 4.3000000e+00 5.1000000e+00 3.0000000e+00 4.8000000e+00 4.3000000e+00 4.6000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 5.2000000e+00 5.4000000e+00 3.5000000e+00 4.2000000e+00 3.4000000e+00 5.2000000e+00 3.4000000e+00 4.2000000e+00 4.5000000e+00 3.3000000e+00 3.4000000e+00 4.1000000e+00 4.3000000e+00 4.6000000e+00 4.9000000e+00 4.1000000e+00 3.6000000e+00 4.1000000e+00 4.6000000e+00 4.1000000e+00 4.0000000e+00 3.3000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.6000000e+00 4.4000000e+00 4.2000000e+00 3.7000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.6000000e+00 7.0000000e-01 9.0000000e-01 6.0000000e-01 6.0000000e-01 6.0000000e-01 6.0000000e-01 6.0000000e-01 6.0000000e-01 8.0000000e-01 6.0000000e-01 9.0000000e-01 5.0000000e-01 4.0000000e-01 9.0000000e-01 5.0000000e-01 6.0000000e-01 5.0000000e-01 4.0000000e-01 1.3000000e+00 4.0000000e-01 6.0000000e-01 9.0000000e-01 6.0000000e-01 6.0000000e-01 4.0000000e-01 7.0000000e-01 4.0000000e-01 3.7000000e+00 3.5000000e+00 3.9000000e+00 3.0000000e+00 3.6000000e+00 3.5000000e+00 3.7000000e+00 2.3000000e+00 3.6000000e+00 2.9000000e+00 2.5000000e+00 3.2000000e+00 3.0000000e+00 3.7000000e+00 2.6000000e+00 3.4000000e+00 3.5000000e+00 3.1000000e+00 3.5000000e+00 2.9000000e+00 3.8000000e+00 3.0000000e+00 3.9000000e+00 3.7000000e+00 3.3000000e+00 3.4000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 2.5000000e+00 2.8000000e+00 2.7000000e+00 2.9000000e+00 4.1000000e+00 3.5000000e+00 3.5000000e+00 3.7000000e+00 3.4000000e+00 3.1000000e+00 3.0000000e+00 3.4000000e+00 3.6000000e+00 3.0000000e+00 2.3000000e+00 3.2000000e+00 3.2000000e+00 3.2000000e+00 3.3000000e+00 2.0000000e+00 3.1000000e+00 5.0000000e+00 4.1000000e+00 4.9000000e+00 4.6000000e+00 4.8000000e+00 5.6000000e+00 3.5000000e+00 5.3000000e+00 4.8000000e+00 5.1000000e+00 4.1000000e+00 4.3000000e+00 4.5000000e+00 4.0000000e+00 4.1000000e+00 4.3000000e+00 4.5000000e+00 5.7000000e+00 5.9000000e+00 4.0000000e+00 4.7000000e+00 3.9000000e+00 5.7000000e+00 3.9000000e+00 4.7000000e+00 5.0000000e+00 3.8000000e+00 3.9000000e+00 4.6000000e+00 4.8000000e+00 5.1000000e+00 5.4000000e+00 4.6000000e+00 4.1000000e+00 4.6000000e+00 5.1000000e+00 4.6000000e+00 4.5000000e+00 3.8000000e+00 4.4000000e+00 4.6000000e+00 4.1000000e+00 4.1000000e+00 4.9000000e+00 4.7000000e+00 4.2000000e+00 4.0000000e+00 4.2000000e+00 4.4000000e+00 4.1000000e+00 3.0000000e-01 3.0000000e-01 1.0000000e-01 3.0000000e-01 3.0000000e-01 4.0000000e-01 3.0000000e-01 3.0000000e-01 8.0000000e-01 9.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 4.0000000e-01 7.0000000e-01 3.0000000e-01 4.0000000e-01 1.0000000e+00 7.0000000e-01 2.0000000e-01 5.0000000e-01 3.0000000e-01 5.0000000e-01 5.0000000e-01 4.0000000e-01 3.0000000e-01 3.0000000e+00 2.8000000e+00 3.2000000e+00 2.3000000e+00 2.9000000e+00 2.8000000e+00 3.0000000e+00 1.6000000e+00 2.9000000e+00 2.2000000e+00 1.8000000e+00 2.5000000e+00 2.3000000e+00 3.0000000e+00 1.9000000e+00 2.7000000e+00 2.8000000e+00 2.4000000e+00 2.8000000e+00 2.2000000e+00 3.1000000e+00 2.3000000e+00 3.2000000e+00 3.0000000e+00 2.6000000e+00 2.7000000e+00 3.1000000e+00 3.3000000e+00 2.8000000e+00 1.8000000e+00 2.1000000e+00 2.0000000e+00 2.2000000e+00 3.4000000e+00 2.8000000e+00 2.8000000e+00 3.0000000e+00 2.7000000e+00 2.4000000e+00 2.3000000e+00 2.7000000e+00 2.9000000e+00 2.3000000e+00 1.6000000e+00 2.5000000e+00 2.5000000e+00 2.5000000e+00 2.6000000e+00 1.3000000e+00 2.4000000e+00 4.3000000e+00 3.4000000e+00 4.2000000e+00 3.9000000e+00 4.1000000e+00 4.9000000e+00 2.8000000e+00 4.6000000e+00 4.1000000e+00 4.4000000e+00 3.4000000e+00 3.6000000e+00 3.8000000e+00 3.3000000e+00 3.4000000e+00 3.6000000e+00 3.8000000e+00 5.0000000e+00 5.2000000e+00 3.3000000e+00 4.0000000e+00 3.2000000e+00 5.0000000e+00 3.2000000e+00 4.0000000e+00 4.3000000e+00 3.1000000e+00 3.2000000e+00 3.9000000e+00 4.1000000e+00 4.4000000e+00 4.7000000e+00 3.9000000e+00 3.4000000e+00 3.9000000e+00 4.4000000e+00 3.9000000e+00 3.8000000e+00 3.1000000e+00 3.7000000e+00 3.9000000e+00 3.4000000e+00 3.4000000e+00 4.2000000e+00 4.0000000e+00 3.5000000e+00 3.3000000e+00 3.5000000e+00 3.7000000e+00 3.4000000e+00 4.0000000e-01 3.0000000e-01 4.0000000e-01 5.0000000e-01 3.0000000e-01 3.0000000e-01 6.0000000e-01 7.0000000e-01 8.0000000e-01 4.0000000e-01 7.0000000e-01 7.0000000e-01 4.0000000e-01 6.0000000e-01 4.0000000e-01 6.0000000e-01 1.1000000e+00 6.0000000e-01 4.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 5.0000000e-01 5.0000000e-01 5.0000000e-01 2.8000000e+00 2.6000000e+00 3.0000000e+00 2.1000000e+00 2.7000000e+00 2.6000000e+00 2.8000000e+00 1.4000000e+00 2.7000000e+00 2.0000000e+00 1.6000000e+00 2.3000000e+00 2.1000000e+00 2.8000000e+00 1.7000000e+00 2.5000000e+00 2.6000000e+00 2.2000000e+00 2.6000000e+00 2.0000000e+00 2.9000000e+00 2.1000000e+00 3.0000000e+00 2.8000000e+00 2.4000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.6000000e+00 1.6000000e+00 1.9000000e+00 1.8000000e+00 2.0000000e+00 3.2000000e+00 2.6000000e+00 2.6000000e+00 2.8000000e+00 2.5000000e+00 2.2000000e+00 2.1000000e+00 2.5000000e+00 2.7000000e+00 2.1000000e+00 1.4000000e+00 2.3000000e+00 2.3000000e+00 2.3000000e+00 2.4000000e+00 1.1000000e+00 2.2000000e+00 4.1000000e+00 3.2000000e+00 4.0000000e+00 3.7000000e+00 3.9000000e+00 4.7000000e+00 2.6000000e+00 4.4000000e+00 3.9000000e+00 4.2000000e+00 3.2000000e+00 3.4000000e+00 3.6000000e+00 3.1000000e+00 3.2000000e+00 3.4000000e+00 3.6000000e+00 4.8000000e+00 5.0000000e+00 3.1000000e+00 3.8000000e+00 3.0000000e+00 4.8000000e+00 3.0000000e+00 3.8000000e+00 4.1000000e+00 2.9000000e+00 3.0000000e+00 3.7000000e+00 3.9000000e+00 4.2000000e+00 4.5000000e+00 3.7000000e+00 3.2000000e+00 3.7000000e+00 4.2000000e+00 3.7000000e+00 3.6000000e+00 2.9000000e+00 3.5000000e+00 3.7000000e+00 3.2000000e+00 3.2000000e+00 4.0000000e+00 3.8000000e+00 3.3000000e+00 3.1000000e+00 3.3000000e+00 3.5000000e+00 3.2000000e+00 4.0000000e-01 5.0000000e-01 4.0000000e-01 3.0000000e-01 2.0000000e-01 4.0000000e-01 1.1000000e+00 1.2000000e+00 1.0000000e-01 4.0000000e-01 5.0000000e-01 1.0000000e-01 6.0000000e-01 4.0000000e-01 5.0000000e-01 7.0000000e-01 6.0000000e-01 5.0000000e-01 8.0000000e-01 2.0000000e-01 8.0000000e-01 4.0000000e-01 7.0000000e-01 3.0000000e-01 3.1000000e+00 2.9000000e+00 3.3000000e+00 2.4000000e+00 3.0000000e+00 2.9000000e+00 3.1000000e+00 1.7000000e+00 3.0000000e+00 2.3000000e+00 1.9000000e+00 2.6000000e+00 2.4000000e+00 3.1000000e+00 2.0000000e+00 2.8000000e+00 2.9000000e+00 2.5000000e+00 2.9000000e+00 2.3000000e+00 3.2000000e+00 2.4000000e+00 3.3000000e+00 3.1000000e+00 2.7000000e+00 2.8000000e+00 3.2000000e+00 3.4000000e+00 2.9000000e+00 1.9000000e+00 2.2000000e+00 2.1000000e+00 2.3000000e+00 3.5000000e+00 2.9000000e+00 2.9000000e+00 3.1000000e+00 2.8000000e+00 2.5000000e+00 2.4000000e+00 2.8000000e+00 3.0000000e+00 2.4000000e+00 1.7000000e+00 2.6000000e+00 2.6000000e+00 2.6000000e+00 2.7000000e+00 1.4000000e+00 2.5000000e+00 4.4000000e+00 3.5000000e+00 4.3000000e+00 4.0000000e+00 4.2000000e+00 5.0000000e+00 2.9000000e+00 4.7000000e+00 4.2000000e+00 4.5000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.4000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 5.1000000e+00 5.3000000e+00 3.4000000e+00 4.1000000e+00 3.3000000e+00 5.1000000e+00 3.3000000e+00 4.1000000e+00 4.4000000e+00 3.2000000e+00 3.3000000e+00 4.0000000e+00 4.2000000e+00 4.5000000e+00 4.8000000e+00 4.0000000e+00 3.5000000e+00 4.0000000e+00 4.5000000e+00 4.0000000e+00 3.9000000e+00 3.2000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.5000000e+00 4.3000000e+00 4.1000000e+00 3.6000000e+00 3.4000000e+00 3.6000000e+00 3.8000000e+00 3.5000000e+00 2.0000000e-01 2.0000000e-01 3.0000000e-01 3.0000000e-01 4.0000000e-01 7.0000000e-01 8.0000000e-01 3.0000000e-01 4.0000000e-01 5.0000000e-01 3.0000000e-01 6.0000000e-01 2.0000000e-01 3.0000000e-01 1.1000000e+00 6.0000000e-01 2.0000000e-01 4.0000000e-01 4.0000000e-01 4.0000000e-01 4.0000000e-01 3.0000000e-01 2.0000000e-01 3.1000000e+00 2.9000000e+00 3.3000000e+00 2.4000000e+00 3.0000000e+00 2.9000000e+00 3.1000000e+00 1.7000000e+00 3.0000000e+00 2.3000000e+00 1.9000000e+00 2.6000000e+00 2.4000000e+00 3.1000000e+00 2.0000000e+00 2.8000000e+00 2.9000000e+00 2.5000000e+00 2.9000000e+00 2.3000000e+00 3.2000000e+00 2.4000000e+00 3.3000000e+00 3.1000000e+00 2.7000000e+00 2.8000000e+00 3.2000000e+00 3.4000000e+00 2.9000000e+00 1.9000000e+00 2.2000000e+00 2.1000000e+00 2.3000000e+00 3.5000000e+00 2.9000000e+00 2.9000000e+00 3.1000000e+00 2.8000000e+00 2.5000000e+00 2.4000000e+00 2.8000000e+00 3.0000000e+00 2.4000000e+00 1.7000000e+00 2.6000000e+00 2.6000000e+00 2.6000000e+00 2.7000000e+00 1.4000000e+00 2.5000000e+00 4.4000000e+00 3.5000000e+00 4.3000000e+00 4.0000000e+00 4.2000000e+00 5.0000000e+00 2.9000000e+00 4.7000000e+00 4.2000000e+00 4.5000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.4000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 5.1000000e+00 5.3000000e+00 3.4000000e+00 4.1000000e+00 3.3000000e+00 5.1000000e+00 3.3000000e+00 4.1000000e+00 4.4000000e+00 3.2000000e+00 3.3000000e+00 4.0000000e+00 4.2000000e+00 4.5000000e+00 4.8000000e+00 4.0000000e+00 3.5000000e+00 4.0000000e+00 4.5000000e+00 4.0000000e+00 3.9000000e+00 3.2000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.5000000e+00 4.3000000e+00 4.1000000e+00 3.6000000e+00 3.4000000e+00 3.6000000e+00 3.8000000e+00 3.5000000e+00 1.0000000e-01 5.0000000e-01 4.0000000e-01 2.0000000e-01 6.0000000e-01 7.0000000e-01 4.0000000e-01 3.0000000e-01 3.0000000e-01 4.0000000e-01 8.0000000e-01 1.0000000e-01 2.0000000e-01 1.2000000e+00 8.0000000e-01 4.0000000e-01 4.0000000e-01 5.0000000e-01 3.0000000e-01 6.0000000e-01 2.0000000e-01 2.0000000e-01 3.2000000e+00 3.0000000e+00 3.4000000e+00 2.5000000e+00 3.1000000e+00 3.0000000e+00 3.2000000e+00 1.8000000e+00 3.1000000e+00 2.4000000e+00 2.0000000e+00 2.7000000e+00 2.5000000e+00 3.2000000e+00 2.1000000e+00 2.9000000e+00 3.0000000e+00 2.6000000e+00 3.0000000e+00 2.4000000e+00 3.3000000e+00 2.5000000e+00 3.4000000e+00 3.2000000e+00 2.8000000e+00 2.9000000e+00 3.3000000e+00 3.5000000e+00 3.0000000e+00 2.0000000e+00 2.3000000e+00 2.2000000e+00 2.4000000e+00 3.6000000e+00 3.0000000e+00 3.0000000e+00 3.2000000e+00 2.9000000e+00 2.6000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.5000000e+00 1.8000000e+00 2.7000000e+00 2.7000000e+00 2.7000000e+00 2.8000000e+00 1.5000000e+00 2.6000000e+00 4.5000000e+00 3.6000000e+00 4.4000000e+00 4.1000000e+00 4.3000000e+00 5.1000000e+00 3.0000000e+00 4.8000000e+00 4.3000000e+00 4.6000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 5.2000000e+00 5.4000000e+00 3.5000000e+00 4.2000000e+00 3.4000000e+00 5.2000000e+00 3.4000000e+00 4.2000000e+00 4.5000000e+00 3.3000000e+00 3.4000000e+00 4.1000000e+00 4.3000000e+00 4.6000000e+00 4.9000000e+00 4.1000000e+00 3.6000000e+00 4.1000000e+00 4.6000000e+00 4.1000000e+00 4.0000000e+00 3.3000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.6000000e+00 4.4000000e+00 4.2000000e+00 3.7000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.6000000e+00 5.0000000e-01 4.0000000e-01 2.0000000e-01 7.0000000e-01 8.0000000e-01 3.0000000e-01 2.0000000e-01 3.0000000e-01 3.0000000e-01 8.0000000e-01 1.0000000e-01 2.0000000e-01 1.1000000e+00 8.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 4.0000000e-01 6.0000000e-01 3.0000000e-01 2.0000000e-01 3.3000000e+00 3.1000000e+00 3.5000000e+00 2.6000000e+00 3.2000000e+00 3.1000000e+00 3.3000000e+00 1.9000000e+00 3.2000000e+00 2.5000000e+00 2.1000000e+00 2.8000000e+00 2.6000000e+00 3.3000000e+00 2.2000000e+00 3.0000000e+00 3.1000000e+00 2.7000000e+00 3.1000000e+00 2.5000000e+00 3.4000000e+00 2.6000000e+00 3.5000000e+00 3.3000000e+00 2.9000000e+00 3.0000000e+00 3.4000000e+00 3.6000000e+00 3.1000000e+00 2.1000000e+00 2.4000000e+00 2.3000000e+00 2.5000000e+00 3.7000000e+00 3.1000000e+00 3.1000000e+00 3.3000000e+00 3.0000000e+00 2.7000000e+00 2.6000000e+00 3.0000000e+00 3.2000000e+00 2.6000000e+00 1.9000000e+00 2.8000000e+00 2.8000000e+00 2.8000000e+00 2.9000000e+00 1.6000000e+00 2.7000000e+00 4.6000000e+00 3.7000000e+00 4.5000000e+00 4.2000000e+00 4.4000000e+00 5.2000000e+00 3.1000000e+00 4.9000000e+00 4.4000000e+00 4.7000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 5.3000000e+00 5.5000000e+00 3.6000000e+00 4.3000000e+00 3.5000000e+00 5.3000000e+00 3.5000000e+00 4.3000000e+00 4.6000000e+00 3.4000000e+00 3.5000000e+00 4.2000000e+00 4.4000000e+00 4.7000000e+00 5.0000000e+00 4.2000000e+00 3.7000000e+00 4.2000000e+00 4.7000000e+00 4.2000000e+00 4.1000000e+00 3.4000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.7000000e+00 4.5000000e+00 4.3000000e+00 3.8000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.7000000e+00 1.0000000e-01 7.0000000e-01 9.0000000e-01 1.0000000e+00 2.0000000e-01 4.0000000e-01 8.0000000e-01 2.0000000e-01 3.0000000e-01 4.0000000e-01 3.0000000e-01 9.0000000e-01 3.0000000e-01 4.0000000e-01 6.0000000e-01 2.0000000e-01 6.0000000e-01 2.0000000e-01 6.0000000e-01 3.0000000e-01 3.1000000e+00 2.9000000e+00 3.3000000e+00 2.4000000e+00 3.0000000e+00 2.9000000e+00 3.1000000e+00 1.7000000e+00 3.0000000e+00 2.3000000e+00 1.9000000e+00 2.6000000e+00 2.4000000e+00 3.1000000e+00 2.0000000e+00 2.8000000e+00 2.9000000e+00 2.5000000e+00 2.9000000e+00 2.3000000e+00 3.2000000e+00 2.4000000e+00 3.3000000e+00 3.1000000e+00 2.7000000e+00 2.8000000e+00 3.2000000e+00 3.4000000e+00 2.9000000e+00 1.9000000e+00 2.2000000e+00 2.1000000e+00 2.3000000e+00 3.5000000e+00 2.9000000e+00 2.9000000e+00 3.1000000e+00 2.8000000e+00 2.5000000e+00 2.4000000e+00 2.8000000e+00 3.0000000e+00 2.4000000e+00 1.7000000e+00 2.6000000e+00 2.6000000e+00 2.6000000e+00 2.7000000e+00 1.4000000e+00 2.5000000e+00 4.4000000e+00 3.5000000e+00 4.3000000e+00 4.0000000e+00 4.2000000e+00 5.0000000e+00 2.9000000e+00 4.7000000e+00 4.2000000e+00 4.5000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.4000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 5.1000000e+00 5.3000000e+00 3.4000000e+00 4.1000000e+00 3.3000000e+00 5.1000000e+00 3.3000000e+00 4.1000000e+00 4.4000000e+00 3.2000000e+00 3.3000000e+00 4.0000000e+00 4.2000000e+00 4.5000000e+00 4.8000000e+00 4.0000000e+00 3.5000000e+00 4.0000000e+00 4.5000000e+00 4.0000000e+00 3.9000000e+00 3.2000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.5000000e+00 4.3000000e+00 4.1000000e+00 3.6000000e+00 3.4000000e+00 3.6000000e+00 3.8000000e+00 3.5000000e+00 6.0000000e-01 1.0000000e+00 1.1000000e+00 1.0000000e-01 4.0000000e-01 7.0000000e-01 1.0000000e-01 4.0000000e-01 3.0000000e-01 4.0000000e-01 8.0000000e-01 4.0000000e-01 4.0000000e-01 7.0000000e-01 2.0000000e-01 7.0000000e-01 2.0000000e-01 6.0000000e-01 2.0000000e-01 3.1000000e+00 2.9000000e+00 3.3000000e+00 2.4000000e+00 3.0000000e+00 2.9000000e+00 3.1000000e+00 1.7000000e+00 3.0000000e+00 2.3000000e+00 1.9000000e+00 2.6000000e+00 2.4000000e+00 3.1000000e+00 2.0000000e+00 2.8000000e+00 2.9000000e+00 2.5000000e+00 2.9000000e+00 2.3000000e+00 3.2000000e+00 2.4000000e+00 3.3000000e+00 3.1000000e+00 2.7000000e+00 2.8000000e+00 3.2000000e+00 3.4000000e+00 2.9000000e+00 1.9000000e+00 2.2000000e+00 2.1000000e+00 2.3000000e+00 3.5000000e+00 2.9000000e+00 2.9000000e+00 3.1000000e+00 2.8000000e+00 2.5000000e+00 2.4000000e+00 2.8000000e+00 3.0000000e+00 2.4000000e+00 1.7000000e+00 2.6000000e+00 2.6000000e+00 2.6000000e+00 2.7000000e+00 1.4000000e+00 2.5000000e+00 4.4000000e+00 3.5000000e+00 4.3000000e+00 4.0000000e+00 4.2000000e+00 5.0000000e+00 2.9000000e+00 4.7000000e+00 4.2000000e+00 4.5000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.4000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 5.1000000e+00 5.3000000e+00 3.4000000e+00 4.1000000e+00 3.3000000e+00 5.1000000e+00 3.3000000e+00 4.1000000e+00 4.4000000e+00 3.2000000e+00 3.3000000e+00 4.0000000e+00 4.2000000e+00 4.5000000e+00 4.8000000e+00 4.0000000e+00 3.5000000e+00 4.0000000e+00 4.5000000e+00 4.0000000e+00 3.9000000e+00 3.2000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.5000000e+00 4.3000000e+00 4.1000000e+00 3.6000000e+00 3.4000000e+00 3.6000000e+00 3.8000000e+00 3.5000000e+00 7.0000000e-01 8.0000000e-01 5.0000000e-01 4.0000000e-01 2.0000000e-01 5.0000000e-01 1.0000000e+00 3.0000000e-01 4.0000000e-01 1.1000000e+00 1.0000000e+00 4.0000000e-01 4.0000000e-01 6.0000000e-01 4.0000000e-01 8.0000000e-01 3.0000000e-01 4.0000000e-01 3.2000000e+00 3.0000000e+00 3.4000000e+00 2.5000000e+00 3.1000000e+00 3.0000000e+00 3.2000000e+00 1.8000000e+00 3.1000000e+00 2.4000000e+00 2.0000000e+00 2.7000000e+00 2.5000000e+00 3.2000000e+00 2.1000000e+00 2.9000000e+00 3.0000000e+00 2.6000000e+00 3.0000000e+00 2.4000000e+00 3.3000000e+00 2.5000000e+00 3.4000000e+00 3.2000000e+00 2.8000000e+00 2.9000000e+00 3.3000000e+00 3.5000000e+00 3.0000000e+00 2.0000000e+00 2.3000000e+00 2.2000000e+00 2.4000000e+00 3.6000000e+00 3.0000000e+00 3.0000000e+00 3.2000000e+00 2.9000000e+00 2.6000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.5000000e+00 1.8000000e+00 2.7000000e+00 2.7000000e+00 2.7000000e+00 2.8000000e+00 1.5000000e+00 2.6000000e+00 4.5000000e+00 3.6000000e+00 4.4000000e+00 4.1000000e+00 4.3000000e+00 5.1000000e+00 3.0000000e+00 4.8000000e+00 4.3000000e+00 4.6000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 5.2000000e+00 5.4000000e+00 3.5000000e+00 4.2000000e+00 3.4000000e+00 5.2000000e+00 3.4000000e+00 4.2000000e+00 4.5000000e+00 3.3000000e+00 3.4000000e+00 4.1000000e+00 4.3000000e+00 4.6000000e+00 4.9000000e+00 4.1000000e+00 3.6000000e+00 4.1000000e+00 4.6000000e+00 4.1000000e+00 4.0000000e+00 3.3000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.6000000e+00 4.4000000e+00 4.2000000e+00 3.7000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.6000000e+00 3.0000000e-01 1.0000000e+00 9.0000000e-01 6.0000000e-01 1.0000000e+00 1.1000000e+00 7.0000000e-01 6.0000000e-01 1.8000000e+00 9.0000000e-01 6.0000000e-01 4.0000000e-01 1.1000000e+00 3.0000000e-01 9.0000000e-01 4.0000000e-01 8.0000000e-01 3.2000000e+00 3.0000000e+00 3.4000000e+00 2.5000000e+00 3.1000000e+00 3.0000000e+00 3.2000000e+00 1.8000000e+00 3.1000000e+00 2.4000000e+00 2.1000000e+00 2.7000000e+00 2.5000000e+00 3.2000000e+00 2.1000000e+00 2.9000000e+00 3.0000000e+00 2.6000000e+00 3.0000000e+00 2.4000000e+00 3.3000000e+00 2.5000000e+00 3.4000000e+00 3.2000000e+00 2.8000000e+00 2.9000000e+00 3.3000000e+00 3.5000000e+00 3.0000000e+00 2.0000000e+00 2.3000000e+00 2.2000000e+00 2.4000000e+00 3.6000000e+00 3.0000000e+00 3.0000000e+00 3.2000000e+00 2.9000000e+00 2.6000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.5000000e+00 1.8000000e+00 2.7000000e+00 2.7000000e+00 2.7000000e+00 2.8000000e+00 1.6000000e+00 2.6000000e+00 4.5000000e+00 3.6000000e+00 4.4000000e+00 4.1000000e+00 4.3000000e+00 5.1000000e+00 3.0000000e+00 4.8000000e+00 4.3000000e+00 4.6000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 5.2000000e+00 5.4000000e+00 3.5000000e+00 4.2000000e+00 3.4000000e+00 5.2000000e+00 3.4000000e+00 4.2000000e+00 4.5000000e+00 3.3000000e+00 3.4000000e+00 4.1000000e+00 4.3000000e+00 4.6000000e+00 4.9000000e+00 4.1000000e+00 3.6000000e+00 4.1000000e+00 4.6000000e+00 4.1000000e+00 4.0000000e+00 3.3000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.6000000e+00 4.4000000e+00 4.2000000e+00 3.7000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.6000000e+00 1.1000000e+00 1.0000000e+00 7.0000000e-01 1.1000000e+00 1.2000000e+00 8.0000000e-01 7.0000000e-01 1.9000000e+00 1.1000000e+00 7.0000000e-01 5.0000000e-01 1.2000000e+00 4.0000000e-01 1.0000000e+00 5.0000000e-01 9.0000000e-01 3.3000000e+00 3.1000000e+00 3.5000000e+00 2.6000000e+00 3.2000000e+00 3.1000000e+00 3.3000000e+00 1.9000000e+00 3.2000000e+00 2.5000000e+00 2.2000000e+00 2.8000000e+00 2.6000000e+00 3.3000000e+00 2.2000000e+00 3.0000000e+00 3.1000000e+00 2.7000000e+00 3.1000000e+00 2.5000000e+00 3.4000000e+00 2.6000000e+00 3.5000000e+00 3.3000000e+00 2.9000000e+00 3.0000000e+00 3.4000000e+00 3.6000000e+00 3.1000000e+00 2.1000000e+00 2.4000000e+00 2.3000000e+00 2.5000000e+00 3.7000000e+00 3.1000000e+00 3.1000000e+00 3.3000000e+00 3.0000000e+00 2.7000000e+00 2.6000000e+00 3.0000000e+00 3.2000000e+00 2.6000000e+00 1.9000000e+00 2.8000000e+00 2.8000000e+00 2.8000000e+00 2.9000000e+00 1.7000000e+00 2.7000000e+00 4.6000000e+00 3.7000000e+00 4.5000000e+00 4.2000000e+00 4.4000000e+00 5.2000000e+00 3.1000000e+00 4.9000000e+00 4.4000000e+00 4.7000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 5.3000000e+00 5.5000000e+00 3.6000000e+00 4.3000000e+00 3.5000000e+00 5.3000000e+00 3.5000000e+00 4.3000000e+00 4.6000000e+00 3.4000000e+00 3.5000000e+00 4.2000000e+00 4.4000000e+00 4.7000000e+00 5.0000000e+00 4.2000000e+00 3.7000000e+00 4.2000000e+00 4.7000000e+00 4.2000000e+00 4.1000000e+00 3.4000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.7000000e+00 4.5000000e+00 4.3000000e+00 3.8000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.7000000e+00 3.0000000e-01 6.0000000e-01 0.0000000e+00 5.0000000e-01 3.0000000e-01 4.0000000e-01 8.0000000e-01 5.0000000e-01 5.0000000e-01 7.0000000e-01 2.0000000e-01 7.0000000e-01 3.0000000e-01 6.0000000e-01 2.0000000e-01 3.2000000e+00 3.0000000e+00 3.4000000e+00 2.5000000e+00 3.1000000e+00 3.0000000e+00 3.2000000e+00 1.8000000e+00 3.1000000e+00 2.4000000e+00 2.0000000e+00 2.7000000e+00 2.5000000e+00 3.2000000e+00 2.1000000e+00 2.9000000e+00 3.0000000e+00 2.6000000e+00 3.0000000e+00 2.4000000e+00 3.3000000e+00 2.5000000e+00 3.4000000e+00 3.2000000e+00 2.8000000e+00 2.9000000e+00 3.3000000e+00 3.5000000e+00 3.0000000e+00 2.0000000e+00 2.3000000e+00 2.2000000e+00 2.4000000e+00 3.6000000e+00 3.0000000e+00 3.0000000e+00 3.2000000e+00 2.9000000e+00 2.6000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.5000000e+00 1.8000000e+00 2.7000000e+00 2.7000000e+00 2.7000000e+00 2.8000000e+00 1.5000000e+00 2.6000000e+00 4.5000000e+00 3.6000000e+00 4.4000000e+00 4.1000000e+00 4.3000000e+00 5.1000000e+00 3.0000000e+00 4.8000000e+00 4.3000000e+00 4.6000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 5.2000000e+00 5.4000000e+00 3.5000000e+00 4.2000000e+00 3.4000000e+00 5.2000000e+00 3.4000000e+00 4.2000000e+00 4.5000000e+00 3.3000000e+00 3.4000000e+00 4.1000000e+00 4.3000000e+00 4.6000000e+00 4.9000000e+00 4.1000000e+00 3.6000000e+00 4.1000000e+00 4.6000000e+00 4.1000000e+00 4.0000000e+00 3.3000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.6000000e+00 4.4000000e+00 4.2000000e+00 3.7000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.6000000e+00 5.0000000e-01 3.0000000e-01 6.0000000e-01 3.0000000e-01 3.0000000e-01 9.0000000e-01 6.0000000e-01 4.0000000e-01 7.0000000e-01 2.0000000e-01 6.0000000e-01 4.0000000e-01 5.0000000e-01 2.0000000e-01 3.5000000e+00 3.3000000e+00 3.7000000e+00 2.8000000e+00 3.4000000e+00 3.3000000e+00 3.5000000e+00 2.1000000e+00 3.4000000e+00 2.7000000e+00 2.3000000e+00 3.0000000e+00 2.8000000e+00 3.5000000e+00 2.4000000e+00 3.2000000e+00 3.3000000e+00 2.9000000e+00 3.3000000e+00 2.7000000e+00 3.6000000e+00 2.8000000e+00 3.7000000e+00 3.5000000e+00 3.1000000e+00 3.2000000e+00 3.6000000e+00 3.8000000e+00 3.3000000e+00 2.3000000e+00 2.6000000e+00 2.5000000e+00 2.7000000e+00 3.9000000e+00 3.3000000e+00 3.3000000e+00 3.5000000e+00 3.2000000e+00 2.9000000e+00 2.8000000e+00 3.2000000e+00 3.4000000e+00 2.8000000e+00 2.1000000e+00 3.0000000e+00 3.0000000e+00 3.0000000e+00 3.1000000e+00 1.8000000e+00 2.9000000e+00 4.8000000e+00 3.9000000e+00 4.7000000e+00 4.4000000e+00 4.6000000e+00 5.4000000e+00 3.3000000e+00 5.1000000e+00 4.6000000e+00 4.9000000e+00 3.9000000e+00 4.1000000e+00 4.3000000e+00 3.8000000e+00 3.9000000e+00 4.1000000e+00 4.3000000e+00 5.5000000e+00 5.7000000e+00 3.8000000e+00 4.5000000e+00 3.7000000e+00 5.5000000e+00 3.7000000e+00 4.5000000e+00 4.8000000e+00 3.6000000e+00 3.7000000e+00 4.4000000e+00 4.6000000e+00 4.9000000e+00 5.2000000e+00 4.4000000e+00 3.9000000e+00 4.4000000e+00 4.9000000e+00 4.4000000e+00 4.3000000e+00 3.6000000e+00 4.2000000e+00 4.4000000e+00 3.9000000e+00 3.9000000e+00 4.7000000e+00 4.5000000e+00 4.0000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 3.9000000e+00 6.0000000e-01 1.1000000e+00 4.0000000e-01 5.0000000e-01 1.2000000e+00 1.1000000e+00 5.0000000e-01 6.0000000e-01 7.0000000e-01 4.0000000e-01 9.0000000e-01 2.0000000e-01 5.0000000e-01 3.4000000e+00 3.2000000e+00 3.6000000e+00 2.7000000e+00 3.3000000e+00 3.2000000e+00 3.4000000e+00 2.0000000e+00 3.3000000e+00 2.6000000e+00 2.2000000e+00 2.9000000e+00 2.7000000e+00 3.4000000e+00 2.3000000e+00 3.1000000e+00 3.2000000e+00 2.8000000e+00 3.2000000e+00 2.6000000e+00 3.5000000e+00 2.7000000e+00 3.6000000e+00 3.4000000e+00 3.0000000e+00 3.1000000e+00 3.5000000e+00 3.7000000e+00 3.2000000e+00 2.2000000e+00 2.5000000e+00 2.4000000e+00 2.6000000e+00 3.8000000e+00 3.2000000e+00 3.2000000e+00 3.4000000e+00 3.1000000e+00 2.8000000e+00 2.7000000e+00 3.1000000e+00 3.3000000e+00 2.7000000e+00 2.0000000e+00 2.9000000e+00 2.9000000e+00 2.9000000e+00 3.0000000e+00 1.7000000e+00 2.8000000e+00 4.7000000e+00 3.8000000e+00 4.6000000e+00 4.3000000e+00 4.5000000e+00 5.3000000e+00 3.2000000e+00 5.0000000e+00 4.5000000e+00 4.8000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 5.4000000e+00 5.6000000e+00 3.7000000e+00 4.4000000e+00 3.6000000e+00 5.4000000e+00 3.6000000e+00 4.4000000e+00 4.7000000e+00 3.5000000e+00 3.6000000e+00 4.3000000e+00 4.5000000e+00 4.8000000e+00 5.1000000e+00 4.3000000e+00 3.8000000e+00 4.3000000e+00 4.8000000e+00 4.3000000e+00 4.2000000e+00 3.5000000e+00 4.1000000e+00 4.3000000e+00 3.8000000e+00 3.8000000e+00 4.6000000e+00 4.4000000e+00 3.9000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.8000000e+00 5.0000000e-01 3.0000000e-01 4.0000000e-01 8.0000000e-01 5.0000000e-01 5.0000000e-01 7.0000000e-01 2.0000000e-01 7.0000000e-01 3.0000000e-01 6.0000000e-01 2.0000000e-01 3.2000000e+00 3.0000000e+00 3.4000000e+00 2.5000000e+00 3.1000000e+00 3.0000000e+00 3.2000000e+00 1.8000000e+00 3.1000000e+00 2.4000000e+00 2.0000000e+00 2.7000000e+00 2.5000000e+00 3.2000000e+00 2.1000000e+00 2.9000000e+00 3.0000000e+00 2.6000000e+00 3.0000000e+00 2.4000000e+00 3.3000000e+00 2.5000000e+00 3.4000000e+00 3.2000000e+00 2.8000000e+00 2.9000000e+00 3.3000000e+00 3.5000000e+00 3.0000000e+00 2.0000000e+00 2.3000000e+00 2.2000000e+00 2.4000000e+00 3.6000000e+00 3.0000000e+00 3.0000000e+00 3.2000000e+00 2.9000000e+00 2.6000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.5000000e+00 1.8000000e+00 2.7000000e+00 2.7000000e+00 2.7000000e+00 2.8000000e+00 1.5000000e+00 2.6000000e+00 4.5000000e+00 3.6000000e+00 4.4000000e+00 4.1000000e+00 4.3000000e+00 5.1000000e+00 3.0000000e+00 4.8000000e+00 4.3000000e+00 4.6000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 5.2000000e+00 5.4000000e+00 3.5000000e+00 4.2000000e+00 3.4000000e+00 5.2000000e+00 3.4000000e+00 4.2000000e+00 4.5000000e+00 3.3000000e+00 3.4000000e+00 4.1000000e+00 4.3000000e+00 4.6000000e+00 4.9000000e+00 4.1000000e+00 3.6000000e+00 4.1000000e+00 4.6000000e+00 4.1000000e+00 4.0000000e+00 3.3000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.6000000e+00 4.4000000e+00 4.2000000e+00 3.7000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.6000000e+00 7.0000000e-01 6.0000000e-01 7.0000000e-01 2.0000000e-01 6.0000000e-01 8.0000000e-01 4.0000000e-01 8.0000000e-01 2.0000000e-01 9.0000000e-01 6.0000000e-01 3.4000000e+00 3.2000000e+00 3.6000000e+00 2.7000000e+00 3.3000000e+00 3.2000000e+00 3.4000000e+00 2.0000000e+00 3.3000000e+00 2.6000000e+00 2.2000000e+00 2.9000000e+00 2.7000000e+00 3.4000000e+00 2.3000000e+00 3.1000000e+00 3.2000000e+00 2.8000000e+00 3.2000000e+00 2.6000000e+00 3.5000000e+00 2.7000000e+00 3.6000000e+00 3.4000000e+00 3.0000000e+00 3.1000000e+00 3.5000000e+00 3.7000000e+00 3.2000000e+00 2.2000000e+00 2.5000000e+00 2.4000000e+00 2.6000000e+00 3.8000000e+00 3.2000000e+00 3.2000000e+00 3.4000000e+00 3.1000000e+00 2.8000000e+00 2.7000000e+00 3.1000000e+00 3.3000000e+00 2.7000000e+00 2.0000000e+00 2.9000000e+00 2.9000000e+00 2.9000000e+00 3.0000000e+00 1.7000000e+00 2.8000000e+00 4.7000000e+00 3.8000000e+00 4.6000000e+00 4.3000000e+00 4.5000000e+00 5.3000000e+00 3.2000000e+00 5.0000000e+00 4.5000000e+00 4.8000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 5.4000000e+00 5.6000000e+00 3.7000000e+00 4.4000000e+00 3.6000000e+00 5.4000000e+00 3.6000000e+00 4.4000000e+00 4.7000000e+00 3.5000000e+00 3.6000000e+00 4.3000000e+00 4.5000000e+00 4.8000000e+00 5.1000000e+00 4.3000000e+00 3.8000000e+00 4.3000000e+00 4.8000000e+00 4.3000000e+00 4.2000000e+00 3.5000000e+00 4.1000000e+00 4.3000000e+00 3.8000000e+00 3.8000000e+00 4.6000000e+00 4.4000000e+00 3.9000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.8000000e+00 2.0000000e-01 1.1000000e+00 7.0000000e-01 4.0000000e-01 4.0000000e-01 4.0000000e-01 4.0000000e-01 5.0000000e-01 3.0000000e-01 1.0000000e-01 3.2000000e+00 3.0000000e+00 3.4000000e+00 2.5000000e+00 3.1000000e+00 3.0000000e+00 3.2000000e+00 1.8000000e+00 3.1000000e+00 2.4000000e+00 2.0000000e+00 2.7000000e+00 2.5000000e+00 3.2000000e+00 2.1000000e+00 2.9000000e+00 3.0000000e+00 2.6000000e+00 3.0000000e+00 2.4000000e+00 3.3000000e+00 2.5000000e+00 3.4000000e+00 3.2000000e+00 2.8000000e+00 2.9000000e+00 3.3000000e+00 3.5000000e+00 3.0000000e+00 2.0000000e+00 2.3000000e+00 2.2000000e+00 2.4000000e+00 3.6000000e+00 3.0000000e+00 3.0000000e+00 3.2000000e+00 2.9000000e+00 2.6000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.5000000e+00 1.8000000e+00 2.7000000e+00 2.7000000e+00 2.7000000e+00 2.8000000e+00 1.5000000e+00 2.6000000e+00 4.5000000e+00 3.6000000e+00 4.4000000e+00 4.1000000e+00 4.3000000e+00 5.1000000e+00 3.0000000e+00 4.8000000e+00 4.3000000e+00 4.6000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 5.2000000e+00 5.4000000e+00 3.5000000e+00 4.2000000e+00 3.4000000e+00 5.2000000e+00 3.4000000e+00 4.2000000e+00 4.5000000e+00 3.3000000e+00 3.4000000e+00 4.1000000e+00 4.3000000e+00 4.6000000e+00 4.9000000e+00 4.1000000e+00 3.6000000e+00 4.1000000e+00 4.6000000e+00 4.1000000e+00 4.0000000e+00 3.3000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.6000000e+00 4.4000000e+00 4.2000000e+00 3.7000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.6000000e+00 1.2000000e+00 6.0000000e-01 3.0000000e-01 6.0000000e-01 5.0000000e-01 3.0000000e-01 4.0000000e-01 3.0000000e-01 2.0000000e-01 3.4000000e+00 3.2000000e+00 3.6000000e+00 2.7000000e+00 3.3000000e+00 3.2000000e+00 3.4000000e+00 2.0000000e+00 3.3000000e+00 2.6000000e+00 2.2000000e+00 2.9000000e+00 2.7000000e+00 3.4000000e+00 2.3000000e+00 3.1000000e+00 3.2000000e+00 2.8000000e+00 3.2000000e+00 2.6000000e+00 3.5000000e+00 2.7000000e+00 3.6000000e+00 3.4000000e+00 3.0000000e+00 3.1000000e+00 3.5000000e+00 3.7000000e+00 3.2000000e+00 2.2000000e+00 2.5000000e+00 2.4000000e+00 2.6000000e+00 3.8000000e+00 3.2000000e+00 3.2000000e+00 3.4000000e+00 3.1000000e+00 2.8000000e+00 2.7000000e+00 3.1000000e+00 3.3000000e+00 2.7000000e+00 2.0000000e+00 2.9000000e+00 2.9000000e+00 2.9000000e+00 3.0000000e+00 1.7000000e+00 2.8000000e+00 4.7000000e+00 3.8000000e+00 4.6000000e+00 4.3000000e+00 4.5000000e+00 5.3000000e+00 3.2000000e+00 5.0000000e+00 4.5000000e+00 4.8000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 5.4000000e+00 5.6000000e+00 3.7000000e+00 4.4000000e+00 3.6000000e+00 5.4000000e+00 3.6000000e+00 4.4000000e+00 4.7000000e+00 3.5000000e+00 3.6000000e+00 4.3000000e+00 4.5000000e+00 4.8000000e+00 5.1000000e+00 4.3000000e+00 3.8000000e+00 4.3000000e+00 4.8000000e+00 4.3000000e+00 4.2000000e+00 3.5000000e+00 4.1000000e+00 4.3000000e+00 3.8000000e+00 3.8000000e+00 4.6000000e+00 4.4000000e+00 3.9000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.8000000e+00 9.0000000e-01 1.2000000e+00 1.5000000e+00 7.0000000e-01 1.5000000e+00 9.0000000e-01 1.4000000e+00 1.0000000e+00 3.4000000e+00 3.2000000e+00 3.6000000e+00 2.7000000e+00 3.3000000e+00 3.2000000e+00 3.4000000e+00 2.0000000e+00 3.3000000e+00 2.6000000e+00 2.2000000e+00 2.9000000e+00 2.7000000e+00 3.4000000e+00 2.3000000e+00 3.1000000e+00 3.2000000e+00 2.8000000e+00 3.2000000e+00 2.6000000e+00 3.5000000e+00 2.7000000e+00 3.6000000e+00 3.4000000e+00 3.0000000e+00 3.1000000e+00 3.5000000e+00 3.7000000e+00 3.2000000e+00 2.2000000e+00 2.5000000e+00 2.4000000e+00 2.6000000e+00 3.8000000e+00 3.2000000e+00 3.2000000e+00 3.4000000e+00 3.1000000e+00 2.8000000e+00 2.7000000e+00 3.1000000e+00 3.3000000e+00 2.7000000e+00 2.0000000e+00 2.9000000e+00 2.9000000e+00 2.9000000e+00 3.0000000e+00 1.7000000e+00 2.8000000e+00 4.7000000e+00 3.8000000e+00 4.6000000e+00 4.3000000e+00 4.5000000e+00 5.3000000e+00 3.2000000e+00 5.0000000e+00 4.5000000e+00 4.8000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 5.4000000e+00 5.6000000e+00 3.7000000e+00 4.4000000e+00 3.6000000e+00 5.4000000e+00 3.6000000e+00 4.4000000e+00 4.7000000e+00 3.5000000e+00 3.6000000e+00 4.3000000e+00 4.5000000e+00 4.8000000e+00 5.1000000e+00 4.3000000e+00 3.8000000e+00 4.3000000e+00 4.8000000e+00 4.3000000e+00 4.2000000e+00 3.5000000e+00 4.1000000e+00 4.3000000e+00 3.8000000e+00 3.8000000e+00 4.6000000e+00 4.4000000e+00 3.9000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.8000000e+00 6.0000000e-01 7.0000000e-01 4.0000000e-01 7.0000000e-01 2.0000000e-01 9.0000000e-01 6.0000000e-01 3.4000000e+00 3.2000000e+00 3.6000000e+00 2.7000000e+00 3.3000000e+00 3.2000000e+00 3.4000000e+00 2.0000000e+00 3.3000000e+00 2.6000000e+00 2.2000000e+00 2.9000000e+00 2.7000000e+00 3.4000000e+00 2.3000000e+00 3.1000000e+00 3.2000000e+00 2.8000000e+00 3.2000000e+00 2.6000000e+00 3.5000000e+00 2.7000000e+00 3.6000000e+00 3.4000000e+00 3.0000000e+00 3.1000000e+00 3.5000000e+00 3.7000000e+00 3.2000000e+00 2.2000000e+00 2.5000000e+00 2.4000000e+00 2.6000000e+00 3.8000000e+00 3.2000000e+00 3.2000000e+00 3.4000000e+00 3.1000000e+00 2.8000000e+00 2.7000000e+00 3.1000000e+00 3.3000000e+00 2.7000000e+00 2.0000000e+00 2.9000000e+00 2.9000000e+00 2.9000000e+00 3.0000000e+00 1.7000000e+00 2.8000000e+00 4.7000000e+00 3.8000000e+00 4.6000000e+00 4.3000000e+00 4.5000000e+00 5.3000000e+00 3.2000000e+00 5.0000000e+00 4.5000000e+00 4.8000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.8000000e+00 4.0000000e+00 4.2000000e+00 5.4000000e+00 5.6000000e+00 3.7000000e+00 4.4000000e+00 3.6000000e+00 5.4000000e+00 3.6000000e+00 4.4000000e+00 4.7000000e+00 3.5000000e+00 3.6000000e+00 4.3000000e+00 4.5000000e+00 4.8000000e+00 5.1000000e+00 4.3000000e+00 3.8000000e+00 4.3000000e+00 4.8000000e+00 4.3000000e+00 4.2000000e+00 3.5000000e+00 4.1000000e+00 4.3000000e+00 3.8000000e+00 3.8000000e+00 4.6000000e+00 4.4000000e+00 3.9000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.8000000e+00 3.0000000e-01 5.0000000e-01 4.0000000e-01 4.0000000e-01 4.0000000e-01 4.0000000e-01 3.1000000e+00 2.9000000e+00 3.3000000e+00 2.4000000e+00 3.0000000e+00 2.9000000e+00 3.1000000e+00 1.7000000e+00 3.0000000e+00 2.3000000e+00 1.9000000e+00 2.6000000e+00 2.4000000e+00 3.1000000e+00 2.0000000e+00 2.8000000e+00 2.9000000e+00 2.5000000e+00 2.9000000e+00 2.3000000e+00 3.2000000e+00 2.4000000e+00 3.3000000e+00 3.1000000e+00 2.7000000e+00 2.8000000e+00 3.2000000e+00 3.4000000e+00 2.9000000e+00 1.9000000e+00 2.2000000e+00 2.1000000e+00 2.3000000e+00 3.5000000e+00 2.9000000e+00 2.9000000e+00 3.1000000e+00 2.8000000e+00 2.5000000e+00 2.4000000e+00 2.8000000e+00 3.0000000e+00 2.4000000e+00 1.7000000e+00 2.6000000e+00 2.6000000e+00 2.6000000e+00 2.7000000e+00 1.4000000e+00 2.5000000e+00 4.4000000e+00 3.5000000e+00 4.3000000e+00 4.0000000e+00 4.2000000e+00 5.0000000e+00 2.9000000e+00 4.7000000e+00 4.2000000e+00 4.5000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.4000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 5.1000000e+00 5.3000000e+00 3.4000000e+00 4.1000000e+00 3.3000000e+00 5.1000000e+00 3.3000000e+00 4.1000000e+00 4.4000000e+00 3.2000000e+00 3.3000000e+00 4.0000000e+00 4.2000000e+00 4.5000000e+00 4.8000000e+00 4.0000000e+00 3.5000000e+00 4.0000000e+00 4.5000000e+00 4.0000000e+00 3.9000000e+00 3.2000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.5000000e+00 4.3000000e+00 4.1000000e+00 3.6000000e+00 3.4000000e+00 3.6000000e+00 3.8000000e+00 3.5000000e+00 8.0000000e-01 3.0000000e-01 6.0000000e-01 4.0000000e-01 5.0000000e-01 2.8000000e+00 2.6000000e+00 3.0000000e+00 2.1000000e+00 2.7000000e+00 2.6000000e+00 2.8000000e+00 1.4000000e+00 2.7000000e+00 2.0000000e+00 1.8000000e+00 2.3000000e+00 2.1000000e+00 2.8000000e+00 1.7000000e+00 2.5000000e+00 2.6000000e+00 2.2000000e+00 2.6000000e+00 2.0000000e+00 2.9000000e+00 2.1000000e+00 3.0000000e+00 2.8000000e+00 2.4000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.6000000e+00 1.6000000e+00 1.9000000e+00 1.8000000e+00 2.0000000e+00 3.2000000e+00 2.6000000e+00 2.6000000e+00 2.8000000e+00 2.5000000e+00 2.2000000e+00 2.1000000e+00 2.5000000e+00 2.7000000e+00 2.1000000e+00 1.5000000e+00 2.3000000e+00 2.3000000e+00 2.3000000e+00 2.4000000e+00 1.3000000e+00 2.2000000e+00 4.1000000e+00 3.2000000e+00 4.0000000e+00 3.7000000e+00 3.9000000e+00 4.7000000e+00 2.6000000e+00 4.4000000e+00 3.9000000e+00 4.2000000e+00 3.2000000e+00 3.4000000e+00 3.6000000e+00 3.1000000e+00 3.2000000e+00 3.4000000e+00 3.6000000e+00 4.8000000e+00 5.0000000e+00 3.1000000e+00 3.8000000e+00 3.0000000e+00 4.8000000e+00 3.0000000e+00 3.8000000e+00 4.1000000e+00 2.9000000e+00 3.0000000e+00 3.7000000e+00 3.9000000e+00 4.2000000e+00 4.5000000e+00 3.7000000e+00 3.2000000e+00 3.7000000e+00 4.2000000e+00 3.7000000e+00 3.6000000e+00 2.9000000e+00 3.5000000e+00 3.7000000e+00 3.2000000e+00 3.2000000e+00 4.0000000e+00 3.8000000e+00 3.3000000e+00 3.1000000e+00 3.3000000e+00 3.5000000e+00 3.2000000e+00 8.0000000e-01 2.0000000e-01 7.0000000e-01 3.0000000e-01 3.3000000e+00 3.1000000e+00 3.5000000e+00 2.6000000e+00 3.2000000e+00 3.1000000e+00 3.3000000e+00 1.9000000e+00 3.2000000e+00 2.5000000e+00 2.1000000e+00 2.8000000e+00 2.6000000e+00 3.3000000e+00 2.2000000e+00 3.0000000e+00 3.1000000e+00 2.7000000e+00 3.1000000e+00 2.5000000e+00 3.4000000e+00 2.6000000e+00 3.5000000e+00 3.3000000e+00 2.9000000e+00 3.0000000e+00 3.4000000e+00 3.6000000e+00 3.1000000e+00 2.1000000e+00 2.4000000e+00 2.3000000e+00 2.5000000e+00 3.7000000e+00 3.1000000e+00 3.1000000e+00 3.3000000e+00 3.0000000e+00 2.7000000e+00 2.6000000e+00 3.0000000e+00 3.2000000e+00 2.6000000e+00 1.9000000e+00 2.8000000e+00 2.8000000e+00 2.8000000e+00 2.9000000e+00 1.6000000e+00 2.7000000e+00 4.6000000e+00 3.7000000e+00 4.5000000e+00 4.2000000e+00 4.4000000e+00 5.2000000e+00 3.1000000e+00 4.9000000e+00 4.4000000e+00 4.7000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 5.3000000e+00 5.5000000e+00 3.6000000e+00 4.3000000e+00 3.5000000e+00 5.3000000e+00 3.5000000e+00 4.3000000e+00 4.6000000e+00 3.4000000e+00 3.5000000e+00 4.2000000e+00 4.4000000e+00 4.7000000e+00 5.0000000e+00 4.2000000e+00 3.7000000e+00 4.2000000e+00 4.7000000e+00 4.2000000e+00 4.1000000e+00 3.4000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.7000000e+00 4.5000000e+00 4.3000000e+00 3.8000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.7000000e+00 6.0000000e-01 2.0000000e-01 5.0000000e-01 3.1000000e+00 2.9000000e+00 3.3000000e+00 2.4000000e+00 3.0000000e+00 2.9000000e+00 3.1000000e+00 1.7000000e+00 3.0000000e+00 2.3000000e+00 1.9000000e+00 2.6000000e+00 2.4000000e+00 3.1000000e+00 2.0000000e+00 2.8000000e+00 2.9000000e+00 2.5000000e+00 2.9000000e+00 2.3000000e+00 3.2000000e+00 2.4000000e+00 3.3000000e+00 3.1000000e+00 2.7000000e+00 2.8000000e+00 3.2000000e+00 3.4000000e+00 2.9000000e+00 1.9000000e+00 2.2000000e+00 2.1000000e+00 2.3000000e+00 3.5000000e+00 2.9000000e+00 2.9000000e+00 3.1000000e+00 2.8000000e+00 2.5000000e+00 2.4000000e+00 2.8000000e+00 3.0000000e+00 2.4000000e+00 1.7000000e+00 2.6000000e+00 2.6000000e+00 2.6000000e+00 2.7000000e+00 1.4000000e+00 2.5000000e+00 4.4000000e+00 3.5000000e+00 4.3000000e+00 4.0000000e+00 4.2000000e+00 5.0000000e+00 2.9000000e+00 4.7000000e+00 4.2000000e+00 4.5000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.4000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 5.1000000e+00 5.3000000e+00 3.4000000e+00 4.1000000e+00 3.3000000e+00 5.1000000e+00 3.3000000e+00 4.1000000e+00 4.4000000e+00 3.2000000e+00 3.3000000e+00 4.0000000e+00 4.2000000e+00 4.5000000e+00 4.8000000e+00 4.0000000e+00 3.5000000e+00 4.0000000e+00 4.5000000e+00 4.0000000e+00 3.9000000e+00 3.2000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.5000000e+00 4.3000000e+00 4.1000000e+00 3.6000000e+00 3.4000000e+00 3.6000000e+00 3.8000000e+00 3.5000000e+00 7.0000000e-01 4.0000000e-01 3.3000000e+00 3.1000000e+00 3.5000000e+00 2.6000000e+00 3.2000000e+00 3.1000000e+00 3.3000000e+00 1.9000000e+00 3.2000000e+00 2.5000000e+00 2.1000000e+00 2.8000000e+00 2.6000000e+00 3.3000000e+00 2.2000000e+00 3.0000000e+00 3.1000000e+00 2.7000000e+00 3.1000000e+00 2.5000000e+00 3.4000000e+00 2.6000000e+00 3.5000000e+00 3.3000000e+00 2.9000000e+00 3.0000000e+00 3.4000000e+00 3.6000000e+00 3.1000000e+00 2.1000000e+00 2.4000000e+00 2.3000000e+00 2.5000000e+00 3.7000000e+00 3.1000000e+00 3.1000000e+00 3.3000000e+00 3.0000000e+00 2.7000000e+00 2.6000000e+00 3.0000000e+00 3.2000000e+00 2.6000000e+00 1.9000000e+00 2.8000000e+00 2.8000000e+00 2.8000000e+00 2.9000000e+00 1.6000000e+00 2.7000000e+00 4.6000000e+00 3.7000000e+00 4.5000000e+00 4.2000000e+00 4.4000000e+00 5.2000000e+00 3.1000000e+00 4.9000000e+00 4.4000000e+00 4.7000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 5.3000000e+00 5.5000000e+00 3.6000000e+00 4.3000000e+00 3.5000000e+00 5.3000000e+00 3.5000000e+00 4.3000000e+00 4.6000000e+00 3.4000000e+00 3.5000000e+00 4.2000000e+00 4.4000000e+00 4.7000000e+00 5.0000000e+00 4.2000000e+00 3.7000000e+00 4.2000000e+00 4.7000000e+00 4.2000000e+00 4.1000000e+00 3.4000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.7000000e+00 4.5000000e+00 4.3000000e+00 3.8000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.7000000e+00 4.0000000e-01 3.2000000e+00 3.0000000e+00 3.4000000e+00 2.5000000e+00 3.1000000e+00 3.0000000e+00 3.2000000e+00 1.8000000e+00 3.1000000e+00 2.4000000e+00 2.0000000e+00 2.7000000e+00 2.5000000e+00 3.2000000e+00 2.1000000e+00 2.9000000e+00 3.0000000e+00 2.6000000e+00 3.0000000e+00 2.4000000e+00 3.3000000e+00 2.5000000e+00 3.4000000e+00 3.2000000e+00 2.8000000e+00 2.9000000e+00 3.3000000e+00 3.5000000e+00 3.0000000e+00 2.0000000e+00 2.3000000e+00 2.2000000e+00 2.4000000e+00 3.6000000e+00 3.0000000e+00 3.0000000e+00 3.2000000e+00 2.9000000e+00 2.6000000e+00 2.5000000e+00 2.9000000e+00 3.1000000e+00 2.5000000e+00 1.8000000e+00 2.7000000e+00 2.7000000e+00 2.7000000e+00 2.8000000e+00 1.5000000e+00 2.6000000e+00 4.5000000e+00 3.6000000e+00 4.4000000e+00 4.1000000e+00 4.3000000e+00 5.1000000e+00 3.0000000e+00 4.8000000e+00 4.3000000e+00 4.6000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.5000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 5.2000000e+00 5.4000000e+00 3.5000000e+00 4.2000000e+00 3.4000000e+00 5.2000000e+00 3.4000000e+00 4.2000000e+00 4.5000000e+00 3.3000000e+00 3.4000000e+00 4.1000000e+00 4.3000000e+00 4.6000000e+00 4.9000000e+00 4.1000000e+00 3.6000000e+00 4.1000000e+00 4.6000000e+00 4.1000000e+00 4.0000000e+00 3.3000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.6000000e+00 4.4000000e+00 4.2000000e+00 3.7000000e+00 3.5000000e+00 3.7000000e+00 3.9000000e+00 3.6000000e+00 3.3000000e+00 3.1000000e+00 3.5000000e+00 2.6000000e+00 3.2000000e+00 3.1000000e+00 3.3000000e+00 1.9000000e+00 3.2000000e+00 2.5000000e+00 2.1000000e+00 2.8000000e+00 2.6000000e+00 3.3000000e+00 2.2000000e+00 3.0000000e+00 3.1000000e+00 2.7000000e+00 3.1000000e+00 2.5000000e+00 3.4000000e+00 2.6000000e+00 3.5000000e+00 3.3000000e+00 2.9000000e+00 3.0000000e+00 3.4000000e+00 3.6000000e+00 3.1000000e+00 2.1000000e+00 2.4000000e+00 2.3000000e+00 2.5000000e+00 3.7000000e+00 3.1000000e+00 3.1000000e+00 3.3000000e+00 3.0000000e+00 2.7000000e+00 2.6000000e+00 3.0000000e+00 3.2000000e+00 2.6000000e+00 1.9000000e+00 2.8000000e+00 2.8000000e+00 2.8000000e+00 2.9000000e+00 1.6000000e+00 2.7000000e+00 4.6000000e+00 3.7000000e+00 4.5000000e+00 4.2000000e+00 4.4000000e+00 5.2000000e+00 3.1000000e+00 4.9000000e+00 4.4000000e+00 4.7000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 3.6000000e+00 3.7000000e+00 3.9000000e+00 4.1000000e+00 5.3000000e+00 5.5000000e+00 3.6000000e+00 4.3000000e+00 3.5000000e+00 5.3000000e+00 3.5000000e+00 4.3000000e+00 4.6000000e+00 3.4000000e+00 3.5000000e+00 4.2000000e+00 4.4000000e+00 4.7000000e+00 5.0000000e+00 4.2000000e+00 3.7000000e+00 4.2000000e+00 4.7000000e+00 4.2000000e+00 4.1000000e+00 3.4000000e+00 4.0000000e+00 4.2000000e+00 3.7000000e+00 3.7000000e+00 4.5000000e+00 4.3000000e+00 3.8000000e+00 3.6000000e+00 3.8000000e+00 4.0000000e+00 3.7000000e+00 6.0000000e-01 2.0000000e-01 1.5000000e+00 5.0000000e-01 1.3000000e+00 7.0000000e-01 2.1000000e+00 4.0000000e-01 1.8000000e+00 2.0000000e+00 1.1000000e+00 1.0000000e+00 9.0000000e-01 1.4000000e+00 3.0000000e-01 1.4000000e+00 1.2000000e+00 1.0000000e+00 1.4000000e+00 1.1000000e+00 9.0000000e-01 7.0000000e-01 9.0000000e-01 6.0000000e-01 4.0000000e-01 4.0000000e-01 3.0000000e-01 1.0000000e+00 1.3000000e+00 1.5000000e+00 1.5000000e+00 1.2000000e+00 1.0000000e+00 1.6000000e+00 1.0000000e+00 3.0000000e-01 9.0000000e-01 1.4000000e+00 1.5000000e+00 1.5000000e+00 9.0000000e-01 1.2000000e+00 2.0000000e+00 1.4000000e+00 1.3000000e+00 1.3000000e+00 8.0000000e-01 1.9000000e+00 1.3000000e+00 1.3000000e+00 1.2000000e+00 1.2000000e+00 9.0000000e-01 1.1000000e+00 1.9000000e+00 2.1000000e+00 1.6000000e+00 1.1000000e+00 1.4000000e+00 6.0000000e-01 6.0000000e-01 8.0000000e-01 1.3000000e+00 1.2000000e+00 9.0000000e-01 8.0000000e-01 2.0000000e+00 2.2000000e+00 1.0000000e+00 1.0000000e+00 1.4000000e+00 2.0000000e+00 7.0000000e-01 1.0000000e+00 1.3000000e+00 8.0000000e-01 9.0000000e-01 9.0000000e-01 1.1000000e+00 1.4000000e+00 1.7000000e+00 9.0000000e-01 7.0000000e-01 9.0000000e-01 1.4000000e+00 1.0000000e+00 8.0000000e-01 1.0000000e+00 7.0000000e-01 1.0000000e+00 9.0000000e-01 1.2000000e+00 1.2000000e+00 1.1000000e+00 9.0000000e-01 7.0000000e-01 6.0000000e-01 9.0000000e-01 1.1000000e+00 5.0000000e-01 9.0000000e-01 4.0000000e-01 7.0000000e-01 2.0000000e-01 1.5000000e+00 3.0000000e-01 1.2000000e+00 1.4000000e+00 5.0000000e-01 1.0000000e+00 3.0000000e-01 9.0000000e-01 3.0000000e-01 8.0000000e-01 6.0000000e-01 1.0000000e+00 8.0000000e-01 5.0000000e-01 5.0000000e-01 7.0000000e-01 4.0000000e-01 3.0000000e-01 2.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 1.0000000e+00 9.0000000e-01 9.0000000e-01 6.0000000e-01 6.0000000e-01 1.0000000e+00 4.0000000e-01 3.0000000e-01 9.0000000e-01 8.0000000e-01 9.0000000e-01 9.0000000e-01 3.0000000e-01 6.0000000e-01 1.4000000e+00 8.0000000e-01 7.0000000e-01 7.0000000e-01 3.0000000e-01 1.5000000e+00 7.0000000e-01 1.5000000e+00 6.0000000e-01 1.4000000e+00 1.1000000e+00 1.3000000e+00 2.1000000e+00 1.5000000e+00 1.8000000e+00 1.3000000e+00 1.6000000e+00 6.0000000e-01 8.0000000e-01 1.0000000e+00 7.0000000e-01 9.0000000e-01 8.0000000e-01 1.0000000e+00 2.2000000e+00 2.4000000e+00 1.0000000e+00 1.2000000e+00 8.0000000e-01 2.2000000e+00 5.0000000e-01 1.2000000e+00 1.5000000e+00 4.0000000e-01 4.0000000e-01 1.1000000e+00 1.3000000e+00 1.6000000e+00 1.9000000e+00 1.1000000e+00 6.0000000e-01 1.1000000e+00 1.6000000e+00 1.1000000e+00 1.0000000e+00 4.0000000e-01 9.0000000e-01 1.1000000e+00 8.0000000e-01 6.0000000e-01 1.4000000e+00 1.2000000e+00 8.0000000e-01 7.0000000e-01 7.0000000e-01 9.0000000e-01 6.0000000e-01 1.4000000e+00 4.0000000e-01 1.2000000e+00 6.0000000e-01 2.0000000e+00 3.0000000e-01 1.7000000e+00 1.9000000e+00 1.0000000e+00 9.0000000e-01 8.0000000e-01 1.3000000e+00 5.0000000e-01 1.3000000e+00 1.1000000e+00 9.0000000e-01 1.3000000e+00 1.0000000e+00 9.0000000e-01 6.0000000e-01 8.0000000e-01 6.0000000e-01 5.0000000e-01 3.0000000e-01 2.0000000e-01 9.0000000e-01 1.4000000e+00 1.4000000e+00 1.4000000e+00 1.1000000e+00 9.0000000e-01 1.5000000e+00 9.0000000e-01 2.0000000e-01 8.0000000e-01 1.3000000e+00 1.4000000e+00 1.4000000e+00 8.0000000e-01 1.1000000e+00 1.9000000e+00 1.3000000e+00 1.2000000e+00 1.2000000e+00 7.0000000e-01 1.9000000e+00 1.2000000e+00 1.1000000e+00 1.1000000e+00 1.0000000e+00 7.0000000e-01 9.0000000e-01 1.7000000e+00 2.0000000e+00 1.4000000e+00 9.0000000e-01 1.2000000e+00 5.0000000e-01 5.0000000e-01 6.0000000e-01 1.2000000e+00 1.1000000e+00 8.0000000e-01 6.0000000e-01 1.8000000e+00 2.0000000e+00 9.0000000e-01 8.0000000e-01 1.3000000e+00 1.8000000e+00 6.0000000e-01 8.0000000e-01 1.1000000e+00 7.0000000e-01 8.0000000e-01 7.0000000e-01 9.0000000e-01 1.2000000e+00 1.5000000e+00 7.0000000e-01 6.0000000e-01 8.0000000e-01 1.2000000e+00 9.0000000e-01 6.0000000e-01 9.0000000e-01 6.0000000e-01 9.0000000e-01 8.0000000e-01 1.1000000e+00 1.0000000e+00 1.0000000e+00 8.0000000e-01 6.0000000e-01 5.0000000e-01 8.0000000e-01 1.0000000e+00 1.0000000e+00 5.0000000e-01 1.0000000e+00 7.0000000e-01 1.1000000e+00 4.0000000e-01 5.0000000e-01 7.0000000e-01 5.0000000e-01 7.0000000e-01 6.0000000e-01 1.2000000e+00 7.0000000e-01 4.0000000e-01 7.0000000e-01 2.0000000e-01 9.0000000e-01 6.0000000e-01 9.0000000e-01 7.0000000e-01 9.0000000e-01 1.1000000e+00 1.3000000e+00 1.2000000e+00 6.0000000e-01 5.0000000e-01 2.0000000e-01 3.0000000e-01 4.0000000e-01 1.1000000e+00 7.0000000e-01 1.1000000e+00 1.2000000e+00 8.0000000e-01 7.0000000e-01 2.0000000e-01 4.0000000e-01 7.0000000e-01 3.0000000e-01 7.0000000e-01 4.0000000e-01 7.0000000e-01 6.0000000e-01 7.0000000e-01 1.0000000e+00 5.0000000e-01 2.0000000e+00 1.1000000e+00 1.9000000e+00 1.6000000e+00 1.8000000e+00 2.6000000e+00 6.0000000e-01 2.3000000e+00 1.8000000e+00 2.1000000e+00 1.1000000e+00 1.3000000e+00 1.5000000e+00 1.0000000e+00 1.1000000e+00 1.3000000e+00 1.5000000e+00 2.7000000e+00 2.9000000e+00 1.0000000e+00 1.7000000e+00 9.0000000e-01 2.7000000e+00 9.0000000e-01 1.7000000e+00 2.0000000e+00 8.0000000e-01 9.0000000e-01 1.6000000e+00 1.8000000e+00 2.1000000e+00 2.4000000e+00 1.6000000e+00 1.1000000e+00 1.6000000e+00 2.2000000e+00 1.6000000e+00 1.5000000e+00 8.0000000e-01 1.4000000e+00 1.6000000e+00 1.4000000e+00 1.1000000e+00 1.9000000e+00 1.7000000e+00 1.2000000e+00 1.0000000e+00 1.2000000e+00 1.4000000e+00 1.1000000e+00 8.0000000e-01 5.0000000e-01 1.6000000e+00 2.0000000e-01 1.3000000e+00 1.5000000e+00 6.0000000e-01 6.0000000e-01 4.0000000e-01 1.0000000e+00 3.0000000e-01 9.0000000e-01 7.0000000e-01 6.0000000e-01 9.0000000e-01 6.0000000e-01 6.0000000e-01 3.0000000e-01 4.0000000e-01 3.0000000e-01 2.0000000e-01 3.0000000e-01 4.0000000e-01 5.0000000e-01 1.1000000e+00 1.0000000e+00 1.0000000e+00 7.0000000e-01 5.0000000e-01 1.1000000e+00 6.0000000e-01 3.0000000e-01 5.0000000e-01 9.0000000e-01 1.0000000e+00 1.0000000e+00 4.0000000e-01 7.0000000e-01 1.5000000e+00 9.0000000e-01 8.0000000e-01 8.0000000e-01 3.0000000e-01 1.6000000e+00 8.0000000e-01 1.4000000e+00 7.0000000e-01 1.3000000e+00 1.0000000e+00 1.2000000e+00 2.0000000e+00 1.6000000e+00 1.7000000e+00 1.2000000e+00 1.5000000e+00 5.0000000e-01 7.0000000e-01 9.0000000e-01 8.0000000e-01 9.0000000e-01 8.0000000e-01 9.0000000e-01 2.1000000e+00 2.3000000e+00 6.0000000e-01 1.1000000e+00 9.0000000e-01 2.1000000e+00 3.0000000e-01 1.1000000e+00 1.4000000e+00 3.0000000e-01 4.0000000e-01 1.0000000e+00 1.2000000e+00 1.5000000e+00 1.8000000e+00 1.0000000e+00 5.0000000e-01 1.0000000e+00 1.5000000e+00 1.0000000e+00 9.0000000e-01 5.0000000e-01 8.0000000e-01 1.0000000e+00 8.0000000e-01 7.0000000e-01 1.3000000e+00 1.1000000e+00 8.0000000e-01 4.0000000e-01 6.0000000e-01 8.0000000e-01 6.0000000e-01 6.0000000e-01 1.2000000e+00 9.0000000e-01 6.0000000e-01 1.0000000e+00 3.0000000e-01 6.0000000e-01 4.0000000e-01 9.0000000e-01 1.0000000e+00 2.0000000e-01 4.0000000e-01 6.0000000e-01 6.0000000e-01 5.0000000e-01 5.0000000e-01 6.0000000e-01 4.0000000e-01 7.0000000e-01 9.0000000e-01 1.1000000e+00 1.0000000e+00 3.0000000e-01 1.0000000e+00 7.0000000e-01 8.0000000e-01 6.0000000e-01 6.0000000e-01 3.0000000e-01 6.0000000e-01 1.0000000e+00 6.0000000e-01 4.0000000e-01 5.0000000e-01 2.0000000e-01 4.0000000e-01 5.0000000e-01 1.2000000e+00 3.0000000e-01 3.0000000e-01 3.0000000e-01 5.0000000e-01 1.5000000e+00 4.0000000e-01 1.5000000e+00 6.0000000e-01 1.4000000e+00 1.1000000e+00 1.3000000e+00 2.1000000e+00 8.0000000e-01 1.8000000e+00 1.3000000e+00 1.6000000e+00 8.0000000e-01 8.0000000e-01 1.1000000e+00 7.0000000e-01 1.1000000e+00 1.0000000e+00 1.0000000e+00 2.2000000e+00 2.4000000e+00 6.0000000e-01 1.2000000e+00 7.0000000e-01 2.2000000e+00 6.0000000e-01 1.2000000e+00 1.5000000e+00 5.0000000e-01 5.0000000e-01 1.1000000e+00 1.5000000e+00 1.7000000e+00 2.2000000e+00 1.1000000e+00 6.0000000e-01 1.1000000e+00 2.0000000e+00 1.1000000e+00 1.0000000e+00 5.0000000e-01 1.2000000e+00 1.1000000e+00 1.2000000e+00 6.0000000e-01 1.4000000e+00 1.2000000e+00 1.0000000e+00 6.0000000e-01 8.0000000e-01 1.0000000e+00 6.0000000e-01 1.4000000e+00 4.0000000e-01 1.1000000e+00 1.3000000e+00 5.0000000e-01 1.1000000e+00 4.0000000e-01 1.1000000e+00 4.0000000e-01 7.0000000e-01 6.0000000e-01 1.1000000e+00 8.0000000e-01 4.0000000e-01 7.0000000e-01 8.0000000e-01 5.0000000e-01 4.0000000e-01 3.0000000e-01 5.0000000e-01 4.0000000e-01 4.0000000e-01 1.2000000e+00 9.0000000e-01 1.0000000e+00 8.0000000e-01 6.0000000e-01 9.0000000e-01 3.0000000e-01 4.0000000e-01 1.0000000e+00 7.0000000e-01 8.0000000e-01 8.0000000e-01 3.0000000e-01 7.0000000e-01 1.4000000e+00 7.0000000e-01 6.0000000e-01 6.0000000e-01 4.0000000e-01 1.7000000e+00 6.0000000e-01 1.3000000e+00 6.0000000e-01 1.2000000e+00 9.0000000e-01 1.1000000e+00 1.9000000e+00 1.4000000e+00 1.6000000e+00 1.1000000e+00 1.4000000e+00 4.0000000e-01 6.0000000e-01 8.0000000e-01 8.0000000e-01 8.0000000e-01 7.0000000e-01 8.0000000e-01 2.0000000e+00 2.2000000e+00 1.1000000e+00 1.0000000e+00 7.0000000e-01 2.0000000e+00 6.0000000e-01 1.0000000e+00 1.3000000e+00 5.0000000e-01 3.0000000e-01 9.0000000e-01 1.1000000e+00 1.4000000e+00 1.7000000e+00 9.0000000e-01 5.0000000e-01 9.0000000e-01 1.4000000e+00 9.0000000e-01 8.0000000e-01 3.0000000e-01 7.0000000e-01 9.0000000e-01 7.0000000e-01 6.0000000e-01 1.2000000e+00 1.0000000e+00 7.0000000e-01 8.0000000e-01 5.0000000e-01 7.0000000e-01 4.0000000e-01 1.7000000e+00 6.0000000e-01 4.0000000e-01 1.0000000e+00 1.1000000e+00 1.4000000e+00 7.0000000e-01 1.8000000e+00 1.2000000e+00 9.0000000e-01 1.3000000e+00 7.0000000e-01 1.5000000e+00 1.2000000e+00 1.6000000e+00 1.4000000e+00 1.5000000e+00 1.7000000e+00 1.9000000e+00 1.8000000e+00 1.2000000e+00 8.0000000e-01 6.0000000e-01 6.0000000e-01 9.0000000e-01 1.8000000e+00 1.2000000e+00 1.2000000e+00 1.8000000e+00 1.4000000e+00 8.0000000e-01 7.0000000e-01 1.1000000e+00 1.3000000e+00 9.0000000e-01 1.0000000e-01 9.0000000e-01 9.0000000e-01 9.0000000e-01 1.3000000e+00 3.0000000e-01 8.0000000e-01 2.7000000e+00 1.8000000e+00 2.6000000e+00 2.3000000e+00 2.5000000e+00 3.3000000e+00 1.2000000e+00 3.0000000e+00 2.5000000e+00 2.8000000e+00 1.8000000e+00 2.0000000e+00 2.2000000e+00 1.7000000e+00 1.8000000e+00 2.0000000e+00 2.2000000e+00 3.4000000e+00 3.6000000e+00 1.7000000e+00 2.4000000e+00 1.6000000e+00 3.4000000e+00 1.6000000e+00 2.4000000e+00 2.7000000e+00 1.5000000e+00 1.6000000e+00 2.3000000e+00 2.5000000e+00 2.8000000e+00 3.1000000e+00 2.3000000e+00 1.8000000e+00 2.3000000e+00 2.8000000e+00 2.3000000e+00 2.2000000e+00 1.5000000e+00 2.1000000e+00 2.3000000e+00 2.0000000e+00 1.8000000e+00 2.6000000e+00 2.4000000e+00 1.9000000e+00 1.7000000e+00 1.9000000e+00 2.1000000e+00 1.8000000e+00 1.4000000e+00 1.6000000e+00 7.0000000e-01 7.0000000e-01 5.0000000e-01 1.0000000e+00 2.0000000e-01 1.0000000e+00 8.0000000e-01 7.0000000e-01 1.0000000e+00 7.0000000e-01 6.0000000e-01 4.0000000e-01 5.0000000e-01 3.0000000e-01 2.0000000e-01 2.0000000e-01 4.0000000e-01 6.0000000e-01 1.1000000e+00 1.1000000e+00 1.1000000e+00 8.0000000e-01 6.0000000e-01 1.2000000e+00 6.0000000e-01 2.0000000e-01 6.0000000e-01 1.0000000e+00 1.1000000e+00 1.1000000e+00 5.0000000e-01 8.0000000e-01 1.6000000e+00 1.0000000e+00 9.0000000e-01 9.0000000e-01 4.0000000e-01 1.6000000e+00 9.0000000e-01 1.4000000e+00 8.0000000e-01 1.3000000e+00 1.0000000e+00 1.2000000e+00 2.0000000e+00 1.7000000e+00 1.7000000e+00 1.2000000e+00 1.5000000e+00 7.0000000e-01 7.0000000e-01 9.0000000e-01 9.0000000e-01 1.1000000e+00 1.0000000e+00 9.0000000e-01 2.1000000e+00 2.3000000e+00 7.0000000e-01 1.1000000e+00 1.0000000e+00 2.1000000e+00 5.0000000e-01 1.1000000e+00 1.4000000e+00 5.0000000e-01 5.0000000e-01 1.0000000e+00 1.2000000e+00 1.5000000e+00 1.8000000e+00 1.0000000e+00 5.0000000e-01 1.0000000e+00 1.5000000e+00 1.1000000e+00 9.0000000e-01 6.0000000e-01 8.0000000e-01 1.1000000e+00 1.0000000e+00 8.0000000e-01 1.3000000e+00 1.2000000e+00 1.0000000e+00 6.0000000e-01 7.0000000e-01 1.0000000e+00 7.0000000e-01 7.0000000e-01 7.0000000e-01 8.0000000e-01 9.0000000e-01 4.0000000e-01 1.5000000e+00 6.0000000e-01 6.0000000e-01 1.0000000e+00 4.0000000e-01 9.0000000e-01 9.0000000e-01 1.1000000e+00 9.0000000e-01 1.2000000e+00 1.4000000e+00 1.6000000e+00 1.5000000e+00 8.0000000e-01 5.0000000e-01 3.0000000e-01 4.0000000e-01 6.0000000e-01 1.2000000e+00 6.0000000e-01 8.0000000e-01 1.5000000e+00 1.1000000e+00 4.0000000e-01 3.0000000e-01 5.0000000e-01 9.0000000e-01 6.0000000e-01 6.0000000e-01 4.0000000e-01 5.0000000e-01 5.0000000e-01 1.0000000e+00 9.0000000e-01 5.0000000e-01 2.1000000e+00 1.2000000e+00 2.0000000e+00 1.7000000e+00 1.9000000e+00 2.7000000e+00 6.0000000e-01 2.4000000e+00 1.9000000e+00 2.2000000e+00 1.3000000e+00 1.4000000e+00 1.6000000e+00 1.1000000e+00 1.2000000e+00 1.4000000e+00 1.6000000e+00 2.8000000e+00 3.0000000e+00 1.1000000e+00 1.8000000e+00 1.0000000e+00 2.8000000e+00 1.1000000e+00 1.8000000e+00 2.1000000e+00 1.0000000e+00 1.0000000e+00 1.7000000e+00 2.0000000e+00 2.2000000e+00 2.7000000e+00 1.7000000e+00 1.2000000e+00 1.7000000e+00 2.5000000e+00 1.7000000e+00 1.6000000e+00 9.0000000e-01 1.7000000e+00 1.7000000e+00 1.7000000e+00 1.2000000e+00 2.0000000e+00 1.8000000e+00 1.5000000e+00 1.1000000e+00 1.3000000e+00 1.5000000e+00 1.2000000e+00 1.0000000e+00 1.0000000e+00 1.2000000e+00 9.0000000e-01 1.7000000e+00 1.0000000e+00 8.0000000e-01 1.2000000e+00 6.0000000e-01 1.3000000e+00 1.1000000e+00 1.4000000e+00 1.2000000e+00 1.4000000e+00 1.6000000e+00 1.8000000e+00 1.7000000e+00 1.0000000e+00 7.0000000e-01 5.0000000e-01 5.0000000e-01 8.0000000e-01 1.6000000e+00 1.0000000e+00 1.4000000e+00 1.7000000e+00 1.3000000e+00 1.0000000e+00 5.0000000e-01 9.0000000e-01 1.1000000e+00 8.0000000e-01 3.0000000e-01 7.0000000e-01 1.0000000e+00 9.0000000e-01 1.2000000e+00 5.0000000e-01 8.0000000e-01 2.5000000e+00 1.6000000e+00 2.4000000e+00 2.1000000e+00 2.3000000e+00 3.1000000e+00 1.0000000e+00 2.8000000e+00 2.3000000e+00 2.6000000e+00 1.6000000e+00 1.8000000e+00 2.0000000e+00 1.5000000e+00 1.6000000e+00 1.8000000e+00 2.0000000e+00 3.2000000e+00 3.4000000e+00 1.5000000e+00 2.2000000e+00 1.4000000e+00 3.2000000e+00 1.4000000e+00 2.2000000e+00 2.5000000e+00 1.3000000e+00 1.4000000e+00 2.1000000e+00 2.3000000e+00 2.6000000e+00 2.9000000e+00 2.1000000e+00 1.6000000e+00 2.1000000e+00 2.7000000e+00 2.1000000e+00 2.0000000e+00 1.3000000e+00 1.9000000e+00 2.1000000e+00 1.9000000e+00 1.6000000e+00 2.4000000e+00 2.2000000e+00 1.7000000e+00 1.5000000e+00 1.7000000e+00 1.9000000e+00 1.6000000e+00 8.0000000e-01 5.0000000e-01 6.0000000e-01 8.0000000e-01 3.0000000e-01 5.0000000e-01 8.0000000e-01 5.0000000e-01 6.0000000e-01 2.0000000e-01 7.0000000e-01 5.0000000e-01 5.0000000e-01 7.0000000e-01 9.0000000e-01 8.0000000e-01 3.0000000e-01 7.0000000e-01 6.0000000e-01 6.0000000e-01 3.0000000e-01 9.0000000e-01 5.0000000e-01 4.0000000e-01 8.0000000e-01 7.0000000e-01 3.0000000e-01 5.0000000e-01 4.0000000e-01 4.0000000e-01 4.0000000e-01 9.0000000e-01 3.0000000e-01 3.0000000e-01 2.0000000e-01 3.0000000e-01 1.2000000e+00 2.0000000e-01 1.8000000e+00 9.0000000e-01 1.7000000e+00 1.4000000e+00 1.6000000e+00 2.4000000e+00 1.0000000e+00 2.1000000e+00 1.6000000e+00 1.9000000e+00 9.0000000e-01 1.1000000e+00 1.3000000e+00 8.0000000e-01 9.0000000e-01 1.1000000e+00 1.3000000e+00 2.5000000e+00 2.7000000e+00 8.0000000e-01 1.5000000e+00 7.0000000e-01 2.5000000e+00 7.0000000e-01 1.5000000e+00 1.8000000e+00 6.0000000e-01 7.0000000e-01 1.4000000e+00 1.6000000e+00 1.9000000e+00 2.2000000e+00 1.4000000e+00 9.0000000e-01 1.4000000e+00 1.9000000e+00 1.4000000e+00 1.3000000e+00 6.0000000e-01 1.2000000e+00 1.4000000e+00 1.0000000e+00 9.0000000e-01 1.7000000e+00 1.5000000e+00 1.0000000e+00 8.0000000e-01 1.0000000e+00 1.2000000e+00 9.0000000e-01 7.0000000e-01 7.0000000e-01 9.0000000e-01 8.0000000e-01 5.0000000e-01 5.0000000e-01 4.0000000e-01 1.0000000e+00 6.0000000e-01 9.0000000e-01 7.0000000e-01 7.0000000e-01 8.0000000e-01 8.0000000e-01 1.0000000e+00 7.0000000e-01 5.0000000e-01 5.0000000e-01 5.0000000e-01 5.0000000e-01 1.1000000e+00 8.0000000e-01 1.2000000e+00 9.0000000e-01 4.0000000e-01 8.0000000e-01 5.0000000e-01 5.0000000e-01 8.0000000e-01 4.0000000e-01 1.0000000e+00 5.0000000e-01 8.0000000e-01 7.0000000e-01 7.0000000e-01 1.0000000e+00 6.0000000e-01 2.0000000e+00 1.1000000e+00 1.9000000e+00 1.6000000e+00 1.8000000e+00 2.6000000e+00 1.1000000e+00 2.3000000e+00 1.8000000e+00 2.1000000e+00 1.1000000e+00 1.3000000e+00 1.5000000e+00 1.0000000e+00 1.4000000e+00 1.3000000e+00 1.5000000e+00 2.7000000e+00 2.9000000e+00 1.0000000e+00 1.7000000e+00 1.0000000e+00 2.7000000e+00 9.0000000e-01 1.7000000e+00 2.0000000e+00 8.0000000e-01 9.0000000e-01 1.6000000e+00 1.8000000e+00 2.1000000e+00 2.4000000e+00 1.6000000e+00 1.1000000e+00 1.6000000e+00 2.1000000e+00 1.6000000e+00 1.5000000e+00 8.0000000e-01 1.4000000e+00 1.6000000e+00 1.3000000e+00 1.1000000e+00 1.9000000e+00 1.7000000e+00 1.3000000e+00 1.0000000e+00 1.2000000e+00 1.4000000e+00 1.1000000e+00 1.1000000e+00 6.0000000e-01 5.0000000e-01 6.0000000e-01 7.0000000e-01 8.0000000e-01 4.0000000e-01 7.0000000e-01 4.0000000e-01 2.0000000e-01 4.0000000e-01 5.0000000e-01 7.0000000e-01 6.0000000e-01 2.0000000e-01 1.2000000e+00 9.0000000e-01 1.0000000e+00 8.0000000e-01 4.0000000e-01 7.0000000e-01 5.0000000e-01 6.0000000e-01 6.0000000e-01 6.0000000e-01 7.0000000e-01 6.0000000e-01 1.0000000e-01 7.0000000e-01 1.4000000e+00 5.0000000e-01 5.0000000e-01 5.0000000e-01 4.0000000e-01 1.7000000e+00 6.0000000e-01 1.3000000e+00 5.0000000e-01 1.2000000e+00 9.0000000e-01 1.1000000e+00 1.9000000e+00 1.2000000e+00 1.6000000e+00 1.1000000e+00 1.4000000e+00 6.0000000e-01 6.0000000e-01 8.0000000e-01 6.0000000e-01 1.0000000e+00 9.0000000e-01 8.0000000e-01 2.0000000e+00 2.2000000e+00 7.0000000e-01 1.0000000e+00 6.0000000e-01 2.0000000e+00 4.0000000e-01 1.0000000e+00 1.3000000e+00 4.0000000e-01 4.0000000e-01 9.0000000e-01 1.1000000e+00 1.4000000e+00 1.8000000e+00 9.0000000e-01 4.0000000e-01 9.0000000e-01 1.6000000e+00 1.0000000e+00 8.0000000e-01 4.0000000e-01 8.0000000e-01 1.0000000e+00 9.0000000e-01 5.0000000e-01 1.2000000e+00 1.1000000e+00 9.0000000e-01 5.0000000e-01 6.0000000e-01 9.0000000e-01 4.0000000e-01 1.1000000e+00 9.0000000e-01 5.0000000e-01 9.0000000e-01 4.0000000e-01 1.2000000e+00 5.0000000e-01 1.3000000e+00 1.1000000e+00 8.0000000e-01 1.0000000e+00 1.2000000e+00 1.4000000e+00 9.0000000e-01 3.0000000e-01 5.0000000e-01 5.0000000e-01 3.0000000e-01 1.5000000e+00 9.0000000e-01 9.0000000e-01 1.1000000e+00 8.0000000e-01 5.0000000e-01 4.0000000e-01 8.0000000e-01 1.0000000e+00 4.0000000e-01 6.0000000e-01 6.0000000e-01 6.0000000e-01 6.0000000e-01 7.0000000e-01 6.0000000e-01 5.0000000e-01 2.4000000e+00 1.5000000e+00 2.3000000e+00 2.0000000e+00 2.2000000e+00 3.0000000e+00 9.0000000e-01 2.7000000e+00 2.2000000e+00 2.5000000e+00 1.5000000e+00 1.7000000e+00 1.9000000e+00 1.4000000e+00 1.5000000e+00 1.7000000e+00 1.9000000e+00 3.1000000e+00 3.3000000e+00 1.4000000e+00 2.1000000e+00 1.3000000e+00 3.1000000e+00 1.3000000e+00 2.1000000e+00 2.4000000e+00 1.2000000e+00 1.3000000e+00 2.0000000e+00 2.2000000e+00 2.5000000e+00 2.8000000e+00 2.0000000e+00 1.5000000e+00 2.0000000e+00 2.5000000e+00 2.0000000e+00 1.9000000e+00 1.2000000e+00 1.8000000e+00 2.0000000e+00 1.5000000e+00 1.5000000e+00 2.3000000e+00 2.1000000e+00 1.6000000e+00 1.4000000e+00 1.6000000e+00 1.8000000e+00 1.5000000e+00 1.1000000e+00 9.0000000e-01 9.0000000e-01 1.1000000e+00 8.0000000e-01 6.0000000e-01 6.0000000e-01 6.0000000e-01 3.0000000e-01 1.0000000e-01 4.0000000e-01 6.0000000e-01 7.0000000e-01 1.0000000e+00 1.2000000e+00 1.2000000e+00 9.0000000e-01 7.0000000e-01 1.3000000e+00 7.0000000e-01 3.0000000e-01 8.0000000e-01 1.1000000e+00 1.2000000e+00 1.2000000e+00 6.0000000e-01 9.0000000e-01 1.7000000e+00 1.1000000e+00 1.0000000e+00 1.0000000e+00 5.0000000e-01 1.6000000e+00 1.0000000e+00 1.6000000e+00 9.0000000e-01 1.5000000e+00 1.2000000e+00 1.4000000e+00 2.2000000e+00 1.8000000e+00 1.9000000e+00 1.4000000e+00 1.7000000e+00 7.0000000e-01 9.0000000e-01 1.1000000e+00 1.0000000e+00 1.0000000e+00 9.0000000e-01 1.1000000e+00 2.3000000e+00 2.5000000e+00 9.0000000e-01 1.3000000e+00 1.1000000e+00 2.3000000e+00 5.0000000e-01 1.3000000e+00 1.6000000e+00 5.0000000e-01 6.0000000e-01 1.2000000e+00 1.4000000e+00 1.7000000e+00 2.0000000e+00 1.2000000e+00 7.0000000e-01 1.2000000e+00 1.7000000e+00 1.2000000e+00 1.1000000e+00 7.0000000e-01 1.0000000e+00 1.2000000e+00 9.0000000e-01 9.0000000e-01 1.5000000e+00 1.3000000e+00 9.0000000e-01 6.0000000e-01 8.0000000e-01 1.0000000e+00 8.0000000e-01 5.0000000e-01 8.0000000e-01 6.0000000e-01 3.0000000e-01 5.0000000e-01 7.0000000e-01 5.0000000e-01 8.0000000e-01 1.0000000e+00 1.2000000e+00 1.1000000e+00 4.0000000e-01 1.0000000e+00 7.0000000e-01 8.0000000e-01 6.0000000e-01 6.0000000e-01 2.0000000e-01 4.0000000e-01 1.1000000e+00 7.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 5.0000000e-01 5.0000000e-01 1.2000000e+00 3.0000000e-01 3.0000000e-01 3.0000000e-01 6.0000000e-01 1.5000000e+00 4.0000000e-01 1.5000000e+00 6.0000000e-01 1.5000000e+00 1.1000000e+00 1.3000000e+00 2.1000000e+00 7.0000000e-01 1.8000000e+00 1.3000000e+00 1.6000000e+00 9.0000000e-01 8.0000000e-01 1.2000000e+00 5.0000000e-01 9.0000000e-01 8.0000000e-01 1.0000000e+00 2.2000000e+00 2.4000000e+00 8.0000000e-01 1.3000000e+00 5.0000000e-01 2.2000000e+00 7.0000000e-01 1.2000000e+00 1.6000000e+00 6.0000000e-01 5.0000000e-01 1.1000000e+00 1.6000000e+00 1.8000000e+00 2.3000000e+00 1.1000000e+00 7.0000000e-01 1.1000000e+00 2.1000000e+00 1.1000000e+00 1.0000000e+00 4.0000000e-01 1.3000000e+00 1.1000000e+00 1.3000000e+00 6.0000000e-01 1.4000000e+00 1.2000000e+00 1.1000000e+00 7.0000000e-01 9.0000000e-01 9.0000000e-01 6.0000000e-01 5.0000000e-01 2.0000000e-01 8.0000000e-01 3.0000000e-01 8.0000000e-01 6.0000000e-01 6.0000000e-01 8.0000000e-01 1.0000000e+00 9.0000000e-01 5.0000000e-01 6.0000000e-01 3.0000000e-01 4.0000000e-01 2.0000000e-01 1.0000000e+00 5.0000000e-01 7.0000000e-01 9.0000000e-01 5.0000000e-01 3.0000000e-01 3.0000000e-01 3.0000000e-01 5.0000000e-01 2.0000000e-01 8.0000000e-01 3.0000000e-01 3.0000000e-01 3.0000000e-01 4.0000000e-01 1.1000000e+00 3.0000000e-01 1.9000000e+00 1.0000000e+00 1.8000000e+00 1.5000000e+00 1.7000000e+00 2.5000000e+00 9.0000000e-01 2.2000000e+00 1.7000000e+00 2.0000000e+00 1.0000000e+00 1.2000000e+00 1.4000000e+00 1.0000000e+00 1.4000000e+00 1.3000000e+00 1.4000000e+00 2.6000000e+00 2.8000000e+00 9.0000000e-01 1.6000000e+00 1.0000000e+00 2.6000000e+00 8.0000000e-01 1.6000000e+00 1.9000000e+00 8.0000000e-01 8.0000000e-01 1.5000000e+00 1.7000000e+00 2.0000000e+00 2.3000000e+00 1.5000000e+00 1.0000000e+00 1.5000000e+00 2.0000000e+00 1.5000000e+00 1.4000000e+00 8.0000000e-01 1.3000000e+00 1.5000000e+00 1.3000000e+00 1.0000000e+00 1.8000000e+00 1.6000000e+00 1.3000000e+00 9.0000000e-01 1.1000000e+00 1.3000000e+00 1.0000000e+00 6.0000000e-01 1.0000000e+00 6.0000000e-01 4.0000000e-01 6.0000000e-01 7.0000000e-01 8.0000000e-01 6.0000000e-01 8.0000000e-01 7.0000000e-01 1.0000000e+00 7.0000000e-01 8.0000000e-01 6.0000000e-01 6.0000000e-01 8.0000000e-01 1.2000000e+00 9.0000000e-01 2.0000000e-01 8.0000000e-01 7.0000000e-01 7.0000000e-01 8.0000000e-01 5.0000000e-01 1.2000000e+00 6.0000000e-01 8.0000000e-01 7.0000000e-01 7.0000000e-01 1.5000000e+00 6.0000000e-01 1.5000000e+00 6.0000000e-01 1.4000000e+00 1.1000000e+00 1.3000000e+00 2.1000000e+00 1.3000000e+00 1.8000000e+00 1.3000000e+00 1.6000000e+00 1.0000000e+00 8.0000000e-01 1.0000000e+00 5.0000000e-01 9.0000000e-01 1.0000000e+00 1.0000000e+00 2.2000000e+00 2.4000000e+00 5.0000000e-01 1.2000000e+00 6.0000000e-01 2.2000000e+00 5.0000000e-01 1.2000000e+00 1.5000000e+00 6.0000000e-01 8.0000000e-01 1.1000000e+00 1.3000000e+00 1.6000000e+00 1.9000000e+00 1.1000000e+00 6.0000000e-01 1.1000000e+00 1.6000000e+00 1.2000000e+00 1.0000000e+00 8.0000000e-01 9.0000000e-01 1.1000000e+00 9.0000000e-01 6.0000000e-01 1.4000000e+00 1.2000000e+00 8.0000000e-01 5.0000000e-01 8.0000000e-01 1.2000000e+00 8.0000000e-01 9.0000000e-01 5.0000000e-01 1.0000000e+00 8.0000000e-01 8.0000000e-01 1.0000000e+00 1.2000000e+00 1.1000000e+00 6.0000000e-01 4.0000000e-01 1.0000000e-01 2.0000000e-01 2.0000000e-01 1.2000000e+00 6.0000000e-01 9.0000000e-01 1.1000000e+00 7.0000000e-01 5.0000000e-01 2.0000000e-01 5.0000000e-01 7.0000000e-01 2.0000000e-01 6.0000000e-01 3.0000000e-01 5.0000000e-01 4.0000000e-01 6.0000000e-01 9.0000000e-01 3.0000000e-01 2.1000000e+00 1.2000000e+00 2.0000000e+00 1.7000000e+00 1.9000000e+00 2.7000000e+00 7.0000000e-01 2.4000000e+00 1.9000000e+00 2.2000000e+00 1.2000000e+00 1.4000000e+00 1.6000000e+00 1.1000000e+00 1.3000000e+00 1.4000000e+00 1.6000000e+00 2.8000000e+00 3.0000000e+00 1.1000000e+00 1.8000000e+00 1.0000000e+00 2.8000000e+00 1.0000000e+00 1.8000000e+00 2.1000000e+00 9.0000000e-01 1.0000000e+00 1.7000000e+00 1.9000000e+00 2.2000000e+00 2.5000000e+00 1.7000000e+00 1.2000000e+00 1.7000000e+00 2.2000000e+00 1.7000000e+00 1.6000000e+00 9.0000000e-01 1.5000000e+00 1.7000000e+00 1.3000000e+00 1.2000000e+00 2.0000000e+00 1.8000000e+00 1.3000000e+00 1.1000000e+00 1.3000000e+00 1.5000000e+00 1.2000000e+00 8.0000000e-01 7.0000000e-01 6.0000000e-01 5.0000000e-01 7.0000000e-01 9.0000000e-01 8.0000000e-01 3.0000000e-01 1.3000000e+00 1.0000000e+00 1.1000000e+00 9.0000000e-01 5.0000000e-01 5.0000000e-01 3.0000000e-01 8.0000000e-01 9.0000000e-01 7.0000000e-01 8.0000000e-01 6.0000000e-01 4.0000000e-01 8.0000000e-01 1.5000000e+00 6.0000000e-01 6.0000000e-01 6.0000000e-01 5.0000000e-01 1.8000000e+00 7.0000000e-01 1.2000000e+00 5.0000000e-01 1.2000000e+00 8.0000000e-01 1.0000000e+00 1.8000000e+00 1.0000000e+00 1.5000000e+00 1.0000000e+00 1.3000000e+00 6.0000000e-01 5.0000000e-01 9.0000000e-01 7.0000000e-01 6.0000000e-01 5.0000000e-01 7.0000000e-01 1.9000000e+00 2.1000000e+00 1.0000000e+00 1.0000000e+00 4.0000000e-01 1.9000000e+00 5.0000000e-01 9.0000000e-01 1.3000000e+00 4.0000000e-01 2.0000000e-01 8.0000000e-01 1.3000000e+00 1.5000000e+00 2.0000000e+00 8.0000000e-01 4.0000000e-01 8.0000000e-01 1.8000000e+00 8.0000000e-01 7.0000000e-01 2.0000000e-01 1.0000000e+00 8.0000000e-01 1.0000000e+00 5.0000000e-01 1.1000000e+00 9.0000000e-01 8.0000000e-01 7.0000000e-01 6.0000000e-01 6.0000000e-01 3.0000000e-01 9.0000000e-01 7.0000000e-01 3.0000000e-01 5.0000000e-01 8.0000000e-01 1.0000000e+00 5.0000000e-01 5.0000000e-01 6.0000000e-01 6.0000000e-01 3.0000000e-01 1.1000000e+00 7.0000000e-01 6.0000000e-01 7.0000000e-01 5.0000000e-01 5.0000000e-01 6.0000000e-01 6.0000000e-01 6.0000000e-01 3.0000000e-01 1.1000000e+00 5.0000000e-01 4.0000000e-01 4.0000000e-01 3.0000000e-01 1.0000000e+00 4.0000000e-01 2.0000000e+00 1.1000000e+00 1.9000000e+00 1.6000000e+00 1.8000000e+00 2.6000000e+00 1.2000000e+00 2.3000000e+00 1.8000000e+00 2.1000000e+00 1.1000000e+00 1.3000000e+00 1.5000000e+00 1.0000000e+00 1.1000000e+00 1.3000000e+00 1.5000000e+00 2.7000000e+00 2.9000000e+00 1.0000000e+00 1.7000000e+00 9.0000000e-01 2.7000000e+00 9.0000000e-01 1.7000000e+00 2.0000000e+00 8.0000000e-01 9.0000000e-01 1.6000000e+00 1.8000000e+00 2.1000000e+00 2.4000000e+00 1.6000000e+00 1.1000000e+00 1.6000000e+00 2.1000000e+00 1.6000000e+00 1.5000000e+00 8.0000000e-01 1.4000000e+00 1.6000000e+00 1.1000000e+00 1.1000000e+00 1.9000000e+00 1.7000000e+00 1.2000000e+00 1.0000000e+00 1.2000000e+00 1.4000000e+00 1.1000000e+00 3.0000000e-01 6.0000000e-01 5.0000000e-01 5.0000000e-01 5.0000000e-01 4.0000000e-01 1.4000000e+00 1.1000000e+00 1.2000000e+00 1.0000000e+00 3.0000000e-01 9.0000000e-01 9.0000000e-01 6.0000000e-01 5.0000000e-01 8.0000000e-01 9.0000000e-01 8.0000000e-01 5.0000000e-01 9.0000000e-01 1.6000000e+00 7.0000000e-01 7.0000000e-01 7.0000000e-01 6.0000000e-01 1.9000000e+00 8.0000000e-01 1.1000000e+00 5.0000000e-01 1.0000000e+00 7.0000000e-01 9.0000000e-01 1.7000000e+00 1.4000000e+00 1.4000000e+00 9.0000000e-01 1.2000000e+00 7.0000000e-01 4.0000000e-01 6.0000000e-01 6.0000000e-01 9.0000000e-01 8.0000000e-01 6.0000000e-01 1.8000000e+00 2.0000000e+00 3.0000000e-01 8.0000000e-01 7.0000000e-01 1.8000000e+00 3.0000000e-01 8.0000000e-01 1.1000000e+00 3.0000000e-01 5.0000000e-01 7.0000000e-01 9.0000000e-01 1.2000000e+00 1.6000000e+00 7.0000000e-01 3.0000000e-01 7.0000000e-01 1.4000000e+00 9.0000000e-01 6.0000000e-01 5.0000000e-01 6.0000000e-01 9.0000000e-01 8.0000000e-01 5.0000000e-01 1.0000000e+00 1.0000000e+00 8.0000000e-01 4.0000000e-01 5.0000000e-01 9.0000000e-01 5.0000000e-01 4.0000000e-01 5.0000000e-01 7.0000000e-01 6.0000000e-01 3.0000000e-01 1.2000000e+00 9.0000000e-01 1.0000000e+00 8.0000000e-01 4.0000000e-01 7.0000000e-01 6.0000000e-01 6.0000000e-01 5.0000000e-01 6.0000000e-01 7.0000000e-01 6.0000000e-01 2.0000000e-01 7.0000000e-01 1.4000000e+00 5.0000000e-01 5.0000000e-01 5.0000000e-01 4.0000000e-01 1.7000000e+00 6.0000000e-01 1.3000000e+00 7.0000000e-01 1.2000000e+00 9.0000000e-01 1.1000000e+00 1.9000000e+00 1.2000000e+00 1.6000000e+00 1.1000000e+00 1.4000000e+00 8.0000000e-01 7.0000000e-01 9.0000000e-01 8.0000000e-01 1.2000000e+00 1.1000000e+00 8.0000000e-01 2.0000000e+00 2.2000000e+00 6.0000000e-01 1.1000000e+00 8.0000000e-01 2.0000000e+00 6.0000000e-01 1.0000000e+00 1.3000000e+00 6.0000000e-01 6.0000000e-01 9.0000000e-01 1.1000000e+00 1.4000000e+00 1.8000000e+00 1.0000000e+00 4.0000000e-01 9.0000000e-01 1.6000000e+00 1.2000000e+00 8.0000000e-01 6.0000000e-01 9.0000000e-01 1.2000000e+00 1.1000000e+00 7.0000000e-01 1.2000000e+00 1.3000000e+00 1.1000000e+00 7.0000000e-01 8.0000000e-01 1.1000000e+00 6.0000000e-01 2.0000000e-01 5.0000000e-01 7.0000000e-01 4.0000000e-01 8.0000000e-01 9.0000000e-01 9.0000000e-01 6.0000000e-01 8.0000000e-01 1.0000000e+00 5.0000000e-01 4.0000000e-01 6.0000000e-01 8.0000000e-01 9.0000000e-01 9.0000000e-01 3.0000000e-01 6.0000000e-01 1.4000000e+00 8.0000000e-01 7.0000000e-01 7.0000000e-01 2.0000000e-01 1.3000000e+00 7.0000000e-01 1.7000000e+00 8.0000000e-01 1.6000000e+00 1.3000000e+00 1.5000000e+00 2.3000000e+00 1.5000000e+00 2.0000000e+00 1.5000000e+00 1.8000000e+00 8.0000000e-01 1.0000000e+00 1.2000000e+00 7.0000000e-01 1.1000000e+00 1.0000000e+00 1.2000000e+00 2.4000000e+00 2.6000000e+00 7.0000000e-01 1.4000000e+00 8.0000000e-01 2.4000000e+00 6.0000000e-01 1.4000000e+00 1.7000000e+00 5.0000000e-01 6.0000000e-01 1.3000000e+00 1.5000000e+00 1.8000000e+00 2.1000000e+00 1.3000000e+00 8.0000000e-01 1.3000000e+00 1.8000000e+00 1.3000000e+00 1.2000000e+00 5.0000000e-01 1.1000000e+00 1.3000000e+00 1.0000000e+00 8.0000000e-01 1.6000000e+00 1.4000000e+00 1.0000000e+00 7.0000000e-01 9.0000000e-01 1.1000000e+00 8.0000000e-01 4.0000000e-01 6.0000000e-01 6.0000000e-01 9.0000000e-01 1.1000000e+00 1.1000000e+00 8.0000000e-01 7.0000000e-01 1.2000000e+00 6.0000000e-01 3.0000000e-01 7.0000000e-01 1.0000000e+00 1.1000000e+00 1.1000000e+00 5.0000000e-01 8.0000000e-01 1.6000000e+00 1.0000000e+00 9.0000000e-01 9.0000000e-01 4.0000000e-01 1.5000000e+00 9.0000000e-01 1.6000000e+00 8.0000000e-01 1.5000000e+00 1.2000000e+00 1.4000000e+00 2.2000000e+00 1.7000000e+00 1.9000000e+00 1.4000000e+00 1.7000000e+00 7.0000000e-01 9.0000000e-01 1.1000000e+00 9.0000000e-01 1.0000000e+00 9.0000000e-01 1.1000000e+00 2.3000000e+00 2.5000000e+00 8.0000000e-01 1.3000000e+00 1.0000000e+00 2.3000000e+00 5.0000000e-01 1.3000000e+00 1.6000000e+00 4.0000000e-01 5.0000000e-01 1.2000000e+00 1.4000000e+00 1.7000000e+00 2.0000000e+00 1.2000000e+00 7.0000000e-01 1.2000000e+00 1.7000000e+00 1.2000000e+00 1.1000000e+00 6.0000000e-01 1.0000000e+00 1.2000000e+00 9.0000000e-01 8.0000000e-01 1.5000000e+00 1.3000000e+00 9.0000000e-01 6.0000000e-01 8.0000000e-01 1.0000000e+00 7.0000000e-01 3.0000000e-01 8.0000000e-01 1.3000000e+00 1.3000000e+00 1.3000000e+00 1.0000000e+00 8.0000000e-01 1.4000000e+00 8.0000000e-01 3.0000000e-01 5.0000000e-01 1.2000000e+00 1.3000000e+00 1.3000000e+00 7.0000000e-01 1.0000000e+00 1.8000000e+00 1.2000000e+00 1.1000000e+00 1.1000000e+00 6.0000000e-01 1.8000000e+00 1.1000000e+00 1.2000000e+00 1.0000000e+00 1.1000000e+00 8.0000000e-01 1.0000000e+00 1.8000000e+00 1.9000000e+00 1.5000000e+00 1.0000000e+00 1.3000000e+00 6.0000000e-01 5.0000000e-01 7.0000000e-01 1.1000000e+00 1.0000000e+00 9.0000000e-01 7.0000000e-01 1.9000000e+00 2.1000000e+00 8.0000000e-01 9.0000000e-01 1.2000000e+00 1.9000000e+00 5.0000000e-01 9.0000000e-01 1.2000000e+00 6.0000000e-01 7.0000000e-01 8.0000000e-01 1.0000000e+00 1.3000000e+00 1.6000000e+00 8.0000000e-01 5.0000000e-01 8.0000000e-01 1.3000000e+00 1.0000000e+00 7.0000000e-01 8.0000000e-01 7.0000000e-01 1.0000000e+00 9.0000000e-01 1.0000000e+00 1.1000000e+00 1.1000000e+00 9.0000000e-01 5.0000000e-01 6.0000000e-01 9.0000000e-01 9.0000000e-01 7.0000000e-01 1.5000000e+00 1.2000000e+00 1.3000000e+00 1.1000000e+00 7.0000000e-01 1.3000000e+00 7.0000000e-01 3.0000000e-01 7.0000000e-01 1.1000000e+00 1.2000000e+00 1.2000000e+00 6.0000000e-01 1.0000000e+00 1.7000000e+00 1.1000000e+00 1.0000000e+00 1.0000000e+00 7.0000000e-01 2.0000000e+00 1.0000000e+00 1.0000000e+00 9.0000000e-01 9.0000000e-01 6.0000000e-01 8.0000000e-01 1.6000000e+00 1.8000000e+00 1.3000000e+00 8.0000000e-01 1.1000000e+00 3.0000000e-01 3.0000000e-01 5.0000000e-01 1.0000000e+00 9.0000000e-01 6.0000000e-01 5.0000000e-01 1.7000000e+00 1.9000000e+00 8.0000000e-01 7.0000000e-01 1.1000000e+00 1.7000000e+00 4.0000000e-01 7.0000000e-01 1.0000000e+00 5.0000000e-01 6.0000000e-01 6.0000000e-01 8.0000000e-01 1.1000000e+00 1.4000000e+00 6.0000000e-01 4.0000000e-01 6.0000000e-01 1.1000000e+00 7.0000000e-01 5.0000000e-01 7.0000000e-01 4.0000000e-01 7.0000000e-01 6.0000000e-01 9.0000000e-01 9.0000000e-01 8.0000000e-01 6.0000000e-01 5.0000000e-01 3.0000000e-01 6.0000000e-01 8.0000000e-01 1.0000000e+00 7.0000000e-01 8.0000000e-01 6.0000000e-01 6.0000000e-01 6.0000000e-01 5.0000000e-01 7.0000000e-01 6.0000000e-01 4.0000000e-01 5.0000000e-01 5.0000000e-01 1.0000000e-01 5.0000000e-01 1.2000000e+00 4.0000000e-01 3.0000000e-01 3.0000000e-01 2.0000000e-01 1.5000000e+00 4.0000000e-01 1.5000000e+00 6.0000000e-01 1.4000000e+00 1.1000000e+00 1.3000000e+00 2.1000000e+00 1.1000000e+00 1.8000000e+00 1.3000000e+00 1.6000000e+00 6.0000000e-01 8.0000000e-01 1.0000000e+00 5.0000000e-01 9.0000000e-01 8.0000000e-01 1.0000000e+00 2.2000000e+00 2.4000000e+00 7.0000000e-01 1.2000000e+00 5.0000000e-01 2.2000000e+00 4.0000000e-01 1.2000000e+00 1.5000000e+00 3.0000000e-01 4.0000000e-01 1.1000000e+00 1.3000000e+00 1.6000000e+00 1.9000000e+00 1.1000000e+00 6.0000000e-01 1.1000000e+00 1.7000000e+00 1.1000000e+00 1.0000000e+00 3.0000000e-01 9.0000000e-01 1.1000000e+00 9.0000000e-01 6.0000000e-01 1.4000000e+00 1.2000000e+00 8.0000000e-01 5.0000000e-01 7.0000000e-01 9.0000000e-01 6.0000000e-01 3.0000000e-01 2.0000000e-01 4.0000000e-01 1.6000000e+00 1.0000000e+00 1.0000000e+00 1.2000000e+00 9.0000000e-01 6.0000000e-01 5.0000000e-01 9.0000000e-01 1.1000000e+00 5.0000000e-01 7.0000000e-01 7.0000000e-01 7.0000000e-01 7.0000000e-01 8.0000000e-01 6.0000000e-01 6.0000000e-01 2.5000000e+00 1.6000000e+00 2.4000000e+00 2.1000000e+00 2.3000000e+00 3.1000000e+00 1.0000000e+00 2.8000000e+00 2.3000000e+00 2.6000000e+00 1.6000000e+00 1.8000000e+00 2.0000000e+00 1.5000000e+00 1.6000000e+00 1.8000000e+00 2.0000000e+00 3.2000000e+00 3.4000000e+00 1.5000000e+00 2.2000000e+00 1.4000000e+00 3.2000000e+00 1.4000000e+00 2.2000000e+00 2.5000000e+00 1.3000000e+00 1.4000000e+00 2.1000000e+00 2.3000000e+00 2.6000000e+00 2.9000000e+00 2.1000000e+00 1.6000000e+00 2.1000000e+00 2.6000000e+00 2.1000000e+00 2.0000000e+00 1.3000000e+00 1.9000000e+00 2.1000000e+00 1.6000000e+00 1.6000000e+00 2.4000000e+00 2.2000000e+00 1.7000000e+00 1.5000000e+00 1.7000000e+00 1.9000000e+00 1.6000000e+00 1.0000000e-01 3.0000000e-01 1.3000000e+00 7.0000000e-01 1.0000000e+00 1.2000000e+00 8.0000000e-01 6.0000000e-01 2.0000000e-01 6.0000000e-01 8.0000000e-01 3.0000000e-01 5.0000000e-01 4.0000000e-01 6.0000000e-01 5.0000000e-01 7.0000000e-01 8.0000000e-01 4.0000000e-01 2.2000000e+00 1.3000000e+00 2.1000000e+00 1.8000000e+00 2.0000000e+00 2.8000000e+00 7.0000000e-01 2.5000000e+00 2.0000000e+00 2.3000000e+00 1.3000000e+00 1.5000000e+00 1.7000000e+00 1.2000000e+00 1.3000000e+00 1.5000000e+00 1.7000000e+00 2.9000000e+00 3.1000000e+00 1.2000000e+00 1.9000000e+00 1.1000000e+00 2.9000000e+00 1.1000000e+00 1.9000000e+00 2.2000000e+00 1.0000000e+00 1.1000000e+00 1.8000000e+00 2.0000000e+00 2.3000000e+00 2.6000000e+00 1.8000000e+00 1.3000000e+00 1.8000000e+00 2.3000000e+00 1.8000000e+00 1.7000000e+00 1.0000000e+00 1.6000000e+00 1.8000000e+00 1.4000000e+00 1.3000000e+00 2.1000000e+00 1.9000000e+00 1.4000000e+00 1.2000000e+00 1.4000000e+00 1.6000000e+00 1.3000000e+00 3.0000000e-01 1.4000000e+00 8.0000000e-01 1.0000000e+00 1.2000000e+00 8.0000000e-01 6.0000000e-01 3.0000000e-01 7.0000000e-01 9.0000000e-01 3.0000000e-01 5.0000000e-01 5.0000000e-01 6.0000000e-01 5.0000000e-01 7.0000000e-01 7.0000000e-01 4.0000000e-01 2.3000000e+00 1.4000000e+00 2.2000000e+00 1.9000000e+00 2.1000000e+00 2.9000000e+00 8.0000000e-01 2.6000000e+00 2.1000000e+00 2.4000000e+00 1.4000000e+00 1.6000000e+00 1.8000000e+00 1.3000000e+00 1.4000000e+00 1.6000000e+00 1.8000000e+00 3.0000000e+00 3.2000000e+00 1.3000000e+00 2.0000000e+00 1.2000000e+00 3.0000000e+00 1.2000000e+00 2.0000000e+00 2.3000000e+00 1.1000000e+00 1.2000000e+00 1.9000000e+00 2.1000000e+00 2.4000000e+00 2.7000000e+00 1.9000000e+00 1.4000000e+00 1.9000000e+00 2.4000000e+00 1.9000000e+00 1.8000000e+00 1.1000000e+00 1.7000000e+00 1.9000000e+00 1.4000000e+00 1.4000000e+00 2.2000000e+00 2.0000000e+00 1.5000000e+00 1.3000000e+00 1.5000000e+00 1.7000000e+00 1.4000000e+00 1.2000000e+00 6.0000000e-01 7.0000000e-01 9.0000000e-01 5.0000000e-01 3.0000000e-01 3.0000000e-01 5.0000000e-01 7.0000000e-01 1.0000000e-01 8.0000000e-01 3.0000000e-01 3.0000000e-01 3.0000000e-01 4.0000000e-01 9.0000000e-01 2.0000000e-01 2.1000000e+00 1.2000000e+00 2.0000000e+00 1.7000000e+00 1.9000000e+00 2.7000000e+00 9.0000000e-01 2.4000000e+00 1.9000000e+00 2.2000000e+00 1.2000000e+00 1.4000000e+00 1.6000000e+00 1.1000000e+00 1.2000000e+00 1.4000000e+00 1.6000000e+00 2.8000000e+00 3.0000000e+00 1.1000000e+00 1.8000000e+00 1.0000000e+00 2.8000000e+00 1.0000000e+00 1.8000000e+00 2.1000000e+00 9.0000000e-01 1.0000000e+00 1.7000000e+00 1.9000000e+00 2.2000000e+00 2.5000000e+00 1.7000000e+00 1.2000000e+00 1.7000000e+00 2.2000000e+00 1.7000000e+00 1.6000000e+00 9.0000000e-01 1.5000000e+00 1.7000000e+00 1.2000000e+00 1.2000000e+00 2.0000000e+00 1.8000000e+00 1.3000000e+00 1.1000000e+00 1.3000000e+00 1.5000000e+00 1.2000000e+00 6.0000000e-01 7.0000000e-01 7.0000000e-01 7.0000000e-01 1.0000000e+00 1.1000000e+00 7.0000000e-01 5.0000000e-01 1.1000000e+00 1.8000000e+00 9.0000000e-01 9.0000000e-01 9.0000000e-01 8.0000000e-01 2.1000000e+00 1.0000000e+00 9.0000000e-01 3.0000000e-01 1.1000000e+00 5.0000000e-01 7.0000000e-01 1.6000000e+00 1.1000000e+00 1.3000000e+00 7.0000000e-01 1.2000000e+00 5.0000000e-01 4.0000000e-01 8.0000000e-01 4.0000000e-01 8.0000000e-01 7.0000000e-01 5.0000000e-01 1.7000000e+00 1.8000000e+00 5.0000000e-01 9.0000000e-01 4.0000000e-01 1.7000000e+00 3.0000000e-01 7.0000000e-01 1.2000000e+00 3.0000000e-01 3.0000000e-01 5.0000000e-01 1.2000000e+00 1.4000000e+00 1.9000000e+00 6.0000000e-01 3.0000000e-01 5.0000000e-01 1.7000000e+00 8.0000000e-01 4.0000000e-01 3.0000000e-01 9.0000000e-01 8.0000000e-01 9.0000000e-01 3.0000000e-01 8.0000000e-01 9.0000000e-01 7.0000000e-01 3.0000000e-01 5.0000000e-01 7.0000000e-01 3.0000000e-01 6.0000000e-01 1.3000000e+00 9.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 7.0000000e-01 5.0000000e-01 1.2000000e+00 3.0000000e-01 3.0000000e-01 3.0000000e-01 8.0000000e-01 1.5000000e+00 4.0000000e-01 1.5000000e+00 6.0000000e-01 1.7000000e+00 1.1000000e+00 1.3000000e+00 2.2000000e+00 5.0000000e-01 1.9000000e+00 1.3000000e+00 1.8000000e+00 1.1000000e+00 1.0000000e+00 1.4000000e+00 5.0000000e-01 9.0000000e-01 1.0000000e+00 1.1000000e+00 2.3000000e+00 2.4000000e+00 8.0000000e-01 1.5000000e+00 5.0000000e-01 2.3000000e+00 9.0000000e-01 1.3000000e+00 1.8000000e+00 8.0000000e-01 7.0000000e-01 1.1000000e+00 1.8000000e+00 2.0000000e+00 2.5000000e+00 1.1000000e+00 9.0000000e-01 1.1000000e+00 2.3000000e+00 1.1000000e+00 1.0000000e+00 6.0000000e-01 1.5000000e+00 1.3000000e+00 1.5000000e+00 6.0000000e-01 1.4000000e+00 1.3000000e+00 1.3000000e+00 9.0000000e-01 1.1000000e+00 9.0000000e-01 6.0000000e-01 7.0000000e-01 1.1000000e+00 4.0000000e-01 9.0000000e-01 8.0000000e-01 4.0000000e-01 8.0000000e-01 1.2000000e+00 7.0000000e-01 4.0000000e-01 5.0000000e-01 5.0000000e-01 1.5000000e+00 6.0000000e-01 1.5000000e+00 7.0000000e-01 1.4000000e+00 1.1000000e+00 1.3000000e+00 2.1000000e+00 1.1000000e+00 1.8000000e+00 1.3000000e+00 1.6000000e+00 6.0000000e-01 8.0000000e-01 1.0000000e+00 9.0000000e-01 8.0000000e-01 8.0000000e-01 1.0000000e+00 2.2000000e+00 2.4000000e+00 1.2000000e+00 1.2000000e+00 6.0000000e-01 2.2000000e+00 7.0000000e-01 1.2000000e+00 1.5000000e+00 6.0000000e-01 4.0000000e-01 1.1000000e+00 1.3000000e+00 1.6000000e+00 1.9000000e+00 1.1000000e+00 6.0000000e-01 1.1000000e+00 1.7000000e+00 1.1000000e+00 1.0000000e+00 4.0000000e-01 9.0000000e-01 1.1000000e+00 9.0000000e-01 7.0000000e-01 1.4000000e+00 1.2000000e+00 7.0000000e-01 9.0000000e-01 7.0000000e-01 9.0000000e-01 6.0000000e-01 8.0000000e-01 1.1000000e+00 1.2000000e+00 1.2000000e+00 6.0000000e-01 9.0000000e-01 1.7000000e+00 1.1000000e+00 1.0000000e+00 1.0000000e+00 5.0000000e-01 1.7000000e+00 1.0000000e+00 1.3000000e+00 9.0000000e-01 1.2000000e+00 9.0000000e-01 1.1000000e+00 1.9000000e+00 1.8000000e+00 1.6000000e+00 1.1000000e+00 1.4000000e+00 5.0000000e-01 6.0000000e-01 8.0000000e-01 1.0000000e+00 9.0000000e-01 8.0000000e-01 8.0000000e-01 2.0000000e+00 2.2000000e+00 9.0000000e-01 1.0000000e+00 1.1000000e+00 2.0000000e+00 4.0000000e-01 1.0000000e+00 1.3000000e+00 5.0000000e-01 6.0000000e-01 9.0000000e-01 1.1000000e+00 1.4000000e+00 1.7000000e+00 9.0000000e-01 4.0000000e-01 9.0000000e-01 1.4000000e+00 9.0000000e-01 8.0000000e-01 7.0000000e-01 7.0000000e-01 9.0000000e-01 8.0000000e-01 9.0000000e-01 1.2000000e+00 1.0000000e+00 8.0000000e-01 6.0000000e-01 5.0000000e-01 8.0000000e-01 8.0000000e-01 7.0000000e-01 8.0000000e-01 8.0000000e-01 7.0000000e-01 5.0000000e-01 1.3000000e+00 7.0000000e-01 7.0000000e-01 6.0000000e-01 6.0000000e-01 1.4000000e+00 6.0000000e-01 1.6000000e+00 7.0000000e-01 1.5000000e+00 1.2000000e+00 1.4000000e+00 2.2000000e+00 1.4000000e+00 1.9000000e+00 1.4000000e+00 1.7000000e+00 9.0000000e-01 9.0000000e-01 1.1000000e+00 7.0000000e-01 1.1000000e+00 1.0000000e+00 1.1000000e+00 2.3000000e+00 2.5000000e+00 6.0000000e-01 1.3000000e+00 7.0000000e-01 2.3000000e+00 5.0000000e-01 1.3000000e+00 1.6000000e+00 5.0000000e-01 7.0000000e-01 1.2000000e+00 1.4000000e+00 1.7000000e+00 2.0000000e+00 1.2000000e+00 7.0000000e-01 1.2000000e+00 1.7000000e+00 1.2000000e+00 1.1000000e+00 7.0000000e-01 1.0000000e+00 1.2000000e+00 1.0000000e+00 7.0000000e-01 1.5000000e+00 1.3000000e+00 1.0000000e+00 6.0000000e-01 8.0000000e-01 1.1000000e+00 7.0000000e-01 5.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 8.0000000e-01 3.0000000e-01 1.0000000e-01 1.0000000e-01 6.0000000e-01 1.1000000e+00 2.0000000e-01 1.9000000e+00 1.0000000e+00 1.8000000e+00 1.5000000e+00 1.7000000e+00 2.5000000e+00 7.0000000e-01 2.2000000e+00 1.7000000e+00 2.0000000e+00 1.0000000e+00 1.2000000e+00 1.4000000e+00 9.0000000e-01 1.1000000e+00 1.2000000e+00 1.4000000e+00 2.6000000e+00 2.8000000e+00 9.0000000e-01 1.6000000e+00 8.0000000e-01 2.6000000e+00 8.0000000e-01 1.6000000e+00 1.9000000e+00 7.0000000e-01 8.0000000e-01 1.5000000e+00 1.7000000e+00 2.0000000e+00 2.3000000e+00 1.5000000e+00 1.0000000e+00 1.5000000e+00 2.1000000e+00 1.5000000e+00 1.4000000e+00 7.0000000e-01 1.3000000e+00 1.5000000e+00 1.3000000e+00 1.0000000e+00 1.8000000e+00 1.6000000e+00 1.1000000e+00 9.0000000e-01 1.1000000e+00 1.3000000e+00 1.0000000e+00 4.0000000e-01 6.0000000e-01 3.0000000e-01 7.0000000e-01 2.0000000e-01 5.0000000e-01 4.0000000e-01 7.0000000e-01 1.0000000e+00 3.0000000e-01 2.0000000e+00 1.1000000e+00 1.9000000e+00 1.6000000e+00 1.8000000e+00 2.6000000e+00 6.0000000e-01 2.3000000e+00 1.8000000e+00 2.1000000e+00 1.1000000e+00 1.3000000e+00 1.5000000e+00 1.0000000e+00 1.1000000e+00 1.3000000e+00 1.5000000e+00 2.7000000e+00 2.9000000e+00 1.0000000e+00 1.7000000e+00 9.0000000e-01 2.7000000e+00 9.0000000e-01 1.7000000e+00 2.0000000e+00 8.0000000e-01 9.0000000e-01 1.6000000e+00 1.8000000e+00 2.1000000e+00 2.4000000e+00 1.6000000e+00 1.1000000e+00 1.6000000e+00 2.2000000e+00 1.6000000e+00 1.5000000e+00 8.0000000e-01 1.4000000e+00 1.6000000e+00 1.4000000e+00 1.1000000e+00 1.9000000e+00 1.7000000e+00 1.2000000e+00 1.0000000e+00 1.2000000e+00 1.4000000e+00 1.1000000e+00 6.0000000e-01 4.0000000e-01 1.1000000e+00 2.0000000e-01 4.0000000e-01 3.0000000e-01 7.0000000e-01 1.4000000e+00 3.0000000e-01 1.6000000e+00 7.0000000e-01 1.6000000e+00 1.2000000e+00 1.4000000e+00 2.2000000e+00 6.0000000e-01 1.9000000e+00 1.4000000e+00 1.7000000e+00 1.0000000e+00 9.0000000e-01 1.3000000e+00 8.0000000e-01 1.2000000e+00 1.1000000e+00 1.1000000e+00 2.3000000e+00 2.5000000e+00 6.0000000e-01 1.4000000e+00 8.0000000e-01 2.3000000e+00 8.0000000e-01 1.3000000e+00 1.7000000e+00 7.0000000e-01 6.0000000e-01 1.2000000e+00 1.7000000e+00 1.9000000e+00 2.4000000e+00 1.2000000e+00 8.0000000e-01 1.2000000e+00 2.2000000e+00 1.2000000e+00 1.1000000e+00 6.0000000e-01 1.4000000e+00 1.2000000e+00 1.4000000e+00 7.0000000e-01 1.5000000e+00 1.3000000e+00 1.2000000e+00 8.0000000e-01 1.0000000e+00 1.1000000e+00 7.0000000e-01 6.0000000e-01 1.3000000e+00 5.0000000e-01 4.0000000e-01 4.0000000e-01 3.0000000e-01 1.6000000e+00 5.0000000e-01 1.4000000e+00 5.0000000e-01 1.3000000e+00 1.0000000e+00 1.2000000e+00 2.0000000e+00 1.2000000e+00 1.7000000e+00 1.2000000e+00 1.5000000e+00 6.0000000e-01 7.0000000e-01 9.0000000e-01 6.0000000e-01 1.0000000e+00 9.0000000e-01 9.0000000e-01 2.1000000e+00 2.3000000e+00 8.0000000e-01 1.1000000e+00 6.0000000e-01 2.1000000e+00 4.0000000e-01 1.1000000e+00 1.4000000e+00 4.0000000e-01 4.0000000e-01 1.0000000e+00 1.2000000e+00 1.5000000e+00 1.8000000e+00 1.0000000e+00 5.0000000e-01 1.0000000e+00 1.6000000e+00 1.0000000e+00 9.0000000e-01 4.0000000e-01 8.0000000e-01 1.0000000e+00 9.0000000e-01 5.0000000e-01 1.3000000e+00 1.1000000e+00 9.0000000e-01 5.0000000e-01 6.0000000e-01 9.0000000e-01 5.0000000e-01 8.0000000e-01 2.0000000e-01 4.0000000e-01 3.0000000e-01 4.0000000e-01 1.0000000e+00 2.0000000e-01 2.0000000e+00 1.1000000e+00 1.9000000e+00 1.6000000e+00 1.8000000e+00 2.6000000e+00 9.0000000e-01 2.3000000e+00 1.8000000e+00 2.1000000e+00 1.1000000e+00 1.3000000e+00 1.5000000e+00 1.0000000e+00 1.2000000e+00 1.3000000e+00 1.5000000e+00 2.7000000e+00 2.9000000e+00 1.0000000e+00 1.7000000e+00 9.0000000e-01 2.7000000e+00 9.0000000e-01 1.7000000e+00 2.0000000e+00 8.0000000e-01 9.0000000e-01 1.6000000e+00 1.8000000e+00 2.1000000e+00 2.4000000e+00 1.6000000e+00 1.1000000e+00 1.6000000e+00 2.1000000e+00 1.6000000e+00 1.5000000e+00 8.0000000e-01 1.4000000e+00 1.6000000e+00 1.1000000e+00 1.1000000e+00 1.9000000e+00 1.7000000e+00 1.2000000e+00 1.0000000e+00 1.2000000e+00 1.4000000e+00 1.1000000e+00 9.0000000e-01 9.0000000e-01 9.0000000e-01 1.2000000e+00 3.0000000e-01 8.0000000e-01 2.7000000e+00 1.8000000e+00 2.6000000e+00 2.3000000e+00 2.5000000e+00 3.3000000e+00 1.2000000e+00 3.0000000e+00 2.5000000e+00 2.8000000e+00 1.8000000e+00 2.0000000e+00 2.2000000e+00 1.7000000e+00 1.8000000e+00 2.0000000e+00 2.2000000e+00 3.4000000e+00 3.6000000e+00 1.7000000e+00 2.4000000e+00 1.6000000e+00 3.4000000e+00 1.6000000e+00 2.4000000e+00 2.7000000e+00 1.5000000e+00 1.6000000e+00 2.3000000e+00 2.5000000e+00 2.8000000e+00 3.1000000e+00 2.3000000e+00 1.8000000e+00 2.3000000e+00 2.8000000e+00 2.3000000e+00 2.2000000e+00 1.5000000e+00 2.1000000e+00 2.3000000e+00 1.9000000e+00 1.8000000e+00 2.6000000e+00 2.4000000e+00 1.9000000e+00 1.7000000e+00 1.9000000e+00 2.1000000e+00 1.8000000e+00 3.0000000e-01 2.0000000e-01 6.0000000e-01 1.2000000e+00 1.0000000e-01 1.8000000e+00 9.0000000e-01 1.7000000e+00 1.4000000e+00 1.6000000e+00 2.4000000e+00 7.0000000e-01 2.1000000e+00 1.6000000e+00 1.9000000e+00 9.0000000e-01 1.1000000e+00 1.3000000e+00 8.0000000e-01 1.1000000e+00 1.1000000e+00 1.3000000e+00 2.5000000e+00 2.7000000e+00 8.0000000e-01 1.5000000e+00 7.0000000e-01 2.5000000e+00 7.0000000e-01 1.5000000e+00 1.8000000e+00 6.0000000e-01 7.0000000e-01 1.4000000e+00 1.6000000e+00 1.9000000e+00 2.3000000e+00 1.4000000e+00 9.0000000e-01 1.4000000e+00 2.1000000e+00 1.4000000e+00 1.3000000e+00 6.0000000e-01 1.3000000e+00 1.4000000e+00 1.3000000e+00 9.0000000e-01 1.7000000e+00 1.5000000e+00 1.1000000e+00 8.0000000e-01 1.0000000e+00 1.2000000e+00 9.0000000e-01 1.0000000e-01 5.0000000e-01 1.2000000e+00 2.0000000e-01 1.8000000e+00 9.0000000e-01 1.7000000e+00 1.4000000e+00 1.6000000e+00 2.4000000e+00 8.0000000e-01 2.1000000e+00 1.6000000e+00 1.9000000e+00 9.0000000e-01 1.1000000e+00 1.3000000e+00 8.0000000e-01 1.2000000e+00 1.1000000e+00 1.3000000e+00 2.5000000e+00 2.7000000e+00 8.0000000e-01 1.5000000e+00 8.0000000e-01 2.5000000e+00 7.0000000e-01 1.5000000e+00 1.8000000e+00 6.0000000e-01 7.0000000e-01 1.4000000e+00 1.6000000e+00 1.9000000e+00 2.2000000e+00 1.4000000e+00 9.0000000e-01 1.4000000e+00 2.0000000e+00 1.4000000e+00 1.3000000e+00 6.0000000e-01 1.2000000e+00 1.4000000e+00 1.2000000e+00 9.0000000e-01 1.7000000e+00 1.5000000e+00 1.1000000e+00 8.0000000e-01 1.0000000e+00 1.2000000e+00 9.0000000e-01 5.0000000e-01 1.2000000e+00 1.0000000e-01 1.8000000e+00 9.0000000e-01 1.7000000e+00 1.4000000e+00 1.6000000e+00 2.4000000e+00 8.0000000e-01 2.1000000e+00 1.6000000e+00 1.9000000e+00 9.0000000e-01 1.1000000e+00 1.3000000e+00 8.0000000e-01 1.1000000e+00 1.1000000e+00 1.3000000e+00 2.5000000e+00 2.7000000e+00 8.0000000e-01 1.5000000e+00 7.0000000e-01 2.5000000e+00 7.0000000e-01 1.5000000e+00 1.8000000e+00 6.0000000e-01 7.0000000e-01 1.4000000e+00 1.6000000e+00 1.9000000e+00 2.2000000e+00 1.4000000e+00 9.0000000e-01 1.4000000e+00 2.0000000e+00 1.4000000e+00 1.3000000e+00 6.0000000e-01 1.2000000e+00 1.4000000e+00 1.2000000e+00 9.0000000e-01 1.7000000e+00 1.5000000e+00 1.0000000e+00 8.0000000e-01 1.0000000e+00 1.2000000e+00 9.0000000e-01 1.3000000e+00 5.0000000e-01 1.7000000e+00 8.0000000e-01 1.6000000e+00 1.3000000e+00 1.5000000e+00 2.3000000e+00 1.3000000e+00 2.0000000e+00 1.5000000e+00 1.8000000e+00 8.0000000e-01 1.0000000e+00 1.2000000e+00 7.0000000e-01 1.1000000e+00 1.0000000e+00 1.2000000e+00 2.4000000e+00 2.6000000e+00 7.0000000e-01 1.4000000e+00 7.0000000e-01 2.4000000e+00 6.0000000e-01 1.4000000e+00 1.7000000e+00 5.0000000e-01 6.0000000e-01 1.3000000e+00 1.5000000e+00 1.8000000e+00 2.1000000e+00 1.3000000e+00 8.0000000e-01 1.3000000e+00 1.8000000e+00 1.3000000e+00 1.2000000e+00 5.0000000e-01 1.1000000e+00 1.3000000e+00 1.0000000e+00 8.0000000e-01 1.6000000e+00 1.4000000e+00 1.0000000e+00 7.0000000e-01 9.0000000e-01 1.1000000e+00 8.0000000e-01 1.1000000e+00 3.0000000e+00 2.1000000e+00 2.9000000e+00 2.6000000e+00 2.8000000e+00 3.6000000e+00 1.5000000e+00 3.3000000e+00 2.8000000e+00 3.1000000e+00 2.1000000e+00 2.3000000e+00 2.5000000e+00 2.0000000e+00 2.1000000e+00 2.3000000e+00 2.5000000e+00 3.7000000e+00 3.9000000e+00 2.0000000e+00 2.7000000e+00 1.9000000e+00 3.7000000e+00 1.9000000e+00 2.7000000e+00 3.0000000e+00 1.8000000e+00 1.9000000e+00 2.6000000e+00 2.8000000e+00 3.1000000e+00 3.4000000e+00 2.6000000e+00 2.1000000e+00 2.6000000e+00 3.1000000e+00 2.6000000e+00 2.5000000e+00 1.8000000e+00 2.4000000e+00 2.6000000e+00 2.1000000e+00 2.1000000e+00 2.9000000e+00 2.7000000e+00 2.2000000e+00 2.0000000e+00 2.2000000e+00 2.4000000e+00 2.1000000e+00 1.9000000e+00 1.0000000e+00 1.8000000e+00 1.5000000e+00 1.7000000e+00 2.5000000e+00 8.0000000e-01 2.2000000e+00 1.7000000e+00 2.0000000e+00 1.0000000e+00 1.2000000e+00 1.4000000e+00 9.0000000e-01 1.1000000e+00 1.2000000e+00 1.4000000e+00 2.6000000e+00 2.8000000e+00 9.0000000e-01 1.6000000e+00 8.0000000e-01 2.6000000e+00 8.0000000e-01 1.6000000e+00 1.9000000e+00 7.0000000e-01 8.0000000e-01 1.5000000e+00 1.7000000e+00 2.0000000e+00 2.3000000e+00 1.5000000e+00 1.0000000e+00 1.5000000e+00 2.0000000e+00 1.5000000e+00 1.4000000e+00 7.0000000e-01 1.3000000e+00 1.5000000e+00 1.2000000e+00 1.0000000e+00 1.8000000e+00 1.6000000e+00 1.1000000e+00 9.0000000e-01 1.1000000e+00 1.3000000e+00 1.0000000e+00 9.0000000e-01 8.0000000e-01 7.0000000e-01 3.0000000e-01 1.3000000e+00 1.5000000e+00 1.0000000e+00 8.0000000e-01 9.0000000e-01 9.0000000e-01 7.0000000e-01 5.0000000e-01 1.0000000e+00 9.0000000e-01 7.0000000e-01 7.0000000e-01 1.4000000e+00 1.4000000e+00 1.1000000e+00 6.0000000e-01 1.1000000e+00 1.4000000e+00 1.1000000e+00 4.0000000e-01 9.0000000e-01 1.2000000e+00 1.1000000e+00 5.0000000e-01 9.0000000e-01 1.1000000e+00 1.6000000e+00 5.0000000e-01 1.0000000e+00 1.1000000e+00 1.4000000e+00 4.0000000e-01 7.0000000e-01 1.2000000e+00 6.0000000e-01 4.0000000e-01 9.0000000e-01 9.0000000e-01 5.0000000e-01 4.0000000e-01 8.0000000e-01 1.0000000e+00 8.0000000e-01 6.0000000e-01 9.0000000e-01 1.3000000e+00 5.0000000e-01 7.0000000e-01 1.8000000e+00 9.0000000e-01 1.5000000e+00 9.0000000e-01 1.4000000e+00 7.0000000e-01 6.0000000e-01 1.0000000e+00 2.0000000e-01 5.0000000e-01 6.0000000e-01 7.0000000e-01 1.9000000e+00 1.9000000e+00 5.0000000e-01 1.1000000e+00 2.0000000e-01 1.9000000e+00 5.0000000e-01 9.0000000e-01 1.4000000e+00 4.0000000e-01 3.0000000e-01 6.0000000e-01 1.4000000e+00 1.6000000e+00 2.1000000e+00 6.0000000e-01 5.0000000e-01 5.0000000e-01 1.9000000e+00 7.0000000e-01 6.0000000e-01 3.0000000e-01 1.1000000e+00 9.0000000e-01 1.1000000e+00 0.0000000e+00 1.0000000e+00 9.0000000e-01 9.0000000e-01 5.0000000e-01 7.0000000e-01 7.0000000e-01 3.0000000e-01 8.0000000e-01 6.0000000e-01 7.0000000e-01 2.2000000e+00 4.0000000e-01 5.0000000e-01 6.0000000e-01 8.0000000e-01 7.0000000e-01 4.0000000e-01 1.4000000e+00 1.3000000e+00 7.0000000e-01 6.0000000e-01 8.0000000e-01 1.0000000e+00 1.1000000e+00 2.0000000e-01 1.5000000e+00 8.0000000e-01 1.0000000e+00 4.0000000e-01 3.0000000e-01 1.1000000e+00 1.0000000e+00 7.0000000e-01 5.0000000e-01 3.0000000e-01 8.0000000e-01 7.0000000e-01 8.0000000e-01 1.0000000e+00 6.0000000e-01 8.0000000e-01 7.0000000e-01 1.1000000e+00 5.0000000e-01 4.0000000e-01 8.0000000e-01 1.3000000e+00 3.0000000e-01 4.0000000e-01 7.0000000e-01 9.0000000e-01 7.0000000e-01 9.0000000e-01 1.2000000e+00 4.0000000e-01 1.3000000e+00 1.4000000e+00 1.0000000e+00 4.0000000e-01 9.0000000e-01 5.0000000e-01 3.0000000e-01 5.0000000e-01 6.0000000e-01 6.0000000e-01 5.0000000e-01 2.0000000e-01 1.4000000e+00 1.4000000e+00 7.0000000e-01 6.0000000e-01 7.0000000e-01 1.4000000e+00 7.0000000e-01 4.0000000e-01 9.0000000e-01 8.0000000e-01 7.0000000e-01 3.0000000e-01 9.0000000e-01 1.1000000e+00 1.6000000e+00 4.0000000e-01 5.0000000e-01 4.0000000e-01 1.4000000e+00 6.0000000e-01 2.0000000e-01 8.0000000e-01 6.0000000e-01 6.0000000e-01 6.0000000e-01 5.0000000e-01 5.0000000e-01 7.0000000e-01 5.0000000e-01 6.0000000e-01 4.0000000e-01 5.0000000e-01 5.0000000e-01 1.1000000e+00 1.6000000e+00 8.0000000e-01 5.0000000e-01 7.0000000e-01 7.0000000e-01 5.0000000e-01 3.0000000e-01 8.0000000e-01 7.0000000e-01 5.0000000e-01 4.0000000e-01 1.2000000e+00 1.2000000e+00 8.0000000e-01 4.0000000e-01 9.0000000e-01 1.2000000e+00 9.0000000e-01 3.0000000e-01 7.0000000e-01 1.0000000e+00 9.0000000e-01 2.0000000e-01 7.0000000e-01 9.0000000e-01 1.4000000e+00 2.0000000e-01 7.0000000e-01 8.0000000e-01 1.2000000e+00 4.0000000e-01 4.0000000e-01 1.0000000e+00 4.0000000e-01 2.0000000e-01 7.0000000e-01 7.0000000e-01 3.0000000e-01 3.0000000e-01 6.0000000e-01 8.0000000e-01 6.0000000e-01 4.0000000e-01 7.0000000e-01 2.7000000e+00 3.0000000e-01 9.0000000e-01 6.0000000e-01 1.5000000e+00 1.3000000e+00 1.1000000e+00 1.9000000e+00 1.8000000e+00 1.3000000e+00 1.1000000e+00 8.0000000e-01 4.0000000e-01 1.6000000e+00 9.0000000e-01 2.0000000e+00 2.0000000e-01 1.7000000e+00 9.0000000e-01 6.0000000e-01 1.8000000e+00 1.7000000e+00 1.2000000e+00 8.0000000e-01 5.0000000e-01 8.0000000e-01 1.2000000e+00 1.5000000e+00 1.5000000e+00 5.0000000e-01 1.3000000e+00 1.2000000e+00 1.8000000e+00 1.2000000e+00 1.0000000e+00 1.5000000e+00 1.8000000e+00 8.0000000e-01 9.0000000e-01 1.4000000e+00 1.6000000e+00 1.4000000e+00 1.4000000e+00 1.7000000e+00 2.4000000e+00 1.8000000e+00 2.3000000e+00 1.6000000e+00 1.5000000e+00 1.9000000e+00 8.0000000e-01 9.0000000e-01 1.5000000e+00 1.6000000e+00 2.8000000e+00 2.8000000e+00 1.1000000e+00 2.0000000e+00 7.0000000e-01 2.8000000e+00 1.4000000e+00 1.8000000e+00 2.3000000e+00 1.3000000e+00 1.2000000e+00 1.5000000e+00 2.3000000e+00 2.5000000e+00 3.0000000e+00 1.5000000e+00 1.4000000e+00 1.2000000e+00 2.8000000e+00 1.4000000e+00 1.5000000e+00 1.1000000e+00 2.0000000e+00 1.8000000e+00 2.0000000e+00 9.0000000e-01 1.9000000e+00 1.8000000e+00 1.8000000e+00 1.4000000e+00 1.6000000e+00 1.3000000e+00 1.0000000e+00 6.0000000e-01 7.0000000e-01 1.2000000e+00 1.0000000e+00 8.0000000e-01 1.6000000e+00 1.5000000e+00 1.0000000e+00 8.0000000e-01 9.0000000e-01 6.0000000e-01 1.3000000e+00 6.0000000e-01 1.7000000e+00 4.0000000e-01 1.4000000e+00 6.0000000e-01 3.0000000e-01 1.5000000e+00 1.4000000e+00 9.0000000e-01 5.0000000e-01 2.0000000e-01 9.0000000e-01 9.0000000e-01 1.2000000e+00 1.2000000e+00 5.0000000e-01 1.0000000e+00 9.0000000e-01 1.5000000e+00 9.0000000e-01 7.0000000e-01 1.2000000e+00 1.5000000e+00 5.0000000e-01 7.0000000e-01 1.1000000e+00 1.3000000e+00 1.1000000e+00 1.1000000e+00 1.4000000e+00 1.1000000e+00 7.0000000e-01 5.0000000e-01 5.0000000e-01 1.0000000e+00 9.0000000e-01 7.0000000e-01 5.0000000e-01 1.3000000e+00 1.1000000e+00 8.0000000e-01 7.0000000e-01 1.1000000e+00 1.0000000e+00 9.0000000e-01 8.0000000e-01 7.0000000e-01 1.0000000e+00 9.0000000e-01 3.0000000e-01 5.0000000e-01 7.0000000e-01 1.3000000e+00 4.0000000e-01 7.0000000e-01 6.0000000e-01 1.0000000e+00 9.0000000e-01 6.0000000e-01 1.0000000e+00 6.0000000e-01 6.0000000e-01 7.0000000e-01 9.0000000e-01 7.0000000e-01 8.0000000e-01 6.0000000e-01 8.0000000e-01 6.0000000e-01 9.0000000e-01 8.0000000e-01 1.0000000e+00 9.0000000e-01 6.0000000e-01 1.5000000e+00 1.4000000e+00 8.0000000e-01 7.0000000e-01 6.0000000e-01 1.0000000e+00 1.4000000e+00 4.0000000e-01 1.6000000e+00 8.0000000e-01 1.2000000e+00 5.0000000e-01 7.0000000e-01 1.3000000e+00 1.2000000e+00 8.0000000e-01 9.0000000e-01 8.0000000e-01 7.0000000e-01 8.0000000e-01 1.0000000e+00 1.1000000e+00 6.0000000e-01 9.0000000e-01 8.0000000e-01 1.3000000e+00 7.0000000e-01 5.0000000e-01 1.0000000e+00 1.4000000e+00 4.0000000e-01 5.0000000e-01 9.0000000e-01 1.1000000e+00 9.0000000e-01 1.0000000e+00 1.3000000e+00 5.0000000e-01 4.0000000e-01 8.0000000e-01 7.0000000e-01 3.0000000e-01 4.0000000e-01 1.6000000e+00 1.8000000e+00 1.0000000e+00 6.0000000e-01 9.0000000e-01 1.6000000e+00 5.0000000e-01 6.0000000e-01 9.0000000e-01 4.0000000e-01 4.0000000e-01 5.0000000e-01 7.0000000e-01 1.0000000e+00 1.4000000e+00 5.0000000e-01 5.0000000e-01 6.0000000e-01 1.2000000e+00 5.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 7.0000000e-01 8.0000000e-01 6.0000000e-01 3.0000000e-01 7.0000000e-01 2.0000000e-01 3.0000000e-01 6.0000000e-01 4.0000000e-01 7.0000000e-01 6.0000000e-01 5.0000000e-01 3.0000000e-01 1.4000000e+00 1.6000000e+00 5.0000000e-01 5.0000000e-01 8.0000000e-01 1.4000000e+00 4.0000000e-01 6.0000000e-01 8.0000000e-01 5.0000000e-01 4.0000000e-01 3.0000000e-01 8.0000000e-01 1.0000000e+00 1.5000000e+00 3.0000000e-01 4.0000000e-01 5.0000000e-01 1.3000000e+00 7.0000000e-01 4.0000000e-01 5.0000000e-01 5.0000000e-01 5.0000000e-01 5.0000000e-01 6.0000000e-01 6.0000000e-01 6.0000000e-01 4.0000000e-01 3.0000000e-01 3.0000000e-01 7.0000000e-01 5.0000000e-01 1.1000000e+00 1.0000000e+00 4.0000000e-01 3.0000000e-01 1.2000000e+00 1.4000000e+00 8.0000000e-01 2.0000000e-01 1.2000000e+00 1.2000000e+00 6.0000000e-01 3.0000000e-01 5.0000000e-01 7.0000000e-01 7.0000000e-01 4.0000000e-01 5.0000000e-01 6.0000000e-01 1.1000000e+00 4.0000000e-01 6.0000000e-01 7.0000000e-01 9.0000000e-01 5.0000000e-01 4.0000000e-01 8.0000000e-01 1.0000000e-01 3.0000000e-01 4.0000000e-01 1.0000000e+00 4.0000000e-01 4.0000000e-01 3.0000000e-01 5.0000000e-01 3.0000000e-01 6.0000000e-01 9.0000000e-01 4.0000000e-01 7.0000000e-01 8.0000000e-01 2.0000000e+00 2.0000000e+00 5.0000000e-01 1.2000000e+00 3.0000000e-01 2.0000000e+00 6.0000000e-01 1.0000000e+00 1.5000000e+00 5.0000000e-01 5.0000000e-01 7.0000000e-01 1.5000000e+00 1.7000000e+00 2.2000000e+00 7.0000000e-01 6.0000000e-01 6.0000000e-01 2.0000000e+00 9.0000000e-01 7.0000000e-01 5.0000000e-01 1.2000000e+00 1.0000000e+00 1.2000000e+00 2.0000000e-01 1.1000000e+00 1.0000000e+00 1.0000000e+00 6.0000000e-01 8.0000000e-01 9.0000000e-01 5.0000000e-01 6.0000000e-01 7.0000000e-01 1.9000000e+00 1.9000000e+00 9.0000000e-01 1.1000000e+00 4.0000000e-01 1.9000000e+00 6.0000000e-01 9.0000000e-01 1.4000000e+00 6.0000000e-01 6.0000000e-01 6.0000000e-01 1.4000000e+00 1.6000000e+00 2.1000000e+00 6.0000000e-01 9.0000000e-01 1.0000000e+00 1.9000000e+00 6.0000000e-01 6.0000000e-01 6.0000000e-01 1.1000000e+00 9.0000000e-01 1.1000000e+00 5.0000000e-01 1.0000000e+00 9.0000000e-01 9.0000000e-01 5.0000000e-01 7.0000000e-01 6.0000000e-01 6.0000000e-01 5.0000000e-01 1.4000000e+00 1.6000000e+00 1.0000000e+00 5.0000000e-01 8.0000000e-01 1.4000000e+00 5.0000000e-01 4.0000000e-01 8.0000000e-01 5.0000000e-01 5.0000000e-01 4.0000000e-01 8.0000000e-01 1.0000000e+00 1.5000000e+00 4.0000000e-01 8.0000000e-01 9.0000000e-01 1.3000000e+00 3.0000000e-01 5.0000000e-01 5.0000000e-01 5.0000000e-01 3.0000000e-01 5.0000000e-01 6.0000000e-01 6.0000000e-01 4.0000000e-01 3.0000000e-01 7.0000000e-01 3.0000000e-01 2.0000000e-01 5.0000000e-01 1.2000000e+00 1.4000000e+00 8.0000000e-01 5.0000000e-01 9.0000000e-01 1.2000000e+00 6.0000000e-01 3.0000000e-01 7.0000000e-01 7.0000000e-01 6.0000000e-01 3.0000000e-01 7.0000000e-01 9.0000000e-01 1.4000000e+00 4.0000000e-01 4.0000000e-01 4.0000000e-01 1.2000000e+00 6.0000000e-01 1.0000000e-01 7.0000000e-01 4.0000000e-01 6.0000000e-01 5.0000000e-01 7.0000000e-01 5.0000000e-01 7.0000000e-01 5.0000000e-01 5.0000000e-01 3.0000000e-01 5.0000000e-01 6.0000000e-01 1.2000000e+00 1.7000000e+00 1.0000000e+00 2.1000000e+00 1.0000000e+00 1.8000000e+00 1.0000000e+00 7.0000000e-01 1.9000000e+00 1.8000000e+00 1.3000000e+00 9.0000000e-01 1.0000000e+00 3.0000000e-01 1.3000000e+00 1.6000000e+00 1.6000000e+00 8.0000000e-01 1.4000000e+00 1.3000000e+00 1.9000000e+00 1.3000000e+00 1.1000000e+00 1.6000000e+00 1.9000000e+00 9.0000000e-01 1.0000000e+00 1.5000000e+00 1.7000000e+00 1.5000000e+00 1.5000000e+00 1.8000000e+00 1.9000000e+00 1.2000000e+00 2.1000000e+00 3.0000000e-01 2.0000000e+00 1.2000000e+00 9.0000000e-01 2.1000000e+00 2.0000000e+00 1.3000000e+00 1.1000000e+00 8.0000000e-01 1.2000000e+00 1.3000000e+00 1.8000000e+00 1.6000000e+00 8.0000000e-01 1.4000000e+00 1.4000000e+00 2.1000000e+00 1.5000000e+00 1.3000000e+00 1.8000000e+00 1.9000000e+00 1.0000000e+00 1.2000000e+00 1.7000000e+00 1.9000000e+00 1.7000000e+00 1.5000000e+00 1.8000000e+00 1.0000000e+00 6.0000000e-01 1.7000000e+00 5.0000000e-01 1.1000000e+00 1.2000000e+00 6.0000000e-01 8.0000000e-01 6.0000000e-01 1.2000000e+00 1.4000000e+00 1.9000000e+00 7.0000000e-01 6.0000000e-01 6.0000000e-01 1.7000000e+00 1.2000000e+00 9.0000000e-01 8.0000000e-01 9.0000000e-01 9.0000000e-01 9.0000000e-01 5.0000000e-01 1.0000000e+00 1.1000000e+00 8.0000000e-01 4.0000000e-01 8.0000000e-01 1.2000000e+00 8.0000000e-01 1.3000000e+00 1.0000000e+00 8.0000000e-01 2.0000000e-01 5.0000000e-01 9.0000000e-01 8.0000000e-01 5.0000000e-01 7.0000000e-01 5.0000000e-01 1.0000000e+00 5.0000000e-01 8.0000000e-01 9.0000000e-01 8.0000000e-01 6.0000000e-01 5.0000000e-01 9.0000000e-01 3.0000000e-01 2.0000000e-01 6.0000000e-01 1.1000000e+00 2.0000000e-01 2.0000000e-01 5.0000000e-01 7.0000000e-01 5.0000000e-01 7.0000000e-01 1.0000000e+00 2.1000000e+00 7.0000000e-01 1.1000000e+00 1.6000000e+00 6.0000000e-01 5.0000000e-01 8.0000000e-01 1.6000000e+00 1.8000000e+00 2.3000000e+00 8.0000000e-01 7.0000000e-01 7.0000000e-01 2.1000000e+00 7.0000000e-01 8.0000000e-01 4.0000000e-01 1.3000000e+00 1.1000000e+00 1.3000000e+00 2.0000000e-01 1.2000000e+00 1.1000000e+00 1.1000000e+00 7.0000000e-01 9.0000000e-01 6.0000000e-01 3.0000000e-01 1.8000000e+00 1.0000000e+00 7.0000000e-01 1.9000000e+00 1.8000000e+00 1.3000000e+00 9.0000000e-01 6.0000000e-01 1.0000000e+00 1.3000000e+00 1.6000000e+00 1.6000000e+00 6.0000000e-01 1.4000000e+00 1.3000000e+00 1.9000000e+00 1.3000000e+00 1.1000000e+00 1.6000000e+00 1.9000000e+00 9.0000000e-01 1.0000000e+00 1.5000000e+00 1.7000000e+00 1.5000000e+00 1.5000000e+00 1.8000000e+00 8.0000000e-01 1.1000000e+00 1.0000000e-01 3.0000000e-01 7.0000000e-01 9.0000000e-01 1.2000000e+00 1.6000000e+00 7.0000000e-01 3.0000000e-01 7.0000000e-01 1.4000000e+00 7.0000000e-01 6.0000000e-01 3.0000000e-01 6.0000000e-01 7.0000000e-01 6.0000000e-01 5.0000000e-01 1.0000000e+00 8.0000000e-01 5.0000000e-01 2.0000000e-01 3.0000000e-01 7.0000000e-01 4.0000000e-01 5.0000000e-01 9.0000000e-01 8.0000000e-01 5.0000000e-01 5.0000000e-01 7.0000000e-01 1.2000000e+00 5.0000000e-01 6.0000000e-01 7.0000000e-01 1.0000000e+00 4.0000000e-01 3.0000000e-01 9.0000000e-01 3.0000000e-01 3.0000000e-01 6.0000000e-01 9.0000000e-01 2.0000000e-01 4.0000000e-01 5.0000000e-01 8.0000000e-01 5.0000000e-01 5.0000000e-01 8.0000000e-01 1.2000000e+00 1.1000000e+00 8.0000000e-01 2.0000000e-01 4.0000000e-01 7.0000000e-01 8.0000000e-01 9.0000000e-01 1.1000000e+00 5.0000000e-01 9.0000000e-01 8.0000000e-01 1.2000000e+00 6.0000000e-01 6.0000000e-01 9.0000000e-01 1.4000000e+00 5.0000000e-01 7.0000000e-01 8.0000000e-01 1.0000000e+00 8.0000000e-01 1.0000000e+00 1.3000000e+00 2.0000000e-01 8.0000000e-01 1.0000000e+00 1.3000000e+00 1.7000000e+00 8.0000000e-01 3.0000000e-01 8.0000000e-01 1.5000000e+00 8.0000000e-01 7.0000000e-01 2.0000000e-01 7.0000000e-01 8.0000000e-01 7.0000000e-01 4.0000000e-01 1.1000000e+00 9.0000000e-01 5.0000000e-01 3.0000000e-01 4.0000000e-01 6.0000000e-01 3.0000000e-01 7.0000000e-01 1.1000000e+00 1.3000000e+00 1.8000000e+00 7.0000000e-01 3.0000000e-01 7.0000000e-01 1.6000000e+00 7.0000000e-01 6.0000000e-01 1.0000000e-01 8.0000000e-01 7.0000000e-01 8.0000000e-01 3.0000000e-01 1.0000000e+00 8.0000000e-01 6.0000000e-01 5.0000000e-01 4.0000000e-01 5.0000000e-01 2.0000000e-01 8.0000000e-01 1.0000000e+00 1.5000000e+00 1.0000000e-01 6.0000000e-01 7.0000000e-01 1.3000000e+00 6.0000000e-01 3.0000000e-01 8.0000000e-01 5.0000000e-01 3.0000000e-01 5.0000000e-01 6.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 6.0000000e-01 4.0000000e-01 6.0000000e-01 5.0000000e-01 3.0000000e-01 8.0000000e-01 8.0000000e-01 9.0000000e-01 1.1000000e+00 7.0000000e-01 9.0000000e-01 8.0000000e-01 1.2000000e+00 5.0000000e-01 8.0000000e-01 7.0000000e-01 1.4000000e+00 7.0000000e-01 9.0000000e-01 7.0000000e-01 9.0000000e-01 7.0000000e-01 1.0000000e+00 1.3000000e+00 1.0000000e+00 1.0000000e+00 1.1000000e+00 1.3000000e+00 4.0000000e-01 1.1000000e+00 1.0000000e+00 1.4000000e+00 7.0000000e-01 7.0000000e-01 1.0000000e+00 1.6000000e+00 6.0000000e-01 7.0000000e-01 9.0000000e-01 1.1000000e+00 9.0000000e-01 1.2000000e+00 1.5000000e+00 1.5000000e+00 1.6000000e+00 1.8000000e+00 8.0000000e-01 1.6000000e+00 1.5000000e+00 1.9000000e+00 1.0000000e+00 1.2000000e+00 1.3000000e+00 2.1000000e+00 1.1000000e+00 1.2000000e+00 1.2000000e+00 1.6000000e+00 1.4000000e+00 1.7000000e+00 2.0000000e+00 7.0000000e-01 8.0000000e-01 1.3000000e+00 6.0000000e-01 4.0000000e-01 8.0000000e-01 5.0000000e-01 3.0000000e-01 5.0000000e-01 6.0000000e-01 4.0000000e-01 5.0000000e-01 4.0000000e-01 6.0000000e-01 4.0000000e-01 6.0000000e-01 5.0000000e-01 5.0000000e-01 1.4000000e+00 9.0000000e-01 4.0000000e-01 3.0000000e-01 6.0000000e-01 9.0000000e-01 8.0000000e-01 5.0000000e-01 8.0000000e-01 1.0000000e+00 8.0000000e-01 4.0000000e-01 5.0000000e-01 8.0000000e-01 4.0000000e-01 1.6000000e+00 1.0000000e+00 5.0000000e-01 8.0000000e-01 8.0000000e-01 1.0000000e+00 9.0000000e-01 5.0000000e-01 9.0000000e-01 1.1000000e+00 9.0000000e-01 6.0000000e-01 6.0000000e-01 9.0000000e-01 5.0000000e-01 1.4000000e+00 1.3000000e+00 1.7000000e+00 8.0000000e-01 1.0000000e+00 1.0000000e+00 1.9000000e+00 9.0000000e-01 1.0000000e+00 1.0000000e+00 1.4000000e+00 1.2000000e+00 1.5000000e+00 1.8000000e+00 6.0000000e-01 8.0000000e-01 6.0000000e-01 4.0000000e-01 6.0000000e-01 7.0000000e-01 5.0000000e-01 4.0000000e-01 4.0000000e-01 9.0000000e-01 4.0000000e-01 2.0000000e-01 6.0000000e-01 7.0000000e-01 5.0000000e-01 6.0000000e-01 5.0000000e-01 6.0000000e-01 5.0000000e-01 7.0000000e-01 5.0000000e-01 6.0000000e-01 3.0000000e-01 5.0000000e-01 5.0000000e-01 9.0000000e-01 8.0000000e-01 9.0000000e-01 3.0000000e-01 1.1000000e+00 9.0000000e-01 7.0000000e-01 5.0000000e-01 5.0000000e-01 6.0000000e-01 3.0000000e-01 3.0000000e-01 3.0000000e-01 1.1000000e+00 5.0000000e-01 4.0000000e-01 2.0000000e-01 6.0000000e-01 4.0000000e-01 7.0000000e-01 1.0000000e+00 5.0000000e-01 9.0000000e-01 3.0000000e-01 2.0000000e-01 4.0000000e-01 6.0000000e-01 4.0000000e-01 5.0000000e-01 8.0000000e-01 1.1000000e+00 8.0000000e-01 6.0000000e-01 2.0000000e-01 6.0000000e-01 4.0000000e-01 7.0000000e-01 1.0000000e+00 1.0000000e+00 9.0000000e-01 9.0000000e-01 5.0000000e-01 7.0000000e-01 7.0000000e-01 3.0000000e-01 2.0000000e-01 7.0000000e-01 9.0000000e-01 7.0000000e-01 6.0000000e-01 9.0000000e-01 5.0000000e-01 8.0000000e-01 5.0000000e-01 5.0000000e-01 8.0000000e-01 5.0000000e-01 3.0000000e-01 5.0000000e-01 8.0000000e-01 5.0000000e-01 9.0000000e-01 5.0000000e-01 4.0000000e-01 6.0000000e-01 5.0000000e-01 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-chebyshev-ml.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-chebyshev-ml.txt new file mode 100644 index 0000000000000000000000000000000000000000..786486295935319c03a60a349f03328c127935b9 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-chebyshev-ml.txt @@ -0,0 +1 @@ + 8.9084734e-01 9.3573853e-01 9.3507398e-01 9.6040691e-01 9.2918157e-01 9.6617342e-01 9.0430930e-01 9.5753424e-01 8.7106898e-01 9.2169905e-01 9.7401159e-01 8.9013416e-01 9.3956689e-01 9.0041896e-01 9.2588355e-01 9.3849417e-01 8.9713468e-01 9.1481804e-01 9.7500539e-01 9.0012586e-01 9.0962559e-01 8.5860091e-01 8.6981095e-01 8.9995771e-01 8.8070172e-01 9.1456657e-01 8.6711474e-01 9.2593917e-01 8.7560376e-01 8.5193121e-01 9.0898542e-01 8.7765302e-01 8.6555584e-01 8.6093485e-01 9.0447028e-01 8.7614405e-01 9.4803522e-01 8.4998062e-01 7.8398996e-01 8.9538612e-01 8.3902291e-01 9.9039470e-01 9.5480519e-01 8.9152195e-01 9.1623329e-01 7.9094921e-01 9.1777100e-01 9.8972335e-01 9.0429093e-01 8.7646362e-01 9.2136649e-01 9.7178177e-01 8.9610979e-01 9.4710327e-01 9.3612450e-01 9.0241499e-01 7.7992538e-01 8.7262126e-01 9.3325183e-01 8.5796531e-01 9.4267977e-01 6.7224167e-01 7.9568368e-01 8.6411267e-01 9.3311642e-01 9.0160114e-01 9.0698887e-01 8.5833256e-01 9.6902830e-01 9.5072298e-01 8.6808495e-01 9.7879599e-01 8.8060729e-01 8.2818573e-01 8.4366706e-01 8.4506700e-01 9.4532981e-01 9.1792306e-01 7.8917825e-01 9.8337805e-01 8.1751613e-01 9.3037855e-01 9.1618832e-01 8.6568874e-01 8.9751397e-01 8.7923710e-01 8.6814329e-01 9.0330164e-01 8.2426213e-01 9.4644643e-01 8.8431293e-01 8.8497426e-01 9.0633818e-01 9.5537161e-01 8.2167575e-01 8.7771053e-01 9.0681167e-01 8.7626143e-01 8.7463464e-01 9.8033940e-01 9.2920881e-01 9.5108549e-01 9.1287466e-01 8.0052218e-01 9.2409517e-01 8.8252650e-01 8.7873923e-01 9.2989402e-01 9.1985043e-01 9.6172646e-01 8.8223856e-01 9.4477822e-01 8.8310948e-01 9.4461306e-01 9.1875210e-01 9.1233363e-01 9.2124013e-01 9.5460897e-01 8.4640982e-01 9.0882657e-01 9.8169468e-01 9.7828355e-01 8.4150533e-01 8.6888923e-01 9.7138825e-01 8.7988144e-01 9.6720910e-01 8.9450147e-01 9.5331584e-01 8.8871809e-01 8.9736685e-01 8.6258146e-01 9.1331565e-01 9.0968870e-01 9.4833654e-01 9.0536967e-01 9.5099871e-01 8.0251958e-01 9.2526150e-01 9.8971957e-01 9.0340947e-01 9.4955892e-01 9.6838162e-01 8.7534901e-01 9.1178797e-01 9.2649154e-01 9.5260993e-01 9.3178143e-01 9.4943000e-01 8.7816171e-01 9.6506542e-01 8.3422958e-01 9.3443585e-01 9.3220084e-01 8.5706573e-01 8.4666325e-01 9.0474744e-01 9.1080644e-01 9.2406899e-01 8.7901768e-01 9.3265263e-01 9.5992829e-01 9.5696271e-01 9.1932272e-01 8.0937044e-01 9.0904917e-01 8.9516756e-01 9.4797906e-01 8.4159421e-01 9.6773901e-01 9.7099825e-01 9.6941820e-01 9.8174088e-01 9.7569951e-01 9.3655362e-01 8.4130333e-01 9.5994549e-01 8.4235414e-01 9.1429418e-01 9.3418117e-01 8.4600977e-01 8.8166496e-01 8.7594776e-01 8.8571112e-01 9.6308174e-01 9.5315927e-01 8.6997519e-01 8.9383032e-01 9.4686804e-01 9.4399596e-01 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-cityblock-ml-iris.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-cityblock-ml-iris.txt new file mode 100644 index 0000000000000000000000000000000000000000..6722928a4a4491c74d3fef5205276b532b15dcbf --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-cityblock-ml-iris.txt @@ -0,0 +1 @@ + 7.0000000e-01 8.0000000e-01 1.0000000e+00 2.0000000e-01 1.2000000e+00 7.0000000e-01 3.0000000e-01 1.3000000e+00 8.0000000e-01 6.0000000e-01 6.0000000e-01 9.0000000e-01 1.7000000e+00 1.4000000e+00 1.8000000e+00 1.0000000e+00 1.0000000e-01 1.3000000e+00 5.0000000e-01 7.0000000e-01 5.0000000e-01 1.0000000e+00 8.0000000e-01 9.0000000e-01 8.0000000e-01 6.0000000e-01 2.0000000e-01 2.0000000e-01 9.0000000e-01 9.0000000e-01 7.0000000e-01 9.0000000e-01 1.1000000e+00 8.0000000e-01 6.0000000e-01 5.0000000e-01 8.0000000e-01 1.3000000e+00 2.0000000e-01 3.0000000e-01 2.0000000e+00 1.1000000e+00 7.0000000e-01 1.0000000e+00 9.0000000e-01 5.0000000e-01 8.0000000e-01 5.0000000e-01 3.0000000e-01 6.7000000e+00 6.0000000e+00 7.0000000e+00 5.3000000e+00 6.6000000e+00 5.5000000e+00 6.1000000e+00 4.0000000e+00 6.4000000e+00 4.6000000e+00 4.5000000e+00 5.4000000e+00 5.6000000e+00 6.1000000e+00 4.4000000e+00 6.2000000e+00 5.4000000e+00 5.0000000e+00 6.8000000e+00 4.9000000e+00 6.1000000e+00 5.4000000e+00 7.0000000e+00 6.0000000e+00 5.9000000e+00 6.2000000e+00 7.0000000e+00 7.2000000e+00 5.9000000e+00 4.4000000e+00 4.8000000e+00 4.6000000e+00 5.0000000e+00 6.8000000e+00 5.2000000e+00 5.5000000e+00 6.6000000e+00 6.5000000e+00 4.8000000e+00 5.1000000e+00 5.3000000e+00 5.9000000e+00 5.2000000e+00 4.0000000e+00 5.2000000e+00 4.9000000e+00 5.1000000e+00 5.7000000e+00 3.5000000e+00 5.1000000e+00 8.3000000e+00 6.9000000e+00 8.9000000e+00 7.6000000e+00 8.3000000e+00 1.0100000e+01 5.8000000e+00 9.3000000e+00 8.6000000e+00 9.2000000e+00 7.2000000e+00 7.7000000e+00 8.2000000e+00 7.0000000e+00 7.3000000e+00 7.6000000e+00 7.6000000e+00 1.0200000e+01 1.1100000e+01 7.1000000e+00 8.5000000e+00 6.5000000e+00 1.0400000e+01 7.1000000e+00 8.0000000e+00 8.6000000e+00 6.8000000e+00 6.6000000e+00 8.1000000e+00 8.4000000e+00 9.4000000e+00 9.9000000e+00 8.2000000e+00 6.9000000e+00 7.3000000e+00 9.9000000e+00 7.7000000e+00 7.4000000e+00 6.4000000e+00 8.1000000e+00 8.4000000e+00 8.0000000e+00 6.9000000e+00 8.6000000e+00 8.4000000e+00 8.0000000e+00 7.5000000e+00 7.5000000e+00 7.3000000e+00 6.6000000e+00 5.0000000e-01 5.0000000e-01 7.0000000e-01 1.9000000e+00 8.0000000e-01 6.0000000e-01 6.0000000e-01 3.0000000e-01 1.3000000e+00 7.0000000e-01 2.0000000e-01 1.0000000e+00 2.1000000e+00 2.5000000e+00 1.7000000e+00 8.0000000e-01 2.0000000e+00 1.2000000e+00 1.2000000e+00 1.2000000e+00 1.3000000e+00 1.1000000e+00 1.0000000e+00 3.0000000e-01 9.0000000e-01 9.0000000e-01 7.0000000e-01 6.0000000e-01 4.0000000e-01 1.2000000e+00 1.6000000e+00 1.8000000e+00 3.0000000e-01 5.0000000e-01 1.2000000e+00 3.0000000e-01 6.0000000e-01 7.0000000e-01 8.0000000e-01 1.3000000e+00 8.0000000e-01 1.2000000e+00 1.7000000e+00 2.0000000e-01 1.2000000e+00 5.0000000e-01 1.2000000e+00 4.0000000e-01 6.8000000e+00 6.1000000e+00 6.9000000e+00 5.0000000e+00 6.3000000e+00 5.2000000e+00 6.4000000e+00 3.3000000e+00 6.1000000e+00 4.3000000e+00 4.0000000e+00 5.1000000e+00 5.3000000e+00 5.8000000e+00 4.1000000e+00 6.1000000e+00 5.1000000e+00 4.7000000e+00 6.5000000e+00 4.6000000e+00 6.2000000e+00 5.1000000e+00 6.7000000e+00 5.7000000e+00 5.6000000e+00 5.9000000e+00 6.7000000e+00 6.9000000e+00 5.6000000e+00 4.1000000e+00 4.5000000e+00 4.3000000e+00 4.7000000e+00 6.5000000e+00 4.9000000e+00 6.0000000e+00 6.5000000e+00 6.2000000e+00 4.5000000e+00 4.8000000e+00 5.0000000e+00 5.6000000e+00 4.9000000e+00 3.5000000e+00 4.9000000e+00 4.6000000e+00 4.8000000e+00 5.4000000e+00 3.2000000e+00 4.8000000e+00 8.6000000e+00 6.6000000e+00 8.6000000e+00 7.3000000e+00 8.0000000e+00 9.8000000e+00 5.1000000e+00 9.0000000e+00 8.3000000e+00 9.9000000e+00 7.3000000e+00 7.4000000e+00 7.9000000e+00 6.7000000e+00 7.0000000e+00 7.7000000e+00 7.3000000e+00 1.0900000e+01 1.0800000e+01 6.8000000e+00 8.6000000e+00 6.2000000e+00 1.0100000e+01 6.8000000e+00 8.3000000e+00 8.7000000e+00 6.5000000e+00 6.3000000e+00 7.8000000e+00 8.1000000e+00 9.1000000e+00 1.0600000e+01 7.9000000e+00 6.6000000e+00 7.0000000e+00 9.6000000e+00 8.2000000e+00 7.3000000e+00 6.1000000e+00 8.0000000e+00 8.3000000e+00 7.9000000e+00 6.6000000e+00 8.7000000e+00 8.7000000e+00 7.7000000e+00 7.2000000e+00 7.2000000e+00 7.8000000e+00 6.3000000e+00 4.0000000e-01 8.0000000e-01 2.0000000e+00 5.0000000e-01 7.0000000e-01 7.0000000e-01 6.0000000e-01 1.4000000e+00 6.0000000e-01 5.0000000e-01 9.0000000e-01 2.0000000e+00 2.6000000e+00 1.6000000e+00 9.0000000e-01 2.1000000e+00 1.3000000e+00 1.3000000e+00 1.3000000e+00 8.0000000e-01 1.2000000e+00 9.0000000e-01 8.0000000e-01 1.0000000e+00 1.0000000e+00 8.0000000e-01 3.0000000e-01 5.0000000e-01 1.3000000e+00 1.7000000e+00 1.9000000e+00 6.0000000e-01 4.0000000e-01 1.1000000e+00 6.0000000e-01 5.0000000e-01 8.0000000e-01 7.0000000e-01 1.2000000e+00 3.0000000e-01 1.3000000e+00 1.8000000e+00 5.0000000e-01 1.3000000e+00 2.0000000e-01 1.3000000e+00 5.0000000e-01 6.9000000e+00 6.2000000e+00 7.2000000e+00 5.5000000e+00 6.8000000e+00 5.7000000e+00 6.5000000e+00 3.8000000e+00 6.6000000e+00 4.8000000e+00 4.5000000e+00 5.6000000e+00 5.8000000e+00 6.3000000e+00 4.6000000e+00 6.4000000e+00 5.6000000e+00 5.2000000e+00 7.0000000e+00 5.1000000e+00 6.3000000e+00 5.6000000e+00 7.2000000e+00 6.2000000e+00 6.1000000e+00 6.4000000e+00 7.2000000e+00 7.4000000e+00 6.1000000e+00 4.6000000e+00 5.0000000e+00 4.8000000e+00 5.2000000e+00 7.0000000e+00 5.4000000e+00 6.1000000e+00 6.8000000e+00 6.7000000e+00 5.0000000e+00 5.3000000e+00 5.5000000e+00 6.1000000e+00 5.4000000e+00 4.0000000e+00 5.4000000e+00 5.1000000e+00 5.3000000e+00 5.9000000e+00 3.7000000e+00 5.3000000e+00 8.7000000e+00 7.1000000e+00 9.1000000e+00 7.8000000e+00 8.5000000e+00 1.0300000e+01 5.6000000e+00 9.5000000e+00 8.8000000e+00 1.0000000e+01 7.4000000e+00 7.9000000e+00 8.4000000e+00 7.2000000e+00 7.5000000e+00 7.8000000e+00 7.8000000e+00 1.1000000e+01 1.1300000e+01 7.3000000e+00 8.7000000e+00 6.7000000e+00 1.0600000e+01 7.3000000e+00 8.4000000e+00 8.8000000e+00 7.0000000e+00 6.8000000e+00 8.3000000e+00 8.6000000e+00 9.6000000e+00 1.0700000e+01 8.4000000e+00 7.1000000e+00 7.5000000e+00 1.0100000e+01 8.3000000e+00 7.6000000e+00 6.6000000e+00 8.3000000e+00 8.6000000e+00 8.2000000e+00 7.1000000e+00 8.8000000e+00 8.8000000e+00 8.2000000e+00 7.7000000e+00 7.7000000e+00 7.9000000e+00 6.8000000e+00 1.0000000e+00 2.0000000e+00 5.0000000e-01 7.0000000e-01 5.0000000e-01 4.0000000e-01 1.4000000e+00 6.0000000e-01 5.0000000e-01 9.0000000e-01 2.4000000e+00 2.6000000e+00 2.0000000e+00 1.1000000e+00 2.1000000e+00 1.3000000e+00 1.3000000e+00 1.3000000e+00 1.0000000e+00 1.2000000e+00 9.0000000e-01 6.0000000e-01 1.0000000e+00 1.0000000e+00 1.0000000e+00 3.0000000e-01 3.0000000e-01 1.3000000e+00 1.7000000e+00 2.1000000e+00 4.0000000e-01 8.0000000e-01 1.5000000e+00 4.0000000e-01 5.0000000e-01 8.0000000e-01 1.1000000e+00 1.2000000e+00 5.0000000e-01 1.3000000e+00 1.8000000e+00 5.0000000e-01 1.3000000e+00 2.0000000e-01 1.3000000e+00 7.0000000e-01 6.9000000e+00 6.2000000e+00 7.0000000e+00 5.3000000e+00 6.6000000e+00 5.5000000e+00 6.5000000e+00 3.6000000e+00 6.4000000e+00 4.6000000e+00 4.3000000e+00 5.4000000e+00 5.6000000e+00 6.1000000e+00 4.4000000e+00 6.2000000e+00 5.4000000e+00 5.0000000e+00 6.8000000e+00 4.9000000e+00 6.3000000e+00 5.4000000e+00 7.0000000e+00 6.0000000e+00 5.9000000e+00 6.2000000e+00 7.0000000e+00 7.2000000e+00 5.9000000e+00 4.4000000e+00 4.8000000e+00 4.6000000e+00 5.0000000e+00 6.8000000e+00 5.2000000e+00 6.1000000e+00 6.6000000e+00 6.5000000e+00 4.8000000e+00 5.1000000e+00 5.3000000e+00 5.9000000e+00 5.2000000e+00 3.8000000e+00 5.2000000e+00 4.9000000e+00 5.1000000e+00 5.7000000e+00 3.5000000e+00 5.1000000e+00 8.7000000e+00 6.9000000e+00 8.9000000e+00 7.6000000e+00 8.3000000e+00 1.0100000e+01 5.4000000e+00 9.3000000e+00 8.6000000e+00 1.0000000e+01 7.4000000e+00 7.7000000e+00 8.2000000e+00 7.0000000e+00 7.3000000e+00 7.8000000e+00 7.6000000e+00 1.1000000e+01 1.1100000e+01 7.1000000e+00 8.7000000e+00 6.5000000e+00 1.0400000e+01 7.1000000e+00 8.4000000e+00 8.8000000e+00 6.8000000e+00 6.6000000e+00 8.1000000e+00 8.4000000e+00 9.4000000e+00 1.0700000e+01 8.2000000e+00 6.9000000e+00 7.3000000e+00 9.9000000e+00 8.3000000e+00 7.4000000e+00 6.4000000e+00 8.1000000e+00 8.4000000e+00 8.0000000e+00 6.9000000e+00 8.8000000e+00 8.8000000e+00 8.0000000e+00 7.5000000e+00 7.5000000e+00 7.9000000e+00 6.6000000e+00 1.2000000e+00 7.0000000e-01 3.0000000e-01 1.3000000e+00 8.0000000e-01 6.0000000e-01 6.0000000e-01 9.0000000e-01 1.7000000e+00 1.4000000e+00 1.8000000e+00 1.0000000e+00 3.0000000e-01 1.3000000e+00 5.0000000e-01 9.0000000e-01 5.0000000e-01 8.0000000e-01 1.0000000e+00 9.0000000e-01 8.0000000e-01 6.0000000e-01 4.0000000e-01 4.0000000e-01 9.0000000e-01 9.0000000e-01 9.0000000e-01 9.0000000e-01 1.1000000e+00 8.0000000e-01 6.0000000e-01 7.0000000e-01 8.0000000e-01 1.3000000e+00 4.0000000e-01 3.0000000e-01 2.0000000e+00 1.1000000e+00 7.0000000e-01 1.0000000e+00 9.0000000e-01 5.0000000e-01 8.0000000e-01 5.0000000e-01 3.0000000e-01 6.9000000e+00 6.2000000e+00 7.2000000e+00 5.5000000e+00 6.8000000e+00 5.7000000e+00 6.3000000e+00 4.0000000e+00 6.6000000e+00 4.8000000e+00 4.5000000e+00 5.6000000e+00 5.8000000e+00 6.3000000e+00 4.6000000e+00 6.4000000e+00 5.6000000e+00 5.2000000e+00 7.0000000e+00 5.1000000e+00 6.3000000e+00 5.6000000e+00 7.2000000e+00 6.2000000e+00 6.1000000e+00 6.4000000e+00 7.2000000e+00 7.4000000e+00 6.1000000e+00 4.6000000e+00 5.0000000e+00 4.8000000e+00 5.2000000e+00 7.0000000e+00 5.4000000e+00 5.7000000e+00 6.8000000e+00 6.7000000e+00 5.0000000e+00 5.3000000e+00 5.5000000e+00 6.1000000e+00 5.4000000e+00 4.0000000e+00 5.4000000e+00 5.1000000e+00 5.3000000e+00 5.9000000e+00 3.7000000e+00 5.3000000e+00 8.5000000e+00 7.1000000e+00 9.1000000e+00 7.8000000e+00 8.5000000e+00 1.0300000e+01 5.8000000e+00 9.5000000e+00 8.8000000e+00 9.2000000e+00 7.4000000e+00 7.9000000e+00 8.4000000e+00 7.2000000e+00 7.5000000e+00 7.8000000e+00 7.8000000e+00 1.0200000e+01 1.1300000e+01 7.3000000e+00 8.7000000e+00 6.7000000e+00 1.0600000e+01 7.3000000e+00 8.2000000e+00 8.8000000e+00 7.0000000e+00 6.8000000e+00 8.3000000e+00 8.6000000e+00 9.6000000e+00 9.9000000e+00 8.4000000e+00 7.1000000e+00 7.5000000e+00 1.0100000e+01 7.9000000e+00 7.6000000e+00 6.6000000e+00 8.3000000e+00 8.6000000e+00 8.2000000e+00 7.1000000e+00 8.8000000e+00 8.6000000e+00 8.2000000e+00 7.7000000e+00 7.7000000e+00 7.5000000e+00 6.8000000e+00 1.7000000e+00 1.3000000e+00 2.5000000e+00 1.8000000e+00 6.0000000e-01 1.4000000e+00 2.1000000e+00 2.9000000e+00 1.2000000e+00 1.0000000e+00 4.0000000e-01 1.1000000e+00 5.0000000e-01 7.0000000e-01 7.0000000e-01 7.0000000e-01 2.0000000e+00 1.0000000e+00 1.5000000e+00 1.6000000e+00 1.0000000e+00 1.0000000e+00 1.2000000e+00 1.7000000e+00 1.7000000e+00 7.0000000e-01 9.0000000e-01 9.0000000e-01 1.8000000e+00 1.8000000e+00 1.1000000e+00 1.8000000e+00 2.5000000e+00 1.2000000e+00 1.3000000e+00 3.0000000e+00 2.3000000e+00 1.1000000e+00 6.0000000e-01 1.9000000e+00 7.0000000e-01 2.0000000e+00 7.0000000e-01 1.5000000e+00 6.3000000e+00 5.6000000e+00 6.6000000e+00 4.9000000e+00 6.2000000e+00 5.1000000e+00 5.7000000e+00 4.2000000e+00 6.0000000e+00 4.6000000e+00 4.7000000e+00 5.0000000e+00 5.2000000e+00 5.7000000e+00 4.0000000e+00 5.8000000e+00 5.0000000e+00 4.6000000e+00 6.4000000e+00 4.5000000e+00 5.7000000e+00 5.0000000e+00 6.6000000e+00 5.6000000e+00 5.5000000e+00 5.8000000e+00 6.6000000e+00 6.8000000e+00 5.5000000e+00 4.0000000e+00 4.4000000e+00 4.2000000e+00 4.6000000e+00 6.4000000e+00 4.8000000e+00 5.1000000e+00 6.2000000e+00 6.1000000e+00 4.4000000e+00 4.7000000e+00 4.9000000e+00 5.5000000e+00 4.8000000e+00 4.2000000e+00 4.8000000e+00 4.5000000e+00 4.7000000e+00 5.3000000e+00 3.7000000e+00 4.7000000e+00 7.9000000e+00 6.5000000e+00 8.5000000e+00 7.2000000e+00 7.9000000e+00 9.7000000e+00 6.0000000e+00 8.9000000e+00 8.2000000e+00 8.6000000e+00 6.8000000e+00 7.3000000e+00 7.8000000e+00 6.6000000e+00 6.9000000e+00 7.2000000e+00 7.2000000e+00 9.2000000e+00 1.0700000e+01 6.7000000e+00 8.1000000e+00 6.1000000e+00 1.0000000e+01 6.7000000e+00 7.6000000e+00 8.2000000e+00 6.4000000e+00 6.2000000e+00 7.7000000e+00 8.0000000e+00 9.0000000e+00 8.9000000e+00 7.8000000e+00 6.5000000e+00 6.9000000e+00 9.5000000e+00 7.3000000e+00 7.0000000e+00 6.0000000e+00 7.7000000e+00 8.0000000e+00 7.6000000e+00 6.5000000e+00 8.2000000e+00 8.0000000e+00 7.6000000e+00 7.1000000e+00 7.1000000e+00 6.9000000e+00 6.2000000e+00 6.0000000e-01 8.0000000e-01 9.0000000e-01 1.3000000e+00 5.0000000e-01 8.0000000e-01 1.2000000e+00 2.1000000e+00 2.3000000e+00 1.5000000e+00 6.0000000e-01 1.8000000e+00 1.0000000e+00 1.2000000e+00 1.0000000e+00 7.0000000e-01 1.1000000e+00 8.0000000e-01 1.1000000e+00 7.0000000e-01 9.0000000e-01 7.0000000e-01 6.0000000e-01 8.0000000e-01 1.0000000e+00 1.6000000e+00 1.8000000e+00 9.0000000e-01 9.0000000e-01 1.2000000e+00 9.0000000e-01 8.0000000e-01 7.0000000e-01 6.0000000e-01 1.3000000e+00 6.0000000e-01 1.0000000e+00 1.5000000e+00 6.0000000e-01 1.2000000e+00 3.0000000e-01 1.2000000e+00 6.0000000e-01 7.0000000e+00 6.3000000e+00 7.3000000e+00 5.6000000e+00 6.9000000e+00 5.8000000e+00 6.4000000e+00 3.9000000e+00 6.7000000e+00 4.9000000e+00 4.6000000e+00 5.7000000e+00 5.9000000e+00 6.4000000e+00 4.7000000e+00 6.5000000e+00 5.7000000e+00 5.3000000e+00 7.1000000e+00 5.2000000e+00 6.4000000e+00 5.7000000e+00 7.3000000e+00 6.3000000e+00 6.2000000e+00 6.5000000e+00 7.3000000e+00 7.5000000e+00 6.2000000e+00 4.7000000e+00 5.1000000e+00 4.9000000e+00 5.3000000e+00 7.1000000e+00 5.5000000e+00 5.8000000e+00 6.9000000e+00 6.8000000e+00 5.1000000e+00 5.4000000e+00 5.6000000e+00 6.2000000e+00 5.5000000e+00 4.1000000e+00 5.5000000e+00 5.2000000e+00 5.4000000e+00 6.0000000e+00 3.8000000e+00 5.4000000e+00 8.6000000e+00 7.2000000e+00 9.2000000e+00 7.9000000e+00 8.6000000e+00 1.0400000e+01 5.7000000e+00 9.6000000e+00 8.9000000e+00 9.7000000e+00 7.5000000e+00 8.0000000e+00 8.5000000e+00 7.3000000e+00 7.6000000e+00 7.9000000e+00 7.9000000e+00 1.0700000e+01 1.1400000e+01 7.4000000e+00 8.8000000e+00 6.8000000e+00 1.0700000e+01 7.4000000e+00 8.3000000e+00 8.9000000e+00 7.1000000e+00 6.9000000e+00 8.4000000e+00 8.7000000e+00 9.7000000e+00 1.0400000e+01 8.5000000e+00 7.2000000e+00 7.6000000e+00 1.0200000e+01 8.0000000e+00 7.7000000e+00 6.7000000e+00 8.4000000e+00 8.7000000e+00 8.3000000e+00 7.2000000e+00 8.9000000e+00 8.7000000e+00 8.3000000e+00 7.8000000e+00 7.8000000e+00 7.6000000e+00 6.9000000e+00 1.2000000e+00 5.0000000e-01 7.0000000e-01 3.0000000e-01 8.0000000e-01 1.6000000e+00 1.7000000e+00 1.9000000e+00 1.3000000e+00 4.0000000e-01 1.4000000e+00 6.0000000e-01 6.0000000e-01 6.0000000e-01 1.1000000e+00 7.0000000e-01 6.0000000e-01 5.0000000e-01 3.0000000e-01 3.0000000e-01 3.0000000e-01 6.0000000e-01 6.0000000e-01 6.0000000e-01 1.0000000e+00 1.4000000e+00 5.0000000e-01 5.0000000e-01 8.0000000e-01 5.0000000e-01 1.2000000e+00 1.0000000e-01 4.0000000e-01 1.9000000e+00 1.0000000e+00 6.0000000e-01 1.1000000e+00 8.0000000e-01 6.0000000e-01 7.0000000e-01 6.0000000e-01 2.0000000e-01 6.6000000e+00 5.9000000e+00 6.9000000e+00 5.2000000e+00 6.5000000e+00 5.4000000e+00 6.0000000e+00 3.7000000e+00 6.3000000e+00 4.5000000e+00 4.2000000e+00 5.3000000e+00 5.5000000e+00 6.0000000e+00 4.3000000e+00 6.1000000e+00 5.3000000e+00 4.9000000e+00 6.7000000e+00 4.8000000e+00 6.0000000e+00 5.3000000e+00 6.9000000e+00 5.9000000e+00 5.8000000e+00 6.1000000e+00 6.9000000e+00 7.1000000e+00 5.8000000e+00 4.3000000e+00 4.7000000e+00 4.5000000e+00 4.9000000e+00 6.7000000e+00 5.1000000e+00 5.4000000e+00 6.5000000e+00 6.4000000e+00 4.7000000e+00 5.0000000e+00 5.2000000e+00 5.8000000e+00 5.1000000e+00 3.7000000e+00 5.1000000e+00 4.8000000e+00 5.0000000e+00 5.6000000e+00 3.4000000e+00 5.0000000e+00 8.2000000e+00 6.8000000e+00 8.8000000e+00 7.5000000e+00 8.2000000e+00 1.0000000e+01 5.5000000e+00 9.2000000e+00 8.5000000e+00 9.3000000e+00 7.1000000e+00 7.6000000e+00 8.1000000e+00 6.9000000e+00 7.2000000e+00 7.5000000e+00 7.5000000e+00 1.0300000e+01 1.1000000e+01 7.0000000e+00 8.4000000e+00 6.4000000e+00 1.0300000e+01 7.0000000e+00 7.9000000e+00 8.5000000e+00 6.7000000e+00 6.5000000e+00 8.0000000e+00 8.3000000e+00 9.3000000e+00 1.0000000e+01 8.1000000e+00 6.8000000e+00 7.2000000e+00 9.8000000e+00 7.6000000e+00 7.3000000e+00 6.3000000e+00 8.0000000e+00 8.3000000e+00 7.9000000e+00 6.8000000e+00 8.5000000e+00 8.3000000e+00 7.9000000e+00 7.4000000e+00 7.4000000e+00 7.2000000e+00 6.5000000e+00 9.0000000e-01 1.9000000e+00 1.1000000e+00 6.0000000e-01 6.0000000e-01 2.7000000e+00 3.1000000e+00 2.3000000e+00 1.4000000e+00 2.6000000e+00 1.8000000e+00 1.8000000e+00 1.8000000e+00 1.3000000e+00 1.7000000e+00 1.4000000e+00 9.0000000e-01 1.5000000e+00 1.5000000e+00 1.3000000e+00 8.0000000e-01 8.0000000e-01 1.8000000e+00 2.2000000e+00 2.4000000e+00 9.0000000e-01 1.1000000e+00 1.8000000e+00 9.0000000e-01 2.0000000e-01 1.3000000e+00 1.4000000e+00 9.0000000e-01 4.0000000e-01 1.8000000e+00 2.3000000e+00 6.0000000e-01 1.8000000e+00 5.0000000e-01 1.8000000e+00 1.0000000e+00 7.4000000e+00 6.7000000e+00 7.5000000e+00 5.4000000e+00 6.7000000e+00 5.6000000e+00 7.0000000e+00 3.7000000e+00 6.5000000e+00 4.7000000e+00 4.4000000e+00 5.7000000e+00 5.7000000e+00 6.2000000e+00 4.5000000e+00 6.7000000e+00 5.7000000e+00 5.1000000e+00 6.9000000e+00 5.0000000e+00 6.8000000e+00 5.5000000e+00 7.1000000e+00 6.1000000e+00 6.0000000e+00 6.5000000e+00 7.1000000e+00 7.5000000e+00 6.0000000e+00 4.5000000e+00 4.9000000e+00 4.7000000e+00 5.1000000e+00 6.9000000e+00 5.5000000e+00 6.6000000e+00 7.1000000e+00 6.6000000e+00 5.1000000e+00 5.2000000e+00 5.4000000e+00 6.2000000e+00 5.3000000e+00 3.9000000e+00 5.3000000e+00 5.2000000e+00 5.2000000e+00 5.8000000e+00 3.6000000e+00 5.2000000e+00 9.2000000e+00 7.0000000e+00 9.2000000e+00 7.7000000e+00 8.6000000e+00 1.0400000e+01 5.5000000e+00 9.4000000e+00 8.7000000e+00 1.0500000e+01 7.9000000e+00 7.8000000e+00 8.5000000e+00 7.1000000e+00 7.4000000e+00 8.3000000e+00 7.9000000e+00 1.1500000e+01 1.1200000e+01 7.2000000e+00 9.2000000e+00 6.6000000e+00 1.0500000e+01 7.2000000e+00 8.9000000e+00 9.3000000e+00 6.9000000e+00 6.9000000e+00 8.2000000e+00 8.7000000e+00 9.5000000e+00 1.1200000e+01 8.3000000e+00 7.0000000e+00 7.4000000e+00 1.0200000e+01 8.8000000e+00 7.9000000e+00 6.7000000e+00 8.6000000e+00 8.9000000e+00 8.5000000e+00 7.0000000e+00 9.3000000e+00 9.3000000e+00 8.3000000e+00 7.6000000e+00 7.8000000e+00 8.4000000e+00 6.9000000e+00 1.2000000e+00 6.0000000e-01 3.0000000e-01 1.1000000e+00 2.2000000e+00 2.4000000e+00 1.8000000e+00 9.0000000e-01 1.9000000e+00 1.1000000e+00 1.1000000e+00 1.1000000e+00 1.4000000e+00 1.0000000e+00 9.0000000e-01 4.0000000e-01 8.0000000e-01 8.0000000e-01 8.0000000e-01 5.0000000e-01 3.0000000e-01 1.1000000e+00 1.3000000e+00 1.9000000e+00 0.0000000e+00 6.0000000e-01 1.3000000e+00 0.0000000e+00 9.0000000e-01 6.0000000e-01 9.0000000e-01 1.6000000e+00 9.0000000e-01 1.1000000e+00 1.6000000e+00 5.0000000e-01 1.1000000e+00 6.0000000e-01 1.1000000e+00 5.0000000e-01 6.7000000e+00 6.0000000e+00 6.8000000e+00 5.1000000e+00 6.4000000e+00 5.3000000e+00 6.3000000e+00 3.4000000e+00 6.2000000e+00 4.4000000e+00 4.1000000e+00 5.2000000e+00 5.4000000e+00 5.9000000e+00 4.2000000e+00 6.0000000e+00 5.2000000e+00 4.8000000e+00 6.6000000e+00 4.7000000e+00 6.1000000e+00 5.2000000e+00 6.8000000e+00 5.8000000e+00 5.7000000e+00 6.0000000e+00 6.8000000e+00 7.0000000e+00 5.7000000e+00 4.2000000e+00 4.6000000e+00 4.4000000e+00 4.8000000e+00 6.6000000e+00 5.0000000e+00 5.9000000e+00 6.4000000e+00 6.3000000e+00 4.6000000e+00 4.9000000e+00 5.1000000e+00 5.7000000e+00 5.0000000e+00 3.6000000e+00 5.0000000e+00 4.7000000e+00 4.9000000e+00 5.5000000e+00 3.3000000e+00 4.9000000e+00 8.5000000e+00 6.7000000e+00 8.7000000e+00 7.4000000e+00 8.1000000e+00 9.9000000e+00 5.2000000e+00 9.1000000e+00 8.4000000e+00 9.8000000e+00 7.2000000e+00 7.5000000e+00 8.0000000e+00 6.8000000e+00 7.1000000e+00 7.6000000e+00 7.4000000e+00 1.0800000e+01 1.0900000e+01 6.9000000e+00 8.5000000e+00 6.3000000e+00 1.0200000e+01 6.9000000e+00 8.2000000e+00 8.6000000e+00 6.6000000e+00 6.4000000e+00 7.9000000e+00 8.2000000e+00 9.2000000e+00 1.0500000e+01 8.0000000e+00 6.7000000e+00 7.1000000e+00 9.7000000e+00 8.1000000e+00 7.2000000e+00 6.2000000e+00 7.9000000e+00 8.2000000e+00 7.8000000e+00 6.7000000e+00 8.6000000e+00 8.6000000e+00 7.8000000e+00 7.3000000e+00 7.3000000e+00 7.7000000e+00 6.4000000e+00 1.0000000e+00 1.5000000e+00 2.3000000e+00 1.0000000e+00 1.2000000e+00 6.0000000e-01 7.0000000e-01 7.0000000e-01 5.0000000e-01 5.0000000e-01 5.0000000e-01 1.4000000e+00 1.2000000e+00 1.3000000e+00 1.2000000e+00 1.0000000e+00 4.0000000e-01 6.0000000e-01 1.3000000e+00 1.3000000e+00 5.0000000e-01 7.0000000e-01 7.0000000e-01 1.2000000e+00 1.2000000e+00 5.0000000e-01 1.2000000e+00 1.9000000e+00 6.0000000e-01 9.0000000e-01 2.6000000e+00 1.7000000e+00 1.1000000e+00 1.0000000e+00 1.5000000e+00 5.0000000e-01 1.4000000e+00 1.0000000e-01 9.0000000e-01 6.5000000e+00 5.8000000e+00 6.8000000e+00 5.1000000e+00 6.4000000e+00 5.3000000e+00 5.9000000e+00 4.4000000e+00 6.2000000e+00 4.8000000e+00 4.9000000e+00 5.2000000e+00 5.4000000e+00 5.9000000e+00 4.2000000e+00 6.0000000e+00 5.2000000e+00 4.8000000e+00 6.6000000e+00 4.7000000e+00 5.9000000e+00 5.2000000e+00 6.8000000e+00 5.8000000e+00 5.7000000e+00 6.0000000e+00 6.8000000e+00 7.0000000e+00 5.7000000e+00 4.2000000e+00 4.6000000e+00 4.4000000e+00 4.8000000e+00 6.6000000e+00 5.0000000e+00 5.3000000e+00 6.4000000e+00 6.3000000e+00 4.6000000e+00 4.9000000e+00 5.1000000e+00 5.7000000e+00 5.0000000e+00 4.4000000e+00 5.0000000e+00 4.7000000e+00 4.9000000e+00 5.5000000e+00 3.9000000e+00 4.9000000e+00 8.1000000e+00 6.7000000e+00 8.7000000e+00 7.4000000e+00 8.1000000e+00 9.9000000e+00 6.2000000e+00 9.1000000e+00 8.4000000e+00 8.8000000e+00 7.0000000e+00 7.5000000e+00 8.0000000e+00 6.8000000e+00 7.1000000e+00 7.4000000e+00 7.4000000e+00 9.6000000e+00 1.0900000e+01 6.9000000e+00 8.3000000e+00 6.3000000e+00 1.0200000e+01 6.9000000e+00 7.8000000e+00 8.4000000e+00 6.6000000e+00 6.4000000e+00 7.9000000e+00 8.2000000e+00 9.2000000e+00 9.3000000e+00 8.0000000e+00 6.7000000e+00 7.1000000e+00 9.7000000e+00 7.5000000e+00 7.2000000e+00 6.2000000e+00 7.9000000e+00 8.2000000e+00 7.8000000e+00 6.7000000e+00 8.4000000e+00 8.2000000e+00 7.8000000e+00 7.3000000e+00 7.3000000e+00 7.1000000e+00 6.4000000e+00 7.0000000e-01 1.5000000e+00 2.0000000e+00 2.2000000e+00 1.6000000e+00 7.0000000e-01 1.5000000e+00 9.0000000e-01 7.0000000e-01 9.0000000e-01 1.0000000e+00 8.0000000e-01 3.0000000e-01 6.0000000e-01 4.0000000e-01 6.0000000e-01 6.0000000e-01 3.0000000e-01 3.0000000e-01 9.0000000e-01 1.3000000e+00 1.7000000e+00 6.0000000e-01 8.0000000e-01 1.1000000e+00 6.0000000e-01 1.1000000e+00 4.0000000e-01 7.0000000e-01 1.8000000e+00 9.0000000e-01 7.0000000e-01 1.2000000e+00 7.0000000e-01 7.0000000e-01 6.0000000e-01 9.0000000e-01 5.0000000e-01 6.7000000e+00 6.0000000e+00 7.0000000e+00 5.3000000e+00 6.6000000e+00 5.5000000e+00 6.1000000e+00 3.6000000e+00 6.4000000e+00 4.6000000e+00 4.3000000e+00 5.4000000e+00 5.6000000e+00 6.1000000e+00 4.4000000e+00 6.2000000e+00 5.4000000e+00 5.0000000e+00 6.8000000e+00 4.9000000e+00 6.1000000e+00 5.4000000e+00 7.0000000e+00 6.0000000e+00 5.9000000e+00 6.2000000e+00 7.0000000e+00 7.2000000e+00 5.9000000e+00 4.4000000e+00 4.8000000e+00 4.6000000e+00 5.0000000e+00 6.8000000e+00 5.2000000e+00 5.5000000e+00 6.6000000e+00 6.5000000e+00 4.8000000e+00 5.1000000e+00 5.3000000e+00 5.9000000e+00 5.2000000e+00 3.8000000e+00 5.2000000e+00 4.9000000e+00 5.1000000e+00 5.7000000e+00 3.5000000e+00 5.1000000e+00 8.3000000e+00 6.9000000e+00 8.9000000e+00 7.6000000e+00 8.3000000e+00 1.0100000e+01 5.4000000e+00 9.3000000e+00 8.6000000e+00 9.4000000e+00 7.2000000e+00 7.7000000e+00 8.2000000e+00 7.0000000e+00 7.3000000e+00 7.6000000e+00 7.6000000e+00 1.0400000e+01 1.1100000e+01 7.1000000e+00 8.5000000e+00 6.5000000e+00 1.0400000e+01 7.1000000e+00 8.0000000e+00 8.6000000e+00 6.8000000e+00 6.6000000e+00 8.1000000e+00 8.4000000e+00 9.4000000e+00 1.0100000e+01 8.2000000e+00 6.9000000e+00 7.3000000e+00 9.9000000e+00 7.7000000e+00 7.4000000e+00 6.4000000e+00 8.1000000e+00 8.4000000e+00 8.0000000e+00 6.9000000e+00 8.6000000e+00 8.4000000e+00 8.0000000e+00 7.5000000e+00 7.5000000e+00 7.3000000e+00 6.6000000e+00 8.0000000e-01 2.3000000e+00 2.7000000e+00 1.9000000e+00 1.0000000e+00 2.2000000e+00 1.4000000e+00 1.4000000e+00 1.4000000e+00 1.3000000e+00 1.3000000e+00 1.0000000e+00 5.0000000e-01 1.1000000e+00 1.1000000e+00 9.0000000e-01 6.0000000e-01 4.0000000e-01 1.4000000e+00 1.6000000e+00 2.0000000e+00 3.0000000e-01 7.0000000e-01 1.4000000e+00 3.0000000e-01 6.0000000e-01 9.0000000e-01 1.0000000e+00 1.3000000e+00 8.0000000e-01 1.4000000e+00 1.9000000e+00 2.0000000e-01 1.4000000e+00 5.0000000e-01 1.4000000e+00 6.0000000e-01 7.0000000e+00 6.3000000e+00 7.1000000e+00 5.2000000e+00 6.5000000e+00 5.4000000e+00 6.6000000e+00 3.5000000e+00 6.3000000e+00 4.5000000e+00 4.2000000e+00 5.3000000e+00 5.5000000e+00 6.0000000e+00 4.3000000e+00 6.3000000e+00 5.3000000e+00 4.9000000e+00 6.7000000e+00 4.8000000e+00 6.4000000e+00 5.3000000e+00 6.9000000e+00 5.9000000e+00 5.8000000e+00 6.1000000e+00 6.9000000e+00 7.1000000e+00 5.8000000e+00 4.3000000e+00 4.7000000e+00 4.5000000e+00 4.9000000e+00 6.7000000e+00 5.1000000e+00 6.2000000e+00 6.7000000e+00 6.4000000e+00 4.7000000e+00 5.0000000e+00 5.2000000e+00 5.8000000e+00 5.1000000e+00 3.7000000e+00 5.1000000e+00 4.8000000e+00 5.0000000e+00 5.6000000e+00 3.4000000e+00 5.0000000e+00 8.8000000e+00 6.8000000e+00 8.8000000e+00 7.5000000e+00 8.2000000e+00 1.0000000e+01 5.3000000e+00 9.2000000e+00 8.5000000e+00 1.0100000e+01 7.5000000e+00 7.6000000e+00 8.1000000e+00 6.9000000e+00 7.2000000e+00 7.9000000e+00 7.5000000e+00 1.1100000e+01 1.1000000e+01 7.0000000e+00 8.8000000e+00 6.4000000e+00 1.0300000e+01 7.0000000e+00 8.5000000e+00 8.9000000e+00 6.7000000e+00 6.5000000e+00 8.0000000e+00 8.3000000e+00 9.3000000e+00 1.0800000e+01 8.1000000e+00 6.8000000e+00 7.2000000e+00 9.8000000e+00 8.4000000e+00 7.5000000e+00 6.3000000e+00 8.2000000e+00 8.5000000e+00 8.1000000e+00 6.8000000e+00 8.9000000e+00 8.9000000e+00 7.9000000e+00 7.4000000e+00 7.4000000e+00 8.0000000e+00 6.5000000e+00 2.7000000e+00 3.5000000e+00 2.5000000e+00 1.8000000e+00 3.0000000e+00 2.2000000e+00 2.2000000e+00 2.2000000e+00 1.1000000e+00 2.1000000e+00 1.8000000e+00 1.3000000e+00 1.9000000e+00 1.9000000e+00 1.7000000e+00 1.2000000e+00 1.2000000e+00 2.2000000e+00 2.4000000e+00 2.8000000e+00 1.1000000e+00 1.1000000e+00 2.0000000e+00 1.1000000e+00 4.0000000e-01 1.7000000e+00 1.6000000e+00 1.3000000e+00 6.0000000e-01 2.2000000e+00 2.7000000e+00 1.0000000e+00 2.2000000e+00 9.0000000e-01 2.2000000e+00 1.4000000e+00 7.8000000e+00 7.1000000e+00 7.9000000e+00 6.0000000e+00 7.3000000e+00 6.2000000e+00 7.4000000e+00 4.3000000e+00 7.1000000e+00 5.3000000e+00 5.0000000e+00 6.1000000e+00 6.3000000e+00 6.8000000e+00 5.1000000e+00 7.1000000e+00 6.1000000e+00 5.7000000e+00 7.5000000e+00 5.6000000e+00 7.2000000e+00 6.1000000e+00 7.7000000e+00 6.7000000e+00 6.6000000e+00 6.9000000e+00 7.7000000e+00 7.9000000e+00 6.6000000e+00 5.1000000e+00 5.5000000e+00 5.3000000e+00 5.7000000e+00 7.5000000e+00 5.9000000e+00 7.0000000e+00 7.5000000e+00 7.2000000e+00 5.5000000e+00 5.8000000e+00 6.0000000e+00 6.6000000e+00 5.9000000e+00 4.5000000e+00 5.9000000e+00 5.6000000e+00 5.8000000e+00 6.4000000e+00 4.2000000e+00 5.8000000e+00 9.6000000e+00 7.6000000e+00 9.6000000e+00 8.3000000e+00 9.0000000e+00 1.0800000e+01 6.1000000e+00 1.0000000e+01 9.3000000e+00 1.0900000e+01 8.3000000e+00 8.4000000e+00 8.9000000e+00 7.7000000e+00 8.0000000e+00 8.7000000e+00 8.3000000e+00 1.1900000e+01 1.1800000e+01 7.8000000e+00 9.6000000e+00 7.2000000e+00 1.1100000e+01 7.8000000e+00 9.3000000e+00 9.7000000e+00 7.5000000e+00 7.3000000e+00 8.8000000e+00 9.1000000e+00 1.0100000e+01 1.1600000e+01 8.9000000e+00 7.6000000e+00 8.0000000e+00 1.0600000e+01 9.2000000e+00 8.3000000e+00 7.1000000e+00 9.0000000e+00 9.3000000e+00 8.9000000e+00 7.6000000e+00 9.7000000e+00 9.7000000e+00 8.7000000e+00 8.2000000e+00 8.2000000e+00 8.8000000e+00 7.3000000e+00 1.0000000e+00 8.0000000e-01 1.5000000e+00 9.0000000e-01 1.3000000e+00 1.5000000e+00 1.5000000e+00 1.8000000e+00 2.2000000e+00 2.3000000e+00 2.2000000e+00 2.0000000e+00 1.4000000e+00 1.4000000e+00 2.3000000e+00 2.3000000e+00 1.5000000e+00 1.1000000e+00 7.0000000e-01 2.2000000e+00 1.6000000e+00 9.0000000e-01 2.2000000e+00 2.5000000e+00 1.6000000e+00 1.5000000e+00 3.2000000e+00 2.3000000e+00 2.1000000e+00 1.8000000e+00 2.3000000e+00 1.3000000e+00 2.2000000e+00 1.1000000e+00 1.7000000e+00 6.7000000e+00 6.0000000e+00 7.0000000e+00 5.9000000e+00 6.6000000e+00 5.7000000e+00 6.1000000e+00 5.4000000e+00 6.4000000e+00 5.8000000e+00 5.9000000e+00 5.4000000e+00 5.6000000e+00 6.1000000e+00 4.8000000e+00 6.2000000e+00 5.8000000e+00 5.0000000e+00 6.8000000e+00 5.3000000e+00 6.1000000e+00 5.4000000e+00 7.0000000e+00 6.0000000e+00 5.9000000e+00 6.2000000e+00 7.0000000e+00 7.2000000e+00 5.9000000e+00 4.6000000e+00 5.4000000e+00 5.2000000e+00 5.0000000e+00 6.8000000e+00 6.0000000e+00 5.5000000e+00 6.6000000e+00 6.5000000e+00 5.2000000e+00 5.7000000e+00 5.9000000e+00 5.9000000e+00 5.2000000e+00 5.4000000e+00 5.6000000e+00 5.1000000e+00 5.3000000e+00 5.7000000e+00 4.9000000e+00 5.3000000e+00 8.3000000e+00 6.9000000e+00 8.9000000e+00 7.6000000e+00 8.3000000e+00 1.0100000e+01 7.2000000e+00 9.3000000e+00 8.6000000e+00 9.0000000e+00 7.2000000e+00 7.7000000e+00 8.2000000e+00 7.2000000e+00 7.3000000e+00 7.6000000e+00 7.6000000e+00 9.6000000e+00 1.1100000e+01 7.1000000e+00 8.5000000e+00 6.9000000e+00 1.0400000e+01 7.1000000e+00 8.0000000e+00 8.6000000e+00 6.8000000e+00 6.6000000e+00 8.1000000e+00 8.4000000e+00 9.4000000e+00 9.3000000e+00 8.2000000e+00 6.9000000e+00 7.3000000e+00 9.9000000e+00 7.7000000e+00 7.4000000e+00 6.4000000e+00 8.1000000e+00 8.4000000e+00 8.0000000e+00 6.9000000e+00 8.6000000e+00 8.4000000e+00 8.0000000e+00 7.5000000e+00 7.5000000e+00 7.3000000e+00 6.6000000e+00 1.0000000e+00 1.7000000e+00 9.0000000e-01 1.3000000e+00 1.7000000e+00 1.3000000e+00 2.6000000e+00 2.0000000e+00 2.5000000e+00 2.4000000e+00 1.8000000e+00 1.6000000e+00 1.8000000e+00 2.5000000e+00 2.5000000e+00 1.3000000e+00 1.1000000e+00 7.0000000e-01 2.4000000e+00 2.4000000e+00 1.5000000e+00 2.4000000e+00 3.1000000e+00 1.8000000e+00 1.9000000e+00 3.6000000e+00 2.9000000e+00 1.9000000e+00 1.6000000e+00 2.5000000e+00 1.5000000e+00 2.6000000e+00 1.3000000e+00 2.1000000e+00 6.7000000e+00 6.0000000e+00 7.0000000e+00 5.7000000e+00 6.6000000e+00 5.5000000e+00 6.1000000e+00 5.2000000e+00 6.4000000e+00 5.6000000e+00 5.7000000e+00 5.4000000e+00 5.6000000e+00 6.1000000e+00 4.6000000e+00 6.2000000e+00 5.6000000e+00 5.0000000e+00 6.8000000e+00 5.1000000e+00 6.1000000e+00 5.4000000e+00 7.0000000e+00 6.0000000e+00 5.9000000e+00 6.2000000e+00 7.0000000e+00 7.2000000e+00 5.9000000e+00 4.4000000e+00 5.2000000e+00 5.0000000e+00 5.0000000e+00 6.8000000e+00 5.8000000e+00 5.5000000e+00 6.6000000e+00 6.5000000e+00 5.0000000e+00 5.5000000e+00 5.7000000e+00 5.9000000e+00 5.2000000e+00 5.2000000e+00 5.4000000e+00 4.9000000e+00 5.1000000e+00 5.7000000e+00 4.7000000e+00 5.1000000e+00 8.3000000e+00 6.9000000e+00 8.9000000e+00 7.6000000e+00 8.3000000e+00 1.0100000e+01 7.0000000e+00 9.3000000e+00 8.6000000e+00 9.0000000e+00 7.2000000e+00 7.7000000e+00 8.2000000e+00 7.0000000e+00 7.3000000e+00 7.6000000e+00 7.6000000e+00 9.6000000e+00 1.1100000e+01 7.1000000e+00 8.5000000e+00 6.7000000e+00 1.0400000e+01 7.1000000e+00 8.0000000e+00 8.6000000e+00 6.8000000e+00 6.6000000e+00 8.1000000e+00 8.4000000e+00 9.4000000e+00 9.3000000e+00 8.2000000e+00 6.9000000e+00 7.3000000e+00 9.9000000e+00 7.7000000e+00 7.4000000e+00 6.4000000e+00 8.1000000e+00 8.4000000e+00 8.0000000e+00 6.9000000e+00 8.6000000e+00 8.4000000e+00 8.0000000e+00 7.5000000e+00 7.5000000e+00 7.3000000e+00 6.6000000e+00 9.0000000e-01 9.0000000e-01 7.0000000e-01 1.1000000e+00 7.0000000e-01 1.6000000e+00 1.4000000e+00 1.9000000e+00 1.8000000e+00 1.2000000e+00 1.0000000e+00 1.0000000e+00 1.9000000e+00 1.9000000e+00 7.0000000e-01 9.0000000e-01 7.0000000e-01 1.8000000e+00 1.4000000e+00 7.0000000e-01 1.8000000e+00 2.1000000e+00 1.2000000e+00 9.0000000e-01 2.6000000e+00 1.9000000e+00 1.3000000e+00 1.0000000e+00 1.7000000e+00 9.0000000e-01 1.8000000e+00 7.0000000e-01 1.3000000e+00 6.7000000e+00 6.0000000e+00 7.0000000e+00 5.3000000e+00 6.6000000e+00 5.5000000e+00 6.1000000e+00 4.6000000e+00 6.4000000e+00 5.0000000e+00 5.1000000e+00 5.4000000e+00 5.6000000e+00 6.1000000e+00 4.4000000e+00 6.2000000e+00 5.4000000e+00 5.0000000e+00 6.8000000e+00 4.9000000e+00 6.1000000e+00 5.4000000e+00 7.0000000e+00 6.0000000e+00 5.9000000e+00 6.2000000e+00 7.0000000e+00 7.2000000e+00 5.9000000e+00 4.4000000e+00 4.8000000e+00 4.6000000e+00 5.0000000e+00 6.8000000e+00 5.2000000e+00 5.5000000e+00 6.6000000e+00 6.5000000e+00 4.8000000e+00 5.1000000e+00 5.3000000e+00 5.9000000e+00 5.2000000e+00 4.6000000e+00 5.2000000e+00 4.9000000e+00 5.1000000e+00 5.7000000e+00 4.1000000e+00 5.1000000e+00 8.3000000e+00 6.9000000e+00 8.9000000e+00 7.6000000e+00 8.3000000e+00 1.0100000e+01 6.4000000e+00 9.3000000e+00 8.6000000e+00 9.0000000e+00 7.2000000e+00 7.7000000e+00 8.2000000e+00 7.0000000e+00 7.3000000e+00 7.6000000e+00 7.6000000e+00 9.6000000e+00 1.1100000e+01 7.1000000e+00 8.5000000e+00 6.5000000e+00 1.0400000e+01 7.1000000e+00 8.0000000e+00 8.6000000e+00 6.8000000e+00 6.6000000e+00 8.1000000e+00 8.4000000e+00 9.4000000e+00 9.3000000e+00 8.2000000e+00 6.9000000e+00 7.3000000e+00 9.9000000e+00 7.7000000e+00 7.4000000e+00 6.4000000e+00 8.1000000e+00 8.4000000e+00 8.0000000e+00 6.9000000e+00 8.6000000e+00 8.4000000e+00 8.0000000e+00 7.5000000e+00 7.5000000e+00 7.3000000e+00 6.6000000e+00 1.2000000e+00 4.0000000e-01 8.0000000e-01 4.0000000e-01 1.1000000e+00 7.0000000e-01 1.0000000e+00 9.0000000e-01 5.0000000e-01 3.0000000e-01 3.0000000e-01 1.0000000e+00 1.0000000e+00 6.0000000e-01 1.0000000e+00 1.2000000e+00 9.0000000e-01 7.0000000e-01 6.0000000e-01 9.0000000e-01 1.4000000e+00 3.0000000e-01 2.0000000e-01 1.9000000e+00 1.2000000e+00 6.0000000e-01 9.0000000e-01 8.0000000e-01 6.0000000e-01 9.0000000e-01 6.0000000e-01 4.0000000e-01 6.6000000e+00 5.9000000e+00 6.9000000e+00 5.2000000e+00 6.5000000e+00 5.4000000e+00 6.0000000e+00 3.9000000e+00 6.3000000e+00 4.5000000e+00 4.4000000e+00 5.3000000e+00 5.5000000e+00 6.0000000e+00 4.3000000e+00 6.1000000e+00 5.3000000e+00 4.9000000e+00 6.7000000e+00 4.8000000e+00 6.0000000e+00 5.3000000e+00 6.9000000e+00 5.9000000e+00 5.8000000e+00 6.1000000e+00 6.9000000e+00 7.1000000e+00 5.8000000e+00 4.3000000e+00 4.7000000e+00 4.5000000e+00 4.9000000e+00 6.7000000e+00 5.1000000e+00 5.4000000e+00 6.5000000e+00 6.4000000e+00 4.7000000e+00 5.0000000e+00 5.2000000e+00 5.8000000e+00 5.1000000e+00 3.9000000e+00 5.1000000e+00 4.8000000e+00 5.0000000e+00 5.6000000e+00 3.4000000e+00 5.0000000e+00 8.2000000e+00 6.8000000e+00 8.8000000e+00 7.5000000e+00 8.2000000e+00 1.0000000e+01 5.7000000e+00 9.2000000e+00 8.5000000e+00 9.1000000e+00 7.1000000e+00 7.6000000e+00 8.1000000e+00 6.9000000e+00 7.2000000e+00 7.5000000e+00 7.5000000e+00 1.0100000e+01 1.1000000e+01 7.0000000e+00 8.4000000e+00 6.4000000e+00 1.0300000e+01 7.0000000e+00 7.9000000e+00 8.5000000e+00 6.7000000e+00 6.5000000e+00 8.0000000e+00 8.3000000e+00 9.3000000e+00 9.8000000e+00 8.1000000e+00 6.8000000e+00 7.2000000e+00 9.8000000e+00 7.6000000e+00 7.3000000e+00 6.3000000e+00 8.0000000e+00 8.3000000e+00 7.9000000e+00 6.8000000e+00 8.5000000e+00 8.3000000e+00 7.9000000e+00 7.4000000e+00 7.4000000e+00 7.2000000e+00 6.5000000e+00 8.0000000e-01 8.0000000e-01 1.0000000e+00 2.1000000e+00 1.3000000e+00 1.6000000e+00 1.7000000e+00 1.3000000e+00 1.1000000e+00 1.3000000e+00 1.8000000e+00 1.8000000e+00 1.0000000e+00 1.2000000e+00 1.0000000e+00 1.9000000e+00 1.9000000e+00 1.0000000e+00 1.9000000e+00 2.6000000e+00 1.3000000e+00 1.4000000e+00 3.1000000e+00 2.4000000e+00 1.4000000e+00 9.0000000e-01 2.0000000e+00 8.0000000e-01 2.1000000e+00 8.0000000e-01 1.6000000e+00 6.0000000e+00 5.3000000e+00 6.3000000e+00 5.0000000e+00 5.9000000e+00 4.8000000e+00 5.4000000e+00 4.5000000e+00 5.7000000e+00 4.9000000e+00 5.0000000e+00 4.7000000e+00 4.9000000e+00 5.4000000e+00 3.9000000e+00 5.5000000e+00 4.9000000e+00 4.3000000e+00 6.1000000e+00 4.4000000e+00 5.4000000e+00 4.7000000e+00 6.3000000e+00 5.3000000e+00 5.2000000e+00 5.5000000e+00 6.3000000e+00 6.5000000e+00 5.2000000e+00 3.7000000e+00 4.5000000e+00 4.3000000e+00 4.3000000e+00 6.1000000e+00 5.1000000e+00 4.8000000e+00 5.9000000e+00 5.8000000e+00 4.3000000e+00 4.8000000e+00 5.0000000e+00 5.2000000e+00 4.5000000e+00 4.5000000e+00 4.7000000e+00 4.2000000e+00 4.4000000e+00 5.0000000e+00 4.0000000e+00 4.4000000e+00 7.6000000e+00 6.2000000e+00 8.2000000e+00 6.9000000e+00 7.6000000e+00 9.4000000e+00 6.3000000e+00 8.6000000e+00 7.9000000e+00 8.3000000e+00 6.5000000e+00 7.0000000e+00 7.5000000e+00 6.3000000e+00 6.6000000e+00 6.9000000e+00 6.9000000e+00 8.9000000e+00 1.0400000e+01 6.4000000e+00 7.8000000e+00 6.0000000e+00 9.7000000e+00 6.4000000e+00 7.3000000e+00 7.9000000e+00 6.1000000e+00 5.9000000e+00 7.4000000e+00 7.7000000e+00 8.7000000e+00 8.6000000e+00 7.5000000e+00 6.2000000e+00 6.6000000e+00 9.2000000e+00 7.0000000e+00 6.7000000e+00 5.7000000e+00 7.4000000e+00 7.7000000e+00 7.3000000e+00 6.2000000e+00 7.9000000e+00 7.7000000e+00 7.3000000e+00 6.8000000e+00 6.8000000e+00 6.6000000e+00 5.9000000e+00 1.0000000e+00 2.0000000e-01 1.3000000e+00 9.0000000e-01 1.2000000e+00 1.1000000e+00 7.0000000e-01 5.0000000e-01 7.0000000e-01 1.2000000e+00 1.2000000e+00 8.0000000e-01 6.0000000e-01 1.0000000e+00 1.1000000e+00 1.1000000e+00 1.0000000e+00 1.1000000e+00 1.8000000e+00 5.0000000e-01 6.0000000e-01 2.3000000e+00 1.6000000e+00 8.0000000e-01 5.0000000e-01 1.2000000e+00 2.0000000e-01 1.3000000e+00 4.0000000e-01 8.0000000e-01 6.8000000e+00 6.1000000e+00 7.1000000e+00 5.4000000e+00 6.7000000e+00 5.6000000e+00 6.2000000e+00 4.1000000e+00 6.5000000e+00 4.7000000e+00 4.6000000e+00 5.5000000e+00 5.7000000e+00 6.2000000e+00 4.5000000e+00 6.3000000e+00 5.5000000e+00 5.1000000e+00 6.9000000e+00 5.0000000e+00 6.2000000e+00 5.5000000e+00 7.1000000e+00 6.1000000e+00 6.0000000e+00 6.3000000e+00 7.1000000e+00 7.3000000e+00 6.0000000e+00 4.5000000e+00 4.9000000e+00 4.7000000e+00 5.1000000e+00 6.9000000e+00 5.3000000e+00 5.6000000e+00 6.7000000e+00 6.6000000e+00 4.9000000e+00 5.2000000e+00 5.4000000e+00 6.0000000e+00 5.3000000e+00 4.1000000e+00 5.3000000e+00 5.0000000e+00 5.2000000e+00 5.8000000e+00 3.6000000e+00 5.2000000e+00 8.4000000e+00 7.0000000e+00 9.0000000e+00 7.7000000e+00 8.4000000e+00 1.0200000e+01 5.9000000e+00 9.4000000e+00 8.7000000e+00 9.1000000e+00 7.3000000e+00 7.8000000e+00 8.3000000e+00 7.1000000e+00 7.4000000e+00 7.7000000e+00 7.7000000e+00 9.7000000e+00 1.1200000e+01 7.2000000e+00 8.6000000e+00 6.6000000e+00 1.0500000e+01 7.2000000e+00 8.1000000e+00 8.7000000e+00 6.9000000e+00 6.7000000e+00 8.2000000e+00 8.5000000e+00 9.5000000e+00 9.4000000e+00 8.3000000e+00 7.0000000e+00 7.4000000e+00 1.0000000e+01 7.8000000e+00 7.5000000e+00 6.5000000e+00 8.2000000e+00 8.5000000e+00 8.1000000e+00 7.0000000e+00 8.7000000e+00 8.5000000e+00 8.1000000e+00 7.6000000e+00 7.6000000e+00 7.4000000e+00 6.7000000e+00 1.0000000e+00 1.7000000e+00 7.0000000e-01 8.0000000e-01 9.0000000e-01 7.0000000e-01 5.0000000e-01 5.0000000e-01 1.0000000e+00 1.0000000e+00 4.0000000e-01 1.2000000e+00 1.2000000e+00 1.1000000e+00 1.1000000e+00 6.0000000e-01 1.1000000e+00 1.8000000e+00 5.0000000e-01 1.0000000e+00 2.5000000e+00 1.6000000e+00 1.0000000e+00 1.1000000e+00 1.4000000e+00 8.0000000e-01 1.3000000e+00 6.0000000e-01 8.0000000e-01 6.0000000e+00 5.3000000e+00 6.3000000e+00 4.6000000e+00 5.9000000e+00 4.8000000e+00 5.4000000e+00 3.9000000e+00 5.7000000e+00 4.3000000e+00 4.4000000e+00 4.7000000e+00 4.9000000e+00 5.4000000e+00 3.7000000e+00 5.5000000e+00 4.7000000e+00 4.3000000e+00 6.1000000e+00 4.2000000e+00 5.4000000e+00 4.7000000e+00 6.3000000e+00 5.3000000e+00 5.2000000e+00 5.5000000e+00 6.3000000e+00 6.5000000e+00 5.2000000e+00 3.7000000e+00 4.1000000e+00 3.9000000e+00 4.3000000e+00 6.1000000e+00 4.5000000e+00 4.8000000e+00 5.9000000e+00 5.8000000e+00 4.1000000e+00 4.4000000e+00 4.6000000e+00 5.2000000e+00 4.5000000e+00 3.9000000e+00 4.5000000e+00 4.2000000e+00 4.4000000e+00 5.0000000e+00 3.4000000e+00 4.4000000e+00 7.6000000e+00 6.2000000e+00 8.2000000e+00 6.9000000e+00 7.6000000e+00 9.4000000e+00 5.7000000e+00 8.6000000e+00 7.9000000e+00 8.7000000e+00 6.5000000e+00 7.0000000e+00 7.5000000e+00 6.3000000e+00 6.6000000e+00 6.9000000e+00 6.9000000e+00 9.7000000e+00 1.0400000e+01 6.4000000e+00 7.8000000e+00 5.8000000e+00 9.7000000e+00 6.4000000e+00 7.3000000e+00 7.9000000e+00 6.1000000e+00 5.9000000e+00 7.4000000e+00 7.7000000e+00 8.7000000e+00 9.4000000e+00 7.5000000e+00 6.2000000e+00 6.6000000e+00 9.2000000e+00 7.0000000e+00 6.7000000e+00 5.7000000e+00 7.4000000e+00 7.7000000e+00 7.3000000e+00 6.2000000e+00 7.9000000e+00 7.7000000e+00 7.3000000e+00 6.8000000e+00 6.8000000e+00 6.6000000e+00 5.9000000e+00 1.3000000e+00 7.0000000e-01 1.2000000e+00 1.1000000e+00 5.0000000e-01 5.0000000e-01 7.0000000e-01 1.2000000e+00 1.2000000e+00 6.0000000e-01 8.0000000e-01 1.2000000e+00 1.1000000e+00 1.1000000e+00 1.0000000e+00 1.1000000e+00 1.8000000e+00 5.0000000e-01 6.0000000e-01 2.3000000e+00 1.6000000e+00 6.0000000e-01 5.0000000e-01 1.2000000e+00 4.0000000e-01 1.3000000e+00 4.0000000e-01 8.0000000e-01 6.6000000e+00 5.9000000e+00 6.9000000e+00 5.2000000e+00 6.5000000e+00 5.4000000e+00 6.0000000e+00 3.9000000e+00 6.3000000e+00 4.5000000e+00 4.4000000e+00 5.3000000e+00 5.5000000e+00 6.0000000e+00 4.3000000e+00 6.1000000e+00 5.3000000e+00 4.9000000e+00 6.7000000e+00 4.8000000e+00 6.0000000e+00 5.3000000e+00 6.9000000e+00 5.9000000e+00 5.8000000e+00 6.1000000e+00 6.9000000e+00 7.1000000e+00 5.8000000e+00 4.3000000e+00 4.7000000e+00 4.5000000e+00 4.9000000e+00 6.7000000e+00 5.1000000e+00 5.4000000e+00 6.5000000e+00 6.4000000e+00 4.7000000e+00 5.0000000e+00 5.2000000e+00 5.8000000e+00 5.1000000e+00 3.9000000e+00 5.1000000e+00 4.8000000e+00 5.0000000e+00 5.6000000e+00 3.4000000e+00 5.0000000e+00 8.2000000e+00 6.8000000e+00 8.8000000e+00 7.5000000e+00 8.2000000e+00 1.0000000e+01 5.7000000e+00 9.2000000e+00 8.5000000e+00 8.9000000e+00 7.1000000e+00 7.6000000e+00 8.1000000e+00 6.9000000e+00 7.2000000e+00 7.5000000e+00 7.5000000e+00 9.7000000e+00 1.1000000e+01 7.0000000e+00 8.4000000e+00 6.4000000e+00 1.0300000e+01 7.0000000e+00 7.9000000e+00 8.5000000e+00 6.7000000e+00 6.5000000e+00 8.0000000e+00 8.3000000e+00 9.3000000e+00 9.4000000e+00 8.1000000e+00 6.8000000e+00 7.2000000e+00 9.8000000e+00 7.6000000e+00 7.3000000e+00 6.3000000e+00 8.0000000e+00 8.3000000e+00 7.9000000e+00 6.8000000e+00 8.5000000e+00 8.3000000e+00 7.9000000e+00 7.4000000e+00 7.4000000e+00 7.2000000e+00 6.5000000e+00 1.8000000e+00 1.3000000e+00 1.6000000e+00 1.4000000e+00 1.2000000e+00 1.2000000e+00 1.1000000e+00 1.3000000e+00 1.7000000e+00 1.7000000e+00 1.9000000e+00 1.4000000e+00 1.0000000e+00 1.3000000e+00 1.4000000e+00 1.1000000e+00 1.2000000e+00 9.0000000e-01 1.8000000e+00 9.0000000e-01 1.5000000e+00 1.8000000e+00 1.3000000e+00 1.3000000e+00 8.0000000e-01 1.3000000e+00 1.1000000e+00 7.7000000e+00 7.0000000e+00 8.0000000e+00 6.3000000e+00 7.6000000e+00 6.5000000e+00 7.1000000e+00 4.6000000e+00 7.4000000e+00 5.6000000e+00 5.3000000e+00 6.4000000e+00 6.6000000e+00 7.1000000e+00 5.4000000e+00 7.2000000e+00 6.4000000e+00 6.0000000e+00 7.8000000e+00 5.9000000e+00 7.1000000e+00 6.4000000e+00 8.0000000e+00 7.0000000e+00 6.9000000e+00 7.2000000e+00 8.0000000e+00 8.2000000e+00 6.9000000e+00 5.4000000e+00 5.8000000e+00 5.6000000e+00 6.0000000e+00 7.8000000e+00 6.2000000e+00 6.5000000e+00 7.6000000e+00 7.5000000e+00 5.8000000e+00 6.1000000e+00 6.3000000e+00 6.9000000e+00 6.2000000e+00 4.8000000e+00 6.2000000e+00 5.9000000e+00 6.1000000e+00 6.7000000e+00 4.5000000e+00 6.1000000e+00 9.3000000e+00 7.9000000e+00 9.9000000e+00 8.6000000e+00 9.3000000e+00 1.1100000e+01 6.4000000e+00 1.0300000e+01 9.6000000e+00 1.0000000e+01 8.2000000e+00 8.7000000e+00 9.2000000e+00 8.0000000e+00 8.3000000e+00 8.6000000e+00 8.6000000e+00 1.1000000e+01 1.2100000e+01 8.1000000e+00 9.5000000e+00 7.5000000e+00 1.1400000e+01 8.1000000e+00 9.0000000e+00 9.6000000e+00 7.8000000e+00 7.6000000e+00 9.1000000e+00 9.4000000e+00 1.0400000e+01 1.0700000e+01 9.2000000e+00 7.9000000e+00 8.3000000e+00 1.0900000e+01 8.7000000e+00 8.4000000e+00 7.4000000e+00 9.1000000e+00 9.4000000e+00 9.0000000e+00 7.9000000e+00 9.6000000e+00 9.4000000e+00 9.0000000e+00 8.5000000e+00 8.5000000e+00 8.3000000e+00 7.6000000e+00 9.0000000e-01 8.0000000e-01 4.0000000e-01 8.0000000e-01 8.0000000e-01 9.0000000e-01 9.0000000e-01 7.0000000e-01 1.5000000e+00 1.9000000e+00 1.0000000e+00 1.0000000e+00 1.3000000e+00 1.0000000e+00 1.7000000e+00 6.0000000e-01 9.0000000e-01 2.2000000e+00 1.5000000e+00 5.0000000e-01 8.0000000e-01 1.1000000e+00 9.0000000e-01 1.2000000e+00 1.1000000e+00 7.0000000e-01 5.9000000e+00 5.2000000e+00 6.2000000e+00 4.5000000e+00 5.8000000e+00 4.7000000e+00 5.3000000e+00 3.2000000e+00 5.6000000e+00 3.8000000e+00 3.7000000e+00 4.6000000e+00 4.8000000e+00 5.3000000e+00 3.6000000e+00 5.4000000e+00 4.6000000e+00 4.2000000e+00 6.0000000e+00 4.1000000e+00 5.3000000e+00 4.6000000e+00 6.2000000e+00 5.2000000e+00 5.1000000e+00 5.4000000e+00 6.2000000e+00 6.4000000e+00 5.1000000e+00 3.6000000e+00 4.0000000e+00 3.8000000e+00 4.2000000e+00 6.0000000e+00 4.4000000e+00 4.9000000e+00 5.8000000e+00 5.7000000e+00 4.0000000e+00 4.3000000e+00 4.5000000e+00 5.1000000e+00 4.4000000e+00 3.2000000e+00 4.4000000e+00 4.1000000e+00 4.3000000e+00 4.9000000e+00 2.7000000e+00 4.3000000e+00 7.5000000e+00 6.1000000e+00 8.1000000e+00 6.8000000e+00 7.5000000e+00 9.3000000e+00 5.0000000e+00 8.5000000e+00 7.8000000e+00 8.8000000e+00 6.4000000e+00 6.9000000e+00 7.4000000e+00 6.2000000e+00 6.5000000e+00 6.8000000e+00 6.8000000e+00 9.8000000e+00 1.0300000e+01 6.3000000e+00 7.7000000e+00 5.7000000e+00 9.6000000e+00 6.3000000e+00 7.2000000e+00 7.8000000e+00 6.0000000e+00 5.8000000e+00 7.3000000e+00 7.6000000e+00 8.6000000e+00 9.5000000e+00 7.4000000e+00 6.1000000e+00 6.5000000e+00 9.1000000e+00 7.1000000e+00 6.6000000e+00 5.6000000e+00 7.3000000e+00 7.6000000e+00 7.2000000e+00 6.1000000e+00 7.8000000e+00 7.6000000e+00 7.2000000e+00 6.7000000e+00 6.7000000e+00 6.7000000e+00 5.8000000e+00 9.0000000e-01 7.0000000e-01 9.0000000e-01 9.0000000e-01 6.0000000e-01 6.0000000e-01 1.2000000e+00 1.6000000e+00 2.0000000e+00 9.0000000e-01 1.1000000e+00 1.4000000e+00 9.0000000e-01 1.4000000e+00 7.0000000e-01 1.0000000e+00 2.1000000e+00 1.2000000e+00 1.0000000e+00 9.0000000e-01 1.0000000e+00 1.0000000e+00 9.0000000e-01 1.2000000e+00 8.0000000e-01 6.4000000e+00 5.7000000e+00 6.7000000e+00 5.0000000e+00 6.3000000e+00 5.2000000e+00 5.8000000e+00 3.3000000e+00 6.1000000e+00 4.3000000e+00 4.0000000e+00 5.1000000e+00 5.3000000e+00 5.8000000e+00 4.1000000e+00 5.9000000e+00 5.1000000e+00 4.7000000e+00 6.5000000e+00 4.6000000e+00 5.8000000e+00 5.1000000e+00 6.7000000e+00 5.7000000e+00 5.6000000e+00 5.9000000e+00 6.7000000e+00 6.9000000e+00 5.6000000e+00 4.1000000e+00 4.5000000e+00 4.3000000e+00 4.7000000e+00 6.5000000e+00 4.9000000e+00 5.2000000e+00 6.3000000e+00 6.2000000e+00 4.5000000e+00 4.8000000e+00 5.0000000e+00 5.6000000e+00 4.9000000e+00 3.5000000e+00 4.9000000e+00 4.6000000e+00 4.8000000e+00 5.4000000e+00 3.2000000e+00 4.8000000e+00 8.0000000e+00 6.6000000e+00 8.6000000e+00 7.3000000e+00 8.0000000e+00 9.8000000e+00 5.1000000e+00 9.0000000e+00 8.3000000e+00 9.1000000e+00 6.9000000e+00 7.4000000e+00 7.9000000e+00 6.7000000e+00 7.0000000e+00 7.3000000e+00 7.3000000e+00 1.0100000e+01 1.0800000e+01 6.8000000e+00 8.2000000e+00 6.2000000e+00 1.0100000e+01 6.8000000e+00 7.7000000e+00 8.3000000e+00 6.5000000e+00 6.3000000e+00 7.8000000e+00 8.1000000e+00 9.1000000e+00 9.8000000e+00 7.9000000e+00 6.6000000e+00 7.0000000e+00 9.6000000e+00 7.4000000e+00 7.1000000e+00 6.1000000e+00 7.8000000e+00 8.1000000e+00 7.7000000e+00 6.6000000e+00 8.3000000e+00 8.1000000e+00 7.7000000e+00 7.2000000e+00 7.2000000e+00 7.0000000e+00 6.3000000e+00 6.0000000e-01 8.0000000e-01 8.0000000e-01 5.0000000e-01 3.0000000e-01 1.1000000e+00 1.5000000e+00 1.9000000e+00 4.0000000e-01 6.0000000e-01 1.3000000e+00 4.0000000e-01 9.0000000e-01 6.0000000e-01 9.0000000e-01 1.6000000e+00 1.1000000e+00 9.0000000e-01 1.4000000e+00 5.0000000e-01 9.0000000e-01 8.0000000e-01 1.1000000e+00 5.0000000e-01 6.5000000e+00 5.8000000e+00 6.6000000e+00 4.7000000e+00 6.0000000e+00 4.9000000e+00 6.1000000e+00 3.2000000e+00 5.8000000e+00 4.0000000e+00 3.7000000e+00 4.8000000e+00 5.0000000e+00 5.5000000e+00 3.8000000e+00 5.8000000e+00 4.8000000e+00 4.4000000e+00 6.2000000e+00 4.3000000e+00 5.9000000e+00 4.8000000e+00 6.4000000e+00 5.4000000e+00 5.3000000e+00 5.6000000e+00 6.4000000e+00 6.6000000e+00 5.3000000e+00 3.8000000e+00 4.2000000e+00 4.0000000e+00 4.4000000e+00 6.2000000e+00 4.6000000e+00 5.7000000e+00 6.2000000e+00 5.9000000e+00 4.2000000e+00 4.5000000e+00 4.7000000e+00 5.3000000e+00 4.6000000e+00 3.2000000e+00 4.6000000e+00 4.3000000e+00 4.5000000e+00 5.1000000e+00 2.9000000e+00 4.5000000e+00 8.3000000e+00 6.3000000e+00 8.3000000e+00 7.0000000e+00 7.7000000e+00 9.5000000e+00 5.0000000e+00 8.7000000e+00 8.0000000e+00 9.6000000e+00 7.0000000e+00 7.1000000e+00 7.6000000e+00 6.4000000e+00 6.7000000e+00 7.4000000e+00 7.0000000e+00 1.0600000e+01 1.0500000e+01 6.5000000e+00 8.3000000e+00 5.9000000e+00 9.8000000e+00 6.5000000e+00 8.0000000e+00 8.4000000e+00 6.2000000e+00 6.0000000e+00 7.5000000e+00 7.8000000e+00 8.8000000e+00 1.0300000e+01 7.6000000e+00 6.3000000e+00 6.7000000e+00 9.3000000e+00 7.9000000e+00 7.0000000e+00 5.8000000e+00 7.7000000e+00 8.0000000e+00 7.6000000e+00 6.3000000e+00 8.4000000e+00 8.4000000e+00 7.4000000e+00 6.9000000e+00 6.9000000e+00 7.5000000e+00 6.0000000e+00 6.0000000e-01 6.0000000e-01 7.0000000e-01 7.0000000e-01 5.0000000e-01 1.3000000e+00 1.7000000e+00 8.0000000e-01 8.0000000e-01 1.1000000e+00 8.0000000e-01 1.5000000e+00 4.0000000e-01 5.0000000e-01 2.0000000e+00 1.3000000e+00 3.0000000e-01 8.0000000e-01 9.0000000e-01 7.0000000e-01 1.0000000e+00 9.0000000e-01 5.0000000e-01 6.3000000e+00 5.6000000e+00 6.6000000e+00 4.9000000e+00 6.2000000e+00 5.1000000e+00 5.7000000e+00 3.4000000e+00 6.0000000e+00 4.2000000e+00 3.9000000e+00 5.0000000e+00 5.2000000e+00 5.7000000e+00 4.0000000e+00 5.8000000e+00 5.0000000e+00 4.6000000e+00 6.4000000e+00 4.5000000e+00 5.7000000e+00 5.0000000e+00 6.6000000e+00 5.6000000e+00 5.5000000e+00 5.8000000e+00 6.6000000e+00 6.8000000e+00 5.5000000e+00 4.0000000e+00 4.4000000e+00 4.2000000e+00 4.6000000e+00 6.4000000e+00 4.8000000e+00 5.1000000e+00 6.2000000e+00 6.1000000e+00 4.4000000e+00 4.7000000e+00 4.9000000e+00 5.5000000e+00 4.8000000e+00 3.4000000e+00 4.8000000e+00 4.5000000e+00 4.7000000e+00 5.3000000e+00 3.1000000e+00 4.7000000e+00 7.9000000e+00 6.5000000e+00 8.5000000e+00 7.2000000e+00 7.9000000e+00 9.7000000e+00 5.2000000e+00 8.9000000e+00 8.2000000e+00 9.0000000e+00 6.8000000e+00 7.3000000e+00 7.8000000e+00 6.6000000e+00 6.9000000e+00 7.2000000e+00 7.2000000e+00 1.0000000e+01 1.0700000e+01 6.7000000e+00 8.1000000e+00 6.1000000e+00 1.0000000e+01 6.7000000e+00 7.6000000e+00 8.2000000e+00 6.4000000e+00 6.2000000e+00 7.7000000e+00 8.0000000e+00 9.0000000e+00 9.7000000e+00 7.8000000e+00 6.5000000e+00 6.9000000e+00 9.5000000e+00 7.3000000e+00 7.0000000e+00 6.0000000e+00 7.7000000e+00 8.0000000e+00 7.6000000e+00 6.5000000e+00 8.2000000e+00 8.0000000e+00 7.6000000e+00 7.1000000e+00 7.1000000e+00 6.9000000e+00 6.2000000e+00 2.0000000e-01 9.0000000e-01 9.0000000e-01 5.0000000e-01 7.0000000e-01 1.1000000e+00 8.0000000e-01 8.0000000e-01 5.0000000e-01 8.0000000e-01 1.5000000e+00 2.0000000e-01 5.0000000e-01 2.2000000e+00 1.3000000e+00 7.0000000e-01 1.0000000e+00 1.1000000e+00 5.0000000e-01 1.0000000e+00 3.0000000e-01 5.0000000e-01 6.5000000e+00 5.8000000e+00 6.8000000e+00 5.1000000e+00 6.4000000e+00 5.3000000e+00 5.9000000e+00 4.0000000e+00 6.2000000e+00 4.4000000e+00 4.5000000e+00 5.2000000e+00 5.4000000e+00 5.9000000e+00 4.2000000e+00 6.0000000e+00 5.2000000e+00 4.8000000e+00 6.6000000e+00 4.7000000e+00 5.9000000e+00 5.2000000e+00 6.8000000e+00 5.8000000e+00 5.7000000e+00 6.0000000e+00 6.8000000e+00 7.0000000e+00 5.7000000e+00 4.2000000e+00 4.6000000e+00 4.4000000e+00 4.8000000e+00 6.6000000e+00 5.0000000e+00 5.3000000e+00 6.4000000e+00 6.3000000e+00 4.6000000e+00 4.9000000e+00 5.1000000e+00 5.7000000e+00 5.0000000e+00 4.0000000e+00 5.0000000e+00 4.7000000e+00 4.9000000e+00 5.5000000e+00 3.5000000e+00 4.9000000e+00 8.1000000e+00 6.7000000e+00 8.7000000e+00 7.4000000e+00 8.1000000e+00 9.9000000e+00 5.8000000e+00 9.1000000e+00 8.4000000e+00 9.0000000e+00 7.0000000e+00 7.5000000e+00 8.0000000e+00 6.8000000e+00 7.1000000e+00 7.4000000e+00 7.4000000e+00 1.0000000e+01 1.0900000e+01 6.9000000e+00 8.3000000e+00 6.3000000e+00 1.0200000e+01 6.9000000e+00 7.8000000e+00 8.4000000e+00 6.6000000e+00 6.4000000e+00 7.9000000e+00 8.2000000e+00 9.2000000e+00 9.7000000e+00 8.0000000e+00 6.7000000e+00 7.1000000e+00 9.7000000e+00 7.5000000e+00 7.2000000e+00 6.2000000e+00 7.9000000e+00 8.2000000e+00 7.8000000e+00 6.7000000e+00 8.4000000e+00 8.2000000e+00 7.8000000e+00 7.3000000e+00 7.3000000e+00 7.1000000e+00 6.4000000e+00 9.0000000e-01 9.0000000e-01 5.0000000e-01 9.0000000e-01 1.1000000e+00 8.0000000e-01 6.0000000e-01 5.0000000e-01 8.0000000e-01 1.3000000e+00 2.0000000e-01 5.0000000e-01 2.0000000e+00 1.1000000e+00 9.0000000e-01 1.2000000e+00 9.0000000e-01 7.0000000e-01 8.0000000e-01 5.0000000e-01 3.0000000e-01 6.5000000e+00 5.8000000e+00 6.8000000e+00 5.1000000e+00 6.4000000e+00 5.3000000e+00 5.9000000e+00 4.0000000e+00 6.2000000e+00 4.4000000e+00 4.5000000e+00 5.2000000e+00 5.4000000e+00 5.9000000e+00 4.2000000e+00 6.0000000e+00 5.2000000e+00 4.8000000e+00 6.6000000e+00 4.7000000e+00 5.9000000e+00 5.2000000e+00 6.8000000e+00 5.8000000e+00 5.7000000e+00 6.0000000e+00 6.8000000e+00 7.0000000e+00 5.7000000e+00 4.2000000e+00 4.6000000e+00 4.4000000e+00 4.8000000e+00 6.6000000e+00 5.0000000e+00 5.3000000e+00 6.4000000e+00 6.3000000e+00 4.6000000e+00 4.9000000e+00 5.1000000e+00 5.7000000e+00 5.0000000e+00 4.0000000e+00 5.0000000e+00 4.7000000e+00 4.9000000e+00 5.5000000e+00 3.5000000e+00 4.9000000e+00 8.1000000e+00 6.7000000e+00 8.7000000e+00 7.4000000e+00 8.1000000e+00 9.9000000e+00 5.8000000e+00 9.1000000e+00 8.4000000e+00 9.2000000e+00 7.0000000e+00 7.5000000e+00 8.0000000e+00 6.8000000e+00 7.1000000e+00 7.4000000e+00 7.4000000e+00 1.0200000e+01 1.0900000e+01 6.9000000e+00 8.3000000e+00 6.3000000e+00 1.0200000e+01 6.9000000e+00 7.8000000e+00 8.4000000e+00 6.6000000e+00 6.4000000e+00 7.9000000e+00 8.2000000e+00 9.2000000e+00 9.9000000e+00 8.0000000e+00 6.7000000e+00 7.1000000e+00 9.7000000e+00 7.5000000e+00 7.2000000e+00 6.2000000e+00 7.9000000e+00 8.2000000e+00 7.8000000e+00 6.7000000e+00 8.4000000e+00 8.2000000e+00 7.8000000e+00 7.3000000e+00 7.3000000e+00 7.1000000e+00 6.4000000e+00 2.0000000e-01 1.2000000e+00 1.6000000e+00 2.0000000e+00 5.0000000e-01 7.0000000e-01 1.4000000e+00 5.0000000e-01 8.0000000e-01 7.0000000e-01 1.0000000e+00 1.5000000e+00 6.0000000e-01 1.0000000e+00 1.5000000e+00 6.0000000e-01 1.0000000e+00 3.0000000e-01 1.2000000e+00 6.0000000e-01 6.6000000e+00 5.9000000e+00 6.9000000e+00 5.2000000e+00 6.5000000e+00 5.4000000e+00 6.2000000e+00 3.5000000e+00 6.3000000e+00 4.5000000e+00 4.2000000e+00 5.3000000e+00 5.5000000e+00 6.0000000e+00 4.3000000e+00 6.1000000e+00 5.3000000e+00 4.9000000e+00 6.7000000e+00 4.8000000e+00 6.0000000e+00 5.3000000e+00 6.9000000e+00 5.9000000e+00 5.8000000e+00 6.1000000e+00 6.9000000e+00 7.1000000e+00 5.8000000e+00 4.3000000e+00 4.7000000e+00 4.5000000e+00 4.9000000e+00 6.7000000e+00 5.1000000e+00 5.8000000e+00 6.5000000e+00 6.4000000e+00 4.7000000e+00 5.0000000e+00 5.2000000e+00 5.8000000e+00 5.1000000e+00 3.7000000e+00 5.1000000e+00 4.8000000e+00 5.0000000e+00 5.6000000e+00 3.4000000e+00 5.0000000e+00 8.4000000e+00 6.8000000e+00 8.8000000e+00 7.5000000e+00 8.2000000e+00 1.0000000e+01 5.3000000e+00 9.2000000e+00 8.5000000e+00 9.7000000e+00 7.1000000e+00 7.6000000e+00 8.1000000e+00 6.9000000e+00 7.2000000e+00 7.5000000e+00 7.5000000e+00 1.0700000e+01 1.1000000e+01 7.0000000e+00 8.4000000e+00 6.4000000e+00 1.0300000e+01 7.0000000e+00 8.1000000e+00 8.5000000e+00 6.7000000e+00 6.5000000e+00 8.0000000e+00 8.3000000e+00 9.3000000e+00 1.0400000e+01 8.1000000e+00 6.8000000e+00 7.2000000e+00 9.8000000e+00 8.0000000e+00 7.3000000e+00 6.3000000e+00 8.0000000e+00 8.3000000e+00 7.9000000e+00 6.8000000e+00 8.5000000e+00 8.5000000e+00 7.9000000e+00 7.4000000e+00 7.4000000e+00 7.6000000e+00 6.5000000e+00 1.2000000e+00 1.6000000e+00 2.0000000e+00 3.0000000e-01 7.0000000e-01 1.4000000e+00 3.0000000e-01 8.0000000e-01 7.0000000e-01 1.0000000e+00 1.5000000e+00 8.0000000e-01 1.0000000e+00 1.5000000e+00 4.0000000e-01 1.0000000e+00 5.0000000e-01 1.2000000e+00 6.0000000e-01 6.6000000e+00 5.9000000e+00 6.7000000e+00 5.0000000e+00 6.3000000e+00 5.2000000e+00 6.2000000e+00 3.3000000e+00 6.1000000e+00 4.3000000e+00 4.0000000e+00 5.1000000e+00 5.3000000e+00 5.8000000e+00 4.1000000e+00 5.9000000e+00 5.1000000e+00 4.7000000e+00 6.5000000e+00 4.6000000e+00 6.0000000e+00 5.1000000e+00 6.7000000e+00 5.7000000e+00 5.6000000e+00 5.9000000e+00 6.7000000e+00 6.9000000e+00 5.6000000e+00 4.1000000e+00 4.5000000e+00 4.3000000e+00 4.7000000e+00 6.5000000e+00 4.9000000e+00 5.8000000e+00 6.3000000e+00 6.2000000e+00 4.5000000e+00 4.8000000e+00 5.0000000e+00 5.6000000e+00 4.9000000e+00 3.5000000e+00 4.9000000e+00 4.6000000e+00 4.8000000e+00 5.4000000e+00 3.2000000e+00 4.8000000e+00 8.4000000e+00 6.6000000e+00 8.6000000e+00 7.3000000e+00 8.0000000e+00 9.8000000e+00 5.1000000e+00 9.0000000e+00 8.3000000e+00 9.7000000e+00 7.1000000e+00 7.4000000e+00 7.9000000e+00 6.7000000e+00 7.0000000e+00 7.5000000e+00 7.3000000e+00 1.0700000e+01 1.0800000e+01 6.8000000e+00 8.4000000e+00 6.2000000e+00 1.0100000e+01 6.8000000e+00 8.1000000e+00 8.5000000e+00 6.5000000e+00 6.3000000e+00 7.8000000e+00 8.1000000e+00 9.1000000e+00 1.0400000e+01 7.9000000e+00 6.6000000e+00 7.0000000e+00 9.6000000e+00 8.0000000e+00 7.1000000e+00 6.1000000e+00 7.8000000e+00 8.1000000e+00 7.7000000e+00 6.6000000e+00 8.5000000e+00 8.5000000e+00 7.7000000e+00 7.2000000e+00 7.2000000e+00 7.6000000e+00 6.3000000e+00 1.2000000e+00 1.2000000e+00 1.1000000e+00 1.1000000e+00 6.0000000e-01 1.1000000e+00 1.8000000e+00 5.0000000e-01 8.0000000e-01 2.3000000e+00 1.6000000e+00 8.0000000e-01 1.1000000e+00 1.2000000e+00 1.0000000e+00 1.3000000e+00 6.0000000e-01 8.0000000e-01 6.0000000e+00 5.3000000e+00 6.3000000e+00 4.6000000e+00 5.9000000e+00 4.8000000e+00 5.4000000e+00 3.9000000e+00 5.7000000e+00 4.3000000e+00 4.4000000e+00 4.7000000e+00 4.9000000e+00 5.4000000e+00 3.7000000e+00 5.5000000e+00 4.7000000e+00 4.3000000e+00 6.1000000e+00 4.2000000e+00 5.4000000e+00 4.7000000e+00 6.3000000e+00 5.3000000e+00 5.2000000e+00 5.5000000e+00 6.3000000e+00 6.5000000e+00 5.2000000e+00 3.7000000e+00 4.1000000e+00 3.9000000e+00 4.3000000e+00 6.1000000e+00 4.5000000e+00 4.8000000e+00 5.9000000e+00 5.8000000e+00 4.1000000e+00 4.4000000e+00 4.6000000e+00 5.2000000e+00 4.5000000e+00 3.9000000e+00 4.5000000e+00 4.2000000e+00 4.4000000e+00 5.0000000e+00 3.4000000e+00 4.4000000e+00 7.6000000e+00 6.2000000e+00 8.2000000e+00 6.9000000e+00 7.6000000e+00 9.4000000e+00 5.7000000e+00 8.6000000e+00 7.9000000e+00 8.7000000e+00 6.5000000e+00 7.0000000e+00 7.5000000e+00 6.3000000e+00 6.6000000e+00 6.9000000e+00 6.9000000e+00 9.7000000e+00 1.0400000e+01 6.4000000e+00 7.8000000e+00 5.8000000e+00 9.7000000e+00 6.4000000e+00 7.3000000e+00 7.9000000e+00 6.1000000e+00 5.9000000e+00 7.4000000e+00 7.7000000e+00 8.7000000e+00 9.4000000e+00 7.5000000e+00 6.2000000e+00 6.6000000e+00 9.2000000e+00 7.0000000e+00 6.7000000e+00 5.7000000e+00 7.4000000e+00 7.7000000e+00 7.3000000e+00 6.2000000e+00 7.9000000e+00 7.7000000e+00 7.3000000e+00 6.8000000e+00 6.8000000e+00 6.6000000e+00 5.9000000e+00 6.0000000e-01 1.3000000e+00 1.5000000e+00 1.2000000e+00 1.3000000e+00 2.2000000e+00 9.0000000e-01 1.2000000e+00 2.9000000e+00 2.0000000e+00 1.4000000e+00 1.1000000e+00 1.8000000e+00 6.0000000e-01 1.7000000e+00 6.0000000e-01 1.2000000e+00 7.2000000e+00 6.5000000e+00 7.5000000e+00 5.8000000e+00 7.1000000e+00 6.0000000e+00 6.6000000e+00 4.7000000e+00 6.9000000e+00 5.1000000e+00 5.2000000e+00 5.9000000e+00 6.1000000e+00 6.6000000e+00 4.9000000e+00 6.7000000e+00 5.9000000e+00 5.5000000e+00 7.3000000e+00 5.4000000e+00 6.6000000e+00 5.9000000e+00 7.5000000e+00 6.5000000e+00 6.4000000e+00 6.7000000e+00 7.5000000e+00 7.7000000e+00 6.4000000e+00 4.9000000e+00 5.3000000e+00 5.1000000e+00 5.5000000e+00 7.3000000e+00 5.7000000e+00 6.0000000e+00 7.1000000e+00 7.0000000e+00 5.3000000e+00 5.6000000e+00 5.8000000e+00 6.4000000e+00 5.7000000e+00 4.7000000e+00 5.7000000e+00 5.4000000e+00 5.6000000e+00 6.2000000e+00 4.2000000e+00 5.6000000e+00 8.8000000e+00 7.4000000e+00 9.4000000e+00 8.1000000e+00 8.8000000e+00 1.0600000e+01 6.5000000e+00 9.8000000e+00 9.1000000e+00 9.5000000e+00 7.7000000e+00 8.2000000e+00 8.7000000e+00 7.5000000e+00 7.8000000e+00 8.1000000e+00 8.1000000e+00 1.0100000e+01 1.1600000e+01 7.6000000e+00 9.0000000e+00 7.0000000e+00 1.0900000e+01 7.6000000e+00 8.5000000e+00 9.1000000e+00 7.3000000e+00 7.1000000e+00 8.6000000e+00 8.9000000e+00 9.9000000e+00 9.8000000e+00 8.7000000e+00 7.4000000e+00 7.8000000e+00 1.0400000e+01 8.2000000e+00 7.9000000e+00 6.9000000e+00 8.6000000e+00 8.9000000e+00 8.5000000e+00 7.4000000e+00 9.1000000e+00 8.9000000e+00 8.5000000e+00 8.0000000e+00 8.0000000e+00 7.8000000e+00 7.1000000e+00 1.9000000e+00 1.7000000e+00 8.0000000e-01 1.9000000e+00 2.4000000e+00 1.3000000e+00 1.4000000e+00 3.1000000e+00 2.2000000e+00 1.8000000e+00 1.5000000e+00 2.0000000e+00 1.0000000e+00 1.9000000e+00 8.0000000e-01 1.4000000e+00 7.0000000e+00 6.3000000e+00 7.3000000e+00 5.6000000e+00 6.9000000e+00 5.8000000e+00 6.4000000e+00 5.1000000e+00 6.7000000e+00 5.5000000e+00 5.6000000e+00 5.7000000e+00 5.9000000e+00 6.4000000e+00 4.7000000e+00 6.5000000e+00 5.7000000e+00 5.3000000e+00 7.1000000e+00 5.2000000e+00 6.4000000e+00 5.7000000e+00 7.3000000e+00 6.3000000e+00 6.2000000e+00 6.5000000e+00 7.3000000e+00 7.5000000e+00 6.2000000e+00 4.7000000e+00 5.1000000e+00 4.9000000e+00 5.3000000e+00 7.1000000e+00 5.7000000e+00 5.8000000e+00 6.9000000e+00 6.8000000e+00 5.1000000e+00 5.4000000e+00 5.6000000e+00 6.2000000e+00 5.5000000e+00 5.1000000e+00 5.5000000e+00 5.2000000e+00 5.4000000e+00 6.0000000e+00 4.6000000e+00 5.4000000e+00 8.6000000e+00 7.2000000e+00 9.2000000e+00 7.9000000e+00 8.6000000e+00 1.0400000e+01 6.9000000e+00 9.6000000e+00 8.9000000e+00 9.3000000e+00 7.5000000e+00 8.0000000e+00 8.5000000e+00 7.3000000e+00 7.6000000e+00 7.9000000e+00 7.9000000e+00 9.9000000e+00 1.1400000e+01 7.4000000e+00 8.8000000e+00 6.8000000e+00 1.0700000e+01 7.4000000e+00 8.3000000e+00 8.9000000e+00 7.1000000e+00 6.9000000e+00 8.4000000e+00 8.7000000e+00 9.7000000e+00 9.6000000e+00 8.5000000e+00 7.2000000e+00 7.6000000e+00 1.0200000e+01 8.0000000e+00 7.7000000e+00 6.7000000e+00 8.4000000e+00 8.7000000e+00 8.3000000e+00 7.2000000e+00 8.9000000e+00 8.7000000e+00 8.3000000e+00 7.8000000e+00 7.8000000e+00 7.6000000e+00 6.9000000e+00 6.0000000e-01 1.3000000e+00 0.0000000e+00 9.0000000e-01 6.0000000e-01 9.0000000e-01 1.6000000e+00 9.0000000e-01 1.1000000e+00 1.6000000e+00 5.0000000e-01 1.1000000e+00 6.0000000e-01 1.1000000e+00 5.0000000e-01 6.7000000e+00 6.0000000e+00 6.8000000e+00 5.1000000e+00 6.4000000e+00 5.3000000e+00 6.3000000e+00 3.4000000e+00 6.2000000e+00 4.4000000e+00 4.1000000e+00 5.2000000e+00 5.4000000e+00 5.9000000e+00 4.2000000e+00 6.0000000e+00 5.2000000e+00 4.8000000e+00 6.6000000e+00 4.7000000e+00 6.1000000e+00 5.2000000e+00 6.8000000e+00 5.8000000e+00 5.7000000e+00 6.0000000e+00 6.8000000e+00 7.0000000e+00 5.7000000e+00 4.2000000e+00 4.6000000e+00 4.4000000e+00 4.8000000e+00 6.6000000e+00 5.0000000e+00 5.9000000e+00 6.4000000e+00 6.3000000e+00 4.6000000e+00 4.9000000e+00 5.1000000e+00 5.7000000e+00 5.0000000e+00 3.6000000e+00 5.0000000e+00 4.7000000e+00 4.9000000e+00 5.5000000e+00 3.3000000e+00 4.9000000e+00 8.5000000e+00 6.7000000e+00 8.7000000e+00 7.4000000e+00 8.1000000e+00 9.9000000e+00 5.2000000e+00 9.1000000e+00 8.4000000e+00 9.8000000e+00 7.2000000e+00 7.5000000e+00 8.0000000e+00 6.8000000e+00 7.1000000e+00 7.6000000e+00 7.4000000e+00 1.0800000e+01 1.0900000e+01 6.9000000e+00 8.5000000e+00 6.3000000e+00 1.0200000e+01 6.9000000e+00 8.2000000e+00 8.6000000e+00 6.6000000e+00 6.4000000e+00 7.9000000e+00 8.2000000e+00 9.2000000e+00 1.0500000e+01 8.0000000e+00 6.7000000e+00 7.1000000e+00 9.7000000e+00 8.1000000e+00 7.2000000e+00 6.2000000e+00 7.9000000e+00 8.2000000e+00 7.8000000e+00 6.7000000e+00 8.6000000e+00 8.6000000e+00 7.8000000e+00 7.3000000e+00 7.3000000e+00 7.7000000e+00 6.4000000e+00 9.0000000e-01 6.0000000e-01 9.0000000e-01 6.0000000e-01 5.0000000e-01 1.6000000e+00 7.0000000e-01 1.1000000e+00 1.6000000e+00 7.0000000e-01 1.1000000e+00 6.0000000e-01 1.1000000e+00 3.0000000e-01 6.7000000e+00 6.0000000e+00 7.0000000e+00 5.3000000e+00 6.6000000e+00 5.5000000e+00 6.3000000e+00 3.8000000e+00 6.4000000e+00 4.6000000e+00 4.3000000e+00 5.4000000e+00 5.6000000e+00 6.1000000e+00 4.4000000e+00 6.2000000e+00 5.4000000e+00 5.0000000e+00 6.8000000e+00 4.9000000e+00 6.1000000e+00 5.4000000e+00 7.0000000e+00 6.0000000e+00 5.9000000e+00 6.2000000e+00 7.0000000e+00 7.2000000e+00 5.9000000e+00 4.4000000e+00 4.8000000e+00 4.6000000e+00 5.0000000e+00 6.8000000e+00 5.2000000e+00 5.9000000e+00 6.6000000e+00 6.5000000e+00 4.8000000e+00 5.1000000e+00 5.3000000e+00 5.9000000e+00 5.2000000e+00 3.8000000e+00 5.2000000e+00 4.9000000e+00 5.1000000e+00 5.7000000e+00 3.5000000e+00 5.1000000e+00 8.5000000e+00 6.9000000e+00 8.9000000e+00 7.6000000e+00 8.3000000e+00 1.0100000e+01 5.6000000e+00 9.3000000e+00 8.6000000e+00 9.8000000e+00 7.2000000e+00 7.7000000e+00 8.2000000e+00 7.0000000e+00 7.3000000e+00 7.6000000e+00 7.6000000e+00 1.0800000e+01 1.1100000e+01 7.1000000e+00 8.5000000e+00 6.5000000e+00 1.0400000e+01 7.1000000e+00 8.2000000e+00 8.6000000e+00 6.8000000e+00 6.6000000e+00 8.1000000e+00 8.4000000e+00 9.4000000e+00 1.0500000e+01 8.2000000e+00 6.9000000e+00 7.3000000e+00 9.9000000e+00 8.1000000e+00 7.4000000e+00 6.4000000e+00 8.1000000e+00 8.4000000e+00 8.0000000e+00 6.9000000e+00 8.6000000e+00 8.6000000e+00 8.0000000e+00 7.5000000e+00 7.5000000e+00 7.7000000e+00 6.6000000e+00 1.3000000e+00 1.6000000e+00 7.0000000e-01 6.0000000e-01 2.3000000e+00 1.4000000e+00 1.2000000e+00 1.5000000e+00 1.4000000e+00 1.0000000e+00 1.3000000e+00 6.0000000e-01 8.0000000e-01 6.4000000e+00 5.7000000e+00 6.7000000e+00 5.0000000e+00 6.3000000e+00 5.2000000e+00 5.8000000e+00 4.5000000e+00 6.1000000e+00 4.9000000e+00 5.0000000e+00 5.1000000e+00 5.3000000e+00 5.8000000e+00 4.1000000e+00 5.9000000e+00 5.1000000e+00 4.7000000e+00 6.5000000e+00 4.6000000e+00 5.8000000e+00 5.1000000e+00 6.7000000e+00 5.7000000e+00 5.6000000e+00 5.9000000e+00 6.7000000e+00 6.9000000e+00 5.6000000e+00 4.1000000e+00 4.5000000e+00 4.3000000e+00 4.7000000e+00 6.5000000e+00 5.1000000e+00 5.2000000e+00 6.3000000e+00 6.2000000e+00 4.5000000e+00 4.8000000e+00 5.0000000e+00 5.6000000e+00 4.9000000e+00 4.5000000e+00 4.9000000e+00 4.6000000e+00 4.8000000e+00 5.4000000e+00 4.0000000e+00 4.8000000e+00 8.0000000e+00 6.6000000e+00 8.6000000e+00 7.3000000e+00 8.0000000e+00 9.8000000e+00 6.3000000e+00 9.0000000e+00 8.3000000e+00 8.9000000e+00 6.9000000e+00 7.4000000e+00 7.9000000e+00 6.7000000e+00 7.0000000e+00 7.3000000e+00 7.3000000e+00 9.9000000e+00 1.0800000e+01 6.8000000e+00 8.2000000e+00 6.2000000e+00 1.0100000e+01 6.8000000e+00 7.7000000e+00 8.3000000e+00 6.5000000e+00 6.3000000e+00 7.8000000e+00 8.1000000e+00 9.1000000e+00 9.6000000e+00 7.9000000e+00 6.6000000e+00 7.0000000e+00 9.6000000e+00 7.4000000e+00 7.1000000e+00 6.1000000e+00 7.8000000e+00 8.1000000e+00 7.7000000e+00 6.6000000e+00 8.3000000e+00 8.1000000e+00 7.7000000e+00 7.2000000e+00 7.2000000e+00 7.0000000e+00 6.3000000e+00 9.0000000e-01 6.0000000e-01 9.0000000e-01 1.6000000e+00 9.0000000e-01 1.1000000e+00 1.6000000e+00 5.0000000e-01 1.1000000e+00 6.0000000e-01 1.1000000e+00 5.0000000e-01 6.7000000e+00 6.0000000e+00 6.8000000e+00 5.1000000e+00 6.4000000e+00 5.3000000e+00 6.3000000e+00 3.4000000e+00 6.2000000e+00 4.4000000e+00 4.1000000e+00 5.2000000e+00 5.4000000e+00 5.9000000e+00 4.2000000e+00 6.0000000e+00 5.2000000e+00 4.8000000e+00 6.6000000e+00 4.7000000e+00 6.1000000e+00 5.2000000e+00 6.8000000e+00 5.8000000e+00 5.7000000e+00 6.0000000e+00 6.8000000e+00 7.0000000e+00 5.7000000e+00 4.2000000e+00 4.6000000e+00 4.4000000e+00 4.8000000e+00 6.6000000e+00 5.0000000e+00 5.9000000e+00 6.4000000e+00 6.3000000e+00 4.6000000e+00 4.9000000e+00 5.1000000e+00 5.7000000e+00 5.0000000e+00 3.6000000e+00 5.0000000e+00 4.7000000e+00 4.9000000e+00 5.5000000e+00 3.3000000e+00 4.9000000e+00 8.5000000e+00 6.7000000e+00 8.7000000e+00 7.4000000e+00 8.1000000e+00 9.9000000e+00 5.2000000e+00 9.1000000e+00 8.4000000e+00 9.8000000e+00 7.2000000e+00 7.5000000e+00 8.0000000e+00 6.8000000e+00 7.1000000e+00 7.6000000e+00 7.4000000e+00 1.0800000e+01 1.0900000e+01 6.9000000e+00 8.5000000e+00 6.3000000e+00 1.0200000e+01 6.9000000e+00 8.2000000e+00 8.6000000e+00 6.6000000e+00 6.4000000e+00 7.9000000e+00 8.2000000e+00 9.2000000e+00 1.0500000e+01 8.0000000e+00 6.7000000e+00 7.1000000e+00 9.7000000e+00 8.1000000e+00 7.2000000e+00 6.2000000e+00 7.9000000e+00 8.2000000e+00 7.8000000e+00 6.7000000e+00 8.6000000e+00 8.6000000e+00 7.8000000e+00 7.3000000e+00 7.3000000e+00 7.7000000e+00 6.4000000e+00 1.3000000e+00 1.2000000e+00 9.0000000e-01 2.0000000e-01 1.8000000e+00 2.3000000e+00 6.0000000e-01 1.8000000e+00 5.0000000e-01 1.8000000e+00 1.0000000e+00 7.4000000e+00 6.7000000e+00 7.5000000e+00 5.6000000e+00 6.9000000e+00 5.8000000e+00 7.0000000e+00 3.9000000e+00 6.7000000e+00 4.9000000e+00 4.6000000e+00 5.7000000e+00 5.9000000e+00 6.4000000e+00 4.7000000e+00 6.7000000e+00 5.7000000e+00 5.3000000e+00 7.1000000e+00 5.2000000e+00 6.8000000e+00 5.7000000e+00 7.3000000e+00 6.3000000e+00 6.2000000e+00 6.5000000e+00 7.3000000e+00 7.5000000e+00 6.2000000e+00 4.7000000e+00 5.1000000e+00 4.9000000e+00 5.3000000e+00 7.1000000e+00 5.5000000e+00 6.6000000e+00 7.1000000e+00 6.8000000e+00 5.1000000e+00 5.4000000e+00 5.6000000e+00 6.2000000e+00 5.5000000e+00 4.1000000e+00 5.5000000e+00 5.2000000e+00 5.4000000e+00 6.0000000e+00 3.8000000e+00 5.4000000e+00 9.2000000e+00 7.2000000e+00 9.2000000e+00 7.9000000e+00 8.6000000e+00 1.0400000e+01 5.7000000e+00 9.6000000e+00 8.9000000e+00 1.0500000e+01 7.9000000e+00 8.0000000e+00 8.5000000e+00 7.3000000e+00 7.6000000e+00 8.3000000e+00 7.9000000e+00 1.1500000e+01 1.1400000e+01 7.4000000e+00 9.2000000e+00 6.8000000e+00 1.0700000e+01 7.4000000e+00 8.9000000e+00 9.3000000e+00 7.1000000e+00 6.9000000e+00 8.4000000e+00 8.7000000e+00 9.7000000e+00 1.1200000e+01 8.5000000e+00 7.2000000e+00 7.6000000e+00 1.0200000e+01 8.8000000e+00 7.9000000e+00 6.7000000e+00 8.6000000e+00 8.9000000e+00 8.5000000e+00 7.2000000e+00 9.3000000e+00 9.3000000e+00 8.3000000e+00 7.8000000e+00 7.8000000e+00 8.4000000e+00 6.9000000e+00 5.0000000e-01 2.0000000e+00 1.1000000e+00 7.0000000e-01 1.0000000e+00 9.0000000e-01 5.0000000e-01 8.0000000e-01 5.0000000e-01 3.0000000e-01 6.5000000e+00 5.8000000e+00 6.8000000e+00 5.1000000e+00 6.4000000e+00 5.3000000e+00 5.9000000e+00 3.8000000e+00 6.2000000e+00 4.4000000e+00 4.3000000e+00 5.2000000e+00 5.4000000e+00 5.9000000e+00 4.2000000e+00 6.0000000e+00 5.2000000e+00 4.8000000e+00 6.6000000e+00 4.7000000e+00 5.9000000e+00 5.2000000e+00 6.8000000e+00 5.8000000e+00 5.7000000e+00 6.0000000e+00 6.8000000e+00 7.0000000e+00 5.7000000e+00 4.2000000e+00 4.6000000e+00 4.4000000e+00 4.8000000e+00 6.6000000e+00 5.0000000e+00 5.3000000e+00 6.4000000e+00 6.3000000e+00 4.6000000e+00 4.9000000e+00 5.1000000e+00 5.7000000e+00 5.0000000e+00 3.8000000e+00 5.0000000e+00 4.7000000e+00 4.9000000e+00 5.5000000e+00 3.3000000e+00 4.9000000e+00 8.1000000e+00 6.7000000e+00 8.7000000e+00 7.4000000e+00 8.1000000e+00 9.9000000e+00 5.6000000e+00 9.1000000e+00 8.4000000e+00 9.2000000e+00 7.0000000e+00 7.5000000e+00 8.0000000e+00 6.8000000e+00 7.1000000e+00 7.4000000e+00 7.4000000e+00 1.0200000e+01 1.0900000e+01 6.9000000e+00 8.3000000e+00 6.3000000e+00 1.0200000e+01 6.9000000e+00 7.8000000e+00 8.4000000e+00 6.6000000e+00 6.4000000e+00 7.9000000e+00 8.2000000e+00 9.2000000e+00 9.9000000e+00 8.0000000e+00 6.7000000e+00 7.1000000e+00 9.7000000e+00 7.5000000e+00 7.2000000e+00 6.2000000e+00 7.9000000e+00 8.2000000e+00 7.8000000e+00 6.7000000e+00 8.4000000e+00 8.2000000e+00 7.8000000e+00 7.3000000e+00 7.3000000e+00 7.1000000e+00 6.4000000e+00 1.7000000e+00 1.0000000e+00 6.0000000e-01 1.1000000e+00 8.0000000e-01 8.0000000e-01 9.0000000e-01 8.0000000e-01 4.0000000e-01 6.8000000e+00 6.1000000e+00 7.1000000e+00 5.4000000e+00 6.7000000e+00 5.6000000e+00 6.2000000e+00 3.9000000e+00 6.5000000e+00 4.7000000e+00 4.4000000e+00 5.5000000e+00 5.7000000e+00 6.2000000e+00 4.5000000e+00 6.3000000e+00 5.5000000e+00 5.1000000e+00 6.9000000e+00 5.0000000e+00 6.2000000e+00 5.5000000e+00 7.1000000e+00 6.1000000e+00 6.0000000e+00 6.3000000e+00 7.1000000e+00 7.3000000e+00 6.0000000e+00 4.5000000e+00 4.9000000e+00 4.7000000e+00 5.1000000e+00 6.9000000e+00 5.3000000e+00 5.6000000e+00 6.7000000e+00 6.6000000e+00 4.9000000e+00 5.2000000e+00 5.4000000e+00 6.0000000e+00 5.3000000e+00 3.9000000e+00 5.3000000e+00 5.0000000e+00 5.2000000e+00 5.8000000e+00 3.6000000e+00 5.2000000e+00 8.4000000e+00 7.0000000e+00 9.0000000e+00 7.7000000e+00 8.4000000e+00 1.0200000e+01 5.7000000e+00 9.4000000e+00 8.7000000e+00 9.3000000e+00 7.3000000e+00 7.8000000e+00 8.3000000e+00 7.1000000e+00 7.4000000e+00 7.7000000e+00 7.7000000e+00 1.0300000e+01 1.1200000e+01 7.2000000e+00 8.6000000e+00 6.6000000e+00 1.0500000e+01 7.2000000e+00 8.1000000e+00 8.7000000e+00 6.9000000e+00 6.7000000e+00 8.2000000e+00 8.5000000e+00 9.5000000e+00 1.0000000e+01 8.3000000e+00 7.0000000e+00 7.4000000e+00 1.0000000e+01 7.8000000e+00 7.5000000e+00 6.5000000e+00 8.2000000e+00 8.5000000e+00 8.1000000e+00 7.0000000e+00 8.7000000e+00 8.5000000e+00 8.1000000e+00 7.6000000e+00 7.6000000e+00 7.4000000e+00 6.7000000e+00 1.1000000e+00 2.3000000e+00 2.8000000e+00 1.1000000e+00 2.5000000e+00 1.2000000e+00 2.5000000e+00 1.7000000e+00 7.9000000e+00 7.2000000e+00 8.0000000e+00 4.7000000e+00 7.0000000e+00 5.9000000e+00 7.5000000e+00 3.2000000e+00 7.0000000e+00 4.8000000e+00 3.7000000e+00 6.2000000e+00 5.0000000e+00 6.7000000e+00 5.0000000e+00 7.2000000e+00 6.2000000e+00 5.2000000e+00 6.2000000e+00 4.7000000e+00 7.3000000e+00 5.8000000e+00 6.8000000e+00 6.4000000e+00 6.5000000e+00 7.0000000e+00 7.4000000e+00 8.0000000e+00 6.5000000e+00 4.4000000e+00 4.4000000e+00 4.2000000e+00 5.2000000e+00 7.0000000e+00 6.0000000e+00 7.1000000e+00 7.6000000e+00 5.9000000e+00 5.6000000e+00 4.9000000e+00 5.3000000e+00 6.7000000e+00 5.2000000e+00 3.2000000e+00 5.4000000e+00 5.7000000e+00 5.7000000e+00 6.3000000e+00 3.3000000e+00 5.5000000e+00 9.7000000e+00 7.1000000e+00 9.7000000e+00 8.2000000e+00 9.1000000e+00 1.0900000e+01 5.2000000e+00 9.9000000e+00 8.4000000e+00 1.1000000e+01 8.4000000e+00 7.9000000e+00 9.0000000e+00 6.8000000e+00 7.7000000e+00 8.8000000e+00 8.4000000e+00 1.2000000e+01 1.1100000e+01 6.5000000e+00 9.7000000e+00 6.9000000e+00 1.0800000e+01 7.3000000e+00 9.4000000e+00 9.8000000e+00 7.2000000e+00 7.4000000e+00 8.5000000e+00 9.2000000e+00 9.8000000e+00 1.1700000e+01 8.6000000e+00 7.3000000e+00 7.3000000e+00 1.0700000e+01 9.3000000e+00 8.4000000e+00 7.2000000e+00 9.1000000e+00 9.4000000e+00 9.0000000e+00 7.1000000e+00 9.8000000e+00 9.8000000e+00 8.8000000e+00 7.3000000e+00 8.3000000e+00 8.9000000e+00 7.4000000e+00 1.6000000e+00 2.1000000e+00 8.0000000e-01 1.6000000e+00 3.0000000e-01 1.6000000e+00 8.0000000e-01 7.2000000e+00 6.5000000e+00 7.5000000e+00 5.8000000e+00 7.1000000e+00 6.0000000e+00 6.8000000e+00 4.1000000e+00 6.9000000e+00 5.1000000e+00 4.8000000e+00 5.9000000e+00 6.1000000e+00 6.6000000e+00 4.9000000e+00 6.7000000e+00 5.9000000e+00 5.5000000e+00 7.3000000e+00 5.4000000e+00 6.6000000e+00 5.9000000e+00 7.5000000e+00 6.5000000e+00 6.4000000e+00 6.7000000e+00 7.5000000e+00 7.7000000e+00 6.4000000e+00 4.9000000e+00 5.3000000e+00 5.1000000e+00 5.5000000e+00 7.3000000e+00 5.7000000e+00 6.4000000e+00 7.1000000e+00 7.0000000e+00 5.3000000e+00 5.6000000e+00 5.8000000e+00 6.4000000e+00 5.7000000e+00 4.3000000e+00 5.7000000e+00 5.4000000e+00 5.6000000e+00 6.2000000e+00 4.0000000e+00 5.6000000e+00 9.0000000e+00 7.4000000e+00 9.4000000e+00 8.1000000e+00 8.8000000e+00 1.0600000e+01 5.9000000e+00 9.8000000e+00 9.1000000e+00 1.0300000e+01 7.7000000e+00 8.2000000e+00 8.7000000e+00 7.5000000e+00 7.8000000e+00 8.1000000e+00 8.1000000e+00 1.1300000e+01 1.1600000e+01 7.6000000e+00 9.0000000e+00 7.0000000e+00 1.0900000e+01 7.6000000e+00 8.7000000e+00 9.1000000e+00 7.3000000e+00 7.1000000e+00 8.6000000e+00 8.9000000e+00 9.9000000e+00 1.1000000e+01 8.7000000e+00 7.4000000e+00 7.8000000e+00 1.0400000e+01 8.6000000e+00 7.9000000e+00 6.9000000e+00 8.6000000e+00 8.9000000e+00 8.5000000e+00 7.4000000e+00 9.1000000e+00 9.1000000e+00 8.5000000e+00 8.0000000e+00 8.0000000e+00 8.2000000e+00 7.1000000e+00 9.0000000e-01 1.2000000e+00 8.0000000e-01 1.3000000e+00 1.0000000e+00 8.0000000e-01 6.2000000e+00 5.5000000e+00 6.5000000e+00 4.8000000e+00 6.1000000e+00 5.0000000e+00 5.6000000e+00 3.3000000e+00 5.9000000e+00 4.1000000e+00 3.8000000e+00 4.9000000e+00 5.1000000e+00 5.6000000e+00 3.9000000e+00 5.7000000e+00 4.9000000e+00 4.5000000e+00 6.3000000e+00 4.4000000e+00 5.6000000e+00 4.9000000e+00 6.5000000e+00 5.5000000e+00 5.4000000e+00 5.7000000e+00 6.5000000e+00 6.7000000e+00 5.4000000e+00 3.9000000e+00 4.3000000e+00 4.1000000e+00 4.5000000e+00 6.3000000e+00 4.7000000e+00 5.0000000e+00 6.1000000e+00 6.0000000e+00 4.3000000e+00 4.6000000e+00 4.8000000e+00 5.4000000e+00 4.7000000e+00 3.3000000e+00 4.7000000e+00 4.4000000e+00 4.6000000e+00 5.2000000e+00 3.0000000e+00 4.6000000e+00 7.8000000e+00 6.4000000e+00 8.4000000e+00 7.1000000e+00 7.8000000e+00 9.6000000e+00 5.1000000e+00 8.8000000e+00 8.1000000e+00 8.7000000e+00 6.7000000e+00 7.2000000e+00 7.7000000e+00 6.5000000e+00 6.8000000e+00 7.1000000e+00 7.1000000e+00 9.7000000e+00 1.0600000e+01 6.6000000e+00 8.0000000e+00 6.0000000e+00 9.9000000e+00 6.6000000e+00 7.5000000e+00 8.1000000e+00 6.3000000e+00 6.1000000e+00 7.6000000e+00 7.9000000e+00 8.9000000e+00 9.4000000e+00 7.7000000e+00 6.4000000e+00 6.8000000e+00 9.4000000e+00 7.2000000e+00 6.9000000e+00 5.9000000e+00 7.6000000e+00 7.9000000e+00 7.5000000e+00 6.4000000e+00 8.1000000e+00 7.9000000e+00 7.5000000e+00 7.0000000e+00 7.0000000e+00 6.8000000e+00 6.1000000e+00 1.7000000e+00 5.0000000e-01 1.8000000e+00 9.0000000e-01 1.3000000e+00 6.3000000e+00 5.6000000e+00 6.6000000e+00 4.9000000e+00 6.2000000e+00 5.1000000e+00 5.7000000e+00 3.6000000e+00 6.0000000e+00 4.2000000e+00 4.1000000e+00 5.0000000e+00 5.2000000e+00 5.7000000e+00 4.0000000e+00 5.8000000e+00 5.0000000e+00 4.6000000e+00 6.4000000e+00 4.5000000e+00 5.7000000e+00 5.0000000e+00 6.6000000e+00 5.6000000e+00 5.5000000e+00 5.8000000e+00 6.6000000e+00 6.8000000e+00 5.5000000e+00 4.0000000e+00 4.4000000e+00 4.2000000e+00 4.6000000e+00 6.4000000e+00 4.8000000e+00 5.1000000e+00 6.2000000e+00 6.1000000e+00 4.4000000e+00 4.7000000e+00 4.9000000e+00 5.5000000e+00 4.8000000e+00 3.6000000e+00 4.8000000e+00 4.5000000e+00 4.7000000e+00 5.3000000e+00 3.1000000e+00 4.7000000e+00 7.9000000e+00 6.5000000e+00 8.5000000e+00 7.2000000e+00 7.9000000e+00 9.7000000e+00 5.4000000e+00 8.9000000e+00 8.2000000e+00 8.6000000e+00 6.8000000e+00 7.3000000e+00 7.8000000e+00 6.6000000e+00 6.9000000e+00 7.2000000e+00 7.2000000e+00 9.2000000e+00 1.0700000e+01 6.7000000e+00 8.1000000e+00 6.1000000e+00 1.0000000e+01 6.7000000e+00 7.6000000e+00 8.2000000e+00 6.4000000e+00 6.2000000e+00 7.7000000e+00 8.0000000e+00 9.0000000e+00 8.9000000e+00 7.8000000e+00 6.5000000e+00 6.9000000e+00 9.5000000e+00 7.3000000e+00 7.0000000e+00 6.0000000e+00 7.7000000e+00 8.0000000e+00 7.6000000e+00 6.5000000e+00 8.2000000e+00 8.0000000e+00 7.6000000e+00 7.1000000e+00 7.1000000e+00 6.9000000e+00 6.2000000e+00 1.4000000e+00 5.0000000e-01 1.4000000e+00 6.0000000e-01 6.8000000e+00 6.1000000e+00 6.9000000e+00 5.0000000e+00 6.3000000e+00 5.2000000e+00 6.4000000e+00 3.3000000e+00 6.1000000e+00 4.3000000e+00 4.0000000e+00 5.1000000e+00 5.3000000e+00 5.8000000e+00 4.1000000e+00 6.1000000e+00 5.1000000e+00 4.7000000e+00 6.5000000e+00 4.6000000e+00 6.2000000e+00 5.1000000e+00 6.7000000e+00 5.7000000e+00 5.6000000e+00 5.9000000e+00 6.7000000e+00 6.9000000e+00 5.6000000e+00 4.1000000e+00 4.5000000e+00 4.3000000e+00 4.7000000e+00 6.5000000e+00 4.9000000e+00 6.0000000e+00 6.5000000e+00 6.2000000e+00 4.5000000e+00 4.8000000e+00 5.0000000e+00 5.6000000e+00 4.9000000e+00 3.5000000e+00 4.9000000e+00 4.6000000e+00 4.8000000e+00 5.4000000e+00 3.2000000e+00 4.8000000e+00 8.6000000e+00 6.6000000e+00 8.6000000e+00 7.3000000e+00 8.0000000e+00 9.8000000e+00 5.1000000e+00 9.0000000e+00 8.3000000e+00 9.9000000e+00 7.3000000e+00 7.4000000e+00 7.9000000e+00 6.7000000e+00 7.0000000e+00 7.7000000e+00 7.3000000e+00 1.0900000e+01 1.0800000e+01 6.8000000e+00 8.6000000e+00 6.2000000e+00 1.0100000e+01 6.8000000e+00 8.3000000e+00 8.7000000e+00 6.5000000e+00 6.3000000e+00 7.8000000e+00 8.1000000e+00 9.1000000e+00 1.0600000e+01 7.9000000e+00 6.6000000e+00 7.0000000e+00 9.6000000e+00 8.2000000e+00 7.3000000e+00 6.1000000e+00 8.0000000e+00 8.3000000e+00 7.9000000e+00 6.6000000e+00 8.7000000e+00 8.7000000e+00 7.7000000e+00 7.2000000e+00 7.2000000e+00 7.8000000e+00 6.3000000e+00 1.3000000e+00 4.0000000e-01 8.0000000e-01 6.8000000e+00 6.1000000e+00 7.1000000e+00 5.4000000e+00 6.7000000e+00 5.6000000e+00 6.2000000e+00 4.1000000e+00 6.5000000e+00 4.7000000e+00 4.6000000e+00 5.5000000e+00 5.7000000e+00 6.2000000e+00 4.5000000e+00 6.3000000e+00 5.5000000e+00 5.1000000e+00 6.9000000e+00 5.0000000e+00 6.2000000e+00 5.5000000e+00 7.1000000e+00 6.1000000e+00 6.0000000e+00 6.3000000e+00 7.1000000e+00 7.3000000e+00 6.0000000e+00 4.5000000e+00 4.9000000e+00 4.7000000e+00 5.1000000e+00 6.9000000e+00 5.3000000e+00 5.6000000e+00 6.7000000e+00 6.6000000e+00 4.9000000e+00 5.2000000e+00 5.4000000e+00 6.0000000e+00 5.3000000e+00 4.1000000e+00 5.3000000e+00 5.0000000e+00 5.2000000e+00 5.8000000e+00 3.6000000e+00 5.2000000e+00 8.4000000e+00 7.0000000e+00 9.0000000e+00 7.7000000e+00 8.4000000e+00 1.0200000e+01 5.9000000e+00 9.4000000e+00 8.7000000e+00 9.1000000e+00 7.3000000e+00 7.8000000e+00 8.3000000e+00 7.1000000e+00 7.4000000e+00 7.7000000e+00 7.7000000e+00 9.7000000e+00 1.1200000e+01 7.2000000e+00 8.6000000e+00 6.6000000e+00 1.0500000e+01 7.2000000e+00 8.1000000e+00 8.7000000e+00 6.9000000e+00 6.7000000e+00 8.2000000e+00 8.5000000e+00 9.5000000e+00 9.4000000e+00 8.3000000e+00 7.0000000e+00 7.4000000e+00 1.0000000e+01 7.8000000e+00 7.5000000e+00 6.5000000e+00 8.2000000e+00 8.5000000e+00 8.1000000e+00 7.0000000e+00 8.7000000e+00 8.5000000e+00 8.1000000e+00 7.6000000e+00 7.6000000e+00 7.4000000e+00 6.7000000e+00 1.3000000e+00 5.0000000e-01 6.9000000e+00 6.2000000e+00 7.2000000e+00 5.5000000e+00 6.8000000e+00 5.7000000e+00 6.5000000e+00 3.8000000e+00 6.6000000e+00 4.8000000e+00 4.5000000e+00 5.6000000e+00 5.8000000e+00 6.3000000e+00 4.6000000e+00 6.4000000e+00 5.6000000e+00 5.2000000e+00 7.0000000e+00 5.1000000e+00 6.3000000e+00 5.6000000e+00 7.2000000e+00 6.2000000e+00 6.1000000e+00 6.4000000e+00 7.2000000e+00 7.4000000e+00 6.1000000e+00 4.6000000e+00 5.0000000e+00 4.8000000e+00 5.2000000e+00 7.0000000e+00 5.4000000e+00 6.1000000e+00 6.8000000e+00 6.7000000e+00 5.0000000e+00 5.3000000e+00 5.5000000e+00 6.1000000e+00 5.4000000e+00 4.0000000e+00 5.4000000e+00 5.1000000e+00 5.3000000e+00 5.9000000e+00 3.7000000e+00 5.3000000e+00 8.7000000e+00 7.1000000e+00 9.1000000e+00 7.8000000e+00 8.5000000e+00 1.0300000e+01 5.6000000e+00 9.5000000e+00 8.8000000e+00 1.0000000e+01 7.4000000e+00 7.9000000e+00 8.4000000e+00 7.2000000e+00 7.5000000e+00 7.8000000e+00 7.8000000e+00 1.1000000e+01 1.1300000e+01 7.3000000e+00 8.7000000e+00 6.7000000e+00 1.0600000e+01 7.3000000e+00 8.4000000e+00 8.8000000e+00 7.0000000e+00 6.8000000e+00 8.3000000e+00 8.6000000e+00 9.6000000e+00 1.0700000e+01 8.4000000e+00 7.1000000e+00 7.5000000e+00 1.0100000e+01 8.3000000e+00 7.6000000e+00 6.6000000e+00 8.3000000e+00 8.6000000e+00 8.2000000e+00 7.1000000e+00 8.8000000e+00 8.8000000e+00 8.2000000e+00 7.7000000e+00 7.7000000e+00 7.9000000e+00 6.8000000e+00 8.0000000e-01 6.6000000e+00 5.9000000e+00 6.9000000e+00 5.2000000e+00 6.5000000e+00 5.4000000e+00 6.0000000e+00 4.3000000e+00 6.3000000e+00 4.7000000e+00 4.8000000e+00 5.3000000e+00 5.5000000e+00 6.0000000e+00 4.3000000e+00 6.1000000e+00 5.3000000e+00 4.9000000e+00 6.7000000e+00 4.8000000e+00 6.0000000e+00 5.3000000e+00 6.9000000e+00 5.9000000e+00 5.8000000e+00 6.1000000e+00 6.9000000e+00 7.1000000e+00 5.8000000e+00 4.3000000e+00 4.7000000e+00 4.5000000e+00 4.9000000e+00 6.7000000e+00 5.1000000e+00 5.4000000e+00 6.5000000e+00 6.4000000e+00 4.7000000e+00 5.0000000e+00 5.2000000e+00 5.8000000e+00 5.1000000e+00 4.3000000e+00 5.1000000e+00 4.8000000e+00 5.0000000e+00 5.6000000e+00 3.8000000e+00 5.0000000e+00 8.2000000e+00 6.8000000e+00 8.8000000e+00 7.5000000e+00 8.2000000e+00 1.0000000e+01 6.1000000e+00 9.2000000e+00 8.5000000e+00 8.9000000e+00 7.1000000e+00 7.6000000e+00 8.1000000e+00 6.9000000e+00 7.2000000e+00 7.5000000e+00 7.5000000e+00 9.7000000e+00 1.1000000e+01 7.0000000e+00 8.4000000e+00 6.4000000e+00 1.0300000e+01 7.0000000e+00 7.9000000e+00 8.5000000e+00 6.7000000e+00 6.5000000e+00 8.0000000e+00 8.3000000e+00 9.3000000e+00 9.4000000e+00 8.1000000e+00 6.8000000e+00 7.2000000e+00 9.8000000e+00 7.6000000e+00 7.3000000e+00 6.3000000e+00 8.0000000e+00 8.3000000e+00 7.9000000e+00 6.8000000e+00 8.5000000e+00 8.3000000e+00 7.9000000e+00 7.4000000e+00 7.4000000e+00 7.2000000e+00 6.5000000e+00 6.6000000e+00 5.9000000e+00 6.9000000e+00 5.2000000e+00 6.5000000e+00 5.4000000e+00 6.0000000e+00 3.7000000e+00 6.3000000e+00 4.5000000e+00 4.2000000e+00 5.3000000e+00 5.5000000e+00 6.0000000e+00 4.3000000e+00 6.1000000e+00 5.3000000e+00 4.9000000e+00 6.7000000e+00 4.8000000e+00 6.0000000e+00 5.3000000e+00 6.9000000e+00 5.9000000e+00 5.8000000e+00 6.1000000e+00 6.9000000e+00 7.1000000e+00 5.8000000e+00 4.3000000e+00 4.7000000e+00 4.5000000e+00 4.9000000e+00 6.7000000e+00 5.1000000e+00 5.6000000e+00 6.5000000e+00 6.4000000e+00 4.7000000e+00 5.0000000e+00 5.2000000e+00 5.8000000e+00 5.1000000e+00 3.7000000e+00 5.1000000e+00 4.8000000e+00 5.0000000e+00 5.6000000e+00 3.4000000e+00 5.0000000e+00 8.2000000e+00 6.8000000e+00 8.8000000e+00 7.5000000e+00 8.2000000e+00 1.0000000e+01 5.5000000e+00 9.2000000e+00 8.5000000e+00 9.5000000e+00 7.1000000e+00 7.6000000e+00 8.1000000e+00 6.9000000e+00 7.2000000e+00 7.5000000e+00 7.5000000e+00 1.0500000e+01 1.1000000e+01 7.0000000e+00 8.4000000e+00 6.4000000e+00 1.0300000e+01 7.0000000e+00 7.9000000e+00 8.5000000e+00 6.7000000e+00 6.5000000e+00 8.0000000e+00 8.3000000e+00 9.3000000e+00 1.0200000e+01 8.1000000e+00 6.8000000e+00 7.2000000e+00 9.8000000e+00 7.8000000e+00 7.3000000e+00 6.3000000e+00 8.0000000e+00 8.3000000e+00 7.9000000e+00 6.8000000e+00 8.5000000e+00 8.3000000e+00 7.9000000e+00 7.4000000e+00 7.4000000e+00 7.4000000e+00 6.5000000e+00 9.0000000e-01 5.0000000e-01 3.2000000e+00 1.1000000e+00 2.0000000e+00 1.0000000e+00 4.7000000e+00 9.0000000e-01 3.1000000e+00 4.8000000e+00 1.9000000e+00 3.1000000e+00 1.2000000e+00 2.9000000e+00 7.0000000e-01 1.9000000e+00 2.7000000e+00 2.1000000e+00 3.2000000e+00 1.6000000e+00 2.1000000e+00 1.7000000e+00 1.5000000e+00 1.4000000e+00 9.0000000e-01 7.0000000e-01 1.1000000e+00 1.6000000e+00 3.5000000e+00 3.5000000e+00 3.7000000e+00 2.7000000e+00 2.1000000e+00 2.1000000e+00 1.6000000e+00 5.0000000e-01 2.0000000e+00 2.3000000e+00 3.0000000e+00 2.6000000e+00 1.2000000e+00 2.7000000e+00 4.7000000e+00 2.5000000e+00 2.2000000e+00 2.2000000e+00 1.6000000e+00 4.6000000e+00 2.4000000e+00 3.2000000e+00 2.6000000e+00 2.2000000e+00 2.3000000e+00 2.6000000e+00 3.4000000e+00 3.3000000e+00 2.6000000e+00 2.5000000e+00 3.1000000e+00 1.5000000e+00 2.2000000e+00 1.9000000e+00 2.9000000e+00 3.0000000e+00 2.1000000e+00 1.9000000e+00 4.1000000e+00 4.4000000e+00 2.4000000e+00 2.0000000e+00 2.6000000e+00 3.7000000e+00 1.8000000e+00 2.1000000e+00 1.9000000e+00 1.7000000e+00 1.7000000e+00 2.6000000e+00 1.7000000e+00 2.7000000e+00 3.8000000e+00 2.7000000e+00 1.6000000e+00 2.4000000e+00 3.2000000e+00 2.8000000e+00 1.9000000e+00 1.7000000e+00 1.6000000e+00 2.3000000e+00 1.5000000e+00 2.6000000e+00 2.3000000e+00 2.5000000e+00 1.9000000e+00 2.2000000e+00 1.8000000e+00 2.6000000e+00 2.1000000e+00 1.0000000e+00 2.5000000e+00 6.0000000e-01 1.3000000e+00 5.0000000e-01 4.0000000e+00 8.0000000e-01 2.4000000e+00 4.1000000e+00 1.0000000e+00 2.4000000e+00 9.0000000e-01 2.2000000e+00 6.0000000e-01 1.0000000e+00 2.0000000e+00 1.2000000e+00 2.5000000e+00 1.1000000e+00 1.4000000e+00 1.2000000e+00 1.2000000e+00 7.0000000e-01 6.0000000e-01 1.2000000e+00 1.2000000e+00 7.0000000e-01 2.8000000e+00 2.8000000e+00 3.0000000e+00 2.0000000e+00 1.6000000e+00 1.2000000e+00 7.0000000e-01 6.0000000e-01 1.3000000e+00 1.6000000e+00 2.3000000e+00 1.9000000e+00 7.0000000e-01 2.0000000e+00 4.0000000e+00 1.8000000e+00 1.5000000e+00 1.5000000e+00 9.0000000e-01 3.9000000e+00 1.7000000e+00 2.7000000e+00 2.1000000e+00 2.9000000e+00 1.8000000e+00 2.3000000e+00 4.1000000e+00 2.4000000e+00 3.3000000e+00 2.6000000e+00 3.8000000e+00 1.2000000e+00 1.7000000e+00 2.2000000e+00 2.4000000e+00 2.5000000e+00 1.6000000e+00 1.6000000e+00 4.8000000e+00 5.1000000e+00 1.9000000e+00 2.5000000e+00 2.1000000e+00 4.4000000e+00 1.3000000e+00 2.2000000e+00 2.6000000e+00 1.2000000e+00 1.2000000e+00 2.1000000e+00 2.4000000e+00 3.4000000e+00 4.5000000e+00 2.2000000e+00 1.1000000e+00 2.1000000e+00 3.9000000e+00 2.3000000e+00 1.4000000e+00 1.2000000e+00 2.1000000e+00 2.4000000e+00 2.0000000e+00 2.1000000e+00 2.6000000e+00 2.6000000e+00 2.0000000e+00 1.7000000e+00 1.5000000e+00 2.1000000e+00 1.6000000e+00 3.3000000e+00 1.0000000e+00 2.1000000e+00 1.1000000e+00 4.8000000e+00 1.0000000e+00 3.2000000e+00 4.9000000e+00 1.8000000e+00 3.2000000e+00 1.3000000e+00 3.0000000e+00 8.0000000e-01 1.8000000e+00 2.8000000e+00 2.0000000e+00 3.3000000e+00 1.5000000e+00 2.2000000e+00 1.2000000e+00 1.6000000e+00 1.5000000e+00 1.0000000e+00 6.0000000e-01 6.0000000e-01 1.5000000e+00 3.6000000e+00 3.6000000e+00 3.8000000e+00 2.8000000e+00 1.6000000e+00 2.0000000e+00 1.7000000e+00 4.0000000e-01 2.1000000e+00 2.4000000e+00 3.1000000e+00 2.7000000e+00 1.3000000e+00 2.8000000e+00 4.8000000e+00 2.6000000e+00 2.3000000e+00 2.3000000e+00 1.7000000e+00 4.7000000e+00 2.5000000e+00 2.9000000e+00 2.1000000e+00 1.9000000e+00 1.8000000e+00 2.1000000e+00 3.1000000e+00 3.2000000e+00 2.3000000e+00 2.0000000e+00 3.0000000e+00 1.2000000e+00 1.7000000e+00 1.4000000e+00 2.4000000e+00 2.5000000e+00 1.8000000e+00 1.4000000e+00 4.0000000e+00 4.1000000e+00 1.9000000e+00 1.7000000e+00 2.1000000e+00 3.4000000e+00 1.3000000e+00 1.8000000e+00 1.8000000e+00 1.4000000e+00 1.2000000e+00 2.1000000e+00 1.4000000e+00 2.4000000e+00 3.7000000e+00 2.2000000e+00 1.1000000e+00 2.1000000e+00 2.9000000e+00 2.5000000e+00 1.4000000e+00 1.4000000e+00 1.1000000e+00 1.8000000e+00 1.0000000e+00 2.1000000e+00 2.0000000e+00 2.2000000e+00 1.4000000e+00 1.7000000e+00 1.3000000e+00 2.3000000e+00 1.6000000e+00 2.3000000e+00 1.2000000e+00 2.8000000e+00 1.7000000e+00 2.3000000e+00 9.0000000e-01 1.6000000e+00 1.5000000e+00 9.0000000e-01 2.0000000e+00 1.1000000e+00 2.5000000e+00 1.5000000e+00 1.1000000e+00 1.5000000e+00 6.0000000e-01 2.6000000e+00 1.1000000e+00 2.1000000e+00 1.9000000e+00 1.8000000e+00 2.3000000e+00 2.7000000e+00 3.3000000e+00 1.8000000e+00 1.3000000e+00 5.0000000e-01 7.0000000e-01 9.0000000e-01 2.3000000e+00 1.5000000e+00 2.4000000e+00 2.9000000e+00 1.2000000e+00 9.0000000e-01 2.0000000e-01 8.0000000e-01 2.0000000e+00 7.0000000e-01 1.5000000e+00 7.0000000e-01 1.2000000e+00 1.0000000e+00 1.6000000e+00 1.8000000e+00 8.0000000e-01 5.0000000e+00 2.4000000e+00 5.0000000e+00 3.5000000e+00 4.4000000e+00 6.2000000e+00 1.7000000e+00 5.2000000e+00 3.7000000e+00 6.3000000e+00 3.7000000e+00 3.2000000e+00 4.3000000e+00 2.1000000e+00 3.0000000e+00 4.1000000e+00 3.7000000e+00 7.3000000e+00 6.4000000e+00 1.8000000e+00 5.0000000e+00 2.2000000e+00 6.1000000e+00 2.6000000e+00 4.7000000e+00 5.1000000e+00 2.5000000e+00 2.7000000e+00 3.8000000e+00 4.5000000e+00 5.1000000e+00 7.0000000e+00 3.9000000e+00 2.6000000e+00 2.6000000e+00 6.0000000e+00 4.6000000e+00 3.7000000e+00 2.5000000e+00 4.4000000e+00 4.7000000e+00 4.3000000e+00 2.4000000e+00 5.1000000e+00 5.1000000e+00 4.1000000e+00 2.6000000e+00 3.6000000e+00 4.2000000e+00 2.7000000e+00 1.1000000e+00 9.0000000e-01 3.8000000e+00 4.0000000e-01 2.2000000e+00 3.9000000e+00 1.2000000e+00 2.2000000e+00 7.0000000e-01 2.2000000e+00 8.0000000e-01 1.2000000e+00 1.8000000e+00 1.0000000e+00 2.3000000e+00 1.5000000e+00 1.2000000e+00 8.0000000e-01 8.0000000e-01 7.0000000e-01 6.0000000e-01 6.0000000e-01 1.0000000e+00 7.0000000e-01 2.6000000e+00 2.6000000e+00 2.8000000e+00 1.8000000e+00 1.2000000e+00 1.4000000e+00 1.3000000e+00 6.0000000e-01 1.1000000e+00 1.8000000e+00 2.1000000e+00 1.7000000e+00 7.0000000e-01 1.8000000e+00 3.8000000e+00 1.6000000e+00 1.7000000e+00 1.5000000e+00 9.0000000e-01 3.7000000e+00 1.5000000e+00 3.1000000e+00 1.7000000e+00 2.7000000e+00 1.6000000e+00 2.1000000e+00 3.9000000e+00 2.2000000e+00 2.9000000e+00 2.0000000e+00 4.0000000e+00 1.4000000e+00 1.3000000e+00 2.0000000e+00 2.0000000e+00 2.1000000e+00 2.0000000e+00 1.4000000e+00 5.0000000e+00 4.5000000e+00 1.5000000e+00 2.7000000e+00 1.7000000e+00 3.8000000e+00 9.0000000e-01 2.4000000e+00 2.8000000e+00 8.0000000e-01 1.2000000e+00 1.7000000e+00 2.2000000e+00 2.8000000e+00 4.7000000e+00 1.8000000e+00 7.0000000e-01 1.7000000e+00 3.7000000e+00 2.7000000e+00 1.6000000e+00 1.2000000e+00 2.1000000e+00 2.4000000e+00 2.0000000e+00 1.7000000e+00 2.8000000e+00 2.8000000e+00 1.8000000e+00 1.3000000e+00 1.3000000e+00 2.5000000e+00 1.6000000e+00 1.6000000e+00 2.7000000e+00 1.1000000e+00 1.3000000e+00 2.8000000e+00 9.0000000e-01 1.7000000e+00 8.0000000e-01 1.1000000e+00 1.5000000e+00 5.0000000e-01 9.0000000e-01 1.3000000e+00 1.2000000e+00 1.4000000e+00 9.0000000e-01 1.5000000e+00 7.0000000e-01 1.0000000e+00 1.3000000e+00 1.5000000e+00 2.1000000e+00 6.0000000e-01 1.5000000e+00 1.5000000e+00 1.7000000e+00 9.0000000e-01 1.3000000e+00 7.0000000e-01 1.2000000e+00 1.7000000e+00 1.2000000e+00 7.0000000e-01 1.0000000e+00 6.0000000e-01 8.0000000e-01 9.0000000e-01 2.7000000e+00 5.0000000e-01 6.0000000e-01 4.0000000e-01 8.0000000e-01 2.6000000e+00 4.0000000e-01 3.8000000e+00 1.4000000e+00 3.8000000e+00 2.3000000e+00 3.2000000e+00 5.0000000e+00 1.5000000e+00 4.0000000e+00 3.1000000e+00 5.1000000e+00 2.5000000e+00 2.2000000e+00 3.1000000e+00 1.5000000e+00 1.8000000e+00 2.9000000e+00 2.5000000e+00 6.1000000e+00 5.6000000e+00 1.6000000e+00 3.8000000e+00 1.2000000e+00 4.9000000e+00 1.6000000e+00 3.5000000e+00 3.9000000e+00 1.3000000e+00 1.5000000e+00 2.6000000e+00 3.3000000e+00 3.9000000e+00 5.8000000e+00 2.7000000e+00 1.4000000e+00 1.8000000e+00 4.8000000e+00 3.4000000e+00 2.5000000e+00 1.3000000e+00 3.2000000e+00 3.5000000e+00 3.1000000e+00 1.4000000e+00 3.9000000e+00 3.9000000e+00 2.9000000e+00 2.0000000e+00 2.4000000e+00 3.0000000e+00 1.5000000e+00 4.3000000e+00 1.1000000e+00 2.7000000e+00 4.4000000e+00 1.3000000e+00 2.7000000e+00 8.0000000e-01 2.5000000e+00 1.1000000e+00 1.3000000e+00 2.3000000e+00 1.5000000e+00 2.8000000e+00 8.0000000e-01 1.7000000e+00 1.1000000e+00 1.1000000e+00 1.2000000e+00 1.1000000e+00 1.3000000e+00 1.1000000e+00 1.0000000e+00 3.1000000e+00 3.1000000e+00 3.3000000e+00 2.3000000e+00 1.3000000e+00 1.5000000e+00 6.0000000e-01 7.0000000e-01 1.6000000e+00 1.9000000e+00 2.6000000e+00 2.2000000e+00 8.0000000e-01 2.3000000e+00 4.3000000e+00 2.1000000e+00 1.8000000e+00 1.8000000e+00 1.2000000e+00 4.2000000e+00 2.0000000e+00 2.2000000e+00 1.8000000e+00 2.8000000e+00 1.5000000e+00 2.2000000e+00 4.0000000e+00 2.5000000e+00 3.2000000e+00 2.5000000e+00 3.5000000e+00 1.1000000e+00 1.6000000e+00 2.1000000e+00 2.1000000e+00 2.2000000e+00 1.5000000e+00 1.5000000e+00 4.5000000e+00 5.0000000e+00 1.8000000e+00 2.4000000e+00 1.8000000e+00 4.3000000e+00 1.0000000e+00 1.9000000e+00 2.5000000e+00 9.0000000e-01 9.0000000e-01 2.0000000e+00 2.3000000e+00 3.3000000e+00 4.2000000e+00 2.1000000e+00 1.0000000e+00 2.0000000e+00 3.8000000e+00 1.8000000e+00 1.3000000e+00 9.0000000e-01 2.0000000e+00 2.3000000e+00 1.9000000e+00 1.8000000e+00 2.5000000e+00 2.3000000e+00 1.9000000e+00 1.4000000e+00 1.4000000e+00 1.6000000e+00 1.3000000e+00 3.8000000e+00 1.6000000e+00 7.0000000e-01 3.0000000e+00 2.0000000e+00 3.5000000e+00 1.8000000e+00 4.0000000e+00 3.0000000e+00 2.0000000e+00 3.2000000e+00 1.5000000e+00 4.1000000e+00 2.6000000e+00 3.6000000e+00 3.2000000e+00 3.3000000e+00 3.8000000e+00 4.2000000e+00 4.8000000e+00 3.3000000e+00 1.2000000e+00 1.2000000e+00 1.0000000e+00 2.0000000e+00 3.8000000e+00 2.8000000e+00 3.9000000e+00 4.4000000e+00 2.9000000e+00 2.4000000e+00 1.7000000e+00 2.1000000e+00 3.5000000e+00 2.0000000e+00 2.0000000e-01 2.2000000e+00 2.5000000e+00 2.5000000e+00 3.1000000e+00 7.0000000e-01 2.3000000e+00 6.5000000e+00 3.9000000e+00 6.5000000e+00 5.0000000e+00 5.9000000e+00 7.7000000e+00 2.0000000e+00 6.7000000e+00 5.2000000e+00 7.8000000e+00 5.2000000e+00 4.7000000e+00 5.8000000e+00 3.6000000e+00 4.5000000e+00 5.6000000e+00 5.2000000e+00 8.8000000e+00 7.9000000e+00 3.5000000e+00 6.5000000e+00 3.7000000e+00 7.6000000e+00 4.1000000e+00 6.2000000e+00 6.6000000e+00 4.0000000e+00 4.2000000e+00 5.3000000e+00 6.0000000e+00 6.6000000e+00 8.5000000e+00 5.4000000e+00 4.1000000e+00 4.1000000e+00 7.5000000e+00 6.1000000e+00 5.2000000e+00 4.0000000e+00 5.9000000e+00 6.2000000e+00 5.8000000e+00 3.9000000e+00 6.6000000e+00 6.6000000e+00 5.6000000e+00 4.1000000e+00 5.1000000e+00 5.7000000e+00 4.2000000e+00 2.4000000e+00 3.9000000e+00 1.4000000e+00 2.2000000e+00 7.0000000e-01 2.0000000e+00 6.0000000e-01 1.4000000e+00 1.8000000e+00 1.4000000e+00 2.3000000e+00 1.7000000e+00 1.2000000e+00 1.2000000e+00 8.0000000e-01 5.0000000e-01 4.0000000e-01 6.0000000e-01 1.0000000e+00 9.0000000e-01 2.6000000e+00 2.6000000e+00 2.8000000e+00 1.8000000e+00 1.6000000e+00 1.6000000e+00 1.5000000e+00 6.0000000e-01 1.1000000e+00 1.6000000e+00 2.1000000e+00 1.7000000e+00 7.0000000e-01 1.8000000e+00 3.8000000e+00 1.6000000e+00 1.5000000e+00 1.3000000e+00 7.0000000e-01 3.7000000e+00 1.5000000e+00 3.3000000e+00 2.1000000e+00 2.7000000e+00 1.8000000e+00 2.3000000e+00 3.9000000e+00 2.6000000e+00 2.9000000e+00 2.2000000e+00 4.0000000e+00 1.6000000e+00 1.7000000e+00 2.0000000e+00 2.4000000e+00 2.5000000e+00 2.2000000e+00 1.6000000e+00 5.0000000e+00 4.7000000e+00 1.9000000e+00 2.7000000e+00 2.1000000e+00 4.0000000e+00 1.3000000e+00 2.4000000e+00 2.8000000e+00 1.2000000e+00 1.4000000e+00 2.1000000e+00 2.2000000e+00 3.0000000e+00 4.7000000e+00 2.2000000e+00 1.1000000e+00 1.9000000e+00 3.7000000e+00 2.9000000e+00 1.8000000e+00 1.4000000e+00 2.1000000e+00 2.4000000e+00 2.0000000e+00 2.1000000e+00 2.8000000e+00 2.8000000e+00 1.8000000e+00 1.7000000e+00 1.5000000e+00 2.7000000e+00 1.8000000e+00 1.7000000e+00 1.4000000e+00 1.8000000e+00 1.9000000e+00 1.0000000e+00 2.4000000e+00 1.4000000e+00 1.2000000e+00 2.2000000e+00 9.0000000e-01 2.5000000e+00 1.2000000e+00 2.4000000e+00 2.0000000e+00 1.9000000e+00 2.2000000e+00 2.6000000e+00 3.2000000e+00 1.7000000e+00 1.4000000e+00 1.0000000e+00 1.2000000e+00 8.0000000e-01 2.2000000e+00 1.2000000e+00 2.3000000e+00 2.8000000e+00 2.1000000e+00 1.0000000e+00 7.0000000e-01 1.1000000e+00 1.9000000e+00 1.0000000e+00 1.6000000e+00 8.0000000e-01 1.3000000e+00 1.1000000e+00 1.7000000e+00 1.5000000e+00 9.0000000e-01 4.9000000e+00 2.3000000e+00 4.9000000e+00 3.4000000e+00 4.3000000e+00 6.1000000e+00 1.4000000e+00 5.1000000e+00 4.0000000e+00 6.2000000e+00 3.6000000e+00 3.1000000e+00 4.2000000e+00 2.4000000e+00 2.9000000e+00 4.0000000e+00 3.6000000e+00 7.2000000e+00 6.5000000e+00 2.5000000e+00 4.9000000e+00 2.1000000e+00 6.0000000e+00 2.5000000e+00 4.6000000e+00 5.0000000e+00 2.4000000e+00 2.6000000e+00 3.7000000e+00 4.4000000e+00 5.0000000e+00 6.9000000e+00 3.8000000e+00 2.5000000e+00 2.7000000e+00 5.9000000e+00 4.5000000e+00 3.6000000e+00 2.4000000e+00 4.3000000e+00 4.6000000e+00 4.2000000e+00 2.3000000e+00 5.0000000e+00 5.0000000e+00 4.0000000e+00 2.9000000e+00 3.5000000e+00 4.1000000e+00 2.6000000e+00 3.1000000e+00 1.7000000e+00 3.6000000e+00 1.9000000e+00 4.1000000e+00 3.1000000e+00 2.1000000e+00 2.9000000e+00 1.6000000e+00 4.2000000e+00 2.7000000e+00 3.7000000e+00 3.3000000e+00 3.4000000e+00 3.9000000e+00 4.3000000e+00 4.9000000e+00 3.4000000e+00 1.3000000e+00 1.3000000e+00 1.1000000e+00 2.1000000e+00 3.9000000e+00 2.9000000e+00 4.0000000e+00 4.5000000e+00 2.8000000e+00 2.5000000e+00 1.8000000e+00 2.2000000e+00 3.6000000e+00 2.1000000e+00 5.0000000e-01 2.3000000e+00 2.6000000e+00 2.6000000e+00 3.2000000e+00 1.2000000e+00 2.4000000e+00 6.6000000e+00 4.0000000e+00 6.6000000e+00 5.1000000e+00 6.0000000e+00 7.8000000e+00 2.3000000e+00 6.8000000e+00 5.3000000e+00 7.9000000e+00 5.3000000e+00 4.8000000e+00 5.9000000e+00 3.7000000e+00 4.6000000e+00 5.7000000e+00 5.3000000e+00 8.9000000e+00 8.0000000e+00 3.2000000e+00 6.6000000e+00 3.8000000e+00 7.7000000e+00 4.2000000e+00 6.3000000e+00 6.7000000e+00 4.1000000e+00 4.3000000e+00 5.4000000e+00 6.1000000e+00 6.7000000e+00 8.6000000e+00 5.5000000e+00 4.2000000e+00 4.2000000e+00 7.6000000e+00 6.2000000e+00 5.3000000e+00 4.1000000e+00 6.0000000e+00 6.3000000e+00 5.9000000e+00 4.0000000e+00 6.7000000e+00 6.7000000e+00 5.7000000e+00 4.2000000e+00 5.2000000e+00 5.8000000e+00 4.3000000e+00 1.6000000e+00 9.0000000e-01 1.2000000e+00 1.2000000e+00 6.0000000e-01 1.0000000e+00 1.4000000e+00 1.5000000e+00 1.1000000e+00 8.0000000e-01 1.6000000e+00 1.2000000e+00 9.0000000e-01 1.0000000e+00 1.8000000e+00 1.8000000e+00 5.0000000e-01 1.8000000e+00 1.8000000e+00 2.0000000e+00 1.0000000e+00 1.4000000e+00 8.0000000e-01 9.0000000e-01 1.4000000e+00 1.5000000e+00 6.0000000e-01 1.3000000e+00 1.3000000e+00 7.0000000e-01 1.0000000e+00 3.0000000e+00 8.0000000e-01 5.0000000e-01 5.0000000e-01 7.0000000e-01 2.9000000e+00 7.0000000e-01 3.5000000e+00 1.7000000e+00 3.5000000e+00 2.2000000e+00 2.9000000e+00 4.7000000e+00 2.0000000e+00 3.9000000e+00 3.2000000e+00 4.8000000e+00 2.2000000e+00 2.3000000e+00 2.8000000e+00 2.0000000e+00 2.1000000e+00 2.6000000e+00 2.2000000e+00 5.8000000e+00 5.7000000e+00 1.7000000e+00 3.5000000e+00 1.7000000e+00 5.0000000e+00 1.7000000e+00 3.2000000e+00 3.6000000e+00 1.4000000e+00 1.2000000e+00 2.7000000e+00 3.0000000e+00 4.0000000e+00 5.5000000e+00 2.8000000e+00 1.5000000e+00 2.1000000e+00 4.5000000e+00 3.1000000e+00 2.2000000e+00 1.0000000e+00 2.9000000e+00 3.2000000e+00 2.8000000e+00 1.7000000e+00 3.6000000e+00 3.6000000e+00 2.6000000e+00 2.1000000e+00 2.1000000e+00 2.7000000e+00 1.2000000e+00 1.9000000e+00 1.8000000e+00 2.4000000e+00 2.2000000e+00 8.0000000e-01 1.2000000e+00 9.0000000e-01 2.7000000e+00 1.0000000e+00 2.0000000e+00 1.6000000e+00 1.7000000e+00 2.2000000e+00 2.6000000e+00 3.2000000e+00 1.7000000e+00 1.2000000e+00 1.0000000e+00 1.0000000e+00 1.0000000e+00 2.2000000e+00 2.4000000e+00 2.3000000e+00 2.8000000e+00 1.1000000e+00 1.6000000e+00 1.1000000e+00 1.5000000e+00 1.9000000e+00 8.0000000e-01 1.8000000e+00 1.4000000e+00 1.5000000e+00 1.5000000e+00 1.5000000e+00 2.3000000e+00 1.3000000e+00 4.9000000e+00 2.7000000e+00 4.9000000e+00 3.4000000e+00 4.3000000e+00 6.1000000e+00 2.6000000e+00 5.1000000e+00 3.6000000e+00 6.2000000e+00 3.6000000e+00 3.1000000e+00 4.2000000e+00 2.6000000e+00 3.3000000e+00 4.0000000e+00 3.6000000e+00 7.2000000e+00 6.3000000e+00 1.5000000e+00 4.9000000e+00 2.9000000e+00 6.0000000e+00 2.5000000e+00 4.6000000e+00 5.0000000e+00 2.4000000e+00 2.6000000e+00 3.7000000e+00 4.4000000e+00 5.0000000e+00 6.9000000e+00 3.8000000e+00 2.5000000e+00 2.5000000e+00 5.9000000e+00 4.5000000e+00 3.6000000e+00 2.4000000e+00 4.3000000e+00 4.6000000e+00 4.2000000e+00 2.7000000e+00 5.0000000e+00 5.0000000e+00 4.0000000e+00 2.5000000e+00 3.5000000e+00 4.1000000e+00 2.8000000e+00 1.7000000e+00 1.1000000e+00 9.0000000e-01 1.5000000e+00 1.1000000e+00 2.0000000e+00 1.0000000e+00 9.0000000e-01 9.0000000e-01 3.0000000e-01 8.0000000e-01 9.0000000e-01 9.0000000e-01 1.3000000e+00 4.0000000e-01 2.3000000e+00 2.3000000e+00 2.5000000e+00 1.5000000e+00 9.0000000e-01 1.1000000e+00 1.0000000e+00 9.0000000e-01 1.2000000e+00 1.3000000e+00 1.8000000e+00 1.4000000e+00 2.0000000e-01 1.5000000e+00 3.5000000e+00 1.3000000e+00 1.2000000e+00 1.0000000e+00 6.0000000e-01 3.4000000e+00 1.2000000e+00 3.0000000e+00 1.4000000e+00 3.0000000e+00 1.5000000e+00 2.4000000e+00 4.2000000e+00 2.1000000e+00 3.2000000e+00 2.5000000e+00 4.3000000e+00 1.7000000e+00 1.6000000e+00 2.3000000e+00 1.7000000e+00 1.8000000e+00 2.1000000e+00 1.7000000e+00 5.3000000e+00 5.0000000e+00 1.2000000e+00 3.0000000e+00 1.4000000e+00 4.3000000e+00 1.0000000e+00 2.7000000e+00 3.1000000e+00 7.0000000e-01 7.0000000e-01 2.0000000e+00 2.5000000e+00 3.3000000e+00 5.0000000e+00 2.1000000e+00 8.0000000e-01 1.2000000e+00 4.0000000e+00 2.6000000e+00 1.7000000e+00 7.0000000e-01 2.4000000e+00 2.7000000e+00 2.3000000e+00 1.4000000e+00 3.1000000e+00 3.1000000e+00 2.1000000e+00 1.4000000e+00 1.6000000e+00 2.2000000e+00 1.1000000e+00 2.2000000e+00 1.2000000e+00 1.2000000e+00 2.4000000e+00 9.0000000e-01 2.3000000e+00 1.0000000e+00 2.6000000e+00 1.8000000e+00 1.5000000e+00 2.0000000e+00 2.6000000e+00 3.0000000e+00 1.5000000e+00 8.0000000e-01 1.0000000e+00 1.0000000e+00 8.0000000e-01 2.4000000e+00 1.4000000e+00 2.1000000e+00 2.6000000e+00 2.1000000e+00 6.0000000e-01 9.0000000e-01 1.3000000e+00 1.7000000e+00 1.0000000e+00 1.8000000e+00 8.0000000e-01 9.0000000e-01 7.0000000e-01 1.3000000e+00 1.7000000e+00 7.0000000e-01 4.7000000e+00 2.5000000e+00 4.7000000e+00 3.2000000e+00 4.1000000e+00 5.9000000e+00 2.4000000e+00 4.9000000e+00 4.2000000e+00 6.0000000e+00 3.4000000e+00 3.3000000e+00 4.0000000e+00 2.6000000e+00 2.9000000e+00 3.8000000e+00 3.4000000e+00 7.0000000e+00 6.7000000e+00 2.7000000e+00 4.7000000e+00 2.1000000e+00 6.0000000e+00 2.7000000e+00 4.4000000e+00 4.8000000e+00 2.4000000e+00 2.4000000e+00 3.7000000e+00 4.2000000e+00 5.0000000e+00 6.7000000e+00 3.8000000e+00 2.5000000e+00 2.9000000e+00 5.7000000e+00 4.3000000e+00 3.4000000e+00 2.2000000e+00 4.1000000e+00 4.4000000e+00 4.0000000e+00 2.5000000e+00 4.8000000e+00 4.8000000e+00 3.8000000e+00 3.1000000e+00 3.3000000e+00 3.9000000e+00 2.4000000e+00 1.4000000e+00 2.0000000e+00 1.6000000e+00 2.5000000e+00 1.7000000e+00 1.4000000e+00 1.6000000e+00 1.4000000e+00 7.0000000e-01 2.0000000e-01 8.0000000e-01 1.0000000e+00 1.1000000e+00 2.8000000e+00 2.8000000e+00 3.0000000e+00 2.0000000e+00 2.0000000e+00 1.6000000e+00 1.3000000e+00 4.0000000e-01 1.3000000e+00 1.6000000e+00 2.3000000e+00 1.9000000e+00 9.0000000e-01 2.0000000e+00 4.0000000e+00 1.8000000e+00 1.5000000e+00 1.5000000e+00 9.0000000e-01 3.9000000e+00 1.7000000e+00 3.3000000e+00 2.5000000e+00 2.7000000e+00 2.2000000e+00 2.5000000e+00 3.9000000e+00 2.8000000e+00 3.1000000e+00 2.4000000e+00 3.8000000e+00 1.6000000e+00 2.1000000e+00 2.0000000e+00 2.8000000e+00 2.9000000e+00 2.2000000e+00 1.8000000e+00 4.8000000e+00 4.9000000e+00 2.3000000e+00 2.5000000e+00 2.5000000e+00 4.2000000e+00 1.7000000e+00 2.2000000e+00 2.6000000e+00 1.6000000e+00 1.6000000e+00 2.5000000e+00 2.2000000e+00 3.2000000e+00 4.5000000e+00 2.6000000e+00 1.5000000e+00 2.3000000e+00 3.7000000e+00 2.9000000e+00 1.8000000e+00 1.6000000e+00 1.9000000e+00 2.2000000e+00 1.8000000e+00 2.5000000e+00 2.6000000e+00 2.6000000e+00 1.8000000e+00 2.1000000e+00 1.7000000e+00 2.7000000e+00 2.0000000e+00 1.4000000e+00 1.4000000e+00 1.5000000e+00 1.1000000e+00 1.4000000e+00 1.6000000e+00 1.2000000e+00 1.3000000e+00 1.2000000e+00 1.8000000e+00 1.8000000e+00 5.0000000e-01 2.0000000e+00 1.8000000e+00 2.0000000e+00 1.4000000e+00 1.4000000e+00 2.0000000e-01 9.0000000e-01 1.4000000e+00 1.7000000e+00 6.0000000e-01 1.3000000e+00 9.0000000e-01 7.0000000e-01 1.4000000e+00 3.0000000e+00 8.0000000e-01 7.0000000e-01 7.0000000e-01 1.1000000e+00 2.9000000e+00 9.0000000e-01 3.5000000e+00 1.5000000e+00 3.5000000e+00 2.2000000e+00 2.9000000e+00 4.7000000e+00 1.4000000e+00 3.9000000e+00 3.2000000e+00 4.8000000e+00 2.2000000e+00 2.3000000e+00 2.8000000e+00 1.6000000e+00 1.9000000e+00 2.6000000e+00 2.2000000e+00 5.8000000e+00 5.7000000e+00 1.7000000e+00 3.5000000e+00 1.1000000e+00 5.0000000e+00 1.7000000e+00 3.2000000e+00 3.6000000e+00 1.4000000e+00 1.2000000e+00 2.7000000e+00 3.0000000e+00 4.0000000e+00 5.5000000e+00 2.8000000e+00 1.5000000e+00 2.1000000e+00 4.5000000e+00 3.1000000e+00 2.2000000e+00 1.0000000e+00 2.9000000e+00 3.2000000e+00 2.8000000e+00 1.5000000e+00 3.6000000e+00 3.6000000e+00 2.6000000e+00 2.1000000e+00 2.1000000e+00 2.7000000e+00 1.2000000e+00 1.8000000e+00 7.0000000e-01 2.1000000e+00 8.0000000e-01 2.0000000e+00 1.2000000e+00 1.3000000e+00 1.8000000e+00 2.2000000e+00 2.8000000e+00 1.3000000e+00 8.0000000e-01 1.0000000e+00 1.0000000e+00 4.0000000e-01 1.8000000e+00 1.6000000e+00 1.9000000e+00 2.4000000e+00 1.5000000e+00 8.0000000e-01 9.0000000e-01 9.0000000e-01 1.5000000e+00 4.0000000e-01 2.0000000e+00 6.0000000e-01 7.0000000e-01 7.0000000e-01 1.1000000e+00 2.1000000e+00 5.0000000e-01 4.5000000e+00 1.9000000e+00 4.5000000e+00 3.0000000e+00 3.9000000e+00 5.7000000e+00 2.2000000e+00 4.7000000e+00 3.6000000e+00 5.8000000e+00 3.2000000e+00 2.7000000e+00 3.8000000e+00 2.2000000e+00 2.5000000e+00 3.6000000e+00 3.2000000e+00 6.8000000e+00 6.1000000e+00 2.1000000e+00 4.5000000e+00 2.1000000e+00 5.6000000e+00 2.1000000e+00 4.2000000e+00 4.6000000e+00 2.0000000e+00 2.2000000e+00 3.3000000e+00 4.0000000e+00 4.6000000e+00 6.5000000e+00 3.4000000e+00 2.1000000e+00 2.3000000e+00 5.5000000e+00 4.1000000e+00 3.2000000e+00 2.0000000e+00 3.9000000e+00 4.2000000e+00 3.8000000e+00 1.9000000e+00 4.6000000e+00 4.6000000e+00 3.6000000e+00 2.5000000e+00 3.1000000e+00 3.7000000e+00 2.2000000e+00 1.9000000e+00 1.9000000e+00 1.4000000e+00 8.0000000e-01 1.2000000e+00 1.3000000e+00 1.4000000e+00 1.6000000e+00 2.0000000e+00 9.0000000e-01 2.4000000e+00 2.0000000e+00 2.2000000e+00 1.8000000e+00 1.4000000e+00 1.6000000e+00 1.5000000e+00 1.6000000e+00 5.0000000e-01 2.0000000e+00 1.7000000e+00 1.5000000e+00 1.1000000e+00 1.6000000e+00 3.0000000e+00 1.6000000e+00 1.9000000e+00 1.7000000e+00 1.1000000e+00 3.3000000e+00 1.7000000e+00 3.7000000e+00 1.9000000e+00 3.7000000e+00 2.2000000e+00 3.1000000e+00 4.9000000e+00 1.8000000e+00 3.9000000e+00 2.4000000e+00 5.0000000e+00 2.4000000e+00 1.9000000e+00 3.0000000e+00 1.8000000e+00 2.5000000e+00 2.8000000e+00 2.4000000e+00 6.0000000e+00 5.1000000e+00 7.0000000e-01 3.7000000e+00 2.1000000e+00 4.8000000e+00 1.3000000e+00 3.4000000e+00 3.8000000e+00 1.2000000e+00 1.6000000e+00 2.5000000e+00 3.2000000e+00 3.8000000e+00 5.7000000e+00 2.6000000e+00 1.3000000e+00 1.7000000e+00 4.7000000e+00 3.3000000e+00 2.4000000e+00 1.6000000e+00 3.1000000e+00 3.4000000e+00 3.0000000e+00 1.9000000e+00 3.8000000e+00 3.8000000e+00 2.8000000e+00 1.3000000e+00 2.3000000e+00 2.9000000e+00 2.0000000e+00 2.6000000e+00 1.1000000e+00 2.1000000e+00 1.7000000e+00 1.8000000e+00 2.3000000e+00 2.7000000e+00 3.3000000e+00 1.8000000e+00 7.0000000e-01 3.0000000e-01 5.0000000e-01 5.0000000e-01 2.3000000e+00 1.7000000e+00 2.4000000e+00 2.9000000e+00 1.6000000e+00 9.0000000e-01 4.0000000e-01 8.0000000e-01 2.0000000e+00 5.0000000e-01 1.5000000e+00 7.0000000e-01 1.0000000e+00 1.0000000e+00 1.6000000e+00 1.4000000e+00 8.0000000e-01 5.0000000e+00 2.4000000e+00 5.0000000e+00 3.5000000e+00 4.4000000e+00 6.2000000e+00 1.9000000e+00 5.2000000e+00 3.7000000e+00 6.3000000e+00 3.7000000e+00 3.2000000e+00 4.3000000e+00 2.1000000e+00 3.0000000e+00 4.1000000e+00 3.7000000e+00 7.3000000e+00 6.4000000e+00 2.2000000e+00 5.0000000e+00 2.2000000e+00 6.1000000e+00 2.6000000e+00 4.7000000e+00 5.1000000e+00 2.5000000e+00 2.7000000e+00 3.8000000e+00 4.5000000e+00 5.1000000e+00 7.0000000e+00 3.9000000e+00 2.6000000e+00 2.6000000e+00 6.0000000e+00 4.6000000e+00 3.7000000e+00 2.5000000e+00 4.4000000e+00 4.7000000e+00 4.3000000e+00 2.4000000e+00 5.1000000e+00 5.1000000e+00 4.1000000e+00 2.6000000e+00 3.6000000e+00 4.2000000e+00 2.7000000e+00 1.9000000e+00 1.5000000e+00 1.3000000e+00 1.8000000e+00 1.7000000e+00 1.7000000e+00 1.3000000e+00 1.0000000e+00 2.9000000e+00 2.9000000e+00 3.1000000e+00 2.1000000e+00 1.1000000e+00 1.3000000e+00 8.0000000e-01 1.3000000e+00 2.2000000e+00 1.7000000e+00 2.4000000e+00 2.0000000e+00 1.0000000e+00 2.1000000e+00 4.1000000e+00 1.9000000e+00 1.6000000e+00 1.6000000e+00 1.6000000e+00 4.0000000e+00 1.8000000e+00 2.4000000e+00 1.0000000e+00 2.8000000e+00 1.5000000e+00 2.2000000e+00 4.0000000e+00 2.1000000e+00 3.2000000e+00 2.5000000e+00 3.7000000e+00 1.1000000e+00 1.6000000e+00 2.1000000e+00 1.3000000e+00 1.4000000e+00 1.5000000e+00 1.5000000e+00 4.7000000e+00 5.0000000e+00 1.6000000e+00 2.4000000e+00 1.0000000e+00 4.3000000e+00 1.0000000e+00 2.1000000e+00 2.5000000e+00 7.0000000e-01 5.0000000e-01 2.0000000e+00 2.7000000e+00 3.3000000e+00 4.4000000e+00 2.1000000e+00 1.4000000e+00 2.0000000e+00 3.8000000e+00 2.0000000e+00 1.3000000e+00 3.0000000e-01 2.0000000e+00 2.3000000e+00 1.9000000e+00 1.0000000e+00 2.5000000e+00 2.5000000e+00 1.9000000e+00 1.4000000e+00 1.4000000e+00 1.6000000e+00 5.0000000e-01 1.6000000e+00 8.0000000e-01 7.0000000e-01 1.2000000e+00 1.6000000e+00 2.2000000e+00 9.0000000e-01 1.4000000e+00 1.4000000e+00 1.6000000e+00 6.0000000e-01 1.6000000e+00 1.6000000e+00 1.5000000e+00 1.8000000e+00 1.1000000e+00 8.0000000e-01 9.0000000e-01 1.3000000e+00 9.0000000e-01 6.0000000e-01 2.6000000e+00 8.0000000e-01 9.0000000e-01 7.0000000e-01 5.0000000e-01 2.5000000e+00 5.0000000e-01 3.9000000e+00 2.1000000e+00 3.9000000e+00 2.4000000e+00 3.3000000e+00 5.1000000e+00 2.4000000e+00 4.1000000e+00 3.2000000e+00 5.2000000e+00 2.6000000e+00 2.3000000e+00 3.2000000e+00 2.4000000e+00 2.5000000e+00 3.0000000e+00 2.6000000e+00 6.2000000e+00 5.7000000e+00 1.9000000e+00 3.9000000e+00 2.1000000e+00 5.0000000e+00 1.7000000e+00 3.6000000e+00 4.0000000e+00 1.4000000e+00 1.6000000e+00 2.7000000e+00 3.4000000e+00 4.0000000e+00 5.9000000e+00 2.8000000e+00 1.5000000e+00 1.9000000e+00 4.9000000e+00 3.5000000e+00 2.6000000e+00 1.6000000e+00 3.3000000e+00 3.6000000e+00 3.2000000e+00 2.1000000e+00 4.0000000e+00 4.0000000e+00 3.0000000e+00 2.1000000e+00 2.5000000e+00 3.1000000e+00 2.0000000e+00 1.0000000e+00 1.3000000e+00 1.4000000e+00 1.0000000e+00 1.2000000e+00 1.1000000e+00 2.6000000e+00 2.4000000e+00 2.6000000e+00 2.0000000e+00 8.0000000e-01 1.8000000e+00 1.7000000e+00 1.2000000e+00 9.0000000e-01 2.2000000e+00 1.9000000e+00 1.7000000e+00 1.1000000e+00 1.8000000e+00 3.6000000e+00 1.8000000e+00 2.1000000e+00 1.9000000e+00 1.3000000e+00 3.5000000e+00 1.9000000e+00 2.9000000e+00 1.3000000e+00 2.9000000e+00 1.4000000e+00 2.3000000e+00 4.1000000e+00 2.0000000e+00 3.1000000e+00 1.6000000e+00 4.2000000e+00 1.6000000e+00 1.1000000e+00 2.2000000e+00 1.2000000e+00 1.9000000e+00 2.0000000e+00 1.6000000e+00 5.2000000e+00 4.3000000e+00 7.0000000e-01 2.9000000e+00 1.5000000e+00 4.0000000e+00 5.0000000e-01 2.6000000e+00 3.0000000e+00 8.0000000e-01 1.0000000e+00 1.7000000e+00 2.4000000e+00 3.0000000e+00 4.9000000e+00 1.8000000e+00 5.0000000e-01 1.1000000e+00 3.9000000e+00 2.5000000e+00 1.6000000e+00 1.2000000e+00 2.3000000e+00 2.6000000e+00 2.2000000e+00 1.3000000e+00 3.0000000e+00 3.0000000e+00 2.0000000e+00 5.0000000e-01 1.5000000e+00 2.3000000e+00 1.4000000e+00 9.0000000e-01 1.2000000e+00 1.0000000e+00 1.6000000e+00 7.0000000e-01 2.0000000e+00 2.0000000e+00 2.2000000e+00 1.2000000e+00 1.0000000e+00 1.4000000e+00 1.3000000e+00 1.2000000e+00 1.1000000e+00 1.4000000e+00 1.7000000e+00 1.1000000e+00 5.0000000e-01 1.2000000e+00 3.2000000e+00 1.2000000e+00 1.1000000e+00 1.1000000e+00 7.0000000e-01 3.1000000e+00 1.1000000e+00 3.3000000e+00 1.5000000e+00 3.3000000e+00 1.8000000e+00 2.7000000e+00 4.5000000e+00 2.2000000e+00 3.5000000e+00 2.6000000e+00 4.6000000e+00 2.0000000e+00 1.7000000e+00 2.6000000e+00 1.8000000e+00 1.9000000e+00 2.4000000e+00 2.0000000e+00 5.6000000e+00 5.1000000e+00 1.3000000e+00 3.3000000e+00 1.5000000e+00 4.4000000e+00 1.1000000e+00 3.0000000e+00 3.4000000e+00 8.0000000e-01 1.0000000e+00 2.1000000e+00 2.8000000e+00 3.4000000e+00 5.3000000e+00 2.2000000e+00 9.0000000e-01 1.3000000e+00 4.3000000e+00 2.9000000e+00 2.0000000e+00 1.0000000e+00 2.7000000e+00 3.0000000e+00 2.6000000e+00 1.5000000e+00 3.4000000e+00 3.4000000e+00 2.4000000e+00 1.5000000e+00 1.9000000e+00 2.5000000e+00 1.4000000e+00 5.0000000e-01 1.1000000e+00 1.5000000e+00 8.0000000e-01 2.1000000e+00 2.1000000e+00 2.3000000e+00 1.3000000e+00 1.7000000e+00 1.5000000e+00 1.4000000e+00 1.1000000e+00 8.0000000e-01 1.1000000e+00 1.6000000e+00 1.4000000e+00 8.0000000e-01 1.3000000e+00 3.3000000e+00 1.1000000e+00 1.0000000e+00 8.0000000e-01 2.0000000e-01 3.2000000e+00 1.0000000e+00 3.4000000e+00 2.2000000e+00 3.2000000e+00 1.9000000e+00 2.6000000e+00 4.4000000e+00 2.5000000e+00 3.4000000e+00 2.7000000e+00 4.5000000e+00 1.9000000e+00 1.8000000e+00 2.5000000e+00 2.5000000e+00 2.6000000e+00 2.3000000e+00 1.9000000e+00 5.5000000e+00 5.2000000e+00 2.0000000e+00 3.2000000e+00 2.2000000e+00 4.5000000e+00 1.4000000e+00 2.9000000e+00 3.3000000e+00 1.3000000e+00 1.5000000e+00 2.2000000e+00 2.7000000e+00 3.5000000e+00 5.2000000e+00 2.3000000e+00 1.2000000e+00 2.0000000e+00 4.2000000e+00 3.0000000e+00 1.9000000e+00 1.5000000e+00 2.6000000e+00 2.9000000e+00 2.5000000e+00 2.2000000e+00 3.3000000e+00 3.3000000e+00 2.3000000e+00 1.8000000e+00 1.8000000e+00 2.8000000e+00 1.9000000e+00 8.0000000e-01 1.0000000e+00 9.0000000e-01 2.6000000e+00 2.6000000e+00 2.8000000e+00 1.8000000e+00 1.8000000e+00 1.4000000e+00 1.3000000e+00 6.0000000e-01 1.1000000e+00 1.4000000e+00 2.1000000e+00 1.7000000e+00 7.0000000e-01 1.8000000e+00 3.8000000e+00 1.6000000e+00 1.3000000e+00 1.3000000e+00 7.0000000e-01 3.7000000e+00 1.5000000e+00 3.3000000e+00 2.3000000e+00 2.7000000e+00 2.0000000e+00 2.3000000e+00 3.9000000e+00 2.6000000e+00 3.1000000e+00 2.4000000e+00 4.0000000e+00 1.6000000e+00 1.9000000e+00 2.0000000e+00 2.6000000e+00 2.7000000e+00 2.2000000e+00 1.6000000e+00 5.0000000e+00 4.9000000e+00 2.1000000e+00 2.7000000e+00 2.3000000e+00 4.2000000e+00 1.5000000e+00 2.4000000e+00 2.8000000e+00 1.4000000e+00 1.4000000e+00 2.3000000e+00 2.2000000e+00 3.2000000e+00 4.7000000e+00 2.4000000e+00 1.3000000e+00 2.1000000e+00 3.7000000e+00 2.9000000e+00 1.8000000e+00 1.4000000e+00 2.1000000e+00 2.4000000e+00 2.0000000e+00 2.3000000e+00 2.8000000e+00 2.8000000e+00 1.8000000e+00 1.9000000e+00 1.5000000e+00 2.7000000e+00 1.8000000e+00 8.0000000e-01 1.3000000e+00 3.0000000e+00 3.0000000e+00 3.2000000e+00 2.2000000e+00 1.4000000e+00 2.0000000e+00 1.9000000e+00 6.0000000e-01 1.5000000e+00 2.2000000e+00 2.5000000e+00 2.1000000e+00 1.1000000e+00 2.2000000e+00 4.2000000e+00 2.0000000e+00 2.1000000e+00 1.9000000e+00 1.3000000e+00 4.1000000e+00 1.9000000e+00 3.3000000e+00 1.9000000e+00 2.3000000e+00 1.8000000e+00 2.3000000e+00 3.5000000e+00 2.8000000e+00 2.5000000e+00 1.8000000e+00 3.6000000e+00 1.6000000e+00 1.5000000e+00 1.6000000e+00 2.2000000e+00 2.3000000e+00 2.2000000e+00 1.6000000e+00 4.6000000e+00 4.1000000e+00 1.7000000e+00 2.3000000e+00 1.9000000e+00 3.4000000e+00 1.1000000e+00 2.2000000e+00 2.4000000e+00 1.0000000e+00 1.4000000e+00 1.9000000e+00 1.8000000e+00 2.4000000e+00 4.3000000e+00 2.0000000e+00 9.0000000e-01 1.7000000e+00 3.3000000e+00 2.9000000e+00 1.8000000e+00 1.4000000e+00 1.7000000e+00 2.2000000e+00 1.6000000e+00 1.9000000e+00 2.4000000e+00 2.6000000e+00 1.6000000e+00 1.5000000e+00 1.5000000e+00 2.7000000e+00 1.8000000e+00 1.5000000e+00 3.6000000e+00 3.6000000e+00 3.8000000e+00 2.8000000e+00 1.2000000e+00 2.0000000e+00 1.7000000e+00 6.0000000e-01 2.1000000e+00 2.4000000e+00 3.1000000e+00 2.7000000e+00 1.3000000e+00 2.8000000e+00 4.8000000e+00 2.6000000e+00 2.3000000e+00 2.3000000e+00 1.7000000e+00 4.7000000e+00 2.5000000e+00 2.5000000e+00 1.5000000e+00 1.7000000e+00 1.2000000e+00 1.5000000e+00 2.9000000e+00 2.8000000e+00 2.1000000e+00 1.4000000e+00 3.0000000e+00 8.0000000e-01 1.1000000e+00 1.0000000e+00 1.8000000e+00 1.9000000e+00 1.4000000e+00 8.0000000e-01 4.0000000e+00 3.9000000e+00 1.7000000e+00 1.7000000e+00 1.7000000e+00 3.2000000e+00 9.0000000e-01 1.4000000e+00 1.8000000e+00 1.0000000e+00 8.0000000e-01 1.5000000e+00 1.4000000e+00 2.2000000e+00 3.7000000e+00 1.6000000e+00 9.0000000e-01 1.9000000e+00 2.7000000e+00 2.1000000e+00 1.0000000e+00 1.0000000e+00 1.1000000e+00 1.4000000e+00 1.0000000e+00 1.5000000e+00 1.8000000e+00 1.8000000e+00 8.0000000e-01 1.1000000e+00 7.0000000e-01 1.9000000e+00 1.0000000e+00 2.1000000e+00 2.1000000e+00 2.3000000e+00 1.3000000e+00 9.0000000e-01 7.0000000e-01 6.0000000e-01 1.1000000e+00 1.2000000e+00 1.1000000e+00 1.6000000e+00 1.2000000e+00 4.0000000e-01 1.3000000e+00 3.3000000e+00 1.1000000e+00 1.0000000e+00 8.0000000e-01 6.0000000e-01 3.2000000e+00 1.0000000e+00 3.2000000e+00 1.4000000e+00 3.2000000e+00 1.7000000e+00 2.6000000e+00 4.4000000e+00 1.7000000e+00 3.4000000e+00 2.7000000e+00 4.5000000e+00 1.9000000e+00 1.8000000e+00 2.5000000e+00 1.7000000e+00 1.8000000e+00 2.3000000e+00 1.9000000e+00 5.5000000e+00 5.2000000e+00 1.2000000e+00 3.2000000e+00 1.4000000e+00 4.5000000e+00 1.2000000e+00 2.9000000e+00 3.3000000e+00 9.0000000e-01 9.0000000e-01 2.2000000e+00 2.7000000e+00 3.5000000e+00 5.2000000e+00 2.3000000e+00 1.0000000e+00 1.6000000e+00 4.2000000e+00 2.8000000e+00 1.9000000e+00 7.0000000e-01 2.6000000e+00 2.9000000e+00 2.5000000e+00 1.4000000e+00 3.3000000e+00 3.3000000e+00 2.3000000e+00 1.6000000e+00 1.8000000e+00 2.4000000e+00 1.1000000e+00 8.0000000e-01 6.0000000e-01 8.0000000e-01 2.6000000e+00 2.2000000e+00 2.7000000e+00 3.2000000e+00 2.1000000e+00 1.4000000e+00 1.1000000e+00 1.3000000e+00 2.3000000e+00 8.0000000e-01 1.2000000e+00 1.2000000e+00 1.3000000e+00 1.3000000e+00 1.9000000e+00 1.3000000e+00 1.1000000e+00 5.3000000e+00 2.7000000e+00 5.3000000e+00 3.8000000e+00 4.7000000e+00 6.5000000e+00 2.6000000e+00 5.5000000e+00 4.2000000e+00 6.6000000e+00 4.0000000e+00 3.5000000e+00 4.6000000e+00 2.6000000e+00 3.3000000e+00 4.4000000e+00 4.0000000e+00 7.6000000e+00 6.7000000e+00 2.7000000e+00 5.3000000e+00 2.7000000e+00 6.4000000e+00 2.9000000e+00 5.0000000e+00 5.4000000e+00 2.8000000e+00 3.0000000e+00 4.1000000e+00 4.8000000e+00 5.4000000e+00 7.3000000e+00 4.2000000e+00 2.9000000e+00 2.9000000e+00 6.3000000e+00 4.9000000e+00 4.0000000e+00 2.8000000e+00 4.7000000e+00 5.0000000e+00 4.6000000e+00 2.7000000e+00 5.4000000e+00 5.4000000e+00 4.4000000e+00 3.1000000e+00 3.9000000e+00 4.5000000e+00 3.0000000e+00 2.0000000e-01 8.0000000e-01 2.6000000e+00 1.8000000e+00 2.7000000e+00 3.2000000e+00 1.7000000e+00 1.2000000e+00 5.0000000e-01 9.0000000e-01 2.3000000e+00 8.0000000e-01 1.2000000e+00 1.0000000e+00 1.3000000e+00 1.3000000e+00 1.9000000e+00 1.3000000e+00 1.1000000e+00 5.3000000e+00 2.7000000e+00 5.3000000e+00 3.8000000e+00 4.7000000e+00 6.5000000e+00 2.0000000e+00 5.5000000e+00 4.0000000e+00 6.6000000e+00 4.0000000e+00 3.5000000e+00 4.6000000e+00 2.4000000e+00 3.3000000e+00 4.4000000e+00 4.0000000e+00 7.6000000e+00 6.7000000e+00 2.3000000e+00 5.3000000e+00 2.5000000e+00 6.4000000e+00 2.9000000e+00 5.0000000e+00 5.4000000e+00 2.8000000e+00 3.0000000e+00 4.1000000e+00 4.8000000e+00 5.4000000e+00 7.3000000e+00 4.2000000e+00 2.9000000e+00 2.9000000e+00 6.3000000e+00 4.9000000e+00 4.0000000e+00 2.8000000e+00 4.7000000e+00 5.0000000e+00 4.6000000e+00 2.7000000e+00 5.4000000e+00 5.4000000e+00 4.4000000e+00 2.9000000e+00 3.9000000e+00 4.5000000e+00 3.0000000e+00 1.0000000e+00 2.8000000e+00 2.0000000e+00 2.9000000e+00 3.4000000e+00 1.9000000e+00 1.4000000e+00 7.0000000e-01 1.1000000e+00 2.5000000e+00 1.0000000e+00 1.0000000e+00 1.2000000e+00 1.5000000e+00 1.5000000e+00 2.1000000e+00 1.3000000e+00 1.3000000e+00 5.5000000e+00 2.9000000e+00 5.5000000e+00 4.0000000e+00 4.9000000e+00 6.7000000e+00 2.2000000e+00 5.7000000e+00 4.2000000e+00 6.8000000e+00 4.2000000e+00 3.7000000e+00 4.8000000e+00 2.6000000e+00 3.5000000e+00 4.6000000e+00 4.2000000e+00 7.8000000e+00 6.9000000e+00 2.5000000e+00 5.5000000e+00 2.7000000e+00 6.6000000e+00 3.1000000e+00 5.2000000e+00 5.6000000e+00 3.0000000e+00 3.2000000e+00 4.3000000e+00 5.0000000e+00 5.6000000e+00 7.5000000e+00 4.4000000e+00 3.1000000e+00 3.1000000e+00 6.5000000e+00 5.1000000e+00 4.2000000e+00 3.0000000e+00 4.9000000e+00 5.2000000e+00 4.8000000e+00 2.9000000e+00 5.6000000e+00 5.6000000e+00 4.6000000e+00 3.1000000e+00 4.1000000e+00 4.7000000e+00 3.2000000e+00 1.8000000e+00 1.6000000e+00 1.9000000e+00 2.4000000e+00 1.5000000e+00 8.0000000e-01 7.0000000e-01 9.0000000e-01 1.5000000e+00 2.0000000e-01 2.0000000e+00 6.0000000e-01 7.0000000e-01 7.0000000e-01 1.1000000e+00 1.9000000e+00 5.0000000e-01 4.5000000e+00 1.9000000e+00 4.5000000e+00 3.0000000e+00 3.9000000e+00 5.7000000e+00 2.2000000e+00 4.7000000e+00 3.6000000e+00 5.8000000e+00 3.2000000e+00 2.7000000e+00 3.8000000e+00 2.2000000e+00 2.5000000e+00 3.6000000e+00 3.2000000e+00 6.8000000e+00 6.1000000e+00 2.1000000e+00 4.5000000e+00 2.1000000e+00 5.6000000e+00 2.1000000e+00 4.2000000e+00 4.6000000e+00 2.0000000e+00 2.2000000e+00 3.3000000e+00 4.0000000e+00 4.6000000e+00 6.5000000e+00 3.4000000e+00 2.1000000e+00 2.3000000e+00 5.5000000e+00 4.1000000e+00 3.2000000e+00 2.0000000e+00 3.9000000e+00 4.2000000e+00 3.8000000e+00 1.9000000e+00 4.6000000e+00 4.6000000e+00 3.6000000e+00 2.5000000e+00 3.1000000e+00 3.7000000e+00 2.2000000e+00 1.6000000e+00 1.3000000e+00 1.6000000e+00 1.7000000e+00 2.0000000e+00 2.1000000e+00 1.7000000e+00 1.1000000e+00 1.8000000e+00 3.8000000e+00 1.6000000e+00 1.9000000e+00 1.7000000e+00 1.5000000e+00 3.7000000e+00 1.7000000e+00 2.7000000e+00 5.0000000e-01 2.7000000e+00 1.2000000e+00 2.1000000e+00 3.9000000e+00 2.0000000e+00 2.9000000e+00 1.8000000e+00 4.0000000e+00 1.4000000e+00 9.0000000e-01 2.0000000e+00 1.0000000e+00 1.1000000e+00 1.8000000e+00 1.4000000e+00 5.0000000e+00 4.3000000e+00 7.0000000e-01 2.7000000e+00 1.1000000e+00 3.8000000e+00 7.0000000e-01 2.4000000e+00 2.8000000e+00 8.0000000e-01 8.0000000e-01 1.5000000e+00 2.2000000e+00 2.8000000e+00 4.7000000e+00 1.6000000e+00 5.0000000e-01 9.0000000e-01 3.7000000e+00 2.3000000e+00 1.4000000e+00 8.0000000e-01 2.1000000e+00 2.4000000e+00 2.0000000e+00 5.0000000e-01 2.8000000e+00 2.8000000e+00 1.8000000e+00 9.0000000e-01 1.3000000e+00 1.9000000e+00 6.0000000e-01 1.1000000e+00 1.6000000e+00 1.9000000e+00 8.0000000e-01 1.3000000e+00 9.0000000e-01 9.0000000e-01 1.6000000e+00 2.8000000e+00 1.0000000e+00 9.0000000e-01 9.0000000e-01 1.3000000e+00 2.7000000e+00 1.1000000e+00 3.7000000e+00 1.7000000e+00 3.7000000e+00 2.4000000e+00 3.1000000e+00 4.9000000e+00 1.2000000e+00 4.1000000e+00 3.4000000e+00 5.0000000e+00 2.4000000e+00 2.5000000e+00 3.0000000e+00 1.8000000e+00 2.1000000e+00 2.8000000e+00 2.4000000e+00 6.0000000e+00 5.9000000e+00 1.9000000e+00 3.7000000e+00 1.3000000e+00 5.2000000e+00 1.9000000e+00 3.4000000e+00 3.8000000e+00 1.6000000e+00 1.4000000e+00 2.9000000e+00 3.2000000e+00 4.2000000e+00 5.7000000e+00 3.0000000e+00 1.7000000e+00 2.3000000e+00 4.7000000e+00 3.3000000e+00 2.4000000e+00 1.2000000e+00 3.1000000e+00 3.4000000e+00 3.0000000e+00 1.7000000e+00 3.8000000e+00 3.8000000e+00 2.8000000e+00 2.3000000e+00 2.3000000e+00 2.9000000e+00 1.4000000e+00 1.3000000e+00 1.8000000e+00 1.5000000e+00 2.2000000e+00 1.8000000e+00 8.0000000e-01 1.9000000e+00 3.9000000e+00 1.7000000e+00 1.4000000e+00 1.4000000e+00 1.2000000e+00 3.8000000e+00 1.6000000e+00 2.8000000e+00 1.8000000e+00 3.4000000e+00 2.1000000e+00 2.8000000e+00 4.6000000e+00 2.1000000e+00 3.8000000e+00 3.1000000e+00 3.9000000e+00 1.7000000e+00 2.2000000e+00 2.7000000e+00 2.1000000e+00 2.2000000e+00 2.1000000e+00 2.1000000e+00 4.9000000e+00 5.6000000e+00 1.8000000e+00 3.0000000e+00 1.8000000e+00 4.9000000e+00 1.6000000e+00 2.5000000e+00 3.1000000e+00 1.3000000e+00 1.1000000e+00 2.6000000e+00 2.9000000e+00 3.9000000e+00 4.6000000e+00 2.7000000e+00 1.6000000e+00 2.2000000e+00 4.4000000e+00 2.2000000e+00 1.9000000e+00 9.0000000e-01 2.6000000e+00 2.9000000e+00 2.5000000e+00 1.8000000e+00 3.1000000e+00 2.9000000e+00 2.5000000e+00 2.0000000e+00 2.0000000e+00 1.8000000e+00 1.3000000e+00 1.7000000e+00 2.0000000e+00 2.7000000e+00 2.3000000e+00 9.0000000e-01 2.4000000e+00 4.4000000e+00 2.2000000e+00 1.9000000e+00 1.9000000e+00 1.3000000e+00 4.3000000e+00 2.1000000e+00 2.9000000e+00 2.1000000e+00 2.3000000e+00 1.8000000e+00 2.1000000e+00 3.5000000e+00 2.8000000e+00 2.7000000e+00 2.0000000e+00 3.4000000e+00 1.2000000e+00 1.7000000e+00 1.6000000e+00 2.4000000e+00 2.5000000e+00 1.8000000e+00 1.4000000e+00 4.4000000e+00 4.5000000e+00 1.9000000e+00 2.1000000e+00 2.1000000e+00 3.8000000e+00 1.3000000e+00 1.8000000e+00 2.2000000e+00 1.2000000e+00 1.2000000e+00 2.1000000e+00 1.8000000e+00 2.8000000e+00 4.1000000e+00 2.2000000e+00 1.1000000e+00 2.1000000e+00 3.3000000e+00 2.5000000e+00 1.4000000e+00 1.2000000e+00 1.5000000e+00 1.8000000e+00 1.4000000e+00 2.1000000e+00 2.2000000e+00 2.2000000e+00 1.4000000e+00 1.7000000e+00 1.3000000e+00 2.3000000e+00 1.6000000e+00 1.7000000e+00 1.4000000e+00 1.2000000e+00 1.2000000e+00 1.3000000e+00 2.7000000e+00 1.3000000e+00 1.6000000e+00 1.4000000e+00 8.0000000e-01 3.0000000e+00 1.4000000e+00 3.8000000e+00 2.2000000e+00 3.8000000e+00 2.3000000e+00 3.2000000e+00 5.0000000e+00 2.1000000e+00 4.0000000e+00 2.5000000e+00 5.1000000e+00 2.5000000e+00 2.0000000e+00 3.1000000e+00 2.1000000e+00 2.8000000e+00 2.9000000e+00 2.5000000e+00 6.1000000e+00 5.2000000e+00 1.2000000e+00 3.8000000e+00 2.4000000e+00 4.9000000e+00 1.4000000e+00 3.5000000e+00 3.9000000e+00 1.5000000e+00 1.9000000e+00 2.6000000e+00 3.3000000e+00 3.9000000e+00 5.8000000e+00 2.7000000e+00 1.4000000e+00 1.8000000e+00 4.8000000e+00 3.4000000e+00 2.5000000e+00 1.9000000e+00 3.2000000e+00 3.5000000e+00 3.1000000e+00 2.2000000e+00 3.9000000e+00 3.9000000e+00 2.9000000e+00 1.4000000e+00 2.4000000e+00 3.2000000e+00 2.3000000e+00 7.0000000e-01 9.0000000e-01 1.1000000e+00 8.0000000e-01 2.4000000e+00 4.0000000e-01 3.0000000e-01 3.0000000e-01 9.0000000e-01 2.3000000e+00 3.0000000e-01 4.1000000e+00 2.1000000e+00 4.1000000e+00 2.8000000e+00 3.5000000e+00 5.3000000e+00 2.0000000e+00 4.5000000e+00 3.8000000e+00 5.4000000e+00 2.8000000e+00 2.9000000e+00 3.4000000e+00 2.2000000e+00 2.5000000e+00 3.2000000e+00 2.8000000e+00 6.4000000e+00 6.3000000e+00 2.3000000e+00 4.1000000e+00 1.7000000e+00 5.6000000e+00 2.3000000e+00 3.8000000e+00 4.2000000e+00 2.0000000e+00 1.8000000e+00 3.3000000e+00 3.6000000e+00 4.6000000e+00 6.1000000e+00 3.4000000e+00 2.1000000e+00 2.5000000e+00 5.1000000e+00 3.7000000e+00 2.8000000e+00 1.6000000e+00 3.5000000e+00 3.8000000e+00 3.4000000e+00 2.1000000e+00 4.2000000e+00 4.2000000e+00 3.2000000e+00 2.7000000e+00 2.7000000e+00 3.3000000e+00 1.8000000e+00 6.0000000e-01 1.8000000e+00 5.0000000e-01 1.7000000e+00 5.0000000e-01 1.0000000e+00 8.0000000e-01 1.4000000e+00 1.6000000e+00 6.0000000e-01 4.8000000e+00 2.2000000e+00 4.8000000e+00 3.3000000e+00 4.2000000e+00 6.0000000e+00 1.5000000e+00 5.0000000e+00 3.5000000e+00 6.1000000e+00 3.5000000e+00 3.0000000e+00 4.1000000e+00 1.9000000e+00 2.8000000e+00 3.9000000e+00 3.5000000e+00 7.1000000e+00 6.2000000e+00 2.0000000e+00 4.8000000e+00 2.0000000e+00 5.9000000e+00 2.4000000e+00 4.5000000e+00 4.9000000e+00 2.3000000e+00 2.5000000e+00 3.6000000e+00 4.3000000e+00 4.9000000e+00 6.8000000e+00 3.7000000e+00 2.4000000e+00 2.4000000e+00 5.8000000e+00 4.4000000e+00 3.5000000e+00 2.3000000e+00 4.2000000e+00 4.5000000e+00 4.1000000e+00 2.2000000e+00 4.9000000e+00 4.9000000e+00 3.9000000e+00 2.4000000e+00 3.4000000e+00 4.0000000e+00 2.5000000e+00 1.4000000e+00 7.0000000e-01 2.1000000e+00 5.0000000e-01 8.0000000e-01 8.0000000e-01 1.2000000e+00 2.0000000e+00 8.0000000e-01 4.4000000e+00 1.8000000e+00 4.4000000e+00 2.9000000e+00 3.8000000e+00 5.6000000e+00 1.3000000e+00 4.6000000e+00 3.3000000e+00 5.7000000e+00 3.1000000e+00 2.6000000e+00 3.7000000e+00 1.7000000e+00 2.4000000e+00 3.5000000e+00 3.1000000e+00 6.7000000e+00 5.8000000e+00 1.8000000e+00 4.4000000e+00 1.6000000e+00 5.5000000e+00 2.0000000e+00 4.1000000e+00 4.5000000e+00 1.9000000e+00 2.1000000e+00 3.2000000e+00 3.9000000e+00 4.5000000e+00 6.4000000e+00 3.3000000e+00 2.0000000e+00 2.0000000e+00 5.4000000e+00 4.0000000e+00 3.1000000e+00 1.9000000e+00 3.8000000e+00 4.1000000e+00 3.7000000e+00 1.8000000e+00 4.5000000e+00 4.5000000e+00 3.5000000e+00 2.2000000e+00 3.0000000e+00 3.6000000e+00 2.1000000e+00 1.5000000e+00 3.5000000e+00 1.3000000e+00 1.0000000e+00 1.0000000e+00 6.0000000e-01 3.4000000e+00 1.2000000e+00 3.0000000e+00 1.6000000e+00 3.0000000e+00 1.7000000e+00 2.4000000e+00 4.2000000e+00 2.1000000e+00 3.4000000e+00 2.7000000e+00 4.3000000e+00 1.7000000e+00 1.8000000e+00 2.3000000e+00 1.9000000e+00 2.0000000e+00 2.1000000e+00 1.7000000e+00 5.3000000e+00 5.2000000e+00 1.4000000e+00 3.0000000e+00 1.6000000e+00 4.5000000e+00 1.2000000e+00 2.7000000e+00 3.1000000e+00 9.0000000e-01 7.0000000e-01 2.2000000e+00 2.5000000e+00 3.5000000e+00 5.0000000e+00 2.3000000e+00 1.0000000e+00 1.4000000e+00 4.0000000e+00 2.6000000e+00 1.7000000e+00 7.0000000e-01 2.4000000e+00 2.7000000e+00 2.3000000e+00 1.6000000e+00 3.1000000e+00 3.1000000e+00 2.1000000e+00 1.6000000e+00 1.6000000e+00 2.2000000e+00 1.1000000e+00 2.0000000e+00 6.0000000e-01 7.0000000e-01 7.0000000e-01 1.1000000e+00 1.9000000e+00 5.0000000e-01 4.5000000e+00 1.9000000e+00 4.5000000e+00 3.0000000e+00 3.9000000e+00 5.7000000e+00 2.0000000e+00 4.7000000e+00 3.4000000e+00 5.8000000e+00 3.2000000e+00 2.7000000e+00 3.8000000e+00 2.0000000e+00 2.5000000e+00 3.6000000e+00 3.2000000e+00 6.8000000e+00 5.9000000e+00 1.9000000e+00 4.5000000e+00 2.1000000e+00 5.6000000e+00 2.1000000e+00 4.2000000e+00 4.6000000e+00 2.0000000e+00 2.2000000e+00 3.3000000e+00 4.0000000e+00 4.6000000e+00 6.5000000e+00 3.4000000e+00 2.1000000e+00 2.1000000e+00 5.5000000e+00 4.1000000e+00 3.2000000e+00 2.0000000e+00 3.9000000e+00 4.2000000e+00 3.8000000e+00 1.9000000e+00 4.6000000e+00 4.6000000e+00 3.6000000e+00 2.3000000e+00 3.1000000e+00 3.7000000e+00 2.2000000e+00 2.2000000e+00 2.5000000e+00 2.5000000e+00 3.1000000e+00 7.0000000e-01 2.3000000e+00 6.5000000e+00 3.9000000e+00 6.5000000e+00 5.0000000e+00 5.9000000e+00 7.7000000e+00 2.2000000e+00 6.7000000e+00 5.2000000e+00 7.8000000e+00 5.2000000e+00 4.7000000e+00 5.8000000e+00 3.6000000e+00 4.5000000e+00 5.6000000e+00 5.2000000e+00 8.8000000e+00 7.9000000e+00 3.3000000e+00 6.5000000e+00 3.7000000e+00 7.6000000e+00 4.1000000e+00 6.2000000e+00 6.6000000e+00 4.0000000e+00 4.2000000e+00 5.3000000e+00 6.0000000e+00 6.6000000e+00 8.5000000e+00 5.4000000e+00 4.1000000e+00 4.1000000e+00 7.5000000e+00 6.1000000e+00 5.2000000e+00 4.0000000e+00 5.9000000e+00 6.2000000e+00 5.8000000e+00 3.9000000e+00 6.6000000e+00 6.6000000e+00 5.6000000e+00 4.1000000e+00 5.1000000e+00 5.7000000e+00 4.2000000e+00 5.0000000e-01 3.0000000e-01 9.0000000e-01 2.1000000e+00 3.0000000e-01 4.3000000e+00 1.7000000e+00 4.3000000e+00 2.8000000e+00 3.7000000e+00 5.5000000e+00 1.6000000e+00 4.5000000e+00 3.4000000e+00 5.6000000e+00 3.0000000e+00 2.5000000e+00 3.6000000e+00 1.8000000e+00 2.3000000e+00 3.4000000e+00 3.0000000e+00 6.6000000e+00 5.9000000e+00 1.9000000e+00 4.3000000e+00 1.5000000e+00 5.4000000e+00 1.9000000e+00 4.0000000e+00 4.4000000e+00 1.8000000e+00 2.0000000e+00 3.1000000e+00 3.8000000e+00 4.4000000e+00 6.3000000e+00 3.2000000e+00 1.9000000e+00 2.1000000e+00 5.3000000e+00 3.9000000e+00 3.0000000e+00 1.8000000e+00 3.7000000e+00 4.0000000e+00 3.6000000e+00 1.7000000e+00 4.4000000e+00 4.4000000e+00 3.4000000e+00 2.3000000e+00 2.9000000e+00 3.5000000e+00 2.0000000e+00 2.0000000e-01 8.0000000e-01 2.4000000e+00 4.0000000e-01 4.0000000e+00 2.0000000e+00 4.0000000e+00 2.7000000e+00 3.4000000e+00 5.2000000e+00 2.1000000e+00 4.4000000e+00 3.7000000e+00 5.3000000e+00 2.7000000e+00 2.8000000e+00 3.3000000e+00 2.1000000e+00 2.4000000e+00 3.1000000e+00 2.7000000e+00 6.3000000e+00 6.2000000e+00 2.2000000e+00 4.0000000e+00 1.8000000e+00 5.5000000e+00 2.2000000e+00 3.7000000e+00 4.1000000e+00 1.9000000e+00 1.7000000e+00 3.2000000e+00 3.5000000e+00 4.5000000e+00 6.0000000e+00 3.3000000e+00 2.0000000e+00 2.4000000e+00 5.0000000e+00 3.6000000e+00 2.7000000e+00 1.5000000e+00 3.4000000e+00 3.7000000e+00 3.3000000e+00 2.0000000e+00 4.1000000e+00 4.1000000e+00 3.1000000e+00 2.6000000e+00 2.6000000e+00 3.2000000e+00 1.7000000e+00 6.0000000e-01 2.4000000e+00 2.0000000e-01 4.0000000e+00 1.8000000e+00 4.0000000e+00 2.5000000e+00 3.4000000e+00 5.2000000e+00 1.9000000e+00 4.2000000e+00 3.5000000e+00 5.3000000e+00 2.7000000e+00 2.6000000e+00 3.3000000e+00 1.9000000e+00 2.2000000e+00 3.1000000e+00 2.7000000e+00 6.3000000e+00 6.0000000e+00 2.0000000e+00 4.0000000e+00 1.6000000e+00 5.3000000e+00 2.0000000e+00 3.7000000e+00 4.1000000e+00 1.7000000e+00 1.7000000e+00 3.0000000e+00 3.5000000e+00 4.3000000e+00 6.0000000e+00 3.1000000e+00 1.8000000e+00 2.2000000e+00 5.0000000e+00 3.6000000e+00 2.7000000e+00 1.5000000e+00 3.4000000e+00 3.7000000e+00 3.3000000e+00 1.8000000e+00 4.1000000e+00 4.1000000e+00 3.1000000e+00 2.4000000e+00 2.6000000e+00 3.2000000e+00 1.7000000e+00 3.0000000e+00 8.0000000e-01 3.4000000e+00 2.0000000e+00 3.4000000e+00 1.9000000e+00 2.8000000e+00 4.6000000e+00 2.3000000e+00 3.6000000e+00 2.9000000e+00 4.7000000e+00 2.1000000e+00 2.0000000e+00 2.7000000e+00 2.3000000e+00 2.4000000e+00 2.5000000e+00 2.1000000e+00 5.7000000e+00 5.4000000e+00 1.8000000e+00 3.4000000e+00 2.0000000e+00 4.7000000e+00 1.4000000e+00 3.1000000e+00 3.5000000e+00 1.1000000e+00 1.3000000e+00 2.4000000e+00 2.9000000e+00 3.7000000e+00 5.4000000e+00 2.5000000e+00 1.2000000e+00 1.8000000e+00 4.4000000e+00 3.0000000e+00 2.1000000e+00 1.3000000e+00 2.8000000e+00 3.1000000e+00 2.7000000e+00 2.0000000e+00 3.5000000e+00 3.5000000e+00 2.5000000e+00 1.8000000e+00 2.0000000e+00 2.6000000e+00 1.7000000e+00 2.2000000e+00 6.4000000e+00 3.8000000e+00 6.4000000e+00 4.9000000e+00 5.8000000e+00 7.6000000e+00 2.3000000e+00 6.6000000e+00 5.1000000e+00 7.7000000e+00 5.1000000e+00 4.6000000e+00 5.7000000e+00 3.5000000e+00 4.4000000e+00 5.5000000e+00 5.1000000e+00 8.7000000e+00 7.8000000e+00 3.6000000e+00 6.4000000e+00 3.6000000e+00 7.5000000e+00 4.0000000e+00 6.1000000e+00 6.5000000e+00 3.9000000e+00 4.1000000e+00 5.2000000e+00 5.9000000e+00 6.5000000e+00 8.4000000e+00 5.3000000e+00 4.0000000e+00 4.0000000e+00 7.4000000e+00 6.0000000e+00 5.1000000e+00 3.9000000e+00 5.8000000e+00 6.1000000e+00 5.7000000e+00 3.8000000e+00 6.5000000e+00 6.5000000e+00 5.5000000e+00 4.0000000e+00 5.0000000e+00 5.6000000e+00 4.1000000e+00 4.2000000e+00 1.8000000e+00 4.2000000e+00 2.7000000e+00 3.6000000e+00 5.4000000e+00 1.9000000e+00 4.4000000e+00 3.5000000e+00 5.5000000e+00 2.9000000e+00 2.6000000e+00 3.5000000e+00 1.9000000e+00 2.2000000e+00 3.3000000e+00 2.9000000e+00 6.5000000e+00 6.0000000e+00 2.0000000e+00 4.2000000e+00 1.6000000e+00 5.3000000e+00 2.0000000e+00 3.9000000e+00 4.3000000e+00 1.7000000e+00 1.9000000e+00 3.0000000e+00 3.7000000e+00 4.3000000e+00 6.2000000e+00 3.1000000e+00 1.8000000e+00 2.2000000e+00 5.2000000e+00 3.8000000e+00 2.9000000e+00 1.7000000e+00 3.6000000e+00 3.9000000e+00 3.5000000e+00 1.8000000e+00 4.3000000e+00 4.3000000e+00 3.3000000e+00 2.4000000e+00 2.8000000e+00 3.4000000e+00 1.9000000e+00 2.6000000e+00 1.6000000e+00 1.5000000e+00 1.0000000e+00 2.6000000e+00 4.5000000e+00 2.4000000e+00 2.1000000e+00 1.3000000e+00 1.7000000e+00 2.0000000e+00 1.7000000e+00 2.9000000e+00 2.0000000e+00 1.1000000e+00 1.7000000e+00 2.9000000e+00 3.2000000e+00 3.4000000e+00 1.2000000e+00 2.8000000e+00 3.1000000e+00 2.4000000e+00 1.1000000e+00 1.7000000e+00 2.5000000e+00 2.3000000e+00 1.4000000e+00 2.3000000e+00 2.3000000e+00 3.0000000e+00 1.3000000e+00 2.4000000e+00 2.4000000e+00 2.0000000e+00 6.0000000e-01 1.5000000e+00 2.5000000e+00 1.8000000e+00 1.1000000e+00 1.9000000e+00 2.6000000e+00 9.0000000e-01 7.0000000e-01 1.7000000e+00 2.4000000e+00 1.8000000e+00 1.0000000e+00 2.3000000e+00 2.6000000e+00 1.3000000e+00 2.0000000e+00 3.8000000e+00 1.9000000e+00 3.0000000e+00 1.9000000e+00 3.9000000e+00 1.3000000e+00 8.0000000e-01 1.9000000e+00 5.0000000e-01 6.0000000e-01 1.7000000e+00 1.5000000e+00 4.9000000e+00 4.2000000e+00 1.2000000e+00 2.6000000e+00 6.0000000e-01 3.7000000e+00 8.0000000e-01 2.3000000e+00 2.9000000e+00 9.0000000e-01 9.0000000e-01 1.4000000e+00 2.7000000e+00 2.7000000e+00 4.6000000e+00 1.5000000e+00 1.0000000e+00 1.4000000e+00 3.6000000e+00 2.2000000e+00 1.5000000e+00 9.0000000e-01 2.0000000e+00 2.3000000e+00 1.9000000e+00 0.0000000e+00 2.7000000e+00 2.7000000e+00 1.7000000e+00 8.0000000e-01 1.2000000e+00 1.8000000e+00 5.0000000e-01 1.5000000e+00 8.0000000e-01 1.2000000e+00 4.5000000e+00 1.0000000e+00 1.3000000e+00 1.3000000e+00 1.7000000e+00 1.8000000e+00 7.0000000e-01 2.9000000e+00 2.6000000e+00 1.7000000e+00 1.3000000e+00 2.3000000e+00 2.2000000e+00 3.4000000e+00 8.0000000e-01 2.8000000e+00 1.7000000e+00 2.4000000e+00 9.0000000e-01 7.0000000e-01 2.5000000e+00 2.3000000e+00 1.2000000e+00 7.0000000e-01 9.0000000e-01 2.2000000e+00 1.3000000e+00 2.4000000e+00 2.4000000e+00 1.0000000e+00 1.8000000e+00 1.5000000e+00 2.5000000e+00 8.0000000e-01 1.1000000e+00 1.3000000e+00 2.6000000e+00 7.0000000e-01 1.3000000e+00 1.3000000e+00 2.4000000e+00 1.4000000e+00 2.0000000e+00 2.3000000e+00 9.0000000e-01 2.7000000e+00 3.0000000e+00 1.7000000e+00 1.0000000e+00 2.8000000e+00 1.2000000e+00 7.0000000e-01 1.0000000e+00 1.8000000e+00 1.7000000e+00 1.2000000e+00 4.0000000e-01 3.8000000e+00 3.5000000e+00 1.9000000e+00 1.5000000e+00 1.7000000e+00 2.8000000e+00 9.0000000e-01 1.2000000e+00 1.6000000e+00 1.0000000e+00 1.0000000e+00 5.0000000e-01 1.4000000e+00 1.8000000e+00 3.5000000e+00 6.0000000e-01 9.0000000e-01 9.0000000e-01 2.5000000e+00 1.1000000e+00 4.0000000e-01 1.2000000e+00 1.3000000e+00 1.2000000e+00 1.8000000e+00 1.3000000e+00 1.6000000e+00 1.6000000e+00 1.4000000e+00 1.1000000e+00 9.0000000e-01 1.3000000e+00 1.0000000e+00 2.0000000e+00 3.9000000e+00 1.8000000e+00 1.1000000e+00 1.9000000e+00 1.1000000e+00 1.2000000e+00 7.0000000e-01 2.3000000e+00 1.8000000e+00 9.0000000e-01 7.0000000e-01 2.9000000e+00 2.8000000e+00 2.8000000e+00 8.0000000e-01 2.2000000e+00 2.5000000e+00 1.8000000e+00 7.0000000e-01 1.5000000e+00 1.9000000e+00 1.7000000e+00 6.0000000e-01 1.3000000e+00 1.7000000e+00 3.0000000e+00 5.0000000e-01 1.8000000e+00 1.8000000e+00 1.6000000e+00 1.0000000e+00 9.0000000e-01 1.9000000e+00 1.0000000e+00 7.0000000e-01 1.3000000e+00 2.0000000e+00 7.0000000e-01 9.0000000e-01 9.0000000e-01 1.8000000e+00 8.0000000e-01 1.2000000e+00 1.7000000e+00 5.7000000e+00 1.0000000e+00 2.5000000e+00 1.9000000e+00 2.9000000e+00 3.0000000e+00 1.9000000e+00 4.1000000e+00 3.8000000e+00 2.9000000e+00 2.5000000e+00 1.1000000e+00 1.0000000e+00 4.6000000e+00 2.0000000e+00 4.0000000e+00 5.0000000e-01 3.6000000e+00 2.1000000e+00 1.5000000e+00 3.7000000e+00 3.5000000e+00 2.4000000e+00 1.7000000e+00 1.1000000e+00 1.4000000e+00 2.5000000e+00 3.6000000e+00 3.6000000e+00 8.0000000e-01 3.0000000e+00 2.7000000e+00 3.7000000e+00 2.0000000e+00 2.3000000e+00 2.5000000e+00 3.8000000e+00 1.9000000e+00 2.5000000e+00 2.5000000e+00 3.6000000e+00 2.6000000e+00 3.2000000e+00 3.5000000e+00 4.7000000e+00 3.2000000e+00 5.8000000e+00 3.2000000e+00 2.7000000e+00 3.8000000e+00 1.6000000e+00 2.5000000e+00 3.6000000e+00 3.2000000e+00 6.8000000e+00 5.9000000e+00 2.1000000e+00 4.5000000e+00 1.7000000e+00 5.6000000e+00 2.1000000e+00 4.2000000e+00 4.6000000e+00 2.0000000e+00 2.2000000e+00 3.3000000e+00 4.2000000e+00 4.6000000e+00 6.5000000e+00 3.4000000e+00 2.5000000e+00 2.7000000e+00 5.5000000e+00 4.1000000e+00 3.2000000e+00 2.0000000e+00 3.9000000e+00 4.2000000e+00 3.8000000e+00 1.9000000e+00 4.6000000e+00 4.6000000e+00 3.6000000e+00 2.1000000e+00 3.1000000e+00 3.7000000e+00 2.2000000e+00 1.5000000e+00 1.7000000e+00 2.5000000e+00 2.2000000e+00 1.7000000e+00 3.5000000e+00 3.4000000e+00 2.7000000e+00 1.7000000e+00 2.1000000e+00 1.8000000e+00 3.6000000e+00 1.8000000e+00 3.4000000e+00 1.1000000e+00 2.6000000e+00 1.9000000e+00 7.0000000e-01 2.7000000e+00 2.7000000e+00 2.0000000e+00 9.0000000e-01 5.0000000e-01 1.8000000e+00 2.1000000e+00 2.6000000e+00 2.6000000e+00 1.2000000e+00 2.8000000e+00 1.9000000e+00 2.9000000e+00 1.8000000e+00 2.1000000e+00 2.3000000e+00 3.0000000e+00 1.7000000e+00 2.3000000e+00 2.3000000e+00 2.8000000e+00 2.2000000e+00 3.0000000e+00 2.7000000e+00 2.6000000e+00 1.8000000e+00 1.1000000e+00 1.2000000e+00 2.0000000e+00 2.5000000e+00 2.0000000e+00 1.0000000e+00 3.6000000e+00 2.7000000e+00 2.1000000e+00 1.5000000e+00 2.5000000e+00 2.4000000e+00 1.5000000e+00 1.2000000e+00 1.4000000e+00 1.8000000e+00 2.0000000e+00 1.1000000e+00 1.2000000e+00 1.4000000e+00 3.3000000e+00 1.2000000e+00 1.7000000e+00 1.3000000e+00 2.3000000e+00 2.1000000e+00 1.2000000e+00 2.2000000e+00 1.5000000e+00 1.4000000e+00 2.0000000e+00 1.9000000e+00 1.4000000e+00 1.6000000e+00 1.6000000e+00 1.3000000e+00 1.5000000e+00 2.3000000e+00 2.0000000e+00 2.6000000e+00 3.1000000e+00 2.0000000e+00 4.2000000e+00 3.3000000e+00 2.2000000e+00 2.6000000e+00 1.6000000e+00 2.5000000e+00 4.7000000e+00 1.3000000e+00 4.1000000e+00 2.4000000e+00 3.7000000e+00 1.6000000e+00 1.2000000e+00 3.8000000e+00 3.6000000e+00 2.5000000e+00 1.8000000e+00 1.6000000e+00 1.7000000e+00 2.4000000e+00 3.7000000e+00 3.7000000e+00 1.3000000e+00 1.7000000e+00 2.6000000e+00 3.8000000e+00 1.9000000e+00 1.6000000e+00 2.0000000e+00 3.9000000e+00 1.2000000e+00 1.2000000e+00 2.2000000e+00 3.7000000e+00 2.7000000e+00 2.1000000e+00 3.6000000e+00 9.0000000e-01 1.0000000e+00 1.6000000e+00 1.5000000e+00 6.0000000e-01 8.0000000e-01 3.6000000e+00 3.9000000e+00 2.1000000e+00 1.3000000e+00 1.5000000e+00 3.2000000e+00 1.1000000e+00 1.0000000e+00 1.8000000e+00 1.2000000e+00 1.0000000e+00 1.1000000e+00 2.0000000e+00 2.4000000e+00 3.3000000e+00 1.2000000e+00 1.1000000e+00 2.1000000e+00 2.7000000e+00 1.3000000e+00 8.0000000e-01 1.2000000e+00 9.0000000e-01 1.2000000e+00 8.0000000e-01 1.3000000e+00 1.4000000e+00 1.4000000e+00 8.0000000e-01 1.1000000e+00 3.0000000e-01 1.1000000e+00 1.0000000e+00 1.1000000e+00 1.3000000e+00 1.4000000e+00 9.0000000e-01 7.0000000e-01 4.1000000e+00 3.4000000e+00 1.6000000e+00 1.8000000e+00 1.4000000e+00 2.9000000e+00 6.0000000e-01 1.5000000e+00 2.1000000e+00 9.0000000e-01 1.1000000e+00 6.0000000e-01 1.9000000e+00 1.9000000e+00 3.8000000e+00 7.0000000e-01 8.0000000e-01 1.2000000e+00 2.8000000e+00 1.6000000e+00 7.0000000e-01 1.3000000e+00 1.2000000e+00 1.5000000e+00 1.5000000e+00 8.0000000e-01 1.9000000e+00 1.9000000e+00 1.1000000e+00 6.0000000e-01 6.0000000e-01 1.4000000e+00 1.1000000e+00 2.2000000e+00 1.9000000e+00 1.0000000e+00 6.0000000e-01 3.0000000e+00 2.9000000e+00 2.7000000e+00 7.0000000e-01 2.1000000e+00 2.4000000e+00 1.7000000e+00 6.0000000e-01 1.4000000e+00 1.8000000e+00 1.6000000e+00 7.0000000e-01 1.2000000e+00 1.6000000e+00 2.9000000e+00 8.0000000e-01 1.7000000e+00 1.9000000e+00 1.7000000e+00 1.3000000e+00 8.0000000e-01 1.8000000e+00 3.0000000e-01 6.0000000e-01 8.0000000e-01 1.9000000e+00 8.0000000e-01 1.0000000e+00 6.0000000e-01 1.7000000e+00 7.0000000e-01 1.3000000e+00 1.6000000e+00 9.0000000e-01 2.0000000e+00 2.0000000e+00 5.2000000e+00 4.3000000e+00 1.1000000e+00 2.9000000e+00 5.0000000e-01 4.0000000e+00 1.1000000e+00 2.6000000e+00 3.4000000e+00 1.2000000e+00 1.2000000e+00 1.7000000e+00 3.2000000e+00 3.2000000e+00 4.9000000e+00 1.8000000e+00 1.5000000e+00 1.7000000e+00 3.9000000e+00 2.5000000e+00 2.0000000e+00 1.2000000e+00 2.3000000e+00 2.6000000e+00 2.2000000e+00 5.0000000e-01 3.0000000e+00 3.0000000e+00 2.0000000e+00 7.0000000e-01 1.5000000e+00 2.1000000e+00 1.0000000e+00 1.3000000e+00 1.9000000e+00 4.7000000e+00 4.0000000e+00 1.8000000e+00 2.2000000e+00 8.0000000e-01 3.9000000e+00 1.4000000e+00 2.3000000e+00 3.3000000e+00 1.3000000e+00 1.3000000e+00 1.4000000e+00 3.1000000e+00 3.1000000e+00 4.8000000e+00 1.3000000e+00 1.4000000e+00 2.0000000e+00 3.2000000e+00 1.6000000e+00 1.9000000e+00 1.3000000e+00 2.0000000e+00 1.7000000e+00 1.5000000e+00 6.0000000e-01 2.3000000e+00 2.1000000e+00 1.3000000e+00 1.4000000e+00 1.4000000e+00 1.4000000e+00 9.0000000e-01 1.0000000e+00 3.4000000e+00 3.5000000e+00 2.5000000e+00 9.0000000e-01 1.9000000e+00 3.4000000e+00 1.5000000e+00 1.0000000e+00 2.0000000e+00 1.6000000e+00 1.4000000e+00 9.0000000e-01 2.2000000e+00 2.6000000e+00 3.5000000e+00 8.0000000e-01 1.5000000e+00 2.1000000e+00 2.3000000e+00 7.0000000e-01 8.0000000e-01 1.6000000e+00 9.0000000e-01 8.0000000e-01 8.0000000e-01 1.7000000e+00 1.0000000e+00 1.0000000e+00 6.0000000e-01 1.5000000e+00 7.0000000e-01 5.0000000e-01 1.4000000e+00 3.6000000e+00 3.5000000e+00 2.1000000e+00 1.3000000e+00 1.9000000e+00 2.8000000e+00 1.1000000e+00 1.0000000e+00 1.4000000e+00 1.2000000e+00 1.0000000e+00 7.0000000e-01 1.2000000e+00 1.8000000e+00 3.3000000e+00 8.0000000e-01 1.1000000e+00 1.3000000e+00 2.3000000e+00 1.3000000e+00 2.0000000e-01 1.2000000e+00 9.0000000e-01 1.0000000e+00 1.4000000e+00 1.5000000e+00 1.4000000e+00 1.4000000e+00 1.0000000e+00 1.3000000e+00 5.0000000e-01 1.3000000e+00 1.0000000e+00 1.5000000e+00 5.7000000e+00 2.5000000e+00 5.1000000e+00 1.2000000e+00 4.7000000e+00 2.6000000e+00 2.2000000e+00 4.8000000e+00 4.6000000e+00 3.5000000e+00 2.8000000e+00 2.2000000e+00 7.0000000e-01 3.4000000e+00 4.7000000e+00 4.7000000e+00 1.5000000e+00 3.1000000e+00 3.6000000e+00 4.8000000e+00 2.9000000e+00 3.0000000e+00 3.2000000e+00 4.9000000e+00 2.4000000e+00 2.8000000e+00 3.4000000e+00 4.7000000e+00 3.7000000e+00 3.3000000e+00 4.6000000e+00 4.8000000e+00 2.6000000e+00 4.6000000e+00 7.0000000e-01 4.0000000e+00 3.1000000e+00 2.5000000e+00 4.3000000e+00 4.5000000e+00 3.0000000e+00 2.7000000e+00 1.7000000e+00 2.2000000e+00 2.9000000e+00 4.2000000e+00 3.8000000e+00 1.2000000e+00 3.6000000e+00 3.7000000e+00 4.7000000e+00 3.0000000e+00 2.9000000e+00 3.1000000e+00 4.2000000e+00 2.5000000e+00 3.1000000e+00 3.1000000e+00 3.8000000e+00 3.6000000e+00 3.8000000e+00 4.5000000e+00 3.4000000e+00 1.6000000e+00 4.5000000e+00 1.2000000e+00 3.1000000e+00 3.5000000e+00 1.3000000e+00 1.3000000e+00 2.2000000e+00 2.9000000e+00 3.5000000e+00 5.4000000e+00 2.3000000e+00 1.0000000e+00 1.2000000e+00 4.4000000e+00 3.0000000e+00 2.1000000e+00 1.3000000e+00 2.8000000e+00 3.1000000e+00 2.7000000e+00 1.2000000e+00 3.5000000e+00 3.5000000e+00 2.5000000e+00 1.0000000e+00 2.0000000e+00 2.6000000e+00 1.3000000e+00 2.8000000e+00 2.5000000e+00 2.4000000e+00 5.0000000e-01 1.1000000e+00 2.5000000e+00 2.3000000e+00 1.2000000e+00 1.3000000e+00 1.7000000e+00 2.6000000e+00 1.1000000e+00 2.4000000e+00 2.4000000e+00 1.4000000e+00 1.0000000e+00 1.3000000e+00 2.5000000e+00 6.0000000e-01 5.0000000e-01 7.0000000e-01 2.6000000e+00 3.0000000e-01 5.0000000e-01 9.0000000e-01 2.4000000e+00 1.4000000e+00 1.2000000e+00 2.3000000e+00 3.9000000e+00 1.0000000e+00 2.5000000e+00 3.3000000e+00 9.0000000e-01 9.0000000e-01 1.6000000e+00 3.1000000e+00 3.1000000e+00 4.8000000e+00 1.7000000e+00 1.4000000e+00 2.0000000e+00 3.8000000e+00 2.4000000e+00 1.9000000e+00 9.0000000e-01 2.2000000e+00 2.5000000e+00 2.1000000e+00 6.0000000e-01 2.9000000e+00 2.9000000e+00 1.9000000e+00 1.2000000e+00 1.4000000e+00 2.0000000e+00 9.0000000e-01 3.5000000e+00 2.6000000e+00 1.8000000e+00 3.6000000e+00 3.8000000e+00 2.5000000e+00 2.0000000e+00 1.0000000e+00 1.5000000e+00 2.6000000e+00 3.5000000e+00 3.5000000e+00 1.1000000e+00 3.5000000e+00 3.0000000e+00 4.0000000e+00 2.5000000e+00 2.8000000e+00 3.0000000e+00 3.7000000e+00 2.4000000e+00 3.0000000e+00 3.0000000e+00 3.5000000e+00 2.9000000e+00 3.7000000e+00 3.8000000e+00 2.1000000e+00 2.5000000e+00 3.0000000e-01 5.0000000e-01 1.2000000e+00 2.3000000e+00 2.5000000e+00 4.4000000e+00 1.3000000e+00 6.0000000e-01 1.4000000e+00 3.4000000e+00 2.0000000e+00 1.1000000e+00 7.0000000e-01 1.8000000e+00 2.1000000e+00 1.7000000e+00 8.0000000e-01 2.5000000e+00 2.5000000e+00 1.5000000e+00 4.0000000e-01 1.0000000e+00 1.8000000e+00 9.0000000e-01 1.2000000e+00 2.2000000e+00 2.0000000e+00 9.0000000e-01 1.4000000e+00 1.8000000e+00 2.5000000e+00 1.0000000e+00 2.1000000e+00 2.1000000e+00 1.9000000e+00 9.0000000e-01 1.0000000e+00 2.2000000e+00 7.0000000e-01 6.0000000e-01 1.2000000e+00 2.3000000e+00 6.0000000e-01 4.0000000e-01 1.0000000e+00 2.1000000e+00 1.1000000e+00 1.1000000e+00 2.0000000e+00 2.6000000e+00 2.4000000e+00 1.9000000e+00 6.0000000e-01 8.0000000e-01 1.9000000e+00 2.0000000e+00 2.5000000e+00 2.5000000e+00 1.3000000e+00 2.1000000e+00 1.4000000e+00 2.6000000e+00 1.3000000e+00 1.6000000e+00 1.8000000e+00 2.9000000e+00 1.0000000e+00 1.6000000e+00 2.0000000e+00 2.7000000e+00 1.9000000e+00 2.3000000e+00 2.4000000e+00 4.0000000e-01 1.3000000e+00 2.4000000e+00 2.6000000e+00 4.5000000e+00 1.4000000e+00 7.0000000e-01 1.5000000e+00 3.5000000e+00 2.1000000e+00 1.2000000e+00 4.0000000e-01 1.9000000e+00 2.2000000e+00 1.8000000e+00 9.0000000e-01 2.6000000e+00 2.6000000e+00 1.6000000e+00 7.0000000e-01 1.1000000e+00 1.7000000e+00 8.0000000e-01 1.5000000e+00 2.2000000e+00 2.8000000e+00 4.3000000e+00 1.6000000e+00 9.0000000e-01 1.5000000e+00 3.3000000e+00 1.9000000e+00 1.0000000e+00 2.0000000e-01 1.7000000e+00 2.0000000e+00 1.6000000e+00 9.0000000e-01 2.4000000e+00 2.4000000e+00 1.4000000e+00 9.0000000e-01 9.0000000e-01 1.5000000e+00 4.0000000e-01 1.7000000e+00 1.7000000e+00 3.4000000e+00 1.0000000e-01 1.2000000e+00 1.2000000e+00 2.2000000e+00 1.0000000e+00 7.0000000e-01 1.7000000e+00 1.0000000e+00 9.0000000e-01 1.5000000e+00 1.4000000e+00 1.3000000e+00 1.3000000e+00 1.1000000e+00 1.2000000e+00 8.0000000e-01 1.2000000e+00 1.5000000e+00 1.0000000e+00 2.5000000e+00 1.8000000e+00 1.9000000e+00 1.9000000e+00 1.5000000e+00 2.3000000e+00 1.4000000e+00 2.4000000e+00 1.3000000e+00 1.6000000e+00 1.8000000e+00 2.7000000e+00 1.4000000e+00 1.8000000e+00 1.8000000e+00 2.5000000e+00 1.7000000e+00 2.5000000e+00 2.2000000e+00 1.9000000e+00 1.8000000e+00 2.5000000e+00 2.5000000e+00 9.0000000e-01 2.7000000e+00 2.0000000e+00 3.0000000e+00 1.7000000e+00 2.0000000e+00 2.2000000e+00 2.7000000e+00 1.6000000e+00 2.2000000e+00 2.2000000e+00 2.5000000e+00 2.1000000e+00 2.9000000e+00 2.8000000e+00 3.5000000e+00 4.4000000e+00 4.4000000e+00 1.6000000e+00 3.2000000e+00 3.3000000e+00 4.5000000e+00 2.8000000e+00 3.1000000e+00 3.3000000e+00 4.6000000e+00 2.5000000e+00 2.9000000e+00 3.5000000e+00 4.4000000e+00 3.4000000e+00 3.4000000e+00 4.3000000e+00 1.3000000e+00 1.3000000e+00 2.1000000e+00 9.0000000e-01 8.0000000e-01 1.8000000e+00 1.1000000e+00 8.0000000e-01 1.4000000e+00 1.5000000e+00 1.2000000e+00 1.2000000e+00 1.0000000e+00 1.3000000e+00 9.0000000e-01 1.1000000e+00 1.6000000e+00 1.0000000e+00 3.4000000e+00 2.0000000e+00 1.1000000e+00 1.1000000e+00 1.8000000e+00 2.1000000e+00 1.7000000e+00 1.0000000e+00 2.5000000e+00 2.5000000e+00 1.5000000e+00 8.0000000e-01 1.0000000e+00 1.8000000e+00 9.0000000e-01 3.4000000e+00 2.0000000e+00 1.3000000e+00 1.7000000e+00 2.2000000e+00 2.1000000e+00 2.7000000e+00 1.4000000e+00 2.5000000e+00 2.5000000e+00 2.3000000e+00 1.4000000e+00 1.8000000e+00 2.0000000e+00 1.5000000e+00 2.4000000e+00 2.5000000e+00 3.5000000e+00 1.8000000e+00 1.7000000e+00 1.9000000e+00 3.6000000e+00 1.3000000e+00 1.9000000e+00 1.9000000e+00 3.4000000e+00 2.4000000e+00 2.6000000e+00 3.3000000e+00 1.1000000e+00 2.1000000e+00 1.4000000e+00 7.0000000e-01 1.5000000e+00 2.2000000e+00 1.1000000e+00 7.0000000e-01 1.3000000e+00 2.0000000e+00 1.4000000e+00 4.0000000e-01 1.9000000e+00 1.2000000e+00 9.0000000e-01 1.0000000e+00 1.4000000e+00 1.5000000e+00 1.4000000e+00 1.4000000e+00 1.2000000e+00 1.3000000e+00 7.0000000e-01 1.1000000e+00 1.0000000e+00 1.9000000e+00 2.2000000e+00 1.8000000e+00 9.0000000e-01 2.6000000e+00 2.6000000e+00 1.6000000e+00 1.1000000e+00 1.1000000e+00 1.7000000e+00 4.0000000e-01 7.0000000e-01 5.0000000e-01 2.0000000e+00 9.0000000e-01 1.1000000e+00 7.0000000e-01 1.8000000e+00 8.0000000e-01 1.2000000e+00 1.7000000e+00 8.0000000e-01 2.3000000e+00 6.0000000e-01 4.0000000e-01 6.0000000e-01 2.1000000e+00 1.1000000e+00 1.1000000e+00 2.0000000e+00 1.9000000e+00 1.0000000e+00 1.2000000e+00 4.0000000e-01 1.7000000e+00 9.0000000e-01 1.3000000e+00 1.6000000e+00 2.7000000e+00 2.7000000e+00 1.7000000e+00 8.0000000e-01 1.2000000e+00 1.8000000e+00 5.0000000e-01 6.0000000e-01 1.0000000e+00 2.5000000e+00 1.5000000e+00 1.3000000e+00 2.4000000e+00 1.0000000e+00 2.5000000e+00 1.5000000e+00 1.1000000e+00 2.4000000e+00 1.5000000e+00 5.0000000e-01 1.1000000e+00 1.4000000e+00 1.0000000e+00 1.8000000e+00 1.1000000e+00 1.2000000e+00 9.0000000e-01 1.5000000e+00 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-cityblock-ml.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-cityblock-ml.txt new file mode 100644 index 0000000000000000000000000000000000000000..8fb22e62200894f9693010ebf45fb23751f4e3a6 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-cityblock-ml.txt @@ -0,0 +1 @@ + 3.2420590e+01 3.3246607e+01 3.0526910e+01 3.5166573e+01 3.1868301e+01 3.6025002e+01 3.2513623e+01 3.6557796e+01 3.3752212e+01 3.4422130e+01 3.2526018e+01 3.2581161e+01 3.3743555e+01 3.6960777e+01 3.4225270e+01 3.2965308e+01 3.4591031e+01 3.4204203e+01 3.4678123e+01 3.5728720e+01 3.0830047e+01 3.1550681e+01 3.3304790e+01 3.2676753e+01 3.2742330e+01 3.1684556e+01 3.2830915e+01 3.2956614e+01 2.7365639e+01 3.3207307e+01 3.3420925e+01 3.4357941e+01 2.8280126e+01 3.4523458e+01 3.2705274e+01 3.2455891e+01 3.1636060e+01 3.1594957e+01 3.1805202e+01 3.3886574e+01 3.3438829e+01 3.3330030e+01 3.4168514e+01 3.0637353e+01 4.2149167e+01 3.6340559e+01 2.9315308e+01 3.5778314e+01 3.7693050e+01 3.2598714e+01 3.2990836e+01 3.4967659e+01 3.9748920e+01 3.6745043e+01 2.7117550e+01 3.6014760e+01 2.9367558e+01 3.3845350e+01 3.5477339e+01 3.1513372e+01 3.2517953e+01 2.4755097e+01 3.0229897e+01 3.4799343e+01 3.3371710e+01 2.9600910e+01 3.3275088e+01 3.3567110e+01 3.4527016e+01 3.4942320e+01 3.2359383e+01 3.2607100e+01 3.1467914e+01 2.9032039e+01 3.3122878e+01 2.8496709e+01 2.9908448e+01 2.9962886e+01 3.0345299e+01 3.1737613e+01 2.8551485e+01 3.2610551e+01 3.3082660e+01 3.3719298e+01 3.6434018e+01 3.6589278e+01 3.3889586e+01 3.8036774e+01 3.1483497e+01 3.4196794e+01 3.5154035e+01 3.5488608e+01 3.6143183e+01 3.3473491e+01 3.4686446e+01 2.8687495e+01 3.5725742e+01 3.0188298e+01 3.3084534e+01 3.3538519e+01 3.6226849e+01 2.9052099e+01 3.6032733e+01 3.0811503e+01 3.2616190e+01 3.3888566e+01 3.3074570e+01 2.9683515e+01 3.0600771e+01 3.4345247e+01 3.6983843e+01 3.3692824e+01 3.3762461e+01 3.4024582e+01 3.3698854e+01 3.1238613e+01 3.4978833e+01 3.4991078e+01 3.4577741e+01 3.3749227e+01 3.4982272e+01 3.0487868e+01 3.2317632e+01 3.1125588e+01 3.4413791e+01 3.1881871e+01 3.1373821e+01 3.0416864e+01 3.2066187e+01 3.1128313e+01 3.0240249e+01 3.0125198e+01 3.1343454e+01 3.5479092e+01 3.4450767e+01 3.2953507e+01 3.4456795e+01 3.0136375e+01 3.3462150e+01 2.9894274e+01 3.1367432e+01 3.2839320e+01 3.1440398e+01 2.9400374e+01 3.1106338e+01 3.1242624e+01 3.5537892e+01 3.3056459e+01 2.8610281e+01 3.4296217e+01 3.5819772e+01 3.2503922e+01 3.0963029e+01 3.4762112e+01 3.4796284e+01 2.9645345e+01 3.4468088e+01 2.6975590e+01 3.3738555e+01 2.8825009e+01 3.2663999e+01 3.2547878e+01 3.2308091e+01 3.2489966e+01 3.0868597e+01 3.2974220e+01 3.0866111e+01 3.8197342e+01 3.0609568e+01 3.5478978e+01 2.9249184e+01 3.6185622e+01 3.1948258e+01 3.2649719e+01 3.3305650e+01 3.4643955e+01 3.6566241e+01 3.4968484e+01 3.2632218e+01 3.6741383e+01 3.5700008e+01 3.1962468e+01 3.1410623e+01 3.0412061e+01 3.3749077e+01 3.5649661e+01 3.7649263e+01 3.2832574e+01 3.1783914e+01 2.8264292e+01 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-correlation-ml-iris.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-correlation-ml-iris.txt new file mode 100644 index 0000000000000000000000000000000000000000..f297500381fe33428e6725ea3b10ab6191a46fa3 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-correlation-ml-iris.txt @@ -0,0 +1 @@ + 4.0013388e-03 2.6088954e-05 1.8315482e-03 6.5266850e-04 4.1394685e-04 1.1888069e-03 4.6185289e-04 1.9233577e-03 3.4480388e-03 1.5150632e-05 1.9126718e-03 3.0974734e-03 2.2295833e-04 2.4043394e-03 5.0134320e-03 3.0165570e-03 1.3145239e-04 6.0759419e-04 1.6672981e-03 4.0036132e-03 6.1375191e-04 8.5916540e-03 3.0212269e-03 8.6923503e-03 7.7875235e-03 5.1612907e-04 2.9662451e-04 6.2402983e-04 2.7278440e-03 4.0510347e-03 3.0027154e-03 6.2616145e-03 4.1342211e-03 3.4480388e-03 1.5822510e-03 1.7143312e-03 3.4480388e-03 2.2462074e-04 6.1048465e-04 6.5190641e-04 2.4247873e-02 9.0785596e-04 2.1652052e-04 3.4845573e-03 3.2507646e-03 2.3346511e-03 4.0773355e-04 1.1278223e-04 5.0819669e-04 2.1340893e-01 2.1253858e-01 2.5193073e-01 2.9479565e-01 2.6774348e-01 2.8869785e-01 2.3348217e-01 1.9273490e-01 2.4443270e-01 2.4320510e-01 2.7679421e-01 2.1672263e-01 2.6813840e-01 2.8435705e-01 1.5561363e-01 2.0057173e-01 2.7812139e-01 2.2900256e-01 3.4724680e-01 2.3882260e-01 2.9132931e-01 2.0333645e-01 3.5307051e-01 2.8812452e-01 2.1722530e-01 2.1423111e-01 2.7396952e-01 2.9207940e-01 2.6626182e-01 1.7106032e-01 2.4279706e-01 2.2559055e-01 2.0940857e-01 3.8432412e-01 2.9354670e-01 2.0829958e-01 2.3669414e-01 3.0463326e-01 2.1035851e-01 2.6623117e-01 3.0835417e-01 2.5871089e-01 2.3465249e-01 2.0319416e-01 2.6292582e-01 2.1771735e-01 2.3212816e-01 2.2399387e-01 1.3799316e-01 2.3049526e-01 4.8512087e-01 4.2535066e-01 4.0184471e-01 4.1903049e-01 4.4627199e-01 4.4692268e-01 4.3569888e-01 4.2673251e-01 4.5731950e-01 3.7438176e-01 3.0619251e-01 4.0039114e-01 3.7245195e-01 4.5829878e-01 4.5814844e-01 3.6107062e-01 3.7600936e-01 3.7662883e-01 5.2492832e-01 4.2684428e-01 3.7975064e-01 4.0636707e-01 4.6364339e-01 3.4607190e-01 3.6988036e-01 3.6764668e-01 3.2524634e-01 3.1943549e-01 4.4481193e-01 3.5496498e-01 4.1356534e-01 3.2082320e-01 4.5322964e-01 3.4300770e-01 4.4485158e-01 3.9755578e-01 3.9702418e-01 3.7202285e-01 3.1131344e-01 3.4018064e-01 4.0217537e-01 3.1441868e-01 4.2535066e-01 4.1533176e-01 3.9695242e-01 3.5313531e-01 3.9400199e-01 3.4652657e-01 3.6608320e-01 3.6684161e-01 3.3929143e-03 2.6033698e-03 7.7673212e-03 6.4081099e-03 9.2794464e-03 2.8819447e-03 1.4536586e-03 9.6714455e-04 3.7992387e-03 5.9342609e-03 3.9974031e-04 6.0694735e-03 9.1304628e-03 1.7655983e-02 1.1643899e-02 4.0363794e-03 1.6463709e-03 1.0706739e-02 6.7984475e-04 7.6845878e-03 2.3516587e-02 9.9502337e-05 1.0315881e-02 1.0821735e-03 1.8887942e-03 2.4624674e-03 1.5760536e-03 3.6638868e-03 1.6253664e-03 7.8762517e-04 1.9487010e-02 1.6211862e-02 9.6714455e-04 2.2382105e-03 2.1712385e-03 9.6714455e-04 2.9674185e-03 1.9068589e-03 6.4555509e-03 8.8254342e-03 8.1777355e-03 3.4663084e-03 9.6481454e-03 9.7747764e-05 1.0706793e-02 4.2246850e-03 4.9836128e-03 1.6613867e-03 1.6856078e-01 1.6930583e-01 2.0381801e-01 2.4171317e-01 2.1689289e-01 2.4212069e-01 1.9027913e-01 1.5127382e-01 1.9696970e-01 1.9830901e-01 2.2503195e-01 1.7290786e-01 2.1618942e-01 2.3648275e-01 1.1720113e-01 1.5636322e-01 2.3357633e-01 1.8548772e-01 2.8791738e-01 1.9215793e-01 2.4470933e-01 1.5850128e-01 2.9662484e-01 2.4061109e-01 1.7172858e-01 1.6853658e-01 2.2283143e-01 2.4032537e-01 2.1849821e-01 1.2975740e-01 1.9502432e-01 1.7953012e-01 1.6504306e-01 3.2966120e-01 2.4985160e-01 1.6946778e-01 1.8991741e-01 2.4919698e-01 1.7046257e-01 2.1691882e-01 2.6018338e-01 2.1310883e-01 1.8776864e-01 1.5909082e-01 2.1620321e-01 1.7782256e-01 1.8911127e-01 1.7894094e-01 9.9649433e-02 1.8605378e-01 4.2702260e-01 3.6742642e-01 3.4284735e-01 3.6351462e-01 3.8703088e-01 3.8643219e-01 3.8033312e-01 3.6849688e-01 3.9561383e-01 3.1894438e-01 2.5437467e-01 3.4129756e-01 3.1464030e-01 3.9617829e-01 3.9513061e-01 3.0506617e-01 3.2181902e-01 3.2465822e-01 4.5849285e-01 3.6615509e-01 3.2201598e-01 3.4969244e-01 4.0175045e-01 2.8934891e-01 3.1614551e-01 3.1385643e-01 2.7059114e-01 2.6798818e-01 3.8429703e-01 3.0087709e-01 3.5349775e-01 2.7097983e-01 3.9156246e-01 2.9045741e-01 3.8972428e-01 3.3603762e-01 3.4254663e-01 3.1960575e-01 2.6050327e-01 2.8406500e-01 3.4225008e-01 2.5735736e-01 3.6742642e-01 3.5724408e-01 3.3861338e-01 2.9412113e-01 3.3288556e-01 2.9101723e-01 3.1374321e-01 3.1516519e-01 1.6665208e-03 9.3886805e-04 6.2270349e-04 1.5623211e-03 3.9549141e-04 1.6439076e-03 3.0144044e-03 3.0583810e-05 2.0234943e-03 2.6246966e-03 3.8983492e-04 2.5645160e-03 5.6944285e-03 3.3339055e-03 1.2831328e-04 4.1302346e-04 2.1101667e-03 3.4972086e-03 8.7482704e-04 9.4271115e-03 2.5080125e-03 8.7042936e-03 7.0125369e-03 3.5088415e-04 1.9451019e-04 3.9574419e-04 2.5986219e-03 3.6402032e-03 2.4900748e-03 7.0784673e-03 4.7935149e-03 3.0144044e-03 1.2869381e-03 1.4017897e-03 3.0144044e-03 1.7197161e-04 4.4525534e-04 7.8138074e-04 2.2693053e-02 1.2229281e-03 1.5754704e-04 3.7899670e-03 2.6957902e-03 2.7721274e-03 4.5733371e-04 2.2324575e-04 3.1003560e-04 2.1002397e-01 2.0931874e-01 2.4834042e-01 2.9081912e-01 2.6391644e-01 2.8536997e-01 2.3033428e-01 1.8962461e-01 2.4088505e-01 2.3991724e-01 2.7290008e-01 2.1345771e-01 2.6419304e-01 2.8088883e-01 1.5266518e-01 1.9720348e-01 2.7496549e-01 2.2580939e-01 3.4275207e-01 2.3533918e-01 2.8800391e-01 1.9991219e-01 3.4890690e-01 2.8470246e-01 2.1378625e-01 2.1075909e-01 2.7013290e-01 2.8823552e-01 2.6275308e-01 1.6787442e-01 2.3921107e-01 2.2212337e-01 2.0605918e-01 3.8041788e-01 2.9051019e-01 2.0550537e-01 2.3319159e-01 3.0043218e-01 2.0746652e-01 2.6256228e-01 3.0491843e-01 2.5539836e-01 2.3113139e-01 1.9984797e-01 2.5951290e-01 2.1484809e-01 2.2899468e-01 2.2062653e-01 1.3495710e-01 2.2721304e-01 4.8106467e-01 4.2120214e-01 3.9753504e-01 4.1511036e-01 4.4203186e-01 4.4255637e-01 4.3182495e-01 4.2255527e-01 4.5284888e-01 3.7037516e-01 3.0238339e-01 3.9606802e-01 3.6819494e-01 4.5378706e-01 4.5354234e-01 3.5697379e-01 3.7213234e-01 3.7297305e-01 5.2009409e-01 4.2241474e-01 3.7552000e-01 4.0230555e-01 4.5916611e-01 3.4185974e-01 3.6603540e-01 3.6379117e-01 3.2119479e-01 3.1570003e-01 4.4043880e-01 3.5104995e-01 4.0917086e-01 3.1725229e-01 4.4875464e-01 3.3921954e-01 4.4101743e-01 3.9296628e-01 3.9316311e-01 3.6831351e-01 3.0762140e-01 3.3601664e-01 3.9776902e-01 3.1006892e-01 4.2120214e-01 4.1114584e-01 3.9269988e-01 3.4869458e-01 3.8944692e-01 3.4244384e-01 3.6236872e-01 3.6319420e-01 3.2811792e-03 2.1674206e-03 3.8606330e-03 4.5444049e-04 1.6669051e-04 6.9315236e-04 1.5191179e-03 7.4896915e-04 1.0486334e-03 3.0115188e-03 8.3553530e-03 1.1528814e-02 9.5172421e-03 2.7099731e-03 7.1677618e-04 4.9455548e-03 1.1260396e-03 4.0113810e-03 1.7041109e-02 1.7048436e-03 3.2998306e-03 3.5839458e-03 6.5708756e-04 7.5073414e-04 1.6739794e-03 1.4404874e-04 6.5489426e-04 3.9918560e-03 9.7678136e-03 9.5698494e-03 6.9315236e-04 4.1051921e-03 4.2098821e-03 6.9315236e-04 7.7852178e-04 5.0066998e-04 4.6641147e-03 1.9877450e-02 2.9999880e-03 2.6696154e-03 2.3124511e-03 2.6940762e-03 3.6188953e-03 7.8131154e-04 1.7395433e-03 1.1236329e-03 1.8068407e-01 1.7911784e-01 2.1632614e-01 2.5732132e-01 2.3189913e-01 2.4898678e-01 1.9775994e-01 1.6095697e-01 2.0933838e-01 2.0710048e-01 2.4048237e-01 1.8306865e-01 2.3298507e-01 2.4543409e-01 1.2760114e-01 1.6921167e-01 2.3873595e-01 1.9385405e-01 3.0859675e-01 2.0396213e-01 2.5141439e-01 1.7197884e-01 3.1193260e-01 2.4875015e-01 1.8437187e-01 1.8189435e-01 2.3759181e-01 2.5412614e-01 2.2898904e-01 1.4232827e-01 2.0806035e-01 1.9199138e-01 1.7693745e-01 3.4002004e-01 2.5277786e-01 1.7384453e-01 2.0213849e-01 2.6767804e-01 1.7597754e-01 2.2968366e-01 2.6752309e-01 2.2134041e-01 2.0039734e-01 1.7140536e-01 2.2556075e-01 1.8258974e-01 1.9648053e-01 1.9006393e-01 1.1321036e-01 1.9554999e-01 4.3600761e-01 3.7954719e-01 3.5812457e-01 3.7278397e-01 3.9968201e-01 4.0081518e-01 3.8843945e-01 3.8096257e-01 4.1111272e-01 3.3107441e-01 2.6691137e-01 3.5682832e-01 3.3041468e-01 4.1223120e-01 4.1255773e-01 3.1903974e-01 3.3211211e-01 3.3199965e-01 4.7707633e-01 3.8217339e-01 3.3708398e-01 3.6131644e-01 4.1712805e-01 3.0571403e-01 3.2625308e-01 3.2419755e-01 2.8563873e-01 2.7883266e-01 3.9884997e-01 3.1256889e-01 3.6952768e-01 2.7953122e-01 4.0726631e-01 3.0093515e-01 3.9702583e-01 3.5566883e-01 3.5181973e-01 3.2782384e-01 2.7114516e-01 3.0000941e-01 3.5891976e-01 2.7762255e-01 3.7954719e-01 3.7024637e-01 3.5327118e-01 3.1362016e-01 3.5214869e-01 3.0546169e-01 3.2226324e-01 3.2277503e-01 1.1668032e-04 8.6044327e-05 1.4968429e-03 3.9691382e-03 6.2388252e-03 7.0588028e-04 1.9691519e-03 6.1279520e-03 1.9660913e-04 2.5761274e-03 2.5168387e-03 2.4029967e-03 9.7429318e-04 2.3122381e-03 2.3682626e-04 7.1643085e-03 1.3128642e-04 5.3939078e-03 6.2992904e-03 9.0353935e-03 1.2266741e-02 2.0706893e-03 1.5408774e-03 2.5522607e-03 3.9522692e-03 6.6899152e-03 6.3980861e-03 2.9039306e-03 1.6942568e-03 6.2388252e-03 3.9336207e-03 4.1533642e-03 6.2388252e-03 1.2180733e-03 2.1518176e-03 8.8270219e-04 3.2743785e-02 7.7572782e-05 1.3417853e-03 2.5322339e-03 6.7844678e-03 8.2761566e-04 8.6236157e-04 3.1792685e-04 2.2579028e-03 2.2976852e-01 2.2800773e-01 2.6917639e-01 3.1391346e-01 2.8619117e-01 3.0434544e-01 2.4844431e-01 2.0773635e-01 2.6148944e-01 2.5886513e-01 2.9555853e-01 2.3241008e-01 2.8723433e-01 3.0077518e-01 1.6999944e-01 2.1692490e-01 2.9290302e-01 2.4423212e-01 3.6894940e-01 2.5556289e-01 3.0695160e-01 2.1997775e-01 3.7292526e-01 3.0427758e-01 2.3385552e-01 2.3106102e-01 2.9243468e-01 3.1048744e-01 2.8298832e-01 1.8662712e-01 2.6007204e-01 2.4232174e-01 2.2560003e-01 4.0265980e-01 3.0762748e-01 2.2151447e-01 2.5355085e-01 3.2493368e-01 2.2408199e-01 2.8382455e-01 3.2448802e-01 2.7442187e-01 2.5162228e-01 2.1940897e-01 2.7915380e-01 2.3127910e-01 2.4702051e-01 2.4019206e-01 1.5301315e-01 2.4619533e-01 5.0391216e-01 4.4483392e-01 4.2228707e-01 4.3731273e-01 4.6617394e-01 4.6750253e-01 4.5367757e-01 4.4636521e-01 4.7842690e-01 3.9329580e-01 3.2434154e-01 4.2091234e-01 3.9272980e-01 4.7962551e-01 4.7998875e-01 3.8052757e-01 3.9422077e-01 3.9365636e-01 5.4778535e-01 4.4784024e-01 3.9985415e-01 4.2545240e-01 4.8476479e-01 3.6622351e-01 3.8794414e-01 3.8577592e-01 3.4462011e-01 3.3712507e-01 4.6543611e-01 3.7346604e-01 4.3442200e-01 3.3762412e-01 4.7437523e-01 3.6087712e-01 4.6258851e-01 4.1954525e-01 4.1507031e-01 3.8935328e-01 3.2880662e-01 3.6009673e-01 4.2314218e-01 3.3549029e-01 4.4483392e-01 4.3505302e-01 4.1710447e-01 3.7450914e-01 4.1581746e-01 3.6597096e-01 3.8346411e-01 3.8386195e-01 2.7739415e-04 8.2117467e-04 2.7843462e-03 4.7394226e-03 3.9365385e-04 1.1964598e-03 4.7400628e-03 2.5527396e-04 3.2634446e-03 3.7103657e-03 3.3188195e-03 8.6302611e-04 1.5635411e-03 6.0189508e-04 5.5859876e-03 3.8282951e-04 7.0925635e-03 5.0273924e-03 7.3470160e-03 1.0223636e-02 1.3503463e-03 9.3049535e-04 1.9663208e-03 2.7155903e-03 5.0798223e-03 5.5875952e-03 3.5987384e-03 2.6550151e-03 4.7394226e-03 3.5923878e-03 3.7937786e-03 4.7394226e-03 6.6480476e-04 1.3814035e-03 1.1581699e-03 3.0091048e-02 1.0888067e-04 1.1634967e-03 1.9052023e-03 5.6332034e-03 7.9034466e-04 3.5005887e-04 1.0179107e-04 1.6076683e-03 2.2018795e-01 2.1841167e-01 2.5888963e-01 3.0298911e-01 2.7568827e-01 2.9345793e-01 2.3845526e-01 1.9853879e-01 2.5133209e-01 2.4870042e-01 2.8491736e-01 2.2273608e-01 2.7678086e-01 2.8993699e-01 1.6165333e-01 2.0762176e-01 2.8220337e-01 2.3432093e-01 3.5743296e-01 2.4549712e-01 2.9602684e-01 2.1063470e-01 3.6116406e-01 2.9338620e-01 2.2421094e-01 2.2149308e-01 2.8182182e-01 2.9956540e-01 2.7243830e-01 1.7796817e-01 2.4995634e-01 2.3251210e-01 2.1609445e-01 3.9047864e-01 2.9675065e-01 2.1202908e-01 2.4353030e-01 3.1395037e-01 2.1453916e-01 2.7329907e-01 3.1330772e-01 2.6399518e-01 2.4164659e-01 2.1003834e-01 2.6865531e-01 2.2160867e-01 2.3705638e-01 2.3039039e-01 1.4523591e-01 2.3625874e-01 4.9071957e-01 4.3219633e-01 4.0993016e-01 4.2475440e-01 4.5332327e-01 4.5465382e-01 4.4096188e-01 4.3371359e-01 4.6548638e-01 3.8123224e-01 3.1318896e-01 4.0857587e-01 3.8073064e-01 4.6668253e-01 4.6707002e-01 3.6864305e-01 3.8213773e-01 3.8159377e-01 5.3428461e-01 4.3521869e-01 3.8775353e-01 4.1301893e-01 4.7176152e-01 3.5457739e-01 3.7593537e-01 3.7379344e-01 3.3323181e-01 3.2577190e-01 4.5261005e-01 3.6164142e-01 4.2194514e-01 3.2625778e-01 4.6147754e-01 3.4920516e-01 4.4979521e-01 4.0734174e-01 4.0275102e-01 3.7733353e-01 3.1756791e-01 3.4852048e-01 4.1080565e-01 3.2443308e-01 4.3219633e-01 4.2252463e-01 4.0479526e-01 3.6286403e-01 4.0364435e-01 3.5428112e-01 3.7151258e-01 3.7191203e-01 2.0478784e-03 4.7860280e-03 7.2727783e-03 1.2329906e-03 2.0550268e-03 7.3066158e-03 5.3810576e-04 3.2245377e-03 2.1674888e-03 2.7856851e-03 1.6387773e-03 3.1323423e-03 6.7307381e-05 8.3332066e-03 3.3954200e-04 4.9119026e-03 7.6276175e-03 8.9240504e-03 1.3851706e-02 2.8347122e-03 2.2069601e-03 3.5278340e-03 4.3892066e-03 7.6179982e-03 7.9398397e-03 2.0003115e-03 1.2885024e-03 7.2727783e-03 5.1809110e-03 5.4327573e-03 7.2727783e-03 1.7938257e-03 2.8924302e-03 1.4132511e-03 3.5877316e-02 5.5425651e-05 2.1070391e-03 2.2246722e-03 8.2675293e-03 4.8309816e-04 1.2152730e-03 6.6498554e-04 3.1323983e-03 2.3387083e-01 2.3171300e-01 2.7340823e-01 3.1873143e-01 2.9087099e-01 3.0765106e-01 2.5178166e-01 2.1138210e-01 2.6568600e-01 2.6244481e-01 3.0032621e-01 2.3618270e-01 2.9221666e-01 3.0443867e-01 1.7368514e-01 2.2112593e-01 2.9589691e-01 2.4771596e-01 3.7467992e-01 2.5965416e-01 3.1023215e-01 2.2429067e-01 3.7775475e-01 3.0780450e-01 2.3805322e-01 2.3537447e-01 2.9708156e-01 3.1499475e-01 2.8689460e-01 1.9071775e-01 2.6437980e-01 2.4650321e-01 2.2965596e-01 4.0666307e-01 3.1024566e-01 2.2426781e-01 2.5770992e-01 3.3024819e-01 2.2703835e-01 2.8812097e-01 3.2789845e-01 2.7792695e-01 2.5584753e-01 2.2352457e-01 2.8285984e-01 2.3411709e-01 2.5033634e-01 2.4414228e-01 1.5718330e-01 2.4987685e-01 5.0772777e-01 4.4916856e-01 4.2715006e-01 4.4114868e-01 4.7061118e-01 4.7223859e-01 4.5731921e-01 4.5076024e-01 4.8335950e-01 3.9759816e-01 3.2864932e-01 4.2581769e-01 3.9765561e-01 4.8465345e-01 4.8525127e-01 3.8513607e-01 3.9820652e-01 3.9712803e-01 5.5326906e-01 4.5284577e-01 4.0466523e-01 4.2968979e-01 4.8967945e-01 3.7122633e-01 3.9189300e-01 3.8976354e-01 3.4937792e-01 3.4115590e-01 4.7020033e-01 3.7767688e-01 4.3942138e-01 3.4125876e-01 4.7934102e-01 3.6486747e-01 4.6609349e-01 4.2514437e-01 4.1889348e-01 3.9297481e-01 3.3279384e-01 3.6502235e-01 4.2824304e-01 3.4111505e-01 4.4916856e-01 4.3953404e-01 4.2185806e-01 3.8004789e-01 4.2135185e-01 3.7064704e-01 3.8713375e-01 3.8737322e-01 5.9378937e-04 1.6263483e-03 3.1194349e-04 8.5089275e-04 1.6365846e-03 1.1579874e-03 4.9430863e-03 7.7957878e-03 5.8209267e-03 9.7423596e-04 2.1559031e-04 2.8280232e-03 2.1261057e-03 1.8496545e-03 1.2342594e-02 1.9347552e-03 5.4995961e-03 5.2624400e-03 1.3773080e-04 7.1496401e-05 7.1145768e-04 9.6706058e-04 1.9028496e-03 3.0842001e-03 7.5087003e-03 6.3709632e-03 1.6263483e-03 2.4219636e-03 2.5416684e-03 1.6263483e-03 4.5881830e-05 1.0508341e-04 2.2101780e-03 2.1711060e-02 1.4779987e-03 1.0004664e-03 2.4029906e-03 2.5527616e-03 2.4859397e-03 1.2918144e-04 4.6388898e-04 3.7292268e-04 1.9674800e-01 1.9551090e-01 2.3384591e-01 2.7581575e-01 2.4956432e-01 2.6852776e-01 2.1529223e-01 1.7652116e-01 2.2659936e-01 2.2483764e-01 2.5838801e-01 1.9958250e-01 2.5031938e-01 2.6459593e-01 1.4127677e-01 1.8459488e-01 2.5809699e-01 2.1110498e-01 3.2773890e-01 2.2109976e-01 2.7105695e-01 1.8736680e-01 3.3227725e-01 2.6813261e-01 2.0050552e-01 1.9777445e-01 2.5552383e-01 2.7284453e-01 2.4733170e-01 1.5638593e-01 2.2514733e-01 2.0849921e-01 1.9287136e-01 3.6191982e-01 2.7281863e-01 1.9071038e-01 2.1912633e-01 2.8593968e-01 1.9281596e-01 2.4768186e-01 2.8763479e-01 2.3971138e-01 2.1723753e-01 1.8699948e-01 2.4393940e-01 1.9979806e-01 2.1397418e-01 2.0672587e-01 1.2529166e-01 2.1270878e-01 4.6033946e-01 4.0222602e-01 3.7977808e-01 3.9565939e-01 4.2276626e-01 4.2367223e-01 4.1181849e-01 4.0362790e-01 4.3403229e-01 3.5248619e-01 2.8628855e-01 3.7840466e-01 3.5121985e-01 4.3508597e-01 4.3518504e-01 3.3982310e-01 3.5380487e-01 3.5403534e-01 5.0086936e-01 4.0431760e-01 3.5820087e-01 3.8360776e-01 4.4020334e-01 3.2567463e-01 3.4780712e-01 3.4566354e-01 3.0520609e-01 2.9886193e-01 4.2163480e-01 3.3351442e-01 3.9135037e-01 2.9988740e-01 4.3006423e-01 3.2170490e-01 4.2068520e-01 3.7643926e-01 3.7416586e-01 3.4964963e-01 2.9095264e-01 3.1987117e-01 3.8035231e-01 2.9582266e-01 4.0222602e-01 3.9256940e-01 3.7489846e-01 3.3318735e-01 3.7289799e-01 3.2576051e-01 3.4389968e-01 3.4452790e-01 2.6022528e-04 1.6357171e-03 1.5776794e-03 3.8821876e-04 3.3383101e-03 8.1348232e-03 1.2673676e-02 9.6454978e-03 2.5951087e-03 4.7710550e-04 5.9640558e-03 5.0935416e-04 4.5005321e-03 1.8295131e-02 8.0881241e-04 4.5548809e-03 2.4342161e-03 4.9437559e-04 7.1285200e-04 1.1827453e-03 5.3640347e-04 3.9274104e-04 2.7126384e-03 1.1795471e-02 1.0834355e-02 2.6022528e-04 3.1798475e-03 3.2407554e-03 2.6022528e-04 8.6271302e-04 3.7982619e-04 4.6816553e-03 1.6563494e-02 3.8583498e-03 2.4190920e-03 3.6876972e-03 1.5540748e-03 4.9548680e-03 1.1822578e-03 2.1020911e-03 7.8943086e-04 1.7690932e-01 1.7592254e-01 2.1244374e-01 2.5265403e-01 2.2738778e-01 2.4651370e-01 1.9514374e-01 1.5780110e-01 2.0549282e-01 2.0415245e-01 2.3585798e-01 1.7978451e-01 2.2802648e-01 2.4243736e-01 1.2428265e-01 1.6526016e-01 2.3669421e-01 1.9101658e-01 3.0265561e-01 2.0025949e-01 2.4898144e-01 1.6786898e-01 3.0733331e-01 2.4595698e-01 1.8046568e-01 1.7781045e-01 2.3314059e-01 2.4991164e-01 2.2560913e-01 1.3845901e-01 2.0404813e-01 1.8812805e-01 1.7322140e-01 3.3666075e-01 2.5129679e-01 1.7201674e-01 1.9833201e-01 2.6229128e-01 1.7386253e-01 2.2573363e-01 2.6492814e-01 2.1852944e-01 1.9648937e-01 1.6758641e-01 2.2246603e-01 1.8066071e-01 1.9389274e-01 1.8653629e-01 1.0911288e-01 1.9242842e-01 4.3299781e-01 3.7574545e-01 3.5353088e-01 3.6969868e-01 3.9574789e-01 3.9644649e-01 3.8564737e-01 3.7707427e-01 4.0646475e-01 3.2727058e-01 2.6301141e-01 3.5217112e-01 3.2569733e-01 4.0744443e-01 4.0742674e-01 3.1477415e-01 3.2876954e-01 3.2939944e-01 4.7166141e-01 3.7739415e-01 3.3254323e-01 3.5763917e-01 4.1251084e-01 3.0085067e-01 3.2295735e-01 3.2084322e-01 2.8110727e-01 2.7535557e-01 3.9443856e-01 3.0887601e-01 3.6474538e-01 2.7663010e-01 4.0256676e-01 2.9754793e-01 3.9443683e-01 3.4998590e-01 3.4873324e-01 3.2500314e-01 2.6771990e-01 2.9525187e-01 3.5397733e-01 2.7178914e-01 3.7574545e-01 3.6622316e-01 3.4883278e-01 3.0797294e-01 3.4655783e-01 3.0107914e-01 3.1936679e-01 3.2010756e-01 3.0868881e-03 2.8691382e-03 1.3643967e-04 5.3429196e-03 1.0581034e-02 1.6459895e-02 1.2551534e-02 4.1576220e-03 1.2160579e-03 8.7064401e-03 5.4418849e-05 6.8214146e-03 2.2732626e-02 5.6586090e-04 4.9831593e-03 1.1314391e-03 1.3090644e-03 1.7262411e-03 1.9770194e-03 1.0389613e-03 9.3641634e-05 2.8067647e-03 1.5471006e-02 1.4411876e-02 0.0000000e+00 4.0251529e-03 4.0402030e-03 0.0000000e+00 2.0104773e-03 1.1579294e-03 6.7733512e-03 1.3328703e-02 6.1195429e-03 3.8280621e-03 5.4471697e-03 1.3203495e-03 7.3930866e-03 2.5511055e-03 3.8011014e-03 1.5935161e-03 1.6488937e-01 1.6420208e-01 1.9946134e-01 2.3841307e-01 2.1377841e-01 2.3352484e-01 1.8323739e-01 1.4660873e-01 1.9269692e-01 1.9183992e-01 2.2200730e-01 1.6791595e-01 2.1423078e-01 2.2922867e-01 1.1407468e-01 1.5349471e-01 2.2418179e-01 1.7908948e-01 2.8692621e-01 1.8765985e-01 2.3596576e-01 1.5596498e-01 2.9203641e-01 2.3278981e-01 1.6829150e-01 1.6563525e-01 2.1942293e-01 2.3592536e-01 2.1256421e-01 1.2755291e-01 1.9121342e-01 1.7576718e-01 1.6132929e-01 3.2148865e-01 2.3885357e-01 1.6118125e-01 1.8573297e-01 2.4757051e-01 1.6279862e-01 2.1240660e-01 2.5149161e-01 2.0595435e-01 1.8389163e-01 1.5580881e-01 2.0964365e-01 1.6953436e-01 1.8203376e-01 1.7437090e-01 9.9184065e-02 1.8031354e-01 4.1664204e-01 3.5971944e-01 3.3744612e-01 3.5416868e-01 3.7936058e-01 3.7982315e-01 3.7006184e-01 3.6098196e-01 3.8956200e-01 3.1201251e-01 2.4889912e-01 3.3607844e-01 3.1002022e-01 3.9046127e-01 3.9028467e-01 2.9949936e-01 3.1373736e-01 3.1479561e-01 4.5355800e-01 3.6085089e-01 3.1682959e-01 3.4195608e-01 3.9553949e-01 2.8555816e-01 3.0804941e-01 3.0593834e-01 2.6633772e-01 2.6121338e-01 3.7782244e-01 2.9399549e-01 3.4839508e-01 2.6278429e-01 3.8569374e-01 2.8303600e-01 3.7885421e-01 3.3349568e-01 3.3352424e-01 3.1033775e-01 2.5375578e-01 2.8011018e-01 3.3772574e-01 2.5671985e-01 3.5971944e-01 3.5022311e-01 3.3289784e-01 2.9224130e-01 3.3016010e-01 2.8599652e-01 3.0475125e-01 3.0561759e-01 1.6232219e-03 2.8110674e-03 3.0992704e-04 2.8009412e-03 5.3859157e-03 3.4428307e-03 2.2389965e-04 4.8865483e-04 1.7600776e-03 3.6417064e-03 7.4576509e-04 9.1296419e-03 2.8123816e-03 8.0068765e-03 7.3379880e-03 3.9579356e-04 1.9713653e-04 6.0194434e-04 2.3367622e-03 3.6239908e-03 3.0185118e-03 6.3202257e-03 4.4046298e-03 3.0868881e-03 1.7141363e-03 1.8461990e-03 3.0868881e-03 1.2729358e-04 4.6571753e-04 8.6393185e-04 2.3903803e-02 9.0441478e-04 3.0528309e-04 3.1648190e-03 3.1223857e-03 2.2339929e-03 2.7724170e-04 9.5102356e-05 4.3913729e-04 2.1061066e-01 2.0964712e-01 2.4888926e-01 2.9163776e-01 2.6471732e-01 2.8522189e-01 2.3035873e-01 1.8998369e-01 2.4143327e-01 2.4006731e-01 2.7373417e-01 2.1381600e-01 2.6519773e-01 2.8097864e-01 1.5319882e-01 1.9790190e-01 2.7464921e-01 2.2594124e-01 3.4406181e-01 2.3583526e-01 2.8783351e-01 2.0067586e-01 3.4959337e-01 2.8469567e-01 2.1442337e-01 2.1148410e-01 2.7089383e-01 2.8885413e-01 2.6304757e-01 1.6861411e-01 2.3983808e-01 2.2272157e-01 2.0662897e-01 3.8050402e-01 2.8992390e-01 2.0524163e-01 2.3373909e-01 3.0156183e-01 2.0732304e-01 2.6311208e-01 3.0478863e-01 2.5545595e-01 2.3172924e-01 2.0047959e-01 2.5968741e-01 2.1460680e-01 2.2900957e-01 2.2107714e-01 1.3590375e-01 2.2746759e-01 4.8087096e-01 4.2142796e-01 3.9814594e-01 4.1502871e-01 4.4228995e-01 4.4300705e-01 4.3159396e-01 4.2281768e-01 4.5341178e-01 3.7067256e-01 3.0283474e-01 3.9670954e-01 3.6890449e-01 4.5441105e-01 4.5432159e-01 3.5749751e-01 3.7222314e-01 3.7273757e-01 5.2092654e-01 4.2307513e-01 3.7613897e-01 4.0250144e-01 4.5970761e-01 3.4267709e-01 3.6611458e-01 3.6389952e-01 3.2189682e-01 3.1593975e-01 4.4091119e-01 3.5132753e-01 4.0985044e-01 3.1723537e-01 4.4934566e-01 3.3938050e-01 4.4068685e-01 3.9407776e-01 3.9311145e-01 3.6818097e-01 3.0785214e-01 3.3679573e-01 3.9853670e-01 3.1138703e-01 4.2142796e-01 4.1148317e-01 3.9324794e-01 3.4985868e-01 3.9052142e-01 3.4304315e-01 3.6227810e-01 3.6300235e-01 3.5297445e-03 2.3993465e-03 8.1469449e-03 8.4116551e-03 8.4748907e-03 3.0443320e-03 1.8587915e-03 2.8140158e-03 3.7033592e-03 2.9317197e-03 1.3265454e-02 4.5015236e-03 2.6265400e-03 7.5415562e-03 1.6353241e-03 1.4046892e-03 3.1172532e-03 6.0159720e-04 2.6265400e-03 7.0517547e-03 5.5270478e-03 6.4518235e-03 2.8691382e-03 6.1014438e-03 6.3013427e-03 2.8691382e-03 1.1615614e-03 1.4498289e-03 4.4069463e-03 2.8268404e-02 1.4610903e-03 3.3082950e-03 4.5136771e-04 5.8170191e-03 1.2876475e-03 5.5964987e-04 1.3152056e-03 2.3446691e-03 1.9624436e-01 1.9365486e-01 2.3272539e-01 2.7570910e-01 2.4962218e-01 2.6341222e-01 2.1161968e-01 1.7505868e-01 2.2555325e-01 2.2171510e-01 2.5853430e-01 1.9783603e-01 2.5146360e-01 2.6075203e-01 1.4121466e-01 1.8483453e-01 2.5221719e-01 2.0803875e-01 3.2980663e-01 2.1983733e-01 2.6580206e-01 1.8792174e-01 3.3096405e-01 2.6375229e-01 2.0022607e-01 1.9799659e-01 2.5530781e-01 2.7170116e-01 2.4472945e-01 1.5721426e-01 2.2453551e-01 2.0791989e-01 1.9232403e-01 3.5721533e-01 2.6541719e-01 1.8583170e-01 2.1815822e-01 2.8740780e-01 1.8853156e-01 2.4642239e-01 2.8243457e-01 2.3594931e-01 2.1655773e-01 1.8685267e-01 2.4074340e-01 1.9492750e-01 2.1026662e-01 2.0538411e-01 1.2769778e-01 2.1026662e-01 4.5350142e-01 3.9795187e-01 3.7769065e-01 3.8983341e-01 4.1851849e-01 4.2042793e-01 4.0510768e-01 3.9953508e-01 4.3130939e-01 3.4895812e-01 2.8413412e-01 3.7648942e-01 3.4987508e-01 4.3267862e-01 4.3359924e-01 3.3758650e-01 3.4918773e-01 3.4772733e-01 4.9915788e-01 4.0231358e-01 3.5632097e-01 3.7931174e-01 4.3732697e-01 3.2511301e-01 3.4317696e-01 3.4120231e-01 3.0420772e-01 2.9548175e-01 4.1851849e-01 3.3003548e-01 3.8954108e-01 2.9516106e-01 4.2751620e-01 3.1771485e-01 4.1340131e-01 3.7704473e-01 3.6865281e-01 3.4390717e-01 2.8759676e-01 3.1915503e-01 3.7909158e-01 2.9821954e-01 3.9795187e-01 3.8894782e-01 3.7251565e-01 3.3442155e-01 3.7333196e-01 3.2403985e-01 3.3841983e-01 3.3852014e-01 4.9713816e-03 9.2903476e-03 1.5944722e-02 1.1386125e-02 3.5402300e-03 9.6201776e-04 8.6911918e-03 9.4953207e-05 6.4447745e-03 2.1940505e-02 1.4660203e-04 6.6774582e-03 1.0681613e-03 1.0987220e-03 1.5397922e-03 1.3925202e-03 1.6744918e-03 4.5493239e-04 1.7274513e-03 1.6063124e-02 1.4167352e-02 1.3643967e-04 2.8974888e-03 2.8893579e-03 1.3643967e-04 1.8844794e-03 1.0195101e-03 5.9835494e-03 1.1907169e-02 6.2144210e-03 3.1461009e-03 6.4603159e-03 6.0804116e-04 7.9398115e-03 2.6608779e-03 3.6611489e-03 1.1878605e-03 1.6827914e-01 1.6808878e-01 2.0330224e-01 2.4208927e-01 2.1725982e-01 2.3901101e-01 1.8791090e-01 1.5022413e-01 1.9646923e-01 1.9636982e-01 2.2550082e-01 1.7178784e-01 2.1730098e-01 2.3423675e-01 1.1690649e-01 1.5652486e-01 2.2988556e-01 1.8351752e-01 2.8999988e-01 1.9148148e-01 2.4151451e-01 1.5889324e-01 2.9641885e-01 2.3800995e-01 1.7162027e-01 1.6875690e-01 2.2303923e-01 2.3997805e-01 2.1702847e-01 1.3016155e-01 1.9481438e-01 1.7925806e-01 1.6471086e-01 3.2723835e-01 2.4516700e-01 1.6613136e-01 1.8943302e-01 2.5069233e-01 1.6755119e-01 2.1637456e-01 2.5710224e-01 2.1080083e-01 1.8747239e-01 1.5900127e-01 2.1430731e-01 1.7454101e-01 1.8671199e-01 1.7813660e-01 1.0093430e-01 1.8452279e-01 4.2348788e-01 3.6545764e-01 3.4229982e-01 3.6044592e-01 3.8515670e-01 3.8525367e-01 3.7671058e-01 3.6665866e-01 3.9483186e-01 3.1729700e-01 2.5339335e-01 3.4086300e-01 3.1448994e-01 3.9561710e-01 3.9513385e-01 3.0425707e-01 3.1942407e-01 3.2109044e-01 4.5863634e-01 3.6575820e-01 3.2152631e-01 3.4763745e-01 4.0088503e-01 2.8963041e-01 3.1371721e-01 3.1153634e-01 2.7048666e-01 2.6621754e-01 3.8319922e-01 2.9918600e-01 3.5318564e-01 2.6828212e-01 3.9088644e-01 2.8836369e-01 3.8573578e-01 3.3732047e-01 3.3961180e-01 3.1641339e-01 2.5871452e-01 2.8421639e-01 3.4227214e-01 2.5952711e-01 3.6545764e-01 3.5568934e-01 3.3784386e-01 2.9565951e-01 3.3403769e-01 2.9050448e-01 3.1070970e-01 3.1176741e-01 1.7225353e-03 3.1252650e-03 1.9141697e-03 3.0572974e-04 1.5621195e-03 7.7657730e-04 6.0730841e-03 9.6969946e-05 6.0804497e-03 4.8728559e-03 1.0019276e-02 1.0630759e-02 1.4028596e-03 1.0008907e-03 1.5106647e-03 3.9425625e-03 5.9922357e-03 4.5089760e-03 4.5296071e-03 2.4544132e-03 5.3429196e-03 2.3927105e-03 2.5658780e-03 5.3429196e-03 8.0759380e-04 1.5345623e-03 3.2653860e-04 2.8784931e-02 4.6959359e-04 5.2961514e-04 3.5529133e-03 5.0787251e-03 1.7528094e-03 7.9750642e-04 1.8469304e-04 1.3949343e-03 2.2601194e-01 2.2489065e-01 2.6538416e-01 3.0933559e-01 2.8173337e-01 3.0217927e-01 2.4601138e-01 2.0461695e-01 2.5772236e-01 2.5608721e-01 2.9099324e-01 2.2920421e-01 2.8227951e-01 2.9802519e-01 1.6660589e-01 2.1294215e-01 2.9118999e-01 2.4154604e-01 3.6304829e-01 2.5194222e-01 3.0483437e-01 2.1582549e-01 3.6852765e-01 3.0175865e-01 2.2996178e-01 2.2696306e-01 2.8805620e-01 3.0640689e-01 2.7978083e-01 1.8266242e-01 2.5611673e-01 2.3849427e-01 2.2189938e-01 3.9968280e-01 3.0655638e-01 2.1989254e-01 2.4981061e-01 3.1957344e-01 2.2214967e-01 2.7998655e-01 3.2222399e-01 2.7182647e-01 2.4776514e-01 2.1557967e-01 2.7625427e-01 2.2956697e-01 2.4461597e-01 2.3673300e-01 1.4870158e-01 2.4319918e-01 5.0146439e-01 4.4143183e-01 4.1797463e-01 4.3468983e-01 4.6265612e-01 4.6350594e-01 4.5140079e-01 4.4286970e-01 4.7413628e-01 3.8981309e-01 3.2063561e-01 4.1652733e-01 3.8823357e-01 4.7518267e-01 4.7516433e-01 3.7651294e-01 3.9124904e-01 3.9150135e-01 5.4273573e-01 4.4336023e-01 3.9556546e-01 4.2215915e-01 4.8051706e-01 3.6152094e-01 3.8501414e-01 3.8277781e-01 3.4024930e-01 3.3391004e-01 4.6138930e-01 3.7007400e-01 4.2991865e-01 3.3504580e-01 4.7002175e-01 3.5780202e-01 4.6054739e-01 4.1401655e-01 4.1241306e-01 3.8694896e-01 3.2563422e-01 3.5550143e-01 4.1844379e-01 3.2964964e-01 4.4143183e-01 4.3139176e-01 4.1295631e-01 3.6894646e-01 4.1038562e-01 3.6180237e-01 3.8096707e-01 3.8161756e-01 2.9059655e-03 2.3706161e-04 1.5622923e-03 4.6985391e-03 3.0899699e-03 1.1144685e-02 1.5452086e-03 4.3912180e-03 8.2378168e-03 1.9894938e-02 1.6022015e-02 4.6248887e-03 4.1434850e-03 3.4955495e-03 1.0239539e-02 1.2012056e-02 5.3911313e-03 8.1025404e-03 3.3141536e-03 1.0581034e-02 2.5128050e-03 2.6447621e-03 1.0581034e-02 4.0444636e-03 5.0265914e-03 5.7591609e-04 3.1111838e-02 3.5439088e-03 1.6935296e-03 1.0096079e-02 7.4536930e-03 6.1909555e-03 4.6446420e-03 2.9301624e-03 3.9714148e-03 2.5068010e-01 2.5098525e-01 2.9216380e-01 3.3638336e-01 3.0774280e-01 3.3430586e-01 2.7479523e-01 2.2946729e-01 2.8415608e-01 2.8467354e-01 3.1719659e-01 2.5534962e-01 3.0706036e-01 3.2874800e-01 1.8820706e-01 2.3625921e-01 3.2370915e-01 2.6954509e-01 3.8903955e-01 2.7840834e-01 3.3718014e-01 2.3890051e-01 3.9852630e-01 3.3314087e-01 2.5453269e-01 2.5085481e-01 3.1457631e-01 3.3452242e-01 3.0863300e-01 2.0400912e-01 2.8201538e-01 2.6372052e-01 2.4645516e-01 4.3401653e-01 3.4099078e-01 2.4885351e-01 2.7587880e-01 3.4510687e-01 2.5062404e-01 3.0740449e-01 3.5503881e-01 3.0161400e-01 2.7344211e-01 2.3943815e-01 3.0560987e-01 2.5890901e-01 2.7338361e-01 2.6272911e-01 1.6653571e-01 2.7061027e-01 5.3996294e-01 4.7622847e-01 4.4996413e-01 4.7092027e-01 4.9784258e-01 4.9765553e-01 4.8884384e-01 4.7750758e-01 5.0792579e-01 4.2270376e-01 3.5026703e-01 4.4829833e-01 4.1874266e-01 5.0865069e-01 5.0773433e-01 4.0771387e-01 4.2529697e-01 4.2723724e-01 5.7654330e-01 4.7578493e-01 4.2683086e-01 4.5657562e-01 5.1458642e-01 3.9050926e-01 4.1892650e-01 4.1646419e-01 3.6916765e-01 3.6521270e-01 4.9536279e-01 4.0243409e-01 4.6185742e-01 3.6775616e-01 5.0354755e-01 3.9037876e-01 4.9872590e-01 4.4290716e-01 4.4784995e-01 4.2202156e-01 3.5667822e-01 3.8450868e-01 4.4953729e-01 3.5436611e-01 4.7622847e-01 4.6530251e-01 4.4515647e-01 3.9606646e-01 4.3939461e-01 3.9207838e-01 4.1563418e-01 4.1682072e-01 1.5609953e-03 4.8490070e-03 9.0958370e-03 1.4989091e-03 1.7813868e-02 2.1261488e-03 5.5450301e-04 1.5694148e-02 1.9384410e-02 2.5209737e-02 8.6954304e-03 7.6213095e-03 8.7105486e-03 1.2654300e-02 1.7334342e-02 1.3883194e-02 2.2522789e-03 1.7443565e-04 1.6459895e-02 9.1718824e-03 9.4916987e-03 1.6459895e-02 6.9918464e-03 8.9833757e-03 2.9662983e-03 4.9266036e-02 2.9055422e-03 5.5731976e-03 8.0889759e-03 1.5739049e-02 3.7597322e-03 6.3200695e-03 4.4644236e-03 8.6395939e-03 2.7692079e-01 2.7499135e-01 3.1941212e-01 3.6719225e-01 3.3760508e-01 3.5656667e-01 2.9687968e-01 2.5298236e-01 3.1115442e-01 3.0819394e-01 3.4760947e-01 2.7976620e-01 3.3861131e-01 3.5300749e-01 2.1161836e-01 2.6294922e-01 3.4413759e-01 2.9242527e-01 4.2523864e-01 3.0477646e-01 3.5931443e-01 2.6623770e-01 4.2973462e-01 3.5665121e-01 2.8133678e-01 2.7828246e-01 3.4429599e-01 3.6357656e-01 3.3414792e-01 2.2982660e-01 3.0962503e-01 2.9049749e-01 2.7240490e-01 4.6073277e-01 3.5937207e-01 2.6744708e-01 3.0261187e-01 3.7874332e-01 2.7038484e-01 3.3511133e-01 3.7800754e-01 3.2481692e-01 3.0053112e-01 2.6567213e-01 3.2997477e-01 2.7805229e-01 2.9533686e-01 2.8819780e-01 1.9246360e-01 2.9461561e-01 5.6604002e-01 5.0500114e-01 4.8160322e-01 4.9684759e-01 5.2728223e-01 5.2878056e-01 5.1374073e-01 5.0662675e-01 5.4019822e-01 4.5105935e-01 3.7828674e-01 4.8016813e-01 4.5059090e-01 5.4146236e-01 5.4186046e-01 4.3772456e-01 4.5187440e-01 4.5090747e-01 6.1216296e-01 5.0833718e-01 4.5807252e-01 4.8471571e-01 5.4678369e-01 4.2264992e-01 4.4526564e-01 4.4301133e-01 3.9982165e-01 3.9174986e-01 5.2663733e-01 4.3017652e-01 4.9431552e-01 3.9206379e-01 5.3598953e-01 4.1681568e-01 5.2288475e-01 4.7864082e-01 4.7360696e-01 4.4651927e-01 3.8292357e-01 4.1618542e-01 4.8251093e-01 3.8978460e-01 5.0500114e-01 4.9485605e-01 4.7615846e-01 4.3123359e-01 4.7475023e-01 4.2239197e-01 4.4037545e-01 4.4066833e-01 2.2696323e-03 5.9674345e-03 2.4448133e-03 1.3335241e-02 1.4550127e-03 2.5899751e-03 1.0462849e-02 2.0483763e-02 1.9016265e-02 5.8048658e-03 5.1341121e-03 4.8749246e-03 1.1285550e-02 1.3907377e-02 7.6337585e-03 6.3180508e-03 2.0267734e-03 1.2551534e-02 4.1078635e-03 4.2919330e-03 1.2551534e-02 4.8854397e-03 6.2043549e-03 8.9134425e-04 3.6466805e-02 3.2782414e-03 2.5696799e-03 9.8307089e-03 9.8120264e-03 5.5450409e-03 5.1728098e-03 3.2838118e-03 5.2555481e-03 2.6123905e-01 2.6103645e-01 3.0329747e-01 3.4864780e-01 3.1958423e-01 3.4458162e-01 2.8459400e-01 2.3921225e-01 2.9516933e-01 2.9488851e-01 3.2923215e-01 2.6553322e-01 3.1926739e-01 3.3946038e-01 1.9751618e-01 2.4678743e-01 3.3347141e-01 2.7948950e-01 4.0283567e-01 2.8923185e-01 3.4744486e-01 2.4959732e-01 4.1128993e-01 3.4370645e-01 2.6525258e-01 2.6168140e-01 3.2643822e-01 3.4638099e-01 3.1949478e-01 2.1402441e-01 2.9314941e-01 2.7451414e-01 2.5691069e-01 4.4594923e-01 3.5036767e-01 2.5760360e-01 2.8676453e-01 3.5805235e-01 2.5967094e-01 3.1875975e-01 3.6562012e-01 3.1188296e-01 2.8438818e-01 2.4989387e-01 3.1618152e-01 2.6787548e-01 2.8314006e-01 2.7321717e-01 1.7615044e-01 2.8082637e-01 5.5224352e-01 4.8885819e-01 4.6311762e-01 4.8285549e-01 5.1073035e-01 5.1093091e-01 5.0061869e-01 4.9022404e-01 5.2151073e-01 4.3495694e-01 3.6199911e-01 4.6149506e-01 4.3176986e-01 5.2236122e-01 5.2173621e-01 4.2026138e-01 4.3714978e-01 4.3841019e-01 5.9117531e-01 4.8927834e-01 4.3976762e-01 4.6895974e-01 5.2818477e-01 4.0343191e-01 4.3068816e-01 4.2826096e-01 3.8162190e-01 3.7670056e-01 5.0866155e-01 4.1442940e-01 4.7525840e-01 3.7873655e-01 5.1715063e-01 4.0199874e-01 5.1036877e-01 4.5693051e-01 4.5962906e-01 4.3336423e-01 3.6804311e-01 3.9729031e-01 4.6298867e-01 3.6775880e-01 4.8885819e-01 4.7805886e-01 4.5813974e-01 4.0968699e-01 4.5331588e-01 4.0460089e-01 4.2699969e-01 4.2797954e-01 8.7894099e-04 2.0541035e-03 4.6305984e-03 6.7282118e-04 8.1166178e-03 3.1872717e-03 1.0880321e-02 8.3605717e-03 8.2577841e-04 6.1811314e-04 5.6936180e-04 3.8806955e-03 4.9821714e-03 2.5043588e-03 7.1844876e-03 4.2468498e-03 4.1576220e-03 9.9353221e-04 1.1055786e-03 4.1576220e-03 5.9733473e-04 9.9247040e-04 3.2081104e-04 2.3598005e-02 1.4307976e-03 3.0934240e-05 4.9322953e-03 3.1299098e-03 3.2877683e-03 9.9769768e-04 4.3968696e-04 6.2770216e-04 2.1786575e-01 2.1746374e-01 2.5686278e-01 2.9961632e-01 2.7235218e-01 2.9521657e-01 2.3917491e-01 1.9737534e-01 2.4929109e-01 2.4877587e-01 2.8142376e-01 2.2163964e-01 2.7235613e-01 2.9042411e-01 1.5945203e-01 2.0466964e-01 2.8483074e-01 2.3445929e-01 3.5153649e-01 2.4372083e-01 2.9790924e-01 2.0734139e-01 3.5860995e-01 2.9439415e-01 2.2162942e-01 2.1843466e-01 2.7871280e-01 2.9725443e-01 2.7179832e-01 1.7471289e-01 2.4749127e-01 2.3015922e-01 2.1385216e-01 3.9117409e-01 3.0083879e-01 2.1421404e-01 2.4147478e-01 3.0893498e-01 2.1609222e-01 2.7129944e-01 3.1500957e-01 2.6459749e-01 2.3931769e-01 2.0744985e-01 2.6864595e-01 2.2369874e-01 2.3782351e-01 2.2882042e-01 1.4076875e-01 2.3574843e-01 4.9305396e-01 4.3221625e-01 4.0786305e-01 4.2639713e-01 4.5320351e-01 4.5351054e-01 4.4342223e-01 4.3354113e-01 4.6376094e-01 3.8078797e-01 3.1179824e-01 4.0634323e-01 3.7808795e-01 4.6463298e-01 4.6419251e-01 3.6697079e-01 3.8279432e-01 3.8398235e-01 5.3121485e-01 4.3292773e-01 3.8560639e-01 4.1316779e-01 4.7015919e-01 3.5131205e-01 3.7664303e-01 3.7434225e-01 3.3054253e-01 3.2553357e-01 4.5134808e-01 3.6126826e-01 4.1953095e-01 3.2738535e-01 4.5959627e-01 3.4943014e-01 4.5279702e-01 4.0259529e-01 4.0419917e-01 3.7916847e-01 3.1736132e-01 3.4544845e-01 4.0790313e-01 3.1842804e-01 4.3221625e-01 4.2193584e-01 4.0305492e-01 3.5775833e-01 3.9908964e-01 3.5217975e-01 3.7311479e-01 3.7405234e-01 4.0128787e-03 1.5082918e-03 2.4327589e-03 1.3749582e-02 9.8644164e-04 7.0275865e-03 4.0509182e-03 9.2137987e-06 8.1954627e-05 2.0221322e-04 1.4919720e-03 1.6918938e-03 1.6810350e-03 9.8366461e-03 7.8161988e-03 1.2160579e-03 1.4072237e-03 1.4774681e-03 1.2160579e-03 1.9402564e-04 2.6249834e-05 2.2527118e-03 1.8043780e-02 2.4914194e-03 7.5228825e-04 4.0311549e-03 1.3209671e-03 4.0483306e-03 6.3837247e-04 9.1866746e-04 4.5668021e-05 1.9279238e-01 1.9221899e-01 2.2979083e-01 2.7088361e-01 2.4479658e-01 2.6610561e-01 2.1267629e-01 1.7326091e-01 2.2258210e-01 2.2184784e-01 2.5349552e-01 1.9619155e-01 2.4503806e-01 2.6157291e-01 1.3780150e-01 1.8042756e-01 2.5616217e-01 2.0823320e-01 3.2136818e-01 2.1724300e-01 2.6868196e-01 1.8301959e-01 3.2745065e-01 2.6534429e-01 1.9640162e-01 1.9346456e-01 2.5082861e-01 2.6843057e-01 2.4386055e-01 1.5229091e-01 2.2093793e-01 2.0444992e-01 1.8898039e-01 3.5852616e-01 2.7153123e-01 1.8897970e-01 2.1514921e-01 2.8018592e-01 1.9075855e-01 2.4355737e-01 2.8508289e-01 2.3688721e-01 2.1314274e-01 1.8298617e-01 2.4079289e-01 1.9795777e-01 2.1138990e-01 2.0306053e-01 1.2090533e-01 2.0951271e-01 4.5737829e-01 3.9834085e-01 3.7497739e-01 3.9259152e-01 4.1873643e-01 4.1914498e-01 4.0909121e-01 3.9964410e-01 4.2918834e-01 3.4857995e-01 2.8224226e-01 3.7353062e-01 3.4626594e-01 4.3008323e-01 4.2978752e-01 3.3538250e-01 3.5042715e-01 3.5150644e-01 4.9516533e-01 3.9931312e-01 3.5345241e-01 3.7985840e-01 4.3539662e-01 3.2054198e-01 3.4448056e-01 3.4226906e-01 3.0044482e-01 2.9530625e-01 4.1705793e-01 3.2972732e-01 3.8633770e-01 2.9699130e-01 4.2515986e-01 3.1826259e-01 4.1819279e-01 3.7038673e-01 3.7108888e-01 3.4686702e-01 2.8745249e-01 3.1485734e-01 3.7515178e-01 2.8956004e-01 3.9834085e-01 3.8842721e-01 3.7027395e-01 3.2715736e-01 3.6694987e-01 3.2117964e-01 3.4102816e-01 3.4191835e-01 9.8460504e-03 4.2097646e-04 3.8720695e-03 8.9609139e-03 1.0271114e-02 1.5759765e-02 3.6853519e-03 2.9640455e-03 4.3261623e-03 5.5313131e-03 9.1074119e-03 8.9974672e-03 1.5687499e-03 7.6879483e-04 8.7064401e-03 5.8625582e-03 6.1329529e-03 8.7064401e-03 2.4949105e-03 3.7729184e-03 1.5387455e-03 3.8489345e-02 2.4427633e-04 2.5870999e-03 2.8098846e-03 9.5472550e-03 6.5811256e-04 1.8465019e-03 1.0925425e-03 3.9557876e-03 2.4136396e-01 2.3914246e-01 2.8140056e-01 3.2726072e-01 2.9909180e-01 3.1587284e-01 2.5940651e-01 2.1853199e-01 2.7358477e-01 2.7023320e-01 3.0865618e-01 2.4367721e-01 3.0046030e-01 3.1269475e-01 1.8026794e-01 2.2845050e-01 3.0393397e-01 2.5531598e-01 3.8377418e-01 2.6747174e-01 3.1847415e-01 2.3166294e-01 3.8684625e-01 3.1607055e-01 2.4560721e-01 2.4289838e-01 3.0537010e-01 3.2346477e-01 2.9500292e-01 1.9758720e-01 2.7227129e-01 2.5416529e-01 2.3708995e-01 4.1588028e-01 3.1833018e-01 2.3144395e-01 2.6550973e-01 3.3890880e-01 2.3429142e-01 2.9628566e-01 3.3633600e-01 2.8587728e-01 2.6362949e-01 2.3087874e-01 2.9089607e-01 2.4143368e-01 2.5794041e-01 2.5175590e-01 1.6347149e-01 2.5753099e-01 5.1758017e-01 4.5875138e-01 4.3664497e-01 4.5058511e-01 4.8035455e-01 4.8203651e-01 4.6682330e-01 4.6036369e-01 4.9325486e-01 4.0679312e-01 3.3723664e-01 4.3530687e-01 4.0692383e-01 4.9456817e-01 4.9519341e-01 3.9426880e-01 4.0735509e-01 4.0616607e-01 5.6363656e-01 4.6254311e-01 4.1397979e-01 4.3911880e-01 4.9961302e-01 3.8027310e-01 4.0098514e-01 3.9884545e-01 3.5820683e-01 3.4982569e-01 4.7998848e-01 3.8669536e-01 4.4902142e-01 3.4986296e-01 4.8921417e-01 3.7374272e-01 4.7562308e-01 4.3467328e-01 4.2816870e-01 4.0201263e-01 3.4137888e-01 3.7400811e-01 4.3776854e-01 3.4988231e-01 4.5875138e-01 4.4907175e-01 4.3130086e-01 3.8919296e-01 4.3084858e-01 3.7966236e-01 3.9613519e-01 3.9634370e-01 7.6697767e-03 2.4232895e-02 4.2497383e-04 5.8645021e-03 7.1697323e-04 1.6459430e-03 2.1472725e-03 2.1701877e-03 1.5644328e-03 2.1493500e-04 2.5540450e-03 1.7185148e-02 1.5785034e-02 5.4418849e-05 4.0402433e-03 4.0294443e-03 5.4418849e-05 2.5045043e-03 1.5070390e-03 7.3845654e-03 1.1685406e-02 7.1165327e-03 4.2192668e-03 6.5870297e-03 1.0764642e-03 8.6213220e-03 3.2147266e-03 4.4993834e-03 1.8554035e-03 1.6163874e-01 1.6124582e-01 1.9600517e-01 2.3441471e-01 2.0995191e-01 2.3066019e-01 1.8049424e-01 1.4375647e-01 1.8928742e-01 1.8888935e-01 2.1809263e-01 1.6489764e-01 2.1018407e-01 2.2610729e-01 1.1131536e-01 1.5021138e-01 2.2157821e-01 1.7624974e-01 2.8213828e-01 1.8434338e-01 2.3311339e-01 1.5259174e-01 2.8788764e-01 2.2976085e-01 1.6495975e-01 1.6222817e-01 2.1560367e-01 2.3216078e-01 2.0930930e-01 1.2444580e-01 1.8772709e-01 1.7242257e-01 1.5812464e-01 3.1788081e-01 2.3649618e-01 1.5894784e-01 1.8237277e-01 2.4318751e-01 1.6040650e-01 2.0886424e-01 2.4850015e-01 2.0301750e-01 1.8048879e-01 1.5257957e-01 2.0654604e-01 1.6721007e-01 1.7931046e-01 1.7120054e-01 9.6139593e-02 1.7732284e-01 4.1297254e-01 3.5577891e-01 3.3316436e-01 3.5061301e-01 3.7530173e-01 3.7554177e-01 3.6661833e-01 3.5699377e-01 3.8511507e-01 3.0820403e-01 2.4524565e-01 3.3176869e-01 3.0575678e-01 3.8594227e-01 3.8559393e-01 2.9549451e-01 3.1016061e-01 3.1160241e-01 4.4857854e-01 3.5641190e-01 3.1263400e-01 3.3812708e-01 3.9109335e-01 2.8129908e-01 3.0451362e-01 3.0237858e-01 2.6230725e-01 2.5773246e-01 3.7352449e-01 2.9029824e-01 3.4398832e-01 2.5959514e-01 3.8123049e-01 2.7952979e-01 3.7549545e-01 3.2868655e-01 3.3002382e-01 3.0704202e-01 2.5032682e-01 2.7592132e-01 3.3326893e-01 2.5208920e-01 3.5577891e-01 3.4619466e-01 3.2870702e-01 2.8757710e-01 3.2540565e-01 2.8197541e-01 3.0143248e-01 3.0241595e-01 4.6779054e-03 6.3405358e-03 1.1072067e-02 1.2740784e-02 2.2273681e-03 1.7042107e-03 2.3469652e-03 4.9562680e-03 7.4940361e-03 5.7695726e-03 3.5981535e-03 1.5844867e-03 6.8214146e-03 3.1957366e-03 3.3967393e-03 6.8214146e-03 1.4289215e-03 2.3814252e-03 3.6906895e-04 3.2052685e-02 4.0942979e-04 9.9039775e-04 3.7975123e-03 6.5400285e-03 1.5831617e-03 1.2837357e-03 4.6903663e-04 2.2256509e-03 2.3440889e-01 2.3310632e-01 2.7431935e-01 3.1898347e-01 2.9103053e-01 3.1107217e-01 2.5431417e-01 2.1253549e-01 2.6655333e-01 2.6462531e-01 3.0042601e-01 2.3750489e-01 2.9168949e-01 3.0705757e-01 1.7397041e-01 2.2119992e-01 2.9980584e-01 2.4986709e-01 3.7353610e-01 2.6066067e-01 3.1374027e-01 2.2416418e-01 3.7874518e-01 3.1076095e-01 2.3844790e-01 2.3545346e-01 2.9741154e-01 3.1590317e-01 2.8873621e-01 1.9043311e-01 2.6497335e-01 2.4708373e-01 2.3022342e-01 4.0978464e-01 3.1511039e-01 2.2757419e-01 2.5853132e-01 3.2950090e-01 2.2996799e-01 2.8911377e-01 3.3136481e-01 2.8050509e-01 2.5648758e-01 2.2384164e-01 2.8507826e-01 2.3741411e-01 2.5289158e-01 2.4520543e-01 1.5591712e-01 2.5163277e-01 5.1215829e-01 4.5200156e-01 4.2861009e-01 4.4496538e-01 4.7341919e-01 4.7441196e-01 4.6168878e-01 4.5347805e-01 4.8519916e-01 3.9997999e-01 3.3019092e-01 4.2716946e-01 3.9865809e-01 4.8629326e-01 4.8637186e-01 3.8670691e-01 4.0127624e-01 4.0126667e-01 5.5444310e-01 4.5424309e-01 4.0600299e-01 4.3254422e-01 4.9161364e-01 3.7174460e-01 3.9497344e-01 3.9273809e-01 3.5018083e-01 3.4346685e-01 4.7229362e-01 3.8003558e-01 4.4070091e-01 3.4442025e-01 4.8107176e-01 3.6755422e-01 4.7082182e-01 4.2490414e-01 4.2252116e-01 3.9675769e-01 3.3509282e-01 3.6564070e-01 4.2918040e-01 3.3977682e-01 4.5200156e-01 4.4195847e-01 4.2350677e-01 3.7942836e-01 4.2122143e-01 3.7189771e-01 3.9075300e-01 3.9132598e-01 2.1401129e-02 2.6296569e-02 3.2566498e-02 1.3297832e-02 1.1999623e-02 1.2969856e-02 1.8466773e-02 2.3873417e-02 1.8518842e-02 4.0273028e-03 1.2616800e-03 2.2732626e-02 1.2827409e-02 1.3181090e-02 2.2732626e-02 1.1261737e-02 1.3701796e-02 5.3984869e-03 5.7610599e-02 5.9941455e-03 8.9691119e-03 1.2694193e-02 2.1144882e-02 7.0627421e-03 1.0543898e-02 8.0308076e-03 1.3063205e-02 2.9989796e-01 2.9808728e-01 3.4381381e-01 3.9275825e-01 3.6234621e-01 3.8238034e-01 3.2086021e-01 2.7526551e-01 3.3529881e-01 3.3248525e-01 3.7261196e-01 3.0300865e-01 3.6317903e-01 3.7865155e-01 2.3211430e-01 2.8532877e-01 3.6963026e-01 3.1621648e-01 4.5177033e-01 3.2875625e-01 3.8520789e-01 2.8867443e-01 4.5697798e-01 3.8242988e-01 3.0442487e-01 3.0118555e-01 3.6926913e-01 3.8920975e-01 3.5915749e-01 2.5088735e-01 3.3365900e-01 3.1393007e-01 2.9523721e-01 4.8898239e-01 3.8528778e-01 2.9050533e-01 3.2648373e-01 4.0430761e-01 2.9352285e-01 3.5998625e-01 4.0438969e-01 3.4965804e-01 3.2429593e-01 2.8821126e-01 3.5492121e-01 3.0147553e-01 3.1927061e-01 3.1166517e-01 2.1164881e-01 3.1841810e-01 5.9626248e-01 5.3406968e-01 5.1001241e-01 5.2586196e-01 5.5673824e-01 5.5816878e-01 5.4309284e-01 5.3570978e-01 5.6971774e-01 4.7901704e-01 4.0442977e-01 5.0852772e-01 4.7828326e-01 5.7096471e-01 5.7126109e-01 4.6526268e-01 4.7993533e-01 4.7902644e-01 6.4260357e-01 5.3722757e-01 4.8599135e-01 5.1340958e-01 5.7642669e-01 4.4962350e-01 4.7318809e-01 4.7087433e-01 4.2633712e-01 4.1835467e-01 5.5597597e-01 4.5768215e-01 5.2292685e-01 4.1877489e-01 5.6541976e-01 4.4406435e-01 5.5240885e-01 5.0657081e-01 5.0216108e-01 4.7452659e-01 4.0930806e-01 4.4303784e-01 5.1082488e-01 4.1541892e-01 5.3406968e-01 5.2368299e-01 5.0449934e-01 4.5807263e-01 5.0263701e-01 4.4952858e-01 4.6823972e-01 4.6855914e-01 8.7198254e-03 1.2902931e-03 1.1684021e-03 1.6341127e-03 1.0742763e-03 2.6208124e-03 1.1173357e-03 8.9620141e-04 1.6960301e-02 1.4197837e-02 5.6586090e-04 2.0157829e-03 1.9836256e-03 5.6586090e-04 2.0413623e-03 1.1637665e-03 5.4511725e-03 1.0718252e-02 6.5990100e-03 2.7263257e-03 7.7966832e-03 1.5754002e-04 8.7922744e-03 3.0619296e-03 3.8030551e-03 1.0550593e-03 1.7203244e-01 1.7235723e-01 2.0751307e-01 2.4611820e-01 2.2109400e-01 2.4491699e-01 1.9298922e-01 1.5421652e-01 2.0061094e-01 2.0129686e-01 2.2934517e-01 1.7603988e-01 2.2070889e-01 2.3964854e-01 1.2009621e-01 1.5990877e-01 2.3601974e-01 1.8834267e-01 2.9339046e-01 1.9567575e-01 2.4748464e-01 1.6217086e-01 3.0116422e-01 2.4364046e-01 1.7530938e-01 1.7223213e-01 2.2701156e-01 2.4439785e-01 2.2188150e-01 1.3311613e-01 1.9877894e-01 1.8311301e-01 1.6845668e-01 3.3339209e-01 2.5192873e-01 1.7150268e-01 1.9350184e-01 2.5414415e-01 1.7271733e-01 2.2071334e-01 2.6313203e-01 2.1605186e-01 1.9141813e-01 1.6255272e-01 2.1936783e-01 1.7996851e-01 1.9179556e-01 1.8227672e-01 1.0300751e-01 1.8912086e-01 4.3075013e-01 3.7158844e-01 3.4752045e-01 3.6713693e-01 3.9134187e-01 3.9105984e-01 3.8378198e-01 3.7272538e-01 4.0046876e-01 3.2297138e-01 2.5826699e-01 3.4601238e-01 3.1932057e-01 4.0113556e-01 4.0033459e-01 3.0938917e-01 3.2551476e-01 3.2781102e-01 4.6405632e-01 3.7102765e-01 3.2659021e-01 3.5371449e-01 4.0659862e-01 2.9405620e-01 3.1978995e-01 3.1753736e-01 2.7499746e-01 2.7161605e-01 3.8895029e-01 3.0476818e-01 3.5833770e-01 2.7419176e-01 3.9644448e-01 2.9409120e-01 3.9304592e-01 3.4147602e-01 3.4611220e-01 3.2290811e-01 2.6406812e-01 2.8867894e-01 3.4717424e-01 2.6265032e-01 3.7158844e-01 3.6154105e-01 3.4316147e-01 2.9940560e-01 3.3824889e-01 2.9538166e-01 3.1708459e-01 3.1834036e-01 8.7316989e-03 6.7615313e-03 6.7580543e-03 9.6081666e-03 2.0657605e-03 3.8371349e-03 1.4271025e-02 1.2184393e-02 1.6084765e-02 4.9831593e-03 1.4699244e-02 1.4912454e-02 4.9831593e-03 6.5028816e-03 6.2489819e-03 1.3726162e-02 3.1411524e-02 7.7445772e-03 1.1141212e-02 2.5000477e-03 1.1143820e-02 6.1604304e-03 5.3711085e-03 7.5849080e-03 8.1835455e-03 1.6688130e-01 1.6291433e-01 2.0003066e-01 2.4149909e-01 2.1722570e-01 2.2445012e-01 1.7758122e-01 1.4623090e-01 1.9343386e-01 1.8753794e-01 2.2568158e-01 1.6690274e-01 2.2030573e-01 2.2323949e-01 1.1699096e-01 1.5725818e-01 2.1323159e-01 1.7489777e-01 2.9532205e-01 1.8786273e-01 2.2655558e-01 1.6049736e-01 2.9226070e-01 2.2550223e-01 1.7083413e-01 1.6938578e-01 2.2221647e-01 2.3649790e-01 2.0956346e-01 1.3266766e-01 1.9299947e-01 1.7760033e-01 1.6320695e-01 3.1350837e-01 2.2421748e-01 1.5253844e-01 1.8664517e-01 2.5447595e-01 1.5560691e-01 2.1266187e-01 2.4223633e-01 2.0012528e-01 1.8549850e-01 1.5864276e-01 2.0519641e-01 1.6093217e-01 1.7628990e-01 1.7435363e-01 1.0801101e-01 1.7763987e-01 4.0351234e-01 3.5280598e-01 3.3582666e-01 3.4348161e-01 3.7251839e-01 3.7541634e-01 3.5722931e-01 3.5450932e-01 3.8642215e-01 3.0688243e-01 2.4703841e-01 3.3487550e-01 3.1018257e-01 3.8808655e-01 3.8990045e-01 2.9749231e-01 3.0596368e-01 3.0291072e-01 4.5287211e-01 3.5944458e-01 3.1570031e-01 3.3498082e-01 3.9202879e-01 2.8759651e-01 3.0023966e-01 2.9853735e-01 2.6729925e-01 2.5639363e-01 3.7372548e-01 2.8896987e-01 3.4745520e-01 2.5469579e-01 3.8297689e-01 2.7675896e-01 3.6463006e-01 3.3839246e-01 3.2358656e-01 2.9982548e-01 2.4898596e-01 2.8176933e-01 3.3810925e-01 2.6587897e-01 3.5280598e-01 3.4488951e-01 3.3055981e-01 2.9862862e-01 3.3464036e-01 2.8522813e-01 2.9487313e-01 2.9445589e-01 4.3312037e-03 5.1674385e-03 4.6600432e-03 4.1032398e-03 1.3249619e-03 3.6837745e-03 2.4877830e-02 2.2958753e-02 1.1314391e-03 6.3769043e-03 6.2810489e-03 1.1314391e-03 5.7702159e-03 4.1635898e-03 1.1902706e-02 7.2040189e-03 1.2293784e-02 7.6706139e-03 1.1339253e-02 1.8296747e-03 1.4280945e-02 6.9429868e-03 8.6587607e-03 4.4388406e-03 1.4462991e-01 1.4494206e-01 1.7756526e-01 2.1378771e-01 1.9031042e-01 2.1286860e-01 1.6419734e-01 1.2822571e-01 1.7113301e-01 1.7185341e-01 1.9804950e-01 1.4833973e-01 1.9005998e-01 2.0775634e-01 9.7105565e-02 1.3348080e-01 2.0467358e-01 1.5981923e-01 2.5874568e-01 1.6653873e-01 2.1530133e-01 1.3558698e-01 2.6575883e-01 2.1156399e-01 1.4766732e-01 1.4484877e-01 1.9583483e-01 2.1211626e-01 1.9101641e-01 1.0897783e-01 1.6943757e-01 1.5488355e-01 1.4132668e-01 2.9650216e-01 2.1994601e-01 1.4455458e-01 1.6451956e-01 2.2152336e-01 1.4555202e-01 1.8989624e-01 2.3000345e-01 1.8566766e-01 1.6258902e-01 1.3589561e-01 1.8870744e-01 1.5235300e-01 1.6309487e-01 1.5410176e-01 8.1942750e-02 1.6048904e-01 3.8999083e-01 3.3294245e-01 3.0988325e-01 3.2882841e-01 3.5187047e-01 3.5156617e-01 3.4487977e-01 3.3402051e-01 3.6059894e-01 2.8649814e-01 2.2516617e-01 3.0844683e-01 2.8301726e-01 3.6124416e-01 3.6050400e-01 2.7355262e-01 2.8899505e-01 2.9139815e-01 4.2192237e-01 3.3236960e-01 2.8992253e-01 3.1585310e-01 3.6648886e-01 2.5905330e-01 2.8355149e-01 2.8139447e-01 2.4097820e-01 2.3780572e-01 3.4954046e-01 2.6919588e-01 3.2022959e-01 2.4036369e-01 3.5673540e-01 2.5910558e-01 3.5384915e-01 3.0430469e-01 3.0871278e-01 2.8664912e-01 2.3068275e-01 2.5394489e-01 3.0958210e-01 2.2970603e-01 3.3294245e-01 3.2329736e-01 3.0571743e-01 2.6432145e-01 3.0120271e-01 2.6026006e-01 2.8107880e-01 2.8234890e-01 3.9333334e-05 2.5761851e-04 1.3896575e-03 1.7536063e-03 1.9216331e-03 9.2702772e-03 7.4022776e-03 1.3090644e-03 1.5444025e-03 1.6252591e-03 1.3090644e-03 1.2151407e-04 1.0618022e-05 2.1493524e-03 1.8833153e-02 2.2172388e-03 7.3253783e-04 3.6800655e-03 1.5497854e-03 3.6733784e-03 4.9421897e-04 7.6664670e-04 7.0183041e-05 1.9407897e-01 1.9337938e-01 2.3114302e-01 2.7244640e-01 2.4629979e-01 2.6718506e-01 2.1373312e-01 1.7438911e-01 2.2391848e-01 2.2298785e-01 2.5503185e-01 1.9737603e-01 2.4663659e-01 2.6276403e-01 1.3891547e-01 1.8173656e-01 2.5713590e-01 2.0933386e-01 3.2324703e-01 2.1854256e-01 2.6975489e-01 1.8436571e-01 3.2904939e-01 2.6649404e-01 1.9772084e-01 1.9481826e-01 2.5232520e-01 2.6989379e-01 2.4511828e-01 1.5354404e-01 2.2230840e-01 2.0576951e-01 1.9024966e-01 3.5987888e-01 2.7239312e-01 1.8983400e-01 2.1646886e-01 2.8191043e-01 1.9167912e-01 2.4493869e-01 2.8620678e-01 2.3801287e-01 2.1448199e-01 1.8427005e-01 2.4198503e-01 1.9884520e-01 2.1243903e-01 2.0430599e-01 1.2215728e-01 2.1067715e-01 4.5871846e-01 3.9981904e-01 3.7661173e-01 3.9390784e-01 4.2025710e-01 4.2076082e-01 4.1035332e-01 4.0114215e-01 4.3087129e-01 3.5002279e-01 2.8365040e-01 3.7517763e-01 3.4790525e-01 4.3179681e-01 4.3157518e-01 3.3691557e-01 3.5177012e-01 3.5268567e-01 4.9705280e-01 4.0100475e-01 3.5505921e-01 3.8129652e-01 4.3707681e-01 3.2219168e-01 3.4580868e-01 3.4360838e-01 3.0200588e-01 2.9663386e-01 4.1868171e-01 3.3113109e-01 3.8802094e-01 2.9819354e-01 4.2685142e-01 3.1959000e-01 4.1941543e-01 3.7225097e-01 3.7239048e-01 3.4809183e-01 2.8876177e-01 3.1647952e-01 3.7686145e-01 2.9138730e-01 3.9981904e-01 3.8994709e-01 3.7187123e-01 3.2897937e-01 3.6879196e-01 3.2272643e-01 3.4226532e-01 3.4310531e-01 3.4181612e-04 1.4644608e-03 2.1632573e-03 2.3231555e-03 8.1286280e-03 6.3818616e-03 1.7262411e-03 1.6624580e-03 1.7631926e-03 1.7262411e-03 2.4569053e-05 5.6859581e-05 1.7551896e-03 2.0541034e-02 1.6702311e-03 5.9025530e-04 3.2341087e-03 2.0408948e-03 3.0131078e-03 2.8888789e-04 4.5924146e-04 1.3293684e-04 1.9862431e-01 1.9776069e-01 2.3600084e-01 2.7779005e-01 2.5142895e-01 2.7187023e-01 2.1810101e-01 1.7860088e-01 2.2871390e-01 2.2752286e-01 2.6024955e-01 2.0181434e-01 2.5187795e-01 2.6758248e-01 1.4283878e-01 1.8622396e-01 2.6161990e-01 2.1373552e-01 3.2920505e-01 2.2325952e-01 2.7444329e-01 1.8891553e-01 3.3470963e-01 2.7127428e-01 2.0233024e-01 1.9944956e-01 2.5748056e-01 2.7510316e-01 2.4993365e-01 1.5775267e-01 2.2713624e-01 2.1043184e-01 1.9474801e-01 3.6534538e-01 2.7678503e-01 1.9377126e-01 2.2119834e-01 2.8749014e-01 1.9572304e-01 2.4991164e-01 2.9104517e-01 2.4261230e-01 2.1922346e-01 1.8874518e-01 2.4669621e-01 2.0288553e-01 2.1678869e-01 2.0886650e-01 1.2608625e-01 2.1517216e-01 4.6449792e-01 4.0560127e-01 3.8251194e-01 3.9944814e-01 4.2616553e-01 4.2679596e-01 4.1587264e-01 4.0695550e-01 4.3702628e-01 3.5557170e-01 2.8885981e-01 3.8108822e-01 3.5369655e-01 4.3799369e-01 4.3786355e-01 3.4252750e-01 3.5719184e-01 3.5788232e-01 5.0366583e-01 4.0706759e-01 3.6083966e-01 3.8695887e-01 4.4324858e-01 3.2788328e-01 3.5118655e-01 3.4899273e-01 3.0749578e-01 3.0179987e-01 4.2472010e-01 3.3655063e-01 3.9402558e-01 3.0319627e-01 4.3300399e-01 3.2485825e-01 4.2490754e-01 3.7841034e-01 3.7783349e-01 3.5333537e-01 2.9386653e-01 3.2211174e-01 3.8285611e-01 2.9712888e-01 4.0560127e-01 3.9574961e-01 3.7770634e-01 3.3490218e-01 3.7491174e-01 3.2829405e-01 3.4750328e-01 3.4827580e-01 2.7893549e-03 2.7277911e-03 9.4108270e-04 1.0799149e-02 7.7770747e-03 1.9770194e-03 5.4325768e-04 5.8945201e-04 1.9770194e-03 5.1514113e-04 3.6478892e-04 1.6876295e-03 1.7172006e-02 2.9808015e-03 3.7816236e-04 5.6735840e-03 1.0535544e-03 5.0675384e-03 1.2248969e-03 1.1742680e-03 5.8878380e-05 1.9840502e-01 1.9840646e-01 2.3601178e-01 2.7699198e-01 2.5062921e-01 2.7429513e-01 2.1981939e-01 1.7908511e-01 2.2870797e-01 2.2884763e-01 2.5935890e-01 2.0237179e-01 2.5038976e-01 2.6920634e-01 1.4261267e-01 1.8559031e-01 2.6457877e-01 2.1508394e-01 3.2684946e-01 2.2341437e-01 2.7694800e-01 1.8806980e-01 3.3447269e-01 2.7322826e-01 2.0195195e-01 1.9876628e-01 2.5683031e-01 2.7497319e-01 2.5083242e-01 1.5688509e-01 2.2686098e-01 2.1020792e-01 1.9457412e-01 3.6717222e-01 2.8066992e-01 1.9637709e-01 2.2117475e-01 2.8566080e-01 1.9793610e-01 2.4995417e-01 2.9345115e-01 2.4428403e-01 2.1902512e-01 1.8834472e-01 2.4798811e-01 2.0544380e-01 2.1853532e-01 2.0913443e-01 1.2439434e-01 2.1611468e-01 4.6739623e-01 4.0702486e-01 3.8261075e-01 4.0188705e-01 4.2751037e-01 4.2749738e-01 4.1883120e-01 4.0825884e-01 4.3736523e-01 3.5667688e-01 2.8932174e-01 3.8108192e-01 3.5341594e-01 4.3812879e-01 4.3747647e-01 3.4285168e-01 3.5898948e-01 3.6076578e-01 5.0317788e-01 4.0703744e-01 3.6087589e-01 3.8845434e-01 4.4366743e-01 3.2719263e-01 3.5301257e-01 3.5071770e-01 3.0715395e-01 3.0299726e-01 4.2534595e-01 3.3768843e-01 3.9391146e-01 3.0525217e-01 4.3324318e-01 3.2636388e-01 4.2820876e-01 3.7681443e-01 3.8013938e-01 3.5586945e-01 2.9507753e-01 3.2153910e-01 3.8242816e-01 2.9467977e-01 4.0702486e-01 3.9678588e-01 3.7800850e-01 3.3305200e-01 3.7343525e-01 3.2833826e-01 3.4988792e-01 3.5099795e-01 7.6889988e-04 5.5936308e-03 9.7548717e-03 1.0412603e-02 1.0389613e-03 5.7781385e-03 5.9052415e-03 1.0389613e-03 1.4340775e-03 1.1584691e-03 6.0259991e-03 2.1726707e-02 3.4598658e-03 3.9021886e-03 1.8160607e-03 3.9104990e-03 3.6199548e-03 1.2013216e-03 2.4248068e-03 2.0560641e-03 1.7726458e-01 1.7519789e-01 2.1239850e-01 2.5350621e-01 2.2831460e-01 2.4335474e-01 1.9301815e-01 1.5733953e-01 2.0548992e-01 2.0248973e-01 2.3687424e-01 1.7915768e-01 2.2981656e-01 2.4028800e-01 1.2483249e-01 1.6617415e-01 2.3289941e-01 1.8936545e-01 3.0533170e-01 2.0007138e-01 2.4571617e-01 1.6904051e-01 3.0733551e-01 2.4338605e-01 1.8100871e-01 1.7874491e-01 2.3386295e-01 2.4993365e-01 2.2441376e-01 1.3976123e-01 2.0438723e-01 1.8845276e-01 1.7353191e-01 3.3400984e-01 2.4631085e-01 1.6886156e-01 1.9837340e-01 2.6441281e-01 1.7118963e-01 2.2560913e-01 2.6174131e-01 2.1639026e-01 1.9675554e-01 1.6819987e-01 2.2078897e-01 1.7753606e-01 1.9173589e-01 1.8624992e-01 1.1156657e-01 1.9127963e-01 4.2879129e-01 3.7350470e-01 3.5299849e-01 3.6620603e-01 3.9355975e-01 3.9506070e-01 3.8147101e-01 3.7498057e-01 4.0550993e-01 3.2554347e-01 2.6225589e-01 3.5177359e-01 3.2570798e-01 4.0674255e-01 4.0737898e-01 3.1405475e-01 3.2617446e-01 3.2545044e-01 4.7160294e-01 3.7696723e-01 3.3214002e-01 3.5535112e-01 4.1144267e-01 3.0143840e-01 3.2034131e-01 3.1835849e-01 2.8130938e-01 2.7364725e-01 3.9315179e-01 3.0715437e-01 3.6445309e-01 2.7384746e-01 4.0174546e-01 2.9539622e-01 3.8981435e-01 3.5158797e-01 3.4545598e-01 3.2149982e-01 2.6601526e-01 2.9570609e-01 3.5410378e-01 2.7466513e-01 3.7350470e-01 3.6448827e-01 3.4805708e-01 3.0999906e-01 3.4801807e-01 3.0074518e-01 3.1606363e-01 3.1638243e-01 3.9211584e-03 1.5428451e-02 1.5051422e-02 9.3641634e-05 5.2251987e-03 5.2564865e-03 9.3641634e-05 2.4059863e-03 1.5411207e-03 7.7716003e-03 1.4517538e-02 6.4009679e-03 4.6963365e-03 4.9429047e-03 2.1131701e-03 7.3135995e-03 2.7662314e-03 4.2415669e-03 2.1979302e-03 1.6154877e-01 1.6047147e-01 1.9568300e-01 2.3468417e-01 2.1025394e-01 2.2838581e-01 1.7884422e-01 1.4313754e-01 1.8898793e-01 1.8753794e-01 2.1845622e-01 1.6418759e-01 2.1103286e-01 2.2447017e-01 1.1131548e-01 1.5046796e-01 2.1889519e-01 1.7489777e-01 2.8359045e-01 1.8392350e-01 2.3077309e-01 1.5301294e-01 2.8765002e-01 2.2785871e-01 1.6499082e-01 1.6250540e-01 2.1577964e-01 2.3190311e-01 2.0826660e-01 1.2493129e-01 1.8764327e-01 1.7232008e-01 1.5800409e-01 3.1597925e-01 2.3306671e-01 1.5663136e-01 1.8209705e-01 2.4426589e-01 1.5839676e-01 2.0849973e-01 2.4621874e-01 2.0137281e-01 1.8035428e-01 1.5264734e-01 2.0519641e-01 1.6491824e-01 1.7763987e-01 1.7071018e-01 9.7334595e-02 1.7628990e-01 4.1013753e-01 3.5415853e-01 3.3261378e-01 3.4819629e-01 3.7372548e-01 3.7447405e-01 3.6377706e-01 3.5546726e-01 3.8432564e-01 3.0688243e-01 2.4450319e-01 3.3130276e-01 3.0553473e-01 3.8531353e-01 3.8537934e-01 2.9480414e-01 3.0829006e-01 3.0887441e-01 4.4839112e-01 3.5594109e-01 3.1215369e-01 3.3646690e-01 3.9023537e-01 2.8142851e-01 3.0262656e-01 3.0057353e-01 2.6218143e-01 2.5639363e-01 3.7251839e-01 2.8896987e-01 3.4359589e-01 2.5757650e-01 3.8052352e-01 2.7792266e-01 3.7237623e-01 3.2948525e-01 3.2773210e-01 3.0459398e-01 2.4898596e-01 2.7596310e-01 3.3313575e-01 2.5365041e-01 3.5415853e-01 3.4488951e-01 3.2799981e-01 2.8862094e-01 3.2611271e-01 2.8152144e-01 2.9910812e-01 2.9982464e-01 1.7874931e-02 1.3166667e-02 2.8067647e-03 5.4483543e-04 4.8491153e-04 2.8067647e-03 2.7932574e-03 2.1120566e-03 4.0283644e-03 1.1006031e-02 7.1968081e-03 1.9824114e-03 1.0903705e-02 3.4373671e-04 1.0364284e-02 4.2441401e-03 4.1832512e-03 1.3456492e-03 1.8893734e-01 1.9027350e-01 2.2602463e-01 2.6493124e-01 2.3909907e-01 2.6731994e-01 2.1287273e-01 1.7119179e-01 2.1885648e-01 2.2106766e-01 2.4751153e-01 1.9400411e-01 2.3783986e-01 2.6104566e-01 1.3465024e-01 1.7581619e-01 2.5867158e-01 2.0765719e-01 3.1157756e-01 2.1392913e-01 2.7004976e-01 1.7791371e-01 3.2221942e-01 2.6551484e-01 1.9215572e-01 1.8858682e-01 2.4539617e-01 2.6396374e-01 2.4190361e-01 1.4753547e-01 2.1663955e-01 2.0044864e-01 1.8527044e-01 3.5759997e-01 2.7597540e-01 1.9143761e-01 2.1146655e-01 2.7190276e-01 1.9231433e-01 2.3971651e-01 2.8607417e-01 2.3671699e-01 2.0909909e-01 1.7885289e-01 2.3973819e-01 2.0020124e-01 2.1166375e-01 2.0015528e-01 1.1482314e-01 2.0802247e-01 4.5814031e-01 3.9622068e-01 3.7010544e-01 3.9277065e-01 4.1629822e-01 4.1528170e-01 4.1031284e-01 3.9724817e-01 4.2445794e-01 3.4613203e-01 2.7894605e-01 3.6843870e-01 3.4078468e-01 4.2489846e-01 4.2345869e-01 3.3131814e-01 3.4950009e-01 3.5299308e-01 4.8820349e-01 3.9397890e-01 3.4860920e-01 3.7803314e-01 4.3080058e-01 3.1437592e-01 3.4366436e-01 3.4124618e-01 2.9521701e-01 2.9351505e-01 4.1304236e-01 3.2750551e-01 3.8091343e-01 2.9709224e-01 4.2023724e-01 3.1695286e-01 4.2011817e-01 3.6184591e-01 3.7113199e-01 3.4760954e-01 2.8576301e-01 3.0899799e-01 3.6912287e-01 2.7985004e-01 3.9622068e-01 3.8552168e-01 3.6588486e-01 3.1841134e-01 3.5869504e-01 3.1661834e-01 3.4148439e-01 3.4312143e-01 1.2983249e-03 1.5471006e-02 1.3470267e-02 1.3877317e-02 1.5471006e-02 7.2739782e-03 9.2612860e-03 6.0792360e-03 5.4160667e-02 2.4574168e-03 8.1477262e-03 3.8451807e-03 1.8194605e-02 1.5067164e-03 5.6792549e-03 4.8846913e-03 1.0004616e-02 2.6108642e-01 2.5718656e-01 3.0162187e-01 3.4990044e-01 3.2118558e-01 3.3212064e-01 2.7586622e-01 2.3634761e-01 2.9366681e-01 2.8770633e-01 3.3110877e-01 2.6200119e-01 3.2383134e-01 3.3046521e-01 1.9829106e-01 2.4860521e-01 3.1887574e-01 2.7240198e-01 4.1018982e-01 2.8711577e-01 3.3461178e-01 2.5228731e-01 4.0944673e-01 3.3325697e-01 2.6572836e-01 2.6351234e-01 3.2731613e-01 3.4479515e-01 3.1382719e-01 2.1730674e-01 2.9282566e-01 2.7420761e-01 2.5662111e-01 4.3493335e-01 3.3165524e-01 2.4546083e-01 2.8544328e-01 3.6363165e-01 2.4916639e-01 3.1676067e-01 3.5299851e-01 3.0301330e-01 2.8384547e-01 2.5066938e-01 3.0887732e-01 2.5579752e-01 2.7431070e-01 2.7082223e-01 1.8355500e-01 2.7545202e-01 5.3566205e-01 4.7913827e-01 4.5930782e-01 4.6887050e-01 5.0113940e-01 5.0408511e-01 4.8425611e-01 4.8100390e-01 5.1611676e-01 4.2712908e-01 3.5770237e-01 4.5815125e-01 4.2990067e-01 5.1783166e-01 5.1944925e-01 4.1592191e-01 4.2634771e-01 4.2297928e-01 5.8870710e-01 4.8576650e-01 4.3645958e-01 4.5912638e-01 5.2238783e-01 4.0361731e-01 4.1983156e-01 4.1785974e-01 3.8054730e-01 3.6909926e-01 5.0215992e-01 4.0667536e-01 4.7224138e-01 3.6745640e-01 5.1222367e-01 3.9280819e-01 4.9246039e-01 4.6045456e-01 4.4643751e-01 4.1946868e-01 3.6048019e-01 3.9703515e-01 4.6143668e-01 3.7590038e-01 4.7913827e-01 4.7009550e-01 4.5350904e-01 4.1479012e-01 4.5636227e-01 4.0162438e-01 4.1380491e-01 4.1334093e-01 1.4411876e-02 8.7935053e-03 9.1184252e-03 1.4411876e-02 5.7453578e-03 7.6054776e-03 2.7409931e-03 4.7624677e-02 1.8780439e-03 4.9746662e-03 5.9684857e-03 1.4534556e-02 2.3601867e-03 4.9286760e-03 3.4466344e-03 7.5341006e-03 2.6746877e-01 2.6516664e-01 3.0921139e-01 3.5673992e-01 3.2754140e-01 3.4481450e-01 2.8624779e-01 2.4359422e-01 3.0108022e-01 2.9756219e-01 3.3745616e-01 2.6990583e-01 3.2887946e-01 3.4163113e-01 2.0331657e-01 2.5392638e-01 3.3233847e-01 2.8201820e-01 4.1489235e-01 2.9472025e-01 3.4749512e-01 2.5726587e-01 4.1828245e-01 3.4508966e-01 2.7189140e-01 2.6903465e-01 3.3406888e-01 3.5284896e-01 3.2333666e-01 2.2149953e-01 2.9970099e-01 2.8083524e-01 2.6300357e-01 4.4804341e-01 3.4702929e-01 2.5691578e-01 2.9267142e-01 3.6866600e-01 2.5996213e-01 3.2467728e-01 3.6599412e-01 3.1379996e-01 2.9070461e-01 2.5648991e-01 3.1904849e-01 2.6736905e-01 2.8471636e-01 2.7833907e-01 1.8530093e-01 2.8435281e-01 5.5199539e-01 4.9206433e-01 4.6946939e-01 4.8356355e-01 5.1418554e-01 5.1595196e-01 5.0010048e-01 4.9372697e-01 5.2743722e-01 4.3877522e-01 3.6710197e-01 4.6809646e-01 4.3893984e-01 5.2878375e-01 5.2942069e-01 4.2592703e-01 4.3928640e-01 4.3789059e-01 5.9924430e-01 4.9601715e-01 4.4619754e-01 4.7193405e-01 5.3393309e-01 4.1149136e-01 4.3273356e-01 4.3054493e-01 3.8875406e-01 3.8007672e-01 5.1386048e-01 4.1809676e-01 4.8216133e-01 3.8002405e-01 5.2330849e-01 4.0472333e-01 5.0903363e-01 4.6735136e-01 4.6059448e-01 4.3368525e-01 3.7134977e-01 4.0504167e-01 4.7061436e-01 3.7989795e-01 4.9206433e-01 4.8217825e-01 4.6398354e-01 4.2055878e-01 4.6343857e-01 4.1088828e-01 4.2766517e-01 4.2782051e-01 4.0251529e-03 4.0402030e-03 0.0000000e+00 2.0104773e-03 1.1579294e-03 6.7733512e-03 1.3328703e-02 6.1195429e-03 3.8280621e-03 5.4471697e-03 1.3203495e-03 7.3930866e-03 2.5511055e-03 3.8011014e-03 1.5935161e-03 1.6488937e-01 1.6420208e-01 1.9946134e-01 2.3841307e-01 2.1377841e-01 2.3352484e-01 1.8323739e-01 1.4660873e-01 1.9269692e-01 1.9183992e-01 2.2200730e-01 1.6791595e-01 2.1423078e-01 2.2922867e-01 1.1407468e-01 1.5349471e-01 2.2418179e-01 1.7908948e-01 2.8692621e-01 1.8765985e-01 2.3596576e-01 1.5596498e-01 2.9203641e-01 2.3278981e-01 1.6829150e-01 1.6563525e-01 2.1942293e-01 2.3592536e-01 2.1256421e-01 1.2755291e-01 1.9121342e-01 1.7576718e-01 1.6132929e-01 3.2148865e-01 2.3885357e-01 1.6118125e-01 1.8573297e-01 2.4757051e-01 1.6279862e-01 2.1240660e-01 2.5149161e-01 2.0595435e-01 1.8389163e-01 1.5580881e-01 2.0964365e-01 1.6953436e-01 1.8203376e-01 1.7437090e-01 9.9184065e-02 1.8031354e-01 4.1664204e-01 3.5971944e-01 3.3744612e-01 3.5416868e-01 3.7936058e-01 3.7982315e-01 3.7006184e-01 3.6098196e-01 3.8956200e-01 3.1201251e-01 2.4889912e-01 3.3607844e-01 3.1002022e-01 3.9046127e-01 3.9028467e-01 2.9949936e-01 3.1373736e-01 3.1479561e-01 4.5355800e-01 3.6085089e-01 3.1682959e-01 3.4195608e-01 3.9553949e-01 2.8555816e-01 3.0804941e-01 3.0593834e-01 2.6633772e-01 2.6121338e-01 3.7782244e-01 2.9399549e-01 3.4839508e-01 2.6278429e-01 3.8569374e-01 2.8303600e-01 3.7885421e-01 3.3349568e-01 3.3352424e-01 3.1033775e-01 2.5375578e-01 2.8011018e-01 3.3772574e-01 2.5671985e-01 3.5971944e-01 3.5022311e-01 3.3289784e-01 2.9224130e-01 3.3016010e-01 2.8599652e-01 3.0475125e-01 3.0561759e-01 3.0700267e-06 4.0251529e-03 1.9467123e-03 1.7971688e-03 1.7301608e-03 1.6293141e-02 4.7718752e-03 6.8454231e-04 9.3235659e-03 1.4106675e-03 7.7429721e-03 3.1097831e-03 2.5391665e-03 9.5764453e-04 2.0739268e-01 2.0836358e-01 2.4589773e-01 2.8656370e-01 2.5981614e-01 2.8739169e-01 2.3131893e-01 1.8849968e-01 2.3845740e-01 2.4007299e-01 2.6857108e-01 2.1230255e-01 2.5877066e-01 2.8137449e-01 1.5046312e-01 1.9386671e-01 2.7809337e-01 2.2610426e-01 3.3523485e-01 2.3325794e-01 2.9016640e-01 1.9614834e-01 3.4542234e-01 2.8580893e-01 2.1082239e-01 2.0722978e-01 2.6628244e-01 2.8528108e-01 2.6193836e-01 1.6431358e-01 2.3627495e-01 2.1939954e-01 2.0354344e-01 3.8077948e-01 2.9536596e-01 2.0839572e-01 2.3078002e-01 2.9414568e-01 2.0957408e-01 2.6009226e-01 3.0679254e-01 2.5613081e-01 2.2839644e-01 1.9694047e-01 2.5948108e-01 2.1757899e-01 2.3004331e-01 2.1886202e-01 1.3010315e-01 2.2671016e-01 4.8309156e-01 4.2059741e-01 3.9446827e-01 4.1650857e-01 4.4118694e-01 4.4046177e-01 4.3416675e-01 4.2171124e-01 4.5001131e-01 3.6938174e-01 3.0049261e-01 3.9280494e-01 3.6453208e-01 4.5055186e-01 4.4930066e-01 3.5453263e-01 3.7247610e-01 3.7543144e-01 5.1540859e-01 4.1899010e-01 3.7243361e-01 4.0192295e-01 4.5645786e-01 3.3753686e-01 3.6646355e-01 3.6403348e-01 3.1765048e-01 3.1516192e-01 4.3820660e-01 3.5021371e-01 4.0564147e-01 3.1837605e-01 4.4574076e-01 3.3915719e-01 4.4399141e-01 3.8666018e-01 3.9439941e-01 3.7011128e-01 3.0715348e-01 3.3195062e-01 3.9368522e-01 3.0254596e-01 4.2059741e-01 4.0983289e-01 3.9004780e-01 3.4211299e-01 3.8338579e-01 3.3953411e-01 3.6390344e-01 3.6538415e-01 4.0402030e-03 2.0647746e-03 1.8810615e-03 1.8744038e-03 1.5904825e-02 5.0089073e-03 7.7718458e-04 9.5962272e-03 1.3536136e-03 8.0354537e-03 3.2683077e-03 2.7053207e-03 1.0204136e-03 2.0663566e-01 2.0767698e-01 2.4509318e-01 2.8563097e-01 2.5892354e-01 2.8672996e-01 2.3068420e-01 1.8783705e-01 2.3766371e-01 2.3938906e-01 2.6765771e-01 2.1160129e-01 2.5782529e-01 2.8065126e-01 1.4982077e-01 1.9310124e-01 2.7749364e-01 2.2544624e-01 3.3411471e-01 2.3248629e-01 2.8950769e-01 1.9536146e-01 3.4445558e-01 2.8510792e-01 2.1004612e-01 2.0643532e-01 2.6539182e-01 2.8440424e-01 2.6118254e-01 1.6358877e-01 2.3546280e-01 2.1862058e-01 2.0279724e-01 3.7994304e-01 2.9482551e-01 2.0788172e-01 2.2999781e-01 2.9312113e-01 2.0902225e-01 2.5926765e-01 3.0610117e-01 2.5545076e-01 2.2760393e-01 1.9618808e-01 2.5876275e-01 2.1704368e-01 2.2941326e-01 2.1812470e-01 1.2939132e-01 2.2601611e-01 4.8224276e-01 4.1968249e-01 3.9347110e-01 4.1568549e-01 4.4024422e-01 4.3946585e-01 4.3337086e-01 4.2078495e-01 4.4897602e-01 3.6849705e-01 2.9964288e-01 3.9180103e-01 3.6353845e-01 4.4949934e-01 4.4820701e-01 3.5360058e-01 3.7164688e-01 3.7469388e-01 5.1424729e-01 4.1795596e-01 3.7145645e-01 4.0103422e-01 4.5542290e-01 3.3654347e-01 3.6564394e-01 3.6320808e-01 3.1671115e-01 3.1435391e-01 4.3720666e-01 3.4935506e-01 4.0461470e-01 3.1763784e-01 4.4470146e-01 3.3834387e-01 4.4321597e-01 3.8553656e-01 3.9358898e-01 3.6934910e-01 3.0635763e-01 3.3097385e-01 3.9264615e-01 3.0146236e-01 4.1968249e-01 4.0889669e-01 3.8907226e-01 3.4102273e-01 3.8227517e-01 3.3859771e-01 3.6313559e-01 3.6464431e-01 2.0104773e-03 1.1579294e-03 6.7733512e-03 1.3328703e-02 6.1195429e-03 3.8280621e-03 5.4471697e-03 1.3203495e-03 7.3930866e-03 2.5511055e-03 3.8011014e-03 1.5935161e-03 1.6488937e-01 1.6420208e-01 1.9946134e-01 2.3841307e-01 2.1377841e-01 2.3352484e-01 1.8323739e-01 1.4660873e-01 1.9269692e-01 1.9183992e-01 2.2200730e-01 1.6791595e-01 2.1423078e-01 2.2922867e-01 1.1407468e-01 1.5349471e-01 2.2418179e-01 1.7908948e-01 2.8692621e-01 1.8765985e-01 2.3596576e-01 1.5596498e-01 2.9203641e-01 2.3278981e-01 1.6829150e-01 1.6563525e-01 2.1942293e-01 2.3592536e-01 2.1256421e-01 1.2755291e-01 1.9121342e-01 1.7576718e-01 1.6132929e-01 3.2148865e-01 2.3885357e-01 1.6118125e-01 1.8573297e-01 2.4757051e-01 1.6279862e-01 2.1240660e-01 2.5149161e-01 2.0595435e-01 1.8389163e-01 1.5580881e-01 2.0964365e-01 1.6953436e-01 1.8203376e-01 1.7437090e-01 9.9184065e-02 1.8031354e-01 4.1664204e-01 3.5971944e-01 3.3744612e-01 3.5416868e-01 3.7936058e-01 3.7982315e-01 3.7006184e-01 3.6098196e-01 3.8956200e-01 3.1201251e-01 2.4889912e-01 3.3607844e-01 3.1002022e-01 3.9046127e-01 3.9028467e-01 2.9949936e-01 3.1373736e-01 3.1479561e-01 4.5355800e-01 3.6085089e-01 3.1682959e-01 3.4195608e-01 3.9553949e-01 2.8555816e-01 3.0804941e-01 3.0593834e-01 2.6633772e-01 2.6121338e-01 3.7782244e-01 2.9399549e-01 3.4839508e-01 2.6278429e-01 3.8569374e-01 2.8303600e-01 3.7885421e-01 3.3349568e-01 3.3352424e-01 3.1033775e-01 2.5375578e-01 2.8011018e-01 3.3772574e-01 2.5671985e-01 3.5971944e-01 3.5022311e-01 3.3289784e-01 2.9224130e-01 3.3016010e-01 2.8599652e-01 3.0475125e-01 3.0561759e-01 1.3213080e-04 1.6348389e-03 2.1958653e-02 1.3024074e-03 6.2459052e-04 2.7868209e-03 2.5128724e-03 2.4948096e-03 1.5213665e-04 2.9312203e-04 2.6269769e-04 2.0119891e-01 2.0014287e-01 2.3871519e-01 2.8086210e-01 2.5438649e-01 2.7419983e-01 2.2034638e-01 1.8091150e-01 2.3139686e-01 2.2990542e-01 2.6326545e-01 2.0423778e-01 2.5497864e-01 2.7008054e-01 1.4507978e-01 1.8881738e-01 2.6377709e-01 2.1604374e-01 3.3279319e-01 2.2588101e-01 2.7676493e-01 1.9156801e-01 3.3788258e-01 2.7371187e-01 2.0495838e-01 2.0212622e-01 2.6043406e-01 2.7802264e-01 2.5251791e-01 1.6022437e-01 2.2986910e-01 2.1306976e-01 1.9729190e-01 3.6816423e-01 2.7878040e-01 1.9567818e-01 2.2384809e-01 2.9081290e-01 1.9773475e-01 2.5268382e-01 2.9345893e-01 2.4498738e-01 2.2190073e-01 1.9130390e-01 2.4917712e-01 2.0485354e-01 2.1902087e-01 2.1139045e-01 1.2850635e-01 2.1757950e-01 4.6735126e-01 4.0863686e-01 3.8577163e-01 4.0223139e-01 4.2927752e-01 4.3005363e-01 4.1858115e-01 4.1002225e-01 4.4039161e-01 3.5852229e-01 2.9170762e-01 3.8436621e-01 3.5694453e-01 4.4140604e-01 4.4138801e-01 3.4560659e-01 3.5999045e-01 3.6042881e-01 5.0737364e-01 4.1042921e-01 3.6404336e-01 3.8992213e-01 4.4661300e-01 3.3112795e-01 3.5395838e-01 3.5178032e-01 3.1059068e-01 3.0453530e-01 4.2798873e-01 3.3942843e-01 3.9736659e-01 3.0574030e-01 4.3638021e-01 3.2761075e-01 4.2755962e-01 3.8201356e-01 3.8058140e-01 3.5594943e-01 2.9656762e-01 3.2531047e-01 3.8623001e-01 3.0061288e-01 4.0863686e-01 3.9884323e-01 3.8090672e-01 3.3841042e-01 3.7847943e-01 3.3138355e-01 3.5013260e-01 3.5082807e-01 2.3963109e-03 1.8894374e-02 2.2439950e-03 9.0594652e-04 3.4335324e-03 1.6224592e-03 3.5937956e-03 4.5783206e-04 8.1747242e-04 1.3119947e-04 1.9231717e-01 1.9150735e-01 2.2920314e-01 2.7047035e-01 2.4441394e-01 2.6481790e-01 2.1164496e-01 1.7262115e-01 2.2200818e-01 2.2091128e-01 2.5312771e-01 1.9549847e-01 2.4484600e-01 2.6050695e-01 1.3741417e-01 1.8008449e-01 2.5474237e-01 2.0730811e-01 3.2133505e-01 2.1663183e-01 2.6736983e-01 1.8273137e-01 3.2682425e-01 2.6418461e-01 1.9596515e-01 1.9311641e-01 2.5039748e-01 2.6783585e-01 2.4301257e-01 1.5205635e-01 2.2044020e-01 2.0395985e-01 1.8849810e-01 3.5730736e-01 2.6984619e-01 1.8774203e-01 2.1458977e-01 2.8004857e-01 1.8962388e-01 2.4294411e-01 2.8377929e-01 2.3583758e-01 2.1263399e-01 1.8257496e-01 2.3984158e-01 1.9672007e-01 2.1035264e-01 2.0243724e-01 1.2095575e-01 2.0869633e-01 4.5579154e-01 3.9719792e-01 3.7421582e-01 3.9117796e-01 4.1759891e-01 4.1818270e-01 4.0752420e-01 3.9853286e-01 4.2831769e-01 3.4756630e-01 2.8146997e-01 3.7279915e-01 3.4563396e-01 4.2926782e-01 4.2911586e-01 3.3459449e-01 3.4922354e-01 3.5000846e-01 4.9447633e-01 3.9856686e-01 3.5272682e-01 3.7871114e-01 4.3449948e-01 3.2004729e-01 3.4327468e-01 3.4109263e-01 2.9987407e-01 2.9431934e-01 4.1611792e-01 3.2872232e-01 3.8562509e-01 2.9576964e-01 4.2431958e-01 3.1716861e-01 4.1652649e-01 3.7009695e-01 3.6972936e-01 3.4546743e-01 2.8647014e-01 3.1433567e-01 3.7453491e-01 2.8958559e-01 3.9719792e-01 3.8739786e-01 3.6946063e-01 3.2697767e-01 3.6662992e-01 3.2048201e-01 3.3967430e-01 3.4047263e-01 2.8241524e-02 1.4713791e-03 4.6823304e-04 6.0296352e-03 5.2071190e-03 3.4182869e-03 1.9529381e-03 9.1025104e-04 1.8441969e-03 2.3388660e-01 2.3348281e-01 2.7404368e-01 3.1787596e-01 2.8991570e-01 3.1331298e-01 2.5580945e-01 2.1274052e-01 2.6625865e-01 2.6571335e-01 2.9921857e-01 2.3779036e-01 2.8985951e-01 3.0846478e-01 1.7343111e-01 2.2024476e-01 3.0259960e-01 2.5097696e-01 3.7082192e-01 2.6053197e-01 3.1606460e-01 2.2298918e-01 3.7823337e-01 3.1251210e-01 2.3776110e-01 2.3444923e-01 2.9645330e-01 3.1548927e-01 2.8938607e-01 1.8922982e-01 2.6439849e-01 2.4655891e-01 2.2974757e-01 4.1142478e-01 3.1887022e-01 2.2998734e-01 2.5821680e-01 3.2732410e-01 2.3197317e-01 2.8887378e-01 3.3359010e-01 2.8195681e-01 2.5599107e-01 2.2312925e-01 2.8613603e-01 2.3977955e-01 2.5441596e-01 2.4519140e-01 1.5385241e-01 2.5232104e-01 5.1493631e-01 4.5323214e-01 4.2845834e-01 4.4724986e-01 4.7457294e-01 4.7489714e-01 4.6451744e-01 4.5458397e-01 4.8531016e-01 4.0086775e-01 3.3039510e-01 4.2690815e-01 3.9810528e-01 4.8619268e-01 4.8572861e-01 3.8678000e-01 4.0288412e-01 4.0400345e-01 5.5371159e-01 4.5396321e-01 4.0578110e-01 4.3384503e-01 4.9180921e-01 3.7075981e-01 3.9660943e-01 3.9426853e-01 3.4955388e-01 3.4443823e-01 4.7269976e-01 3.8095285e-01 4.4033063e-01 3.4628429e-01 4.8107810e-01 3.6885113e-01 4.7400892e-01 4.2299055e-01 4.2466221e-01 3.9913020e-01 3.3607659e-01 3.6477722e-01 4.2848136e-01 3.3695835e-01 4.5323214e-01 4.4278413e-01 4.2356519e-01 3.7724050e-01 4.1943108e-01 3.7167660e-01 3.9296882e-01 3.9389283e-01 3.3787081e-02 2.1999955e-02 3.5606869e-02 9.7919779e-03 3.8730614e-02 2.5164827e-02 2.6849118e-02 1.7903003e-02 1.2662420e-01 1.3061214e-01 1.5776511e-01 1.8787898e-01 1.6611889e-01 2.0099100e-01 1.5292701e-01 1.1474225e-01 1.5177722e-01 1.5820095e-01 1.7289957e-01 1.3332512e-01 1.6306194e-01 1.9266388e-01 8.3782583e-02 1.1475472e-01 1.9583103e-01 1.4727273e-01 2.2350713e-01 1.4824286e-01 2.0360977e-01 1.1578494e-01 2.3876064e-01 1.9766401e-01 1.2872248e-01 1.2487918e-01 1.7184761e-01 1.8912261e-01 1.7398714e-01 9.1697206e-02 1.4908080e-01 1.3596066e-01 1.2380963e-01 2.7656824e-01 2.1428571e-01 1.3903777e-01 1.4563130e-01 1.9085533e-01 1.3814153e-01 1.6927103e-01 2.1683317e-01 1.7245190e-01 1.4312164e-01 1.1792045e-01 1.7357532e-01 1.4591400e-01 1.5204372e-01 1.3733781e-01 6.4362895e-02 1.4610010e-01 3.6994724e-01 3.0922665e-01 2.8172128e-01 3.0981046e-01 3.2683078e-01 3.2376302e-01 3.2734273e-01 3.0972403e-01 3.3079457e-01 2.6398840e-01 2.0377846e-01 2.7991998e-01 2.5479336e-01 3.3054260e-01 3.2764011e-01 2.4845492e-01 2.6936921e-01 2.7648193e-01 3.8578015e-01 3.0244531e-01 2.6262990e-01 2.9337350e-01 3.3673416e-01 2.3057418e-01 2.6437275e-01 2.6189855e-01 2.1511723e-01 2.1874548e-01 3.2151629e-01 2.4786804e-01 2.9060022e-01 2.2492263e-01 3.2669967e-01 2.4001378e-01 3.3739817e-01 2.6941492e-01 2.9020759e-01 2.7043921e-01 2.1216140e-01 2.2627991e-01 2.7921868e-01 1.9599823e-01 3.0922665e-01 2.9841488e-01 2.7865157e-01 2.3076134e-01 2.6697481e-01 2.3479056e-01 2.6453179e-01 2.6724220e-01 1.8463349e-03 1.7603525e-03 7.3051568e-03 4.1015204e-04 7.6986614e-04 4.1505661e-04 2.5516535e-03 2.2715123e-01 2.2501703e-01 2.6621562e-01 3.1107232e-01 2.8349906e-01 3.0014485e-01 2.4486000e-01 2.0495206e-01 2.5858102e-01 2.5538755e-01 2.9285644e-01 2.2943000e-01 2.8485147e-01 2.9693404e-01 1.6780939e-01 2.1457958e-01 2.8854018e-01 2.4083271e-01 3.6655716e-01 2.5261802e-01 3.0270375e-01 2.1770871e-01 3.6954821e-01 3.0027680e-01 2.3128364e-01 2.2864524e-01 2.8964053e-01 3.0736347e-01 2.7955757e-01 1.8460266e-01 2.5729263e-01 2.3962699e-01 2.2298939e-01 3.9825299e-01 3.0280555e-01 2.1772566e-01 2.5069761e-01 3.2250864e-01 2.2044120e-01 2.8076678e-01 3.2019205e-01 2.7070478e-01 2.4885895e-01 2.1694127e-01 2.7557358e-01 2.2744661e-01 2.4343281e-01 2.3729093e-01 1.5163937e-01 2.4296011e-01 4.9867564e-01 4.4043288e-01 4.1855224e-01 4.3250726e-01 4.6172807e-01 4.6333132e-01 4.4859207e-01 4.4201028e-01 4.7437581e-01 3.8923920e-01 3.2088439e-01 4.1722959e-01 3.8928568e-01 4.7566007e-01 4.7625383e-01 3.7686783e-01 3.8986190e-01 3.8884081e-01 5.4387473e-01 4.4406349e-01 3.9623886e-01 4.2109532e-01 4.8065646e-01 3.6308022e-01 3.8359994e-01 3.8148432e-01 3.4142085e-01 3.3328357e-01 4.6130540e-01 3.6948155e-01 4.3073385e-01 3.3341169e-01 4.7038237e-01 3.5679054e-01 4.5732763e-01 4.1658437e-01 4.1040883e-01 3.8470265e-01 3.2499997e-01 3.5692838e-01 4.1963835e-01 3.3330111e-01 4.4043288e-01 4.3085698e-01 4.1330060e-01 3.7185723e-01 4.1281711e-01 3.6250007e-01 3.7890193e-01 3.7915604e-01 5.4235993e-03 2.5998420e-03 3.8677378e-03 1.1491859e-03 6.2877149e-04 4.8332372e-04 2.1486898e-01 2.1467854e-01 2.5369922e-01 2.9604720e-01 2.6891688e-01 2.9246555e-01 2.3653315e-01 1.9467620e-01 2.4616446e-01 2.4597983e-01 2.7792166e-01 2.1880759e-01 2.6876410e-01 2.8748855e-01 1.5684504e-01 2.0165721e-01 2.8227299e-01 2.3174975e-01 3.4738814e-01 2.4066356e-01 2.9516630e-01 2.0426320e-01 3.5491429e-01 2.9152419e-01 2.1857252e-01 2.1532575e-01 2.7527993e-01 2.9385335e-01 2.6877316e-01 1.7184619e-01 2.4431046e-01 2.2708854e-01 2.1089056e-01 3.8786051e-01 2.9845589e-01 2.1195408e-01 2.3838722e-01 3.0508869e-01 2.1371586e-01 2.6806783e-01 3.1216051e-01 2.6180490e-01 2.3620065e-01 2.0447438e-01 2.6573552e-01 2.2136814e-01 2.3519672e-01 2.2587537e-01 1.3797486e-01 2.3292930e-01 4.8968343e-01 4.2865553e-01 4.0406082e-01 4.2311568e-01 4.4955467e-01 4.4970134e-01 4.4022012e-01 4.2994584e-01 4.5983149e-01 3.7733154e-01 3.0847182e-01 4.0252124e-01 3.7430526e-01 4.6065171e-01 4.6008825e-01 3.6337620e-01 3.7950484e-01 3.8097080e-01 5.2689771e-01 4.2900834e-01 3.8187058e-01 4.0969052e-01 4.6622956e-01 3.4753954e-01 3.7338441e-01 3.7106677e-01 3.2693971e-01 3.2232718e-01 4.4752724e-01 3.5789640e-01 4.1563695e-01 3.2438944e-01 4.5565562e-01 3.4619907e-01 4.4965557e-01 3.9841763e-01 4.0096111e-01 3.7608333e-01 3.1419485e-01 3.4172782e-01 4.0397551e-01 3.1440281e-01 4.2865553e-01 4.1831326e-01 3.9931889e-01 3.5369559e-01 3.9495166e-01 3.4857729e-01 3.7001412e-01 3.7103653e-01 9.4891023e-03 8.2375707e-04 1.6686708e-03 2.4475618e-03 4.6565778e-03 2.0491959e-01 2.0139969e-01 2.4160221e-01 2.8586265e-01 2.5951451e-01 2.7003471e-01 2.1844761e-01 1.8272084e-01 2.3436629e-01 2.2908460e-01 2.6861177e-01 2.0572725e-01 2.6206958e-01 2.6821933e-01 1.4908933e-01 1.9377976e-01 2.5813756e-01 2.1522061e-01 3.4200281e-01 2.2841742e-01 2.7236034e-01 1.9712279e-01 3.4101997e-01 2.7089218e-01 2.0911514e-01 2.0716704e-01 2.6510721e-01 2.8112922e-01 2.5280689e-01 1.6599180e-01 2.3361443e-01 2.1674754e-01 2.0090153e-01 3.6527528e-01 2.7043122e-01 1.9136502e-01 2.2690330e-01 2.9871211e-01 1.9453190e-01 2.5541554e-01 2.8925890e-01 2.4310626e-01 2.2546391e-01 1.9558871e-01 2.4836004e-01 2.0063248e-01 2.1704777e-01 2.1367234e-01 1.3678274e-01 2.1790721e-01 4.6096128e-01 4.0671584e-01 3.8773373e-01 3.9744288e-01 4.2748862e-01 4.3009711e-01 4.1223718e-01 4.0843810e-01 4.4142325e-01 3.5773584e-01 2.9306179e-01 3.8663461e-01 3.6011993e-01 4.4301487e-01 4.4448732e-01 3.4710733e-01 3.5722182e-01 3.5456119e-01 5.1046759e-01 4.1264841e-01 3.6628224e-01 3.8788026e-01 4.4738884e-01 3.3559118e-01 3.5113614e-01 3.4925623e-01 3.1415212e-01 3.0373195e-01 4.2825709e-01 3.3863565e-01 3.9988417e-01 3.0248234e-01 4.3771445e-01 3.2582243e-01 4.2019828e-01 3.8883040e-01 3.7626984e-01 3.5109855e-01 2.9576205e-01 3.2946337e-01 3.8969349e-01 3.1023698e-01 4.0671584e-01 3.9807129e-01 3.8231042e-01 3.4615104e-01 3.8497123e-01 3.3374807e-01 3.4573433e-01 3.4546409e-01 9.9827550e-03 3.7862368e-03 4.2584946e-03 1.2265791e-03 1.7617949e-01 1.7703821e-01 2.1212343e-01 2.5052805e-01 2.2530971e-01 2.5127302e-01 1.9850334e-01 1.5861692e-01 2.0515179e-01 2.0665158e-01 2.3356888e-01 1.8070269e-01 2.2448284e-01 2.4549391e-01 1.2367511e-01 1.6367665e-01 2.4261509e-01 1.9359579e-01 2.9712394e-01 2.0027260e-01 2.5390638e-01 1.6582785e-01 3.0629971e-01 2.4971132e-01 1.7938888e-01 1.7609087e-01 2.3136866e-01 2.4921343e-01 2.2715314e-01 1.3644726e-01 2.0313672e-01 1.8736201e-01 1.7259709e-01 3.3997757e-01 2.5916969e-01 1.7732718e-01 1.9796934e-01 2.5795325e-01 1.7832877e-01 2.2545225e-01 2.6961076e-01 2.2173788e-01 1.9575867e-01 1.6649347e-01 2.2485533e-01 1.8584864e-01 1.9731550e-01 1.8682160e-01 1.0543428e-01 1.9413835e-01 4.3845459e-01 3.7813833e-01 3.5313427e-01 3.7426892e-01 3.9794201e-01 3.9726718e-01 3.9130315e-01 3.7920848e-01 4.0649770e-01 3.2906316e-01 2.6354873e-01 3.5155280e-01 3.2453882e-01 4.0704153e-01 4.0591144e-01 3.1492301e-01 3.3203733e-01 3.3498583e-01 4.6984073e-01 3.7668481e-01 3.3204804e-01 3.6021418e-01 4.1270518e-01 2.9886261e-01 3.2629567e-01 3.2396944e-01 2.7989788e-01 2.7743776e-01 3.9510115e-01 3.1077003e-01 3.6387709e-01 2.8054253e-01 4.0239292e-01 3.0024699e-01 4.0081171e-01 3.4598760e-01 3.5305310e-01 3.2985030e-01 2.6984561e-01 2.9352511e-01 3.5245796e-01 2.6611615e-01 3.7813833e-01 3.6780473e-01 3.4887718e-01 3.0350575e-01 3.4281917e-01 3.0065558e-01 3.2390437e-01 3.2536506e-01 1.4872402e-03 1.4261828e-03 4.3370414e-03 2.2707675e-01 2.2400493e-01 2.6569285e-01 3.1123078e-01 2.8378554e-01 2.9683242e-01 2.4257696e-01 2.0422363e-01 2.5811380e-01 2.5348079e-01 2.9319960e-01 2.2849166e-01 2.8589147e-01 2.9450563e-01 1.6807288e-01 2.1502765e-01 2.8470332e-01 2.3897250e-01 3.6819788e-01 2.5200370e-01 2.9929335e-01 2.1837402e-01 3.6884033e-01 2.9747447e-01 2.3136263e-01 2.2907381e-01 2.8973378e-01 3.0680413e-01 2.7799960e-01 1.8547528e-01 2.5712752e-01 2.3949352e-01 2.2288675e-01 3.9517754e-01 2.9790586e-01 2.1461980e-01 2.5028856e-01 3.2375470e-01 2.1774627e-01 2.8014020e-01 3.1681085e-01 2.6834640e-01 2.4865097e-01 2.1711982e-01 2.7360556e-01 2.2434130e-01 2.4112622e-01 2.3662943e-01 1.5362542e-01 2.4153192e-01 4.9407199e-01 4.3763583e-01 4.1728329e-01 4.2863716e-01 4.5893922e-01 4.6123811e-01 4.4410036e-01 4.3933832e-01 4.7263926e-01 3.8698450e-01 3.1961653e-01 4.1608078e-01 3.8854631e-01 4.7414193e-01 4.7530563e-01 3.7551546e-01 3.8685112e-01 3.8465728e-01 5.4280771e-01 4.4284025e-01 3.9512469e-01 4.1829234e-01 4.7881043e-01 3.6289720e-01 3.8058317e-01 3.7858579e-01 3.4094528e-01 3.3115887e-01 4.5930198e-01 3.6727055e-01 4.2965213e-01 3.3035276e-01 4.6876907e-01 3.5423104e-01 4.5243416e-01 4.1718566e-01 4.0676646e-01 3.8091352e-01 3.2289623e-01 3.5664111e-01 4.1894270e-01 3.3518670e-01 4.3763583e-01 4.2851737e-01 4.1182914e-01 3.7291664e-01 4.1330116e-01 3.6151280e-01 3.7529785e-01 3.7518553e-01 2.1466294e-04 8.1135795e-04 2.0395325e-01 2.0232995e-01 2.4147692e-01 2.8429935e-01 2.5773107e-01 2.7550146e-01 2.2191392e-01 1.8311464e-01 2.3414066e-01 2.3177254e-01 2.6670079e-01 2.0650082e-01 2.5876572e-01 2.7190067e-01 1.4755667e-01 1.9178198e-01 2.6468375e-01 2.1783813e-01 3.3738596e-01 2.2849816e-01 2.7802206e-01 1.9468150e-01 3.4113386e-01 2.7532568e-01 2.0783209e-01 2.0518365e-01 2.6370466e-01 2.8101900e-01 2.5475268e-01 1.6319612e-01 2.3278117e-01 2.1587899e-01 1.9999930e-01 3.7014440e-01 2.7911349e-01 1.9654509e-01 2.2657275e-01 2.9494234e-01 1.9887441e-01 2.5547815e-01 2.9483790e-01 2.4668408e-01 2.2473055e-01 1.9413008e-01 2.5114079e-01 2.0579387e-01 2.2056413e-01 2.1387343e-01 1.3181835e-01 2.1964768e-01 4.6883654e-01 4.1098091e-01 3.8893009e-01 4.0388763e-01 4.3171852e-01 4.3291890e-01 4.1992695e-01 4.1244869e-01 4.4351517e-01 3.6095375e-01 2.9436456e-01 3.8758959e-01 3.6027619e-01 4.4466450e-01 4.4498549e-01 3.4851465e-01 3.6196876e-01 3.6168475e-01 5.1115719e-01 4.1372900e-01 3.6718805e-01 3.9217531e-01 4.4969696e-01 3.3465314e-01 3.5590188e-01 3.5378490e-01 3.1382959e-01 3.0675099e-01 4.3089908e-01 3.4178657e-01 4.0069101e-01 3.0739171e-01 4.3956059e-01 3.2969272e-01 4.2869495e-01 3.8625531e-01 3.8227459e-01 3.5742723e-01 2.9874912e-01 3.2874265e-01 3.8973129e-01 3.0516637e-01 4.1098091e-01 4.0141982e-01 3.8392089e-01 3.4269880e-01 3.8263609e-01 3.3443392e-01 3.5169446e-01 3.5216636e-01 9.1517643e-04 2.1524074e-01 2.1387759e-01 2.5373107e-01 2.9714785e-01 2.7003778e-01 2.8920001e-01 2.3426287e-01 1.9410928e-01 2.4622443e-01 2.4423617e-01 2.7915984e-01 2.1812334e-01 2.7081916e-01 2.8531140e-01 1.5727134e-01 2.0260081e-01 2.7829111e-01 2.2998414e-01 3.5056990e-01 2.4050939e-01 2.9179089e-01 2.0549251e-01 3.5521699e-01 2.8889714e-01 2.1915718e-01 2.1632646e-01 2.7619378e-01 2.9404932e-01 2.6759110e-01 1.7313032e-01 2.4473695e-01 2.2745766e-01 2.1120369e-01 3.8534612e-01 2.9320974e-01 2.0849982e-01 2.3847660e-01 3.0758274e-01 2.1079215e-01 2.6804702e-01 3.0890781e-01 2.5958017e-01 2.3652855e-01 2.0509955e-01 2.6402277e-01 2.1797131e-01 2.3288914e-01 2.2557846e-01 1.4040598e-01 2.3171289e-01 4.8566100e-01 4.2666426e-01 4.0387929e-01 4.1975185e-01 4.4765854e-01 4.4867725e-01 4.3614287e-01 4.2811681e-01 4.5929331e-01 3.7580128e-01 3.0785579e-01 4.0248311e-01 3.7465557e-01 4.6038945e-01 4.6053443e-01 3.6291292e-01 3.7703492e-01 3.7702914e-01 5.2744561e-01 4.2898757e-01 3.8178676e-01 4.0761255e-01 4.6557959e-01 3.4846205e-01 3.7087965e-01 3.6870032e-01 3.2740185e-01 3.2070546e-01 4.4660679e-01 3.5633353e-01 4.1573756e-01 3.2160319e-01 4.5525495e-01 3.4414484e-01 4.4510906e-01 4.0053809e-01 3.9779009e-01 3.7261777e-01 3.1255985e-01 3.4249381e-01 4.0450836e-01 3.1773210e-01 4.2666426e-01 4.1685273e-01 3.9886436e-01 3.5618753e-01 3.9691207e-01 3.4850257e-01 3.6675459e-01 3.6731925e-01 1.9628524e-01 1.9595152e-01 2.3363495e-01 2.7477230e-01 2.4851118e-01 2.7084921e-01 2.1685944e-01 1.7678722e-01 2.2636857e-01 2.2599655e-01 2.5724256e-01 1.9993208e-01 2.4854721e-01 2.6607935e-01 1.4078995e-01 1.8369551e-01 2.6097312e-01 2.1228442e-01 3.2508389e-01 2.2103528e-01 2.7346255e-01 1.8624671e-01 3.3183707e-01 2.6996197e-01 1.9987779e-01 1.9682726e-01 2.5462868e-01 2.7249816e-01 2.4805238e-01 1.5523356e-01 2.2463473e-01 2.0803519e-01 1.9245485e-01 3.6364465e-01 2.7666661e-01 1.9319723e-01 2.1887484e-01 2.8382186e-01 1.9489313e-01 2.4750809e-01 2.8994226e-01 2.4123726e-01 2.1680288e-01 1.8634448e-01 2.4506974e-01 2.0223799e-01 2.1557050e-01 2.0677515e-01 1.2326853e-01 2.1346465e-01 4.6321322e-01 4.0354170e-01 3.7970298e-01 3.9803381e-01 4.2400584e-01 4.2423988e-01 4.1474064e-01 4.0481837e-01 4.3422436e-01 3.5345426e-01 2.8656464e-01 3.7821934e-01 3.5073976e-01 4.3506541e-01 4.3461895e-01 3.3997143e-01 3.5549675e-01 3.5686166e-01 5.0021759e-01 4.0411514e-01 3.5805390e-01 3.8499293e-01 4.4048074e-01 3.2475847e-01 3.4952686e-01 3.4727706e-01 3.0464816e-01 2.9991017e-01 4.2212289e-01 3.3451084e-01 3.9105629e-01 3.0183284e-01 4.3015090e-01 3.2308204e-01 4.2396798e-01 3.7459262e-01 3.7639485e-01 3.5210962e-01 2.9201270e-01 3.1907654e-01 3.7972706e-01 2.9306033e-01 4.0354170e-01 3.9347753e-01 3.7503434e-01 3.3106203e-01 3.7117506e-01 3.2561211e-01 3.4620183e-01 3.4718282e-01 5.4794269e-04 1.8595150e-03 7.6486933e-03 3.6709934e-03 1.1297771e-02 3.2211024e-03 9.3536855e-04 1.2319946e-03 2.8277178e-03 4.9162548e-03 4.5756064e-04 4.5051431e-03 8.2041162e-03 5.0174936e-03 3.6228961e-04 1.1821527e-02 2.0977093e-03 2.1132418e-02 9.2067605e-04 1.2006919e-02 4.4257629e-04 2.0287770e-02 9.6871594e-03 3.6190304e-05 1.5767395e-04 4.3807979e-03 7.0604016e-03 4.2468409e-03 2.9914879e-03 1.0695136e-03 1.8996353e-04 2.2349983e-05 3.2007300e-02 1.8626112e-02 5.9280137e-03 7.1455899e-04 1.0704644e-02 4.3625889e-03 3.3835317e-03 1.4689427e-02 5.0222514e-03 5.6899707e-04 1.6818673e-04 4.5805421e-03 5.6585758e-03 3.2371570e-03 3.2354233e-04 1.1207565e-02 1.3610741e-03 7.1737216e-02 4.4570224e-02 3.4818230e-02 4.5037397e-02 5.2043753e-02 5.1252208e-02 5.2740741e-02 4.4819381e-02 5.4844272e-02 2.7492078e-02 9.9689819e-03 3.4289978e-02 2.5632216e-02 5.5069559e-02 5.4817042e-02 2.2717491e-02 2.9451557e-02 3.3085492e-02 8.2968826e-02 4.3268668e-02 2.7878625e-02 3.8225012e-02 5.7392372e-02 1.8533113e-02 2.7752880e-02 2.6863838e-02 1.3522246e-02 1.3720834e-02 5.0366251e-02 2.2136217e-02 3.8620607e-02 1.6104597e-02 5.3184340e-02 1.9805362e-02 5.7449954e-02 3.4065200e-02 3.7316903e-02 3.0490470e-02 1.2067932e-02 1.7032969e-02 3.4772493e-02 1.3995163e-02 4.4570224e-02 4.0370599e-02 3.3379869e-02 2.1584097e-02 3.2788169e-02 1.8689520e-02 2.8313400e-02 2.9690702e-02 2.1810130e-03 9.0584977e-03 5.0419708e-03 8.6169391e-03 1.3497185e-03 5.5621011e-04 1.5626898e-03 1.4715788e-03 6.4159866e-03 2.8759099e-05 6.7456588e-03 6.5333041e-03 5.4642837e-03 1.4108585e-03 8.4463171e-03 6.8795048e-04 2.4580787e-02 1.0388021e-03 9.2286561e-03 1.7639378e-03 2.1069750e-02 7.6032385e-03 7.9175727e-04 1.2932915e-03 5.5725803e-03 7.6219263e-03 3.4673161e-03 4.2795834e-03 1.7380404e-03 7.6483144e-04 5.0584546e-04 3.0216137e-02 1.4096242e-02 2.8861882e-03 1.0548294e-03 1.3430225e-02 1.8234348e-03 3.6876972e-03 1.2061426e-02 3.2511669e-03 1.1268214e-03 9.2690858e-04 3.2976984e-03 2.6938518e-03 1.3276664e-03 2.7368625e-04 1.3465991e-02 4.6822375e-04 6.8703048e-02 4.3340061e-02 3.5237451e-02 4.2511976e-02 5.0937508e-02 5.0961712e-02 4.9575019e-02 4.3743233e-02 5.5024281e-02 2.6603107e-02 9.8022959e-03 3.4840370e-02 2.6494597e-02 5.5508568e-02 5.5916268e-02 2.2800218e-02 2.7686924e-02 2.9943438e-02 8.4266289e-02 4.3880838e-02 2.8349604e-02 3.6881146e-02 5.7478275e-02 1.9879185e-02 2.5944410e-02 2.5180647e-02 1.4399125e-02 1.2641568e-02 5.0169037e-02 2.1180767e-02 3.9323276e-02 1.3938661e-02 5.3485998e-02 1.8367828e-02 5.3859405e-02 3.6620288e-02 3.4933732e-02 2.7786245e-02 1.0959937e-02 1.8222006e-02 3.5858197e-02 1.7515874e-02 4.3340061e-02 3.9619354e-02 3.3535832e-02 2.4403195e-02 3.5188163e-02 1.9107255e-02 2.5791231e-02 2.6740983e-02 2.3644893e-03 7.3259797e-04 5.5696730e-03 2.5707992e-03 4.5988577e-03 6.5028014e-05 1.3580837e-03 1.2238983e-03 1.7109321e-03 1.8714646e-03 2.9944669e-03 1.2905109e-02 3.6725511e-03 6.9487479e-03 1.9516582e-03 1.2369689e-02 2.1307052e-04 6.0423668e-03 3.5751225e-03 1.0028727e-02 4.0861108e-03 1.5902610e-03 2.1378325e-03 8.2628456e-04 1.7251178e-03 8.0406810e-04 9.4788056e-03 1.5999623e-04 8.7509151e-04 2.2560004e-03 1.8732619e-02 1.2379328e-02 7.5803848e-03 2.7223442e-04 5.1089250e-03 5.8562851e-03 2.2798360e-04 7.3027135e-03 2.0605789e-03 3.8651941e-04 3.1125030e-03 1.3286042e-03 6.3896783e-03 2.7088758e-03 9.7424018e-04 2.1879745e-02 1.1792881e-03 5.1158538e-02 2.8393852e-02 2.0746802e-02 2.9099880e-02 3.4416089e-02 3.3763806e-02 3.5540899e-02 2.8575694e-02 3.6757319e-02 1.5144171e-02 3.2315336e-03 2.0363783e-02 1.3898176e-02 3.6986917e-02 3.6943012e-02 1.1630303e-02 1.6809451e-02 2.0213112e-02 6.0723696e-02 2.7441217e-02 1.5470812e-02 2.3398093e-02 3.8846172e-02 9.0112370e-03 1.5570624e-02 1.4874310e-02 5.5171614e-03 5.6710746e-03 3.3048406e-02 1.1270408e-02 2.3776077e-02 7.7482583e-03 3.5413096e-02 9.7831561e-03 3.9569593e-02 2.1047269e-02 2.3004495e-02 1.8015778e-02 4.6822715e-03 7.9260822e-03 2.0880056e-02 7.9428824e-03 2.8393852e-02 2.5015882e-02 1.9595645e-02 1.2073748e-02 1.9972960e-02 8.8353740e-03 1.6316616e-02 1.7585650e-02 7.5921246e-04 7.6581519e-03 8.7602132e-03 1.3285408e-02 3.1081233e-03 6.1183864e-03 3.4258252e-04 8.0693053e-03 1.1527108e-03 4.3989827e-03 2.4770294e-02 1.0297780e-02 1.0716436e-02 8.0921947e-03 4.0468338e-03 3.9682629e-03 8.0100500e-03 9.6963228e-03 3.4263963e-03 5.5915243e-03 6.8271736e-03 7.3405400e-03 4.5375223e-04 3.3086446e-04 2.9090971e-03 1.8954919e-02 3.0536401e-03 5.4665114e-03 8.4934379e-03 1.2174442e-02 1.6139108e-02 1.7445625e-02 4.0248005e-03 8.4214697e-04 1.4968032e-02 1.3210674e-03 7.6674238e-03 5.8292743e-03 4.1363018e-03 9.7236406e-03 4.2254644e-03 1.5250051e-02 9.0649565e-03 6.2807525e-03 3.4303230e-02 6.6673397e-03 3.8666536e-02 1.8227060e-02 1.0732501e-02 2.0722480e-02 2.2627004e-02 2.1137328e-02 2.6644819e-02 1.8156140e-02 2.2956019e-02 8.4429075e-03 1.3075172e-03 1.0338488e-02 5.7120788e-03 2.2877982e-02 2.2249653e-02 5.0348740e-03 1.0858478e-02 1.5670368e-02 4.1328272e-02 1.5415087e-02 7.0760309e-03 1.4735153e-02 2.4690692e-02 2.4709117e-03 1.0136092e-02 9.4846153e-03 1.0671740e-03 3.5238125e-03 2.0483172e-02 6.1432951e-03 1.2637418e-02 6.5903261e-03 2.1786492e-02 6.0819601e-03 3.0486925e-02 9.5174641e-03 1.6103409e-02 1.3353819e-02 3.2356456e-03 1.9926682e-03 1.0243487e-02 2.2538296e-03 1.8227060e-02 1.5108364e-02 1.0188754e-02 3.7627514e-03 8.8362152e-03 3.0791096e-03 1.1920070e-02 1.3588585e-02 8.0203401e-03 5.9881494e-03 7.9998519e-03 1.0330180e-03 3.9563353e-03 9.0962406e-05 4.3155161e-03 3.4798297e-04 4.5913809e-03 1.6934319e-02 5.4778348e-03 1.0415690e-02 5.0724002e-03 7.4143773e-03 1.5625174e-03 8.5090504e-03 5.0363885e-03 7.2978538e-03 5.9687085e-03 3.0800386e-03 3.3854665e-03 6.0369763e-05 9.7766526e-04 2.1106407e-03 1.2150960e-02 8.7050457e-04 2.2450596e-03 4.2656078e-03 1.7573546e-02 1.6541615e-02 1.3010703e-02 1.4863348e-03 2.0318224e-03 1.0715058e-02 5.1959240e-04 9.1091800e-03 4.5577281e-03 1.4679901e-03 5.0882044e-03 3.2208315e-03 1.1416637e-02 6.2084512e-03 2.9761078e-03 2.5010280e-02 3.7556543e-03 4.8641699e-02 2.5613136e-02 1.7022941e-02 2.7738185e-02 3.0983818e-02 2.9540677e-02 3.4381880e-02 2.5612023e-02 3.1832087e-02 1.3388731e-02 2.7364434e-03 1.6556686e-02 1.0555947e-02 3.1795721e-02 3.1144834e-02 9.3248236e-03 1.5850102e-02 2.0586917e-02 5.3133864e-02 2.2885657e-02 1.2291162e-02 2.1220606e-02 3.3851933e-02 5.9611654e-03 1.4821288e-02 1.4065156e-02 3.4935277e-03 5.6486577e-03 2.8790647e-02 1.0114487e-02 1.9481208e-02 8.7344459e-03 3.0476411e-02 9.4253713e-03 3.8601009e-02 1.5492941e-02 2.2081481e-02 1.8082534e-02 4.9261084e-03 5.1866248e-03 1.6531969e-02 3.8794099e-03 2.5613136e-02 2.2037756e-02 1.6246851e-02 7.5034139e-03 1.4652134e-02 6.6254167e-03 1.6367612e-02 1.8037074e-02 3.5963937e-03 1.3253217e-02 6.2726815e-03 2.9800542e-03 8.1679414e-03 8.1170586e-03 1.1643531e-02 4.8148791e-04 2.7366574e-02 1.5666050e-02 3.5602925e-04 4.6080605e-03 1.9717886e-02 6.2846724e-03 1.0858138e-05 1.6108248e-02 9.2526017e-03 1.6342536e-04 1.1289374e-02 1.3182521e-02 7.1086671e-03 4.8107615e-03 2.1505038e-03 2.4867835e-02 7.4585494e-03 9.3457001e-03 1.1859292e-02 8.6506765e-03 1.5825531e-03 7.6287797e-03 7.1464196e-03 1.3469318e-02 7.0587993e-03 4.6011946e-03 3.8423475e-04 1.2933991e-03 8.0463849e-03 1.4044313e-02 1.5554975e-03 5.8246512e-03 3.7445923e-03 7.8179143e-03 4.3383609e-02 5.1292419e-03 3.1208966e-02 1.7106674e-02 1.5590525e-02 1.4711786e-02 2.2118312e-02 2.3677515e-02 1.8355265e-02 1.7620984e-02 2.7322237e-02 8.2125300e-03 3.2025084e-03 1.5673958e-02 1.1993026e-02 2.8215754e-02 3.0043744e-02 8.3225318e-03 7.3692394e-03 7.0283195e-03 5.0297559e-02 2.1175797e-02 1.1957606e-02 1.3050611e-02 2.8749586e-02 1.0337000e-02 6.4346633e-03 6.2339245e-03 7.0135662e-03 2.1302546e-03 2.3356399e-02 5.5096838e-03 1.8637999e-02 1.1462623e-03 2.6577654e-02 3.5495923e-03 2.0668821e-02 2.2280093e-02 1.0461671e-02 6.3164945e-03 1.6640428e-03 9.2261377e-03 1.7584245e-02 1.7910761e-02 1.7106674e-02 1.5703153e-02 1.4029303e-02 1.7152691e-02 2.0996496e-02 7.4959989e-03 5.5175599e-03 5.5902559e-03 3.2004692e-03 2.3419030e-03 2.3799055e-04 7.0894399e-03 1.3013007e-03 8.8089668e-03 2.9046172e-03 1.1317768e-02 5.4246845e-03 3.1331888e-03 1.2023171e-04 2.4596565e-02 1.8369557e-03 3.9714617e-03 5.9789699e-03 1.7350836e-02 3.3069650e-03 3.5250221e-03 4.6752456e-03 5.9850395e-03 6.3682068e-03 1.7841601e-03 1.0289989e-02 3.0278347e-03 2.8250687e-03 3.3130538e-03 2.2020473e-02 6.7612416e-03 1.5121522e-03 2.2413165e-03 1.4397994e-02 9.1427197e-04 3.3482085e-03 6.1881321e-03 7.4537620e-04 2.6935839e-03 4.4237033e-03 1.1678481e-03 9.0068892e-04 2.9616334e-06 1.6314282e-03 2.2817755e-02 4.4730602e-04 5.5111404e-02 3.4158218e-02 2.9021577e-02 3.2043073e-02 4.1089749e-02 4.2083473e-02 3.7707137e-02 3.4692829e-02 4.6329738e-02 1.9906109e-02 6.9820129e-03 2.8847990e-02 2.2051442e-02 4.7099521e-02 4.8343924e-02 1.7860817e-02 1.9868896e-02 2.0488578e-02 7.4490873e-02 3.6906910e-02 2.3107397e-02 2.8319511e-02 4.8426947e-02 1.7182411e-02 1.8331671e-02 1.7811306e-02 1.2023707e-02 8.1012404e-03 4.1487060e-02 1.5227136e-02 3.2990763e-02 8.0392167e-03 4.5098943e-02 1.2350504e-02 4.1149609e-02 3.3318195e-02 2.5517275e-02 1.9030633e-02 6.7530681e-03 1.5581926e-02 3.0469465e-02 1.9100479e-02 3.4158218e-02 3.1415243e-02 2.7190491e-02 2.3321177e-02 3.1828581e-02 1.5212907e-02 1.7498443e-02 1.7919743e-02 3.6042298e-03 3.7468828e-03 9.7768723e-03 7.8664808e-04 9.4997776e-03 1.0849175e-02 2.5690262e-03 9.8725606e-04 1.2645853e-02 2.2464135e-03 3.0594913e-02 2.8398433e-03 1.3996699e-02 1.4253747e-03 2.8011999e-02 1.2147431e-02 1.3365379e-03 1.5899927e-03 8.8722552e-03 1.1913349e-02 6.7897739e-03 2.1135064e-03 3.6254453e-03 1.7898196e-03 6.9240260e-04 3.8891340e-02 1.9082524e-02 3.5297395e-03 2.7024302e-03 1.7766622e-02 2.5342822e-03 6.8092652e-03 1.7593080e-02 6.3527044e-03 2.6240465e-03 7.1495011e-04 6.5371413e-03 3.8357773e-03 3.1136154e-03 1.3436442e-03 8.9702416e-03 2.0253115e-03 8.1348350e-02 5.3552444e-02 4.4248656e-02 5.2648527e-02 6.1923652e-02 6.1838703e-02 6.0414517e-02 5.3985372e-02 6.6201925e-02 3.4742321e-02 1.4883289e-02 4.3767758e-02 3.4228373e-02 6.6672589e-02 6.6939218e-02 3.0219175e-02 3.6020463e-02 3.8455365e-02 9.7619080e-02 5.3827294e-02 3.6463335e-02 4.6373140e-02 6.8906148e-02 2.6398982e-02 3.4032020e-02 3.3159361e-02 2.0120628e-02 1.8469842e-02 6.0950543e-02 2.8524017e-02 4.8737718e-02 1.9976319e-02 6.4489083e-02 2.5275791e-02 6.5080438e-02 4.4969016e-02 4.4191042e-02 3.6066964e-02 1.6430448e-02 2.4524789e-02 4.4743887e-02 2.2062365e-02 5.3552444e-02 4.9370398e-02 4.2403953e-02 3.0850071e-02 4.3434971e-02 2.5846885e-02 3.3807321e-02 3.4832107e-02 1.2988107e-03 1.6703175e-03 1.1675843e-03 2.1414615e-03 3.6300242e-03 1.1143098e-02 2.7878082e-03 7.4699291e-03 1.6417856e-03 1.3833381e-02 5.5119833e-05 6.7870415e-03 2.7321459e-03 1.1691818e-02 4.7830259e-03 1.0265050e-03 1.5056614e-03 1.2372212e-03 2.4522309e-03 1.1336677e-03 8.0050923e-03 5.6870746e-05 4.6915622e-04 1.5562032e-03 2.0887194e-02 1.3125417e-02 6.8837382e-03 7.1162950e-05 5.9522504e-03 5.2043728e-03 5.3649750e-04 8.3200456e-03 2.2696632e-03 1.4322584e-04 2.2876100e-03 1.6070427e-03 5.8684470e-03 2.4558869e-03 5.5570590e-04 1.9651663e-02 8.9172519e-04 5.4659464e-02 3.1114613e-02 2.3119551e-02 3.1736271e-02 3.7415588e-02 3.6761852e-02 3.8397207e-02 3.1313890e-02 3.9883303e-02 1.7150840e-02 4.2007421e-03 2.2713095e-02 1.5842502e-02 4.0120080e-02 4.0057089e-02 1.3428356e-02 1.8845203e-02 2.2251079e-02 6.4673609e-02 3.0152373e-02 1.7530451e-02 2.5859899e-02 4.2056336e-02 1.0552527e-02 1.7518114e-02 1.6789150e-02 6.7575680e-03 6.8601014e-03 3.6016991e-02 1.2994930e-02 2.6303908e-02 8.9623653e-03 3.8482980e-02 1.1333705e-02 4.2542187e-02 2.3287141e-02 2.5337550e-02 1.9991634e-02 5.7451264e-03 9.3841364e-03 2.3239540e-02 8.8973019e-03 3.1114613e-02 2.7595638e-02 2.1905943e-02 1.3658827e-02 2.2169613e-02 1.0410758e-02 1.8207584e-02 1.9484294e-02 4.8008453e-03 1.2650854e-03 6.4006179e-03 1.8900850e-03 1.2501460e-02 5.1363105e-03 3.0955001e-03 2.4385845e-04 2.0020418e-02 1.0205842e-03 3.3467158e-03 5.5033857e-03 1.3788482e-02 2.4101593e-03 2.9461849e-03 4.0056193e-03 3.8916824e-03 4.1559722e-03 7.4799809e-04 1.0679921e-02 1.8732675e-03 2.1213449e-03 3.0477499e-03 1.9047032e-02 6.9834653e-03 2.9438547e-03 1.3758132e-03 1.0992441e-02 2.0426183e-03 1.8183256e-03 5.1275661e-03 3.4870074e-04 1.7800086e-03 4.1941671e-03 4.4278656e-04 2.0594764e-03 2.9165015e-04 1.2452133e-03 2.3762069e-02 2.9165015e-04 5.0966362e-02 3.0166832e-02 2.4694798e-02 2.8788397e-02 3.6671707e-02 3.7274280e-02 3.4472569e-02 3.0604199e-02 4.1125938e-02 1.6692997e-02 4.7977197e-03 2.4489085e-02 1.8077937e-02 4.1761735e-02 4.2713992e-02 1.4455884e-02 1.7039782e-02 1.8322490e-02 6.7670508e-02 3.2041093e-02 1.9169462e-02 2.4724400e-02 4.3157837e-02 1.3510623e-02 1.5640518e-02 1.5102883e-02 8.9767687e-03 6.0642978e-03 3.6671707e-02 1.2419694e-02 2.8323093e-02 6.4935421e-03 3.9910361e-02 1.0006286e-02 3.7967777e-02 2.8141888e-02 2.2594035e-02 1.6734859e-02 4.8977754e-03 1.2095984e-02 2.5839912e-02 1.5166518e-02 3.0166832e-02 2.7378800e-02 2.3072794e-02 1.8885101e-02 2.6783663e-02 1.1941964e-02 1.5226991e-02 1.5844953e-02 5.5898027e-03 3.6211515e-04 4.6884489e-03 1.9469863e-02 6.9494812e-03 1.0856564e-02 6.2070186e-03 5.9174289e-03 2.3319364e-03 8.6215938e-03 6.4261295e-03 5.9157019e-03 6.0481987e-03 4.2268867e-03 4.5610911e-03 4.8970997e-05 6.8799458e-04 2.4420024e-03 1.4255275e-02 1.5079078e-03 3.2366850e-03 5.6006336e-03 1.5957034e-02 1.6871464e-02 1.4787237e-02 2.2762765e-03 1.3333689e-03 1.2378081e-02 7.3736127e-04 8.8932355e-03 5.1508306e-03 2.2779875e-03 6.5293055e-03 3.6737889e-03 1.2985539e-02 7.3417742e-03 4.0613774e-03 2.7837547e-02 4.7997557e-03 4.5639701e-02 2.3278576e-02 1.4877176e-02 2.5663407e-02 2.8314352e-02 2.6769516e-02 3.2135703e-02 2.3238033e-02 2.8854470e-02 1.1827077e-02 2.2644401e-03 1.4421001e-02 8.8429015e-03 2.8776903e-02 2.8063687e-02 7.8778602e-03 1.4365876e-02 1.9273282e-02 4.9067035e-02 2.0328263e-02 1.0496416e-02 1.9196637e-02 3.0789735e-02 4.6457607e-03 1.3443289e-02 1.2708604e-02 2.5804695e-03 5.0424172e-03 2.6041403e-02 8.8829912e-03 1.7122028e-02 8.2367466e-03 2.7547637e-02 8.4529986e-03 3.6274794e-02 1.3225786e-02 2.0335647e-02 1.6784857e-02 4.4669319e-03 3.9860599e-03 1.4316384e-02 2.9523808e-03 2.3278576e-02 1.9803941e-02 1.4205949e-02 5.9492702e-03 1.2454271e-02 5.3895801e-03 1.5143895e-02 1.6858271e-02 5.9387347e-03 5.9571758e-03 6.0526515e-03 1.4146691e-03 8.1320415e-03 6.3420687e-04 2.2943426e-02 7.2217865e-04 8.7156753e-03 1.7123420e-03 1.9617600e-02 7.0385795e-03 6.4044399e-04 1.1390332e-03 4.8019256e-03 6.7384180e-03 2.9679315e-03 4.6026472e-03 1.3268878e-03 5.4152853e-04 4.6516773e-04 2.8772311e-02 1.3783757e-02 3.2459159e-03 7.3821107e-04 1.2234521e-02 2.0992860e-03 3.0774015e-03 1.1372571e-02 2.9352447e-03 8.1022588e-04 9.2842537e-04 2.8855444e-03 2.9418595e-03 1.2977062e-03 1.2869337e-04 1.4124612e-02 3.4246729e-04 6.6626445e-02 4.1505551e-02 3.3416051e-02 4.0874061e-02 4.8928444e-02 4.8860648e-02 4.7883828e-02 4.1881126e-02 5.2796241e-02 2.5141882e-02 8.8605790e-03 3.3017625e-02 2.4870522e-02 5.3247026e-02 5.3590923e-02 2.1349209e-02 2.6308756e-02 2.8721666e-02 8.1439460e-02 4.1842449e-02 2.6703197e-02 3.5208876e-02 5.5212555e-02 1.8433774e-02 2.4622301e-02 2.3863121e-02 1.3181398e-02 1.1675955e-02 4.8074316e-02 1.9890418e-02 3.7380285e-02 1.3082557e-02 5.1276398e-02 1.7233265e-02 5.2150081e-02 3.4634218e-02 3.3454504e-02 2.6550201e-02 1.0070918e-02 1.6842626e-02 3.3968952e-02 1.6166125e-02 4.1505551e-02 3.7811539e-02 3.1780349e-02 2.2766214e-02 3.3244526e-02 1.7747224e-02 2.4583452e-02 2.5577750e-02 7.4058632e-03 1.7632325e-02 5.8672157e-03 1.4554963e-02 7.5139440e-03 6.3063306e-03 2.8227254e-03 1.2216172e-02 5.2171506e-03 8.3411571e-03 9.1198919e-03 3.7613430e-03 3.7527482e-03 5.6979631e-04 2.0412760e-03 4.1677011e-03 1.2238157e-02 1.7043766e-03 3.0984992e-03 5.1374687e-03 2.0730806e-02 2.1628161e-02 1.6669142e-02 2.5627983e-03 1.3966031e-03 1.3985502e-02 1.7150229e-03 1.2743810e-02 7.3773848e-03 2.3644296e-03 5.7186323e-03 5.6669191e-03 1.5046711e-02 9.0550035e-03 4.3221940e-03 2.4177800e-02 5.7926331e-03 5.2977640e-02 2.8412846e-02 1.8464622e-02 3.1548301e-02 3.3726407e-02 3.1637531e-02 3.8729422e-02 2.8292534e-02 3.3574657e-02 1.5809867e-02 4.4178873e-03 1.7890807e-02 1.1580028e-02 3.3334020e-02 3.2156672e-02 1.0943899e-02 1.8967943e-02 2.4791881e-02 5.4103864e-02 2.4225163e-02 1.3643641e-02 2.4071431e-02 3.5681100e-02 6.5373199e-03 1.7959936e-02 1.7099713e-02 4.3929724e-03 8.0887873e-03 3.0809355e-02 1.2543658e-02 2.0721585e-02 1.2037199e-02 3.2114506e-02 1.2207760e-02 4.3300211e-02 1.5218252e-02 2.5733556e-02 2.1932604e-02 7.3680112e-03 5.8739609e-03 1.7443010e-02 2.6299180e-03 2.8412846e-02 2.4437667e-02 1.7887656e-02 6.9159049e-03 1.4494165e-02 7.9434468e-03 2.0060731e-02 2.2068579e-02 2.3875094e-02 1.2000415e-02 1.3948342e-03 3.4546351e-03 1.4939730e-02 3.7950422e-03 6.0175173e-04 1.2211196e-02 7.0052335e-03 9.1256063e-05 8.0336825e-03 9.5484059e-03 3.8945506e-03 2.3206010e-03 7.0732153e-04 2.0727990e-02 4.4889370e-03 6.3258821e-03 8.7927798e-03 9.0069682e-03 3.7952179e-03 7.8092546e-03 4.4335690e-03 9.0550736e-03 6.7946167e-03 2.1531805e-03 9.6426638e-04 7.0770423e-04 5.1150602e-03 1.0670446e-02 5.5187206e-04 6.0114634e-03 3.0771240e-03 5.3655604e-03 3.8039285e-02 3.5100982e-03 3.3392676e-02 1.7228333e-02 1.4023464e-02 1.5984642e-02 2.2267037e-02 2.3075907e-02 2.0330300e-02 1.7609739e-02 2.6354220e-02 7.6657981e-03 1.4938436e-03 1.3975046e-02 9.8087979e-03 2.7013992e-02 2.8227679e-02 6.7815824e-03 7.6426994e-03 8.5739542e-03 4.8734857e-02 1.9601188e-02 1.0188446e-02 1.3147209e-02 2.7911001e-02 7.5145131e-03 6.7053137e-03 6.3732135e-03 4.4764490e-03 1.3642012e-03 2.2654181e-02 4.8866188e-03 1.6888522e-02 1.3930577e-03 2.5469441e-02 3.2860894e-03 2.3095694e-02 1.8694362e-02 1.1451986e-02 7.4272413e-03 8.6465452e-04 6.5073035e-03 1.5400191e-02 1.2824348e-02 1.7228333e-02 1.5313622e-02 1.2672619e-02 1.3006211e-02 1.7530867e-02 5.5400420e-03 6.4187909e-03 6.8900377e-03 3.1968437e-03 2.6175875e-02 9.5689725e-03 4.4766639e-02 9.9845360e-03 2.8418681e-02 3.6870693e-03 4.5253718e-02 2.5815239e-02 5.6468536e-03 5.2271680e-03 1.8578768e-02 2.3906603e-02 1.7414675e-02 6.6309054e-04 1.0701959e-02 7.1563943e-03 4.3943049e-03 6.0754711e-02 3.4699507e-02 9.6990814e-03 9.4374842e-03 2.8881695e-02 8.6238198e-03 1.6549411e-02 3.3492594e-02 1.6963829e-02 8.9575119e-03 3.4839312e-03 1.7214511e-02 1.0985852e-02 1.1115876e-02 7.0774378e-03 2.3223923e-03 9.1191389e-03 1.1169736e-01 7.8250518e-02 6.5808362e-02 7.7763348e-02 8.8114611e-02 8.7449743e-02 8.7215232e-02 7.8675005e-02 9.2203874e-02 5.5132383e-02 2.8794481e-02 6.5100824e-02 5.3025891e-02 9.2531519e-02 9.2220151e-02 4.8731252e-02 5.7186075e-02 6.0580024e-02 1.2745253e-01 7.7174441e-02 5.6198920e-02 6.9678402e-02 9.5449745e-02 4.2538093e-02 5.4722713e-02 5.3576276e-02 3.4860888e-02 3.4291475e-02 8.6329226e-02 4.7343142e-02 7.0978985e-02 3.6695928e-02 9.0088005e-02 4.3430772e-02 9.2828505e-02 6.4239353e-02 6.7481588e-02 5.7536867e-02 3.1542812e-02 4.0297150e-02 6.5753742e-02 3.3241661e-02 7.8250518e-02 7.2933055e-02 6.3794057e-02 4.6178781e-02 6.2571051e-02 4.2843100e-02 5.4666081e-02 5.6027673e-02 1.6139749e-02 3.9412782e-03 2.4265145e-02 2.3891707e-03 1.6498373e-02 4.1418612e-05 2.4988702e-02 1.3783039e-02 4.3146851e-04 2.5122323e-04 6.4815288e-03 1.0052630e-02 7.0587637e-03 1.3669961e-03 2.4020339e-03 9.7331181e-04 2.7171014e-04 3.8783427e-02 2.3881244e-02 7.7285447e-03 2.0010737e-03 1.2962382e-02 6.0316172e-03 5.6775409e-03 1.9642810e-02 8.0347010e-03 1.6772041e-03 5.1201506e-05 7.5139419e-03 7.7685816e-03 5.4104161e-03 1.3577183e-03 7.6646931e-03 3.0214900e-03 8.1621829e-02 5.2182884e-02 4.1040324e-02 5.3055858e-02 6.0133087e-02 5.8980137e-02 6.1457708e-02 5.2397706e-02 6.2608146e-02 3.3589093e-02 1.3750660e-02 4.0409320e-02 3.0837807e-02 6.2732754e-02 6.2152008e-02 2.7986481e-02 3.5988306e-02 4.0227814e-02 9.1799153e-02 5.0051858e-02 3.3478326e-02 4.5393111e-02 6.5357720e-02 2.2750138e-02 3.4139497e-02 3.3132950e-02 1.7367166e-02 1.8328224e-02 5.7997026e-02 2.7720666e-02 4.5013892e-02 2.1236242e-02 6.0787869e-02 2.5266646e-02 6.6573172e-02 3.9086224e-02 4.4693577e-02 3.7322864e-02 1.6444309e-02 2.1159286e-02 4.0674593e-02 1.6113197e-02 5.2182884e-02 4.7503868e-02 3.9598661e-02 2.5231075e-02 3.7795470e-02 2.3382629e-02 3.4903444e-02 3.6481922e-02 4.3266011e-03 2.5120283e-02 7.2104610e-03 3.6362605e-04 1.6818393e-02 1.3224351e-02 8.9751703e-04 1.2039448e-02 1.4078561e-02 9.5477546e-03 7.2983976e-03 3.1999143e-03 2.4639885e-02 8.8187561e-03 1.0207680e-02 1.2236717e-02 1.1661588e-02 8.0001293e-04 5.7297070e-03 8.1532898e-03 1.7517743e-02 5.5505771e-03 6.3202290e-03 1.2261175e-03 1.5275601e-03 9.1326114e-03 1.4417917e-02 2.2056571e-03 4.2297788e-03 3.2218738e-03 8.2583968e-03 4.2679879e-02 5.2144338e-03 3.5325690e-02 2.1286357e-02 2.0340751e-02 1.7932964e-02 2.6773752e-02 2.8858059e-02 2.1473619e-02 2.1925037e-02 3.2987864e-02 1.1596147e-02 5.5679058e-03 2.0475433e-02 1.6418368e-02 3.4058657e-02 3.6285268e-02 1.2036020e-02 1.0227865e-02 8.9974606e-03 5.7847652e-02 2.6531721e-02 1.6295053e-02 1.6788576e-02 3.4473710e-02 1.4498141e-02 9.1389529e-03 8.9727022e-03 1.0441422e-02 4.2212624e-03 2.8555402e-02 8.4473824e-03 2.3791713e-02 2.5698702e-03 3.2242281e-02 5.9266749e-03 2.3676462e-02 2.8216759e-02 1.3343464e-02 8.4809495e-03 3.5554866e-03 1.3166972e-02 2.2745344e-02 2.2629651e-02 2.1286357e-02 1.9992085e-02 1.8520730e-02 2.2324446e-02 2.6771848e-02 1.1107369e-02 7.6788410e-03 7.4852977e-03 2.3512869e-02 1.1702196e-03 5.0486445e-03 4.4067902e-03 1.7493736e-02 4.0658633e-03 2.3529372e-03 3.3047066e-03 5.2094902e-03 6.0430183e-03 1.7805903e-03 8.3604250e-03 2.1645857e-03 1.8214590e-03 2.1737913e-03 2.3530298e-02 8.5714286e-03 1.8444368e-03 1.4565864e-03 1.3243081e-02 1.0630397e-03 2.8808992e-03 7.3652636e-03 1.0835317e-03 1.7933322e-03 3.0961279e-03 1.3436220e-03 1.3043704e-03 1.2482375e-04 8.8034137e-04 2.0043242e-02 1.2482375e-04 5.7954445e-02 3.5775683e-02 2.9742194e-02 3.4149795e-02 4.2824229e-02 4.3477315e-02 4.0214177e-02 3.6256651e-02 4.7605297e-02 2.0950874e-02 7.1042975e-03 2.9499916e-02 2.2329817e-02 4.8271691e-02 4.9230028e-02 1.8375611e-02 2.1296157e-02 2.2492082e-02 7.5802989e-02 3.7751582e-02 2.3617894e-02 2.9827991e-02 4.9792717e-02 1.7017775e-02 1.9724142e-02 1.9131907e-02 1.1873908e-02 8.7349825e-03 4.2824229e-02 1.6130090e-02 3.3687060e-02 9.1410950e-03 4.6289887e-02 1.3350026e-02 4.3904542e-02 3.3071376e-02 2.7381594e-02 2.0813943e-02 7.3233676e-03 1.5432666e-02 3.0904955e-02 1.7682128e-02 3.5775683e-02 3.2747980e-02 2.7982984e-02 2.2571206e-02 3.1620085e-02 1.5454693e-02 1.9154732e-02 1.9759156e-02 1.5625666e-02 2.0014241e-02 2.2906319e-02 3.3689213e-03 1.6561417e-02 1.9555072e-02 1.9724522e-02 6.8229205e-03 6.0996359e-03 1.3507575e-02 3.5744409e-02 1.3348521e-02 1.7651623e-02 2.2506296e-02 1.4148535e-02 3.1413076e-02 3.8119216e-02 1.5501824e-02 1.7783197e-03 3.4445966e-02 9.9745771e-03 1.7822684e-02 1.8993068e-02 1.5436010e-02 2.3911299e-02 1.6070505e-02 3.4793519e-02 2.5109394e-02 1.9730191e-02 5.3384757e-02 2.0981999e-02 3.5016323e-02 1.5808551e-02 7.2216559e-03 2.1250521e-02 1.8323057e-02 1.5289849e-02 2.7077232e-02 1.5342317e-02 1.5450153e-02 9.5719689e-03 7.0769801e-03 6.7142336e-03 3.8618160e-03 1.4833874e-02 1.3052654e-02 5.5299114e-03 1.3477582e-02 2.0871841e-02 2.6745939e-02 9.5407500e-03 5.3018257e-03 1.4058965e-02 1.6863810e-02 2.0380823e-03 1.3353665e-02 1.2655783e-02 3.2775616e-03 9.7625272e-03 1.4632542e-02 9.0437643e-03 7.6711708e-03 1.4740530e-02 1.4381411e-02 1.0907741e-02 3.1026769e-02 2.6758954e-03 1.8148668e-02 1.8095332e-02 1.0256426e-02 2.3444102e-03 5.5327937e-03 1.0086149e-03 1.5808551e-02 1.2612237e-02 7.5482105e-03 2.3261323e-04 2.5482034e-03 4.2287654e-03 1.6814254e-02 1.9242327e-02 6.8098804e-03 2.4185222e-03 1.3095995e-02 4.9100577e-03 8.0319599e-04 1.3085229e-03 1.8113887e-03 3.1306373e-03 1.2541646e-03 7.2250359e-03 1.5182032e-04 3.2471009e-04 1.1793141e-03 2.2134336e-02 1.2798604e-02 5.8036245e-03 2.9068060e-05 7.1481800e-03 4.2574873e-03 8.5847073e-04 8.5715637e-03 2.1039195e-03 1.1389023e-04 1.8746094e-03 1.5895426e-03 4.9316123e-03 1.9257560e-03 2.7708506e-04 1.8515651e-02 5.3986259e-04 5.6637702e-02 3.2886175e-02 2.4967826e-02 3.3187187e-02 3.9414817e-02 3.8923256e-02 3.9880016e-02 3.3128964e-02 4.2231952e-02 1.8470852e-02 4.9097912e-03 2.4570551e-02 1.7467535e-02 4.2525770e-02 4.2580968e-02 1.4790908e-02 2.0011146e-02 2.3142926e-02 6.7845285e-02 3.2285576e-02 1.9161137e-02 2.7420216e-02 4.4447416e-02 1.1980855e-02 1.8611023e-02 1.7883360e-02 7.8729229e-03 7.5466400e-03 3.8175619e-02 1.4096206e-02 2.8321778e-02 9.4496873e-03 4.0815141e-02 1.2211823e-02 4.4024579e-02 2.5465922e-02 2.6596134e-02 2.0925904e-02 6.3340227e-03 1.0720439e-02 2.5211490e-02 1.0333158e-02 3.2886175e-02 2.9360405e-02 2.3656085e-02 1.5413665e-02 2.4285913e-02 1.1678199e-02 1.9116491e-02 2.0313205e-02 1.6950975e-02 9.2576768e-03 2.2830227e-04 1.1996475e-02 1.3943618e-02 7.5471408e-03 5.0950912e-03 2.4447813e-03 2.5903324e-02 8.0139448e-03 9.9879335e-03 1.2585436e-02 8.2754975e-03 1.4174352e-03 8.0478199e-03 7.7042954e-03 1.3901912e-02 7.5078674e-03 4.9957099e-03 2.9997761e-04 1.5395926e-03 8.6362248e-03 1.4833108e-02 1.8222710e-03 6.1957159e-03 4.1238914e-03 8.4102568e-03 4.4734160e-02 5.6076899e-03 3.0288189e-02 1.6597244e-02 1.5336169e-02 1.4117002e-02 2.1529085e-02 2.3159309e-02 1.7633168e-02 1.7119251e-02 2.6802924e-02 7.9632454e-03 3.3472740e-03 1.5438450e-02 1.1914773e-02 2.7716384e-02 2.9607261e-02 8.2241873e-03 7.0346123e-03 6.5727745e-03 4.9604200e-02 2.0828511e-02 1.1808642e-02 1.2615158e-02 2.8194719e-02 1.0429441e-02 6.1245969e-03 5.9452412e-03 7.1618546e-03 2.1261487e-03 2.2855826e-02 5.3452154e-03 1.8357871e-02 1.0397070e-03 2.6087088e-02 3.3990115e-03 1.9871685e-02 2.2251351e-02 9.9773797e-03 5.9192173e-03 1.6976055e-03 9.3317377e-03 1.7391404e-02 1.8375579e-02 1.6597244e-02 1.5280892e-02 1.3772451e-02 1.7356806e-02 2.0968489e-02 7.4978418e-03 5.1634523e-03 5.1963190e-03 2.4233623e-02 1.4077025e-02 4.3787020e-04 1.8512542e-04 6.0477386e-03 9.6703484e-03 7.1488601e-03 1.5477068e-03 2.2742281e-03 9.7171923e-04 3.9271863e-04 3.8509554e-02 2.4774335e-02 8.7360281e-03 1.9891111e-03 1.1995846e-02 6.8973897e-03 5.5019459e-03 1.9965157e-02 8.4152844e-03 1.6247783e-03 1.4531219e-04 7.7480972e-03 8.6972032e-03 5.9824611e-03 1.5176827e-03 7.8567259e-03 3.3493021e-03 8.1204385e-02 5.1575806e-02 4.0135980e-02 5.2803481e-02 5.9400299e-02 5.8042463e-02 6.1291964e-02 5.1745941e-02 6.1508632e-02 3.3138226e-02 1.3469654e-02 3.9479896e-02 2.9967140e-02 6.1565597e-02 6.0825097e-02 2.7361698e-02 3.5748038e-02 4.0333571e-02 9.0138895e-02 4.8984196e-02 3.2667108e-02 4.4902460e-02 6.4253355e-02 2.1894327e-02 3.3940189e-02 3.2913172e-02 1.6731486e-02 1.8202458e-02 5.7045856e-02 2.7382191e-02 4.3985602e-02 2.1375556e-02 5.9676750e-02 2.5108522e-02 6.6474949e-02 3.7689168e-02 4.4508235e-02 3.7339453e-02 1.6368548e-02 2.0371230e-02 3.9606943e-02 1.4908799e-02 5.1575806e-02 4.6824025e-02 3.8781771e-02 2.3989539e-02 3.6452117e-02 2.2748990e-02 3.4902979e-02 3.6586492e-02 7.5459794e-03 1.9125850e-02 2.0310725e-02 6.1222293e-03 3.4447226e-03 8.1418452e-03 3.7867035e-02 1.2077489e-02 1.6567789e-02 2.1605044e-02 3.9038067e-03 1.6430417e-02 2.8689503e-02 1.3569150e-02 4.2181405e-03 2.6167927e-02 7.2610935e-03 7.0630535e-03 1.1392972e-02 1.4088158e-02 2.3849569e-02 9.5566395e-03 2.5308356e-02 1.7804542e-02 1.7150362e-02 5.8921861e-02 1.6182419e-02 2.0027139e-02 6.1819655e-03 2.0410396e-03 8.6030014e-03 8.6357480e-03 7.5787415e-03 1.2598904e-02 6.0656768e-03 8.7139108e-03 1.7031846e-03 2.3331644e-03 1.8821103e-03 3.1682605e-04 8.7160052e-03 8.5600328e-03 2.8826583e-04 3.4529372e-03 7.5176091e-03 2.1668627e-02 4.3875084e-03 6.5654007e-04 4.4940457e-03 9.7914071e-03 1.9831433e-04 3.3391345e-03 2.9870521e-03 6.9985633e-04 2.5162956e-03 7.1853248e-03 1.3860021e-03 2.9754449e-03 4.8339512e-03 8.0121089e-03 2.3142577e-03 1.5373296e-02 2.8512223e-03 6.2399212e-03 5.8796015e-03 3.1092372e-03 2.3415322e-04 1.9852251e-03 5.2321529e-03 6.1819655e-03 4.3274341e-03 1.8113019e-03 1.9110595e-03 2.4033410e-03 9.3130265e-05 5.1498910e-03 6.5356041e-03 9.5659910e-03 1.1252405e-02 5.1556774e-03 3.2048021e-03 1.2695843e-03 2.2856756e-02 5.7848184e-03 7.7211451e-03 1.0283621e-02 8.3602499e-03 2.7615733e-03 7.9786726e-03 5.6505970e-03 1.0691105e-02 7.1332727e-03 3.1295602e-03 5.2401241e-04 9.5266815e-04 6.4319329e-03 1.2318850e-02 9.4872145e-04 6.1326072e-03 3.4758657e-03 6.5333653e-03 4.0853883e-02 4.3049208e-03 3.1649609e-02 1.6528693e-02 1.4101758e-02 1.4838879e-02 2.1483291e-02 2.2597676e-02 1.8841242e-02 1.6959579e-02 2.5991410e-02 7.4250762e-03 1.9970150e-03 1.4113092e-02 1.0250250e-02 2.6744340e-02 2.8212793e-02 6.9997737e-03 7.0607843e-03 7.4739664e-03 4.8397396e-02 1.9593840e-02 1.0430940e-02 1.2525634e-02 2.7473469e-02 8.3209543e-03 6.1476473e-03 5.8775226e-03 5.2455782e-03 1.4265861e-03 2.2224591e-02 4.7507930e-03 1.7000338e-02 1.0369313e-03 2.5178358e-02 3.0495461e-03 2.1392322e-02 1.9628131e-02 1.0500631e-02 6.5204272e-03 9.7357638e-04 7.2933833e-03 1.5732817e-02 1.4704532e-02 1.6528693e-02 1.4858839e-02 1.2681737e-02 1.4339393e-02 1.8427144e-02 5.9852538e-03 5.6194230e-03 5.9265324e-03 8.2461319e-05 3.7688699e-03 6.4113525e-03 4.0576095e-03 3.3120738e-03 8.1782115e-04 1.0911416e-04 1.0750826e-04 3.1097496e-02 1.8955233e-02 6.6951403e-03 5.7580225e-04 9.5785875e-03 5.0095389e-03 2.9949836e-03 1.4512717e-02 5.0859668e-03 4.0940931e-04 2.6323499e-04 4.5146422e-03 6.3221754e-03 3.5606197e-03 3.7002765e-04 1.1722539e-02 1.5048339e-03 7.0395338e-02 4.3268177e-02 3.3370831e-02 4.4028795e-02 5.0578307e-02 4.9629423e-02 5.1746432e-02 4.3478758e-02 5.3066435e-02 2.6481479e-02 9.3392135e-03 3.2828923e-02 2.4313691e-02 5.3237993e-02 5.2867243e-02 2.1623243e-02 2.8596153e-02 3.2496284e-02 8.0563616e-02 4.1614554e-02 2.6578058e-02 3.7074597e-02 5.5590704e-02 1.7323162e-02 2.6950223e-02 2.6053254e-02 1.2554151e-02 1.3157434e-02 4.8740123e-02 2.1279987e-02 3.7040705e-02 1.5739340e-02 5.1410982e-02 1.9129885e-02 5.6480014e-02 3.2271228e-02 3.6432542e-02 2.9847396e-02 1.1573499e-02 1.5895178e-02 3.3202746e-02 1.2659655e-02 4.3268177e-02 3.9046279e-02 3.2014714e-02 2.0067384e-02 3.1045819e-02 1.7642117e-02 2.7677552e-02 2.9133996e-02 4.1910853e-03 7.2076003e-03 5.1147587e-03 2.7507325e-03 1.1620134e-03 3.3310681e-04 2.1458858e-04 3.3405406e-02 2.1499526e-02 8.0088547e-03 9.8332257e-04 9.6892205e-03 6.1744631e-03 3.6704596e-03 1.6544301e-02 6.4217725e-03 7.2111274e-04 2.1270559e-04 5.7183304e-03 7.6981750e-03 4.7117366e-03 8.0177817e-04 1.0442534e-02 2.2910923e-03 7.3784227e-02 4.5661689e-02 3.5029236e-02 4.6823533e-02 5.3065363e-02 5.1836541e-02 5.4866908e-02 4.5828107e-02 5.5174565e-02 2.8408213e-02 1.0505539e-02 3.4430852e-02 2.5609623e-02 5.5260802e-02 5.4654205e-02 2.3114484e-02 3.0836583e-02 3.5207839e-02 8.2686924e-02 4.3372344e-02 2.8064998e-02 3.9380344e-02 5.7772002e-02 1.8254235e-02 2.9162191e-02 2.8206341e-02 1.3497345e-02 1.4745279e-02 5.0900941e-02 2.3090436e-02 3.8677830e-02 1.7710943e-02 5.3450122e-02 2.1019262e-02 5.9801906e-02 3.3130692e-02 3.9030212e-02 3.2379101e-02 1.3108535e-02 1.6839016e-02 3.4625964e-02 1.2551681e-02 4.5661689e-02 4.1207031e-02 3.3732757e-02 2.0513590e-02 3.1937443e-02 1.8908607e-02 3.0105345e-02 3.1711397e-02 5.5341249e-04 1.8100865e-03 1.3685556e-02 1.1595059e-03 2.7733190e-03 5.0259130e-03 1.5582273e-02 1.5303863e-02 1.3216313e-02 1.8061219e-03 1.8483286e-03 1.0961959e-02 4.0632184e-04 7.9419645e-03 4.2030049e-03 1.8572156e-03 5.9964081e-03 2.8843938e-03 1.1487297e-02 6.2195738e-03 3.4171878e-03 2.7328194e-02 3.9549773e-03 4.5323537e-02 2.3233798e-02 1.5194289e-02 2.5226902e-02 2.8389486e-02 2.7075250e-02 3.1585337e-02 2.3242139e-02 2.9332670e-02 1.1663012e-02 1.9950589e-03 1.4768251e-02 9.1566367e-03 2.9330780e-02 2.8799195e-02 7.9264454e-03 1.3962831e-02 1.8481959e-02 5.0115855e-02 2.0802698e-02 1.0733745e-02 1.9041166e-02 3.1266982e-02 4.9760517e-03 1.3001310e-02 1.2292231e-02 2.6877167e-03 4.5798906e-03 2.6364594e-02 8.6153969e-03 1.7566530e-02 7.4744318e-03 2.8043210e-02 7.9969256e-03 3.5640074e-02 1.4109863e-02 1.9847472e-02 1.6098385e-02 3.9587699e-03 4.2468630e-03 1.4818700e-02 3.7268555e-03 2.3233798e-02 1.9851942e-02 1.4429507e-02 6.7117241e-03 1.3281147e-02 5.4664867e-03 1.4483311e-02 1.6079322e-02 1.4644608e-03 1.8793440e-02 2.6529941e-03 4.9386280e-03 7.8423223e-03 1.0293845e-02 1.1871124e-02 1.4064748e-02 3.3517168e-03 2.2145112e-03 1.1983758e-02 7.1285200e-04 4.9198989e-03 3.5944894e-03 3.6244119e-03 9.2640212e-03 2.3814700e-03 1.1959906e-02 6.6391160e-03 5.2659669e-03 3.4768199e-02 5.0225808e-03 3.6096256e-02 1.6893661e-02 1.0608435e-02 1.8369401e-02 2.1445998e-02 2.0588370e-02 2.3840862e-02 1.6945577e-02 2.2798129e-02 7.2320779e-03 4.5716975e-04 1.0311574e-02 5.8475513e-03 2.2922553e-02 2.2802937e-02 4.5367353e-03 8.9750660e-03 1.2721749e-02 4.2209187e-02 1.5508457e-02 6.9302761e-03 1.3261817e-02 2.4477020e-02 2.9037640e-03 8.2014592e-03 7.6405998e-03 1.0779902e-03 2.0077167e-03 2.0000571e-02 4.8259503e-03 1.2764273e-02 4.2375783e-03 2.1711543e-02 4.3575270e-03 2.7378197e-02 1.1026559e-02 1.3799894e-02 1.0731586e-02 1.6733633e-03 2.2875292e-03 1.0634216e-02 4.2659077e-03 1.6893661e-02 1.4117780e-02 9.8480141e-03 5.3491991e-03 1.0216132e-02 2.7977678e-03 9.4220767e-03 1.0761419e-02 1.4255275e-02 1.6372127e-03 2.8542706e-03 4.7214122e-03 1.3332443e-02 7.0444510e-03 6.5532524e-03 1.6174955e-03 6.7559932e-03 5.2389698e-03 5.3640347e-04 3.3171183e-03 5.1283913e-04 2.0296126e-03 6.0950963e-03 1.2744293e-04 5.0948120e-03 1.9318373e-03 2.3608728e-03 2.9089432e-02 1.4755776e-03 4.1865124e-02 2.2429622e-02 1.7100637e-02 2.2021240e-02 2.8022948e-02 2.8179896e-02 2.7393595e-02 2.2729266e-02 3.1385076e-02 1.0928177e-02 1.7748140e-03 1.6893502e-02 1.1535806e-02 3.1856326e-02 3.2502251e-02 8.7863970e-03 1.1670124e-02 1.3706425e-02 5.4822004e-02 2.3316700e-02 1.2494202e-02 1.7833364e-02 3.3214276e-02 7.9216177e-03 1.0562159e-02 1.0054198e-02 4.5572702e-03 2.8793276e-03 2.7614983e-02 7.5454514e-03 2.0103411e-02 3.8323098e-03 3.0272091e-02 5.9246169e-03 3.0771609e-02 1.9772265e-02 1.6666117e-02 1.2065056e-02 2.1106407e-03 6.8455106e-03 1.7918371e-02 1.0155544e-02 2.2429622e-02 1.9803941e-02 1.5812785e-02 1.2351590e-02 1.8630292e-02 6.7616623e-03 1.0713593e-02 1.1544341e-02 7.3852619e-03 4.6030790e-03 2.5842708e-03 5.4300453e-02 3.3576641e-02 1.0668428e-02 6.6015056e-03 2.1814225e-02 9.0913366e-03 1.2584515e-02 3.0243821e-02 1.4861127e-02 6.0467884e-03 1.7442631e-03 1.4568415e-02 1.1492675e-02 1.0173171e-02 5.0439803e-03 2.6472861e-03 7.4513739e-03 1.0326079e-01 7.0098941e-02 5.7127711e-02 7.0823391e-02 7.9250920e-02 7.7946311e-02 8.0298570e-02 7.0363352e-02 8.2049228e-02 4.8294128e-02 2.3708406e-02 5.6369153e-02 4.4949110e-02 8.2157728e-02 8.1370723e-02 4.1592461e-02 5.0974970e-02 5.5456655e-02 1.1462128e-01 6.7593968e-02 4.8172633e-02 6.2189094e-02 8.5184220e-02 3.4981615e-02 4.8742735e-02 4.7569879e-02 2.8345798e-02 2.9430788e-02 7.6817222e-02 4.1186102e-02 6.1732592e-02 3.2638549e-02 7.9961084e-02 3.8043139e-02 8.5993831e-02 5.4182844e-02 6.1100206e-02 5.2203816e-02 2.6988218e-02 3.3049806e-02 5.6579852e-02 2.5305632e-02 7.0098941e-02 6.4715083e-02 5.5458622e-02 3.7374533e-02 5.2731313e-02 3.5938214e-02 4.9377578e-02 5.1061578e-02 3.5870177e-04 1.3937749e-03 2.2192133e-02 1.4887667e-02 7.8001469e-03 8.8171759e-05 5.5216302e-03 5.9793748e-03 7.0276376e-04 9.5746848e-03 3.0437686e-03 8.2181914e-05 2.0068727e-03 2.2506604e-03 6.8090409e-03 3.1469229e-03 6.3301284e-04 1.8528100e-02 1.2625125e-03 5.6704255e-02 3.2399710e-02 2.3806821e-02 3.3394775e-02 3.8737297e-02 3.7833623e-02 4.0310184e-02 3.2556548e-02 4.0845247e-02 1.8140183e-02 4.6897646e-03 2.3353931e-02 1.6279158e-02 4.1004664e-02 4.0734447e-02 1.4064354e-02 2.0110135e-02 2.3937572e-02 6.5512797e-02 3.0871191e-02 1.8117892e-02 2.7110445e-02 4.3069544e-02 1.0732705e-02 1.8772743e-02 1.7996705e-02 7.0003565e-03 7.6876035e-03 3.7052349e-02 1.3928781e-02 2.6945955e-02 1.0128877e-02 3.9392715e-02 1.2368176e-02 4.4616010e-02 2.3284644e-02 2.6871325e-02 2.1527670e-02 6.5473767e-03 9.5899926e-03 2.3719212e-02 8.2529644e-03 3.2399710e-02 2.8696517e-02 2.2657048e-02 1.3399527e-02 2.2203050e-02 1.0884330e-02 1.9665180e-02 2.1074599e-02 3.3845415e-04 2.7555720e-02 1.6677843e-02 6.3795274e-03 1.8362843e-04 8.3039101e-03 4.7168779e-03 1.9845708e-03 1.2200549e-02 3.8746792e-03 1.0179352e-04 6.8781671e-04 3.2951534e-03 5.8068152e-03 2.8838183e-03 1.7929502e-04 1.4079350e-02 1.0261263e-03 6.5064614e-02 3.9139337e-02 2.9910766e-02 3.9801101e-02 4.6137717e-02 4.5316574e-02 4.7159535e-02 3.9352955e-02 4.8674767e-02 2.3254889e-02 7.4636086e-03 2.9417103e-02 2.1432655e-02 4.8877998e-02 4.8632496e-02 1.8795647e-02 2.5200016e-02 2.8886320e-02 7.5371106e-02 3.7782169e-02 2.3498806e-02 3.3236011e-02 5.1084684e-02 1.4998262e-02 2.3652548e-02 2.2813769e-02 1.0515841e-02 1.0877794e-02 4.4476659e-02 1.8379623e-02 3.3440220e-02 1.3262540e-02 4.7104689e-02 1.6362923e-02 5.1690239e-02 2.9302173e-02 3.2587374e-02 2.6378456e-02 9.4404077e-03 1.3645256e-02 2.9862026e-02 1.1376615e-02 3.9139337e-02 3.5158865e-02 2.8588131e-02 1.7920264e-02 2.8103943e-02 1.5132216e-02 2.4337714e-02 2.5719532e-02 3.3433714e-02 1.9092201e-02 5.6820829e-03 9.6311300e-04 1.1687721e-02 4.1741711e-03 3.9152052e-03 1.5429746e-02 5.3660274e-03 8.0766059e-04 9.2937667e-05 4.9943675e-03 5.5161799e-03 3.3131521e-03 4.2533013e-04 1.0435178e-02 1.4826896e-03 7.3827823e-02 4.6346021e-02 3.6506307e-02 4.6683572e-02 5.3981470e-02 5.3241058e-02 5.4467293e-02 4.6614647e-02 5.6933591e-02 2.8894083e-02 1.0839802e-02 3.5973376e-02 2.7110780e-02 5.7179243e-02 5.6957917e-02 2.4065468e-02 3.0813759e-02 3.4360438e-02 8.5582303e-02 4.5156230e-02 2.9396418e-02 3.9850269e-02 5.9522160e-02 1.9818286e-02 2.9063291e-02 2.8164144e-02 1.4610346e-02 1.4656069e-02 5.2344759e-02 2.3377306e-02 4.0412481e-02 1.6984268e-02 5.5250411e-02 2.0918953e-02 5.9213325e-02 3.5814189e-02 3.8804285e-02 3.1759139e-02 1.2931018e-02 1.8261938e-02 3.6495356e-02 1.5089913e-02 4.6346021e-02 4.2098942e-02 3.5016667e-02 2.2986158e-02 3.4503485e-02 1.9934983e-02 2.9546649e-02 3.0900707e-02 1.1335824e-02 3.2301226e-02 2.3277392e-02 1.5629192e-02 3.0795664e-02 1.5041716e-02 5.4315810e-03 1.4713782e-02 2.4451968e-02 3.6761202e-02 1.3762814e-02 2.8473446e-02 2.2472023e-02 2.6736705e-02 8.0230549e-02 2.3341323e-02 8.1067950e-03 1.4485807e-03 2.4486060e-03 1.1703837e-03 3.1310445e-03 3.9732842e-03 2.8350922e-03 1.6242765e-03 5.7101906e-03 4.5289508e-04 6.6077306e-03 2.6813364e-03 3.3571693e-03 6.2840633e-03 7.7260784e-03 2.0715363e-03 5.6385417e-05 8.9610646e-04 1.8073537e-02 3.9621048e-03 2.3604444e-03 4.7560860e-04 6.2480089e-03 5.8573026e-03 1.7069942e-04 2.3254450e-04 6.3902073e-03 3.8624324e-03 3.9083302e-03 1.0347438e-03 3.4531305e-03 3.5564063e-03 5.5040957e-03 1.4887365e-03 4.1720167e-03 8.6822743e-03 2.8448886e-04 5.1458480e-04 4.8536300e-03 5.8397245e-03 3.9827712e-03 1.8058791e-02 1.4485807e-03 1.2408841e-03 1.8448387e-03 1.0796845e-02 8.0405443e-03 3.4808504e-03 5.2754145e-04 8.8520211e-04 8.8923137e-03 1.4043268e-02 2.4126814e-02 9.1698320e-03 1.1327807e-02 1.9771649e-03 4.5360079e-03 1.5317882e-02 2.1762150e-02 5.6097757e-03 7.1877025e-03 6.8496039e-03 1.4100359e-02 5.3810596e-02 9.9629280e-03 3.1307769e-02 2.0553715e-02 2.1937453e-02 1.5991855e-02 2.5676129e-02 2.8613140e-02 1.8469501e-02 2.1322428e-02 3.3003652e-02 1.2471005e-02 8.9752587e-03 2.2249180e-02 1.9221338e-02 3.4330234e-02 3.7274155e-02 1.4283960e-02 1.0136722e-02 7.4549090e-03 5.7532344e-02 2.7732649e-02 1.8492242e-02 1.6393364e-02 3.4241314e-02 1.8497141e-02 9.1551303e-03 9.1767161e-03 1.4470512e-02 6.3039218e-03 2.8459911e-02 9.7413243e-03 2.5409718e-02 3.4719577e-03 3.2484401e-02 7.0164005e-03 2.0017467e-02 3.2249701e-02 1.2084843e-02 7.5073944e-03 5.8227226e-03 1.7146634e-02 2.5055287e-02 2.9865216e-02 2.0553715e-02 2.0008085e-02 1.9953689e-02 2.7764157e-02 3.0721044e-02 1.4086953e-02 7.0439235e-03 6.3871700e-03 6.2932024e-03 2.4881477e-02 1.2570656e-04 9.2318283e-03 1.1425023e-02 3.9781027e-03 6.8287051e-03 6.6316807e-03 5.1943433e-03 1.2253382e-04 1.3842125e-03 4.4535183e-03 2.1436401e-02 2.8241776e-03 6.8828353e-02 4.7091014e-02 4.2520568e-02 4.3241334e-02 5.5155458e-02 5.7042053e-02 4.8981701e-02 4.7857882e-02 6.2261278e-02 3.0649818e-02 1.4761608e-02 4.2406580e-02 3.4493935e-02 6.3340671e-02 6.5239814e-02 2.8920518e-02 2.9750953e-02 2.8851937e-02 9.4568410e-02 5.1830706e-02 3.5536784e-02 4.0198717e-02 6.4555077e-02 2.8697450e-02 2.7846993e-02 2.7347316e-02 2.1934395e-02 1.5675611e-02 5.6443004e-02 2.4878970e-02 4.7356921e-02 1.4503825e-02 6.0963940e-02 2.0840976e-02 5.2367097e-02 4.8672170e-02 3.5784762e-02 2.7656172e-02 1.3836981e-02 2.6623769e-02 4.4650658e-02 3.0852069e-02 4.7091014e-02 4.4370840e-02 4.0176310e-02 3.6600204e-02 4.6858384e-02 2.5835018e-02 2.6019603e-02 2.5994222e-02 6.9728196e-03 4.6608676e-03 9.9835054e-04 9.5223148e-03 2.6272609e-03 2.7884021e-05 1.5635547e-03 2.0372846e-03 5.4615556e-03 2.3300808e-03 2.5698617e-04 1.7457304e-02 7.2996870e-04 5.8453388e-02 3.4095678e-02 2.5737672e-02 3.4628989e-02 4.0687367e-02 4.0032201e-02 4.1519056e-02 3.4313166e-02 4.3287054e-02 1.9386832e-02 5.3532424e-03 2.5306754e-02 1.8013458e-02 4.3531307e-02 4.3448361e-02 1.5446633e-02 2.1111383e-02 2.4519102e-02 6.8935827e-02 3.3123525e-02 1.9821803e-02 2.8570801e-02 4.5547846e-02 1.2302601e-02 1.9692146e-02 1.8929129e-02 8.1934144e-03 8.2421848e-03 3.9256624e-02 1.4936345e-02 2.9083818e-02 1.0370393e-02 4.1828239e-02 1.3093356e-02 4.5785106e-02 2.5766235e-02 2.7913838e-02 2.2194996e-02 6.9953757e-03 1.1047300e-02 2.5843766e-02 1.0033677e-02 3.4095678e-02 3.0429687e-02 2.4458901e-02 1.5454278e-02 2.4603652e-02 1.2196519e-02 2.0322394e-02 2.1606954e-02 2.1763592e-02 3.8778874e-03 1.3140898e-02 1.0973585e-02 6.8570288e-03 1.2689294e-02 8.7227464e-03 2.2446768e-02 1.4768924e-02 9.8837253e-03 3.6594036e-02 1.1176832e-02 4.2371132e-02 2.0489598e-02 1.1322791e-02 2.4620431e-02 2.4482623e-02 2.2010230e-02 3.1108475e-02 2.0217050e-02 2.3141445e-02 1.0944826e-02 3.8599335e-03 1.0791452e-02 6.1542383e-03 2.2743482e-02 2.1333545e-02 6.5515291e-03 1.4388718e-02 2.0852825e-02 3.9383251e-02 1.5461941e-02 7.8878514e-03 1.7372104e-02 2.4911352e-02 2.6880230e-03 1.3798611e-02 1.3025794e-02 2.1193973e-03 6.9838956e-03 2.1270749e-02 8.9787629e-03 1.2743052e-02 1.1335890e-02 2.1877049e-02 9.6533919e-03 3.5351983e-02 7.6384883e-03 2.0107777e-02 1.8067074e-02 6.8413076e-03 2.4741061e-03 1.0039063e-02 3.4670280e-04 2.0489598e-02 1.6923143e-02 1.1154236e-02 2.1521967e-03 7.1850256e-03 4.3898059e-03 1.6491142e-02 1.8665860e-02 7.4245740e-03 1.0715228e-02 3.1685550e-03 5.1120383e-03 5.0451240e-03 4.1323270e-03 1.4489604e-04 8.1318290e-04 3.0839979e-03 1.9714350e-02 1.7947024e-03 6.7440625e-02 4.5128820e-02 3.9916292e-02 4.1909560e-02 5.3040678e-02 5.4550431e-02 4.7872699e-02 4.5818357e-02 5.9509133e-02 2.8778013e-02 1.2927960e-02 3.9749997e-02 3.1835574e-02 6.0466685e-02 6.2068316e-02 2.6673332e-02 2.8274822e-02 2.8015780e-02 9.1028220e-02 4.9020613e-02 3.3018114e-02 3.8378554e-02 6.1817956e-02 2.5959804e-02 2.6422336e-02 2.5876047e-02 1.9520884e-02 1.4184191e-02 5.3918305e-02 2.3137863e-02 4.4568283e-02 1.3507580e-02 5.8174666e-02 1.9385371e-02 5.1416653e-02 4.5132833e-02 3.4491897e-02 2.6637939e-02 1.2404699e-02 2.3988175e-02 4.1744067e-02 2.7329966e-02 4.5128820e-02 4.2235431e-02 3.7715182e-02 3.3171215e-02 4.3405180e-02 2.3512609e-02 2.4946638e-02 2.5117607e-02 5.7451096e-03 2.0181202e-03 1.1916495e-03 5.0056293e-03 1.1565469e-03 7.7131020e-03 3.5313465e-03 2.1072743e-03 2.6393551e-02 2.0670282e-03 4.4935473e-02 2.3639481e-02 1.6646699e-02 2.4503230e-02 2.9137719e-02 2.8488385e-02 3.0530237e-02 2.3788614e-02 3.1241308e-02 1.1731452e-02 1.7654569e-03 1.6307697e-02 1.0602623e-02 3.1457386e-02 3.1449229e-02 8.6094127e-03 1.3341698e-02 1.6740022e-02 5.3656632e-02 2.2705161e-02 1.1958802e-02 1.9130319e-02 3.3171817e-02 6.4720106e-03 1.2268562e-02 1.1633623e-02 3.5425115e-03 3.7925712e-03 2.7828397e-02 8.3873180e-03 1.9384549e-02 5.8220699e-03 3.0002594e-02 7.2263237e-03 3.4339797e-02 1.7195852e-02 1.8977924e-02 1.4659749e-02 3.0403500e-03 5.5430802e-03 1.6804744e-02 6.5028482e-03 2.3639481e-02 2.0526700e-02 1.5612876e-02 9.4514606e-03 1.6202837e-02 6.2323724e-03 1.3120120e-02 1.4374340e-02 2.8180986e-03 1.0509318e-02 1.7897176e-02 2.8798358e-03 9.1928702e-03 6.3970688e-03 1.0746267e-02 5.0496414e-02 7.7981540e-03 2.4751970e-02 1.2458649e-02 1.1686269e-02 1.0356316e-02 1.6774912e-02 1.8282513e-02 1.3498932e-02 1.2919728e-02 2.1579044e-02 5.2962835e-03 2.7725666e-03 1.1818152e-02 9.1091800e-03 2.2436834e-02 2.4265521e-02 5.8512682e-03 4.4398598e-03 4.1822455e-03 4.2435194e-02 1.6425553e-02 8.8184300e-03 9.0473617e-03 2.2804959e-02 8.4055012e-03 3.7245140e-03 3.5955501e-03 5.8501155e-03 1.2261597e-03 1.8027694e-02 3.2889908e-03 1.4332649e-02 2.5252408e-04 2.0964539e-02 1.7865385e-03 1.5552416e-02 1.8549588e-02 6.8429145e-03 3.5948443e-03 1.0694978e-03 7.5092190e-03 1.3665818e-02 1.7252830e-02 1.2458649e-02 1.1370103e-02 1.0296741e-02 1.5007456e-02 1.7383467e-02 5.5463863e-03 2.9922345e-03 3.0734531e-03 3.1960387e-03 6.8662451e-03 1.2966654e-04 2.7649067e-03 8.3427366e-04 2.7984284e-03 2.9822521e-02 1.2731780e-03 4.3416537e-02 2.4875338e-02 2.0714079e-02 2.3200351e-02 3.0852531e-02 3.1753284e-02 2.8200300e-02 2.5332686e-02 3.5512031e-02 1.2989773e-02 3.4785945e-03 2.0603808e-02 1.5135483e-02 3.6226615e-02 3.7456354e-02 1.1531484e-02 1.2959687e-02 1.3737739e-02 6.0763799e-02 2.7435536e-02 1.5849420e-02 1.9923216e-02 3.7336849e-02 1.1567919e-02 1.1725372e-02 1.1300051e-02 7.4803077e-03 3.9656480e-03 3.1244978e-02 9.2703065e-03 2.4126524e-02 3.9496417e-03 3.4455719e-02 7.0383738e-03 3.1302098e-02 2.5203523e-02 1.7680030e-02 1.2436482e-02 3.0466203e-03 1.0266971e-02 2.2126952e-02 1.5206492e-02 2.4875338e-02 2.2550174e-02 1.9125072e-02 1.7383181e-02 2.3878119e-02 9.5944653e-03 1.1168635e-02 1.1615557e-02 1.3151667e-03 2.5320521e-03 6.0366399e-03 2.7823080e-03 2.9364031e-04 1.6476106e-02 9.7247557e-04 6.0284770e-02 3.5334723e-02 2.6546579e-02 3.6095524e-02 4.1987790e-02 4.1172424e-02 4.3178382e-02 3.5527420e-02 4.4374359e-02 2.0339225e-02 5.8436205e-03 2.6082735e-02 1.8603485e-02 4.4570054e-02 4.4351810e-02 1.6144347e-02 2.2244142e-02 2.5921932e-02 7.0056396e-02 3.3998717e-02 2.0524111e-02 2.9752453e-02 4.6679420e-02 1.2673386e-02 2.0806267e-02 2.0008665e-02 8.5632030e-03 8.9793060e-03 4.0369526e-02 1.5814708e-02 2.9884891e-02 1.1327921e-02 4.2874486e-02 1.4012365e-02 4.7563178e-02 2.6115270e-02 2.9259206e-02 2.3493076e-02 7.6990791e-03 1.1423166e-02 2.6517929e-02 9.7961479e-03 3.5334723e-02 3.1531604e-02 2.5300172e-02 1.5549538e-02 2.4969819e-02 1.2759840e-02 2.1558690e-02 2.2929217e-02 6.4418336e-03 6.6136731e-03 4.4102106e-03 9.1481615e-04 8.6358065e-03 2.3009102e-03 7.8700864e-02 5.0063075e-02 3.9499858e-02 5.0635713e-02 5.7926279e-02 5.6986449e-02 5.8777354e-02 5.0310505e-02 6.0682610e-02 3.1865387e-02 1.2666075e-02 3.8913195e-02 2.9597893e-02 6.0871779e-02 6.0471723e-02 2.6606279e-02 3.4024273e-02 3.7905442e-02 8.9816272e-02 4.8416482e-02 3.2086335e-02 4.3354864e-02 6.3371751e-02 2.1811352e-02 3.2202223e-02 3.1242353e-02 1.6436605e-02 1.6909958e-02 5.6040246e-02 2.6101775e-02 4.3480802e-02 1.9524603e-02 5.8918015e-02 2.3597831e-02 6.3733101e-02 3.8161980e-02 4.2440703e-02 3.5140814e-02 1.5073633e-02 2.0215594e-02 3.9313992e-02 1.6000311e-02 5.0063075e-02 4.5569203e-02 3.8016354e-02 2.4659247e-02 3.6849168e-02 2.2186423e-02 3.2805330e-02 3.4269626e-02 3.8467105e-03 1.2875815e-03 2.5072619e-03 2.9525973e-02 1.2875815e-03 4.2282453e-02 2.3357390e-02 1.8646096e-02 2.2313442e-02 2.9124686e-02 2.9658732e-02 2.7480923e-02 2.3735668e-02 3.3135090e-02 1.1714292e-02 2.4574323e-03 1.8489812e-02 1.3106245e-02 3.3729170e-02 3.4672500e-02 9.9345371e-03 1.2062833e-02 1.3461486e-02 5.7431716e-02 2.5093254e-02 1.3932087e-02 1.8599958e-02 3.4955869e-02 9.5459229e-03 1.0897419e-02 1.0433767e-02 5.8375168e-03 3.2324242e-03 2.9124686e-02 8.1819777e-03 2.1845036e-02 3.6925062e-03 3.2054971e-02 6.2644754e-03 3.0710474e-02 2.2249402e-02 1.6897068e-02 1.1997033e-02 2.3970471e-03 8.3620725e-03 1.9766550e-02 1.2536577e-02 2.3357390e-02 2.0894448e-02 1.7210222e-02 1.4675128e-02 2.1017625e-02 7.9709601e-03 1.0694253e-02 1.1329979e-02 8.0862109e-04 3.9488260e-03 2.3216413e-02 2.2109950e-03 6.3313725e-02 4.2461361e-02 3.8219621e-02 3.8832114e-02 5.0144792e-02 5.1966249e-02 4.4333772e-02 4.3192281e-02 5.6977170e-02 2.6944997e-02 1.2389873e-02 3.8126276e-02 3.0729621e-02 5.8026007e-02 5.9897200e-02 2.5415278e-02 2.6079828e-02 2.5293603e-02 8.8103550e-02 4.7063061e-02 3.1649890e-02 3.5923563e-02 5.9166899e-02 2.5434205e-02 2.4297609e-02 2.3831192e-02 1.9112973e-02 1.3083158e-02 5.1398726e-02 2.1557413e-02 4.2826183e-02 1.1968109e-02 5.5744441e-02 1.7792619e-02 4.7600638e-02 4.4377594e-02 3.1768113e-02 2.4143930e-02 1.1416637e-02 2.3484839e-02 4.0313562e-02 2.8205265e-02 4.2461361e-02 3.9889484e-02 3.5980112e-02 3.3161057e-02 4.2633793e-02 2.2600989e-02 2.2605649e-02 2.2606045e-02 1.6651142e-03 2.2593118e-02 4.7494657e-04 5.5766903e-02 3.4735344e-02 2.9594132e-02 3.2557240e-02 4.1723024e-02 4.2746173e-02 3.8238608e-02 3.5278801e-02 4.7033204e-02 2.0363061e-02 7.2717611e-03 2.9420951e-02 2.2560431e-02 4.7813714e-02 4.9078515e-02 1.8314288e-02 2.0299319e-02 2.0869007e-02 7.5386883e-02 3.7549246e-02 2.3623644e-02 2.8844458e-02 4.9142563e-02 1.7633849e-02 1.8744071e-02 1.8222205e-02 1.2402012e-02 8.3988430e-03 4.2147698e-02 1.5629140e-02 3.3602383e-02 8.3018288e-03 4.5796447e-02 1.2702505e-02 4.1687026e-02 3.3943329e-02 2.5980350e-02 1.9415550e-02 7.0260502e-03 1.6012157e-02 3.1063717e-02 1.9520820e-02 3.4735344e-02 3.1983672e-02 2.7741891e-02 2.3833980e-02 3.2440091e-02 1.5637054e-02 1.7874227e-02 1.8281297e-02 1.4972117e-02 3.8328039e-04 6.3723448e-02 3.8719440e-02 3.0384566e-02 3.8629777e-02 4.5827446e-02 4.5472032e-02 4.5653244e-02 3.9023449e-02 4.9116846e-02 2.2930601e-02 7.4083466e-03 2.9962579e-02 2.2100137e-02 4.9469036e-02 4.9598054e-02 1.8997460e-02 2.4379661e-02 2.7279745e-02 7.6566902e-02 3.8413283e-02 2.3958684e-02 3.2715136e-02 5.1484761e-02 1.5886249e-02 2.2794916e-02 2.2023153e-02 1.1094162e-02 1.0331639e-02 4.4681292e-02 1.7978253e-02 3.4097516e-02 1.2099271e-02 4.7608429e-02 1.5662138e-02 4.9957613e-02 3.0977854e-02 3.1455087e-02 2.5013254e-02 8.8604244e-03 1.4432007e-02 3.0714741e-02 1.3426163e-02 3.8719440e-02 3.4992868e-02 2.8902863e-02 1.9656006e-02 2.9684992e-02 1.5494562e-02 2.3064694e-02 2.4203450e-02 1.8836956e-02 1.3755831e-01 9.8685385e-02 8.2425470e-02 1.0000651e-01 1.0925759e-01 1.0726669e-01 1.1120208e-01 9.8918033e-02 1.1167083e-01 7.2661493e-02 4.1665349e-02 8.1426911e-02 6.7501542e-02 1.1159988e-01 1.1014878e-01 6.3989575e-02 7.6224987e-02 8.1835804e-02 1.4773346e-01 9.4587815e-02 7.1696153e-02 8.9447560e-02 1.1534202e-01 5.4876111e-02 7.3538690e-02 7.2081812e-02 4.6952332e-02 4.9385723e-02 1.0589901e-01 6.4038977e-02 8.7644093e-02 5.3625558e-02 1.0917520e-01 6.0322002e-02 1.1787190e-01 7.6918821e-02 8.8499122e-02 7.7885622e-02 4.6255911e-02 5.2612368e-02 8.1239445e-02 4.0019052e-02 9.8685385e-02 9.2131722e-02 8.0633770e-02 5.6243805e-02 7.5363077e-02 5.6811044e-02 7.4440381e-02 7.6512320e-02 5.8097767e-02 3.5211195e-02 2.8463781e-02 3.4215950e-02 4.2147698e-02 4.2414656e-02 4.0542228e-02 3.5615822e-02 4.6295613e-02 2.0363061e-02 6.3798220e-03 2.8163995e-02 2.0925233e-02 4.6838114e-02 4.7487902e-02 1.7368541e-02 2.1117782e-02 2.2967145e-02 7.3810390e-02 3.6316652e-02 2.2375879e-02 2.9367287e-02 4.8511603e-02 1.5463833e-02 1.9583828e-02 1.8938570e-02 1.0601468e-02 8.3988430e-03 4.1723024e-02 1.5629140e-02 3.2244606e-02 9.3153170e-03 4.4933305e-02 1.3111918e-02 4.4412271e-02 3.0809608e-02 2.7438827e-02 2.1093197e-02 7.0260502e-03 1.3969417e-02 2.9313944e-02 1.5218585e-02 3.5211195e-02 3.1983672e-02 2.6841235e-02 2.0313092e-02 2.9439905e-02 1.4332974e-02 1.9364178e-02 2.0170126e-02 3.9924060e-03 1.0538198e-02 3.2148883e-03 2.7366019e-03 4.4621109e-03 1.7397347e-03 4.1425525e-03 5.2723146e-03 1.1136640e-02 2.9112354e-02 1.1160954e-02 1.6541883e-02 6.0336652e-03 8.3590571e-03 1.6026960e-02 9.4770245e-03 8.7523451e-03 9.5282841e-03 8.5487892e-03 1.3900105e-02 5.7309995e-03 4.7773544e-03 2.3853571e-02 1.0495078e-02 1.1045936e-02 2.7111420e-02 2.3076623e-02 4.8207470e-03 1.4681091e-02 1.0141190e-02 2.1316125e-02 5.8141126e-03 1.6474359e-02 1.3064397e-03 2.0347529e-02 5.7992324e-03 9.5368199e-03 2.5369333e-02 2.4565418e-02 1.2896533e-02 4.4389699e-02 3.9924060e-03 5.8442541e-03 1.0341765e-02 2.9771308e-02 2.0024906e-02 2.0168043e-02 1.0668382e-02 1.0461554e-02 1.6977050e-03 8.0038314e-04 3.2736649e-04 7.3247771e-04 1.7861084e-03 1.2199790e-05 1.6168506e-03 2.0903986e-03 1.2529506e-02 1.9650001e-03 4.3150624e-03 2.0139182e-03 3.1759995e-03 4.1258242e-03 2.0323215e-03 3.5878910e-03 9.4977361e-03 1.5488203e-03 3.0112961e-03 2.7909675e-04 1.8152664e-03 8.3701176e-03 2.5714996e-03 2.7148441e-03 1.0520423e-02 9.2964166e-03 7.5284963e-04 3.9888853e-03 1.8331853e-03 9.4586856e-03 1.6039412e-03 5.4889906e-03 2.8052973e-03 7.3341015e-03 1.2316222e-03 3.2601592e-03 1.0868316e-02 8.8162037e-03 2.9210959e-03 2.1963225e-02 0.0000000e+00 1.8230646e-04 1.5254865e-03 1.2273284e-02 6.9788794e-03 6.3577637e-03 3.5631537e-03 4.1101326e-03 4.2047124e-03 2.6033919e-03 1.7916004e-03 6.7524244e-03 1.5279872e-03 2.3303877e-03 1.3468412e-03 7.9573793e-03 9.8329441e-06 8.0754860e-04 2.3639655e-03 2.4986002e-03 1.3799583e-03 2.6729899e-03 6.2996248e-03 1.0853281e-02 4.8574547e-04 3.9201723e-04 1.4418237e-03 2.9002781e-03 3.0725233e-03 3.0407572e-03 2.9093497e-03 5.1175009e-03 6.6599859e-03 1.5926877e-03 2.5889139e-03 1.3713626e-04 8.5117654e-03 1.9829707e-03 4.3442759e-03 8.7298845e-03 2.1325966e-03 3.5994846e-03 5.1472858e-03 7.9423211e-03 3.5289513e-03 2.0294631e-04 1.1925423e-02 1.6977050e-03 7.8274456e-04 4.8500499e-05 4.9289073e-03 1.8879551e-03 2.5218165e-03 4.9495642e-03 6.1589498e-03 1.4775011e-03 2.8508338e-03 3.8437964e-04 1.0082748e-03 4.3870644e-03 2.7766403e-03 1.3317076e-02 4.6107743e-03 7.0365754e-03 5.0970174e-03 7.0294656e-03 5.8145812e-03 1.6991258e-03 1.6190058e-03 1.4192459e-02 4.5311136e-03 5.3518685e-03 7.5607221e-04 4.5347742e-03 1.1372343e-02 2.1219078e-03 2.3903563e-03 1.2745790e-02 9.1602079e-03 2.9606388e-03 4.3905218e-03 4.7897027e-03 8.0493172e-03 4.4779450e-03 5.1908739e-03 9.8295198e-04 1.2281083e-02 3.7969538e-04 1.7665186e-03 1.0605818e-02 1.1571194e-02 6.2101277e-03 2.7119271e-02 8.0038314e-04 1.4492761e-03 3.6743113e-03 1.7056692e-02 1.1710246e-02 8.2821554e-03 2.2240766e-03 2.2684005e-03 3.0380682e-04 2.0343287e-03 2.8037036e-04 8.3123377e-04 3.9939935e-03 1.6647447e-02 2.9061444e-03 6.1278767e-03 1.1769582e-03 2.2926522e-03 6.3717175e-03 3.9793414e-03 5.6921961e-03 6.6386310e-03 1.6577942e-03 4.6178179e-03 1.2108195e-03 8.4773320e-04 1.1017765e-02 4.7223063e-03 4.9236953e-03 1.3900771e-02 1.3046714e-02 3.7972280e-04 6.5335900e-03 2.3480655e-03 1.3286542e-02 9.3142474e-04 8.4820747e-03 2.8343361e-03 8.2403259e-03 2.5815546e-03 5.4537681e-03 1.4900562e-02 1.1670902e-02 3.7659184e-03 2.5593433e-02 3.2736649e-04 7.7091107e-04 2.6079554e-03 1.4611634e-02 8.0055625e-03 9.0564615e-03 5.9260895e-03 6.5055071e-03 3.8779943e-03 5.7015696e-04 1.7303569e-04 4.1690936e-03 1.6322670e-02 1.9974930e-03 5.0009825e-03 3.2570724e-04 9.5057293e-04 5.8304604e-03 4.8059418e-03 7.5457291e-03 5.1241997e-03 6.9111123e-04 3.7782470e-03 1.7092344e-03 2.5698914e-04 9.5453465e-03 5.5846827e-03 5.6938512e-03 1.2788699e-02 1.3393372e-02 7.3809633e-06 6.7682476e-03 1.3200598e-03 1.4442150e-02 1.8441195e-04 9.0822620e-03 4.9911804e-03 5.8437761e-03 3.8589879e-03 6.9829557e-03 1.5273413e-02 1.0318402e-02 2.4584659e-03 2.2525564e-02 7.3247771e-04 8.2385517e-04 1.9942911e-03 1.2041849e-02 5.7258386e-03 8.2738022e-03 7.3225251e-03 8.2204997e-03 2.0515682e-03 5.4510656e-03 5.2217407e-03 1.7964531e-02 7.2742632e-03 1.0588415e-02 6.2949332e-03 8.6345788e-03 9.1795241e-03 3.5876856e-03 2.6991302e-03 1.4376485e-02 6.5862079e-03 8.4804528e-03 2.1372463e-03 5.3927480e-03 1.5896874e-02 4.1394106e-03 4.5375167e-03 1.7523452e-02 1.2909742e-02 4.0941134e-03 7.2891356e-03 7.2227860e-03 1.1126344e-02 5.7124492e-03 8.1126160e-03 1.3907276e-04 1.6260954e-02 1.3854449e-03 3.2122771e-03 1.4553993e-02 1.6151019e-02 9.1578470e-03 3.3857588e-02 1.7861084e-03 2.9619943e-03 6.1829720e-03 2.2326762e-02 1.5680260e-02 1.2223630e-02 3.9245535e-03 3.7050303e-03 1.3686449e-03 2.1603250e-03 1.2649428e-02 1.7801502e-03 4.1458992e-03 1.7278919e-03 2.7991042e-03 4.0888611e-03 2.2218452e-03 3.9716339e-03 8.9665631e-03 1.3013529e-03 2.8806398e-03 3.4594790e-04 1.5677728e-03 8.1916354e-03 2.7802616e-03 2.9107124e-03 1.0452698e-02 9.5134829e-03 5.8171764e-04 4.1098444e-03 1.6001879e-03 9.8257537e-03 1.3468918e-03 5.7037585e-03 3.1132824e-03 6.8805675e-03 1.4645264e-03 3.5912866e-03 1.1107885e-02 8.6722521e-03 2.6587395e-03 2.1561220e-02 1.2199790e-05 1.4772036e-04 1.4023821e-03 1.1878859e-02 6.5538274e-03 6.3060622e-03 3.8811059e-03 4.4873121e-03 5.6719205e-03 1.8601099e-02 2.5037679e-03 5.8026549e-03 3.0990295e-05 3.8568498e-04 7.1301713e-03 6.6581271e-03 9.9891912e-03 3.5467136e-03 7.7986655e-04 4.6294369e-03 2.9226786e-03 3.3006174e-05 1.0560037e-02 7.5497742e-03 7.6393818e-03 1.4326258e-02 1.5841028e-02 1.7171643e-04 8.5994033e-03 1.5671556e-03 1.7334506e-02 1.9316046e-05 1.1306536e-02 6.6195881e-03 5.5794173e-03 5.6606012e-03 9.3044548e-03 1.7865075e-02 1.1490070e-02 2.7178516e-03 2.3185889e-02 1.6168506e-03 1.6521970e-03 2.7157547e-03 1.2355858e-02 5.5768992e-03 9.6617637e-03 9.6558503e-03 1.0729574e-02 4.4050618e-03 1.4462579e-03 1.4084514e-03 6.0437228e-03 6.9280724e-03 5.9092958e-04 3.5267150e-04 2.3264461e-03 1.8099026e-02 3.0921484e-03 8.6005594e-04 9.1287231e-04 6.3843974e-03 3.0627943e-03 4.0297343e-04 3.2526954e-04 3.6399798e-03 2.6478661e-03 3.9939935e-03 3.1762278e-04 2.2988741e-03 3.2596799e-03 5.3016678e-03 9.7044163e-04 7.0435695e-03 5.7009823e-03 1.4263218e-03 1.5142545e-03 3.5226184e-03 3.0792135e-03 2.3251410e-03 1.2857609e-02 2.0903986e-03 1.3292907e-03 8.8570158e-04 6.8622586e-03 5.1349839e-03 1.4775225e-03 1.2815928e-03 1.9995407e-03 7.7887386e-03 4.2718762e-03 1.8880208e-02 1.9223691e-02 2.7240761e-03 5.5247078e-03 8.3688264e-03 3.7206770e-02 1.2358468e-02 4.8889738e-03 9.3012979e-03 2.0063076e-02 2.3808756e-03 4.8847228e-03 4.4654367e-03 8.0211221e-04 5.5572260e-04 1.5849918e-02 2.4737465e-03 1.0011166e-02 2.0320189e-03 1.7697241e-02 2.0106232e-03 2.1009310e-02 1.0002251e-02 9.3994441e-03 6.7786672e-03 4.3329436e-04 1.8154672e-03 8.4395042e-03 6.2214471e-03 1.2529506e-02 1.0325253e-02 7.1412079e-03 5.6981926e-03 9.1712120e-03 1.6108637e-03 5.7438691e-03 6.7900644e-03 6.8888062e-04 2.5080626e-03 2.5613963e-03 1.3274318e-03 2.8814590e-03 6.6724246e-03 1.1044919e-02 5.3338455e-04 3.3999007e-04 1.6762239e-03 3.1000026e-03 2.8256325e-03 3.2387801e-03 3.0867064e-03 4.8730365e-03 6.6378483e-03 1.7822362e-03 2.6462661e-03 1.4123935e-04 8.6230682e-03 2.1318487e-03 4.4281251e-03 9.3233552e-03 1.8673327e-03 3.9343847e-03 5.4568897e-03 7.9015195e-03 3.2859077e-03 1.3180217e-04 1.1320265e-02 1.9650001e-03 9.6799653e-04 7.8282421e-05 4.5166083e-03 1.6331972e-03 2.3904078e-03 5.2224500e-03 6.4841213e-03 5.7642096e-03 5.5885978e-03 3.7048759e-04 3.1695738e-03 7.3434699e-03 1.6768125e-02 2.3743894e-03 1.1932462e-04 3.2200650e-03 6.6976868e-03 7.3134819e-04 3.2564607e-03 2.9664521e-03 1.9437509e-03 4.0525881e-03 4.6657625e-03 1.7256268e-03 1.3667365e-03 6.4082141e-03 5.2167922e-03 3.0823107e-03 1.3133486e-02 1.7068449e-03 5.3434665e-03 5.8085657e-03 4.9261084e-03 9.6684380e-04 7.1816432e-04 6.8418503e-03 4.3150624e-03 2.7358698e-03 7.4246714e-04 2.1999970e-03 1.3715192e-03 6.3897855e-04 5.2531215e-03 6.6567087e-03 1.9959041e-04 7.2877827e-03 7.2348769e-03 1.0891220e-02 3.2459725e-03 7.4122702e-04 4.6749634e-03 3.3669230e-03 7.9583955e-05 1.0437521e-02 8.1436642e-03 8.2061472e-03 1.4337740e-02 1.6319841e-02 3.0462366e-04 9.0085125e-03 1.5214225e-03 1.8068443e-02 2.5934558e-05 1.1842923e-02 7.5545176e-03 5.1162105e-03 6.3606028e-03 1.0107865e-02 1.8360102e-02 1.1411116e-02 2.5943653e-03 2.2590562e-02 2.0139182e-03 1.9469619e-03 2.8165944e-03 1.1880076e-02 5.1539049e-03 9.7568917e-03 1.0422756e-02 1.1596876e-02 7.5663186e-03 8.6488322e-03 1.3133604e-02 3.0107568e-03 7.9406152e-04 4.7466095e-03 4.5711602e-03 4.9936224e-04 9.9296431e-03 9.5749791e-03 9.5587917e-03 1.4081306e-02 1.7234890e-02 8.7040364e-04 9.9040316e-03 1.5012448e-03 1.9639569e-02 3.0179394e-04 1.3010570e-02 1.0161281e-02 3.9519870e-03 8.1767554e-03 1.2080688e-02 1.9279439e-02 1.0989202e-02 2.3266303e-03 2.0713423e-02 3.1759995e-03 2.8067172e-03 3.1032715e-03 1.0490119e-02 4.0786420e-03 9.8110939e-03 1.2277454e-02 1.3709414e-02 1.7582839e-03 4.9489607e-03 1.9934064e-02 3.5016865e-03 3.4697267e-04 2.6310541e-03 8.0617166e-03 9.6411709e-04 1.7064375e-03 1.4666650e-03 1.4745772e-03 2.1108592e-03 5.5260764e-03 5.1802495e-04 2.3341578e-03 3.7167048e-03 6.5626516e-03 1.3180061e-03 1.1565092e-02 3.6658759e-03 3.8514458e-03 3.6514318e-03 2.8125792e-03 9.8545506e-04 1.7565517e-03 7.9513446e-03 4.1258242e-03 2.7177731e-03 1.0483123e-03 3.5558284e-03 3.1649242e-03 2.4110016e-04 3.1231514e-03 4.2303212e-03 8.7046320e-04 1.9803680e-02 4.5057787e-03 2.2875453e-03 8.1473256e-04 7.2784764e-03 5.2841523e-03 3.1936914e-05 6.0579771e-05 5.5427829e-03 2.9996038e-03 4.7111715e-03 6.7018226e-04 3.8206460e-03 2.7379425e-03 6.3961850e-03 9.7000606e-04 5.0455840e-03 8.7517746e-03 5.2181192e-04 4.2086901e-04 3.8740476e-03 5.1909001e-03 4.1846614e-03 1.6912712e-02 2.0323215e-03 1.6814934e-03 2.0140995e-03 1.0246238e-02 8.0709165e-03 2.9533168e-03 3.5001524e-04 7.2402168e-04 2.4525121e-02 8.3786268e-03 5.9730003e-03 2.2241688e-03 1.0490949e-02 1.0052150e-02 8.4481649e-04 1.0306755e-03 9.7104895e-03 4.7051149e-03 7.5682486e-03 2.5521754e-03 7.8053009e-03 3.0734717e-03 9.8801938e-03 2.2384251e-03 3.6192976e-03 1.5052125e-02 6.1736712e-04 1.0280118e-04 5.5375454e-03 9.7589612e-03 8.6474768e-03 2.4375316e-02 3.5878910e-03 3.8390770e-03 5.3089764e-03 1.6859170e-02 1.4176552e-02 6.5576789e-03 2.5984028e-04 9.3320862e-05 6.7547274e-03 1.5238284e-02 1.2713534e-02 3.0890016e-03 2.3712664e-02 2.1340343e-02 2.1521507e-02 3.0005294e-02 3.3960619e-02 5.2290080e-03 2.3006673e-02 8.7125215e-03 3.6416136e-02 3.8281789e-03 2.7389250e-02 1.5157530e-02 1.2639929e-02 1.7411617e-02 2.3820503e-02 3.6850697e-02 2.5373970e-02 1.0602298e-02 3.7784525e-02 9.4977361e-03 1.0004799e-02 1.1952848e-02 2.3559319e-02 1.3109247e-02 2.3603108e-02 2.4562463e-02 2.6017612e-02 1.7241949e-03 2.0286689e-03 1.1335916e-03 5.6322483e-03 5.1221157e-03 5.0559971e-03 8.5835151e-03 1.0650923e-02 5.5566853e-04 5.1134826e-03 1.3892193e-04 1.2640034e-02 5.6438567e-04 7.4313522e-03 8.3161300e-03 2.5369950e-03 4.7342848e-03 7.3166190e-03 1.2276381e-02 6.3456614e-03 5.8916640e-04 1.5594819e-02 1.5488203e-03 9.3082136e-04 7.5849611e-04 7.0579696e-03 2.4440449e-03 5.1791902e-03 7.3166180e-03 8.5826500e-03 2.1075364e-03 5.4157920e-03 1.3748154e-03 2.4371345e-03 2.2201300e-03 2.6881175e-03 4.1574302e-03 3.5021271e-03 1.4032793e-03 9.1188034e-04 6.1085103e-03 4.1365224e-03 2.7438304e-03 1.0770631e-02 2.1519140e-03 3.9794011e-03 4.6480198e-03 5.1312578e-03 1.6288841e-03 5.4679156e-04 8.7532006e-03 3.0112961e-03 1.7262374e-03 2.9055719e-04 3.3158230e-03 1.8013008e-03 9.2887256e-04 4.2320076e-03 5.4776329e-03 3.2889511e-03 6.5019207e-03 1.1654311e-03 1.2550970e-03 7.9744383e-03 6.4095512e-03 1.6783080e-03 2.2182877e-03 1.9380758e-03 6.5001122e-03 2.8053456e-03 3.3035106e-03 3.3582234e-03 7.0744470e-03 5.6581852e-04 1.8141689e-03 7.7202001e-03 6.7565678e-03 2.7207024e-03 1.9179880e-02 2.7909675e-04 2.2008347e-04 1.1064738e-03 1.0688407e-02 6.6082062e-03 4.4435997e-03 1.9606397e-03 2.4773484e-03 1.1763001e-02 8.2259536e-03 8.3480149e-03 1.5692475e-02 1.7083720e-02 2.8355914e-04 9.4960515e-03 2.0536401e-03 1.8469924e-02 1.0092056e-04 1.2279622e-02 6.4441301e-03 6.4046448e-03 6.0274458e-03 9.8857207e-03 1.9188640e-02 1.2736270e-02 3.3492132e-03 2.4941935e-02 1.8152664e-03 1.9865894e-03 3.3071796e-03 1.3641872e-02 6.4197769e-03 1.0769048e-02 1.0309787e-02 1.1341762e-02 5.1119032e-03 4.6662587e-03 4.6505160e-04 3.2269116e-03 9.0774431e-03 2.5215213e-03 4.0057628e-03 6.1199030e-03 9.7447895e-03 3.5360157e-03 1.8995080e-02 2.6805580e-03 8.6582433e-03 8.1342278e-03 3.7198152e-03 3.9443681e-05 2.6670326e-03 3.4016785e-03 8.3701176e-03 6.1426721e-03 2.9189037e-03 1.0083175e-03 2.2713681e-03 3.9595770e-04 7.2341855e-03 8.8447009e-03 1.1230173e-05 5.1389929e-03 2.4707449e-03 5.4731760e-03 5.1980845e-04 4.3112681e-03 2.1787917e-03 7.2534046e-03 6.7672528e-04 5.6623211e-03 9.1277214e-03 7.3619628e-04 3.7016392e-04 3.2564607e-03 4.9531882e-03 4.5742792e-03 1.6438776e-02 2.5714996e-03 2.1421258e-03 2.3256067e-03 1.0175775e-02 8.4088183e-03 2.7613050e-03 2.4755840e-04 6.0873636e-04 4.6703189e-03 2.2089026e-03 5.5642336e-03 3.7824549e-04 4.1878969e-03 2.0462491e-03 7.3148116e-03 5.4583143e-04 6.1390745e-03 8.7247882e-03 9.1073145e-04 4.9034572e-04 2.9664521e-03 4.5041455e-03 4.3650355e-03 1.5605807e-02 2.7148441e-03 2.1951828e-03 2.2077213e-03 9.5777719e-03 8.0120192e-03 2.4278861e-03 3.2552080e-04 7.3734328e-04 1.7636357e-03 1.2290813e-02 2.3919392e-03 6.5534766e-03 4.2355076e-03 1.3428854e-02 2.7760250e-03 2.0719142e-02 5.3736931e-03 9.3604766e-03 7.8350168e-03 1.9437509e-03 2.3451546e-04 4.9805974e-03 3.4615227e-03 1.0520423e-02 8.1642247e-03 4.6947450e-03 2.2490758e-03 4.7893620e-03 5.2359029e-04 6.8110246e-03 8.2524171e-03 1.3046714e-02 1.1318623e-03 8.6855001e-03 5.4130623e-04 1.5131426e-02 5.6179632e-04 1.5407719e-02 1.0669118e-02 5.8683852e-03 3.5797271e-03 6.2414181e-05 2.6714308e-03 7.7088950e-03 9.8081718e-03 9.2964166e-03 7.7221233e-03 5.7330158e-03 7.6711675e-03 9.7842038e-03 1.6419007e-03 2.8364539e-03 3.5173281e-03 6.5335900e-03 1.1340078e-03 1.4192754e-02 1.5964523e-04 8.8481511e-03 5.2711173e-03 5.4383051e-03 3.8856537e-03 6.9538378e-03 1.4900562e-02 9.8443835e-03 2.2013577e-03 2.1746585e-02 7.5284963e-04 7.7091107e-04 1.8026328e-03 1.1463429e-02 5.3229428e-03 7.8904169e-03 7.2583306e-03 8.1944055e-03 3.9135288e-03 1.7196090e-03 8.1113282e-03 2.2942459e-04 9.3463740e-03 6.8261058e-03 2.3665724e-03 1.6309596e-03 1.7256268e-03 2.3397606e-03 3.5922701e-03 1.1208568e-02 3.9888853e-03 2.9455145e-03 1.9660659e-03 6.5467152e-03 6.1492489e-03 9.3538874e-04 1.2212079e-03 1.9267388e-03 1.0793365e-02 1.2592720e-03 6.0147390e-03 9.1609131e-03 1.8537817e-03 4.5335508e-03 6.6172179e-03 1.0131803e-02 4.6089934e-03 1.7595473e-04 1.2987364e-02 1.8331853e-03 9.7087402e-04 3.3609260e-04 5.4018686e-03 1.7068395e-03 3.6646912e-03 6.4787894e-03 7.7901480e-03 1.6754655e-02 6.9641544e-04 1.3182224e-02 1.4651385e-02 4.9466239e-03 2.3931163e-03 5.9263439e-04 5.4211666e-03 1.0221921e-02 1.4928620e-02 9.4586856e-03 8.3819492e-03 7.3339215e-03 1.2011676e-02 1.3620169e-02 3.6119007e-03 1.8435886e-03 2.0979826e-03 1.0794235e-02 6.9811950e-03 4.9473584e-03 5.5993500e-03 9.1192858e-03 1.7103671e-02 1.0654852e-02 2.2936354e-03 2.1887320e-02 1.6039412e-03 1.5236521e-03 2.3684718e-03 1.1405606e-02 4.9416620e-03 8.9601309e-03 9.4128890e-03 1.0537337e-02 1.0144176e-02 9.3650956e-03 2.8049928e-03 1.4261619e-03 9.6795720e-04 3.1673467e-03 5.6308712e-03 1.2399657e-02 5.4889906e-03 4.4629844e-03 3.5148873e-03 8.2921709e-03 8.5570702e-03 1.5767832e-03 9.7941910e-04 1.5044401e-03 1.9162648e-02 2.3258011e-03 4.3611697e-03 1.7154674e-02 1.9266334e-02 1.1399040e-02 3.8294804e-02 2.8052973e-03 4.2987486e-03 8.1194560e-03 2.5933333e-02 1.8564970e-02 1.4940871e-02 5.2230072e-03 4.8296564e-03 1.1136786e-02 1.2996602e-02 1.1896568e-02 3.3692870e-03 1.0295085e-03 6.7928621e-03 7.3341015e-03 5.3674586e-03 2.6380919e-03 1.7126363e-03 1.9252416e-05 3.9628066e-03 1.2371798e-02 1.4417093e-02 5.5916770e-04 7.0172680e-03 8.6736288e-03 5.5025710e-03 2.2796596e-02 1.2316222e-03 1.4793666e-03 2.9451077e-03 1.4303806e-02 1.0475492e-02 5.7470026e-03 7.8882742e-04 9.0526661e-04 4.3645694e-03 7.8632956e-03 7.2260963e-03 2.1331409e-02 3.2601592e-03 3.2514734e-03 4.2300937e-03 1.4385386e-02 1.2160577e-02 5.0215597e-03 4.3279739e-05 5.1818418e-05 3.0767343e-03 9.0015857e-03 9.8042907e-03 1.0868316e-02 9.1698320e-03 6.9442206e-03 8.2610449e-03 1.0963075e-02 2.1355881e-03 3.5431999e-03 4.2180590e-03 3.2143555e-03 3.3819870e-03 8.8162037e-03 6.5643841e-03 3.2940615e-03 1.2995092e-03 2.9075684e-03 3.1897532e-04 6.9331287e-03 8.4863836e-03 1.0164058e-02 2.9210959e-03 1.7078622e-03 4.0814516e-04 3.6297378e-03 8.7693352e-04 2.6826046e-03 6.9132822e-03 8.3825591e-03 2.1963225e-02 1.8183756e-02 1.2010413e-02 1.7351817e-03 6.4958425e-03 5.7545512e-03 1.9704198e-02 2.2181841e-02 1.8230646e-04 1.5254865e-03 1.2273284e-02 6.9788794e-03 6.3577637e-03 3.5631537e-03 4.1101326e-03 6.5324999e-04 9.4729463e-03 5.0293123e-03 4.5622977e-03 3.3814637e-03 4.1233865e-03 5.1615257e-03 2.3326030e-03 2.1577255e-03 4.0325048e-03 5.1426622e-03 1.5351757e-03 2.6422594e-03 1.3282600e-02 1.5461999e-02 3.4307479e-03 1.1531055e-02 1.3518551e-02 4.2918744e-03 5.5398788e-03 8.4122900e-05 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-correlation-ml.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-correlation-ml.txt new file mode 100644 index 0000000000000000000000000000000000000000..2a17a2a8fb002493fff38c7ed059668867768a7e --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-correlation-ml.txt @@ -0,0 +1 @@ + 9.2507465e-01 9.6528566e-01 8.7255441e-01 1.1287379e+00 8.7318727e-01 1.0767102e+00 9.1419676e-01 1.1503304e+00 9.8074509e-01 1.0135025e+00 1.0495025e+00 9.4794536e-01 9.6829273e-01 1.1345767e+00 1.1048008e+00 9.2407796e-01 1.0228634e+00 9.3853195e-01 9.9377619e-01 1.0407662e+00 9.5048989e-01 9.0465688e-01 9.8056930e-01 8.9777156e-01 9.6357127e-01 9.3864452e-01 9.9754613e-01 9.7271356e-01 8.4383151e-01 9.6981983e-01 9.7510267e-01 1.0112663e+00 7.8730400e-01 1.0299498e+00 9.9307979e-01 9.0239520e-01 8.5428231e-01 8.8972742e-01 8.5933162e-01 9.6625934e-01 9.4175449e-01 9.9120729e-01 1.0503963e+00 8.8223053e-01 1.3261434e+00 1.1063209e+00 8.4058398e-01 1.0844267e+00 1.1153093e+00 1.0092643e+00 8.9585237e-01 1.0599818e+00 1.2321707e+00 1.1359624e+00 8.3503556e-01 1.1792243e+00 7.9159781e-01 1.0830419e+00 1.2181870e+00 9.9888500e-01 1.0227144e+00 6.8557277e-01 9.6836193e-01 1.1061227e+00 1.0883453e+00 9.5681974e-01 9.9436299e-01 1.0304323e+00 1.1273949e+00 1.0735563e+00 1.0582583e+00 9.6040272e-01 1.0032137e+00 8.4900547e-01 1.1035351e+00 8.7867480e-01 9.6433176e-01 9.1850122e-01 8.9337435e-01 1.0449390e+00 8.9639384e-01 9.6704971e-01 1.0084258e+00 1.0528587e+00 1.1764481e+00 1.0913280e+00 1.0136672e+00 1.2737156e+00 9.5130359e-01 1.0367909e+00 1.1983402e+00 1.1319901e+00 1.1117462e+00 1.0343695e+00 1.0838628e+00 7.5266057e-01 1.0763316e+00 8.8067924e-01 9.6734383e-01 9.8800551e-01 1.2265742e+00 7.8833055e-01 1.0338670e+00 8.6666625e-01 9.9039950e-01 9.7142684e-01 9.3138616e-01 8.5849977e-01 8.5486301e-01 1.0516028e+00 1.1105313e+00 9.5943505e-01 9.8845171e-01 1.0566288e+00 9.9712198e-01 9.5545756e-01 1.1817974e+00 9.9128482e-01 1.0117892e+00 1.0979115e+00 1.0493943e+00 9.1318848e-01 9.3157311e-01 8.7073304e-01 1.2459441e+00 9.3412689e-01 1.0482297e+00 9.4224032e-01 9.5134153e-01 9.0857493e-01 9.7264161e-01 8.2900820e-01 9.3140549e-01 1.1330242e+00 1.0333002e+00 1.0117861e+00 1.2053255e+00 8.5291396e-01 1.0148928e+00 8.6641379e-01 9.7080819e-01 9.5457159e-01 9.5207457e-01 9.3539674e-01 9.0769069e-01 9.5322590e-01 1.1181803e+00 9.9765614e-01 7.5370610e-01 1.0807114e+00 1.0804601e+00 9.0214124e-01 8.7101998e-01 1.0167435e+00 1.2045936e+00 8.7300539e-01 1.1054300e+00 7.9145574e-01 1.0279340e+00 8.7623462e-01 1.0034756e+00 1.0386933e+00 9.3910970e-01 1.0028455e+00 9.9868824e-01 9.8752945e-01 9.8319327e-01 1.3110209e+00 8.6180633e-01 1.0993856e+00 8.5912563e-01 1.1303979e+00 9.8690459e-01 9.6910090e-01 9.1456819e-01 1.1525339e+00 1.1064552e+00 1.1062255e+00 9.7226683e-01 1.1091447e+00 1.1072238e+00 9.6544444e-01 9.6681036e-01 9.3247685e-01 9.6854634e-01 1.1035119e+00 1.1317148e+00 9.5557793e-01 9.8908485e-01 7.4873648e-01 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-cosine-ml-iris.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-cosine-ml-iris.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b705b348fc3de5041ad9e3d6a1686af61046b2a --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-cosine-ml-iris.txt @@ -0,0 +1 @@ + 1.4208365e-03 1.2652718e-05 8.9939315e-04 2.4232332e-04 9.9747033e-04 9.2045721e-04 2.2040648e-04 8.6480051e-04 1.2354911e-03 5.3650090e-06 1.0275886e-03 1.1695784e-03 2.3556571e-04 1.4590172e-03 1.8981327e-03 1.0939621e-03 1.2392314e-04 3.5850877e-04 8.6078038e-04 1.4490833e-03 8.4059347e-04 3.2873982e-03 2.7359832e-03 4.1316044e-03 2.7719149e-03 1.1814143e-03 1.1431285e-04 2.3850299e-04 1.3446247e-03 1.6406549e-03 1.2070654e-03 2.2241257e-03 1.4969348e-03 1.2354911e-03 7.6154552e-04 9.0853884e-04 1.2354911e-03 1.5825612e-04 2.3716586e-04 2.5806020e-04 8.5870759e-03 4.3447170e-04 2.6103416e-03 3.4026094e-03 1.2625429e-03 1.0000714e-03 2.7088099e-04 4.6161202e-05 1.7993015e-04 7.1619641e-02 7.4013940e-02 8.2336355e-02 9.3599031e-02 8.6542298e-02 9.2667602e-02 8.0934616e-02 6.7002415e-02 7.9695318e-02 8.3991107e-02 8.8330128e-02 7.6449243e-02 8.6123390e-02 9.1414445e-02 5.9767596e-02 6.8589764e-02 9.2363748e-02 7.5261304e-02 1.0768528e-01 7.8250149e-02 9.7383870e-02 6.9410330e-02 1.0895936e-01 9.1644587e-02 7.2677910e-02 7.2208930e-02 8.7635618e-02 9.3586395e-02 8.7700193e-02 5.8825053e-02 7.9271072e-02 7.4136423e-02 7.0977606e-02 1.1670751e-01 9.6691498e-02 7.7157266e-02 7.8793137e-02 9.6187418e-02 7.4355610e-02 8.6677009e-02 9.7286808e-02 8.5214421e-02 7.7419803e-02 6.8888638e-02 8.6192502e-02 7.4757686e-02 7.8851331e-02 7.5042247e-02 5.2484298e-02 7.8023694e-02 1.3991867e-01 1.2655756e-01 1.2099780e-01 1.2515784e-01 1.3134370e-01 1.3306336e-01 1.2911903e-01 1.2854613e-01 1.3655327e-01 1.1601604e-01 9.9632498e-02 1.2063863e-01 1.1404742e-01 1.3409335e-01 1.3451976e-01 1.1368563e-01 1.1469397e-01 1.1505768e-01 1.5479411e-01 1.2906390e-01 1.1634186e-01 1.2299625e-01 1.3892070e-01 1.0732534e-01 1.1401190e-01 1.1254699e-01 1.0266168e-01 1.0210743e-01 1.3111378e-01 1.0950615e-01 1.2501276e-01 1.0108759e-01 1.3297245e-01 1.0624129e-01 1.3360037e-01 1.2002867e-01 1.2233784e-01 1.1387071e-01 1.0061412e-01 1.0649150e-01 1.2174429e-01 1.0147290e-01 1.2655756e-01 1.2438709e-01 1.2138109e-01 1.1044406e-01 1.1910000e-01 1.0821359e-01 1.1609070e-01 1.1329724e-01 1.2085473e-03 1.2060695e-03 2.7592041e-03 3.0736184e-03 3.7201033e-03 1.0861043e-03 7.3910902e-04 3.4790667e-04 1.3491546e-03 2.4493052e-03 1.8482587e-04 2.3308566e-03 3.8997403e-03 6.3069928e-03 4.1362617e-03 1.5079538e-03 7.4890015e-04 4.0049414e-03 3.0763412e-04 3.2877725e-03 8.6909088e-03 1.8863199e-03 4.7592122e-03 4.5180751e-04 1.7148301e-03 8.8703626e-04 5.7128783e-04 1.7151033e-03 8.4814176e-04 4.7551630e-04 6.9313334e-03 5.8126778e-03 3.4790667e-04 9.7078221e-04 1.0390338e-03 3.4790667e-04 1.1371495e-03 7.0598263e-04 2.3100870e-03 3.1332241e-03 2.9870115e-03 3.7693564e-03 5.5008337e-03 2.0081767e-04 3.9261497e-03 1.6237803e-03 1.7731168e-03 5.9153033e-04 5.9997244e-02 6.3706418e-02 7.0131342e-02 8.0131815e-02 7.3670020e-02 8.1412444e-02 7.1132932e-02 5.6572408e-02 6.7223691e-02 7.3993918e-02 7.4363256e-02 6.6371013e-02 7.1106157e-02 7.9730716e-02 5.0610503e-02 5.7285563e-02 8.2536028e-02 6.3695818e-02 9.1877918e-02 6.6044079e-02 8.7700525e-02 5.7975072e-02 9.4407127e-02 7.9385033e-02 6.0900938e-02 6.0521931e-02 7.4070557e-02 8.1073873e-02 7.6438218e-02 4.7634460e-02 6.6728846e-02 6.1732271e-02 5.9656897e-02 1.0363139e-01 8.7312695e-02 6.8806126e-02 6.7142432e-02 8.0911573e-02 6.5091322e-02 7.4541034e-02 8.5313436e-02 7.4229332e-02 6.5328348e-02 5.7461491e-02 7.4891760e-02 6.5136264e-02 6.8598864e-02 6.3641018e-02 4.2790811e-02 6.7276779e-02 1.2872765e-01 1.1385917e-01 1.0708423e-01 1.1221780e-01 1.1844388e-01 1.1798239e-01 1.1767648e-01 1.1356773e-01 1.2073038e-01 1.0467824e-01 8.8441784e-02 1.0671832e-01 1.0091826e-01 1.2051300e-01 1.2244533e-01 1.0247664e-01 1.0203920e-01 1.0334656e-01 1.3764340e-01 1.1314999e-01 1.0390175e-01 1.1148602e-01 1.2274267e-01 9.3929112e-02 1.0239198e-01 9.9372667e-02 9.0109024e-02 9.0770318e-02 1.1749345e-01 9.5509620e-02 1.0956056e-01 8.9331297e-02 1.1936188e-01 9.3207628e-02 1.1935153e-01 1.0516553e-01 1.1204585e-01 1.0191688e-01 8.9582588e-02 9.3806716e-02 1.0922100e-01 8.9087100e-02 1.1385917e-01 1.1193127e-01 1.0978099e-01 9.7766696e-02 1.0448839e-01 9.5849546e-02 1.0619992e-01 1.0212555e-01 7.8301662e-04 3.3186074e-04 9.6097551e-04 9.6384587e-04 1.7160230e-04 7.1714495e-04 1.0915291e-03 1.4406904e-05 9.9431295e-04 1.0280837e-03 3.4520010e-04 1.6070142e-03 2.0814960e-03 1.1810349e-03 9.3270090e-05 2.4892291e-04 9.5000112e-04 1.2447556e-03 8.3736374e-04 3.6303226e-03 2.4141846e-03 3.9965261e-03 2.4688022e-03 1.0115165e-03 6.9871786e-05 1.7487334e-04 1.2251185e-03 1.4398826e-03 9.8199498e-04 2.5137187e-03 1.7466742e-03 1.0915291e-03 7.0690363e-04 8.5846505e-04 1.0915291e-03 1.0992291e-04 1.6427013e-04 2.8562896e-04 8.0123750e-03 5.0490687e-04 2.4076078e-03 3.3222239e-03 1.0270492e-03 1.0987887e-03 2.4862356e-04 7.8815959e-05 1.1120052e-04 7.0071463e-02 7.2494258e-02 8.0694698e-02 9.1816479e-02 8.4823937e-02 9.1055284e-02 7.9406161e-02 6.5540015e-02 7.8075821e-02 8.2418924e-02 8.6586217e-02 7.4908999e-02 8.4375857e-02 8.9771433e-02 5.8365951e-02 6.7055640e-02 9.0792516e-02 7.3755504e-02 1.0570869e-01 7.6652799e-02 9.5758989e-02 6.7858347e-02 1.0707149e-01 9.0015148e-02 7.1111432e-02 7.0634591e-02 8.5909852e-02 9.1841705e-02 8.6060650e-02 5.7382885e-02 7.7642663e-02 7.2560884e-02 6.9439824e-02 1.1486601e-01 9.5132094e-02 7.5722276e-02 7.7186494e-02 9.4329550e-02 7.2913445e-02 8.4999890e-02 9.5631654e-02 8.3632299e-02 7.5814411e-02 6.7360493e-02 8.4581854e-02 7.3324210e-02 7.7335911e-02 7.3484711e-02 5.1093482e-02 7.6474851e-02 1.3800148e-01 1.2463801e-01 1.1904450e-01 1.2328593e-01 1.2938789e-01 1.3104169e-01 1.2726294e-01 1.2658511e-01 1.3448678e-01 1.1418055e-01 9.7888383e-02 1.1868360e-01 1.1213978e-01 1.3206545e-01 1.3251384e-01 1.1184454e-01 1.1286955e-01 1.1328841e-01 1.5256500e-01 1.2703121e-01 1.1444439e-01 1.2112577e-01 1.3684054e-01 1.0544428e-01 1.1220824e-01 1.1073079e-01 1.0084086e-01 1.0036834e-01 1.2912019e-01 1.0768201e-01 1.2300696e-01 9.9385216e-02 1.3095409e-01 1.0446385e-01 1.3171213e-01 1.1800444e-01 1.2052688e-01 1.1209190e-01 9.8892088e-02 1.0463359e-01 1.1979721e-01 9.9600101e-02 1.2463801e-01 1.2247195e-01 1.1948197e-01 1.0852184e-01 1.1709036e-01 1.0637133e-01 1.1433097e-01 1.1154058e-01 1.2829581e-03 8.6520525e-04 1.3042912e-03 2.3052671e-04 6.0609671e-05 6.1408538e-04 7.9384016e-04 2.5551469e-04 9.4346154e-04 1.8930050e-03 4.6203036e-03 3.8649853e-03 3.3273220e-03 9.7135787e-04 2.5836286e-04 1.6395377e-03 4.6720392e-04 1.3833444e-03 6.8585778e-03 1.1817616e-03 1.4184724e-03 1.2935682e-03 4.4534899e-04 4.3337262e-04 9.9734142e-04 6.2957380e-05 2.1802414e-04 1.3452346e-03 3.6759458e-03 3.7514511e-03 6.1408538e-04 2.3527566e-03 2.5967147e-03 6.1408538e-04 3.1896708e-04 3.0643540e-04 1.7034162e-03 7.0964884e-03 1.0371098e-03 1.9760564e-03 1.6993217e-03 9.2490489e-04 1.2129757e-03 2.8785057e-04 7.8777499e-04 6.4144968e-04 5.7636535e-02 5.9786679e-02 6.7275391e-02 7.7706661e-02 7.1288776e-02 7.6308806e-02 6.5987844e-02 5.3398709e-02 6.4839697e-02 6.8887148e-02 7.2874646e-02 6.2111692e-02 7.1088473e-02 7.5274214e-02 4.7295630e-02 5.5048251e-02 7.6266639e-02 6.0532100e-02 9.0997542e-02 6.3501941e-02 8.1155480e-02 5.5841790e-02 9.1620605e-02 7.5304976e-02 5.8627379e-02 5.8302297e-02 7.2188128e-02 7.7632065e-02 7.2128571e-02 4.6353347e-02 6.4522763e-02 5.9860052e-02 5.7075256e-02 9.8501473e-02 8.0208982e-02 6.2676929e-02 6.4117314e-02 8.0306154e-02 5.9903400e-02 7.1264506e-02 8.0454669e-02 6.9667510e-02 6.2855874e-02 5.5234852e-02 7.0611788e-02 6.0083969e-02 6.3933681e-02 6.0638614e-02 4.1119113e-02 6.3291748e-02 1.2072945e-01 1.0797760e-01 1.0284307e-01 1.0630032e-01 1.1246316e-01 1.1377579e-01 1.1035397e-01 1.0939330e-01 1.1704519e-01 9.8543065e-02 8.3389076e-02 1.0253622e-01 9.6610654e-02 1.1523295e-01 1.1624035e-01 9.6621030e-02 9.6718555e-02 9.7003685e-02 1.3426257e-01 1.1013293e-01 9.8838972e-02 1.0496266e-01 1.1920082e-01 9.0400878e-02 9.6352086e-02 9.4617133e-02 8.6118226e-02 8.5443225e-02 1.1226469e-01 9.1815383e-02 1.0642172e-01 8.4132371e-02 1.1413570e-01 8.8823115e-02 1.1373227e-01 1.0228600e-01 1.0454965e-01 9.5917796e-02 8.4129252e-02 8.9732713e-02 1.0404039e-01 8.5714179e-02 1.0797760e-01 1.0611357e-01 1.0375975e-01 9.3828435e-02 1.0141953e-01 9.1231247e-02 9.8764813e-02 9.5558448e-02 7.0033377e-04 3.9650610e-04 5.3529876e-04 1.4703029e-03 2.2471049e-03 2.6137215e-04 9.1585095e-04 2.3098853e-03 3.2779352e-04 1.7003275e-03 9.5035099e-04 8.4163249e-04 3.6423601e-04 8.6760304e-04 2.6110376e-04 2.4965606e-03 5.0990123e-04 2.2208392e-03 3.4995017e-03 3.9813106e-03 4.2652650e-03 1.4776191e-03 5.3856223e-04 9.6152184e-04 1.6178695e-03 2.4296336e-03 2.2824176e-03 1.0483334e-03 6.6735604e-04 2.2471049e-03 1.7166964e-03 1.9224889e-03 2.2471049e-03 4.4953685e-04 7.5090712e-04 3.1050470e-04 1.1530910e-02 8.0837373e-05 2.6173161e-03 2.7612054e-03 2.3974656e-03 3.9140870e-04 3.5730731e-04 1.1232648e-04 8.0278741e-04 7.4728046e-02 7.6441141e-02 8.5477412e-02 9.7141382e-02 8.9947057e-02 9.5081677e-02 8.2962705e-02 6.9633999e-02 8.3013931e-02 8.6069979e-02 9.2215558e-02 7.8736928e-02 9.0603515e-02 9.4074986e-02 6.2034704e-02 7.1640320e-02 9.4150759e-02 7.8195110e-02 1.1214391e-01 8.1468219e-02 9.9059263e-02 7.2514318e-02 1.1269547e-01 9.4545020e-02 7.5842542e-02 7.5358360e-02 9.1332869e-02 9.6662705e-02 9.0277244e-02 6.2066860e-02 8.2644288e-02 7.7554694e-02 7.3959493e-02 1.1955630e-01 9.8181734e-02 7.8602674e-02 8.1755435e-02 1.0058819e-01 7.6248524e-02 8.9701900e-02 9.9938282e-02 8.7676596e-02 8.0619290e-02 7.1976555e-02 8.8793557e-02 7.6779152e-02 8.1107438e-02 7.7952944e-02 5.5245517e-02 8.0550459e-02 1.4162183e-01 1.2912349e-01 1.2423521e-01 1.2779447e-01 1.3393410e-01 1.3660889e-01 1.3105158e-01 1.3208577e-01 1.4040000e-01 1.1817736e-01 1.0200650e-01 1.2388995e-01 1.1706801e-01 1.3699958e-01 1.3682207e-01 1.1586916e-01 1.1739162e-01 1.1729454e-01 1.5902469e-01 1.3308573e-01 1.1901641e-01 1.2511327e-01 1.4289089e-01 1.1059070e-01 1.1627926e-01 1.1550831e-01 1.0561378e-01 1.0446495e-01 1.3405102e-01 1.1291439e-01 1.2888996e-01 1.0359625e-01 1.3590097e-01 1.0925250e-01 1.3665207e-01 1.2379539e-01 1.2392962e-01 1.1624448e-01 1.0286550e-01 1.0945264e-01 1.2440339e-01 1.0449561e-01 1.2912349e-01 1.2690130e-01 1.2362142e-01 1.1341467e-01 1.2276171e-01 1.1097585e-01 1.1759891e-01 1.1534218e-01 1.3143808e-04 7.3710840e-04 1.1313742e-03 2.6277162e-03 9.9332749e-04 4.8298989e-04 2.9659782e-03 1.8303797e-03 3.9657692e-03 1.4753738e-03 1.6266891e-03 7.0233916e-04 8.0313831e-04 3.4526160e-04 2.3291483e-03 1.3867759e-04 4.2228272e-03 1.6991343e-03 2.3223655e-03 3.8453210e-03 4.2904903e-04 9.9302567e-04 1.7706867e-03 9.4981017e-04 1.8259864e-03 2.0820613e-03 2.1473879e-03 2.0420431e-03 2.6277162e-03 3.0779094e-03 3.4332541e-03 2.6277162e-03 6.3280964e-04 1.0576914e-03 9.5198627e-04 1.0925795e-02 3.7286463e-04 7.9546610e-04 9.1841431e-04 2.1468126e-03 4.9129575e-04 4.3562197e-04 7.5083238e-04 1.3686608e-03 6.3901299e-02 6.4740623e-02 7.3708779e-02 8.4613714e-02 7.7866771e-02 8.2261058e-02 7.0449151e-02 5.8874682e-02 7.1767088e-02 7.3210535e-02 8.0660949e-02 6.6601983e-02 8.0033785e-02 8.1391959e-02 5.1369939e-02 6.0897790e-02 8.0716992e-02 6.7403323e-02 9.9203670e-02 7.0276809e-02 8.4922276e-02 6.1688045e-02 9.9339240e-02 8.2362360e-02 6.4928234e-02 6.4360101e-02 7.9641814e-02 8.3721620e-02 7.7549963e-02 5.2617898e-02 7.1414187e-02 6.6946935e-02 6.3031902e-02 1.0509118e-01 8.4332170e-02 6.6064468e-02 7.0064616e-02 8.8758294e-02 6.4379548e-02 7.7371173e-02 8.7052850e-02 7.5305342e-02 6.9340944e-02 6.1339869e-02 7.6377320e-02 6.5179636e-02 6.9093895e-02 6.6669498e-02 4.5609365e-02 6.8684945e-02 1.2445912e-01 1.1341836e-01 1.0935772e-01 1.1262566e-01 1.1789507e-01 1.2147174e-01 1.1488682e-01 1.1752559e-01 1.2531063e-01 1.0271865e-01 8.7888567e-02 1.0902443e-01 1.0234160e-01 1.2080033e-01 1.1990073e-01 1.0043696e-01 1.0286413e-01 1.0252340e-01 1.4292168e-01 1.1866325e-01 1.0381139e-01 1.0919240e-01 1.2785249e-01 9.6570465e-02 1.0127523e-01 1.0149554e-01 9.1688518e-02 9.0323099e-02 1.1822766e-01 9.9584713e-02 1.1452014e-01 9.0018133e-02 1.1983081e-01 9.5741335e-02 1.2190290e-01 1.0915996e-01 1.0773474e-01 1.0161859e-01 8.8729453e-02 9.5169428e-02 1.0868349e-01 9.0278091e-02 1.1341836e-01 1.1118524e-01 1.0767597e-01 9.8555096e-02 1.0809822e-01 9.6490550e-02 1.0179914e-01 1.0040847e-01 9.0953179e-04 1.6478123e-03 3.1324421e-03 9.3747882e-04 6.8074049e-04 3.4285457e-03 1.4256139e-03 3.3141786e-03 8.1135619e-04 1.2040955e-03 7.3894006e-04 1.1469835e-03 5.4914496e-05 3.0238895e-03 1.1512346e-04 2.9874978e-03 2.7356591e-03 2.9755481e-03 4.8570629e-03 9.8132331e-04 1.1267736e-03 1.9187302e-03 1.4320892e-03 2.5472569e-03 2.7129147e-03 1.2621760e-03 1.1868918e-03 3.1324421e-03 3.1260816e-03 3.4622842e-03 3.1324421e-03 7.8737454e-04 1.2923124e-03 7.7291736e-04 1.2676988e-02 1.5795155e-04 1.4073300e-03 1.3093851e-03 2.8558230e-03 2.3589004e-04 5.3160641e-04 6.3306680e-04 1.5563919e-03 6.9394652e-02 7.0160248e-02 7.9549278e-02 9.0909253e-02 8.3929778e-02 8.8133516e-02 7.5949213e-02 6.4094635e-02 7.7538115e-02 7.8838295e-02 8.6828513e-02 7.2078729e-02 8.6190925e-02 8.7328483e-02 5.6305232e-02 6.6307663e-02 8.6433769e-02 7.2861306e-02 1.0610432e-01 7.5977192e-02 9.0782134e-02 6.7147548e-02 1.0605640e-01 8.8295560e-02 7.0476640e-02 6.9912539e-02 8.5755505e-02 8.9909894e-02 8.3415192e-02 5.7694397e-02 7.7198547e-02 7.2551886e-02 6.8485682e-02 1.1174631e-01 9.0047290e-02 7.1258462e-02 7.5770197e-02 9.5276007e-02 6.9606963e-02 8.3332111e-02 9.3091350e-02 8.1019819e-02 7.5041473e-02 6.6748030e-02 8.2172293e-02 7.0413691e-02 7.4567733e-02 7.2221920e-02 5.0422561e-02 7.4234075e-02 1.3135838e-01 1.2029572e-01 1.1630277e-01 1.1941581e-01 1.2489530e-01 1.2871814e-01 1.2159882e-01 1.2460620e-01 1.3270425e-01 1.0925415e-01 9.4076611e-02 1.1596894e-01 1.0908894e-01 1.2799150e-01 1.2695158e-01 1.0694484e-01 1.0944639e-01 1.0895711e-01 1.5084375e-01 1.2591962e-01 1.1052596e-01 1.1587184e-01 1.3530738e-01 1.0320818e-01 1.0775506e-01 1.0806337e-01 9.8123191e-02 9.6541726e-02 1.2533326e-01 1.0616585e-01 1.2166800e-01 9.6181548e-02 1.2699662e-01 1.0216112e-01 1.2885603e-01 1.1626103e-01 1.1421827e-01 1.0807124e-01 9.4882428e-02 1.0171954e-01 1.1554226e-01 9.6763759e-02 1.2029572e-01 1.1801757e-01 1.1438908e-01 1.0525128e-01 1.1515210e-01 1.0301668e-01 1.0810316e-01 1.0676998e-01 2.4407151e-04 6.8243680e-04 1.6882982e-04 4.2217018e-04 8.1245396e-04 8.1915702e-04 2.7980568e-03 2.6783721e-03 2.0076713e-03 3.3526400e-04 9.3506008e-05 1.0407900e-03 7.3148476e-04 9.1895790e-04 4.8425923e-03 1.7878106e-03 2.5638304e-03 1.8092053e-03 6.2482332e-04 4.5470127e-05 3.8680919e-04 4.8577398e-04 7.0932539e-04 1.0773286e-03 2.7081281e-03 2.3916675e-03 6.8243680e-04 1.3234869e-03 1.5152295e-03 6.8243680e-04 1.7279927e-05 4.4719936e-05 7.6774714e-04 7.6386402e-03 5.1509749e-04 2.1386706e-03 2.3673979e-03 8.8641907e-04 8.8317423e-04 5.7646989e-05 1.8767975e-04 1.8238427e-04 6.4591491e-02 6.6891146e-02 7.4787553e-02 8.5653640e-02 7.8909235e-02 8.4481757e-02 7.3468926e-02 6.0165176e-02 7.2232139e-02 7.6459237e-02 8.0572670e-02 6.9287036e-02 7.8547451e-02 8.3338681e-02 5.3514192e-02 6.1787978e-02 8.4336540e-02 6.7840538e-02 9.9351761e-02 7.0839680e-02 8.9318727e-02 6.2598635e-02 1.0029777e-01 8.3444651e-02 6.5618944e-02 6.5228710e-02 7.9886645e-02 8.5622882e-02 7.9922508e-02 5.2526388e-02 7.1863670e-02 6.6948234e-02 6.3994975e-02 1.0763490e-01 8.8479248e-02 6.9931400e-02 7.1440370e-02 8.8224815e-02 6.7118281e-02 7.8968665e-02 8.8858891e-02 7.7432758e-02 7.0109240e-02 6.2023845e-02 7.8396402e-02 6.7393801e-02 7.1380489e-02 6.7813026e-02 4.6767795e-02 7.0645561e-02 1.3044475e-01 1.1734304e-01 1.1197394e-01 1.1577499e-01 1.2198760e-01 1.2346289e-01 1.1982320e-01 1.1899008e-01 1.2683842e-01 1.0736476e-01 9.1564623e-02 1.1164167e-01 1.0538958e-01 1.2475783e-01 1.2551509e-01 1.0524662e-01 1.0574315e-01 1.0607279e-01 1.4459461e-01 1.1962188e-01 1.0766800e-01 1.1407280e-01 1.2909426e-01 9.8905414e-02 1.0524346e-01 1.0359925e-01 9.4433579e-02 9.3820759e-02 1.2176744e-01 1.0065671e-01 1.1574436e-01 9.2625059e-02 1.2364363e-01 9.7538593e-02 1.2367543e-01 1.1121391e-01 1.1355049e-01 1.0493323e-01 9.2419908e-02 9.8167154e-02 1.1298864e-01 9.3668541e-02 1.1734304e-01 1.1533257e-01 1.1267510e-01 1.0222063e-01 1.1031800e-01 9.9779829e-02 1.0752614e-01 1.0448251e-01 3.8330702e-04 7.6710204e-04 5.4934344e-04 6.1141025e-04 1.8880070e-03 4.3782366e-03 4.2558302e-03 3.3445116e-03 9.0730658e-04 1.6460272e-04 1.9935351e-03 2.2277110e-04 1.5935452e-03 7.2001884e-03 1.0201171e-03 1.9163397e-03 8.7300929e-04 4.6754224e-04 3.6671499e-04 7.4258415e-04 2.1567602e-04 1.3361003e-04 9.1168360e-04 4.3156597e-03 4.1158943e-03 3.8330702e-04 1.9019978e-03 2.1146706e-03 3.8330702e-04 3.1982857e-04 2.1854146e-04 1.6719903e-03 5.9155088e-03 1.3110961e-03 2.0595508e-03 2.2774590e-03 5.2912957e-04 1.6598142e-03 4.0619000e-04 8.5702191e-04 4.6128261e-04 5.7335316e-02 5.9791552e-02 6.7034247e-02 7.7315388e-02 7.0912461e-02 7.6541197e-02 6.6231857e-02 5.3290914e-02 6.4524455e-02 6.9096848e-02 7.2330829e-02 6.2164647e-02 7.0266106e-02 7.5359485e-02 4.7211115e-02 5.4717217e-02 7.6724195e-02 6.0437574e-02 9.0217835e-02 6.3227153e-02 8.1624838e-02 5.5479636e-02 9.1272977e-02 7.5343817e-02 5.8299412e-02 5.7952393e-02 7.1727180e-02 7.7451339e-02 7.2165967e-02 4.5880845e-02 6.4164650e-02 5.9464600e-02 5.6817377e-02 9.8638775e-02 8.0838937e-02 6.3146715e-02 6.3916551e-02 7.9536591e-02 6.0201366e-02 7.1084400e-02 8.0631146e-02 6.9793274e-02 6.2554472e-02 5.4911579e-02 7.0667171e-02 6.0374722e-02 6.4102637e-02 6.0460719e-02 4.0707229e-02 6.3307106e-02 1.2135312e-01 1.0820155e-01 1.0273439e-01 1.0658023e-01 1.1268914e-01 1.1365695e-01 1.1088857e-01 1.0931070e-01 1.1680946e-01 9.8829208e-02 8.3503653e-02 1.0241354e-01 9.6518124e-02 1.1527856e-01 1.1644011e-01 9.6835948e-02 9.6892604e-02 9.7403729e-02 1.3389056e-01 1.0978147e-01 9.8889679e-02 1.0531384e-01 1.1893855e-01 9.0170315e-02 9.6654705e-02 9.4696682e-02 8.5999457e-02 8.5628213e-02 1.1232778e-01 9.1692367e-02 1.0609783e-01 8.4336563e-02 1.1417833e-01 8.8845800e-02 1.1399156e-01 1.0186496e-01 1.0510756e-01 9.6245658e-02 8.4341961e-02 8.9608741e-02 1.0408154e-01 8.5412047e-02 1.0820155e-01 1.0631639e-01 1.0398240e-01 9.3623884e-02 1.0104040e-01 9.1224725e-02 9.9332091e-02 9.5993921e-02 1.1067957e-03 1.4791390e-03 7.1256747e-05 2.0377231e-03 4.3755431e-03 5.9630791e-03 4.4970379e-03 1.5921641e-03 6.4984761e-04 3.3935862e-03 1.2039709e-04 3.0970780e-03 8.3950153e-03 2.1890332e-03 3.1326528e-03 5.0256002e-04 1.6389584e-03 6.4717383e-04 7.1019942e-04 8.9864077e-04 3.8255378e-04 1.2286350e-03 5.5229901e-03 5.1766813e-03 0.0000000e+00 1.5860612e-03 1.6773969e-03 0.0000000e+00 8.4337656e-04 4.6746407e-04 2.4549978e-03 4.7529836e-03 2.3235808e-03 4.0683267e-03 4.3260986e-03 6.7336618e-04 2.8454658e-03 1.0918918e-03 1.3756658e-03 5.7784546e-04 5.9573290e-02 6.3070670e-02 6.9597309e-02 7.9911457e-02 7.3480528e-02 7.9923883e-02 7.0144874e-02 5.5923876e-02 6.6635620e-02 7.3192589e-02 7.4096565e-02 6.5836734e-02 7.1022277e-02 7.8555696e-02 5.0423423e-02 5.7089619e-02 8.1093473e-02 6.2483167e-02 9.2251714e-02 6.5399221e-02 8.6573432e-02 5.7873871e-02 9.3861710e-02 7.7914479e-02 6.0545459e-02 6.0328179e-02 7.3725736e-02 8.0652769e-02 7.5662466e-02 4.7500835e-02 6.6267157e-02 6.1219907e-02 5.9246920e-02 1.0235525e-01 8.5584812e-02 6.7627185e-02 6.6676399e-02 8.1028522e-02 6.3874534e-02 7.4037098e-02 8.3735875e-02 7.3091049e-02 6.4875922e-02 5.7134332e-02 7.3898502e-02 6.3669341e-02 6.7483654e-02 6.3032151e-02 4.3195391e-02 6.6465430e-02 1.2757303e-01 1.1294171e-01 1.0654531e-01 1.1074736e-01 1.1756538e-01 1.1705185e-01 1.1633100e-01 1.1230305e-01 1.1988948e-01 1.0404710e-01 8.7981667e-02 1.0622547e-01 1.0061669e-01 1.2008497e-01 1.2242153e-01 1.0217012e-01 1.0084187e-01 1.0181343e-01 1.3714147e-01 1.1243585e-01 1.0356517e-01 1.1071692e-01 1.2181923e-01 9.3742899e-02 1.0137566e-01 9.8085445e-02 8.9840814e-02 8.9979544e-02 1.1682155e-01 9.4340727e-02 1.0893096e-01 8.8036209e-02 1.1887723e-01 9.1995894e-02 1.1718099e-01 1.0529554e-01 1.1115622e-01 1.0048991e-01 8.8823715e-02 9.3647258e-02 1.0909883e-01 8.9729548e-02 1.1294171e-01 1.1121254e-01 1.0947844e-01 9.8164553e-02 1.0458423e-01 9.5468337e-02 1.0529433e-01 1.0077315e-01 9.3075268e-04 1.0661545e-03 2.6597529e-04 1.6036733e-03 2.0280056e-03 1.2436972e-03 1.5688801e-04 3.1850165e-04 8.9411637e-04 1.3235015e-03 8.8731482e-04 3.4816593e-03 2.6719247e-03 3.9091992e-03 2.6159373e-03 1.1443019e-03 7.9601608e-05 2.3028989e-04 1.2135551e-03 1.4956336e-03 1.2137749e-03 2.2449952e-03 1.5932074e-03 1.1067957e-03 8.0827056e-04 9.5525701e-04 1.1067957e-03 1.2520454e-04 1.8684214e-04 3.3283736e-04 8.4659292e-03 4.3428627e-04 2.6431662e-03 3.3043825e-03 1.2192723e-03 9.6672170e-04 2.2673224e-04 4.0165289e-05 1.5556464e-04 7.0885985e-02 7.3312749e-02 8.1555170e-02 9.2789394e-02 8.5768022e-02 9.1811327e-02 8.0210428e-02 6.6299983e-02 7.8898236e-02 8.3277528e-02 8.7497229e-02 7.5768419e-02 8.5268176e-02 9.0575828e-02 5.9182538e-02 6.7899308e-02 9.1577973e-02 7.4436351e-02 1.0683101e-01 7.7459472e-02 9.6638219e-02 6.8724317e-02 1.0805306e-01 9.0746123e-02 7.1944393e-02 7.1498544e-02 8.6811878e-02 9.2796163e-02 8.6929388e-02 5.8156140e-02 7.8485798e-02 7.3355880e-02 7.0259533e-02 1.1577796e-01 9.5890635e-02 7.6480264e-02 7.8047377e-02 9.5335392e-02 7.3634293e-02 8.5899063e-02 9.6384778e-02 8.4415996e-02 7.6657094e-02 6.8177250e-02 8.5395861e-02 7.3990972e-02 7.8093423e-02 7.4294151e-02 5.1950910e-02 7.7279181e-02 1.3907744e-01 1.2568112e-01 1.2011323e-01 1.2420710e-01 1.3046004e-01 1.3207399e-01 1.2824918e-01 1.2752552e-01 1.3553911e-01 1.1524115e-01 9.8893820e-02 1.1975932e-01 1.1323008e-01 1.3322963e-01 1.3377253e-01 1.1295596e-01 1.1379378e-01 1.1416138e-01 1.5374990e-01 1.2806482e-01 1.1555054e-01 1.2219358e-01 1.3787989e-01 1.0651347e-01 1.1318026e-01 1.1161431e-01 1.0188137e-01 1.0132199e-01 1.3022140e-01 1.0855236e-01 1.2404638e-01 1.0022528e-01 1.3210134e-01 1.0532767e-01 1.3250558e-01 1.1917979e-01 1.2157791e-01 1.1297631e-01 9.9847302e-02 1.0571550e-01 1.2097128e-01 1.0080768e-01 1.2568112e-01 1.2354605e-01 1.2062969e-01 1.0973133e-01 1.1825900e-01 1.0742526e-01 1.1535080e-01 1.1244756e-01 1.9470856e-03 1.8498175e-03 4.7714250e-03 2.8358661e-03 3.0255426e-03 1.1308587e-03 6.7035566e-04 9.3284570e-04 1.3935241e-03 9.8369983e-04 5.6854836e-03 1.9144361e-03 1.0961099e-03 2.6770659e-03 6.7637792e-04 7.3922961e-04 1.6168588e-03 1.9795771e-04 8.8027763e-04 2.3819907e-03 2.3199642e-03 2.7913184e-03 1.4791390e-03 3.2257382e-03 3.5250868e-03 1.4791390e-03 4.9791374e-04 7.0216560e-04 1.6800207e-03 1.0022835e-02 5.5855445e-04 1.9786373e-03 9.4684044e-04 1.9956071e-03 4.5593799e-04 2.5049818e-04 7.2992180e-04 1.1563910e-03 6.0779252e-02 6.2273308e-02 7.0462169e-02 8.1326510e-02 7.4767830e-02 7.8734546e-02 6.8077240e-02 5.6059538e-02 6.8181020e-02 7.1050105e-02 7.6799016e-02 6.4482663e-02 7.5580358e-02 7.7962233e-02 4.9642606e-02 5.8153068e-02 7.8105114e-02 6.3436311e-02 9.5564553e-02 6.6739850e-02 8.2930379e-02 5.9008492e-02 9.5418848e-02 7.8187143e-02 6.1832470e-02 6.1508833e-02 7.5927040e-02 8.0793818e-02 7.4771898e-02 4.9618073e-02 6.7927507e-02 6.3289271e-02 6.0099335e-02 1.0140473e-01 8.1745663e-02 6.4187383e-02 6.7135505e-02 8.4768567e-02 6.1827019e-02 7.4354928e-02 8.3103529e-02 7.2159743e-02 6.6094709e-02 5.8361788e-02 7.3251937e-02 6.2103535e-02 6.6220430e-02 6.3584868e-02 4.3971154e-02 6.5863068e-02 1.2260074e-01 1.1066837e-01 1.0619606e-01 1.0899833e-01 1.1518894e-01 1.1739848e-01 1.1240635e-01 1.1296742e-01 1.2096568e-01 1.0086214e-01 8.5896751e-02 1.0590639e-01 9.9771313e-02 1.1830710e-01 1.1878365e-01 9.8989344e-02 9.9484141e-02 9.9300506e-02 1.3860781e-01 1.1421784e-01 1.0167360e-01 1.0723785e-01 1.2323222e-01 9.3791376e-02 9.8729091e-02 9.7617417e-02 8.9196630e-02 8.7906597e-02 1.1533851e-01 9.5241683e-02 1.1037299e-01 8.6684313e-02 1.1722334e-01 9.1866320e-02 1.1676032e-01 1.0620321e-01 1.0631345e-01 9.8352717e-02 8.6492752e-02 9.2837846e-02 1.0689111e-01 8.8947496e-02 1.1066837e-01 1.0877202e-01 1.0619549e-01 9.7005210e-02 1.0523294e-01 9.4129616e-02 1.0043708e-01 9.7689504e-02 1.8508011e-03 3.7513322e-03 6.0039368e-03 4.2304138e-03 1.5191600e-03 7.2789043e-04 3.6236504e-03 2.5132214e-04 3.2740913e-03 8.1034702e-03 2.4941139e-03 4.0964229e-03 6.0206143e-04 1.9190323e-03 6.6472571e-04 5.1664338e-04 1.3616103e-03 7.0613265e-04 1.0312088e-03 5.8211090e-03 5.1401914e-03 7.1256747e-05 1.1045080e-03 1.1556192e-03 7.1256747e-05 9.3818356e-04 5.1597856e-04 2.2957469e-03 4.3308939e-03 2.5276111e-03 4.3800580e-03 5.1684770e-03 5.8668191e-04 3.2395561e-03 1.2942225e-03 1.4104695e-03 4.9075437e-04 6.2060492e-02 6.5820549e-02 7.2324527e-02 8.2688153e-02 7.6151035e-02 8.3216525e-02 7.3194172e-02 5.8477367e-02 6.9270609e-02 7.6249005e-02 7.6681852e-02 6.8643243e-02 7.3331578e-02 8.1706941e-02 5.2792718e-02 5.9477668e-02 8.4501232e-02 6.5244243e-02 9.4903309e-02 6.8042766e-02 9.0018791e-02 6.0245936e-02 9.6930604e-02 8.1064051e-02 6.3026851e-02 6.2769846e-02 7.6368221e-02 8.3589775e-02 7.8680956e-02 4.9590571e-02 6.8853459e-02 6.3691512e-02 6.1750809e-02 1.0592213e-01 8.9183264e-02 7.0750492e-02 6.9363027e-02 8.3535040e-02 6.6868103e-02 7.6873580e-02 8.7073732e-02 7.6162997e-02 6.7469442e-02 5.9546534e-02 7.6928171e-02 6.6694450e-02 7.0471384e-02 6.5682900e-02 4.5133798e-02 6.9312951e-02 1.3167296e-01 1.1664541e-01 1.0993682e-01 1.1453374e-01 1.2132631e-01 1.2063781e-01 1.2028602e-01 1.1588513e-01 1.2343288e-01 1.0759677e-01 9.1184353e-02 1.0959799e-01 1.0389171e-01 1.2371908e-01 1.2606621e-01 1.0559841e-01 1.0439417e-01 1.0553794e-01 1.4077951e-01 1.1579171e-01 1.0695513e-01 1.1441431e-01 1.2538100e-01 9.6825962e-02 1.0496558e-01 1.0155971e-01 9.2933277e-02 9.3305204e-02 1.2046243e-01 9.7626604e-02 1.1224568e-01 9.1421248e-02 1.2250398e-01 9.5336276e-02 1.2112681e-01 1.0839632e-01 1.1495562e-01 1.0414545e-01 9.2136906e-02 9.6777242e-02 1.1252211e-01 9.2559606e-02 1.1664541e-01 1.1484781e-01 1.1301462e-01 1.0121871e-01 1.0770332e-01 9.8720694e-02 1.0901533e-01 1.0446815e-01 7.8277898e-04 1.7490530e-03 1.0345024e-03 5.6185312e-04 1.1591486e-03 1.1405764e-03 2.5549089e-03 1.4484284e-03 2.2580494e-03 4.5713265e-03 5.6870335e-03 4.1902203e-03 2.4320876e-03 6.0369458e-04 6.2286369e-04 2.4521502e-03 2.9038905e-03 2.2436415e-03 1.7675525e-03 9.5896000e-04 2.0377231e-03 8.9090360e-04 9.7827632e-04 2.0377231e-03 7.4516940e-04 8.4824201e-04 4.3724648e-04 1.0582513e-02 7.1366344e-04 4.1221085e-03 4.7945036e-03 2.3833891e-03 1.3170043e-03 8.5049004e-04 2.9093352e-04 6.7142903e-04 7.9558936e-02 8.2158081e-02 9.0820201e-02 1.0264403e-01 9.5277746e-02 1.0150997e-01 8.9387659e-02 7.4718776e-02 8.7974881e-02 9.2637642e-02 9.6993873e-02 8.4761019e-02 9.4485044e-02 1.0025701e-01 6.7224195e-02 7.6433848e-02 1.0126400e-01 8.3185627e-02 1.1729605e-01 8.6461029e-02 1.0658954e-01 7.7314215e-02 1.1857784e-01 1.0034666e-01 8.0683042e-02 8.0237049e-02 9.6300382e-02 1.0267579e-01 9.6489769e-02 6.6032956e-02 8.7552344e-02 8.2099586e-02 7.8915667e-02 1.2662250e-01 1.0571935e-01 8.5387558e-02 8.7148938e-02 1.0518820e-01 8.2417845e-02 9.5416475e-02 1.0627769e-01 9.3794810e-02 8.5650752e-02 7.6704239e-02 9.4843643e-02 8.2753514e-02 8.7142105e-02 8.3165683e-02 5.9528971e-02 8.6320416e-02 1.5080041e-01 1.3699340e-01 1.3123407e-01 1.3538631e-01 1.4196949e-01 1.4361623e-01 1.3957348e-01 1.3881335e-01 1.4720194e-01 1.2611020e-01 1.0906565e-01 1.3086970e-01 1.2408176e-01 1.4489915e-01 1.4541581e-01 1.2374159e-01 1.2456922e-01 1.2489938e-01 1.6613145e-01 1.3940980e-01 1.2649129e-01 1.3333884e-01 1.4960338e-01 1.1706680e-01 1.2394226e-01 1.2226369e-01 1.1222236e-01 1.1158045e-01 1.4175176e-01 1.1903032e-01 1.3525827e-01 1.1036833e-01 1.4372294e-01 1.1569638e-01 1.4384978e-01 1.3029466e-01 1.3261278e-01 1.2368173e-01 1.1003418e-01 1.1624174e-01 1.3214763e-01 1.1113124e-01 1.3699340e-01 1.3478604e-01 1.3174332e-01 1.2045775e-01 1.2933910e-01 1.1801062e-01 1.2611372e-01 1.2312584e-01 2.4038804e-03 9.9356679e-04 1.6379146e-03 2.9968879e-03 2.7777132e-03 5.0292552e-03 2.9485139e-03 1.7810659e-03 7.1187929e-03 1.0385224e-02 6.8192179e-03 4.7007047e-03 2.2536066e-03 1.6978265e-03 5.5995030e-03 5.8830752e-03 3.3086218e-03 3.5101479e-03 1.6089784e-03 4.3755431e-03 1.0574938e-03 1.0592785e-03 4.3755431e-03 2.5472554e-03 2.6641717e-03 1.0704333e-03 1.2070572e-02 2.4953874e-03 6.0785955e-03 8.5181088e-03 3.9627930e-03 3.6619699e-03 2.9233174e-03 1.7757672e-03 2.0595965e-03 9.0904959e-02 9.3846404e-02 1.0296173e-01 1.1510418e-01 1.0729700e-01 1.1521099e-01 1.0181822e-01 8.5988795e-02 1.0000742e-01 1.0504161e-01 1.0917671e-01 9.6459196e-02 1.0622808e-01 1.1358449e-01 7.7434068e-02 8.7329703e-02 1.1478646e-01 9.5582611e-02 1.2982843e-01 9.8465917e-02 1.1998512e-01 8.8160180e-02 1.3221652e-01 1.1399918e-01 9.2024225e-02 9.1371105e-02 1.0854159e-01 1.1533865e-01 1.0916600e-01 7.6158175e-02 9.9423258e-02 9.3687045e-02 9.0204262e-02 1.4138542e-01 1.1970815e-01 9.7663366e-02 9.8994798e-02 1.1736337e-01 9.4681982e-02 1.0777767e-01 1.2034441e-01 1.0671033e-01 9.7400706e-02 8.7763928e-02 1.0767516e-01 9.5332473e-02 9.9630913e-02 9.4930517e-02 6.8563663e-02 9.8462875e-02 1.6617515e-01 1.5176730e-01 1.4543395e-01 1.5072522e-01 1.5691405e-01 1.5882414e-01 1.5479314e-01 1.5416358e-01 1.6247914e-01 1.3996762e-01 1.2197918e-01 1.4500225e-01 1.3765005e-01 1.5950314e-01 1.5937612e-01 1.3710080e-01 1.3913130e-01 1.3976637e-01 1.8183098e-01 1.5420823e-01 1.4014252e-01 1.4766552e-01 1.6507182e-01 1.3020370e-01 1.3818766e-01 1.3684571e-01 1.2517707e-01 1.2500429e-01 1.5651711e-01 1.3335007e-01 1.4978001e-01 1.2432862e-01 1.5834992e-01 1.2988375e-01 1.6032290e-01 1.4373178e-01 1.4688056e-01 1.3840222e-01 1.2332107e-01 1.2926358e-01 1.4578293e-01 1.2292671e-01 1.5176730e-01 1.4922075e-01 1.4546636e-01 1.3299550e-01 1.4276363e-01 1.3134387e-01 1.4008961e-01 1.3766630e-01 5.7728358e-04 1.6620505e-03 3.0662753e-03 5.1693417e-04 6.0968463e-03 8.4744633e-04 8.7364721e-04 5.8106642e-03 6.7399476e-03 8.6083103e-03 3.1702748e-03 2.7104978e-03 3.3164143e-03 4.2509190e-03 5.8084215e-03 4.6709776e-03 9.8526568e-04 3.6786909e-04 5.9630791e-03 3.9566796e-03 4.2657824e-03 5.9630791e-03 2.3876668e-03 3.1383576e-03 1.0693622e-03 1.7187016e-02 9.8571152e-04 3.1367899e-03 3.7448988e-03 5.3108404e-03 1.2637202e-03 2.1359423e-03 1.6418787e-03 3.1352541e-03 8.3834616e-02 8.4243676e-02 9.4832859e-02 1.0703873e-01 9.9466934e-02 1.0403376e-01 9.0316788e-02 7.7914871e-02 9.2850027e-02 9.3299365e-02 1.0296391e-01 8.6082003e-02 1.0248600e-01 1.0318273e-01 6.8824902e-02 8.0299100e-02 1.0157055e-01 8.7955506e-02 1.2341155e-01 9.1142100e-02 1.0580332e-01 8.1173197e-02 1.2350931e-01 1.0460831e-01 8.4991511e-02 8.4254332e-02 1.0174542e-01 1.0573929e-01 9.8648070e-02 7.1061471e-02 9.2438015e-02 8.7508516e-02 8.2750270e-02 1.2928539e-01 1.0529438e-01 8.4835976e-02 9.0594121e-02 1.1204138e-01 8.3577196e-02 9.8754999e-02 1.0957368e-01 9.6258171e-02 8.9990776e-02 8.0898906e-02 9.7508458e-02 8.4744426e-02 8.9161769e-02 8.6853262e-02 6.2377571e-02 8.8830405e-02 1.4853162e-01 1.3772455e-01 1.3389458e-01 1.3729951e-01 1.4254710e-01 1.4753124e-01 1.3874272e-01 1.4343376e-01 1.5191156e-01 1.2542851e-01 1.0950060e-01 1.3351960e-01 1.2589032e-01 1.4575308e-01 1.4361388e-01 1.2273259e-01 1.2665814e-01 1.2593062e-01 1.7100462e-01 1.4482556e-01 1.2707776e-01 1.3245591e-01 1.5480441e-01 1.1982038e-01 1.2429326e-01 1.2550864e-01 1.1421155e-01 1.1236837e-01 1.4320023e-01 1.2379599e-01 1.4017288e-01 1.1252737e-01 1.4478118e-01 1.1925773e-01 1.4807486e-01 1.3379535e-01 1.3019772e-01 1.2505772e-01 1.1047444e-01 1.1793234e-01 1.3214851e-01 1.1203286e-01 1.3772455e-01 1.3511133e-01 1.3062456e-01 1.2117415e-01 1.3256036e-01 1.1928977e-01 1.2368263e-01 1.2328316e-01 7.8697050e-04 2.0732289e-03 9.4315564e-04 4.6001401e-03 8.4240364e-04 1.3015708e-03 4.6297460e-03 7.5292997e-03 6.5572401e-03 2.5566943e-03 1.7941741e-03 1.8226799e-03 3.9920133e-03 4.8070278e-03 2.6490734e-03 2.2737423e-03 8.3198965e-04 4.4970379e-03 1.8707122e-03 2.0801746e-03 4.4970379e-03 1.6864362e-03 2.1518496e-03 3.0908897e-04 1.2802000e-02 1.1444166e-03 2.7605116e-03 4.8428825e-03 3.3840997e-03 1.9469936e-03 1.7958172e-03 1.1565833e-03 1.8697862e-03 8.2127567e-02 8.3518119e-02 9.3314949e-02 1.0506408e-01 9.7541782e-02 1.0397584e-01 9.0341739e-02 7.6817337e-02 9.1083710e-02 9.3231274e-02 1.0048418e-01 8.5524503e-02 9.9112893e-02 1.0267345e-01 6.7846626e-02 7.8515797e-02 1.0225403e-01 8.6849217e-02 1.2022955e-01 8.9502113e-02 1.0655817e-01 7.9297559e-02 1.2165144e-01 1.0391861e-01 8.3203942e-02 8.2410584e-02 9.9528824e-02 1.0443382e-01 9.8019721e-02 6.8818975e-02 9.0543610e-02 8.5485551e-02 8.1186134e-02 1.2894588e-01 1.0651601e-01 8.5580315e-02 8.9213768e-02 1.0886353e-01 8.3754339e-02 9.7441118e-02 1.0932583e-01 9.5882843e-02 8.8282134e-02 7.9128322e-02 9.6917266e-02 8.4873719e-02 8.8927957e-02 8.5532654e-02 6.0384203e-02 8.8123284e-02 1.4980593e-01 1.3770759e-01 1.3282368e-01 1.3741111e-01 1.4254251e-01 1.4639384e-01 1.3970199e-01 1.4238069e-01 1.5040197e-01 1.2563911e-01 1.0916002e-01 1.3240724e-01 1.2489275e-01 1.4520334e-01 1.4360899e-01 1.2274102e-01 1.2644577e-01 1.2642535e-01 1.6908994e-01 1.4294672e-01 1.2654652e-01 1.3286867e-01 1.5320101e-01 1.1837980e-01 1.2451917e-01 1.2497748e-01 1.1312705e-01 1.1222677e-01 1.4268257e-01 1.2261254e-01 1.3839073e-01 1.1239899e-01 1.4421566e-01 1.1854547e-01 1.4805458e-01 1.3176737e-01 1.3127552e-01 1.2532607e-01 1.1042618e-01 1.1684289e-01 1.3160924e-01 1.1043724e-01 1.3770759e-01 1.3504379e-01 1.3066174e-01 1.1987723e-01 1.3066578e-01 1.1856367e-01 1.2478710e-01 1.2391087e-01 3.0983409e-04 7.5828890e-04 1.5917755e-03 4.8958816e-04 3.3744944e-03 2.1101097e-03 4.2400870e-03 2.8698866e-03 7.9583168e-04 2.4610899e-04 3.6436132e-04 1.4311801e-03 1.7294514e-03 8.6738167e-04 2.6111809e-03 1.6704106e-03 1.5921641e-03 8.6161593e-04 1.0547029e-03 1.5921641e-03 2.0427868e-04 3.5845705e-04 1.2194863e-04 8.2981219e-03 4.9180195e-04 1.7380522e-03 3.0734607e-03 1.0728608e-03 1.1397310e-03 3.4603128e-04 1.9200118e-04 2.8845040e-04 6.9779438e-02 7.1836392e-02 8.0319868e-02 9.1354890e-02 8.4353236e-02 9.0635736e-02 7.8599311e-02 6.5140986e-02 7.7899100e-02 8.1486701e-02 8.6472565e-02 7.4062042e-02 8.4619349e-02 8.9336326e-02 5.7575298e-02 6.6635212e-02 8.9946961e-02 7.3779929e-02 1.0532587e-01 7.6464940e-02 9.4587006e-02 6.7402630e-02 1.0673169e-01 8.9925800e-02 7.0797999e-02 7.0219100e-02 8.5721997e-02 9.1187854e-02 8.5377890e-02 5.7235173e-02 7.7431768e-02 7.2498793e-02 6.9063158e-02 1.1428266e-01 9.4218471e-02 7.4725647e-02 7.6703845e-02 9.4228329e-02 7.2261001e-02 8.4462132e-02 9.5360997e-02 8.3133678e-02 7.5506963e-02 6.7041127e-02 8.4070372e-02 7.2903149e-02 7.6784460e-02 7.3115143e-02 5.0413571e-02 7.5926129e-02 1.3636539e-01 1.2353657e-01 1.1821263e-01 1.2258303e-01 1.2822457e-01 1.3051322e-01 1.2599517e-01 1.2631512e-01 1.3406707e-01 1.1278003e-01 9.6722933e-02 1.1783731e-01 1.1110860e-01 1.3080317e-01 1.3063996e-01 1.1029647e-01 1.1216341e-01 1.1248813e-01 1.5199693e-01 1.2674108e-01 1.1318561e-01 1.1969790e-01 1.3653036e-01 1.0458853e-01 1.1112582e-01 1.1028100e-01 9.9890110e-02 9.9356661e-02 1.2805612e-01 1.0750038e-01 1.2261289e-01 9.8791075e-02 1.2975191e-01 1.0408196e-01 1.3162969e-01 1.1713290e-01 1.1886116e-01 1.1132823e-01 9.7814075e-02 1.0357451e-01 1.1833994e-01 9.8179977e-02 1.2353657e-01 1.2124412e-01 1.1787602e-01 1.0709455e-01 1.1618054e-01 1.0529428e-01 1.1269702e-01 1.1053049e-01 1.3650135e-03 5.3926014e-04 9.6875216e-04 5.5085642e-03 1.1951469e-03 2.8096772e-03 1.4033998e-03 3.8702395e-04 1.0970323e-04 3.3218009e-04 5.6326785e-04 5.8024795e-04 5.6723773e-04 3.5935032e-03 3.0059920e-03 6.4984761e-04 1.1677062e-03 1.3673782e-03 6.4984761e-04 7.6378345e-05 6.3488092e-05 8.1586688e-04 6.3954323e-03 8.4458294e-04 1.6959745e-03 2.5316364e-03 4.4648839e-04 1.3649198e-03 2.1646092e-04 4.0910219e-04 1.5323026e-04 6.2114649e-02 6.4461203e-02 7.2168083e-02 8.2712554e-02 7.6067484e-02 8.2127836e-02 7.1085856e-02 5.7869953e-02 6.9689694e-02 7.3941980e-02 7.7755077e-02 6.6772898e-02 7.5730146e-02 8.0858032e-02 5.1159438e-02 5.9263906e-02 8.1982206e-02 6.5662191e-02 9.5957099e-02 6.8346124e-02 8.6755825e-02 6.0017643e-02 9.7272303e-02 8.1103209e-02 6.3092478e-02 6.2637310e-02 7.7107544e-02 8.2765719e-02 7.7320565e-02 5.0179546e-02 6.9272103e-02 6.4477670e-02 6.1520691e-02 1.0482403e-01 8.6201836e-02 6.7723532e-02 6.8849001e-02 8.5128110e-02 6.4954612e-02 7.6260237e-02 8.6474261e-02 7.5037042e-02 6.7540885e-02 5.9554295e-02 7.5917230e-02 6.5334858e-02 6.9084098e-02 6.5352935e-02 4.4308417e-02 6.8222624e-02 1.2733314e-01 1.1424612e-01 1.0876932e-01 1.1294180e-01 1.1881213e-01 1.2027633e-01 1.1690957e-01 1.1601884e-01 1.2357066e-01 1.0430113e-01 8.8647048e-02 1.0842142e-01 1.0217893e-01 1.2134270e-01 1.2195833e-01 1.0207761e-01 1.0292571e-01 1.0341320e-01 1.4095409e-01 1.1639921e-01 1.0445121e-01 1.1097871e-01 1.2583780e-01 9.5736690e-02 1.0236688e-01 1.0085185e-01 9.1372067e-02 9.1009848e-02 1.1849408e-01 9.7905297e-02 1.1253291e-01 9.0050809e-02 1.2026601e-01 9.4848068e-02 1.2106318e-01 1.0772883e-01 1.1055160e-01 1.0223795e-01 8.9621067e-02 9.5003079e-02 1.0961118e-01 9.0242843e-02 1.1424612e-01 1.1217935e-01 1.0939970e-01 9.8767943e-02 1.0686010e-01 9.6691216e-02 1.0462140e-01 1.0177309e-01 3.4212913e-03 2.0350185e-04 2.2645835e-03 3.4346676e-03 3.6178579e-03 5.4115677e-03 1.4013939e-03 1.2010586e-03 1.9342083e-03 1.8303919e-03 3.0241355e-03 3.0182648e-03 8.7783530e-04 7.3200159e-04 3.3935862e-03 3.0016113e-03 3.3110105e-03 3.3935862e-03 9.0468402e-04 1.4291912e-03 6.5529771e-04 1.3482371e-02 1.1883350e-04 1.9129351e-03 1.8189821e-03 3.2224845e-03 2.2840556e-04 6.5009173e-04 5.8224397e-04 1.6275063e-03 7.3184911e-02 7.4026716e-02 8.3609924e-02 9.5240271e-02 8.8102740e-02 9.2390529e-02 7.9966102e-02 6.7767341e-02 8.1513618e-02 8.2938634e-02 9.0997666e-02 7.6011769e-02 9.0234918e-02 9.1578032e-02 5.9804069e-02 7.0034281e-02 9.0682677e-02 7.6686753e-02 1.1071727e-01 7.9918092e-02 9.5151478e-02 7.0899518e-02 1.1069472e-01 9.2509702e-02 7.4297007e-02 7.3732579e-02 8.9920224e-02 9.4250688e-02 8.7608739e-02 6.1121885e-02 8.1169501e-02 7.6375843e-02 7.2267735e-02 1.1652820e-01 9.4360734e-02 7.5150369e-02 7.9755441e-02 9.9609504e-02 7.3443983e-02 8.7507436e-02 9.7438140e-02 8.5130511e-02 7.8978434e-02 7.0471516e-02 8.6314807e-02 7.4241923e-02 7.8526940e-02 7.6102189e-02 5.3711374e-02 7.8190521e-02 1.3653802e-01 1.2528995e-01 1.2121146e-01 1.2435019e-01 1.2997976e-01 1.3382130e-01 1.2659694e-01 1.2959353e-01 1.3786369e-01 1.1404399e-01 9.8548323e-02 1.2087284e-01 1.1387348e-01 1.3314978e-01 1.3209550e-01 1.1169631e-01 1.1419600e-01 1.1368838e-01 1.5633317e-01 1.3093427e-01 1.1535002e-01 1.2078800e-01 1.4049523e-01 1.0785716e-01 1.1249675e-01 1.1275652e-01 1.0267406e-01 1.0105332e-01 1.3042827e-01 1.1078233e-01 1.2662105e-01 1.0064162e-01 1.3213313e-01 1.0672611e-01 1.3386868e-01 1.2116827e-01 1.1908244e-01 1.1278797e-01 9.9360911e-02 1.0635497e-01 1.2047378e-01 1.0130606e-01 1.2528995e-01 1.2297832e-01 1.1929072e-01 1.0997770e-01 1.2004306e-01 1.0767864e-01 1.1284273e-01 1.1147304e-01 2.8709378e-03 9.0791333e-03 1.3407674e-03 2.7138923e-03 2.4677711e-04 1.1444972e-03 7.6121265e-04 8.8810957e-04 7.0009018e-04 1.4757411e-04 9.0393445e-04 6.0883361e-03 5.6961877e-03 1.2039709e-04 1.8816976e-03 2.0265121e-03 1.2039709e-04 8.6239061e-04 5.2686780e-04 2.5538294e-03 4.1367540e-03 2.4461852e-03 3.1968429e-03 3.7345867e-03 3.8813913e-04 2.9749715e-03 1.1153685e-03 1.5845430e-03 6.9221070e-04 5.5493017e-02 5.8687008e-02 6.5182775e-02 7.5153394e-02 6.8882837e-02 7.5289957e-02 6.5516107e-02 5.1904720e-02 6.2434251e-02 6.8395322e-02 6.9725101e-02 6.1264247e-02 6.7000659e-02 7.3915045e-02 4.6337454e-02 5.2993228e-02 7.6203506e-02 5.8574285e-02 8.7235787e-02 6.1228310e-02 8.1349394e-02 5.3727422e-02 8.8860415e-02 7.3529860e-02 5.6419133e-02 5.6136434e-02 6.9314277e-02 7.5768587e-02 7.0921131e-02 4.3887190e-02 6.2047408e-02 5.7247874e-02 5.5122668e-02 9.7063471e-02 8.0589157e-02 6.3015465e-02 6.2273448e-02 7.6485434e-02 5.9534434e-02 6.9400424e-02 7.9100961e-02 6.8556756e-02 6.0632063e-02 5.3105900e-02 6.9320431e-02 5.9485747e-02 6.3075829e-02 5.8812039e-02 3.9389619e-02 6.2057390e-02 1.2120786e-01 1.0709958e-01 1.0095433e-01 1.0522389e-01 1.1158919e-01 1.1144992e-01 1.1038844e-01 1.0698853e-01 1.1429410e-01 9.8230586e-02 8.2643326e-02 1.0062987e-01 9.5029365e-02 1.1396256e-01 1.1592889e-01 9.6297509e-02 9.5506831e-02 9.6444702e-02 1.3110088e-01 1.0707131e-01 9.7795782e-02 1.0475251e-01 1.1626300e-01 8.8405248e-02 9.5813058e-02 9.2970070e-02 8.4549021e-02 8.4699662e-02 1.1089247e-01 8.9470273e-02 1.0356569e-01 8.3077190e-02 1.1281589e-01 8.7056416e-02 1.1197016e-01 9.9670877e-02 1.0510107e-01 9.5157512e-02 8.3537128e-02 8.8197538e-02 1.0308982e-01 8.4141549e-02 1.0709958e-01 1.0532428e-01 1.0341164e-01 9.2382015e-02 9.8953568e-02 8.9983057e-02 9.9390435e-02 9.5301345e-02 3.0771633e-03 2.2394953e-03 3.5785600e-03 4.5455517e-03 7.4728021e-04 1.0553655e-03 1.6471751e-03 1.6255623e-03 2.5337657e-03 2.0402330e-03 1.9207121e-03 1.4230439e-03 3.0970780e-03 2.6131629e-03 2.9423829e-03 3.0970780e-03 7.3620931e-04 1.2096052e-03 5.1210113e-04 1.1445573e-02 3.3743120e-04 9.3762253e-04 1.6709589e-03 2.3328362e-03 6.4367426e-04 6.1292579e-04 6.6980522e-04 1.3596425e-03 6.8771058e-02 6.9631829e-02 7.8939123e-02 9.0076585e-02 8.3106206e-02 8.8021023e-02 7.5587788e-02 6.3613086e-02 7.6977857e-02 7.8355410e-02 8.6058485e-02 7.1477483e-02 8.5350309e-02 8.7042060e-02 5.5585563e-02 6.5564323e-02 8.6285657e-02 7.2679829e-02 1.0489589e-01 7.5454083e-02 9.0429367e-02 6.6346194e-02 1.0535674e-01 8.8189227e-02 6.9809235e-02 6.9152322e-02 8.5027647e-02 8.9182145e-02 8.2908995e-02 5.6974544e-02 7.6567724e-02 7.1978204e-02 6.7853368e-02 1.1142320e-01 9.0045691e-02 7.1019587e-02 7.5131918e-02 9.4265212e-02 6.9407495e-02 8.2681448e-02 9.3017444e-02 8.0734547e-02 7.4408554e-02 6.6081064e-02 8.1800498e-02 7.0361312e-02 7.4293705e-02 7.1683996e-02 4.9412056e-02 7.3791248e-02 1.3087381e-01 1.1972349e-01 1.1554097e-01 1.1917243e-01 1.2428472e-01 1.2815053e-01 1.2126029e-01 1.2425112e-01 1.3208038e-01 1.0854852e-01 9.3334993e-02 1.1518188e-01 1.0821021e-01 1.2711496e-01 1.2583624e-01 1.0606084e-01 1.0908141e-01 1.0877992e-01 1.4997249e-01 1.2525272e-01 1.0965413e-01 1.1522136e-01 1.3472784e-01 1.0229252e-01 1.0728052e-01 1.0776484e-01 9.7267064e-02 9.5981774e-02 1.2460839e-01 1.0582154e-01 1.2096134e-01 9.5922459e-02 1.2615683e-01 1.0184377e-01 1.2900688e-01 1.1512576e-01 1.1363761e-01 1.0783825e-01 9.4308496e-02 1.0078579e-01 1.1452781e-01 9.5389301e-02 1.1972349e-01 1.1733679e-01 1.1347632e-01 1.0398208e-01 1.1403752e-01 1.0220157e-01 1.0755302e-01 1.0649118e-01 1.0147620e-02 1.1247381e-02 1.2064168e-02 6.5374061e-03 4.5897505e-03 4.8228518e-03 7.5563629e-03 9.2308338e-03 7.2321889e-03 1.6011806e-03 5.3396772e-04 8.3950153e-03 4.7739373e-03 4.9472694e-03 8.3950153e-03 4.4998786e-03 5.2439437e-03 2.2809748e-03 2.1071898e-02 2.7056396e-03 6.9610435e-03 7.8780829e-03 8.1126375e-03 3.2257880e-03 4.3393216e-03 3.1425928e-03 4.9174647e-03 1.0007131e-01 1.0106593e-01 1.1217080e-01 1.2532148e-01 1.1715442e-01 1.2248393e-01 1.0792073e-01 9.3860583e-02 1.0976919e-01 1.1122163e-01 1.2044721e-01 1.0322968e-01 1.1921347e-01 1.2149913e-01 8.4186074e-02 9.6291408e-02 1.2023049e-01 1.0442285e-01 1.4247402e-01 1.0795998e-01 1.2499239e-01 9.7246530e-02 1.4298267e-01 1.2269113e-01 1.0132833e-01 1.0059203e-01 1.1928692e-01 1.2425009e-01 1.1675840e-01 8.5744895e-02 1.0931412e-01 1.0376332e-01 9.9002718e-02 1.4971116e-01 1.2434000e-01 1.0215677e-01 1.0769100e-01 1.2998610e-01 1.0050022e-01 1.1660891e-01 1.2830083e-01 1.1408155e-01 1.0679553e-01 9.6866698e-02 1.1540492e-01 1.0158690e-01 1.0644304e-01 1.0354221e-01 7.6665035e-02 1.0598765e-01 1.7102185e-01 1.5912057e-01 1.5467066e-01 1.5843570e-01 1.6430112e-01 1.6898961e-01 1.6040927e-01 1.6442765e-01 1.7347908e-01 1.4613872e-01 1.2882261e-01 1.5426961e-01 1.4623773e-01 1.6767510e-01 1.6569930e-01 1.4326884e-01 1.4700928e-01 1.4639344e-01 1.9375995e-01 1.6572948e-01 1.4772209e-01 1.5370280e-01 1.7644069e-01 1.3951457e-01 1.4477511e-01 1.4552738e-01 1.3362833e-01 1.3186831e-01 1.6485780e-01 1.4332228e-01 1.6088049e-01 1.3176893e-01 1.6660706e-01 1.3873049e-01 1.6938110e-01 1.5434218e-01 1.5143663e-01 1.4540553e-01 1.2987912e-01 1.3768917e-01 1.5323248e-01 1.3136310e-01 1.5912057e-01 1.5638588e-01 1.5175254e-01 1.4128505e-01 1.5308268e-01 1.3923812e-01 1.4444485e-01 1.4370095e-01 2.6770864e-03 1.6033718e-03 4.5840441e-04 2.0276877e-03 2.4561050e-03 1.2787767e-03 1.0310968e-03 1.1138996e-03 7.3996134e-03 6.8122401e-03 2.1890332e-03 3.7576667e-03 4.1081994e-03 2.1890332e-03 1.7366871e-03 1.7496571e-03 3.0804223e-03 5.2624414e-03 3.0566387e-03 8.7139687e-04 2.3320271e-03 9.5854356e-04 3.5582665e-03 1.9033529e-03 2.7781156e-03 2.0582238e-03 4.8466175e-02 5.0119607e-02 5.7333122e-02 6.6635612e-02 6.0625611e-02 6.6546613e-02 5.6002103e-02 4.4610205e-02 5.5428894e-02 5.8355341e-02 6.2731565e-02 5.1936578e-02 6.1589720e-02 6.5254921e-02 3.8121898e-02 4.5707178e-02 6.5954438e-02 5.2310619e-02 7.8737277e-02 5.4221486e-02 6.9833666e-02 4.6306978e-02 8.0104533e-02 6.6061691e-02 4.9289042e-02 4.8703396e-02 6.2029842e-02 6.6459215e-02 6.1626890e-02 3.8139914e-02 5.4977441e-02 5.0955269e-02 4.7810568e-02 8.6879401e-02 6.9864176e-02 5.2960539e-02 5.4195866e-02 6.9397405e-02 5.0805294e-02 6.0771100e-02 7.0699543e-02 5.9928918e-02 5.3277849e-02 4.6137567e-02 6.0647902e-02 5.1507184e-02 5.4535520e-02 5.1271651e-02 3.2182295e-02 5.3653922e-02 1.0655841e-01 9.4809862e-02 8.9943103e-02 9.4257768e-02 9.8930460e-02 1.0102907e-01 9.7318001e-02 9.7573045e-02 1.0420091e-01 8.5339961e-02 7.1237738e-02 8.9593643e-02 8.3615246e-02 1.0099568e-01 1.0093948e-01 8.3072610e-02 8.4968711e-02 8.5464008e-02 1.2001752e-01 9.7755169e-02 8.5475001e-02 9.1482164e-02 1.0648093e-01 7.7912530e-02 8.4002788e-02 8.3421922e-02 7.3855173e-02 7.3645673e-02 9.8656580e-02 8.1073912e-02 9.4018658e-02 7.3420060e-02 1.0008227e-01 7.8012093e-02 1.0282145e-01 8.8787179e-02 9.1014600e-02 8.4377747e-02 7.2315249e-02 7.7005472e-02 8.9946277e-02 7.2132565e-02 9.4809862e-02 9.2717682e-02 8.9711332e-02 7.9921256e-02 8.7947099e-02 7.8589830e-02 8.5634568e-02 8.3685774e-02 3.6322977e-03 2.1046334e-03 3.2662345e-03 4.7576391e-03 8.8436254e-04 1.6169936e-03 5.0909036e-03 5.3937261e-03 6.9592372e-03 3.1326528e-03 7.3963134e-03 7.8155750e-03 3.1326528e-03 2.8162695e-03 2.9888005e-03 5.3841195e-03 1.1640832e-02 3.1058623e-03 3.5268449e-03 8.9518404e-04 4.1579453e-03 2.4418843e-03 2.3174283e-03 3.5804624e-03 3.9289766e-03 4.8779386e-02 4.9807262e-02 5.7295117e-02 6.7429274e-02 6.1528729e-02 6.3805672e-02 5.4672352e-02 4.4305273e-02 5.5263563e-02 5.7527840e-02 6.3439356e-02 5.1886311e-02 6.2844358e-02 6.3392021e-02 3.9105833e-02 4.6659036e-02 6.3315061e-02 5.0431450e-02 8.1151197e-02 5.3901750e-02 6.8036856e-02 4.7518043e-02 7.9948453e-02 6.3397617e-02 4.9788208e-02 4.9648688e-02 6.2516012e-02 6.6678586e-02 6.0874148e-02 3.9322135e-02 5.5164136e-02 5.1029588e-02 4.8159012e-02 8.4641068e-02 6.6410487e-02 5.1100232e-02 5.4352465e-02 7.1152366e-02 4.8870866e-02 6.0790663e-02 6.7705030e-02 5.8185400e-02 5.3489810e-02 4.6729049e-02 5.9304859e-02 4.8888831e-02 5.2875044e-02 5.1050585e-02 3.4854587e-02 5.2844524e-02 1.0451993e-01 9.3506986e-02 8.9732041e-02 9.1442484e-02 9.7717353e-02 9.9707944e-02 9.4802947e-02 9.5351404e-02 1.0312713e-01 8.4850971e-02 7.1294232e-02 8.9511382e-02 8.4075688e-02 1.0102482e-01 1.0205801e-01 8.3487981e-02 8.2948462e-02 8.2499658e-02 1.1982484e-01 9.7067919e-02 8.5815629e-02 9.0584285e-02 1.0517734e-01 7.8728615e-02 8.2465362e-02 8.1175179e-02 7.4451161e-02 7.2780961e-02 9.8027119e-02 7.9186352e-02 9.3572539e-02 7.1178913e-02 9.9960717e-02 7.6001190e-02 9.8069469e-02 9.0444802e-02 8.9768862e-02 8.1715688e-02 7.1540326e-02 7.7885383e-02 9.0855680e-02 7.5245252e-02 9.3506986e-02 9.1968167e-02 9.0109483e-02 8.2320804e-02 8.9509517e-02 7.8843854e-02 8.4366358e-02 8.1217849e-02 2.0130888e-03 1.8101212e-03 1.7679630e-03 1.5452657e-03 5.1945438e-04 1.2854163e-03 8.7808919e-03 8.2238558e-03 5.0256002e-04 2.7264330e-03 2.8467434e-03 5.0256002e-04 1.9812707e-03 1.4461308e-03 4.1136119e-03 2.5737383e-03 4.2121435e-03 4.2634118e-03 5.2197085e-03 6.4299253e-04 4.8925560e-03 2.3856210e-03 3.0302048e-03 1.5954763e-03 5.0938593e-02 5.4618269e-02 6.0341206e-02 6.9748949e-02 6.3744319e-02 7.0794949e-02 6.1613026e-02 4.7841585e-02 5.7516679e-02 6.4388046e-02 6.4176559e-02 5.7259869e-02 6.1078980e-02 6.9247074e-02 4.2780731e-02 4.8566082e-02 7.2247187e-02 5.4065395e-02 8.0844343e-02 5.6422768e-02 7.7401119e-02 4.9239970e-02 8.2976560e-02 6.8666014e-02 5.1795393e-02 5.1539865e-02 6.3922410e-02 7.0731007e-02 6.6410587e-02 3.9578438e-02 5.7098964e-02 5.2392525e-02 5.0683886e-02 9.1729236e-02 7.6796353e-02 5.9700691e-02 5.7658559e-02 7.0380963e-02 5.5891948e-02 6.4553084e-02 7.4314140e-02 6.4188376e-02 5.5862752e-02 4.8638731e-02 6.4818200e-02 5.5721441e-02 5.9023587e-02 5.4325379e-02 3.5659427e-02 5.7806321e-02 1.1646754e-01 1.0183406e-01 9.5237923e-02 9.9907095e-02 1.0622089e-01 1.0525522e-01 1.0561297e-01 1.0087833e-01 1.0779948e-01 9.3522115e-02 7.8070592e-02 9.4910280e-02 8.9633058e-02 1.0829781e-01 1.1081740e-01 9.1634033e-02 9.0337246e-02 9.1650208e-02 1.2399805e-01 1.0057671e-01 9.2649910e-02 9.9949877e-02 1.0962952e-01 8.2940269e-02 9.1028259e-02 8.7623472e-02 7.9432792e-02 8.0075100e-02 1.0524078e-01 8.3828651e-02 9.7259211e-02 7.8329945e-02 1.0714828e-01 8.1794698e-02 1.0616577e-01 9.3567438e-02 1.0077628e-01 9.0271060e-02 7.9035426e-02 8.3003648e-02 9.7873414e-02 7.9050596e-02 1.0183406e-01 1.0015100e-01 9.8558964e-02 8.7141498e-02 9.2951123e-02 8.4912476e-02 9.5252034e-02 9.0710349e-02 8.3242342e-04 1.3658963e-03 5.7230018e-04 8.1918836e-04 9.7205318e-04 4.1873206e-03 3.8010080e-03 1.6389584e-03 2.5918915e-03 2.9169588e-03 1.6389584e-03 5.6093257e-04 7.3131385e-04 1.3995850e-03 7.2853070e-03 1.1548608e-03 5.6661765e-04 1.3645766e-03 9.0462881e-04 1.5033145e-03 5.7640672e-04 1.1086000e-03 1.0041867e-03 5.6613254e-02 5.8073267e-02 6.6069758e-02 7.6238332e-02 6.9820331e-02 7.5150667e-02 6.4021588e-02 5.2221754e-02 6.4043055e-02 6.6631628e-02 7.2118099e-02 6.0001482e-02 7.1017077e-02 7.4033042e-02 4.5299125e-02 5.3744092e-02 7.4268794e-02 6.0257552e-02 8.9540407e-02 6.2698279e-02 7.8447791e-02 5.4448716e-02 9.0401373e-02 7.4795629e-02 5.7546133e-02 5.6993841e-02 7.1300530e-02 7.5820775e-02 7.0342915e-02 4.5615196e-02 6.3638314e-02 5.9296597e-02 5.5885275e-02 9.6910282e-02 7.8117499e-02 6.0390425e-02 6.2700176e-02 7.9484269e-02 5.8304382e-02 6.9718471e-02 7.9589842e-02 6.8316048e-02 6.1785991e-02 5.4151233e-02 6.9205713e-02 5.8981505e-02 6.2496988e-02 5.9482310e-02 3.9268283e-02 6.1808750e-02 1.1700097e-01 1.0528100e-01 1.0062122e-01 1.0448643e-01 1.0962576e-01 1.1218593e-01 1.0740486e-01 1.0838294e-01 1.1564442e-01 9.5242357e-02 8.0565058e-02 1.0027898e-01 9.3976493e-02 1.1211413e-01 1.1185843e-01 9.2981806e-02 9.4878465e-02 9.5039709e-02 1.3246555e-01 1.0898490e-01 9.5760022e-02 1.0161372e-01 1.1802422e-01 8.8109745e-02 9.3746381e-02 9.3301915e-02 8.3669649e-02 8.2970713e-02 1.0958444e-01 9.1015393e-02 1.0506496e-01 8.2570171e-02 1.1114727e-01 8.7646381e-02 1.1324005e-01 9.9872205e-02 1.0076379e-01 9.4009317e-02 8.1526386e-02 8.7041367e-02 1.0052094e-01 8.2193042e-02 1.0528100e-01 1.0314067e-01 9.9984788e-02 9.0308392e-02 9.8939123e-02 8.8538901e-02 9.5061969e-02 9.3157351e-02 1.7227462e-04 7.9314599e-04 8.9844173e-04 8.9518090e-04 2.8880348e-03 2.3244520e-03 6.4717383e-04 8.8327223e-04 1.0385020e-03 6.4717383e-04 4.2082433e-05 2.2535838e-05 6.1632160e-04 7.2421116e-03 6.3599645e-04 2.4204146e-03 3.0244507e-03 7.7555952e-04 1.1490838e-03 1.6721205e-04 1.6116507e-04 5.3985478e-05 6.6593275e-02 6.9140456e-02 7.6991415e-02 8.7909276e-02 8.1079796e-02 8.7140283e-02 7.5972851e-02 6.2229264e-02 7.4340995e-02 7.8983123e-02 8.2638003e-02 7.1602020e-02 8.0355120e-02 8.5886853e-02 5.5471847e-02 6.3724100e-02 8.7131187e-02 7.0026001e-02 1.0150375e-01 7.2956045e-02 9.2179245e-02 6.4526163e-02 1.0277569e-01 8.5954479e-02 6.7618774e-02 6.7207904e-02 8.2005017e-02 8.8025831e-02 8.2391127e-02 5.4193907e-02 7.3937560e-02 6.8913785e-02 6.6018815e-02 1.1053450e-01 9.1432865e-02 7.2512462e-02 7.3622571e-02 9.0228640e-02 6.9559505e-02 8.1277678e-02 9.1538587e-02 7.9923144e-02 7.2198625e-02 6.3968343e-02 8.0855092e-02 6.9835377e-02 7.3807917e-02 6.9953549e-02 4.8370205e-02 7.2961708e-02 1.3388298e-01 1.2040855e-01 1.1476271e-01 1.1886295e-01 1.2510613e-01 1.2637598e-01 1.2310531e-01 1.2187125e-01 1.2970708e-01 1.1033742e-01 9.4233672e-02 1.1441687e-01 1.0810566e-01 1.2778743e-01 1.2861773e-01 1.0813836e-01 1.0864380e-01 1.0911947e-01 1.4755823e-01 1.2232653e-01 1.1049966e-01 1.1716689e-01 1.3196625e-01 1.0144926e-01 1.0821364e-01 1.0641029e-01 9.6993665e-02 9.6571345e-02 1.2478057e-01 1.0328932e-01 1.1842664e-01 9.5377765e-02 1.2666075e-01 1.0023484e-01 1.2682498e-01 1.1377681e-01 1.1674990e-01 1.0792126e-01 9.5167233e-02 1.0076949e-01 1.1586910e-01 9.6070623e-02 1.2040855e-01 1.1835687e-01 1.1566030e-01 1.0480317e-01 1.1289922e-01 1.0248125e-01 1.1065853e-01 1.0752770e-01 1.5518070e-03 1.3360426e-03 6.1855325e-04 3.8684575e-03 2.7981409e-03 7.1019942e-04 2.9249692e-04 3.8108588e-04 7.1019942e-04 3.4811331e-04 2.0628507e-04 6.8481588e-04 6.1413327e-03 1.2640084e-03 3.0810810e-03 4.5162171e-03 6.1490495e-04 2.0823475e-03 6.6391763e-04 4.5940617e-04 4.0824218e-05 6.8980444e-02 7.2049409e-02 7.9659630e-02 9.0518795e-02 8.3601945e-02 9.0707158e-02 7.9362725e-02 6.4838475e-02 7.6843708e-02 8.2367370e-02 8.4912050e-02 7.4621958e-02 8.2116380e-02 8.9210086e-02 5.7968714e-02 6.6009408e-02 9.1025554e-02 7.2793579e-02 1.0368926e-01 7.5498978e-02 9.6154006e-02 6.6776572e-02 1.0567953e-01 8.9202124e-02 6.9982422e-02 6.9528749e-02 8.4404562e-02 9.0968518e-02 8.5580442e-02 5.6059636e-02 7.6365493e-02 7.1188605e-02 6.8464233e-02 1.1430428e-01 9.5645657e-02 7.6165252e-02 7.6295454e-02 9.2254316e-02 7.2920975e-02 8.4113452e-02 9.5088632e-02 8.3209827e-02 7.4687466e-02 6.6271074e-02 8.4049660e-02 7.3195324e-02 7.7054222e-02 7.2597553e-02 5.0198701e-02 7.5958466e-02 1.3864088e-01 1.2443023e-01 1.1820696e-01 1.2296103e-01 1.2918980e-01 1.2996108e-01 1.2761885e-01 1.2545185e-01 1.3315049e-01 1.1429516e-01 9.7708479e-02 1.1783417e-01 1.1147502e-01 1.3162480e-01 1.3265015e-01 1.1194384e-01 1.1244164e-01 1.1326233e-01 1.5100180e-01 1.2549100e-01 1.1411167e-01 1.2131599e-01 1.3539430e-01 1.0451333e-01 1.1218678e-01 1.1003412e-01 1.0016268e-01 1.0019858e-01 1.2861591e-01 1.0655136e-01 1.2158527e-01 9.9029274e-02 1.3048234e-01 1.0368193e-01 1.3098775e-01 1.1671318e-01 1.2117898e-01 1.1194010e-01 9.8811276e-02 1.0398171e-01 1.1952683e-01 9.8904418e-02 1.2443023e-01 1.2231211e-01 1.1957927e-01 1.0792296e-01 1.1588914e-01 1.0590028e-01 1.1501774e-01 1.1169315e-01 2.7458883e-04 1.9079543e-03 3.8013798e-03 4.1957403e-03 8.9864077e-04 3.1780627e-03 3.4575366e-03 8.9864077e-04 6.1086528e-04 6.3429136e-04 2.2515700e-03 7.8191545e-03 1.2413621e-03 2.0952535e-03 1.3093150e-03 1.3748953e-03 1.2388833e-03 4.8114625e-04 1.1404059e-03 1.0969768e-03 5.5584260e-02 5.7510469e-02 6.4993010e-02 7.5368447e-02 6.9057379e-02 7.3499750e-02 6.3437246e-02 5.1298347e-02 6.2635149e-02 6.6332421e-02 7.0700793e-02 5.9790543e-02 6.9153134e-02 7.2596138e-02 4.5395419e-02 5.3097576e-02 7.3376441e-02 5.8208889e-02 8.8752390e-02 6.1292160e-02 7.8242185e-02 5.3906344e-02 8.8989869e-02 7.2610553e-02 5.6579969e-02 5.6297092e-02 6.9966539e-02 7.5157531e-02 6.9589413e-02 4.4676337e-02 6.2364995e-02 5.7806901e-02 5.5013010e-02 9.5419957e-02 7.7143847e-02 6.0075763e-02 6.1882505e-02 7.8193894e-02 5.7405077e-02 6.8884889e-02 7.7590521e-02 6.7073564e-02 6.0698980e-02 5.3256477e-02 6.8055547e-02 5.7544133e-02 6.1428351e-02 5.8436070e-02 3.9618229e-02 6.0914936e-02 1.1719371e-01 1.0478727e-01 9.9928933e-02 1.0301520e-01 1.0921839e-01 1.1065431e-01 1.0694189e-01 1.0626748e-01 1.1395294e-01 9.5522682e-02 8.0692317e-02 9.9640584e-02 9.3821909e-02 1.1210560e-01 1.1313776e-01 9.3722341e-02 9.3659306e-02 9.3792773e-02 1.3107147e-01 1.0721381e-01 9.5955259e-02 1.0180084e-01 1.1608360e-01 8.7786080e-02 9.3279943e-02 9.1618132e-02 8.3505928e-02 8.2622852e-02 1.0912386e-01 8.8978076e-02 1.0355009e-01 8.1236966e-02 1.1101306e-01 8.5950464e-02 1.1026035e-01 9.9640402e-02 1.0131013e-01 9.2768985e-02 8.1325904e-02 8.7087186e-02 1.0113076e-01 8.3368795e-02 1.0478727e-01 1.0299507e-01 1.0075649e-01 9.1267488e-02 9.8760345e-02 8.8473047e-02 9.5602739e-02 9.2388034e-02 1.3192990e-03 5.6049942e-03 5.6260410e-03 3.8255378e-04 2.7098321e-03 2.9260165e-03 3.8255378e-04 8.5873923e-04 6.4551657e-04 2.7466704e-03 5.2436473e-03 2.1741200e-03 2.6488612e-03 2.5599967e-03 7.2546074e-04 2.4454411e-03 9.4817109e-04 1.6251073e-03 9.8969141e-04 5.2867682e-02 5.5519966e-02 6.2241614e-02 7.2187515e-02 6.6023504e-02 7.1524895e-02 6.1872329e-02 4.9090525e-02 5.9694897e-02 6.4712456e-02 6.7154795e-02 5.7947928e-02 6.4972194e-02 7.0357979e-02 4.3573654e-02 5.0441816e-02 7.2068579e-02 5.5680796e-02 8.4591184e-02 5.8459303e-02 7.7051055e-02 5.1193288e-02 8.5601942e-02 7.0117829e-02 5.3803216e-02 5.3535941e-02 6.6621467e-02 7.2473708e-02 6.7439009e-02 4.1816308e-02 5.9366143e-02 5.4760331e-02 5.2431175e-02 9.2978431e-02 7.6152091e-02 5.9131458e-02 5.9321453e-02 7.4096463e-02 5.5985281e-02 6.6256786e-02 7.5362720e-02 6.5046998e-02 5.7885295e-02 5.0561408e-02 6.5880549e-02 5.5988437e-02 5.9621488e-02 5.5930673e-02 3.7267604e-02 5.8818934e-02 1.1596549e-01 1.0264359e-01 9.7070235e-02 1.0079872e-01 1.0704759e-01 1.0746690e-01 1.0547300e-01 1.0308827e-01 1.1044375e-01 9.3809882e-02 7.8755194e-02 9.6766957e-02 9.1194118e-02 1.0959636e-01 1.1126853e-01 9.1984794e-02 9.1378676e-02 9.2003603e-02 1.2714849e-01 1.0351897e-01 9.3695356e-02 1.0013450e-01 1.1244271e-01 8.4898325e-02 9.1456450e-02 8.9057498e-02 8.0952577e-02 8.0704372e-02 1.0658329e-01 8.5941483e-02 1.0000975e-01 7.9159793e-02 1.0848060e-01 8.3337337e-02 1.0760265e-01 9.6215589e-02 1.0020263e-01 9.0833970e-02 7.9520366e-02 8.4523201e-02 9.8885306e-02 8.0736144e-02 1.0264359e-01 1.0090595e-01 9.8957167e-02 8.8690158e-02 9.5447639e-02 8.6121379e-02 9.4585258e-02 9.0802578e-02 6.3934178e-03 4.8940589e-03 1.2286350e-03 9.0839358e-04 1.0654961e-03 1.2286350e-03 9.6426336e-04 7.9049403e-04 1.4335758e-03 3.9777866e-03 2.4355051e-03 2.0107867e-03 4.6162602e-03 1.1770386e-04 3.4806567e-03 1.4352123e-03 1.5474906e-03 6.2303871e-04 6.0828103e-02 6.3671616e-02 7.0896871e-02 8.0864907e-02 7.4298413e-02 8.2081782e-02 7.0784097e-02 5.7058421e-02 6.8417644e-02 7.3405222e-02 7.5846906e-02 6.5924537e-02 7.3406010e-02 8.0389200e-02 5.0100593e-02 5.7793778e-02 8.2174514e-02 6.5233957e-02 9.3014438e-02 6.7186690e-02 8.6645560e-02 5.8420934e-02 9.5569964e-02 8.0832485e-02 6.1703014e-02 6.1092740e-02 7.5364208e-02 8.1326732e-02 7.6506202e-02 4.8648267e-02 6.7850123e-02 6.3129543e-02 6.0279722e-02 1.0421037e-01 8.6793624e-02 6.7911943e-02 6.7612814e-02 8.2552902e-02 6.4996479e-02 7.4977087e-02 8.6383221e-02 7.4662447e-02 6.6198278e-02 5.8199721e-02 7.5325266e-02 6.5572089e-02 6.8824430e-02 6.4314329e-02 4.2494903e-02 6.7537432e-02 1.2698890e-01 1.1333529e-01 1.0720337e-01 1.1257147e-01 1.1782339e-01 1.1890376e-01 1.1671052e-01 1.1501886e-01 1.2195484e-01 1.0334755e-01 8.7523621e-02 1.0680449e-01 1.0051071e-01 1.1973768e-01 1.2022270e-01 1.0080013e-01 1.0231108e-01 1.0334772e-01 1.3872306e-01 1.1462175e-01 1.0296153e-01 1.1014449e-01 1.2423991e-01 9.3883877e-02 1.0176675e-01 1.0022558e-01 8.9772340e-02 9.0213298e-02 1.1713918e-01 9.6981953e-02 1.1075521e-01 8.9707194e-02 1.1871449e-01 9.4162640e-02 1.2118172e-01 1.0525415e-01 1.1008916e-01 1.0200908e-01 8.8850235e-02 9.3264552e-02 1.0788029e-01 8.7700151e-02 1.1333529e-01 1.1110284e-01 1.0804665e-01 9.6438203e-02 1.0447205e-01 9.5256431e-02 1.0425068e-01 1.0162139e-01 4.7487225e-04 5.5229901e-03 5.0553045e-03 5.3192416e-03 5.5229901e-03 2.6440955e-03 3.2948907e-03 2.1817756e-03 1.9232390e-02 1.0060949e-03 5.2893888e-03 3.6565664e-03 6.4838776e-03 7.5722530e-04 2.1347736e-03 1.7405562e-03 3.5508478e-03 8.4906111e-02 8.5684875e-02 9.5941240e-02 1.0863973e-01 1.0110388e-01 1.0421406e-01 9.1634377e-02 7.8911086e-02 9.3575504e-02 9.5023267e-02 1.0394314e-01 8.7940160e-02 1.0307352e-01 1.0372095e-01 7.0927620e-02 8.1814584e-02 1.0248405e-01 8.7682138e-02 1.2553590e-01 9.1822634e-02 1.0758552e-01 8.2848043e-02 1.2459059e-01 1.0427303e-01 8.6172494e-02 8.5771372e-02 1.0276107e-01 1.0743739e-01 1.0000507e-01 7.2180344e-02 9.3352407e-02 8.8118179e-02 8.3972299e-02 1.2999219e-01 1.0601815e-01 8.6245777e-02 9.1942699e-02 1.1341937e-01 8.4389659e-02 1.0016617e-01 1.0942619e-01 9.6927434e-02 9.1068024e-02 8.2112078e-02 9.8354950e-02 8.4918144e-02 8.9929197e-02 8.7860129e-02 6.4913483e-02 8.9916257e-02 1.5108513e-01 1.3966025e-01 1.3579363e-01 1.3800221e-01 1.4462965e-01 1.4853849e-01 1.4049017e-01 1.4366186e-01 1.5284247e-01 1.2813521e-01 1.1198929e-01 1.3549048e-01 1.2835377e-01 1.4847864e-01 1.4775011e-01 1.2601872e-01 1.2764409e-01 1.2670935e-01 1.7255531e-01 1.4567287e-01 1.2987249e-01 1.3506836e-01 1.5547286e-01 1.2211481e-01 1.2607603e-01 1.2598262e-01 1.1656479e-01 1.1426125e-01 1.4534374e-01 1.2395854e-01 1.4127350e-01 1.1320894e-01 1.4734853e-01 1.1969377e-01 1.4703899e-01 1.3646872e-01 1.3305975e-01 1.2588961e-01 1.1250545e-01 1.2058130e-01 1.3549735e-01 1.1610735e-01 1.3966025e-01 1.3745925e-01 1.3401818e-01 1.2501338e-01 1.3525796e-01 1.2173379e-01 1.2646805e-01 1.2458940e-01 5.1766813e-03 3.3038909e-03 3.5089109e-03 5.1766813e-03 2.1988415e-03 2.7782772e-03 1.0688451e-03 1.7030893e-02 8.9726872e-04 4.6231995e-03 4.6736672e-03 5.3382818e-03 1.1647725e-03 1.9758755e-03 1.2750935e-03 2.7128598e-03 8.7833448e-02 8.9010914e-02 9.9253982e-02 1.1183035e-01 1.0412107e-01 1.0885582e-01 9.5547284e-02 8.2028755e-02 9.6837094e-02 9.8811318e-02 1.0697473e-01 9.1242752e-02 1.0570232e-01 1.0798221e-01 7.3423587e-02 8.4439842e-02 1.0715501e-01 9.1521191e-02 1.2824419e-01 9.5124610e-02 1.1205287e-01 8.5389026e-02 1.2841576e-01 1.0878552e-01 8.9048303e-02 8.8474213e-02 1.0589810e-01 1.1091852e-01 1.0379001e-01 7.4413565e-02 9.6465402e-02 9.1132676e-02 8.6893608e-02 1.3487393e-01 1.1110410e-01 9.0320856e-02 9.5130800e-02 1.1613190e-01 8.8387927e-02 1.0357744e-01 1.1422195e-01 1.0103671e-01 9.4160592e-02 8.4870839e-02 1.0232030e-01 8.9160088e-02 9.3889889e-02 9.1104413e-02 6.6493231e-02 9.3508454e-02 1.5639991e-01 1.4440871e-01 1.3995325e-01 1.4327783e-01 1.4942424e-01 1.5327636e-01 1.4579380e-01 1.4864466e-01 1.5749945e-01 1.3242397e-01 1.1574188e-01 1.3959357e-01 1.3216131e-01 1.5281767e-01 1.5172347e-01 1.2991524e-01 1.3242882e-01 1.3190251e-01 1.7712896e-01 1.5002220e-01 1.3380600e-01 1.3964037e-01 1.6023126e-01 1.2562692e-01 1.3071698e-01 1.3077115e-01 1.2010966e-01 1.1841338e-01 1.4987755e-01 1.2848062e-01 1.4548859e-01 1.1783301e-01 1.5172346e-01 1.2426441e-01 1.5309487e-01 1.3983154e-01 1.3778354e-01 1.3093423e-01 1.1660453e-01 1.2409289e-01 1.3931059e-01 1.1865130e-01 1.4440871e-01 1.4196632e-01 1.3805465e-01 1.2801436e-01 1.3865562e-01 1.2553921e-01 1.3109454e-01 1.2958547e-01 1.5860612e-03 1.6773969e-03 0.0000000e+00 8.4337656e-04 4.6746407e-04 2.4549978e-03 4.7529836e-03 2.3235808e-03 4.0683267e-03 4.3260986e-03 6.7336618e-04 2.8454658e-03 1.0918918e-03 1.3756658e-03 5.7784546e-04 5.9573290e-02 6.3070670e-02 6.9597309e-02 7.9911457e-02 7.3480528e-02 7.9923883e-02 7.0144874e-02 5.5923876e-02 6.6635620e-02 7.3192589e-02 7.4096565e-02 6.5836734e-02 7.1022277e-02 7.8555696e-02 5.0423423e-02 5.7089619e-02 8.1093473e-02 6.2483167e-02 9.2251714e-02 6.5399221e-02 8.6573432e-02 5.7873871e-02 9.3861710e-02 7.7914479e-02 6.0545459e-02 6.0328179e-02 7.3725736e-02 8.0652769e-02 7.5662466e-02 4.7500835e-02 6.6267157e-02 6.1219907e-02 5.9246920e-02 1.0235525e-01 8.5584812e-02 6.7627185e-02 6.6676399e-02 8.1028522e-02 6.3874534e-02 7.4037098e-02 8.3735875e-02 7.3091049e-02 6.4875922e-02 5.7134332e-02 7.3898502e-02 6.3669341e-02 6.7483654e-02 6.3032151e-02 4.3195391e-02 6.6465430e-02 1.2757303e-01 1.1294171e-01 1.0654531e-01 1.1074736e-01 1.1756538e-01 1.1705185e-01 1.1633100e-01 1.1230305e-01 1.1988948e-01 1.0404710e-01 8.7981667e-02 1.0622547e-01 1.0061669e-01 1.2008497e-01 1.2242153e-01 1.0217012e-01 1.0084187e-01 1.0181343e-01 1.3714147e-01 1.1243585e-01 1.0356517e-01 1.1071692e-01 1.2181923e-01 9.3742899e-02 1.0137566e-01 9.8085445e-02 8.9840814e-02 8.9979544e-02 1.1682155e-01 9.4340727e-02 1.0893096e-01 8.8036209e-02 1.1887723e-01 9.1995894e-02 1.1718099e-01 1.0529554e-01 1.1115622e-01 1.0048991e-01 8.8823715e-02 9.3647258e-02 1.0909883e-01 8.9729548e-02 1.1294171e-01 1.1121254e-01 1.0947844e-01 9.8164553e-02 1.0458423e-01 9.5468337e-02 1.0529433e-01 1.0077315e-01 1.0959804e-05 1.5860612e-03 1.2066237e-03 9.8801305e-04 9.8752232e-04 6.0992006e-03 2.3026455e-03 4.3295194e-03 6.8464966e-03 1.1467011e-03 3.5017117e-03 1.7326793e-03 1.1803657e-03 5.4725577e-04 7.4912594e-02 7.8462634e-02 8.6080465e-02 9.7055695e-02 8.9913940e-02 9.8246196e-02 8.6359614e-02 7.0875411e-02 8.3096610e-02 8.9373603e-02 9.1095332e-02 8.1132274e-02 8.7784959e-02 9.6471287e-02 6.3584445e-02 7.1727351e-02 9.8741504e-02 7.9297358e-02 1.1001947e-01 8.1763635e-02 1.0392038e-01 7.2462318e-02 1.1283140e-01 9.6493172e-02 7.5904241e-02 7.5362083e-02 9.0691159e-02 9.7798442e-02 9.2550220e-02 6.1191529e-02 8.2519289e-02 7.7118501e-02 7.4418954e-02 1.2241546e-01 1.0373213e-01 8.3271349e-02 8.2617382e-02 9.8302252e-02 7.9806174e-02 9.0742202e-02 1.0274136e-01 9.0294649e-02 8.0841362e-02 7.2046648e-02 9.1054206e-02 8.0166072e-02 8.3952641e-02 7.8850217e-02 5.4962225e-02 8.2583735e-02 1.4771497e-01 1.3277361e-01 1.2596285e-01 1.3150244e-01 1.3764710e-01 1.3814813e-01 1.3643324e-01 1.3364709e-01 1.4127174e-01 1.2228442e-01 1.0501430e-01 1.2555100e-01 1.1896947e-01 1.3983185e-01 1.4080838e-01 1.1967635e-01 1.2050783e-01 1.2165153e-01 1.5932394e-01 1.3324590e-01 1.2180922e-01 1.2960297e-01 1.4356572e-01 1.1163860e-01 1.2028439e-01 1.1797002e-01 1.0728569e-01 1.0776505e-01 1.3685139e-01 1.1414077e-01 1.2924282e-01 1.0675126e-01 1.3867943e-01 1.1135088e-01 1.3991357e-01 1.2389778e-01 1.2963231e-01 1.2019755e-01 1.0634263e-01 1.1117491e-01 1.2727853e-01 1.0546335e-01 1.3277361e-01 1.3050496e-01 1.2753116e-01 1.1493738e-01 1.2310368e-01 1.1333277e-01 1.2330887e-01 1.1999903e-01 1.6773969e-03 1.4044930e-03 1.1476188e-03 1.1728210e-03 6.0850239e-03 2.5611449e-03 4.7720148e-03 7.3487783e-03 1.2981958e-03 3.8044610e-03 1.9624179e-03 1.3573639e-03 6.7050163e-04 7.5875383e-02 7.9591742e-02 8.7130965e-02 9.8136915e-02 9.0968214e-02 9.9474916e-02 8.7612410e-02 7.1886206e-02 8.4072967e-02 9.0657173e-02 9.2037661e-02 8.2322796e-02 8.8559519e-02 9.7661149e-02 6.4636714e-02 7.2692172e-02 1.0010765e-01 8.0266168e-02 1.1103798e-01 8.2745924e-02 1.0537406e-01 7.3430328e-02 1.1396572e-01 9.7599809e-02 7.6869874e-02 7.6340270e-02 9.1668858e-02 9.8974404e-02 9.3760611e-02 6.2005453e-02 8.3489209e-02 7.8020463e-02 7.5407355e-02 1.2375637e-01 1.0517097e-01 8.4594299e-02 8.3682974e-02 9.9214366e-02 8.1008204e-02 9.1862911e-02 1.0394615e-01 9.1478420e-02 8.1837398e-02 7.2994499e-02 9.2227696e-02 8.1322109e-02 8.5126430e-02 7.9879628e-02 5.5860810e-02 8.3714500e-02 1.4946173e-01 1.3427629e-01 1.2730802e-01 1.3293539e-01 1.3918009e-01 1.3947497e-01 1.3805161e-01 1.3491280e-01 1.4255824e-01 1.2381647e-01 1.0639120e-01 1.2689399e-01 1.2032986e-01 1.4134878e-01 1.4247553e-01 1.2120787e-01 1.2187456e-01 1.2309328e-01 1.6066767e-01 1.3444738e-01 1.2325830e-01 1.3118369e-01 1.4483072e-01 1.1290137e-01 1.2175315e-01 1.1925251e-01 1.0857610e-01 1.0914142e-01 1.3832403e-01 1.1530308e-01 1.3045824e-01 1.0804612e-01 1.4018015e-01 1.1257905e-01 1.4124338e-01 1.2516443e-01 1.3130183e-01 1.2160995e-01 1.0773181e-01 1.1250108e-01 1.2878318e-01 1.0678720e-01 1.3427629e-01 1.3201801e-01 1.2910620e-01 1.1632723e-01 1.2438544e-01 1.1469977e-01 1.2494953e-01 1.2148287e-01 8.4337656e-04 4.6746407e-04 2.4549978e-03 4.7529836e-03 2.3235808e-03 4.0683267e-03 4.3260986e-03 6.7336618e-04 2.8454658e-03 1.0918918e-03 1.3756658e-03 5.7784546e-04 5.9573290e-02 6.3070670e-02 6.9597309e-02 7.9911457e-02 7.3480528e-02 7.9923883e-02 7.0144874e-02 5.5923876e-02 6.6635620e-02 7.3192589e-02 7.4096565e-02 6.5836734e-02 7.1022277e-02 7.8555696e-02 5.0423423e-02 5.7089619e-02 8.1093473e-02 6.2483167e-02 9.2251714e-02 6.5399221e-02 8.6573432e-02 5.7873871e-02 9.3861710e-02 7.7914479e-02 6.0545459e-02 6.0328179e-02 7.3725736e-02 8.0652769e-02 7.5662466e-02 4.7500835e-02 6.6267157e-02 6.1219907e-02 5.9246920e-02 1.0235525e-01 8.5584812e-02 6.7627185e-02 6.6676399e-02 8.1028522e-02 6.3874534e-02 7.4037098e-02 8.3735875e-02 7.3091049e-02 6.4875922e-02 5.7134332e-02 7.3898502e-02 6.3669341e-02 6.7483654e-02 6.3032151e-02 4.3195391e-02 6.6465430e-02 1.2757303e-01 1.1294171e-01 1.0654531e-01 1.1074736e-01 1.1756538e-01 1.1705185e-01 1.1633100e-01 1.1230305e-01 1.1988948e-01 1.0404710e-01 8.7981667e-02 1.0622547e-01 1.0061669e-01 1.2008497e-01 1.2242153e-01 1.0217012e-01 1.0084187e-01 1.0181343e-01 1.3714147e-01 1.1243585e-01 1.0356517e-01 1.1071692e-01 1.2181923e-01 9.3742899e-02 1.0137566e-01 9.8085445e-02 8.9840814e-02 8.9979544e-02 1.1682155e-01 9.4340727e-02 1.0893096e-01 8.8036209e-02 1.1887723e-01 9.1995894e-02 1.1718099e-01 1.0529554e-01 1.1115622e-01 1.0048991e-01 8.8823715e-02 9.3647258e-02 1.0909883e-01 8.9729548e-02 1.1294171e-01 1.1121254e-01 1.0947844e-01 9.8164553e-02 1.0458423e-01 9.5468337e-02 1.0529433e-01 1.0077315e-01 6.2742331e-05 5.7500583e-04 7.7277880e-03 4.4752900e-04 1.9151463e-03 2.3881652e-03 8.6221368e-04 8.6997251e-04 5.7712764e-05 1.4261239e-04 1.6337476e-04 6.5357511e-02 6.7564930e-02 7.5599895e-02 8.6482524e-02 7.9693502e-02 8.5392044e-02 7.4152863e-02 6.0880360e-02 7.3094884e-02 7.7108408e-02 8.1483729e-02 6.9905750e-02 7.9537736e-02 8.4220614e-02 5.4020845e-02 6.2478782e-02 8.5095725e-02 6.8776984e-02 1.0023818e-01 7.1693803e-02 8.9974847e-02 6.3277271e-02 1.0126704e-01 8.4456284e-02 6.6380508e-02 6.5944304e-02 8.0776371e-02 8.6401760e-02 8.0678654e-02 5.3232214e-02 7.2705055e-02 6.7807498e-02 6.4728976e-02 1.0860574e-01 8.9250516e-02 7.0532132e-02 7.2192370e-02 8.9155393e-02 6.7825786e-02 7.9751674e-02 8.9848634e-02 7.8255825e-02 7.0908403e-02 6.2757363e-02 7.9213209e-02 6.8195297e-02 7.2146158e-02 6.8587288e-02 4.7220467e-02 7.1390990e-02 1.3114639e-01 1.1816523e-01 1.1284157e-01 1.1675611e-01 1.2280854e-01 1.2450964e-01 1.2061835e-01 1.2011904e-01 1.2793055e-01 1.0801409e-01 9.2203467e-02 1.1250005e-01 1.0614185e-01 1.2553294e-01 1.2604996e-01 1.0581394e-01 1.0665851e-01 1.0697400e-01 1.4569576e-01 1.2071369e-01 1.0835453e-01 1.1475367e-01 1.3023667e-01 9.9676180e-02 1.0601570e-01 1.0459446e-01 9.5152798e-02 9.4544535e-02 1.2261107e-01 1.0171679e-01 1.1677938e-01 9.3513090e-02 1.2443770e-01 9.8519974e-02 1.2493623e-01 1.1202254e-01 1.1414514e-01 1.0583616e-01 9.3110547e-02 9.8863035e-02 1.1361961e-01 9.4163495e-02 1.1816523e-01 1.1608967e-01 1.1325987e-01 1.0277556e-01 1.1111172e-01 1.0049112e-01 1.0810161e-01 1.0529258e-01 8.3201047e-04 6.6553558e-03 8.0817319e-04 2.3666253e-03 2.9401972e-03 6.0430641e-04 1.3109323e-03 2.0042209e-04 2.9042771e-04 6.4823857e-05 6.4369752e-02 6.6980839e-02 7.4622998e-02 8.5371818e-02 7.8644884e-02 8.4714120e-02 7.3778054e-02 6.0124143e-02 7.1976215e-02 7.6757894e-02 8.0112003e-02 6.9445381e-02 7.7800626e-02 8.3451231e-02 5.3558729e-02 6.1563285e-02 8.4824350e-02 6.7739660e-02 9.8727492e-02 7.0619990e-02 8.9865595e-02 6.2353086e-02 1.0002589e-01 8.3464224e-02 6.5377675e-02 6.4985443e-02 7.9506921e-02 8.5546781e-02 8.0035925e-02 5.2147031e-02 7.1577598e-02 6.6610625e-02 6.3822994e-02 1.0780225e-01 8.9119904e-02 7.0461434e-02 7.1328305e-02 8.7570443e-02 6.7451743e-02 7.8878318e-02 8.9018945e-02 7.7592264e-02 6.9886540e-02 6.1789581e-02 7.8498655e-02 6.7684600e-02 7.1587759e-02 6.7704325e-02 4.6526712e-02 7.0724596e-02 1.3117528e-01 1.1766016e-01 1.1197322e-01 1.1607657e-01 1.2231416e-01 1.2340084e-01 1.2042522e-01 1.1891967e-01 1.2666041e-01 1.0778594e-01 9.1812847e-02 1.1163169e-01 1.0543690e-01 1.2494830e-01 1.2593147e-01 1.0563286e-01 1.0596141e-01 1.0649455e-01 1.4431904e-01 1.1933022e-01 1.0786987e-01 1.1454955e-01 1.2887601e-01 9.8812977e-02 1.0562884e-01 1.0369928e-01 9.4451580e-02 9.4102215e-02 1.2194237e-01 1.0054711e-01 1.1549365e-01 9.2857172e-02 1.2382256e-01 9.7583400e-02 1.2385907e-01 1.1095947e-01 1.1423829e-01 1.0528942e-01 9.2735747e-02 9.8196145e-02 1.1321168e-01 9.3608756e-02 1.1766016e-01 1.1565299e-01 1.1307354e-01 1.0223904e-01 1.1010492e-01 9.9908851e-02 1.0821954e-01 1.0496782e-01 9.9295890e-03 5.3473138e-04 2.1693539e-03 3.7076821e-03 1.8222092e-03 1.2380588e-03 7.0429726e-04 3.2576994e-04 6.7027380e-04 7.5169669e-02 7.7062740e-02 8.6033367e-02 9.7417771e-02 9.0184218e-02 9.6534643e-02 8.3912481e-02 7.0270670e-02 8.3626528e-02 8.6844061e-02 9.2545497e-02 7.9257265e-02 9.0777176e-02 9.5235076e-02 6.2208659e-02 7.1858472e-02 9.5535449e-02 7.9390740e-02 1.1189093e-01 8.2130752e-02 1.0013922e-01 7.2643917e-02 1.1330079e-01 9.5998078e-02 7.6221141e-02 7.5580594e-02 9.1730689e-02 9.7114882e-02 9.1048046e-02 6.2224749e-02 8.3137120e-02 7.8094271e-02 7.4382594e-02 1.2083561e-01 9.9831872e-02 7.9711043e-02 8.2237066e-02 1.0057287e-01 7.7408745e-02 9.0227459e-02 1.0148848e-01 8.8790024e-02 8.1095637e-02 7.2322440e-02 8.9773416e-02 7.8184960e-02 8.2186791e-02 7.8567440e-02 5.4863235e-02 8.1347337e-02 1.4275245e-01 1.3005259e-01 1.2482271e-01 1.2925722e-01 1.3482920e-01 1.3759096e-01 1.3236924e-01 1.3338627e-01 1.4130888e-01 1.1880967e-01 1.0247320e-01 1.2443347e-01 1.1741517e-01 1.3747488e-01 1.3688510e-01 1.1618864e-01 1.1858835e-01 1.1879679e-01 1.5963135e-01 1.3387511e-01 1.1938532e-01 1.2588037e-01 1.4388488e-01 1.1083228e-01 1.1728514e-01 1.1680010e-01 1.0591970e-01 1.0525056e-01 1.3476053e-01 1.1410719e-01 1.2959057e-01 1.0487194e-01 1.3643100e-01 1.1046993e-01 1.3880755e-01 1.2375874e-01 1.2479172e-01 1.1764923e-01 1.0361548e-01 1.0965651e-01 1.2456830e-01 1.0392711e-01 1.3005259e-01 1.2763609e-01 1.2394348e-01 1.1308481e-01 1.2275352e-01 1.1138648e-01 1.1846972e-01 1.1666230e-01 1.1839370e-02 9.5901133e-03 1.3740734e-02 3.5338001e-03 1.3550011e-02 8.8526707e-03 9.4699409e-03 6.3350154e-03 4.8467987e-02 5.3749987e-02 5.7717889e-02 6.5676566e-02 6.0050880e-02 7.0693363e-02 6.1877604e-02 4.6729706e-02 5.4665912e-02 6.4242849e-02 5.9590174e-02 5.6493218e-02 5.5132102e-02 6.8254515e-02 4.1974046e-02 4.5979775e-02 7.3375693e-02 5.2912711e-02 7.3889063e-02 5.3879214e-02 7.8254066e-02 4.6403740e-02 7.8645675e-02 6.7578949e-02 4.9098308e-02 4.8671019e-02 5.9827034e-02 6.7861186e-02 6.5136324e-02 3.6759287e-02 5.3980965e-02 4.9365653e-02 4.8462917e-02 9.0010105e-02 7.8830145e-02 6.1496889e-02 5.5380536e-02 6.4107134e-02 5.6871111e-02 6.2034296e-02 7.3759034e-02 6.3674900e-02 5.3119604e-02 4.6143136e-02 6.3811294e-02 5.6759011e-02 5.9030859e-02 5.2419966e-02 3.3258744e-02 5.6880106e-02 1.1655832e-01 1.0005043e-01 9.1684275e-02 9.8727002e-02 1.0425490e-01 1.0138126e-01 1.0565129e-01 9.7538138e-02 1.0314095e-01 9.2386824e-02 7.6571607e-02 9.1274575e-02 8.6336607e-02 1.0505203e-01 1.0829773e-01 9.0077109e-02 8.8858206e-02 9.1549427e-02 1.1781623e-01 9.5530481e-02 9.0068051e-02 9.8963246e-02 1.0479240e-01 7.9118056e-02 9.0207341e-02 8.5766485e-02 7.6442113e-02 7.8991975e-02 1.0229780e-01 8.0971468e-02 9.2462279e-02 7.7616682e-02 1.0394880e-01 7.9854175e-02 1.0493060e-01 8.8086863e-02 1.0105189e-01 8.9771099e-02 7.8157448e-02 7.9782471e-02 9.4953430e-02 7.4768636e-02 1.0005043e-01 9.8253215e-02 9.6744777e-02 8.3113340e-02 8.7744069e-02 8.2353939e-02 9.5830913e-02 9.0799350e-02 2.1341759e-03 1.9110407e-03 2.4747400e-03 1.4759127e-04 2.6111423e-04 2.1389787e-04 9.9338048e-04 7.1511570e-02 7.2884660e-02 8.1954557e-02 9.3478761e-02 8.6419800e-02 9.0995738e-02 7.9065079e-02 6.6366318e-02 7.9643396e-02 8.2112775e-02 8.8849792e-02 7.5066735e-02 8.7600830e-02 9.0111864e-02 5.8883625e-02 6.8498056e-02 8.9863635e-02 7.4803608e-02 1.0853136e-01 7.8097142e-02 9.4627165e-02 6.9370599e-02 1.0871906e-01 9.0676026e-02 7.2617660e-02 7.2144076e-02 8.7900274e-02 9.2810262e-02 8.6387249e-02 5.9335633e-02 7.9309675e-02 7.4397587e-02 7.0710353e-02 1.1504320e-01 9.3692385e-02 7.4629165e-02 7.8263498e-02 9.7248749e-02 7.2487054e-02 8.6011897e-02 9.5823155e-02 8.3806772e-02 7.7264691e-02 6.8838121e-02 8.4948991e-02 7.3047820e-02 7.7341294e-02 7.4548923e-02 5.2558496e-02 7.6909140e-02 1.3627575e-01 1.2430643e-01 1.1978148e-01 1.2301688e-01 1.2902659e-01 1.3200226e-01 1.2597225e-01 1.2757685e-01 1.3584109e-01 1.1348127e-01 9.7761057e-02 1.1945082e-01 1.1270375e-01 1.3215934e-01 1.3182973e-01 1.1125522e-01 1.1287096e-01 1.1260483e-01 1.5425448e-01 1.2876341e-01 1.1448536e-01 1.2024528e-01 1.3833407e-01 1.0647529e-01 1.1163750e-01 1.1113351e-01 1.0149473e-01 1.0013701e-01 1.2927004e-01 1.0879101e-01 1.2459621e-01 9.9330508e-02 1.3108770e-01 1.0504760e-01 1.3186075e-01 1.1958837e-01 1.1892921e-01 1.1162833e-01 9.8541878e-02 1.0525098e-01 1.1976536e-01 1.0049727e-01 1.2430643e-01 1.2212353e-01 1.1885667e-01 1.0916600e-01 1.1853397e-01 1.0665478e-01 1.1270995e-01 1.1063603e-01 1.5750019e-03 2.3061943e-03 2.5267586e-03 1.8816551e-03 2.4916769e-03 2.6490348e-03 5.6749564e-02 5.7171493e-02 6.5939847e-02 7.5932398e-02 6.9508351e-02 7.4656451e-02 6.2624290e-02 5.2024188e-02 6.4437230e-02 6.4937043e-02 7.2745199e-02 5.8611781e-02 7.2652586e-02 7.3573688e-02 4.4171072e-02 5.3594578e-02 7.2641168e-02 6.1050608e-02 8.9566976e-02 6.3051224e-02 7.6010398e-02 5.4225638e-02 9.0321512e-02 7.5195114e-02 5.7639533e-02 5.6852233e-02 7.1710391e-02 7.4949900e-02 6.9318916e-02 4.6230253e-02 6.3971485e-02 6.0026157e-02 5.5798348e-02 9.5989279e-02 7.6232404e-02 5.8444003e-02 6.2302257e-02 8.0224536e-02 5.7278169e-02 6.9150783e-02 7.9467477e-02 6.7704503e-02 6.1864652e-02 5.4241616e-02 6.8592620e-02 5.8516944e-02 6.1759106e-02 5.9360348e-02 3.8591759e-02 6.1151978e-02 1.1324556e-01 1.0303819e-01 9.9201558e-02 1.0318500e-01 1.0721879e-01 1.1147036e-01 1.0460948e-01 1.0828938e-01 1.1523751e-01 9.2280249e-02 7.8300492e-02 9.8832112e-02 9.2088327e-02 1.0954453e-01 1.0774163e-01 8.9704304e-02 9.3649245e-02 9.3477002e-02 1.3171389e-01 1.0896793e-01 9.3248418e-02 9.8534682e-02 1.1788866e-01 8.6730988e-02 9.1550165e-02 9.2743651e-02 8.2023117e-02 8.1036634e-02 1.0749375e-01 9.1211084e-02 1.0479473e-01 8.1639608e-02 1.0872731e-01 8.7298316e-02 1.1342725e-01 9.8507274e-02 9.7018335e-02 9.2572028e-02 7.9424005e-02 8.5123740e-02 9.7519007e-02 7.9504622e-02 1.0303819e-01 1.0060889e-01 9.6540999e-02 8.7528391e-02 9.7464514e-02 8.6517419e-02 9.1407615e-02 9.1076579e-02 4.2759888e-03 1.3998823e-03 1.8495751e-03 2.8301386e-03 3.7334484e-03 5.5009109e-02 5.4964037e-02 6.3820777e-02 7.4331569e-02 6.8062522e-02 7.0406681e-02 5.9595322e-02 4.9880526e-02 6.2237804e-02 6.2265151e-02 7.1113130e-02 5.6594278e-02 7.1451534e-02 6.9994053e-02 4.3126676e-02 5.2381128e-02 6.8520339e-02 5.7597897e-02 8.9058557e-02 6.0751652e-02 7.2510768e-02 5.3201106e-02 8.7849614e-02 7.0985642e-02 5.6028788e-02 5.5591108e-02 6.9920676e-02 7.2931234e-02 6.6633349e-02 4.5295849e-02 6.2044642e-02 5.8063752e-02 5.4097801e-02 9.1903182e-02 7.1473709e-02 5.5091248e-02 6.0376704e-02 7.9310761e-02 5.3854777e-02 6.7042056e-02 7.4968513e-02 6.4284932e-02 5.9983090e-02 5.2745182e-02 6.5463515e-02 5.4553279e-02 5.8476643e-02 5.7183259e-02 3.8909009e-02 5.8515093e-02 1.0925308e-01 9.9624317e-02 9.6622305e-02 9.8607255e-02 1.0383961e-01 1.0792916e-01 1.0029496e-01 1.0408880e-01 1.1184636e-01 8.9608429e-02 7.6157674e-02 9.6354194e-02 9.0095873e-02 1.0708448e-01 1.0618312e-01 8.7751513e-02 8.9756663e-02 8.8888346e-02 1.2885985e-01 1.0591974e-01 9.1173391e-02 9.5499762e-02 1.1429851e-01 8.5048829e-02 8.8069568e-02 8.8675858e-02 8.0228990e-02 7.8160661e-02 1.0454059e-01 8.7419578e-02 1.0196835e-01 7.7696889e-02 1.0615601e-01 8.3458946e-02 1.0727792e-01 9.7348785e-02 9.3770662e-02 8.8214646e-02 7.6638467e-02 8.3519036e-02 9.5849316e-02 7.9674217e-02 9.9624317e-02 9.7643485e-02 9.4514516e-02 8.7075933e-02 9.6245490e-02 8.4428758e-02 8.8195121e-02 8.6900395e-02 3.3656636e-03 1.2813341e-03 1.5508786e-03 5.5126016e-04 5.7906981e-02 6.0932190e-02 6.7790041e-02 7.7661589e-02 7.1242410e-02 7.8649743e-02 6.7963400e-02 5.4275670e-02 6.5215187e-02 7.0651008e-02 7.2495968e-02 6.3298898e-02 6.9915496e-02 7.7039648e-02 4.7868354e-02 5.5074415e-02 7.9095397e-02 6.1872293e-02 8.9630734e-02 6.4010779e-02 8.3786653e-02 5.5727300e-02 9.1943867e-02 7.7179306e-02 5.8787276e-02 5.8290887e-02 7.2059853e-02 7.8226343e-02 7.3481150e-02 4.5978845e-02 6.4704253e-02 5.9980041e-02 5.7435326e-02 1.0050646e-01 8.3655459e-02 6.5308029e-02 6.4668898e-02 7.9130910e-02 6.2159352e-02 7.1908147e-02 8.2739305e-02 7.1488143e-02 6.3159434e-02 5.5376396e-02 7.2163727e-02 6.2508559e-02 6.5824794e-02 6.1340761e-02 4.0472995e-02 6.4599849e-02 1.2380425e-01 1.0993395e-01 1.0373859e-01 1.0879322e-01 1.1440237e-01 1.1495444e-01 1.1335001e-01 1.1089530e-01 1.1789001e-01 1.0041407e-01 8.4708778e-02 1.0336455e-01 9.7357032e-02 1.1642404e-01 1.1748667e-01 9.8081847e-02 9.8747663e-02 9.9805801e-02 1.3456454e-01 1.1060300e-01 9.9947092e-02 1.0709744e-01 1.2004751e-01 9.0729860e-02 9.8544296e-02 9.6489030e-02 8.6759859e-02 8.7175826e-02 1.1367288e-01 9.3122372e-02 1.0688813e-01 8.6280635e-02 1.1536030e-01 9.0496365e-02 1.1670380e-01 1.0195807e-01 1.0724940e-01 9.8472199e-02 8.5899722e-02 9.0288199e-02 1.0497525e-01 8.5251170e-02 1.0993395e-01 1.0787024e-01 1.0524763e-01 9.3789157e-02 1.0121309e-01 9.2226653e-02 1.0148816e-01 9.8306001e-02 5.0782435e-04 6.2020689e-04 1.6756986e-03 7.0476887e-02 7.1501157e-02 8.0709837e-02 9.2336294e-02 8.5349594e-02 8.8954923e-02 7.7301298e-02 6.5155686e-02 7.8476830e-02 8.0402665e-02 8.7884855e-02 7.3650267e-02 8.6974315e-02 8.8299731e-02 5.7895678e-02 6.7595783e-02 8.7665774e-02 7.3314500e-02 1.0776923e-01 7.6895020e-02 9.2474273e-02 6.8514181e-02 1.0728576e-01 8.8812805e-02 7.1614033e-02 7.1214401e-02 8.6845407e-02 9.1428310e-02 8.4778392e-02 5.8702706e-02 7.8223013e-02 7.3389903e-02 6.9650470e-02 1.1290739e-01 9.1229062e-02 7.2678536e-02 7.7045799e-02 9.6518176e-02 7.0683794e-02 8.4677029e-02 9.3753287e-02 8.2039996e-02 7.6152676e-02 6.7885263e-02 8.3273481e-02 7.1166737e-02 7.5618620e-02 7.3311647e-02 5.2129744e-02 7.5414559e-02 1.3361288e-01 1.2212885e-01 1.1803753e-01 1.2062983e-01 1.2681873e-01 1.3003785e-01 1.2339855e-01 1.2552093e-01 1.3397302e-01 1.1145011e-01 9.6072866e-02 1.1773621e-01 1.1108813e-01 1.3021606e-01 1.2991222e-01 1.0941117e-01 1.1074904e-01 1.1019635e-01 1.5245649e-01 1.2709803e-01 1.1272646e-01 1.1805571e-01 1.3644429e-01 1.0507143e-01 1.0948152e-01 1.0908044e-01 1.0002018e-01 9.8259510e-02 1.2725753e-01 1.0697349e-01 1.2296793e-01 9.7285465e-02 1.2913723e-01 1.0312519e-01 1.2920697e-01 1.1832381e-01 1.1655849e-01 1.0932054e-01 9.6669076e-02 1.0377916e-01 1.1803847e-01 9.9488230e-02 1.2212885e-01 1.2004765e-01 1.1693776e-01 1.0790940e-01 1.1723226e-01 1.0500092e-01 1.1038445e-01 1.0827603e-01 1.5232780e-04 4.0007181e-04 6.5289213e-02 6.7204649e-02 7.5443787e-02 8.6444762e-02 7.9660759e-02 8.4749914e-02 7.3546883e-02 6.0641799e-02 7.3012359e-02 7.6531840e-02 8.1598668e-02 6.9499172e-02 7.9923854e-02 8.3724381e-02 5.3799024e-02 6.2453508e-02 8.4253942e-02 6.8486788e-02 1.0054294e-01 7.1576362e-02 8.9122210e-02 6.3281093e-02 1.0114322e-01 8.3993466e-02 6.6335786e-02 6.5925957e-02 8.0814161e-02 8.6165539e-02 8.0247902e-02 5.3368917e-02 7.2666724e-02 6.7816556e-02 6.4623203e-02 1.0800053e-01 8.8235002e-02 6.9728892e-02 7.2010954e-02 8.9470933e-02 6.7181463e-02 7.9529500e-02 8.9243318e-02 7.7739806e-02 7.0823200e-02 6.2720078e-02 7.8762930e-02 6.7548169e-02 7.1608713e-02 6.8390856e-02 4.7339693e-02 7.1004341e-02 1.3006516e-01 1.1747357e-01 1.1247378e-01 1.1599806e-01 1.2210677e-01 1.2411360e-01 1.1962941e-01 1.1968938e-01 1.2763702e-01 1.0730056e-01 9.1685935e-02 1.1214725e-01 1.0578284e-01 1.2500364e-01 1.2540001e-01 1.0518188e-01 1.0602704e-01 1.0612761e-01 1.4550231e-01 1.2054520e-01 1.0786099e-01 1.1396219e-01 1.2996046e-01 9.9460763e-02 1.0527691e-01 1.0405039e-01 9.4844256e-02 9.3945852e-02 1.2206303e-01 1.0136794e-01 1.1659636e-01 9.2882126e-02 1.2391115e-01 9.8044098e-02 1.2415930e-01 1.1196299e-01 1.1316845e-01 1.0506061e-01 9.2491851e-02 9.8554383e-02 1.1313163e-01 9.4057839e-02 1.1747357e-01 1.1542880e-01 1.1260458e-01 1.0255212e-01 1.1101490e-01 1.0006494e-01 1.0712947e-01 1.0442482e-01 3.2637736e-04 7.1228332e-02 7.3360309e-02 8.1848237e-02 9.3197783e-02 8.6156854e-02 9.1733116e-02 8.0052769e-02 6.6468809e-02 7.9277125e-02 8.3130576e-02 8.8073461e-02 7.5751270e-02 8.6114214e-02 9.0610516e-02 5.9264749e-02 6.8242422e-02 9.1255768e-02 7.4667198e-02 1.0756842e-01 7.7803425e-02 9.6260495e-02 6.9087389e-02 1.0845861e-01 9.0870006e-02 7.2305626e-02 7.1861030e-02 8.7311178e-02 9.3009359e-02 8.6960677e-02 5.8641082e-02 7.8892851e-02 7.3809649e-02 7.0554233e-02 1.1577001e-01 9.5424873e-02 7.6110400e-02 7.8288785e-02 9.6097634e-02 7.3451146e-02 8.6123272e-02 9.6377446e-02 8.4403314e-02 7.7003085e-02 6.8529959e-02 8.5437768e-02 7.3849362e-02 7.8032414e-02 7.4531055e-02 5.2299301e-02 7.7339214e-02 1.3853845e-01 1.2553252e-01 1.2026484e-01 1.2407451e-01 1.3030382e-01 1.3228892e-01 1.2783055e-01 1.2774776e-01 1.3586522e-01 1.1498861e-01 9.8800101e-02 1.1991948e-01 1.1333278e-01 1.3320266e-01 1.3352807e-01 1.1273476e-01 1.1373642e-01 1.1391093e-01 1.5417322e-01 1.2849633e-01 1.1550662e-01 1.2189074e-01 1.3824515e-01 1.0674666e-01 1.1296262e-01 1.1166908e-01 1.0200786e-01 1.0119861e-01 1.3020916e-01 1.0880524e-01 1.2443747e-01 1.0015009e-01 1.3208523e-01 1.0543261e-01 1.3248948e-01 1.1957063e-01 1.2107326e-01 1.1278773e-01 9.9690412e-02 1.0583253e-01 1.2090813e-01 1.0100447e-01 1.2553252e-01 1.2339293e-01 1.2039941e-01 1.0985773e-01 1.1861026e-01 1.0744824e-01 1.1483872e-01 1.1213527e-01 6.6878313e-02 6.9715409e-02 7.7364528e-02 8.8171063e-02 8.1336125e-02 8.7984980e-02 7.6788970e-02 6.2680317e-02 7.4638540e-02 7.9773718e-02 8.2744330e-02 7.2225777e-02 8.0191157e-02 8.6590874e-02 5.5913229e-02 6.3969698e-02 8.8177048e-02 7.0519412e-02 1.0143390e-01 7.3287383e-02 9.3242485e-02 6.4744474e-02 1.0311960e-01 8.6619094e-02 6.7881619e-02 6.7447267e-02 8.2187438e-02 8.8483348e-02 8.3036483e-02 5.4275541e-02 7.4193034e-02 6.9119612e-02 6.6341718e-02 1.1134910e-01 9.2648103e-02 7.3522039e-02 7.4021876e-02 9.0141442e-02 7.0408618e-02 8.1718494e-02 9.2345175e-02 8.0646828e-02 7.2501162e-02 6.4223536e-02 8.1515678e-02 7.0682605e-02 7.4552513e-02 7.0364536e-02 4.8478235e-02 7.3560525e-02 1.3517901e-01 1.2131760e-01 1.1535330e-01 1.1982809e-01 1.2602646e-01 1.2698846e-01 1.2430464e-01 1.2251062e-01 1.3021845e-01 1.1127258e-01 9.4973617e-02 1.1499323e-01 1.0869119e-01 1.2854331e-01 1.2950169e-01 1.0899747e-01 1.0948608e-01 1.1017110e-01 1.4797664e-01 1.2271397e-01 1.1121974e-01 1.1817834e-01 1.3245873e-01 1.0189203e-01 1.0916690e-01 1.0716280e-01 9.7527876e-02 9.7386912e-02 1.2555051e-01 1.0384747e-01 1.1883003e-01 9.6216108e-02 1.2741273e-01 1.0091958e-01 1.2779606e-01 1.1407020e-01 1.1794445e-01 1.0890370e-01 9.6003260e-02 1.0130628e-01 1.1658801e-01 9.6417670e-02 1.2131760e-01 1.1923852e-01 1.1654354e-01 1.0526503e-01 1.1322934e-01 1.0313209e-01 1.1184758e-01 1.0860395e-01 7.4548764e-04 4.1909104e-04 1.5729317e-03 7.9277531e-04 2.5985333e-03 2.1157871e-03 2.6363318e-04 2.7214324e-04 2.5006701e-03 1.1999234e-03 1.3641574e-03 2.4228657e-03 1.9193080e-03 1.5580763e-03 9.1547441e-05 4.2498838e-03 5.1587623e-04 4.4451535e-03 1.9710136e-04 5.9468529e-03 1.1637586e-04 4.0879090e-03 1.9577278e-03 7.5438506e-06 5.1321994e-05 9.5746588e-04 1.8362275e-03 1.6353958e-03 8.5567943e-04 2.3534169e-04 2.0155706e-04 2.8744085e-05 6.6464816e-03 6.0500135e-03 3.7609984e-03 3.0183871e-04 2.6908058e-03 1.8208811e-03 9.2994693e-04 3.0287331e-03 1.4489077e-03 1.1766146e-04 3.4058119e-05 1.3255619e-03 1.5104843e-03 1.2375803e-03 1.2042792e-04 2.2770079e-03 7.0925866e-04 1.7863102e-02 1.0250835e-02 7.3485693e-03 9.3316539e-03 1.1683662e-02 1.0169272e-02 1.2909901e-02 9.0217168e-03 1.1005819e-02 9.1383359e-03 4.6331293e-03 7.2658380e-03 6.2625155e-03 1.2163934e-02 1.5604510e-02 9.0849374e-03 6.4499430e-03 7.6430735e-03 1.6734199e-02 8.8633570e-03 7.8095179e-03 1.1083442e-02 1.1720144e-02 4.3192019e-03 7.6217573e-03 5.4833250e-03 3.8602370e-03 4.7396014e-03 1.0813609e-02 4.4772013e-03 7.7667524e-03 3.8237256e-03 1.1654961e-02 4.0471444e-03 1.1640132e-02 6.9842505e-03 1.3199398e-02 6.9808241e-03 4.8195688e-03 4.8204301e-03 9.7963275e-03 5.3012133e-03 1.0250835e-02 1.0025463e-02 1.1016974e-02 6.8718627e-03 6.8391566e-03 5.4173007e-03 1.1780352e-02 7.9156890e-03 7.3587704e-04 1.9839586e-03 1.2219042e-03 1.5405721e-03 4.1726993e-04 3.7297590e-04 1.1835574e-03 6.1737386e-04 2.7177989e-03 1.1395438e-04 5.3634867e-03 1.2095802e-03 9.5552631e-04 7.0211590e-04 1.8297765e-03 1.3098829e-03 5.8522900e-03 1.0011765e-03 2.8317516e-03 7.2859483e-04 4.4710316e-03 2.0244176e-03 7.6733040e-04 6.7685529e-04 2.1301657e-03 1.3518842e-03 6.1205846e-04 2.4644310e-03 1.1938153e-03 1.5975309e-03 5.1076446e-04 5.2791382e-03 3.0339660e-03 1.1907842e-03 3.5011674e-04 4.7257393e-03 3.5465173e-04 7.3647426e-04 2.3478030e-03 5.8214999e-04 7.6861523e-04 8.1449121e-04 5.9893306e-04 4.9750178e-04 2.3193980e-04 3.6882491e-04 2.8017975e-03 9.9802686e-05 1.3102890e-02 7.5969761e-03 6.0828162e-03 7.3064415e-03 8.8657957e-03 9.3996859e-03 9.1529212e-03 8.6958624e-03 1.0707084e-02 5.8653516e-03 2.3848099e-03 6.0110419e-03 4.6435179e-03 9.5841132e-03 1.1495876e-02 5.7351815e-03 4.7762002e-03 5.2279685e-03 1.6343054e-02 9.1684398e-03 5.3835136e-03 7.5338144e-03 1.1677909e-02 3.4411805e-03 4.9237859e-03 4.5530879e-03 2.5678146e-03 2.5808970e-03 8.5897045e-03 4.5950787e-03 7.8389611e-03 2.4182455e-03 9.2053995e-03 3.4479875e-03 1.0780684e-02 6.4366206e-03 8.7029459e-03 4.8244677e-03 2.4820766e-03 3.2994674e-03 6.9725103e-03 3.6004536e-03 7.5969761e-03 7.2055876e-03 7.4680636e-03 4.8244418e-03 6.1219436e-03 3.5524443e-03 7.3785563e-03 5.0327851e-03 4.5958248e-04 1.4323573e-04 1.2376608e-03 1.4854110e-03 8.9326822e-04 1.4516004e-04 1.6538068e-03 6.5338340e-04 1.1299287e-03 2.4074626e-03 6.9551596e-04 2.6949476e-03 7.2730987e-04 2.7608296e-03 6.5430290e-04 2.7448595e-03 1.4433165e-04 4.0981488e-03 7.0217976e-04 2.0017194e-03 8.4737221e-04 3.5875154e-04 4.2590326e-04 3.7194881e-04 5.5222558e-04 6.3134375e-04 2.4465093e-03 1.5551077e-04 5.7141821e-04 4.4617793e-04 3.7751002e-03 4.2307180e-03 3.3297057e-03 8.4238856e-05 1.8060244e-03 1.6735237e-03 1.3470834e-04 1.4289074e-03 6.1420964e-04 1.0488316e-04 6.6710002e-04 4.5037482e-04 1.3817339e-03 8.2351922e-04 1.8947713e-04 4.2527867e-03 4.2014447e-04 1.3415184e-02 6.6868372e-03 4.2910287e-03 5.8862692e-03 7.8406972e-03 6.4938295e-03 9.0912854e-03 5.6561218e-03 7.2322567e-03 6.1641630e-03 2.7540356e-03 4.2344365e-03 3.5847503e-03 8.2354910e-03 1.1610160e-02 6.2859853e-03 3.6577005e-03 4.7344286e-03 1.2033367e-02 5.6148647e-03 4.9101139e-03 7.6703569e-03 7.8664866e-03 2.1500523e-03 4.7726337e-03 2.9188064e-03 1.9107921e-03 2.6804057e-03 7.0603390e-03 2.2776004e-03 4.6992435e-03 1.8838392e-03 7.7943774e-03 1.9124732e-03 7.9102721e-03 4.1636243e-03 9.7823337e-03 4.1721395e-03 2.8414673e-03 2.6224860e-03 6.5787438e-03 3.5255969e-03 6.6868372e-03 6.5865547e-03 7.7526002e-03 4.4665713e-03 4.0404299e-03 3.0508638e-03 8.7371106e-03 5.0758684e-03 1.4741381e-04 1.6125952e-03 2.5451963e-03 2.5693849e-03 7.6673984e-04 2.4419486e-03 4.9090126e-04 2.2351893e-03 2.2914219e-03 9.4806103e-04 4.8625587e-03 2.0262116e-03 3.3701508e-03 1.9166326e-03 1.0683081e-03 9.0452408e-04 4.3648468e-03 1.8983778e-03 7.0324108e-04 1.1499379e-03 1.4013722e-03 1.4463883e-03 3.0992383e-04 2.7889447e-04 9.9370768e-04 4.4215550e-03 7.4609763e-04 1.5322654e-03 1.6670592e-03 2.5458750e-03 4.8164855e-03 4.9491294e-03 7.9622502e-04 9.3705610e-04 3.2918730e-03 3.3244867e-04 1.4917733e-03 1.2997427e-03 8.4964648e-04 1.9833350e-03 9.7663737e-04 3.0207145e-03 1.9767871e-03 1.2186915e-03 6.6584952e-03 1.4294810e-03 1.1447125e-02 4.9138585e-03 2.4483433e-03 4.3479747e-03 5.8020082e-03 4.0665925e-03 7.5951000e-03 3.6015682e-03 4.5184530e-03 5.0362911e-03 2.3873447e-03 2.3916463e-03 2.1166084e-03 5.8005881e-03 9.3326086e-03 5.1921662e-03 2.5583136e-03 3.9040792e-03 8.1942534e-03 3.2098756e-03 3.4610228e-03 6.2351763e-03 5.0378736e-03 9.3974884e-04 3.8135545e-03 1.8905878e-03 1.0935023e-03 2.2739982e-03 4.8352649e-03 1.2660181e-03 2.5068904e-03 1.6511455e-03 5.4229770e-03 1.1989559e-03 6.1054655e-03 2.0081796e-03 8.6788304e-03 3.3159020e-03 2.5546078e-03 1.5534900e-03 4.7975700e-03 2.5264412e-03 4.9138585e-03 4.8875866e-03 6.2264786e-03 3.0375207e-03 1.9750388e-03 2.0217929e-03 8.0063599e-03 4.3571190e-03 1.6611913e-03 2.0167984e-03 1.5438876e-03 3.6494229e-04 2.0217253e-03 4.6462511e-04 1.5312613e-03 2.1707116e-03 9.6955753e-04 3.3920004e-03 1.0848877e-03 3.2679078e-03 1.3217642e-03 1.7681092e-03 4.3634818e-04 4.3762590e-03 9.8982281e-04 1.4702047e-03 1.2309511e-03 6.6753502e-04 6.7519636e-04 2.4877587e-04 3.8105160e-04 8.2183923e-04 3.0399429e-03 3.2267433e-04 8.9534104e-04 8.4272052e-04 3.5139014e-03 4.8234985e-03 4.1432495e-03 3.0463297e-04 1.2193814e-03 2.4923401e-03 1.7011388e-04 1.7584273e-03 1.0444437e-03 3.3026408e-04 1.0723664e-03 7.7198092e-04 2.2859213e-03 1.4276818e-03 5.7687029e-04 4.8466907e-03 8.6936394e-04 1.2850654e-02 6.1088154e-03 3.5569698e-03 5.5719646e-03 7.1488198e-03 5.6571014e-03 8.7634622e-03 5.0674178e-03 6.2538450e-03 5.7468537e-03 2.5694606e-03 3.4855366e-03 2.9211508e-03 7.2454781e-03 1.0560745e-02 5.7784909e-03 3.4230741e-03 4.7152707e-03 1.0513823e-02 4.7114505e-03 4.2697686e-03 7.1803873e-03 6.8688743e-03 1.5447042e-03 4.5401495e-03 2.7361382e-03 1.4855517e-03 2.5857007e-03 6.2270622e-03 2.0576267e-03 3.8519560e-03 2.0130817e-03 6.8461641e-03 1.8250891e-03 7.7109246e-03 3.0910476e-03 9.4645289e-03 4.1075164e-03 2.7837137e-03 2.0667492e-03 5.7442304e-03 2.7416306e-03 6.1088154e-03 5.9744542e-03 7.0784056e-03 3.5969994e-03 3.0144395e-03 2.5834027e-03 8.5675229e-03 5.0446428e-03 9.3410747e-04 2.6108336e-03 1.8631164e-03 1.0514258e-03 2.7757095e-03 1.6027319e-03 5.9009151e-03 9.3507643e-05 4.8585250e-03 3.2279691e-03 7.0814372e-04 1.8064210e-03 4.7021523e-03 1.7906187e-03 1.7438865e-03 3.2726931e-03 2.1092470e-03 4.4199215e-04 2.5742583e-03 2.7576288e-03 2.1865740e-03 8.5954487e-04 4.3875130e-04 6.2385517e-03 2.0706463e-03 2.9895922e-03 2.4900150e-03 1.5452115e-03 1.2972442e-03 2.2089282e-03 1.3825902e-03 4.4047937e-03 1.3378707e-03 8.5528525e-04 1.4287812e-04 2.3200710e-04 1.9018574e-03 3.1193134e-03 2.7835858e-04 1.0440284e-03 6.7774868e-04 1.6434489e-03 8.2787646e-03 9.1805293e-04 8.2830461e-03 3.6334874e-03 2.7936555e-03 2.6701226e-03 4.5417785e-03 4.4199379e-03 4.7638022e-03 3.6853341e-03 5.4544340e-03 3.4799734e-03 1.6014887e-03 2.8117239e-03 2.4093914e-03 5.5035080e-03 8.3987820e-03 4.0331795e-03 1.3946498e-03 1.6013776e-03 9.9231424e-03 4.6841468e-03 3.0824955e-03 4.3724199e-03 6.0877536e-03 1.8755546e-03 2.0838499e-03 1.1387331e-03 1.4636530e-03 1.0937142e-03 4.3877001e-03 1.4753015e-03 3.8552640e-03 2.5868499e-04 5.1223304e-03 7.0168484e-04 4.3920187e-03 3.9679568e-03 5.8082286e-03 1.3720301e-03 1.2437314e-03 1.9911684e-03 4.5361159e-03 3.9571028e-03 3.6334874e-03 3.7423473e-03 5.0666856e-03 3.9975266e-03 3.7265040e-03 1.8650355e-03 5.0595778e-03 1.9211780e-03 1.4802848e-03 2.3288314e-03 6.8065434e-05 4.0423471e-03 2.2193959e-04 7.6466779e-03 9.2054349e-04 2.1021154e-03 2.1770952e-03 5.4412625e-04 2.3412508e-03 6.7735470e-03 2.1146424e-03 1.1473823e-03 2.2087962e-03 4.4699141e-03 2.0616206e-03 2.1327263e-03 2.0380999e-03 3.2539726e-03 1.3598045e-03 3.9670027e-04 4.8634117e-03 2.4197901e-03 3.2204932e-03 1.7622064e-03 3.8856461e-03 1.2334789e-03 4.0452577e-04 1.0887743e-03 6.2435560e-03 2.0292084e-04 1.0829901e-03 1.7786841e-03 4.1228310e-04 1.8859956e-03 2.3286589e-03 5.1772577e-04 4.9172870e-04 2.0007065e-04 1.2918676e-03 5.0330599e-03 3.9898095e-04 9.4287570e-03 5.3866372e-03 4.8647393e-03 5.2819054e-03 6.4598280e-03 8.0073865e-03 6.1852254e-03 7.5566712e-03 9.5128884e-03 3.7267827e-03 1.2843714e-03 4.8237356e-03 3.5085400e-03 7.3800011e-03 8.6672418e-03 3.7373665e-03 3.3006522e-03 3.2553459e-03 1.4768796e-02 8.5372346e-03 3.7597131e-03 5.0208833e-03 1.0540608e-02 2.9216135e-03 2.9987594e-03 3.5026889e-03 1.9346800e-03 1.3415748e-03 6.5619943e-03 4.2356898e-03 7.2096387e-03 1.4370251e-03 7.0771420e-03 2.7742326e-03 8.9575949e-03 5.8574207e-03 5.7119619e-03 3.0499081e-03 1.2067939e-03 2.4757916e-03 5.0772246e-03 3.1235792e-03 5.3866372e-03 5.0347068e-03 5.1609892e-03 3.8212989e-03 5.4644467e-03 2.4256658e-03 4.6018293e-03 2.9278326e-03 8.9754714e-04 1.9308173e-03 2.4780225e-03 8.6351250e-04 4.2337045e-03 2.1236680e-03 7.2381764e-04 2.1294516e-04 3.5897400e-03 7.7335429e-04 6.4715989e-03 7.0701488e-04 5.1814848e-03 2.9010443e-04 5.5409554e-03 2.4566735e-03 3.3429771e-04 3.2970103e-04 2.0470962e-03 2.3835444e-03 1.6383998e-03 1.0044594e-03 8.9092263e-04 8.3257442e-04 1.5048347e-04 7.3947599e-03 5.1765389e-03 2.4819362e-03 5.2929628e-04 4.5409213e-03 9.8467896e-04 1.3414871e-03 3.3640577e-03 1.3544701e-03 5.6680732e-04 2.1931945e-04 1.3672243e-03 8.5440953e-04 8.3314842e-04 2.6161270e-04 1.7366856e-03 5.2799539e-04 1.7649847e-02 1.0764587e-02 8.4383096e-03 9.9924928e-03 1.2273825e-02 1.1788899e-02 1.2850999e-02 1.0630699e-02 1.2964118e-02 9.0438994e-03 4.5288546e-03 8.3580766e-03 6.9988358e-03 1.3044370e-02 1.5771615e-02 8.9276151e-03 7.0025139e-03 7.7681345e-03 1.9248623e-02 1.0890288e-02 8.2148016e-03 1.1050411e-02 1.3845989e-02 5.2067991e-03 7.6819868e-03 6.2976924e-03 4.3733262e-03 4.7066273e-03 1.1733076e-02 5.6953630e-03 9.5825887e-03 4.0184455e-03 1.2555508e-02 4.8201445e-03 1.2938333e-02 8.5012649e-03 1.2613331e-02 7.2187981e-03 4.6491251e-03 5.3739269e-03 1.0213138e-02 5.7106829e-03 1.0764587e-02 1.0424589e-02 1.1013685e-02 7.3861586e-03 8.2413252e-03 5.8213434e-03 1.1031181e-02 7.7860554e-03 2.6482878e-03 4.2794287e-04 1.8319104e-03 1.5871773e-03 1.2340260e-03 2.9761573e-03 6.4181441e-04 3.9337040e-03 3.6570436e-04 2.9155752e-03 1.3382816e-05 5.6692471e-03 6.4631376e-04 2.4262663e-03 1.0063227e-03 2.3414789e-04 3.8352406e-04 2.6670153e-04 1.1841642e-03 1.3362953e-03 1.8214422e-03 1.1939941e-05 1.6841308e-04 4.0205285e-04 4.8423454e-03 5.6256276e-03 4.4224155e-03 3.0861840e-04 1.5326607e-03 2.2893524e-03 5.4845532e-04 1.9363566e-03 1.1483728e-03 6.7060376e-05 4.8890125e-04 9.7136579e-04 1.7676633e-03 1.3375465e-03 2.5372175e-04 4.0846507e-03 8.2917869e-04 1.6077651e-02 8.4460632e-03 5.5177458e-03 7.2638972e-03 9.7215743e-03 7.5597148e-03 1.1218034e-02 6.4234899e-03 8.1582316e-03 8.1119193e-03 4.1520915e-03 5.4624397e-03 4.9276011e-03 1.0142169e-02 1.4194600e-02 8.3023965e-03 4.8434975e-03 6.1466052e-03 1.3239048e-02 6.2447391e-03 6.5902144e-03 9.7724034e-03 8.6919298e-03 3.1454944e-03 6.3952659e-03 3.7622934e-03 3.0039560e-03 4.0045050e-03 8.7466217e-03 2.6847018e-03 5.4026497e-03 2.7900002e-03 9.6269482e-03 2.5687827e-03 8.7444600e-03 5.2241473e-03 1.2215015e-02 5.4919656e-03 4.2251052e-03 3.8716574e-03 8.5147448e-03 4.9424074e-03 8.4460632e-03 8.4294916e-03 9.9304629e-03 6.0757927e-03 5.1533590e-03 4.4115457e-03 1.1061881e-02 6.6918878e-03 4.2077380e-03 2.8084601e-04 8.0255307e-03 1.0009734e-03 2.4531898e-03 2.5259126e-03 4.7784400e-04 2.9272193e-03 6.4204523e-03 2.4613181e-03 8.1446100e-04 2.5131313e-03 4.2288269e-03 2.3479589e-03 2.4787654e-03 2.3219118e-03 3.4016339e-03 1.1923522e-03 3.6609993e-04 5.5309499e-03 2.7130308e-03 3.6876750e-03 2.1157012e-03 3.5197143e-03 1.1211667e-03 5.0040735e-04 1.2581494e-03 6.2453424e-03 4.9316252e-04 1.0956505e-03 1.9034882e-03 5.6262931e-04 2.1623642e-03 2.7381233e-03 6.2275542e-04 9.1647472e-04 4.3469066e-04 1.6016964e-03 5.5073116e-03 6.0170029e-04 8.2861929e-03 4.5965840e-03 4.2124912e-03 4.7715416e-03 5.5699315e-03 7.3813594e-03 5.3659110e-03 7.1660104e-03 8.8786575e-03 2.9267242e-03 8.0445420e-04 4.1635703e-03 2.8364579e-03 6.3397911e-03 7.3211567e-03 2.8639086e-03 2.8974680e-03 2.8626073e-03 1.3776826e-02 8.0525608e-03 2.9632152e-03 4.1293440e-03 9.9396499e-03 2.4124505e-03 2.4179141e-03 3.2613675e-03 1.4673422e-03 9.3714862e-04 5.6839580e-03 4.1506352e-03 6.7187933e-03 1.3083992e-03 6.0861850e-03 2.6486423e-03 8.7285257e-03 5.1099460e-03 4.7657924e-03 2.6722144e-03 7.9417630e-04 1.8862622e-03 4.0883053e-03 2.3510235e-03 4.5965840e-03 4.1923613e-03 4.1490574e-03 2.9383782e-03 4.7171745e-03 1.8344857e-03 3.7646957e-03 2.4446440e-03 3.4307781e-03 6.9180223e-04 1.9272484e-03 5.2229584e-03 1.7410764e-03 5.5262484e-03 1.3512624e-03 1.2930220e-03 5.9265821e-04 7.2336834e-03 1.6622228e-03 1.4643809e-03 1.4579196e-03 1.0665934e-03 1.2486050e-03 4.3399433e-05 1.3778574e-03 2.2390179e-03 3.1206766e-03 3.9982611e-04 7.0342073e-04 1.4793565e-03 4.5495005e-03 7.4063181e-03 6.9037801e-03 1.1215419e-03 3.4551859e-04 4.3750592e-03 1.0242073e-03 2.4559606e-03 2.2544417e-03 6.9180223e-04 1.5393939e-03 1.8990091e-03 3.7039856e-03 2.8782332e-03 1.2534261e-03 6.1345149e-03 2.1154370e-03 1.6389445e-02 8.1714731e-03 4.6971245e-03 6.9480013e-03 9.2874957e-03 6.0735661e-03 1.1557043e-02 5.0795005e-03 6.2695782e-03 8.5942939e-03 4.8981354e-03 4.6386510e-03 4.5456138e-03 9.3051239e-03 1.4039626e-02 8.8459552e-03 4.7683489e-03 6.5513763e-03 1.0462868e-02 4.3969158e-03 6.5113261e-03 1.0098096e-02 6.6155737e-03 2.7131547e-03 6.8044529e-03 3.4785563e-03 3.0414918e-03 4.6799978e-03 7.9508909e-03 2.0423594e-03 3.8146379e-03 3.3303959e-03 8.7946774e-03 2.4271150e-03 7.7798359e-03 3.9016462e-03 1.3149131e-02 5.7850137e-03 5.0633237e-03 3.7856360e-03 8.3083336e-03 4.9921128e-03 8.1714731e-03 8.2786520e-03 1.0189399e-02 5.8912773e-03 3.9649361e-03 4.4771942e-03 1.2268673e-02 7.3587328e-03 6.5787312e-03 1.3233357e-03 1.1455828e-03 1.2416155e-03 1.4002549e-03 2.1211045e-03 6.2047866e-03 1.6380421e-03 2.0343353e-03 1.2366343e-03 4.6737502e-03 2.4960613e-03 1.3635919e-03 1.1869805e-03 2.7420392e-03 1.3311387e-03 5.4030547e-04 3.4496369e-03 1.8301986e-03 2.4543913e-03 1.0360218e-03 4.9823495e-03 2.4358984e-03 7.7653049e-04 6.6085729e-04 5.4666528e-03 3.6251211e-04 9.0034369e-04 2.5308489e-03 6.8325669e-04 1.3068439e-03 1.4466712e-03 7.0328570e-04 7.2909544e-04 3.3427965e-04 8.2319726e-04 3.3236658e-03 2.7101948e-04 1.1415097e-02 6.6763180e-03 5.5975222e-03 6.7637660e-03 7.8425097e-03 9.1076654e-03 7.9396677e-03 8.6849227e-03 1.0537825e-02 4.7340864e-03 1.6981356e-03 5.5204544e-03 4.0238168e-03 8.5090240e-03 9.7837063e-03 4.5130967e-03 4.3644743e-03 4.6397935e-03 1.5929686e-02 9.2384755e-03 4.4702915e-03 6.2885333e-03 1.1607431e-02 3.1082253e-03 4.1080254e-03 4.4476701e-03 2.1448891e-03 1.9903866e-03 7.7241343e-03 4.8610346e-03 7.8308568e-03 2.2349743e-03 8.1986845e-03 3.4906235e-03 1.0785042e-02 6.0455598e-03 7.1678534e-03 4.3085958e-03 1.8327850e-03 2.7372439e-03 5.8248161e-03 2.8157351e-03 6.6763180e-03 6.1912806e-03 6.1165743e-03 3.9060199e-03 5.6854050e-03 2.9112999e-03 5.9286549e-03 4.2459890e-03 4.7261943e-03 7.5564450e-03 3.0589295e-03 9.9138151e-03 2.5436162e-03 2.3081715e-03 1.8344588e-03 1.2327595e-02 2.9913447e-03 3.4407458e-03 3.5166367e-03 2.2912956e-03 2.5985157e-03 1.0536407e-03 4.0148201e-03 5.3033668e-03 3.3636231e-03 1.5135209e-03 1.3379167e-03 2.9432336e-03 8.2210569e-03 1.2378534e-02 1.1256214e-02 3.0883819e-03 6.3877121e-04 7.6741777e-03 3.3091271e-03 5.2745018e-03 5.1312091e-03 2.0746888e-03 2.6973394e-03 4.6616800e-03 6.5765736e-03 5.8096774e-03 2.9820979e-03 7.3187243e-03 4.6783172e-03 2.3410581e-02 1.3144529e-02 8.3391705e-03 1.1305315e-02 1.4457465e-02 9.3485129e-03 1.7555848e-02 7.8838497e-03 9.1347689e-03 1.4043414e-02 9.2390419e-03 8.2683227e-03 8.4558564e-03 1.4291672e-02 2.0441558e-02 1.4348706e-02 8.7091477e-03 1.1171095e-02 1.3577182e-02 6.6301175e-03 1.1191012e-02 1.5865943e-02 9.2559664e-03 5.8683930e-03 1.1694065e-02 6.7001372e-03 6.5334334e-03 8.9560518e-03 1.2574664e-02 4.2523471e-03 6.2343724e-03 6.8791672e-03 1.3649249e-02 5.2782119e-03 1.1089361e-02 6.8777652e-03 1.9771053e-02 1.0157447e-02 9.4893989e-03 7.5319640e-03 1.3411350e-02 8.8625592e-03 1.3144529e-02 1.3390278e-02 1.5951074e-02 1.0173619e-02 7.0905829e-03 8.5554531e-03 1.8741319e-02 1.2400067e-02 4.2985441e-03 2.4763265e-03 1.0193789e-03 1.4380091e-03 3.6495663e-03 1.2003820e-03 2.0584975e-03 2.4845352e-03 1.6034070e-03 3.3059261e-04 1.8671770e-03 2.0088877e-03 1.4284810e-03 4.3098388e-04 2.3514979e-04 5.2698749e-03 1.3824059e-03 2.2360501e-03 1.8501267e-03 1.6468815e-03 1.8319470e-03 2.4154150e-03 8.5423988e-04 3.3259702e-03 1.3633177e-03 3.9750527e-04 2.1357310e-04 1.4089375e-04 1.2605369e-03 2.3906980e-03 1.0696291e-04 1.0906412e-03 5.9076498e-04 1.1304618e-03 7.2732511e-03 6.4012947e-04 8.9598694e-03 3.8314732e-03 2.5915433e-03 2.9763427e-03 4.7600376e-03 4.3053173e-03 5.3266981e-03 3.6190516e-03 5.2272723e-03 3.6549051e-03 1.5047575e-03 2.5888356e-03 2.1634980e-03 5.5055672e-03 8.5050147e-03 4.0885074e-03 1.5151975e-03 1.9844585e-03 9.6042351e-03 4.2899092e-03 2.9941597e-03 4.6609860e-03 5.8520656e-03 1.4443089e-03 2.3092039e-03 1.1621771e-03 1.1296414e-03 1.1169479e-03 4.4204603e-03 1.2641450e-03 3.4620250e-03 3.4971048e-04 5.1226200e-03 6.2752047e-04 4.7853928e-03 3.3731886e-03 6.3070664e-03 1.6662334e-03 1.2828407e-03 1.6597311e-03 4.4397739e-03 3.3292201e-03 3.8314732e-03 3.8867782e-03 5.1669823e-03 3.5417199e-03 3.1734550e-03 1.6842820e-03 5.5385508e-03 2.3108610e-03 1.0105990e-03 4.7523926e-03 2.9847642e-03 9.7105522e-03 2.6675945e-03 5.8410645e-03 1.0628436e-03 8.9773521e-03 5.4199214e-03 1.6519449e-03 1.3847497e-03 4.5932482e-03 4.2245140e-03 3.0278103e-03 1.7095869e-03 2.8675709e-03 2.8000554e-03 1.2095222e-03 1.0633409e-02 6.3588443e-03 2.3146826e-03 1.8579783e-03 7.7501487e-03 1.5279559e-03 3.0361588e-03 6.2292475e-03 2.9996444e-03 2.2092276e-03 1.2670329e-03 3.0585508e-03 1.9631739e-03 1.9448597e-03 1.6026176e-03 7.3057463e-04 1.6268750e-03 1.9360609e-02 1.3271536e-02 1.1367917e-02 1.3356276e-02 1.4871782e-02 1.6028245e-02 1.4980963e-02 1.5218503e-02 1.7630002e-02 1.0242398e-02 5.4451367e-03 1.1236806e-02 9.0841292e-03 1.5577818e-02 1.6739427e-02 9.6435556e-03 9.8426714e-03 1.0341095e-02 2.4442578e-02 1.5482723e-02 9.8424496e-03 1.2530745e-02 1.8870958e-02 7.3605563e-03 9.5556413e-03 9.6316193e-03 6.0281749e-03 6.1257342e-03 1.4596779e-02 9.4938425e-03 1.3739836e-02 6.3629397e-03 1.5181016e-02 7.9755348e-03 1.8111593e-02 1.1305790e-02 1.3376686e-02 9.8378125e-03 5.8135644e-03 6.9819428e-03 1.1631750e-02 6.1445613e-03 1.3271536e-02 1.2517306e-02 1.1992997e-02 8.3045136e-03 1.0906252e-02 7.4644491e-03 1.1536762e-02 9.7524154e-03 4.5852486e-03 9.8595493e-04 5.1231602e-03 5.3641159e-04 6.1291344e-03 9.0289414e-06 4.9719488e-03 2.7623691e-03 1.0135570e-04 4.9630072e-05 1.4573369e-03 2.2050307e-03 1.9067713e-03 6.5935996e-04 5.5655703e-04 4.9349156e-04 5.3910141e-05 7.6334144e-03 6.4541501e-03 3.6168243e-03 4.5600228e-04 3.3337204e-03 1.8551457e-03 1.2329546e-03 3.8576017e-03 1.8263928e-03 3.4082293e-04 2.8939589e-05 1.6992773e-03 1.7320592e-03 1.4340517e-03 2.7567571e-04 1.5103910e-03 8.5202938e-04 1.8535044e-02 1.1041503e-02 8.1659733e-03 1.0422568e-02 1.2515324e-02 1.1445689e-02 1.3674148e-02 1.0415137e-02 1.2394915e-02 9.4870366e-03 4.7984401e-03 8.0611256e-03 6.7876377e-03 1.2924053e-02 1.5886474e-02 9.2445598e-03 7.3109344e-03 8.4847047e-03 1.8293716e-02 1.0175519e-02 8.2306422e-03 1.1561315e-02 1.3225081e-02 4.8091709e-03 8.1976852e-03 6.4746796e-03 4.2076714e-03 5.1007444e-03 1.1683626e-02 5.5527590e-03 8.9342726e-03 4.4973686e-03 1.2442734e-02 4.9468838e-03 1.3343592e-02 7.6599210e-03 1.3497447e-02 7.8132331e-03 5.1004820e-03 5.1592495e-03 1.0155636e-02 5.1788357e-03 1.1041503e-02 1.0666367e-02 1.1283660e-02 6.9627068e-03 7.4793969e-03 5.8082013e-03 1.1981463e-02 8.5614846e-03 3.8688652e-03 7.5179133e-03 3.7407669e-03 3.1676786e-04 4.6173801e-03 4.2799166e-03 2.2501511e-03 4.2413983e-03 4.2204030e-03 4.6109813e-03 1.7937707e-03 8.2328963e-04 8.3021324e-03 4.1326900e-03 5.3767829e-03 3.8579826e-03 2.3734756e-03 1.6523409e-04 8.8835369e-04 2.5288831e-03 7.6911436e-03 1.1035999e-03 1.9572002e-03 1.3626197e-03 8.4501724e-04 3.6117590e-03 4.7013989e-03 1.0056440e-03 1.3674472e-03 9.9055737e-04 2.9505217e-03 8.8795046e-03 1.5067108e-03 6.0099517e-03 3.2148697e-03 3.5475051e-03 3.0620571e-03 4.0315627e-03 6.0415844e-03 3.4044063e-03 5.7826017e-03 7.5784861e-03 2.1065729e-03 8.8233953e-04 3.5528527e-03 2.5792431e-03 5.1245213e-03 6.2842876e-03 2.4095844e-03 1.8446522e-03 1.4167723e-03 1.2151930e-02 7.2262167e-03 2.4839286e-03 2.9019075e-03 8.5383029e-03 2.6181282e-03 1.4064800e-03 2.3288946e-03 1.7187301e-03 6.4203056e-04 4.4078979e-03 3.6116427e-03 6.0606537e-03 7.3312980e-04 4.8772717e-03 2.0701887e-03 6.3495233e-03 5.1782781e-03 3.3738477e-03 1.3922890e-03 5.6378115e-04 2.0528392e-03 3.5526857e-03 3.4142665e-03 3.2148697e-03 3.0384066e-03 3.3899600e-03 3.3852248e-03 4.7610217e-03 1.6939002e-03 2.6027995e-03 1.1563987e-03 4.9937739e-03 2.8043563e-04 6.0192505e-03 1.1047123e-03 3.7340869e-03 9.3891763e-04 5.7693223e-04 8.5742923e-04 1.1063653e-03 2.1518410e-03 1.7873418e-03 1.8443813e-03 4.7874237e-04 4.0562362e-04 6.3806313e-04 5.6896950e-03 5.3990383e-03 4.0838955e-03 7.6270784e-04 3.0255235e-03 1.8702287e-03 1.2256654e-03 1.9416278e-03 1.1863062e-03 4.8488269e-04 7.2384993e-04 1.1782779e-03 1.1397261e-03 1.1824844e-03 4.5012569e-04 4.3416102e-03 9.3532010e-04 1.7514227e-02 9.8600607e-03 7.1630436e-03 8.1480968e-03 1.1292909e-02 9.1710206e-03 1.2255610e-02 7.6051240e-03 9.9403988e-03 9.4620221e-03 5.2227781e-03 7.1398046e-03 6.5861173e-03 1.2201906e-02 1.6541006e-02 9.8696183e-03 5.7022093e-03 6.6806000e-03 1.5779735e-02 7.9447125e-03 8.2548534e-03 1.1179561e-02 1.0455124e-02 4.7301378e-03 7.3678164e-03 4.4876356e-03 4.3705173e-03 4.8557182e-03 1.0520487e-02 3.4331839e-03 7.0769130e-03 3.1675776e-03 1.1611243e-02 3.1862426e-03 9.1961094e-03 7.4495828e-03 1.3429738e-02 6.1002834e-03 5.0525215e-03 5.4421147e-03 1.0502545e-02 7.0546448e-03 9.8600607e-03 9.9581080e-03 1.1708746e-02 8.2306703e-03 7.3218404e-03 5.8241089e-03 1.2089443e-02 7.3253099e-03 3.2913459e-03 8.4499731e-03 4.8569537e-03 8.0216351e-04 3.5049401e-03 4.1209949e-03 4.1951632e-03 1.4430192e-03 2.1132422e-03 3.9581533e-03 7.7606295e-03 2.8139659e-03 3.8070595e-03 4.7702994e-03 3.8227367e-03 9.3108167e-03 1.0381275e-02 3.5346820e-03 5.2926972e-04 8.0977990e-03 2.5864687e-03 3.9952884e-03 4.6152713e-03 3.2808967e-03 5.0209478e-03 3.9992007e-03 7.6245140e-03 5.9395645e-03 4.2477403e-03 1.1072543e-02 4.9514063e-03 1.3733574e-02 6.2131974e-03 2.8230097e-03 5.6455623e-03 6.8638978e-03 3.4892544e-03 9.9148605e-03 3.2690483e-03 3.3086076e-03 7.4423917e-03 5.1197423e-03 2.7541244e-03 3.1219477e-03 6.1841097e-03 1.0726676e-02 7.6421585e-03 4.1594455e-03 6.2994749e-03 5.6115691e-03 2.0176931e-03 4.9542156e-03 8.4395555e-03 3.5502322e-03 1.8230265e-03 6.1478670e-03 3.1652703e-03 2.7049802e-03 4.9489115e-03 5.3042297e-03 1.9463142e-03 1.6986432e-03 4.1722516e-03 5.8173968e-03 2.6602408e-03 6.4952123e-03 1.5042394e-03 1.1842312e-02 5.5188608e-03 5.4735640e-03 2.9735027e-03 6.0829501e-03 4.0306925e-03 6.2131974e-03 6.3472325e-03 8.2596987e-03 4.2451973e-03 1.6828229e-03 3.7151898e-03 1.1574575e-02 7.1331719e-03 5.4811265e-03 5.5565221e-04 2.6852359e-03 1.0154324e-03 1.7597013e-04 3.1956114e-04 3.9523878e-04 1.2388706e-03 1.2655903e-03 1.6805675e-03 3.2406061e-05 1.6284558e-04 3.0055489e-04 4.9827743e-03 5.3992645e-03 4.0722394e-03 2.5388663e-04 1.8315484e-03 2.0093416e-03 5.5333384e-04 1.9333559e-03 1.0417210e-03 4.5631651e-05 3.9213732e-04 8.9628584e-04 1.5141190e-03 1.1540120e-03 1.6596111e-04 3.8108192e-03 6.9068728e-04 1.6110144e-02 8.5829426e-03 5.7514563e-03 7.4081873e-03 9.8865471e-03 7.9109476e-03 1.1246146e-02 6.7496818e-03 8.5805974e-03 8.1149529e-03 4.1088457e-03 5.6967153e-03 5.0837880e-03 1.0378372e-02 1.4309813e-02 8.2945922e-03 4.9454249e-03 6.1635386e-03 1.3817928e-02 6.6600542e-03 6.6926476e-03 9.8029996e-03 9.1474450e-03 3.3107453e-03 6.4113962e-03 3.9012077e-03 3.0861181e-03 3.9737498e-03 8.9756426e-03 2.8871345e-03 5.7720900e-03 2.7832463e-03 9.8623531e-03 2.6826772e-03 9.0033513e-03 5.5466456e-03 1.2137789e-02 5.5287165e-03 4.1655510e-03 3.9755943e-03 8.6395601e-03 5.0222445e-03 8.5829426e-03 8.5444862e-03 9.9728516e-03 6.1969528e-03 5.4521508e-03 4.4886104e-03 1.0936532e-02 6.6624227e-03 6.0879321e-03 5.2071133e-03 3.8816096e-03 5.8831678e-03 5.7002681e-03 6.1926865e-03 2.4416494e-03 1.5149583e-03 1.0539677e-02 5.8224280e-03 7.4292172e-03 5.4190952e-03 2.7168224e-03 2.8895677e-04 1.2473682e-03 3.7477469e-03 9.3088565e-03 2.0944009e-03 2.9293124e-03 2.5720420e-03 1.8897161e-03 5.1660356e-03 6.4102501e-03 2.0138936e-03 2.7413840e-03 2.0664916e-03 4.4338085e-03 1.0353410e-02 2.6118482e-03 4.2150650e-03 2.5222817e-03 3.4164904e-03 3.0582580e-03 3.1593359e-03 6.2318287e-03 2.3862805e-03 6.4839490e-03 7.9101598e-03 1.0920878e-03 5.4699759e-04 3.4046237e-03 2.2291279e-03 4.0543858e-03 4.2004727e-03 1.1970351e-03 2.0117915e-03 1.4112028e-03 1.1968526e-02 7.9088029e-03 1.7082776e-03 1.7239090e-03 9.0238817e-03 2.6874577e-03 9.4975956e-04 2.9722514e-03 1.7009640e-03 5.1343341e-04 3.7130353e-03 4.7806054e-03 6.6267337e-03 1.3220831e-03 3.9245747e-03 2.9403206e-03 7.2757164e-03 5.0266602e-03 1.8157078e-03 1.4701768e-03 3.5054511e-04 1.7883207e-03 2.3616946e-03 2.6617941e-03 2.5222817e-03 2.1723972e-03 1.9530095e-03 2.4533627e-03 4.5559375e-03 1.3609168e-03 1.2016297e-03 8.2861882e-04 4.8139327e-03 2.8209366e-03 1.1052349e-04 3.7194090e-05 1.3880093e-03 2.0960687e-03 1.8746430e-03 7.3307377e-04 5.4600497e-04 5.2531656e-04 7.7399437e-05 7.5260309e-03 6.5039124e-03 3.6958100e-03 4.3794778e-04 3.1691974e-03 1.9589162e-03 1.1747018e-03 3.8950000e-03 1.8610625e-03 3.3531102e-04 5.6607375e-05 1.7087501e-03 1.8728452e-03 1.4997100e-03 3.0123700e-04 1.5391826e-03 8.8147902e-04 1.8294246e-02 1.0829571e-02 7.9341800e-03 1.0299926e-02 1.2275737e-02 1.1220530e-02 1.3508784e-02 1.0262914e-02 1.2147087e-02 9.2823036e-03 4.6531594e-03 7.8245831e-03 6.5524640e-03 1.2610156e-02 1.5512672e-02 9.0061844e-03 7.1992659e-03 8.4158356e-03 1.7921554e-02 9.9492079e-03 7.9854978e-03 1.1342596e-02 1.2982212e-02 4.5954373e-03 8.0580657e-03 6.3922041e-03 4.0251341e-03 4.9895677e-03 1.1418706e-02 5.4787432e-03 8.7107499e-03 4.4679304e-03 1.2142235e-02 4.8867636e-03 1.3297934e-02 7.3458933e-03 1.3299484e-02 7.7358341e-03 4.9917221e-03 4.9413674e-03 9.8545070e-03 4.8770063e-03 1.0829571e-02 1.0435652e-02 1.1007902e-02 6.6474718e-03 7.1727397e-03 5.6106947e-03 1.1815640e-02 8.4729744e-03 1.5166983e-03 3.8470717e-03 4.0414722e-03 1.3464004e-03 1.0521554e-03 2.2256122e-03 8.2355212e-03 2.4972654e-03 3.6758320e-03 4.2952040e-03 1.2466978e-03 5.4237685e-03 7.4233145e-03 2.7434894e-03 1.3920410e-03 5.6705580e-03 1.6006987e-03 1.4795623e-03 2.5504964e-03 2.8217649e-03 4.8039535e-03 2.1716992e-03 5.1387834e-03 3.8511647e-03 3.4066344e-03 1.1638730e-02 3.4223746e-03 9.4998939e-03 3.3659956e-03 1.1438717e-03 2.4828929e-03 3.9653407e-03 1.5796312e-03 5.9993003e-03 1.2126234e-03 1.7377370e-03 4.6402796e-03 3.0884931e-03 1.1351744e-03 1.5562166e-03 3.9244608e-03 8.1556610e-03 5.1855221e-03 1.5226783e-03 2.8914073e-03 4.3431210e-03 9.2550137e-04 2.9272754e-03 5.3162687e-03 2.0104865e-03 7.9177243e-04 3.1975522e-03 8.1317449e-04 1.3785091e-03 2.5714969e-03 2.9511423e-03 2.8161529e-04 5.9442405e-04 1.5991249e-03 3.5615321e-03 5.8433150e-04 3.1011353e-03 9.7656296e-04 8.0983113e-03 2.3700003e-03 3.0461348e-03 1.6450583e-03 4.0872867e-03 3.5603497e-03 3.3659956e-03 3.6518311e-03 5.6844228e-03 3.2852236e-03 1.0303385e-03 1.9470044e-03 7.8778855e-03 3.7000111e-03 1.9300708e-03 2.2574717e-03 1.1284358e-03 1.0646979e-03 1.0312076e-03 5.0621817e-03 1.2060164e-03 1.8000639e-03 2.0650564e-03 2.1487796e-03 3.2333878e-03 4.0195479e-03 1.2411974e-03 2.7183002e-03 2.2726383e-03 8.5094120e-04 2.4056963e-04 6.3782113e-04 1.2937611e-03 2.4889893e-03 5.9722053e-04 1.5621785e-03 1.2375553e-03 1.3358412e-03 8.1240216e-03 1.2311022e-03 1.1517636e-02 5.2909227e-03 3.4509195e-03 3.7153220e-03 6.3154320e-03 4.5407961e-03 7.2027738e-03 3.4054800e-03 5.2043334e-03 5.7490488e-03 3.1731637e-03 3.4719309e-03 3.4347027e-03 7.1701181e-03 1.1379612e-02 6.4467389e-03 2.2692649e-03 2.9960956e-03 9.7363741e-03 4.0178908e-03 4.7338729e-03 6.7982603e-03 5.6061060e-03 2.3699712e-03 3.8192855e-03 1.4133848e-03 2.2956056e-03 2.5088406e-03 5.7314562e-03 9.5862581e-04 3.4107092e-03 9.7091810e-04 6.6778472e-03 7.6184177e-04 4.3247639e-03 4.2032521e-03 8.9746527e-03 2.5881501e-03 2.8171688e-03 3.0086239e-03 6.5256052e-03 5.3225794e-03 5.2909227e-03 5.5860698e-03 7.6013097e-03 5.5376614e-03 4.0938335e-03 3.1000848e-03 8.1789436e-03 3.7376243e-03 3.2267663e-05 8.3707549e-04 1.6905622e-03 1.5718936e-03 9.3681209e-04 1.8762095e-04 1.9684682e-04 4.1277465e-05 6.4440482e-03 6.0518000e-03 3.8422414e-03 2.6274935e-04 2.4665214e-03 1.9088192e-03 8.3864343e-04 2.9786928e-03 1.4388393e-03 8.3975474e-05 5.3416679e-05 1.2919166e-03 1.6159093e-03 1.2740163e-03 1.2266042e-04 2.3692761e-03 7.1636545e-04 1.7563748e-02 9.9676420e-03 7.0439691e-03 9.1049407e-03 1.1370346e-02 9.8276989e-03 1.2673450e-02 8.7383729e-03 1.0632094e-02 8.9036592e-03 4.4721835e-03 6.9588127e-03 5.9822651e-03 1.1786793e-02 1.5215597e-02 8.8361414e-03 6.2553172e-03 7.4909328e-03 1.6226352e-02 8.5173085e-03 7.5296182e-03 1.0823312e-02 1.1340207e-02 4.0626163e-03 7.4274805e-03 5.3041231e-03 3.6467217e-03 4.5925766e-03 1.0472609e-02 4.2980846e-03 7.4369871e-03 3.7248522e-03 1.1287932e-02 3.8978058e-03 1.1428778e-02 6.6149115e-03 1.2975959e-02 6.8214468e-03 4.6824073e-03 4.5741646e-03 9.4691004e-03 5.0187206e-03 9.9676420e-03 9.7385546e-03 1.0722589e-02 6.5565379e-03 6.4801586e-03 5.1854796e-03 1.1596572e-02 7.7633670e-03 9.9158601e-04 1.6686143e-03 1.5457871e-03 9.5071878e-04 3.0701864e-04 3.6362811e-04 4.2548991e-05 6.6288818e-03 6.0417331e-03 3.6564704e-03 2.5834714e-04 2.6458983e-03 1.8764428e-03 8.4820574e-04 3.2578450e-03 1.5209238e-03 1.5090465e-04 6.1935165e-05 1.3587649e-03 1.7158299e-03 1.3006818e-03 1.6628415e-04 2.0535582e-03 7.1188329e-04 1.7324639e-02 9.9147481e-03 7.0600417e-03 9.2840701e-03 1.1302120e-02 1.0064078e-02 1.2589616e-02 9.1080261e-03 1.0920912e-02 8.6425556e-03 4.2412792e-03 6.9624194e-03 5.8567924e-03 1.1639501e-02 1.4739829e-02 8.4651679e-03 6.3684651e-03 7.5923014e-03 1.6475338e-02 8.8252851e-03 7.3097093e-03 1.0588424e-02 1.1694482e-02 3.9807447e-03 7.3452100e-03 5.5353092e-03 3.5104587e-03 4.4753907e-03 1.0430724e-02 4.6273816e-03 7.6755144e-03 3.8450588e-03 1.1170257e-02 4.1281664e-03 1.1986478e-02 6.5423939e-03 1.2634016e-02 6.9257811e-03 4.5247923e-03 4.3922796e-03 9.1553155e-03 4.5676871e-03 9.9147481e-03 9.5995789e-03 1.0353234e-02 6.1627903e-03 6.3902007e-03 5.0235520e-03 1.1247115e-02 7.7428181e-03 9.7824889e-04 1.6624661e-03 3.0059873e-03 2.5249972e-04 6.2343657e-04 1.1719366e-03 4.0275459e-03 6.3575546e-03 5.8712921e-03 7.5872446e-04 5.6741436e-04 3.5908637e-03 6.4996051e-04 1.9776689e-03 1.6840088e-03 4.6219818e-04 1.2917587e-03 1.3743184e-03 3.0187893e-03 2.2373182e-03 9.0828703e-04 5.7426890e-03 1.5775049e-03 1.5168309e-02 7.4080646e-03 4.2538993e-03 6.3033105e-03 8.5100385e-03 5.7899432e-03 1.0520014e-02 4.8624768e-03 6.1169570e-03 7.6384090e-03 4.1091153e-03 4.1981402e-03 3.9923041e-03 8.6172736e-03 1.2997087e-02 7.8717119e-03 4.1667776e-03 5.7584992e-03 1.0387455e-02 4.3546484e-03 5.7746712e-03 9.1054055e-03 6.5301937e-03 2.3054088e-03 5.9614728e-03 3.0379183e-03 2.5067124e-03 3.9126904e-03 7.3239330e-03 1.8370981e-03 3.7021481e-03 2.7152943e-03 8.1304066e-03 2.0347479e-03 7.4172182e-03 3.6502880e-03 1.1915038e-02 5.0530642e-03 4.2458688e-03 3.2213237e-03 7.5116191e-03 4.3860606e-03 7.4080646e-03 7.4726409e-03 9.2071058e-03 5.2421868e-03 3.6675370e-03 3.8308993e-03 1.1024145e-02 6.4520833e-03 3.0133930e-04 5.1037905e-03 1.2017859e-03 2.1951761e-03 1.7686888e-03 1.8224411e-03 2.8788865e-03 3.1740291e-03 7.0420689e-04 2.2350252e-03 2.1605967e-03 1.6074282e-04 9.9312132e-04 6.3910600e-04 1.1068342e-03 2.2522084e-03 4.2563220e-04 2.1383582e-03 1.1781524e-03 1.1965920e-03 6.6826197e-03 8.9701315e-04 8.8374021e-03 3.5249181e-03 1.9006375e-03 3.2674819e-03 4.3522253e-03 3.8602822e-03 5.5032387e-03 3.5903574e-03 4.6280025e-03 3.2207897e-03 1.0860964e-03 1.8528751e-03 1.3287556e-03 4.5637650e-03 7.2040689e-03 3.3452381e-03 1.6438459e-03 2.5042800e-03 8.4078534e-03 3.6412189e-03 2.1968551e-03 4.2884610e-03 5.3072049e-03 5.5962180e-04 2.2924485e-03 1.3972917e-03 4.1775124e-04 1.0120628e-03 3.7672964e-03 1.3901921e-03 2.7802443e-03 7.8074497e-04 4.2513803e-03 8.6439557e-04 5.7017672e-03 1.9558095e-03 6.1305769e-03 2.0764524e-03 1.1750038e-03 7.8121442e-04 3.3536027e-03 1.6840705e-03 3.5249181e-03 3.4031938e-03 4.3169071e-03 2.0323666e-03 1.8104373e-03 1.0313169e-03 5.4663596e-03 2.6797009e-03 4.7017751e-03 1.4050521e-03 2.2967640e-03 1.4490557e-03 2.3196093e-03 1.7015479e-03 1.5767700e-03 5.5713099e-04 3.7392678e-03 8.9324098e-04 2.5002761e-04 8.6482380e-04 1.3585049e-04 1.1239692e-03 1.9761479e-03 8.2927740e-05 9.6014531e-04 3.4965263e-04 8.9552257e-04 5.7645956e-03 3.1975366e-04 8.7743211e-03 4.0156462e-03 2.9085611e-03 3.7265804e-03 4.9611690e-03 5.3200137e-03 5.4291747e-03 4.9090444e-03 6.4181467e-03 3.1699225e-03 9.0457257e-04 2.8707306e-03 2.0343345e-03 5.5511033e-03 7.6886258e-03 3.2962764e-03 1.9800100e-03 2.4033904e-03 1.0905558e-02 5.4434884e-03 2.6411651e-03 4.3219947e-03 7.2333465e-03 1.3483652e-03 2.2580657e-03 1.9023537e-03 8.2889320e-04 8.3511491e-04 4.6996589e-03 2.2192064e-03 4.3941392e-03 6.5409726e-04 5.2313685e-03 1.2879740e-03 6.5768476e-03 3.4674432e-03 5.6567012e-03 2.0849532e-03 8.7522015e-04 1.2925162e-03 3.9107304e-03 2.2116014e-03 4.0156462e-03 3.8265815e-03 4.4724719e-03 2.6832503e-03 3.2108081e-03 1.3825243e-03 4.7909587e-03 2.3944351e-03 1.6956470e-03 1.0108236e-03 9.3414345e-04 1.2241588e-02 1.0680036e-02 6.4457112e-03 2.1113831e-03 4.8851719e-03 3.9417362e-03 3.5304281e-03 6.9169294e-03 4.3255103e-03 1.5489174e-03 5.9380000e-04 4.2050996e-03 3.5612837e-03 3.5981180e-03 1.5473563e-03 1.0469113e-03 2.7881158e-03 2.6084642e-02 1.6915515e-02 1.3046936e-02 1.5813114e-02 1.8728660e-02 1.6622622e-02 2.0172358e-02 1.5047933e-02 1.7480656e-02 1.5121187e-02 8.9988271e-03 1.2921567e-02 1.1505555e-02 1.9202447e-02 2.2948431e-02 1.4807179e-02 1.1989561e-02 1.3522703e-02 2.4353472e-02 1.4534512e-02 1.3492376e-02 1.7699736e-02 1.8260951e-02 8.7551977e-03 1.3397972e-02 1.0605977e-02 8.1065177e-03 9.3705995e-03 1.7600384e-02 8.9170386e-03 1.3238432e-02 8.2394556e-03 1.8591466e-02 8.5466794e-03 1.8371580e-02 1.2139358e-02 2.0015536e-02 1.2667833e-02 9.3753580e-03 9.4099897e-03 1.5925767e-02 9.2577085e-03 1.6915515e-02 1.6530549e-02 1.7369847e-02 1.1736690e-02 1.2003814e-02 1.0321540e-02 1.8104120e-02 1.3766972e-02 1.5141485e-04 3.6186411e-04 5.0640473e-03 5.8846843e-03 4.5372473e-03 2.9889995e-04 1.4503455e-03 2.4048820e-03 5.6473356e-04 2.1694139e-03 1.2760726e-03 5.0001009e-05 4.2762331e-04 1.0752642e-03 1.9285330e-03 1.4459840e-03 2.6007132e-04 3.8461838e-03 8.8079628e-04 1.6321310e-02 8.6239000e-03 5.6156570e-03 7.5378743e-03 9.9017513e-03 7.7506746e-03 1.1476827e-02 6.6644304e-03 8.3385285e-03 8.2160708e-03 4.1911289e-03 5.5513041e-03 4.9688023e-03 1.0246372e-02 1.4224144e-02 8.3426053e-03 5.0473242e-03 6.4114140e-03 1.3391748e-02 6.3862951e-03 6.6425216e-03 9.9154668e-03 8.8906649e-03 3.1510729e-03 6.5653256e-03 3.9767727e-03 3.0148559e-03 4.1087786e-03 8.8891438e-03 2.8692574e-03 5.5219515e-03 2.9822205e-03 9.7392578e-03 2.7559926e-03 9.1569917e-03 5.1978118e-03 1.2376315e-02 5.7353587e-03 4.3202502e-03 3.8711781e-03 8.5388416e-03 4.7844327e-03 8.6239000e-03 8.5671038e-03 9.9856257e-03 5.9819812e-03 5.1316831e-03 4.4550423e-03 1.1213210e-02 6.9205612e-03 3.8131057e-04 6.7888158e-03 7.3363003e-03 5.3694436e-03 6.8516623e-04 1.8924051e-03 2.8895525e-03 1.2584203e-03 3.1106561e-03 1.9851820e-03 2.2993360e-04 3.0705767e-04 1.8065799e-03 2.2681792e-03 1.9895114e-03 4.4561501e-04 3.2950230e-03 1.3536253e-03 1.9442033e-02 1.0986408e-02 7.5586116e-03 9.6139706e-03 1.2432885e-02 9.8077912e-03 1.4077548e-02 8.4254038e-03 1.0370813e-02 1.0478515e-02 5.7856689e-03 7.4894276e-03 6.8497491e-03 1.2864462e-02 1.7242156e-02 1.0603978e-02 6.8089917e-03 8.2980029e-03 1.5941696e-02 8.0862824e-03 8.7712331e-03 1.2406133e-02 1.0894930e-02 4.6791769e-03 8.5829625e-03 5.4740472e-03 4.5017704e-03 5.7029968e-03 1.1309070e-02 4.0232333e-03 7.1989285e-03 4.2761837e-03 1.2289743e-02 4.0060693e-03 1.1002553e-02 7.0316526e-03 1.5021687e-02 7.5484658e-03 5.9167328e-03 5.5390768e-03 1.0934157e-02 6.4525090e-03 1.0986408e-02 1.0943118e-02 1.2502015e-02 7.9589531e-03 6.9802991e-03 6.2208864e-03 1.3663387e-02 8.8999016e-03 6.6062542e-03 5.5827314e-03 3.2137911e-03 2.4648342e-04 3.0882054e-03 1.4855278e-03 8.8238305e-04 3.0312113e-03 1.3048774e-03 1.7074342e-04 4.2409993e-05 1.2055084e-03 1.2882692e-03 1.0204762e-03 8.9780466e-05 2.0467514e-03 5.4370125e-04 1.7241595e-02 9.9776023e-03 7.2970604e-03 9.2205394e-03 1.1400153e-02 1.0313298e-02 1.2454804e-02 9.2538420e-03 1.1254653e-02 8.6534668e-03 4.2479840e-03 7.2108683e-03 6.0807502e-03 1.1908599e-02 1.4998922e-02 8.5435101e-03 6.3304436e-03 7.3992448e-03 1.7031719e-02 9.1810782e-03 7.4786833e-03 1.0592315e-02 1.2037933e-02 4.2382770e-03 7.2750145e-03 5.5074473e-03 3.6741461e-03 4.4146887e-03 1.0634443e-02 4.6823366e-03 8.0104480e-03 3.6842552e-03 1.1424845e-02 4.0945647e-03 1.1857190e-02 7.0169427e-03 1.2513676e-02 6.7752703e-03 4.4459599e-03 4.6022279e-03 9.3965771e-03 4.9465269e-03 9.9776023e-03 9.6902181e-03 1.0478640e-02 6.5221232e-03 6.8355801e-03 5.1573625e-03 1.1079009e-02 7.5518079e-03 2.6192775e-03 5.9216859e-03 4.3727502e-03 5.1296754e-03 5.3199310e-03 2.7670517e-03 1.1371035e-03 2.6020928e-03 5.1188394e-03 7.5382072e-03 2.4476107e-03 5.0616317e-03 3.9293810e-03 5.2302586e-03 1.5095801e-02 4.1435464e-03 4.4658108e-03 8.7058429e-04 4.4660793e-04 2.5555941e-04 1.2381894e-03 8.7244097e-04 2.0362511e-03 8.1311609e-04 1.5164656e-03 1.9481959e-03 1.9017569e-03 4.9004150e-04 8.1438359e-04 1.7141435e-03 4.7093504e-03 2.7065864e-03 6.0393489e-05 4.2915211e-04 3.9373776e-03 1.5669301e-03 1.2950596e-03 2.1025536e-03 1.9522193e-03 1.0322026e-03 8.4218839e-04 9.2905490e-05 1.2346326e-03 1.1781032e-03 9.8002670e-04 7.9339756e-04 1.1328834e-03 6.2948320e-04 1.4629322e-03 3.9084846e-04 1.4164544e-03 1.5298834e-03 3.8721999e-03 2.7001180e-04 1.5287601e-03 1.2669024e-03 2.1037534e-03 3.7134859e-03 8.7058429e-04 1.1775044e-03 2.8495857e-03 2.7086756e-03 1.4023687e-03 1.0191451e-03 3.8647977e-03 9.3179883e-04 1.2988786e-03 3.9786961e-03 9.7659791e-03 1.8948352e-03 3.2059058e-03 1.9902291e-03 1.7004118e-03 5.2879179e-03 6.5830280e-03 1.9368261e-03 2.2268965e-03 1.8962421e-03 4.4774419e-03 1.1162650e-02 2.6447647e-03 4.9365528e-03 3.0323131e-03 3.9972109e-03 2.9343480e-03 3.7523678e-03 6.3980393e-03 2.7120874e-03 6.2404178e-03 8.0807935e-03 1.9416596e-03 1.3024398e-03 4.0245181e-03 3.0697725e-03 5.0283287e-03 5.8270256e-03 2.3505477e-03 2.0375391e-03 1.2652208e-03 1.2527532e-02 8.0556250e-03 2.6750700e-03 2.5225228e-03 9.0764566e-03 3.4699713e-03 1.3308823e-03 2.7664696e-03 2.4678015e-03 9.5729618e-04 4.3858320e-03 4.4729680e-03 6.8828714e-03 1.1547480e-03 4.8183810e-03 2.7179325e-03 6.3087897e-03 6.0843336e-03 2.6715726e-03 1.3701564e-03 8.5085504e-04 2.7129190e-03 3.6187454e-03 4.3357364e-03 3.0323131e-03 2.8888833e-03 3.1752051e-03 4.0026050e-03 5.6110347e-03 2.1520192e-03 2.0021167e-03 9.3001678e-04 2.6139835e-03 9.7625461e-03 4.3820793e-04 2.7906691e-03 3.4740135e-03 1.5471352e-03 3.7324822e-03 3.8774805e-03 1.8049144e-03 1.0166909e-03 9.6586952e-04 2.7620874e-03 5.6379477e-03 1.4267399e-03 9.9420936e-03 6.9534902e-03 7.2046628e-03 7.1611325e-03 8.0864542e-03 1.1050679e-02 7.0236664e-03 1.0684883e-02 1.2982713e-02 4.4982901e-03 2.1523458e-03 7.1621069e-03 5.3786825e-03 9.3055499e-03 9.5487861e-03 4.3879387e-03 5.0693092e-03 4.4931267e-03 1.8805226e-02 1.2143973e-02 5.1616364e-03 5.8432704e-03 1.4239876e-02 5.0396297e-03 4.0643450e-03 5.6688069e-03 3.5911389e-03 2.3422208e-03 8.6067938e-03 6.9700590e-03 1.0540875e-02 2.8498735e-03 9.0488233e-03 4.9258801e-03 1.1781603e-02 8.6822745e-03 5.8089260e-03 4.4337196e-03 2.0267056e-03 4.1354243e-03 6.4148025e-03 4.4976834e-03 6.9534902e-03 6.4275292e-03 5.9584428e-03 5.3006657e-03 8.1437729e-03 3.9023880e-03 4.5299634e-03 3.7988456e-03 2.5123066e-03 1.1946309e-03 2.0097566e-04 1.7928786e-03 5.7143349e-04 1.2667176e-04 4.6644872e-04 4.4712161e-04 1.0683378e-03 5.7468992e-04 7.6554900e-05 3.3664265e-03 2.0582490e-04 1.3553574e-02 7.1051776e-03 4.8941009e-03 6.5257957e-03 8.3098959e-03 7.5373275e-03 9.3233389e-03 6.7621473e-03 8.4467156e-03 6.1291129e-03 2.5944515e-03 4.8248569e-03 3.9028342e-03 8.7515124e-03 1.1627531e-02 6.1178515e-03 4.1203288e-03 5.0572182e-03 1.3529172e-02 6.7984240e-03 5.0687125e-03 7.7357162e-03 9.2015610e-03 2.4873418e-03 4.9175701e-03 3.5355888e-03 2.0473249e-03 2.6605314e-03 7.6511613e-03 3.0628424e-03 5.7307078e-03 2.1169019e-03 8.3320524e-03 2.4574218e-03 9.1102030e-03 4.8098810e-03 9.5736130e-03 4.5225384e-03 2.7314130e-03 2.7690856e-03 6.7080946e-03 3.3506310e-03 7.1051776e-03 6.8798895e-03 7.7001955e-03 4.4569824e-03 4.6305164e-03 3.1848752e-03 8.4170139e-03 5.2045050e-03 6.9296246e-03 2.1360002e-03 3.7784686e-03 3.9888330e-03 1.9332806e-03 3.1165972e-03 3.4622240e-03 6.1843155e-03 4.9689115e-03 2.8276933e-03 8.4143362e-03 3.9488633e-03 1.7390613e-02 8.6823566e-03 4.7125346e-03 7.5297389e-03 9.6551734e-03 5.6073015e-03 1.2632980e-02 4.7967985e-03 5.4595549e-03 9.6779905e-03 6.1919843e-03 4.6437798e-03 4.8811137e-03 9.2634464e-03 1.4470481e-02 9.9239882e-03 5.5116951e-03 7.7393895e-03 8.8498403e-03 3.6104684e-03 7.0913900e-03 1.1068993e-02 5.6668826e-03 3.0002631e-03 7.9032607e-03 4.0760726e-03 3.7279027e-03 5.9729084e-03 7.9919733e-03 2.3383845e-03 3.2272638e-03 4.6096764e-03 8.7690968e-03 3.1364844e-03 7.9578373e-03 3.3962632e-03 1.4631125e-02 6.8663759e-03 6.4834920e-03 4.3461235e-03 8.7377082e-03 5.5255283e-03 8.6823566e-03 8.8561968e-03 1.1024987e-02 6.2645608e-03 3.5745084e-03 5.1960404e-03 1.3983177e-02 8.7265781e-03 1.5360474e-03 2.2738132e-03 6.3957013e-04 1.8470485e-03 1.9436948e-03 8.2753134e-04 1.4870044e-04 1.8575051e-04 1.1511457e-03 4.1570185e-03 4.2481246e-04 1.2022631e-02 7.4558885e-03 6.7319225e-03 7.0097246e-03 8.7236579e-03 1.0059866e-02 8.2686681e-03 9.2543911e-03 1.1644804e-02 5.5866311e-03 2.5062451e-03 6.6946690e-03 5.2622870e-03 9.8836223e-03 1.1452219e-02 5.6355000e-03 4.7339621e-03 4.6436729e-03 1.7620106e-02 1.0378141e-02 5.6675320e-03 7.1003305e-03 1.2674455e-02 4.3836233e-03 4.5891805e-03 4.7259960e-03 3.2437023e-03 2.5249532e-03 8.8366518e-03 5.2434703e-03 8.9867759e-03 2.2946416e-03 9.5089828e-03 3.7537168e-03 1.0503141e-02 7.8427036e-03 7.7804598e-03 4.4127994e-03 2.3620086e-03 3.9941388e-03 7.2903223e-03 4.7424240e-03 7.4558885e-03 7.1215300e-03 7.3539364e-03 5.7328206e-03 7.4284923e-03 3.9643246e-03 6.4306545e-03 4.3729078e-03 1.0852360e-03 3.9664584e-04 4.5123208e-04 1.2414442e-03 2.3150826e-04 1.4183402e-03 7.0426023e-04 4.8163546e-04 5.0741189e-03 3.9595383e-04 1.0937070e-02 5.0339955e-03 3.1168119e-03 4.5426488e-03 6.0432452e-03 5.3182662e-03 7.1300333e-03 4.7641753e-03 6.1358685e-03 4.4885462e-03 1.6916118e-03 3.0636842e-03 2.3987749e-03 6.3937387e-03 9.2584560e-03 4.5899059e-03 2.5786937e-03 3.4750392e-03 1.0541835e-02 4.8350707e-03 3.4370915e-03 5.7977832e-03 6.8277961e-03 1.3144796e-03 3.3638906e-03 2.1338739e-03 1.0504939e-03 1.6413828e-03 5.4173620e-03 1.8780432e-03 3.9014661e-03 1.1794316e-03 6.0207953e-03 1.3473818e-03 6.9135169e-03 3.1440431e-03 7.6724602e-03 2.9974710e-03 1.7751706e-03 1.5977690e-03 4.8531144e-03 2.4494451e-03 5.0339955e-03 4.8947958e-03 5.8464391e-03 3.1299587e-03 2.9881785e-03 1.9161069e-03 6.7804975e-03 3.6799724e-03 6.0827379e-04 2.1616612e-03 3.6536587e-03 6.0346559e-04 1.7560211e-03 1.3150048e-03 2.0808595e-03 9.6848049e-03 1.5050304e-03 8.5509882e-03 3.4934050e-03 2.3873070e-03 2.2266374e-03 4.3437966e-03 3.4432000e-03 4.8822411e-03 2.6118729e-03 4.2515298e-03 3.9280244e-03 2.1763551e-03 2.4215318e-03 2.3726469e-03 5.2469603e-03 8.8156975e-03 4.6543689e-03 1.1653780e-03 1.5634616e-03 8.3770205e-03 3.5034084e-03 3.2683461e-03 4.7014835e-03 4.7252691e-03 1.7941232e-03 2.2843067e-03 6.9328893e-04 1.6436639e-03 1.4866860e-03 4.0234517e-03 7.8970448e-04 2.8726545e-03 3.0564882e-04 4.8340126e-03 3.3681970e-04 3.2031086e-03 3.4962764e-03 6.5051951e-03 1.2935806e-03 1.7549327e-03 2.1673002e-03 4.7736712e-03 4.5514956e-03 3.4934050e-03 3.7661841e-03 5.5497035e-03 4.3927525e-03 3.3294822e-03 2.0638533e-03 5.8922322e-03 2.1421877e-03 1.0254014e-03 1.7967204e-03 2.4056491e-05 4.9606070e-04 1.5493043e-04 7.3786851e-04 5.7634641e-03 2.2821239e-04 9.8983432e-03 4.8234579e-03 3.6558248e-03 4.1003359e-03 5.8726550e-03 5.9033047e-03 6.1776943e-03 5.1708698e-03 7.0154090e-03 4.1004756e-03 1.5716690e-03 3.6383691e-03 2.8864008e-03 6.7180252e-03 9.3042807e-03 4.3918407e-03 2.3314998e-03 2.6748196e-03 1.1913776e-02 5.9266374e-03 3.6227612e-03 5.2997514e-03 7.7658365e-03 2.0655115e-03 2.8598574e-03 2.0567764e-03 1.5031818e-03 1.3330059e-03 5.6389436e-03 2.2318728e-03 4.9186471e-03 7.3077456e-04 6.3335619e-03 1.3529510e-03 6.4463256e-03 4.4695359e-03 6.6841393e-03 2.3650796e-03 1.3974597e-03 2.1137539e-03 5.1383865e-03 3.4413190e-03 4.8234579e-03 4.7468419e-03 5.6953492e-03 3.9468482e-03 4.2095924e-03 2.1520165e-03 5.7168561e-03 2.8181362e-03 2.6785665e-04 8.6267880e-04 1.5080867e-03 1.0657562e-03 9.1259932e-05 3.2834346e-03 5.6400090e-04 1.5768182e-02 8.4481987e-03 5.6912110e-03 7.5460195e-03 9.7379656e-03 8.1209399e-03 1.1078194e-02 7.1125751e-03 8.8544675e-03 7.7247994e-03 3.7380313e-03 5.6213520e-03 4.8502413e-03 1.0137958e-02 1.3681745e-02 7.7719782e-03 4.9953780e-03 6.2009166e-03 1.4059422e-02 6.9488117e-03 6.3504999e-03 9.4504672e-03 9.5001122e-03 3.1213299e-03 6.2307927e-03 4.0875652e-03 2.8287725e-03 3.7400310e-03 8.8571631e-03 3.1845212e-03 5.9757813e-03 2.8285304e-03 9.6559261e-03 2.8616391e-03 9.5937311e-03 5.3787128e-03 1.1658427e-02 5.5682032e-03 3.8827352e-03 3.6680728e-03 8.1913042e-03 4.3904219e-03 8.4481987e-03 8.3060404e-03 9.4592722e-03 5.6422254e-03 5.2631423e-03 4.2070121e-03 1.0442544e-02 6.5544595e-03 1.6777879e-03 1.6905742e-03 1.4559893e-03 2.3696578e-04 1.7661444e-03 8.8626613e-04 1.8929605e-02 1.1198434e-02 8.2126916e-03 1.0357192e-02 1.2691977e-02 1.1286676e-02 1.3897779e-02 1.0124890e-02 1.2174180e-02 9.8437553e-03 5.0898821e-03 8.1181082e-03 6.9678076e-03 1.3160374e-02 1.6460126e-02 9.6980805e-03 7.2881507e-03 8.4988687e-03 1.8112744e-02 9.9154333e-03 8.5214392e-03 1.1906445e-02 1.2939064e-02 4.9240987e-03 8.3797448e-03 6.3232280e-03 4.3836801e-03 5.2916266e-03 1.1816149e-02 5.2785357e-03 8.7418147e-03 4.4568647e-03 1.2648763e-02 4.7832566e-03 1.2911612e-02 7.7565330e-03 1.3968530e-02 7.8153448e-03 5.3323341e-03 5.3832666e-03 1.0542156e-02 5.6397042e-03 1.1198434e-02 1.0902962e-02 1.1744032e-02 7.3882415e-03 7.5970260e-03 6.0277743e-03 1.2454722e-02 8.6970669e-03 6.8936185e-04 2.4185836e-04 6.5755985e-04 5.6966351e-03 2.3035735e-04 9.8692354e-03 4.6426684e-03 3.3219514e-03 3.9792968e-03 5.6658817e-03 5.5182925e-03 6.1624599e-03 4.8454827e-03 6.5522795e-03 4.0009447e-03 1.4714328e-03 3.2975731e-03 2.5896752e-03 6.3872309e-03 9.0422907e-03 4.2582444e-03 2.2027730e-03 2.6736829e-03 1.1276803e-02 5.4428314e-03 3.3876877e-03 5.2005260e-03 7.2827649e-03 1.7342875e-03 2.7931367e-03 1.8984292e-03 1.2582586e-03 1.2661063e-03 5.3418398e-03 1.9890109e-03 4.4646783e-03 7.0136727e-04 6.0091268e-03 1.2000111e-03 6.3087140e-03 3.9600850e-03 6.7054154e-03 2.3290598e-03 1.3528267e-03 1.8394373e-03 4.8617299e-03 3.0806223e-03 4.6426684e-03 4.5595872e-03 5.5227532e-03 3.5904469e-03 3.7269772e-03 1.9354221e-03 5.7786823e-03 2.8379142e-03 1.6160265e-04 9.1316164e-04 4.5133200e-03 3.9636483e-04 1.2999342e-02 7.7990273e-03 6.7507696e-03 6.8565065e-03 9.1164934e-03 9.6187705e-03 8.8289255e-03 8.5171572e-03 1.1041936e-02 6.3870800e-03 3.1070828e-03 6.7336821e-03 5.5817760e-03 1.0377938e-02 1.2745315e-02 6.6393015e-03 4.6463353e-03 4.6865341e-03 1.7095703e-02 9.6546615e-03 6.2703784e-03 7.8942299e-03 1.1919237e-02 4.5195099e-03 4.9936591e-03 4.3235727e-03 3.5370732e-03 2.9138150e-03 9.0955590e-03 4.5162367e-03 8.4195838e-03 2.1592479e-03 9.9327314e-03 3.3056202e-03 9.5169563e-03 7.9097267e-03 8.9017922e-03 4.4124132e-03 2.8482486e-03 4.3995745e-03 8.1140558e-03 5.6448175e-03 7.7990273e-03 7.6396844e-03 8.3822247e-03 6.5839845e-03 7.5512097e-03 4.3854717e-03 7.5528676e-03 4.6977929e-03 6.1532842e-04 4.4755911e-03 9.8852555e-05 1.1287330e-02 6.2297232e-03 5.1189561e-03 5.6158860e-03 7.4118621e-03 7.9100135e-03 7.4458980e-03 7.1082862e-03 9.2159095e-03 4.9487763e-03 1.9996447e-03 5.0869737e-03 4.0020507e-03 8.3714289e-03 1.0564909e-02 5.1004357e-03 3.5205852e-03 3.7366566e-03 1.4679778e-02 7.9564069e-03 4.6553854e-03 6.3553187e-03 1.0091302e-02 3.0597107e-03 3.7953264e-03 3.3093658e-03 2.2411736e-03 1.9075393e-03 7.2834604e-03 3.5416682e-03 6.7651117e-03 1.4482690e-03 7.9807479e-03 2.4205104e-03 8.4840253e-03 5.9704010e-03 7.4790367e-03 3.4333236e-03 1.8691676e-03 2.9457380e-03 6.2606998e-03 3.9378134e-03 6.2297232e-03 6.0227040e-03 6.6475915e-03 4.7553767e-03 5.6493596e-03 2.9997214e-03 6.2979764e-03 3.7014773e-03 2.9064840e-03 2.5951953e-04 1.5239927e-02 8.3975944e-03 6.0152535e-03 7.5736149e-03 9.7205279e-03 8.7194769e-03 1.0665619e-02 7.7107157e-03 9.6513260e-03 7.3495285e-03 3.4129734e-03 5.9493098e-03 4.9891659e-03 1.0300134e-02 1.3429483e-02 7.3762928e-03 4.9967161e-03 5.9349958e-03 1.5151045e-02 7.8143476e-03 6.2821596e-03 9.0873094e-03 1.0390318e-02 3.3768176e-03 5.9427925e-03 4.2522990e-03 2.8707879e-03 3.4399883e-03 9.0442431e-03 3.6087055e-03 6.7269934e-03 2.6557188e-03 9.8316941e-03 3.0241465e-03 9.9672648e-03 5.9844482e-03 1.0964814e-02 5.3765757e-03 3.5060112e-03 3.7251338e-03 8.1205003e-03 4.4033527e-03 8.3975944e-03 8.1986819e-03 9.1329776e-03 5.6810271e-03 5.8010063e-03 4.1618459e-03 9.6695634e-03 6.1457695e-03 3.7030792e-03 2.6425725e-02 1.8599298e-02 1.5467357e-02 1.8635118e-02 2.0442342e-02 2.0541696e-02 2.1259986e-02 1.9510831e-02 2.1931276e-02 1.5294793e-02 9.1682566e-03 1.5285848e-02 1.2953400e-02 2.0823480e-02 2.2513198e-02 1.4419732e-02 1.4350471e-02 1.5480442e-02 2.9209010e-02 1.9066274e-02 1.4266029e-02 1.8093335e-02 2.3152907e-02 1.0464507e-02 1.4480769e-02 1.3685178e-02 9.2298310e-03 1.0125817e-02 1.9700965e-02 1.2730523e-02 1.7262155e-02 1.0225203e-02 2.0352884e-02 1.1535854e-02 2.3443654e-02 1.4503051e-02 1.9462802e-02 1.4723300e-02 9.8246219e-03 1.0395301e-02 1.6330792e-02 8.8773452e-03 1.8599298e-02 1.7720786e-02 1.7175716e-02 1.1774527e-02 1.4190018e-02 1.1287889e-02 1.7334951e-02 1.4959707e-02 1.2176711e-02 6.5819636e-03 5.0346277e-03 6.0397395e-03 7.7827629e-03 7.8599708e-03 8.1942510e-03 7.0899174e-03 9.0304038e-03 5.3331159e-03 2.1084043e-03 4.9833227e-03 3.9086435e-03 8.5223444e-03 1.0895531e-02 5.3819973e-03 3.7720778e-03 4.2725796e-03 1.4381123e-02 7.5978371e-03 4.7474248e-03 6.8472012e-03 9.8808760e-03 2.7678758e-03 4.1999833e-03 3.4360629e-03 2.0712504e-03 2.1185414e-03 7.4497841e-03 3.4016631e-03 6.4264729e-03 1.6858980e-03 8.1251590e-03 2.4514173e-03 8.9161864e-03 5.4840504e-03 8.2209587e-03 3.8745808e-03 2.1076714e-03 2.7824071e-03 6.3561971e-03 3.5186798e-03 6.5819636e-03 6.3377454e-03 6.9667686e-03 4.4964760e-03 5.2124475e-03 2.9917795e-03 7.0285944e-03 4.2716151e-03 1.5675754e-03 4.2437140e-03 2.9528525e-03 1.2801911e-03 5.5300675e-03 5.2313183e-04 7.0373258e-03 7.0028853e-03 1.5817688e-03 4.6017698e-03 4.2905415e-03 3.9763653e-03 1.7507004e-03 9.8088526e-04 2.0205251e-03 3.8651167e-03 2.8498196e-03 8.0083780e-03 8.7219602e-03 2.5429883e-03 8.6090275e-04 7.9906965e-03 6.1518285e-03 2.2097973e-03 5.7963314e-03 5.7460009e-03 4.2262969e-03 2.1872477e-03 8.9731860e-03 7.8793225e-03 5.8991938e-03 1.8999235e-03 7.1341168e-03 7.0170212e-03 6.4409068e-03 6.9062404e-04 3.2402506e-03 4.2346770e-03 4.9489360e-03 1.9844891e-03 6.6121605e-03 1.5675754e-03 1.4409377e-03 1.2937675e-03 4.5154908e-03 6.0031850e-03 4.0189646e-03 1.2526895e-03 2.2326743e-03 6.7976748e-04 4.4251056e-04 5.1964468e-05 1.5314410e-03 4.7093005e-04 2.2872076e-03 2.4409680e-03 6.1996952e-04 1.8531872e-03 7.0675084e-04 7.4672595e-04 2.9977980e-04 1.6320684e-03 1.1279305e-03 6.4871929e-04 6.2074215e-04 4.0109945e-03 3.1610099e-03 4.6600326e-04 4.3207236e-04 3.1187047e-03 1.7495883e-03 3.8892953e-04 1.4972893e-03 1.7881991e-03 1.3932149e-03 1.6264024e-04 3.1616233e-03 2.5553184e-03 1.9652949e-03 2.4129313e-04 2.2301817e-03 3.0218268e-03 1.9168834e-03 1.5054952e-03 6.4024254e-04 1.6084351e-03 1.4082859e-03 5.9336508e-04 3.2376306e-03 1.1102230e-16 6.3653022e-05 8.5949029e-04 1.8263557e-03 1.6881339e-03 9.7411877e-04 1.7845049e-03 6.1330704e-04 7.1368649e-04 9.0151789e-04 6.1896245e-04 2.2461726e-03 1.0406196e-03 1.1172454e-03 1.6730261e-03 1.8311894e-03 1.8071232e-06 2.5364008e-04 8.3907159e-04 3.3874526e-03 2.1375798e-03 4.5487046e-04 1.1672957e-03 2.8115805e-03 1.2138761e-03 7.0446879e-04 1.8201572e-03 1.6098088e-03 5.2152529e-04 1.0325997e-03 6.5974667e-04 9.0603694e-04 1.4060118e-03 4.3618665e-04 1.3469029e-03 7.5850938e-04 1.4500880e-03 6.7416609e-04 1.0299923e-03 2.5247687e-03 4.1453726e-04 3.7399848e-03 9.2294426e-04 1.7551096e-03 7.2749277e-04 1.1614195e-03 2.4439916e-03 6.7976748e-04 8.1575962e-04 2.1038526e-03 1.4799615e-03 3.3653084e-04 6.6936205e-04 3.8899674e-03 1.5033836e-03 6.1892938e-04 8.9565267e-04 1.1187414e-03 1.0854623e-03 1.6238473e-03 1.6997610e-03 2.5416419e-03 7.7939556e-04 1.2163589e-03 1.1645635e-03 3.7479516e-03 2.5673270e-03 2.8413719e-04 3.4882680e-04 3.5538869e-03 2.1358644e-03 1.3529179e-03 1.5262264e-03 2.0757398e-03 1.9224937e-03 7.7565401e-04 6.3114517e-04 2.1204969e-03 1.7089017e-03 5.9516371e-04 1.8253945e-03 1.7466546e-03 1.3725400e-03 9.7938279e-04 1.2586511e-03 1.2414457e-03 2.1946939e-03 3.0180258e-03 3.2655328e-04 2.0574339e-03 1.9692598e-03 1.9049224e-03 4.6812273e-03 4.4251056e-04 7.9383810e-04 2.4056659e-03 3.2171363e-03 2.0291670e-03 1.5121604e-03 3.2358269e-03 7.8092419e-04 1.6056499e-03 4.5150817e-04 2.5183573e-03 2.4854849e-03 8.1663583e-04 2.4301739e-03 9.3222022e-04 1.0572824e-03 1.7339381e-04 1.3855383e-03 1.3424761e-03 1.0242405e-03 9.7281350e-04 3.6981982e-03 3.3860618e-03 6.8052310e-04 4.8835842e-04 3.1532670e-03 2.2405021e-03 6.9163264e-04 1.9828394e-03 2.3495346e-03 1.9517373e-03 1.3548451e-04 3.7877283e-03 2.8247707e-03 2.6466102e-03 1.4866617e-04 2.8614588e-03 3.2185979e-03 2.1613637e-03 1.5430396e-03 1.0217871e-03 2.1845781e-03 1.8662401e-03 6.6257305e-04 3.7358116e-03 5.1964468e-05 1.2907411e-04 9.1062515e-04 2.1316335e-03 1.9388777e-03 1.3908595e-03 1.9526372e-03 9.5243046e-04 3.3534848e-03 2.1612689e-04 1.1409237e-04 3.7511533e-03 4.4135123e-03 6.6848080e-04 1.6638889e-03 1.5639090e-03 5.3797969e-03 4.6512834e-03 1.2304041e-03 2.1424312e-03 1.1209148e-03 3.9967200e-04 2.4397061e-03 3.5566606e-03 2.8773633e-04 1.9980195e-03 2.5921392e-03 1.0825130e-03 2.8538916e-03 3.5346603e-03 9.3770297e-04 1.4682668e-03 3.5169417e-04 2.8507687e-03 1.3414178e-03 1.7057263e-03 1.1395352e-03 1.1778138e-03 6.0686882e-03 1.8828714e-03 4.1140616e-03 2.6499598e-03 2.9837515e-03 5.4227271e-03 1.5314410e-03 2.0381041e-03 4.2816261e-03 3.9075302e-03 1.2227927e-03 2.5264748e-03 6.5268770e-03 2.9950818e-03 4.2523782e-03 4.6456758e-03 7.0284879e-04 2.6206169e-03 2.2973667e-03 2.1186617e-03 1.0662204e-03 1.4771683e-03 1.2714179e-03 1.6200996e-03 9.3400517e-04 6.3864823e-03 5.7928278e-03 1.2702417e-03 3.0680262e-04 5.4794582e-03 3.6431092e-03 7.0967201e-04 2.9368020e-03 3.3273895e-03 2.1071133e-03 1.0635659e-03 5.3575283e-03 5.0378701e-03 2.9935636e-03 1.0701915e-03 3.8904013e-03 4.2643219e-03 4.2480632e-03 6.5030200e-04 1.1722241e-03 2.1985353e-03 2.8568074e-03 1.2361632e-03 4.8426872e-03 4.7093005e-04 4.8520973e-04 9.1253531e-04 3.1519557e-03 3.8819044e-03 2.1030647e-03 9.4974174e-04 6.5992898e-04 2.7415573e-04 4.6934818e-03 4.8265016e-03 1.1075187e-03 2.2246224e-03 2.7094103e-03 7.2547386e-03 5.7651516e-03 1.2879775e-03 2.2498412e-03 1.7969640e-03 2.9988677e-04 3.2873557e-03 4.6281528e-03 3.4411066e-04 2.2557578e-03 3.0860670e-03 7.9349579e-04 3.1195585e-03 3.7700064e-03 1.7729958e-03 8.2927671e-04 3.1955044e-04 2.5127017e-03 2.3924363e-03 1.2355886e-03 6.3306711e-04 1.7271405e-03 7.3517242e-03 1.9482896e-03 4.3986367e-03 3.1257329e-03 4.1788193e-03 6.3227646e-03 2.2872076e-03 2.9291555e-03 5.5970414e-03 4.9483109e-03 1.7952206e-03 3.0186434e-03 7.6597710e-03 3.3340783e-03 5.0895780e-03 5.6951678e-03 1.1683986e-03 2.4173290e-03 2.2930538e-03 6.6766405e-03 6.0598142e-03 2.0196993e-03 3.2103351e-03 7.1260012e-04 2.1040770e-04 3.4457175e-03 4.8676879e-03 4.7880714e-05 2.6160358e-03 3.7638559e-03 1.6534967e-03 3.7166920e-03 4.7397184e-03 1.5966719e-03 1.7314841e-03 3.1225254e-04 3.8216967e-03 2.0442457e-03 2.2822879e-03 1.3421268e-03 1.4265946e-03 7.7649269e-03 2.8740126e-03 5.4160448e-03 3.5155679e-03 4.0306705e-03 6.4534752e-03 2.4409680e-03 3.0445932e-03 5.6145787e-03 4.8826195e-03 1.5492752e-03 3.4872724e-03 8.3107496e-03 4.2635519e-03 8.0787158e-04 1.6588755e-03 9.5088926e-04 1.1215622e-03 1.1319394e-03 1.0749073e-04 1.3651148e-03 1.0419898e-03 7.3951172e-03 5.6721517e-03 2.8717807e-04 1.2167194e-04 6.0929710e-03 1.9467902e-03 2.7497575e-04 2.6021687e-03 1.4711384e-03 7.6653532e-04 1.1979861e-03 4.6497866e-03 4.6528613e-03 2.0491908e-03 1.1214382e-03 3.1087470e-03 5.8331337e-03 2.9008505e-03 5.1851355e-04 1.1077981e-03 7.4180273e-04 1.1189833e-03 3.3213225e-04 1.9786092e-03 6.1996952e-04 3.2630432e-04 1.6788710e-04 1.0717507e-03 2.5327575e-03 6.9916673e-04 4.8860962e-04 5.0860173e-04 1.7852918e-03 8.1925898e-04 2.7637031e-03 3.4415701e-03 7.6048751e-04 1.3454814e-03 1.4168273e-03 9.1102129e-03 5.4634531e-03 7.0608839e-04 1.5253323e-03 6.6930140e-03 9.6900708e-04 7.0882160e-04 2.0455668e-03 3.9468549e-04 1.1422246e-04 2.4972040e-03 3.2985277e-03 4.3265068e-03 9.6084950e-04 2.6351726e-03 1.9457490e-03 6.5435669e-03 2.5549327e-03 2.2787630e-03 1.2770395e-03 6.6117888e-05 4.1362061e-04 1.2709485e-03 9.0111668e-04 1.8531872e-03 1.4879007e-03 1.4236785e-03 8.2396190e-04 2.2228636e-03 3.0260473e-04 1.7887502e-03 9.8733924e-04 2.2593145e-04 8.4529966e-04 3.3545284e-03 2.0967474e-03 4.8795197e-04 1.2181976e-03 2.8660735e-03 1.2480152e-03 6.7735579e-04 1.8245752e-03 1.6711447e-03 4.7937341e-04 1.0455121e-03 6.9960603e-04 8.5898853e-04 1.3874556e-03 4.5677202e-04 1.3792343e-03 7.7973864e-04 1.4683104e-03 6.8342524e-04 1.0561802e-03 2.6555506e-03 3.7342452e-04 3.7432085e-03 9.6667604e-04 1.7304819e-03 6.7810292e-04 1.1254700e-03 2.3291425e-03 7.0675084e-04 8.2471895e-04 2.0738735e-03 1.3951480e-03 2.9534051e-04 6.3569311e-04 3.8846725e-03 1.5360581e-03 9.9102840e-04 2.6998600e-03 1.1403522e-03 5.9435819e-04 1.1584769e-03 4.5439398e-03 2.4115910e-03 2.2376231e-04 1.3051908e-03 3.1170665e-03 2.4639357e-04 6.5093729e-04 1.0408914e-03 3.2170646e-04 6.8086675e-04 7.3723950e-04 1.9464154e-03 1.6938542e-03 1.2010351e-03 8.6567601e-04 1.2605984e-03 4.0415296e-03 6.0024917e-04 2.8241029e-03 9.3145876e-04 8.7987159e-04 1.5390142e-04 6.1621791e-04 1.2031695e-03 7.4672595e-04 6.4561848e-04 1.3132954e-03 5.7671738e-04 4.3996999e-04 1.2646330e-04 2.7819647e-03 1.1571313e-03 1.1519638e-03 1.4945239e-03 1.5137092e-03 1.7542391e-03 3.0584682e-03 3.1624125e-03 6.9423087e-04 8.0741075e-04 2.9564986e-03 2.1264808e-03 1.1956222e-03 2.4834226e-03 2.4046990e-03 2.4389289e-03 1.1428932e-04 4.1572751e-03 2.6270682e-03 3.3826290e-03 1.0906814e-05 3.3779688e-03 3.9749243e-03 1.6265579e-03 2.0735613e-03 1.7238890e-03 2.6977636e-03 1.8191981e-03 5.1180139e-04 3.3068455e-03 2.9977980e-04 3.0495320e-04 9.6732841e-04 1.7461140e-03 1.4560452e-03 1.4920651e-03 2.5772801e-03 1.7019143e-03 1.0341988e-03 4.0085546e-03 3.6492138e-03 7.4340196e-03 7.9703529e-03 1.4966880e-03 7.8440192e-04 7.7789554e-03 4.4532033e-03 2.2360209e-03 5.9110335e-03 4.1723764e-03 3.6115483e-03 1.8645164e-03 8.6587941e-03 6.9790025e-03 5.9223579e-03 1.3508421e-03 6.9679643e-03 8.8100022e-03 4.3884451e-03 9.3956602e-04 3.8113149e-03 3.5744927e-03 3.3082295e-03 7.5316334e-04 3.6491972e-03 1.6320684e-03 1.1884181e-03 4.5803930e-04 2.1497659e-03 4.0210128e-03 2.8148066e-03 1.4099016e-03 2.8014283e-03 2.0075866e-03 1.7351697e-03 8.4094224e-03 6.5677927e-03 3.9418601e-04 3.5055970e-04 7.1718250e-03 2.0973679e-03 6.4851765e-04 3.3744442e-03 1.5292791e-03 9.4071576e-04 1.7144529e-03 5.4753391e-03 5.4188405e-03 2.5828658e-03 1.5301373e-03 3.8027206e-03 7.3328244e-03 3.1192913e-03 6.2731613e-04 1.7741918e-03 8.4678687e-04 1.1412463e-03 3.3683903e-04 1.4744098e-03 1.1279305e-03 6.7560808e-04 1.3395103e-04 7.7360874e-04 2.7301747e-03 8.0481079e-04 5.3215427e-04 1.0082007e-03 2.3386408e-04 4.5650335e-03 2.1085336e-03 8.9398060e-04 1.5597528e-03 2.5626398e-03 8.9643929e-04 4.6401620e-04 2.1474828e-04 9.4200330e-04 7.4363388e-04 8.8544521e-04 1.1214375e-03 1.5513223e-03 4.7369920e-04 1.2949283e-03 5.0107186e-04 1.9686134e-03 1.5839083e-03 3.0734994e-03 1.1037013e-04 1.0184869e-03 9.4459481e-04 1.6215035e-03 3.1102930e-03 6.4871929e-04 8.4571319e-04 2.1956968e-03 2.1853516e-03 1.4074387e-03 6.7079422e-04 3.0128980e-03 5.5375407e-04 5.9745601e-03 3.5596915e-03 1.0825427e-03 1.1193941e-03 3.8619013e-03 1.7868782e-03 2.6699310e-04 7.4652731e-04 1.5644519e-03 7.6914730e-04 1.1868249e-03 2.1537215e-03 2.8904145e-03 6.7050048e-04 1.5688544e-03 1.1553603e-03 2.3985919e-03 2.8520067e-03 2.1226295e-03 2.6532317e-05 9.5443067e-04 1.5325109e-03 1.7403036e-03 3.8293675e-03 6.2074215e-04 7.8759073e-04 1.8993585e-03 2.7454611e-03 2.5765044e-03 1.0363780e-03 2.0443972e-03 1.4335859e-04 1.4016332e-03 5.4805806e-03 6.7405649e-03 6.4579738e-04 5.1748633e-03 6.3487765e-03 4.3874825e-03 6.7084849e-03 8.1049162e-03 2.6677096e-03 4.6345484e-03 1.7447861e-03 7.4893653e-03 2.9062036e-03 5.4610122e-03 3.0610024e-03 2.8530196e-03 9.9111331e-03 5.6471487e-03 8.9070297e-03 6.1633735e-03 5.5983777e-03 9.1911029e-03 4.0109945e-03 4.6927139e-03 7.3914201e-03 7.0233589e-03 3.0645626e-03 6.1283907e-03 1.0939049e-02 7.1096522e-03 3.7615860e-03 5.7439366e-03 2.3434979e-04 2.1625792e-03 4.1436319e-03 1.4386017e-03 3.2647240e-03 4.5819077e-03 2.2920937e-03 1.0610016e-03 6.9564930e-05 3.4218787e-03 2.8472107e-03 1.7665885e-03 1.7134963e-03 1.2022963e-03 8.8958832e-03 3.1032776e-03 5.2642601e-03 3.2432815e-03 4.6032265e-03 6.0005810e-03 3.1610099e-03 3.7408101e-03 6.4052558e-03 4.8371122e-03 1.3589516e-03 3.3936977e-03 9.2321743e-03 4.6963171e-03 5.0386940e-04 4.2984797e-03 8.6973796e-04 3.5526497e-04 1.7666127e-03 7.2192984e-04 6.5802622e-04 6.6868074e-04 3.2431480e-03 2.9035420e-03 1.6594087e-03 6.4854242e-04 2.1612810e-03 4.9124735e-03 1.3725331e-03 1.5050690e-03 9.8777331e-04 7.5260407e-04 4.1403958e-04 1.4453279e-04 1.2645371e-03 4.6600326e-04 2.4792089e-04 4.5627999e-04 4.7560079e-04 1.1214322e-03 2.2091820e-04 1.5167980e-03 7.9735767e-04 5.8276719e-03 2.5886189e-03 4.3280198e-04 2.9205975e-03 2.2021650e-03 1.3597486e-03 9.5466012e-04 5.1915037e-03 4.8194588e-03 2.6659023e-03 8.3877743e-04 3.6595156e-03 5.4665486e-03 3.2603866e-03 3.5246614e-04 1.2546385e-03 1.3738455e-03 1.7317120e-03 4.0173517e-04 2.8852033e-03 4.3207236e-04 2.1872967e-04 1.7262684e-04 1.6274416e-03 2.8950267e-03 1.1933707e-03 5.1057942e-04 6.2761497e-04 3.2515433e-03 4.5844712e-03 2.0397580e-03 4.4892831e-03 5.6236454e-03 2.1663608e-03 1.9457792e-03 4.4715761e-04 4.4562273e-03 2.6795180e-03 2.6855442e-03 1.3224094e-03 1.8950095e-03 8.9432615e-03 3.4981521e-03 6.3671383e-03 4.3127165e-03 4.9533188e-03 7.5137514e-03 3.1187047e-03 3.8229023e-03 6.6814123e-03 5.8612561e-03 2.0597987e-03 4.3006086e-03 9.5397630e-03 5.0775992e-03 1.3692874e-03 9.6403546e-04 1.3966479e-04 8.6664284e-04 1.6597338e-03 1.3212159e-03 1.4578093e-03 1.0432500e-03 1.9220792e-03 8.7918940e-04 4.4168060e-03 5.0670419e-04 4.4696559e-03 1.4208846e-03 1.1004494e-03 1.6436932e-04 1.5507648e-03 1.1191058e-03 1.7495883e-03 1.6621469e-03 2.5414268e-03 8.8363295e-04 4.0096791e-04 3.3482530e-04 4.2345389e-03 1.9374158e-03 1.2770848e-03 1.0395507e-03 3.9095383e-04 9.2829494e-04 2.8992176e-03 3.2975300e-03 9.5393320e-04 1.0925514e-03 1.6776296e-03 3.8507253e-03 2.3805613e-03 1.2082502e-03 2.8135004e-04 4.7639114e-04 8.7356741e-04 7.4310336e-04 2.3860646e-03 3.8892953e-04 3.1610282e-04 8.0643344e-04 1.4728895e-03 2.0712058e-03 4.6512964e-04 1.1229948e-03 8.8791739e-05 1.1956364e-03 1.3055469e-03 1.5870433e-03 3.7223827e-04 1.0219838e-03 4.8252621e-04 2.1760282e-03 1.1580239e-04 1.5036929e-03 1.5974284e-03 4.9006747e-03 5.1331960e-04 1.6812595e-03 1.3616634e-03 2.7816530e-03 3.8434871e-03 1.4972893e-03 1.8359326e-03 3.6884416e-03 3.0552141e-03 1.4996272e-03 1.2110783e-03 4.7697841e-03 1.3648602e-03 3.9191527e-04 1.9808749e-03 1.8113262e-03 2.3841094e-03 7.8154360e-04 2.2164780e-03 1.0439462e-03 5.1766229e-03 1.1157470e-03 3.6934914e-03 1.2626931e-03 5.1659909e-04 5.8959899e-05 1.4097594e-03 7.9470954e-04 1.7881991e-03 1.5872251e-03 2.1165612e-03 7.0368642e-04 9.2823209e-04 1.5533041e-04 3.3160103e-03 1.5048956e-03 2.0235000e-03 2.4966081e-03 3.5807846e-03 4.7284012e-04 2.2730788e-03 1.2853266e-03 5.0519729e-03 2.3762808e-03 2.2444800e-03 6.5500299e-04 2.4750944e-05 4.4815197e-04 1.3292061e-03 1.4780836e-03 1.3932149e-03 1.1924273e-03 1.5277304e-03 1.1896691e-03 2.0673918e-03 2.5400150e-04 1.8225589e-03 5.4227610e-04 2.9880363e-03 1.8314313e-03 2.5238977e-03 5.5757663e-05 2.3698503e-03 2.8213423e-03 1.3040881e-03 2.4190319e-03 1.1221589e-03 2.3332880e-03 1.5386845e-03 7.3215728e-04 3.3801838e-03 1.6264024e-04 2.8457958e-04 1.3051710e-03 1.8856170e-03 1.1599202e-03 1.2252261e-03 2.8396493e-03 1.3307965e-03 7.9081662e-04 1.1208231e-03 3.7513747e-03 2.2532467e-04 1.8915999e-03 1.8066444e-03 7.8138393e-03 1.7396624e-03 2.9887611e-03 2.1626603e-03 4.5716343e-03 4.7705983e-03 3.1616233e-03 3.6125170e-03 5.9695278e-03 4.2653532e-03 1.8208998e-03 2.2513824e-03 7.5822521e-03 3.0950854e-03 2.6638425e-03 2.3329339e-03 1.2833498e-03 1.8503904e-03 7.6221882e-04 7.7332789e-03 2.4545666e-03 4.1819304e-03 2.3678329e-03 3.7122984e-03 4.8118232e-03 2.5553184e-03 3.0167737e-03 5.3596333e-03 3.8038292e-03 8.6990936e-04 2.5148680e-03 7.9707274e-03 3.8479364e-03 3.0845972e-03 3.4545687e-04 3.2912795e-03 2.5772857e-03 4.0614792e-03 4.9082550e-04 6.4992316e-04 1.0688017e-03 2.7640538e-03 2.9796108e-03 1.9652949e-03 2.0639503e-03 3.2701588e-03 2.6492756e-03 2.3500195e-03 8.8549039e-04 3.5901884e-03 9.2048730e-04 3.0276112e-03 3.6195589e-03 1.4632965e-03 2.1763560e-03 1.5224813e-03 2.5475111e-03 1.6768950e-03 5.4331181e-04 3.2527051e-03 2.4129313e-04 2.7799169e-04 1.0453548e-03 1.7267901e-03 1.3027778e-03 1.3633707e-03 2.6503970e-03 1.5759024e-03 2.1731558e-03 1.7887862e-03 5.7263386e-03 8.5148931e-04 1.6383081e-03 1.3458097e-03 3.3594814e-03 3.6389958e-03 2.2301817e-03 2.5225544e-03 4.3534713e-03 3.1787209e-03 1.6954559e-03 1.3061945e-03 5.4111697e-03 1.7803664e-03 4.1741292e-03 7.9197469e-03 2.2821957e-03 5.7150571e-03 5.2344879e-03 5.9478982e-03 9.4860449e-03 3.0218268e-03 3.9157169e-03 7.0424278e-03 7.6315025e-03 4.1845322e-03 4.7751866e-03 8.3019483e-03 3.6628005e-03 5.6294536e-03 2.4239872e-03 2.7647556e-03 9.2421646e-04 1.7874511e-03 2.0292522e-03 1.9168834e-03 1.9458286e-03 3.1481713e-03 1.3908818e-03 1.3324310e-05 1.1782972e-03 5.7639460e-03 3.2058410e-03 2.4140579e-03 2.0956665e-03 3.1463866e-03 1.2261330e-03 4.0134358e-03 1.5054952e-03 1.1240475e-03 4.7360391e-04 2.7309553e-03 5.1301270e-03 2.4137049e-03 8.9922816e-05 1.2592279e-03 8.6164876e-04 1.2616309e-03 1.6936265e-03 3.4914911e-03 6.4024254e-04 8.0798030e-04 1.9823430e-03 2.5037231e-03 2.1768005e-03 8.4515239e-04 2.3117307e-03 2.1993248e-04 5.6812764e-04 1.3931392e-03 1.4308209e-03 1.6084351e-03 1.3403960e-03 1.4811963e-03 1.2106398e-03 2.4235208e-03 3.5787719e-04 1.6247178e-03 6.1681362e-04 9.2162383e-04 6.4491663e-04 1.4082859e-03 1.1774797e-03 1.5785221e-03 4.0122185e-04 7.3237681e-04 6.4530654e-05 2.8852212e-03 1.3991525e-03 1.5175131e-03 5.9336508e-04 2.9036861e-04 2.0099198e-04 5.5129609e-04 1.5179733e-03 6.8841417e-04 1.3866758e-03 1.2880812e-03 3.2376306e-03 2.6196338e-03 2.0860993e-03 2.5676122e-04 1.7880288e-03 9.1594192e-04 3.5976292e-03 3.2249197e-03 6.3653022e-05 8.5949029e-04 1.8263557e-03 1.6881339e-03 9.7411877e-04 1.7845049e-03 6.1330704e-04 4.6521065e-04 1.3489557e-03 1.6857799e-03 7.7549379e-04 1.3461987e-03 6.0478443e-04 1.0485877e-03 2.7784351e-03 1.1708179e-03 5.9587066e-04 1.2049026e-03 1.1592978e-03 4.9960727e-04 2.5830270e-03 2.2390567e-03 9.5053595e-04 5.2396832e-03 2.8622802e-03 2.1952710e-03 8.7416055e-04 1.1307517e-03 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-cosine-ml.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-cosine-ml.txt new file mode 100644 index 0000000000000000000000000000000000000000..7c6b67fa43c5fef11101d28dd46f4c1b325b65ee --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-cosine-ml.txt @@ -0,0 +1 @@ + 2.5695885e-01 2.6882042e-01 2.3470353e-01 2.9299329e-01 2.2742702e-01 3.1253572e-01 2.4986352e-01 3.0770122e-01 2.5191977e-01 2.7931567e-01 2.8133743e-01 2.6316239e-01 2.6067201e-01 3.2982339e-01 2.8993002e-01 2.5506356e-01 2.8728051e-01 2.4952121e-01 2.8613379e-01 2.6894157e-01 2.3606353e-01 2.1670935e-01 2.3470242e-01 2.4294172e-01 2.4376454e-01 2.3228195e-01 2.3554918e-01 2.4851241e-01 2.0917546e-01 2.4971488e-01 2.4264224e-01 2.7405461e-01 1.9086415e-01 2.6346574e-01 2.5908801e-01 2.2138495e-01 2.2910721e-01 2.2169919e-01 2.0660065e-01 2.3207102e-01 2.5554688e-01 2.5153751e-01 2.6073682e-01 2.0919640e-01 3.3984433e-01 2.7503792e-01 2.1709889e-01 2.7068095e-01 3.0307041e-01 2.4529612e-01 2.2987015e-01 2.7736967e-01 3.0310708e-01 3.0544316e-01 1.9205388e-01 2.7098021e-01 2.0722466e-01 2.6387343e-01 2.8998308e-01 2.2633010e-01 2.5177075e-01 1.6347011e-01 2.4036389e-01 2.6485871e-01 2.8491965e-01 2.2273619e-01 2.4511873e-01 2.5930533e-01 2.6589995e-01 2.7797191e-01 2.3357373e-01 2.4279909e-01 2.3544532e-01 1.9447286e-01 2.3993534e-01 2.0856243e-01 2.2125251e-01 2.1988206e-01 2.0590152e-01 2.6441952e-01 2.0052739e-01 2.2978496e-01 2.4483670e-01 2.3879510e-01 2.9398425e-01 2.7541852e-01 2.3777469e-01 2.9151131e-01 2.0672752e-01 2.4584031e-01 2.7475025e-01 2.7064343e-01 2.5603684e-01 2.6165327e-01 2.4233155e-01 1.7892657e-01 2.6111203e-01 1.9965682e-01 2.4201634e-01 2.6281353e-01 3.1928221e-01 1.9731963e-01 2.7752862e-01 2.2633080e-01 2.6783167e-01 2.5447186e-01 2.6424243e-01 2.1960672e-01 2.2984242e-01 2.8788736e-01 2.8681630e-01 2.6949787e-01 2.3993685e-01 2.4440073e-01 2.5010397e-01 2.3230769e-01 2.9879682e-01 2.4200592e-01 2.6957748e-01 2.6073240e-01 2.6355347e-01 2.3403674e-01 2.2411413e-01 2.2956729e-01 2.8105976e-01 2.2913304e-01 2.4898608e-01 2.3304000e-01 2.2692988e-01 2.3728251e-01 2.2552243e-01 2.0364084e-01 2.3359511e-01 2.6619167e-01 2.6666588e-01 2.3666880e-01 2.7239113e-01 2.0146697e-01 2.3045559e-01 2.1695523e-01 2.1387991e-01 2.2366404e-01 2.2809635e-01 2.0901297e-01 2.2441100e-01 2.3418882e-01 2.8552218e-01 2.4609015e-01 2.0282492e-01 2.5940295e-01 2.7407006e-01 2.3344890e-01 2.1179142e-01 2.7047821e-01 2.9832768e-01 2.0859082e-01 2.8881331e-01 1.8384598e-01 2.5286491e-01 2.2012615e-01 2.3615775e-01 2.6845565e-01 2.3356355e-01 2.7164193e-01 2.4179380e-01 2.5247973e-01 2.5637548e-01 3.2126483e-01 2.3100774e-01 2.8832546e-01 2.0043257e-01 2.7918333e-01 2.4884522e-01 2.2904723e-01 2.3738940e-01 2.9461278e-01 2.9782005e-01 3.0332073e-01 2.5175971e-01 3.1203784e-01 2.6611535e-01 2.3713507e-01 2.2203585e-01 2.3602325e-01 2.5093670e-01 2.6860434e-01 3.0137874e-01 2.3759606e-01 2.6840346e-01 1.9200556e-01 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-double-inp.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-double-inp.txt new file mode 100644 index 0000000000000000000000000000000000000000..7a77021775ddb61d226aa8c4ba60f0af013e4a6c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-double-inp.txt @@ -0,0 +1,20 @@ +8.278938049410748956e-01 9.035293984476246987e-01 1.862188994679486731e-01 8.921151312310462433e-01 2.061859119379583216e-02 3.440636727385729676e-01 1.533779912830328662e-01 5.701372300009802663e-01 5.510020730211558915e-01 1.792362258426003496e-01 8.086175120876580857e-01 6.115487184317183189e-01 1.233471787164852618e-02 1.441643531871039663e-03 4.044309209045688913e-01 3.561398959499905148e-01 1.281985712929750720e-01 8.663300833847481508e-01 8.696027786291581352e-01 3.611727370363766454e-01 5.283537658772616830e-01 1.440241088090119526e-01 3.112457227138950566e-01 6.031280796897889873e-01 9.230324792742518047e-01 2.332121881136874908e-01 3.192652267403439659e-02 3.466206294995559656e-01 2.988687728046366399e-01 5.116749542048093513e-02 2.584975830914494344e-01 4.302023478042227289e-01 8.003972751713522849e-01 9.364931911368097328e-01 9.737098649964673891e-01 4.718038453972229762e-01 4.526591686607864817e-01 1.056485678520797666e-01 5.883019714285405710e-01 3.846092237676981274e-01 6.461500053435473845e-01 1.013239729848824933e-01 1.216151561651189761e-01 5.159668929484659827e-01 8.452074473510227115e-01 9.885170962247968873e-01 7.623883073490128615e-01 2.291163243615434997e-02 5.775530980802381364e-01 7.820699896828091635e-01 8.239186345842965942e-01 3.391800105260227571e-01 9.546318451614538292e-01 3.789677917867695367e-01 4.526533399649290690e-02 8.366786473238587707e-01 3.082636811049858094e-01 1.173936820793450853e-01 7.631994969169442200e-02 2.997416650722183329e-01 5.795208655160232203e-01 3.942350892542011431e-01 1.175126383297261379e-01 4.928232513950027149e-01 9.421293996225950096e-01 8.365391053841342295e-02 6.868059693571844093e-01 3.589527962429440722e-01 7.592939427166059962e-01 5.623849466131448649e-01 2.110746828032050715e-01 9.824683704668600859e-01 2.661230142246236996e-01 6.162272315007123469e-01 5.023254536607497656e-01 5.202854476669782624e-02 5.835090668842095596e-01 7.864642118889143552e-01 2.504012386867506823e-01 6.728308641135989365e-01 4.610793534576096420e-01 4.820508770515909980e-01 9.720403251022265989e-01 3.100069285263498120e-01 7.681017126461753275e-01 7.956539306007082146e-02 2.593389637887737464e-01 1.137852590403054531e-01 3.885303073284454012e-01 8.599094660075957686e-01 5.215167875918280682e-02 1.620908248572288102e-01 1.859236090457663249e-01 6.247716512610480555e-01 3.415128495520775020e-01 7.034903368378029320e-01 6.037564640019568163e-01 2.338969434423310290e-01 1.002104885609900187e-02 7.866058403969036217e-01 +8.033694116033356369e-01 8.653264545544031572e-01 7.468340410754038539e-01 6.362430919910603278e-01 5.120006306625468628e-02 9.503348372633585450e-01 4.697732609626817935e-01 4.221305288459429317e-01 3.153452119838391354e-01 2.991014843442657556e-01 1.190667967280257811e-01 3.486567714509342109e-01 8.289493649885054660e-01 8.454811050800014049e-01 9.149673018211901265e-01 7.708707837193897738e-01 2.640157732122547785e-01 2.107897022189605396e-01 4.207633055054439408e-01 6.719500284654699174e-01 1.458031684893063007e-01 1.800412735886125493e-02 8.402733435220011149e-02 4.206760156883160295e-02 1.376933515041314227e-01 1.716717341022133692e-01 1.788220727652158892e-01 8.224310433402118869e-01 7.729093666867475898e-01 2.064223621025984556e-01 9.592092036227207741e-01 8.312490243754996344e-01 6.673289360369902834e-01 4.632847903690773261e-02 7.643954098358983762e-01 9.359341525615098023e-01 1.914966319163026176e-01 4.536590469402868031e-01 8.640836016538007147e-01 3.941529178175462444e-02 5.602101995205478469e-01 9.263806161941660067e-01 1.555995325944817820e-01 6.172208102950116348e-01 6.335576752812099866e-01 9.766975460368043649e-02 4.475795689539874278e-02 3.248842796104995934e-01 5.700377122149502540e-01 9.066962967256807504e-01 5.458460621505676347e-01 6.833401285581487405e-01 2.887244409544044155e-01 1.316338647016834784e-01 2.325673305245992140e-01 4.150121963188406760e-01 3.834845466366055833e-01 8.149365773968725302e-01 1.867003849450201702e-01 3.170322173543018707e-01 6.832093662682684476e-01 1.729728518929105618e-01 9.236557359702636250e-01 9.152941252150086360e-01 7.224879983096620384e-01 8.557920626598064517e-01 5.344883059251644974e-01 4.876873274449112783e-01 8.308277804506420949e-01 3.916624489322212410e-01 3.459695122273966916e-01 4.033512499027409604e-01 6.555726444913008155e-01 7.138452409380238173e-01 1.683937314599968094e-01 1.769382143486440961e-01 7.588683655178136700e-01 3.750589892880819010e-01 7.525176245126207197e-01 6.083961152538303052e-01 1.145972309907993258e-01 6.239614485809552580e-01 1.307655482065895880e-01 8.530458750670916190e-01 4.801602070124768584e-01 8.168122189863546989e-02 3.793139622744635675e-01 1.496986997776840189e-01 7.129023878302899186e-01 6.830979237438047358e-01 7.635375943876505644e-01 1.824004963251233402e-01 5.764695848992339444e-01 8.865113248731604223e-01 5.784337085544002388e-01 9.700026628755119562e-01 7.318207347905059112e-01 3.851401393936705331e-01 1.774291851193399161e-01 9.763423229242296220e-01 +9.287178470949695175e-01 1.748282433617460718e-01 9.238531711586964734e-01 8.291274445125006443e-01 9.513259272578692416e-01 7.486316801165745494e-01 6.257378457524477300e-01 2.062711693536473101e-01 3.970721244184766130e-01 2.738325225026445597e-01 8.735038948299954642e-01 5.415282140033768066e-01 5.176317904298315398e-01 5.347036264518250093e-01 7.482056965410627258e-01 4.140672582824351800e-01 8.709067272363142376e-01 9.499605569181273079e-01 5.380266748336398619e-01 4.369252161707162241e-01 8.235722216228258397e-03 4.308187193646527691e-01 6.030581482859224129e-01 7.316831195156517920e-01 5.540499846834291420e-01 2.044203040111662872e-01 8.645251782981867583e-01 1.816095717570278545e-01 9.639119168018674966e-01 3.572031072322333634e-01 5.580226816834680248e-01 5.586629875016585478e-01 7.213854320902782780e-01 8.513998260042524580e-01 6.308764347277173723e-02 4.299855362100638567e-01 8.789303907444128150e-01 9.178850359236285783e-01 2.275205845091231582e-01 1.899395443939643213e-01 7.103070862773533944e-01 9.450015289553428399e-01 1.691856364522159595e-01 7.368719616877857925e-01 9.600189536623833231e-01 5.128846522932454244e-01 6.209162727118655578e-02 7.992250598838029907e-01 9.141050280518014937e-01 1.471297785256820978e-01 7.466162372930541524e-01 4.656107650642931084e-01 6.399324135161845728e-01 2.023617619481610230e-01 1.019104648900100996e-01 4.390693688536728700e-02 9.822620353006089600e-01 2.881951852926285529e-01 6.191575015960482098e-02 8.989580763251467932e-01 4.635958631890454429e-01 1.781973138114967270e-02 7.906911683818984571e-02 6.525270776225711167e-02 3.620583622807886925e-01 2.651673718940715796e-01 5.829372395929610651e-01 2.118159824373908595e-01 5.900287159143694504e-01 9.405929925178391215e-01 9.262415619063500971e-01 5.639581506302312475e-01 4.529556154689695635e-02 2.873819210518682166e-01 5.718545934306838996e-01 9.877670791317306742e-01 4.120364488714320927e-01 9.896078045634184583e-01 3.796586997026456523e-01 1.178183652203194098e-01 6.641068305236120795e-01 4.045960610587706618e-03 2.262690437428437340e-01 7.839938005832693957e-01 7.695391333937223743e-01 3.713918392552509884e-01 4.245533341514018399e-01 1.475072494020331915e-01 6.011975181419888514e-01 5.158174017998343741e-01 1.788706151398071764e-01 8.880707130134481986e-01 6.463351030474082659e-01 6.499920635615744624e-01 8.570273676455353318e-01 6.055019270899113515e-01 2.123561211054603159e-02 2.027688787664126968e-01 1.930834215328548487e-01 5.131906052747271518e-01 +2.599990881903107010e-01 6.767857524909899336e-01 7.188217446352963558e-01 3.037178903357997672e-01 4.252381412838680541e-01 4.070924411439535984e-02 8.426710493038247485e-02 8.301517457289483426e-01 8.254603255702420705e-01 7.258533909453509514e-01 9.958706809470796451e-01 1.323408451651194584e-01 8.523995455245143571e-01 2.572405385832454705e-02 4.715363690065482727e-01 7.920130365690022378e-01 7.613745641534582775e-01 5.108305991695683002e-01 7.908714335912382376e-01 4.641131983754837043e-01 3.112627109831845873e-01 4.218013908715474436e-01 3.291577909008427394e-01 2.538715054071232213e-01 1.362470842487485401e-01 2.716429790290709745e-01 1.485325814161112534e-01 4.514539027544387517e-01 6.900835128673067365e-01 7.793407072946112457e-02 5.938024345270752624e-01 1.497853829906865553e-01 5.399567982652856424e-01 1.419209916759478496e-03 7.719776132867679497e-01 3.130795105576239523e-01 6.670071611167494030e-01 8.900596881158256979e-01 8.011158503301568645e-01 7.089295605187424520e-01 4.671116382997058114e-01 6.682965170673403899e-01 6.524835265739736823e-02 5.454288420771494783e-01 7.751910790556310049e-01 8.192595541387335256e-01 3.098855848167891835e-01 3.689971355659119601e-01 8.666507475054133769e-01 2.749042684253171220e-01 3.566565602478318775e-01 4.838173174723044978e-01 1.032975933616413489e-01 5.063065339610417492e-02 5.791168455729079900e-01 3.573337411289496668e-01 6.714098909652352898e-01 2.917057662433912846e-01 2.654964332620638467e-01 7.171804039048814694e-01 3.314488637898249657e-01 5.230399837442840649e-01 6.866534136026025692e-02 1.252966394621071178e-01 5.349397882659551184e-01 2.841423847455760709e-01 4.158473635710734362e-01 7.197062989831272128e-01 5.123869045047864113e-01 8.675622821594339840e-01 8.097441845042540054e-01 7.317178252133832439e-01 3.300847596465853462e-01 5.922311859141077273e-01 8.852619511417836318e-02 2.673412917259408994e-01 6.878259052441990651e-01 3.223000927116328462e-01 8.859387123976615319e-01 5.722722388300067742e-01 8.254877606669521750e-01 5.705299682290687624e-01 7.046478734972855262e-01 1.316324413616759559e-01 3.056358395675535800e-01 2.396516834600909140e-01 2.041201422493257311e-01 1.610755140653103989e-01 1.617012564641111538e-01 4.449920510036902144e-01 2.731012972755201274e-01 7.826874666257994662e-01 5.193612375350010746e-01 8.688804522977213729e-01 3.742157602758655610e-02 6.649628920608219307e-01 5.978149424619171315e-01 5.345645500553952711e-01 9.443202650415919441e-01 6.105837075491723498e-01 +6.387761328141735584e-01 4.210087412162694109e-01 3.777306694964789324e-01 3.576349403292201634e-01 7.272699618880260619e-01 9.173392803607671731e-02 1.212535698300880593e-01 3.871229381194544183e-01 7.735150198351389284e-01 4.687200483013695962e-01 5.161778571874678923e-01 9.839646447226980674e-01 8.626932748911960713e-01 9.618485576577924245e-01 2.997996427525421170e-01 3.955404657388794654e-01 8.480126027102616870e-01 8.194992325050480808e-01 2.800213436873294492e-01 7.188391466620779324e-01 2.289766105875049584e-01 3.838547514028287644e-01 1.363553401061209369e-01 2.131328253542326134e-01 2.666779468144075960e-02 3.252883844200405994e-01 4.207860197469600605e-01 2.991365385037647595e-01 9.180779845534067229e-01 8.787338732192649937e-01 5.404510999105649471e-01 1.735493827761729335e-01 7.405224640747264386e-01 3.927355563629583157e-01 3.957109873399460298e-01 1.313029813325972128e-01 6.434498219738993274e-01 7.162213694578050127e-01 6.454998257494671821e-01 3.808124530008022424e-01 2.027201015737234435e-01 6.667632842770417900e-01 1.609491052365198405e-01 1.192413785409307536e-02 4.546773323526854815e-01 7.733541911050207940e-01 3.902525737195561284e-01 4.006023779897505133e-01 5.156517815815246930e-01 6.135685498584592112e-01 7.062153114980724844e-01 5.505858882117883324e-01 3.541308807182554919e-01 5.237151122342533771e-01 5.230649229131387745e-01 1.973541027697351957e-01 7.940327858595511712e-01 9.998588700623055603e-01 3.878271015153827994e-01 4.455006584967207139e-01 8.376414508056347907e-01 3.310833863524501597e-01 8.020469097392601832e-01 1.890327633084128989e-01 3.830289472395409511e-01 8.605040171046141051e-02 9.978185524023941433e-01 8.333890591892906263e-01 4.509013468741837061e-01 6.355778557686052599e-01 1.422515991097305088e-01 9.549891485963732940e-01 7.535776302868563148e-01 9.306005301880662106e-01 2.444330347211679522e-01 5.828218427569508142e-01 1.261938242968304591e-01 2.829188731405173352e-01 8.100246952078660190e-01 2.032739130996042975e-01 3.997268448390065565e-01 3.882777703107541667e-01 1.102505652624736765e-01 5.826634725328041498e-01 6.508734477956333864e-01 1.777287661702166011e-01 4.857051012052149286e-02 6.850537712379254351e-01 5.012281307761055071e-01 3.329154880061502286e-01 5.006261767216675374e-01 4.542081454976160115e-01 6.777801995399822532e-01 4.271303586474960445e-01 7.820470659692947413e-01 5.143462618485082904e-01 4.071273891563575997e-02 8.503383643856671226e-01 6.877485768345151795e-01 6.498843855014626580e-01 +5.539512747016193117e-01 6.329206647391879548e-01 2.798533500321682688e-01 4.825977295850051307e-01 7.625297023172977751e-01 9.081309101427640362e-01 4.124792086535029600e-01 3.647019658319609059e-01 7.529595202332928228e-02 3.072404010876803593e-01 7.890673660964639957e-01 4.079781478915127657e-01 1.440519120695739064e-01 2.538968953804546791e-01 1.595028243568367143e-01 9.066545851872198636e-02 6.367601114674349416e-01 7.622263643880089479e-02 3.015728236404162654e-01 2.424070469873378375e-01 5.711440390241000475e-01 5.717001375511508998e-01 2.237853674032181939e-01 7.112101625753678436e-01 4.321054197012103026e-01 2.505322169010260058e-02 5.877307077139551916e-01 4.415771174397812304e-01 3.766022855145171322e-01 9.803490652619811785e-01 1.229258314111529860e-01 8.108351868714478439e-01 8.558595456964329662e-01 2.168217533833206589e-01 2.034022719386595623e-01 8.687457137579783772e-01 9.013327195854559104e-01 8.156766512673154779e-01 2.717576187546973943e-01 1.756417893371479133e-01 7.555856977566548505e-01 6.708809351312817748e-01 8.998789237886926085e-01 1.936367585946979775e-01 7.949724635465026390e-01 3.164799312763589834e-01 5.493048513173155456e-01 1.608917269168268493e-01 3.048667492191803330e-01 5.599401537727016764e-01 5.779501360842279611e-01 1.296714605309662316e-01 9.160752328055997706e-01 8.058674476110374574e-01 4.385508937505578908e-01 9.212419718012100356e-01 2.249887451242467140e-01 6.283927745352599903e-01 3.778992451536005159e-01 3.571958698867505611e-03 7.276526470528231760e-01 9.051678673805297892e-01 8.465837072484881931e-01 4.548317505393462135e-02 3.189318261926020748e-01 4.446388607398673587e-01 4.292356336344156365e-01 4.203980977718795309e-01 4.698059253071955599e-01 6.151991200848159203e-01 8.479986139404802614e-01 9.870993262459623052e-01 3.164206525899861955e-01 6.464672171639846976e-01 8.508781429592480183e-01 4.733667503354813677e-01 8.076014176740163863e-01 6.671443255679101458e-01 6.639213267047979761e-01 3.681688930741919830e-01 4.679870252651611162e-01 1.790041740686979521e-01 8.446070273663058847e-01 3.350737544979878191e-01 6.600272349677447359e-01 4.356083218487936115e-01 7.995134167346013010e-01 9.083660261041469619e-01 9.743975306734570241e-01 8.144839650654719376e-01 6.865011984586443239e-01 1.709747281999153268e-01 8.534933687161740945e-01 9.494753729726415070e-01 8.140124992294850426e-01 8.936241255316055287e-01 9.087976860818796077e-01 9.030687493451383663e-02 4.025785149840914734e-01 9.592005611533803711e-01 +5.714058727476275523e-01 7.913573761505965365e-02 9.301773447377043036e-01 4.302822433307075256e-01 4.618892554175407783e-01 1.882471300213742760e-01 6.231472878215863487e-01 2.350437450940777717e-01 8.483410480771292894e-01 8.580803842040533036e-01 4.246398783388435350e-01 5.667321565946502604e-01 7.247417018955526480e-02 5.373984417482219333e-01 8.794242091541510931e-01 9.699025554453030162e-01 8.254197752548814160e-01 7.739723972867470492e-01 6.365819416181199841e-01 3.451230687021222820e-02 1.829102490094791644e-02 9.179618383026147965e-01 4.481667270072077214e-01 4.771270250445739380e-01 1.588469404953456454e-01 3.766332499200618633e-01 5.057026248713025751e-02 9.125900914275182352e-01 8.438133644246305076e-01 3.282972411719701222e-01 6.042003956122835584e-01 7.423456085393266290e-01 1.389012737541106546e-02 3.674754266702850991e-02 2.126646727703802586e-01 3.085666164246750887e-01 4.303440338750976757e-01 1.749037978865556342e-01 2.177699993322510519e-01 6.675614739991906355e-01 1.926533336347433512e-01 8.032010572660308600e-01 4.611412981769049679e-01 9.907201268457492827e-01 8.973785930837320235e-01 6.286342392657409128e-01 8.111266245859546364e-01 1.154230969025437092e-01 8.382880466301794176e-01 1.053753927827069115e-01 9.921712862234919328e-01 9.041662667920956631e-01 3.626267376021269362e-01 2.262225368932846425e-02 8.669003741626111204e-01 7.597054897704164089e-01 4.700318514995387442e-01 4.338185014241978665e-01 1.205425463362067573e-01 2.413879270602589111e-01 5.483334840461459025e-01 2.042653841254596925e-01 5.452588940366013270e-01 3.164646091706100339e-01 1.878958248945691301e-01 2.188622304737641855e-01 2.970982599823450698e-01 5.952148400199362976e-01 9.614251220149501176e-01 5.446813400697393392e-01 5.900748097930779146e-01 2.653062526715309621e-01 5.459933097767216692e-01 3.174185404661935550e-01 1.412133354129242457e-01 1.487441669790685594e-01 3.953776242211952674e-01 5.274261039692862418e-01 1.756132307607755072e-01 4.481942852746899630e-01 6.390660088765629521e-01 2.860380430081067571e-01 5.866902519902850166e-03 3.026687645174785946e-02 1.952533570196290924e-01 2.154769096186736066e-01 8.920573593276575064e-01 5.644513191915436767e-01 5.551464696654353492e-01 4.378199413349500579e-01 8.685737643974280608e-01 7.493934764293597173e-02 9.556749726352036234e-01 6.386433482536227890e-01 8.714694524097754691e-02 1.722786161701279628e-01 6.526867532768643176e-01 8.950304705281527662e-01 6.158198776753203152e-01 9.587176904005377809e-01 +7.705718397401561948e-01 3.165816092999733655e-01 4.334200859975760878e-01 8.639807015515663657e-01 5.576514209532534849e-03 2.456745447057938625e-01 1.664686313299922338e-01 9.637084729617834133e-01 1.083448720752323569e-01 1.865218070380464388e-01 3.730358890475884426e-01 5.015351872138350542e-01 7.420710795841709562e-01 4.919420674769692248e-01 3.426558201886464872e-02 8.669984854934246199e-01 2.204243734202966376e-01 4.109792246853891662e-01 4.361732572946559472e-01 6.819306998053020763e-02 9.986304248057148447e-01 4.119289455392274313e-01 8.533050041845835487e-01 3.416914861912183632e-01 6.522191951039880697e-01 4.162803668786793088e-01 9.051674379917418189e-02 4.552378661306888397e-02 2.122677193466918633e-01 7.461518531655018105e-01 4.654688019259497489e-01 7.877564083548750373e-01 4.518328005682387127e-01 7.173857464237374248e-01 6.940056370290903498e-02 2.804574410412373764e-01 6.095681113112718652e-01 3.680596478602831123e-01 1.814569150719304025e-01 6.505055517979729807e-01 2.759585245701871026e-01 1.429501104786028431e-01 7.813891153083207808e-02 8.925314279991185540e-01 6.692056941902108091e-01 1.915141341107173822e-01 5.750233129581091562e-01 2.051961006251528108e-01 3.849013692629975614e-01 9.503788222043518807e-01 7.690419386411734282e-01 9.978147530014782607e-01 1.719584162437415298e-01 4.890758882401113894e-01 7.195660736040896399e-01 2.485818040997200828e-01 9.706486601870933928e-01 5.182604282071262558e-01 8.082072245463804983e-01 4.889961284821118248e-01 8.042893959057633158e-01 3.200685313413229593e-01 8.983245016887355661e-01 2.811495336955205371e-01 3.986095833814048417e-01 8.607229214132059436e-01 4.827620119717191960e-01 6.715610252037491623e-01 9.330824374137768329e-01 7.537710530085762750e-01 9.840804224010484269e-01 2.319352541177217564e-01 9.569114943157627229e-01 5.821928104654411351e-01 6.700479524814679788e-01 5.663434680086896211e-01 8.851091082101365526e-01 6.800562815862243315e-01 3.578475213752868589e-01 2.900164669281133367e-01 8.379170683569914235e-02 9.929972839740475177e-02 5.946248553621906741e-01 1.991332889320840405e-01 8.115065723822508792e-01 2.023388190440008616e-01 4.056545651129230823e-01 2.966825350250481552e-01 7.457176343507545546e-01 9.856015771246517954e-01 2.264338016147812160e-01 8.366528670045663141e-01 6.116829813603242849e-01 2.605933184296719274e-01 5.765962146558850643e-01 5.064075092266390188e-01 5.499615769589756287e-01 9.240234698632640020e-01 7.169900155229913530e-02 3.544181364560751168e-01 +8.154844535553099627e-01 4.797965609394789777e-01 7.476703385713100447e-01 9.086708404761600910e-01 3.191752505450355937e-01 7.611128630021511965e-01 6.246790343299296611e-01 1.942001426217137006e-01 2.789860414631386565e-01 3.236359785042408621e-02 3.178191288741717413e-01 8.372264298357038337e-01 8.872692914664047636e-01 9.589758852077276963e-01 3.123722260380168425e-01 8.980164015338999439e-01 7.260784140459818348e-01 6.567013512265649222e-01 1.028743505926521529e-01 6.821705410750319443e-01 6.889838995316139858e-01 5.587525493094736007e-02 6.921487028366646310e-01 3.616312929861494885e-01 1.673758008792780583e-01 6.626504595920326146e-01 9.125680913222075086e-01 1.424077784972291871e-01 6.508496429060767197e-01 6.615417385775157477e-01 9.654167310675311198e-01 5.536662974550183858e-01 7.092622144968085962e-03 6.694595400455760625e-01 1.828533619119211417e-01 3.421514408394116247e-01 1.242580151818144518e-01 9.888774797458224075e-01 9.777955172739735135e-01 4.271370765628749178e-01 1.211608384809655936e-01 1.580132417172936954e-01 3.242705395708289640e-01 3.268994391754735940e-01 5.213767653645562383e-03 4.475169480357120699e-01 9.593245219293577986e-01 6.994304536782350867e-01 7.063863152769014331e-01 8.381620829497931080e-01 2.760441799736219615e-01 3.755200946645842475e-01 3.627729621737311172e-01 9.518310606719182498e-01 3.577273025276901386e-01 3.991159901003488164e-01 4.187060513068554535e-01 7.422605403637314581e-01 6.697944269780702342e-01 6.020599837037767799e-01 1.571185850817550245e-01 7.519860911185742847e-01 6.635775704496444938e-01 9.487848173531471252e-01 7.900030232338028924e-01 4.143783957270819052e-01 5.618429740858444932e-01 3.737804619062014000e-01 6.179941187802344693e-01 6.553638605616040058e-01 1.009709416658691739e-01 4.935037098582963910e-01 5.485489972455533936e-01 1.024147956480448984e-01 1.195764707555347917e-01 4.910516327810896531e-01 3.551185778630389089e-01 3.857601645798814927e-01 2.074975219600547760e-01 2.084038664460790002e-01 5.268616653491025037e-01 6.948014877618717833e-01 6.179744044618615817e-01 7.063658085955483168e-01 7.925757227686872630e-01 6.199016959584816577e-01 1.163676037434490107e-01 7.425752264755586252e-01 5.403115665133301215e-01 2.546191951391015840e-01 6.961300925345208501e-01 4.003013072125547467e-01 5.906120962720950995e-02 5.879915846330325824e-01 1.213602408288709800e-01 3.801780679842765576e-01 1.731477742402802722e-01 4.624568816669496485e-01 3.304453744619206823e-01 8.810445876116090869e-02 +5.140190515373614932e-01 1.419225260054487459e-01 7.777845802285945354e-01 3.327562899409282071e-01 8.916875699762913943e-01 7.212852862736146564e-01 5.727327199433507321e-01 5.897820225918504189e-01 7.318614954542906892e-01 7.393985144455500480e-01 4.531340740296823100e-01 9.903061584426188224e-01 4.213350938331624773e-01 4.542342471963995987e-01 9.788786426453045530e-01 1.881707000343846303e-02 8.005433413647761176e-01 1.523502822273363755e-01 5.630164732287495921e-01 5.946603842470724599e-01 1.225547698678740582e-01 1.531136594724622491e-01 8.157973612638946825e-02 2.752046015644330490e-01 6.809045821946161370e-01 6.455289724528190387e-01 3.830356726830793646e-01 4.446144649678575034e-01 4.969038423960672191e-01 5.497873820641221432e-01 9.471879627821714331e-01 5.933046675329255448e-01 4.099233758501530378e-02 5.790409810134594659e-01 9.546095885251496549e-01 2.608616052375664074e-01 6.910160339170060562e-01 1.293709850476291168e-01 6.407264616302255078e-03 6.186037089828009261e-01 5.537861302543241049e-01 3.527421038298221845e-01 8.033232052121624944e-01 8.128114152830284711e-01 8.319982582278713235e-01 5.939566376046836460e-01 2.291090283499520597e-01 5.438101817725821130e-01 6.881146379117278888e-01 2.421968586304659166e-01 5.874047918543783275e-01 6.210102709484541794e-01 7.041387566450251212e-01 6.959223476278774134e-01 9.133877300988062498e-01 9.230647706207778525e-01 6.856884219815310155e-01 6.997988808693775820e-01 6.177944932528769417e-01 5.512902545683161515e-01 5.818280341729102911e-01 6.538267999985679646e-01 6.946673485935980219e-01 4.817938258357623571e-02 9.352008817207906333e-01 4.774162142215661042e-01 5.768063588692976529e-01 4.589648891483899540e-02 7.998946815651652997e-01 4.434260476954369201e-01 9.850053510925722566e-01 6.648626681529369309e-01 4.606293826856903140e-01 3.309042418210563774e-01 1.438901922508034614e-01 7.986559119276418484e-01 7.037818421334554042e-01 3.605119534240813772e-01 3.785959549258922641e-01 9.562491516841659100e-01 4.997955143590974147e-01 1.029540300938682762e-01 1.819017177001992502e-01 3.665425750262368831e-01 1.688063588370778412e-01 7.030735208313992901e-01 8.922375654244527610e-01 1.055706412056253152e-01 2.664739907746691561e-01 9.906029568647586325e-01 6.043845090140997911e-03 3.495786295043534775e-01 5.989441999519146131e-01 6.776147193866479679e-01 7.012991789852640601e-01 1.825838783477321536e-01 7.612293578749116385e-01 1.564769891240175292e-01 2.762157292905387251e-01 7.641900040015234818e-01 +4.746013333880729768e-01 7.609202966712714788e-01 2.537820854162747830e-01 1.709362234877408460e-01 1.886635378734374813e-01 2.439567014093724229e-02 7.640304718272151741e-01 3.483216170435471382e-01 7.744289278738043514e-01 4.190437573644867353e-01 5.319091476394965934e-02 8.580130976087452233e-01 6.259446446786639529e-01 8.793213970773006150e-01 2.441023074890465994e-01 7.753405549489799098e-01 8.760187573193888300e-01 5.946480724009295393e-02 2.873093046571124631e-01 8.710837851946537924e-01 9.103181731924696596e-01 6.534637257615111272e-01 4.128420398577182793e-01 4.905858108576378607e-01 6.178275806701372108e-02 6.368043900016381320e-01 2.865296941219959148e-01 6.371773028539067241e-01 4.924322796636745325e-01 1.709313290387282080e-01 1.856892551689268700e-01 9.592782603102242289e-01 5.402593764193130976e-02 7.287312244390512506e-01 5.679467572000697073e-01 6.255587794305905724e-02 3.069660218141317953e-01 1.089960430557104232e-01 5.550748245336984965e-01 2.555948886689661803e-01 4.140925514039996980e-01 1.180376445052062628e-01 8.832322629884041820e-01 7.784546946701487169e-02 3.177678935473182698e-01 6.681804863429485764e-02 7.047099396645268854e-01 4.133897376851528582e-01 5.600656990480865627e-01 3.883995683475501837e-01 4.459430113152932362e-01 4.214077227574740681e-01 4.763369230200156235e-01 2.701480661168440545e-01 4.296286564389811824e-01 9.601402258758658936e-01 6.326999441846863359e-01 2.442086919688498670e-01 8.407708423957936938e-01 3.626867985638081437e-01 3.641441713291436733e-01 7.932397565989488530e-01 8.902073520619256941e-01 1.929173010337000838e-01 7.309376779324568973e-01 7.305852858337777977e-01 6.510197444582447313e-01 9.512661608643838695e-01 8.461467164366111016e-01 9.245490147941206605e-01 2.658844813385705663e-01 9.538758859344749208e-01 8.215517204998477041e-01 8.217795540390903097e-01 7.569662091300560780e-01 6.262685322871274218e-01 5.597770510574888725e-01 8.155720175123675197e-01 8.545688745180864965e-01 8.986051518529034610e-01 2.477911506572628708e-01 8.462580108996445860e-01 6.065941220995090255e-01 6.500490804973033665e-01 1.120463882674053169e-01 9.299049132942927010e-02 1.388364074229719858e-02 5.901199124540731367e-01 2.795110110544174464e-02 1.644097083463245124e-01 5.341029647603202646e-01 5.276816677181681570e-01 5.439849107754858304e-01 5.371677986392331405e-02 4.515163125788429488e-01 5.036243367087100964e-01 5.721818679625961801e-01 5.271368612400184617e-03 7.720961020546839304e-01 9.015383457479009266e-01 +8.301526916287945701e-01 8.704609696144033348e-01 2.955689129581380303e-01 1.762209253489944727e-01 2.698172933050072553e-01 1.138095349991521399e-01 4.092588531860634760e-01 8.202978121681584467e-01 2.822241377079557356e-01 6.117376205659387223e-01 7.169923068016897938e-01 9.310256256264415331e-02 3.989664052931106708e-01 1.651874953308862803e-02 7.890202597932294282e-02 9.068686774810821305e-01 5.203866694486933842e-01 4.297748572844445336e-01 5.208786995443430712e-01 2.163224881365530816e-01 7.274307306357226111e-01 1.675784956180090823e-01 5.969822786565782691e-01 8.959750832846602453e-02 1.253794151891943764e-01 5.352628522116801291e-01 2.562706125890066300e-01 6.030433202137867044e-01 8.330717547440393833e-01 9.603613683422040914e-02 7.569714244468559450e-01 3.184801677796517128e-01 1.667069341164499896e-01 3.132470247801235619e-01 6.417752836394801097e-01 6.433909425912354152e-02 4.056860213146201710e-01 3.166772891331335327e-01 9.574059746098845247e-01 1.492907964460536974e-01 8.311513764927496162e-01 6.652928354977717396e-01 2.396804722185036374e-01 5.812361618600220270e-01 9.724228681350225445e-01 2.853983236378453414e-01 5.337719354896472979e-01 6.779446197712412081e-01 5.485102006140557540e-01 9.010109155962182648e-01 5.724439967467525037e-01 5.965540527411405947e-01 1.598667990086183321e-01 1.363934512727023041e-01 5.327536522697270405e-01 4.123866715061276222e-01 4.617251396918636841e-01 6.935944951381239898e-01 4.300337419593377453e-01 1.892407993760835128e-01 1.666936825594794724e-01 4.625634184864588772e-01 4.805197636774838355e-02 7.003542850133466224e-01 2.130226006716084974e-03 8.678863343041013367e-01 4.874478520451258623e-01 7.043560228741558848e-01 6.317719270475393722e-01 5.372392256296196766e-01 2.982649812986511995e-01 1.272558612133412037e-01 2.467337555730741983e-01 6.546893200021091097e-01 6.291921159383098150e-01 8.505920470407707379e-01 4.046520490181828578e-01 3.875732096593392795e-01 8.551517214319142024e-01 4.152602284179877090e-01 9.587779137989138611e-01 6.977437468944928112e-01 3.240620775541913634e-02 4.025873770391376061e-01 5.485549335619134270e-01 7.146066156157020455e-01 3.012702534568838519e-01 3.526414480395153594e-01 3.309707144485515284e-01 4.315687014460974913e-01 6.641934530697197747e-01 2.172886798352815507e-01 4.807480925564590057e-01 5.006795397998469177e-01 5.818100901154411586e-01 2.107716091585690732e-01 6.606606051140029301e-01 9.317629042790995797e-01 9.840326342340242061e-01 5.752000964817773898e-01 +9.843444595454536872e-01 1.339523968066913540e-02 6.082172659959028671e-03 7.828244785439336662e-01 5.069653703872761819e-01 2.804896494365415327e-01 2.112385836660957139e-02 6.016479440778699228e-02 7.457477935084961818e-01 3.445503949245375397e-01 4.063494277166557200e-01 8.630275274433116817e-01 5.948396018456146850e-01 1.400867933474212457e-01 6.997522422654076646e-01 5.766519767930851081e-01 5.419976500582250889e-01 7.474121304089603735e-01 2.951600193008566686e-01 7.980170422334191827e-01 1.829036799578199757e-01 6.317636496261300749e-01 2.812612231140887431e-02 5.464747656105657381e-01 3.909873503320924204e-01 4.940850205957293406e-01 8.157850130814222611e-01 5.111092739445756150e-01 9.336823640685747439e-01 7.157105167170837445e-01 7.778989455994214097e-01 1.398722535910470466e-01 5.642653936300449091e-01 3.218717164845980028e-01 9.717427501967056402e-01 3.665791984428700134e-01 3.874321311211759156e-02 9.437600858738082188e-02 5.679526822961932231e-01 5.141385991358327079e-01 7.497840799582222715e-02 5.736515309094968318e-01 1.928132849879083954e-01 6.924244068001785823e-01 1.748389677952593146e-01 4.469577663506929532e-01 1.738527450963387455e-01 7.195287763517190793e-01 8.861150811892871682e-01 1.058443750714600506e-01 1.941789362229970894e-01 9.188374820700584422e-02 7.706736301449305104e-01 6.718642548609364828e-01 5.981029087121966237e-01 4.832880127232569434e-01 3.073688779938709148e-01 5.156312334804930009e-01 1.777418420119527553e-01 8.885462205165685079e-01 4.486254681289014723e-02 1.345398129556140132e-01 7.467627984379916484e-01 4.384565546058830643e-01 7.217750080760946263e-01 3.949550352625393890e-01 4.307950907642028593e-01 6.087680934849041270e-01 3.294516167246774874e-01 1.316682090209408962e-01 1.824857738754404046e-01 5.332379826483617524e-01 3.567136182864261151e-02 1.976220743086236631e-01 5.849349042822560296e-01 1.133174406357483344e-01 7.711522754393199675e-01 8.557306786807005183e-01 3.038353471344266143e-01 4.422747047768413875e-01 2.537160404215925702e-01 2.372714099723788328e-01 5.906462765375103396e-01 4.849909323133470007e-01 2.692576210504484813e-01 4.540849506602829821e-01 9.664935719107857759e-01 2.044371576459835804e-01 4.505417469690352616e-01 7.110722322201217249e-01 3.051357995214963870e-01 8.978937034341526457e-01 6.090501112506481185e-01 6.595415779178889215e-01 6.565426836745864581e-01 6.565608489824376059e-01 2.679102664248229626e-01 3.819533138204529443e-01 6.609794961162380744e-01 2.289558446859882856e-01 +9.274935298374649140e-01 1.174096651033715855e-01 3.030761852629033637e-01 1.605508209527917174e-01 9.601854834873225775e-01 4.341959513718630648e-01 6.320768160802121560e-01 4.213429090614078110e-01 3.695553969042019160e-01 5.965457437116089556e-01 3.520335041155040479e-01 7.702703502247409961e-01 8.571112772962534709e-01 7.904077282532658844e-01 2.247339318352784554e-01 6.823720204503556097e-01 5.883435710582129996e-02 6.786037033312407596e-01 9.721137137641507886e-01 2.042576970668320557e-01 8.394085754806240862e-01 7.433082729552867862e-01 4.072614159870893147e-01 7.451483066617257123e-01 1.699472962789440045e-01 1.753052015584344314e-01 2.255269204788400428e-01 7.794755643807432799e-01 8.407732260470973662e-01 9.301182862857163558e-01 3.701995309382508648e-01 4.481909027604019657e-01 1.261889085033987001e-01 5.600591735875248833e-01 8.244692493969552061e-01 8.969188061645969601e-01 4.802217973423368313e-01 3.556164122713412201e-02 3.393317823164623270e-01 2.491242957582864292e-01 9.863253789366602797e-01 5.585415885291432625e-01 3.702350606362231344e-01 6.766101432620400535e-01 6.999259389475386284e-01 6.676108316872160220e-01 7.870681827507105544e-01 8.746765411259082024e-01 9.125268371282718727e-01 6.638849997061806452e-01 3.253268113800632522e-01 7.968625619248901337e-01 7.584122525443606211e-01 9.028886850768532701e-01 5.381622293189292083e-02 8.097562873320752752e-01 7.092942088208666895e-01 9.915538877968065323e-01 4.319294903327922652e-01 4.307127933969153721e-01 2.768507739641907772e-01 8.076253078288621046e-01 2.569233696442670967e-01 7.595893829724666979e-01 5.768081727897018673e-01 2.537536777625452045e-01 8.874419624636734616e-01 5.091705681832693342e-01 4.811826624992353585e-01 2.794462461940371290e-01 3.846927898276129021e-01 5.129562951959991679e-01 8.515004062224775794e-01 7.103144978683579858e-01 9.526388607201888847e-01 2.367905569592337889e-01 9.137336039323161740e-01 5.722969943101696710e-02 2.019723935481291255e-01 3.098764675203513619e-02 1.121146613918624357e-01 9.937693067724532314e-01 8.476717958861412772e-02 2.059652110343795917e-01 2.139791918759540446e-01 9.137860316709250919e-01 9.530862653366889425e-03 2.027843281683039400e-03 2.506229951837134484e-01 6.244523528392044165e-01 5.523937894075592325e-01 3.712168074031840792e-01 4.218847794299319665e-01 4.827576239387890711e-01 5.244634168840578425e-01 5.182241092381567604e-01 3.308639956263292881e-03 9.370528021570383448e-01 4.694554875029453012e-01 4.950447554541728135e-01 +1.525818111800841814e-01 4.708012184002630107e-02 3.899035965341954846e-01 3.928304521031263929e-01 5.602286661727436945e-01 9.738256658043862313e-01 9.404465779766183475e-01 5.750862754958349088e-01 9.547546956257608741e-01 2.750275291553152535e-01 1.682773435862793265e-01 5.865928471016079726e-04 8.543378154943809255e-01 3.547649971465383079e-01 5.058056647397523031e-01 9.116332486700751137e-02 7.534666421106954726e-01 3.082429494433007733e-01 4.527145111847344916e-01 5.456680635225539255e-01 2.504131242494785914e-01 2.509240770568589296e-01 3.949236999582302898e-01 8.782959620323271821e-03 2.474641132111736752e-01 8.229417958971670943e-01 3.444225768479134420e-01 4.000027489436257522e-01 4.247741954177396417e-01 2.497745404169693373e-02 4.325768602588443423e-01 7.336592463477830117e-01 7.667663267650381975e-02 4.179022553581047683e-01 8.745172741480690126e-01 9.417705509525042817e-02 2.807522782799587446e-01 8.212710101351362590e-01 2.211181944001613386e-01 4.319929503523877168e-01 1.858636923768219873e-02 6.737037795085246694e-01 7.997187114913413275e-01 2.976552505976116647e-01 3.272347030789168887e-01 5.550935453236346406e-01 9.224109746648162522e-01 3.192827922106745708e-01 3.500098324549234530e-01 7.821988386980260888e-01 4.478417135239194380e-01 1.580956175222456572e-01 5.300807813550156844e-01 5.806154798468634581e-01 9.456842911054151868e-01 7.688127895655872956e-01 8.456527833650537840e-01 1.784229089865225770e-01 8.114517450321339087e-01 8.062506298824222428e-01 2.113482500442499523e-01 2.629226789210241666e-01 6.478686221690072022e-01 6.006672861605766300e-02 7.013679843242253131e-01 8.784753961212666828e-01 3.487138165323044880e-02 4.928426758517070461e-01 5.976224683315064512e-01 7.629063997052759616e-01 2.761721278953045422e-01 7.240740503283805696e-01 6.131065729985127888e-01 1.630885615792579957e-01 8.473783868551159060e-01 8.347614542399306448e-02 8.137265626844719657e-01 8.512508664918938539e-01 2.777097816703766320e-01 1.729154355214796990e-01 2.203382750835449766e-01 6.134780912629795857e-01 3.524352564238901753e-01 5.370314860129862256e-01 8.013986113284543578e-02 2.555842138998117852e-01 6.553915758947851389e-01 9.679125599178584061e-01 2.549566319678178150e-01 4.008180804370896633e-01 9.145789951670967310e-01 2.787926039163850511e-01 8.599455912576436933e-02 9.637558000691170967e-02 8.274101203974880692e-01 1.803747268179315411e-01 2.175735407836230095e-01 7.825994939720237742e-01 7.928519890958951599e-02 8.707949373106749213e-01 +6.398420210047787160e-01 5.739624494012524059e-01 3.359672805578653998e-01 1.130399363175038641e-02 3.349439685346782269e-01 2.315484030880912147e-01 4.575228302577399875e-01 1.149494135594463229e-01 2.888244352925943836e-01 3.625470995156252485e-01 3.795973190611611203e-01 6.567047810450010736e-01 1.484039742710284715e-01 9.273251916560719676e-01 4.334256728976307871e-01 6.734771102219323513e-01 9.125080197222198430e-01 4.974393931097168542e-01 8.301481563280355136e-01 4.526450714147856047e-01 2.414236092573898151e-01 8.070129698367667359e-02 7.260400697427102923e-01 1.396509691839398215e-02 2.496450588391967429e-01 4.335741205447194435e-01 3.089314419194891803e-01 9.543503534526003307e-01 5.457977547458532364e-01 3.139663643587058406e-01 5.034762326753475792e-01 4.756788330475764104e-01 6.849334942793482428e-01 3.880666613022351052e-01 6.483446580176778218e-01 5.217503801099343530e-01 5.371145824070304720e-01 3.121260159429154468e-01 8.314121854062171968e-01 4.538695969561833410e-01 8.598896961203845724e-01 9.961993522734106099e-01 8.865717795946430613e-01 7.828987966783660379e-01 3.412415531643435695e-01 7.421170530151157685e-01 4.484104178639959359e-01 6.793217012099640462e-01 3.756179958191659951e-01 7.821287098222597933e-01 6.227726265188193722e-02 8.552983413221663112e-01 4.824668768009222619e-01 2.241531065858231031e-01 4.939536577599041856e-01 5.129566641128722182e-01 1.057984177672518511e-01 9.541452507300716146e-01 3.396646181755047511e-01 7.452588103611947901e-01 5.315559265659929311e-01 5.493475179850665358e-01 5.214824278139198466e-01 5.150075718147916204e-01 1.196075368500321146e-01 9.035665331176232495e-01 7.522653903639873185e-01 6.638708679914825384e-01 5.584174553800479446e-01 5.015819402508836511e-01 5.507698483308445248e-01 5.978677577011723976e-01 8.450418028759657529e-01 3.266677322748618995e-01 1.321610045897971819e-01 2.394354042746985600e-01 2.723972163557076831e-01 5.523301747352814539e-01 5.518043850608547185e-01 5.283968096837132755e-02 8.192733312104071297e-01 2.277106024970321219e-02 1.414998099027269252e-01 6.517281615256080851e-01 1.811694734825117781e-01 9.472370614713256920e-01 5.454497319021770485e-01 1.364119913158231556e-01 8.446142008509562871e-01 7.671725984742419069e-01 2.461161648406858804e-01 1.421724627107351369e-01 6.290652581179481118e-01 7.094144689448004248e-01 4.419656923472803367e-02 6.614741876652251440e-01 8.712193265403500586e-02 4.734931280852430202e-01 5.382037050480286133e-01 1.396459758005891283e-01 +9.709329844415439670e-01 8.998575745276288229e-01 9.151313462895852568e-01 6.920489275523904471e-01 2.892231405199537919e-01 6.750679746268205550e-01 5.515642485826798280e-01 1.065253097812824956e-01 2.957026803465776510e-01 8.937347659632134400e-01 9.800016515925590310e-01 7.745900896182087436e-01 1.570977683146633774e-01 1.482028765821026273e-01 2.111147779712029271e-01 9.683759902485811200e-01 6.550951580826911425e-01 8.728324682592377703e-01 5.044803166579884257e-01 8.285704754811143991e-01 1.693574499337324735e-02 6.032669995180495182e-02 1.687026879086964692e-01 7.701554026145973619e-01 1.429888016593102718e-01 5.881172815379975827e-02 9.704206919487038396e-01 4.450807650730836951e-01 1.597445784258376689e-01 9.849229394397314152e-01 4.220083573536804744e-01 9.357693600374825671e-01 2.313199262338369033e-01 4.556443403861323294e-01 2.590791012828855822e-01 8.438664994487065085e-01 5.519045677502344427e-01 4.702170125676508050e-01 6.814723205638187897e-01 7.418295483665861001e-01 3.684921032028853904e-01 1.501895844844561845e-01 4.214513377519605308e-01 8.600279963652578408e-01 6.625616611189292238e-01 5.200151456470966105e-01 7.881072743086801058e-01 2.771703241081423519e-01 9.034135930616548071e-01 5.848441705791300738e-01 8.341698181274771473e-01 1.966638677318299777e-01 7.059747894371543042e-01 7.013854316067694716e-01 1.828430942760242983e-01 4.745548949934464966e-01 6.306422394641082452e-01 7.760751707194470939e-01 9.813187212598396547e-01 2.293595795266353266e-01 7.749261876107090830e-01 2.384106107787011819e-01 9.721209688979495223e-01 2.715569353686980714e-01 2.915573577694993146e-01 3.579601509630966349e-01 3.085697512342830962e-01 4.070219981627976047e-01 1.989632411372218579e-01 7.330003339460906542e-01 5.397259604481572381e-01 6.931009942216573849e-01 1.385457419653816080e-01 1.140339999976658358e-01 3.980752590866034613e-01 9.471822621683767540e-01 5.476643721405823895e-01 6.824131903515884279e-02 5.844099130744569992e-01 2.346881692012994236e-01 9.436439228519653000e-01 4.855518260479008141e-02 8.157036123302675579e-01 1.169761256455048581e-01 5.532962903488753970e-01 1.100965596251435308e-01 9.789490602992410029e-01 8.433487462016989733e-01 1.272410782852178013e-01 2.885715258680641160e-01 7.990943955388217779e-01 1.565305358979097727e-01 9.160846960406943129e-02 8.521842244411678147e-01 4.474243106736998099e-01 3.843945818845087015e-01 4.710645906071458944e-01 2.398348154123419729e-01 6.435351435258193087e-01 7.656897921129046658e-01 +4.894328120406804539e-01 7.881019629214267574e-01 6.974585354155089512e-01 2.023858939857701156e-01 1.660984914264745926e-01 4.854517801734643534e-01 2.789848572630315715e-01 2.311636522410289718e-01 9.821076233980715608e-01 1.220641257408076052e-01 2.614036146663852866e-01 7.657560715165320220e-01 3.968360577545695378e-01 4.566023622802184434e-02 1.049701948619241598e-02 9.281162949127452766e-01 4.490137965769909201e-01 2.095846458383606725e-01 9.195504656719085679e-01 9.683515436855471004e-01 9.800174878114910060e-01 5.517610861380117804e-01 6.711570559348770670e-01 5.125258050287277989e-01 2.105581493613526423e-01 8.281813206544574868e-01 4.964783994807770995e-01 7.284974208756571645e-01 1.320629592816270348e-01 6.652194518096135045e-01 9.430156297917950958e-01 7.477263137894260003e-01 2.054087806450300979e-01 4.248209124837907247e-01 7.657518666018259257e-02 1.031614100713345028e-01 4.122242287567021712e-01 4.919658859336810686e-01 3.752650167259050651e-01 4.175771429986683270e-01 6.131376293448997927e-01 5.463797405837259591e-01 3.119918548921774004e-01 6.331762507678504459e-01 5.484632429281035559e-01 6.815448032785871302e-01 8.065695507425107991e-02 8.720129122297424207e-01 8.318188557125294480e-03 2.199323537180564170e-02 8.933872719887463454e-01 1.953120287872067706e-02 2.478721941404590234e-01 5.994061179859005994e-01 6.588362611693047155e-01 6.332808851020984564e-01 3.823849348043323326e-01 5.111091324899629251e-01 7.034808459110406531e-01 4.347681568463539481e-01 4.316973576672314961e-01 9.620411080123215664e-01 6.247837467655984467e-01 8.196961678222113301e-01 5.574601810887074294e-01 8.800635018469276094e-01 8.772255241161972528e-01 5.075275933138404527e-01 8.022583187266906224e-01 2.320670802521890286e-01 1.165626629103270195e-01 4.623759662685936744e-01 7.938327000737943617e-02 7.986374689793115378e-01 6.728842751465858862e-01 8.133909095059230765e-01 1.202639390769081329e-01 1.052937257108800262e-01 8.717600467040409473e-02 2.163819956545051104e-01 6.596483385763984852e-01 1.202843170392309258e-02 1.538789195854695091e-01 3.120247727263308901e-01 3.408168327248596308e-01 3.241861797851740556e-01 3.637074533655986208e-01 1.533669345890729119e-01 4.455921334699539660e-01 5.619140093874478437e-01 1.881731359879111887e-01 9.416670800570559052e-01 1.740018593664415247e-01 7.030242331869680505e-01 5.922055553954849172e-01 9.326211623391688077e-01 6.608322881013140027e-01 7.009721551241574478e-01 1.079126054675583202e-01 6.158176671761947940e-01 +5.185079639625639336e-01 9.613742991518259284e-01 5.555312825626229634e-01 2.647628827924735084e-01 6.003697207460141350e-01 5.392112376769145898e-01 6.781186965667050925e-01 9.908971748181496508e-01 4.124155872095397468e-01 9.814941401724619485e-02 2.684237785531295994e-02 1.774652505962848181e-01 1.707589529595294753e-01 4.640932098465534450e-01 2.882179883914587348e-01 7.276822905806898945e-01 6.145789546745269449e-01 1.100959863917608805e-01 6.798859723042820491e-01 9.096984032948918220e-01 3.971368455178179158e-01 2.959494950971321980e-01 3.742088799298171065e-02 1.960739526210202310e-01 7.536102695342027369e-01 6.680915510628401277e-01 4.136507204312135366e-01 3.613996339406737590e-01 3.605422038261204554e-01 7.098503555159476619e-01 8.093719147087541366e-01 6.344097009128880638e-01 3.990082448083617228e-01 2.805918009906902544e-01 7.078488167363675698e-01 9.969917259866583059e-01 9.442054998992396309e-01 1.329075240769165278e-01 6.810681350588387861e-02 8.503491437913293094e-01 8.347117439165431252e-01 2.381858201903953587e-01 7.884260706938626129e-01 7.109907917419661105e-01 6.390916681983604963e-02 6.174365227062991179e-01 5.085733343630816083e-01 1.716846139694149231e-01 9.065664924270055991e-02 5.625330757196970177e-01 3.539663480209681579e-01 8.937139525947165319e-01 3.981380511900556307e-02 7.403597927449541150e-01 3.803872284089604427e-02 6.729519695709765825e-01 5.306080908840085097e-01 2.091237680402112664e-01 5.902903662907804661e-01 2.094778612095482551e-01 7.323447855684165342e-01 3.644574495843493356e-01 2.006215478057034041e-01 3.737617545555030896e-01 5.253471759602216240e-01 4.287889547869583318e-01 7.086098806190446187e-01 4.510792335515292351e-01 6.383187180169215269e-01 8.779355722397681472e-01 4.221338898667141848e-01 6.375840144651815367e-01 8.683057298299173832e-01 6.093730356952498095e-01 9.297141161056151626e-01 7.770838342807246946e-01 6.549661287008456956e-02 2.835060738158660110e-01 4.474138867374952699e-01 8.530336387421445510e-01 3.160209657891883683e-01 8.301538680518486535e-01 6.646903097549101691e-01 7.187130118106234145e-01 1.651862041735395747e-01 9.578252676762609719e-01 6.490273812885494209e-02 9.777273484666341163e-01 8.930729829254262508e-01 9.851054752118463265e-01 4.094323402286751401e-01 1.139176240124337713e-01 7.612865863899589414e-01 2.266379302491570158e-01 6.998882496157835531e-01 9.945043379099228753e-01 7.111578056749194854e-01 7.806190603886183910e-01 3.410170920712443099e-01 9.446084168886822452e-01 +5.015172758330755931e-01 5.569527971282052237e-01 1.122406928736449094e-01 8.960352822124777461e-01 6.049568585854003810e-02 1.202196001338627918e-01 1.870314295763603196e-01 9.017590029396971296e-01 3.597904628087450485e-01 2.130941062746317671e-01 2.556281834629479111e-01 5.123669364829196438e-01 4.754061129282013409e-01 9.764470380372083369e-01 8.038663983900646848e-01 6.960491266420890666e-01 2.940135977911654264e-01 2.857282759910040326e-03 4.599343225832352999e-02 5.597554495210212977e-01 7.445266674304001908e-01 3.387528030535971180e-01 6.429542922125383031e-01 2.123331785532429627e-01 5.302332654117811739e-01 7.262555377662539557e-01 3.982425859900724507e-01 3.243388301740235402e-01 6.191064123738921898e-01 8.988047781373914580e-01 7.819700328765150088e-01 7.664269102804815992e-01 6.734095355422575757e-03 2.904762329148526945e-01 5.097537644843168625e-01 9.524734606001823423e-01 4.812869576591960463e-01 6.236868013640477493e-01 1.459170943214320726e-01 9.874505139403206844e-01 7.561708982837871407e-01 3.798591332432484924e-01 6.056633451375117438e-01 7.935708170258731764e-01 1.458141583518740569e-01 7.082511296391911237e-01 1.098798009731616343e-02 3.655618484905173160e-01 9.551862303858617009e-01 8.148959351152762487e-02 4.739306219219985294e-02 7.963357515359494876e-01 6.208332695202813944e-01 3.884182264923189409e-01 4.589167647950288531e-01 6.496652974138312775e-01 2.467528128074852889e-01 5.309593064844935206e-01 5.364606369543487574e-01 2.421352989851309756e-01 3.776834556696828660e-02 1.564861233558080267e-01 5.197231021782636740e-01 8.725375120634637494e-01 2.441225493455024820e-01 2.320363366041028330e-01 5.026358683423555185e-01 7.035766000474735771e-01 8.347805591467084563e-01 2.303229841813967393e-01 6.908373419683054850e-01 2.646662377366995056e-01 1.259467197942290007e-01 9.372770922994989595e-01 6.674216272867254940e-01 1.027944489143072238e-01 5.686267290346079806e-01 3.948222804451942958e-01 4.689706944496729868e-01 4.446117700449114807e-02 6.817992275557515081e-01 9.084821829413957106e-01 9.184021015315092518e-01 3.045815734169987632e-01 2.204958624923980537e-03 7.542672057172502553e-01 9.460844786545006269e-01 3.373139094575949848e-02 9.059565314915285494e-01 9.938525461318854504e-01 2.542072661725306437e-01 9.685734112479216229e-02 8.223629541824816203e-01 1.057429056898460118e-01 8.080679390260248063e-01 5.823014244609205914e-01 6.413551528031806725e-01 1.787341975438894170e-01 1.250471413912357388e-01 8.390281297596062782e-01 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-euclidean-ml-iris.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-euclidean-ml-iris.txt new file mode 100644 index 0000000000000000000000000000000000000000..86de3c7592893bdb4438c9a0e7e60b2e7e5e1727 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-euclidean-ml-iris.txt @@ -0,0 +1 @@ + 5.3851648e-01 5.0990195e-01 6.4807407e-01 1.4142136e-01 6.1644140e-01 5.1961524e-01 1.7320508e-01 9.2195445e-01 4.6904158e-01 3.7416574e-01 3.7416574e-01 5.9160798e-01 9.9498744e-01 8.8317609e-01 1.1045361e+00 5.4772256e-01 1.0000000e-01 7.4161985e-01 3.3166248e-01 4.3588989e-01 3.0000000e-01 6.4807407e-01 4.6904158e-01 5.9160798e-01 5.4772256e-01 3.1622777e-01 1.4142136e-01 1.4142136e-01 5.3851648e-01 5.3851648e-01 3.8729833e-01 6.2449980e-01 8.0622577e-01 4.6904158e-01 3.7416574e-01 4.1231056e-01 4.6904158e-01 8.6602540e-01 1.4142136e-01 1.7320508e-01 1.3490738e+00 7.6811457e-01 4.5825757e-01 6.1644140e-01 5.9160798e-01 3.6055513e-01 5.8309519e-01 3.0000000e-01 2.2360680e-01 4.0037482e+00 3.6166283e+00 4.1641326e+00 3.0935417e+00 3.7920970e+00 3.4161382e+00 3.7854986e+00 2.3452079e+00 3.7496667e+00 2.8879058e+00 2.7037012e+00 3.2280025e+00 3.1464265e+00 3.7000000e+00 2.5806976e+00 3.6276714e+00 3.4351128e+00 3.0099834e+00 3.7682887e+00 2.8827071e+00 3.8535698e+00 3.0757113e+00 4.0472213e+00 3.6578682e+00 3.4161382e+00 3.5972211e+00 4.0472213e+00 4.2449971e+00 3.5312887e+00 2.4939928e+00 2.8178006e+00 2.7018512e+00 2.8948230e+00 4.1352146e+00 3.4117444e+00 3.5199432e+00 3.9115214e+00 3.6180105e+00 3.0000000e+00 3.0215890e+00 3.3120990e+00 3.5958309e+00 3.0099834e+00 2.3874673e+00 3.1527766e+00 3.0740852e+00 3.1256999e+00 3.3451457e+00 2.0904545e+00 3.0577770e+00 5.2848841e+00 4.2083251e+00 5.3018865e+00 4.6904158e+00 5.0566788e+00 6.0950800e+00 3.5916570e+00 5.6364883e+00 5.0477718e+00 5.6391489e+00 4.3566042e+00 4.5199558e+00 4.8538644e+00 4.1904654e+00 4.4170126e+00 4.6260134e+00 4.6454279e+00 6.2401923e+00 6.4984614e+00 4.1412558e+00 5.1215232e+00 4.0286474e+00 6.2112801e+00 4.1097445e+00 4.9699095e+00 5.3122500e+00 3.9774364e+00 4.0074930e+00 4.8404545e+00 5.0970580e+00 5.5461698e+00 6.0141500e+00 4.8805737e+00 4.1605288e+00 4.5705580e+00 5.7887823e+00 4.8918299e+00 4.6065171e+00 3.8961519e+00 4.7968740e+00 5.0199602e+00 4.6368092e+00 4.2083251e+00 5.2573758e+00 5.1361464e+00 4.6540305e+00 4.2766810e+00 4.4598206e+00 4.6508064e+00 4.1400483e+00 3.0000000e-01 3.3166248e-01 6.0827625e-01 1.0908712e+00 5.0990195e-01 4.2426407e-01 5.0990195e-01 1.7320508e-01 8.6602540e-01 4.5825757e-01 1.4142136e-01 6.7823300e-01 1.3601471e+00 1.6278821e+00 1.0535654e+00 5.4772256e-01 1.1747340e+00 8.3666003e-01 7.0710678e-01 7.6157731e-01 7.8102497e-01 5.5677644e-01 6.4807407e-01 2.2360680e-01 5.0000000e-01 5.9160798e-01 5.0000000e-01 3.4641016e-01 2.4494897e-01 6.7823300e-01 1.1489125e+00 1.3416408e+00 1.7320508e-01 3.0000000e-01 7.8740079e-01 1.7320508e-01 5.0990195e-01 4.5825757e-01 5.2915026e-01 8.1853528e-01 5.4772256e-01 6.7823300e-01 9.8488578e-01 1.4142136e-01 8.4852814e-01 3.6055513e-01 8.1240384e-01 3.1622777e-01 4.0963398e+00 3.6864617e+00 4.2367440e+00 2.9698485e+00 3.8118237e+00 3.3911650e+00 3.8600518e+00 2.1470911e+00 3.7881394e+00 2.8053520e+00 2.4617067e+00 3.2449961e+00 3.0413813e+00 3.7121422e+00 2.5592968e+00 3.7000000e+00 3.4336569e+00 2.9715316e+00 3.6918830e+00 2.7928480e+00 3.8935845e+00 3.0740852e+00 4.0187063e+00 3.6565011e+00 3.4467376e+00 3.6510273e+00 4.0804412e+00 4.2953463e+00 3.5383612e+00 2.4186773e+00 2.7000000e+00 2.5787594e+00 2.8548205e+00 4.1170378e+00 3.3985291e+00 3.5972211e+00 3.9786933e+00 3.5580894e+00 2.9983329e+00 2.9291637e+00 3.2434549e+00 3.6221541e+00 2.9546573e+00 2.1794495e+00 3.1032241e+00 3.0789609e+00 3.1144823e+00 3.3645208e+00 1.9131126e+00 3.0298515e+00 5.3385391e+00 4.1809090e+00 5.3572381e+00 4.7085029e+00 5.0911688e+00 6.1595454e+00 3.4799425e+00 5.6868269e+00 5.0408333e+00 5.7471732e+00 4.4192760e+00 4.5210618e+00 4.9020404e+00 4.1340053e+00 4.4022721e+00 4.6808119e+00 4.6829478e+00 6.3694584e+00 6.5314623e+00 4.0620192e+00 5.1903757e+00 4.0024992e+00 6.2617889e+00 4.1060930e+00 5.0428167e+00 5.3898052e+00 3.9812058e+00 4.0311289e+00 4.8518038e+00 5.1584882e+00 5.5919585e+00 6.1546730e+00 4.8918299e+00 4.1689327e+00 4.5475268e+00 5.8600341e+00 4.9598387e+00 4.6508064e+00 3.9153544e+00 4.8600412e+00 5.0724747e+00 4.7021272e+00 4.1809090e+00 5.3207142e+00 5.2067264e+00 4.7000000e+00 4.2497059e+00 4.4988888e+00 4.7180504e+00 4.1533119e+00 2.4494897e-01 5.0990195e-01 1.0862780e+00 2.6457513e-01 4.1231056e-01 4.3588989e-01 3.1622777e-01 8.8317609e-01 3.7416574e-01 2.6457513e-01 5.0000000e-01 1.3638182e+00 1.5874508e+00 1.0099505e+00 5.1961524e-01 1.2369317e+00 7.5498344e-01 8.3066239e-01 7.0000000e-01 5.0990195e-01 6.4807407e-01 6.4031242e-01 4.6904158e-01 5.0990195e-01 6.1644140e-01 5.4772256e-01 3.0000000e-01 3.3166248e-01 7.8102497e-01 1.0535654e+00 1.2845233e+00 3.1622777e-01 3.1622777e-01 8.5440037e-01 3.1622777e-01 3.6055513e-01 4.8989795e-01 4.3588989e-01 9.2736185e-01 3.0000000e-01 6.5574385e-01 9.5916630e-01 2.6457513e-01 7.8102497e-01 1.4142136e-01 8.0622577e-01 3.3166248e-01 4.2766810e+00 3.8496753e+00 4.4158804e+00 3.1543621e+00 3.9974992e+00 3.5510562e+00 4.0112342e+00 2.3065125e+00 3.9749214e+00 2.9495762e+00 2.6476405e+00 3.4029399e+00 3.2588341e+00 3.8794329e+00 2.7202941e+00 3.8807216e+00 3.5749126e+00 3.1527766e+00 3.8961519e+00 2.9782545e+00 4.0311289e+00 3.2588341e+00 4.2071368e+00 3.8314488e+00 3.6318040e+00 3.8340579e+00 4.2731721e+00 4.4698993e+00 3.7027017e+00 2.6153394e+00 2.8879058e+00 2.7712813e+00 3.0364453e+00 4.2825226e+00 3.5298725e+00 3.7322915e+00 4.1545156e+00 3.7669616e+00 3.1464265e+00 3.1032241e+00 3.4073450e+00 3.7854986e+00 3.1400637e+00 2.3537205e+00 3.2680269e+00 3.2326460e+00 3.2726136e+00 3.5425979e+00 2.0856654e+00 3.1953091e+00 5.4726593e+00 4.3347434e+00 5.5290144e+00 4.8682646e+00 5.2469038e+00 6.3364028e+00 3.6083237e+00 5.8660038e+00 5.2249402e+00 5.8940648e+00 4.5738387e+00 4.6936127e+00 5.0695167e+00 4.2918527e+00 4.5442271e+00 4.8270074e+00 4.8456166e+00 6.5207362e+00 6.7178866e+00 4.2508823e+00 5.3488316e+00 4.1436699e+00 6.4467046e+00 4.2813549e+00 5.1942276e+00 5.5587768e+00 4.1496988e+00 4.1856899e+00 5.0149776e+00 5.3385391e+00 5.7775427e+00 6.3126856e+00 5.0537115e+00 4.3416587e+00 4.7169906e+00 6.0406953e+00 5.0921508e+00 4.8062459e+00 4.0669399e+00 5.0269275e+00 5.2287666e+00 4.8682646e+00 4.3347434e+00 5.4753995e+00 5.3535035e+00 4.8641546e+00 4.4305756e+00 4.6615448e+00 4.8487112e+00 4.2988371e+00 6.4807407e-01 1.1661904e+00 3.3166248e-01 5.0000000e-01 3.0000000e-01 3.1622777e-01 1.0000000e+00 3.7416574e-01 2.6457513e-01 5.1961524e-01 1.5297059e+00 1.7146428e+00 1.1661904e+00 6.5574385e-01 1.3228757e+00 8.6602540e-01 8.7749644e-01 8.0622577e-01 7.0710678e-01 6.4807407e-01 5.3851648e-01 4.2426407e-01 5.4772256e-01 7.2111026e-01 6.7823300e-01 1.7320508e-01 2.2360680e-01 8.7749644e-01 1.1704700e+00 1.4247807e+00 3.1622777e-01 5.0990195e-01 1.0049876e+00 3.1622777e-01 3.0000000e-01 5.8309519e-01 6.0827625e-01 8.3666003e-01 3.0000000e-01 7.0000000e-01 9.6953597e-01 2.6457513e-01 8.6602540e-01 1.4142136e-01 9.2195445e-01 4.5825757e-01 4.1773197e+00 3.7336309e+00 4.3058100e+00 2.9849623e+00 3.8729833e+00 3.3926391e+00 3.8897301e+00 2.1118712e+00 3.8548671e+00 2.7784888e+00 2.4515301e+00 3.2680269e+00 3.1080541e+00 3.7376463e+00 2.5806976e+00 3.7762415e+00 3.4205263e+00 3.0000000e+00 3.7496667e+00 2.8160256e+00 3.8923001e+00 3.1304952e+00 4.0620192e+00 3.6851052e+00 3.5114100e+00 3.7229021e+00 4.1545156e+00 4.3497126e+00 3.5623026e+00 2.4698178e+00 2.7202941e+00 2.6038433e+00 2.8913665e+00 4.1279535e+00 3.3674916e+00 3.6069378e+00 4.0422766e+00 3.6262929e+00 2.9966648e+00 2.9376862e+00 3.2357379e+00 3.6482873e+00 2.9899833e+00 2.1633308e+00 3.1080541e+00 3.0838288e+00 3.1224990e+00 3.4132096e+00 1.9157244e+00 3.0446675e+00 5.3357286e+00 4.1773197e+00 5.4064776e+00 4.7222876e+00 5.1097945e+00 6.2153037e+00 3.4205263e+00 5.7384667e+00 5.0813384e+00 5.7844619e+00 4.4519659e+00 4.5530210e+00 4.9457052e+00 4.1303753e+00 4.3965896e+00 4.7010637e+00 4.7095647e+00 6.4140471e+00 6.5901442e+00 4.0877867e+00 5.2297227e+00 3.9862263e+00 6.3229740e+00 4.1436699e+00 5.0695167e+00 5.4387499e+00 4.0124805e+00 4.0472213e+00 4.8733972e+00 5.2172790e+00 5.6550862e+00 6.2153037e+00 4.9132474e+00 4.1988094e+00 4.5552168e+00 5.9321160e+00 4.9628621e+00 4.6690470e+00 3.9268308e+00 4.9101935e+00 5.1048996e+00 4.7602521e+00 4.1773197e+00 5.3497664e+00 5.2325902e+00 4.7455242e+00 4.2883563e+00 4.5332108e+00 4.7191101e+00 4.1496988e+00 6.1644140e-01 4.5825757e-01 2.2360680e-01 9.2195445e-01 5.2915026e-01 4.2426407e-01 3.4641016e-01 6.4031242e-01 9.7467943e-01 9.1651514e-01 1.0862780e+00 5.4772256e-01 1.7320508e-01 7.9372539e-01 2.6457513e-01 5.3851648e-01 2.6457513e-01 5.6568542e-01 5.2915026e-01 5.7445626e-01 6.3245553e-01 3.4641016e-01 2.4494897e-01 2.8284271e-01 5.3851648e-01 5.7445626e-01 5.0000000e-01 5.5677644e-01 7.8102497e-01 5.2915026e-01 4.4721360e-01 5.1961524e-01 5.2915026e-01 8.5440037e-01 2.4494897e-01 1.7320508e-01 1.4000000e+00 7.2801099e-01 4.5825757e-01 5.8309519e-01 6.4031242e-01 3.0000000e-01 5.6568542e-01 3.3166248e-01 3.0000000e-01 4.0607881e+00 3.6633318e+00 4.2190046e+00 3.1480152e+00 3.8496753e+00 3.4568772e+00 3.8249183e+00 2.3874673e+00 3.8078866e+00 2.9223278e+00 2.7586228e+00 3.2710854e+00 3.2186954e+00 3.7456642e+00 2.6267851e+00 3.6851052e+00 3.4669872e+00 3.0626786e+00 3.8340579e+00 2.9376862e+00 3.8845849e+00 3.1336879e+00 4.1036569e+00 3.7067506e+00 3.4741906e+00 3.6551334e+00 4.1085277e+00 4.2965102e+00 3.5763109e+00 2.5573424e+00 2.8740216e+00 2.7604347e+00 2.9495762e+00 4.1785165e+00 3.4380227e+00 3.5510562e+00 3.9648455e+00 3.6864617e+00 3.0364453e+00 3.0708305e+00 3.3541020e+00 3.6400549e+00 3.0659419e+00 2.4372115e+00 3.1968735e+00 3.1128765e+00 3.1670175e+00 3.3985291e+00 2.1424285e+00 3.1032241e+00 5.3131911e+00 4.2461747e+00 5.3507009e+00 4.7307505e+00 5.0960769e+00 6.1457302e+00 3.6166283e+00 5.6877060e+00 5.1009803e+00 5.6762664e+00 4.3977267e+00 4.5683695e+00 4.9010203e+00 4.2308392e+00 4.4508426e+00 4.6626173e+00 4.6882833e+00 6.2785349e+00 6.5536250e+00 4.1964271e+00 5.1643005e+00 4.0607881e+00 6.2657801e+00 4.1605288e+00 5.0079936e+00 5.3591044e+00 4.0249224e+00 4.0472213e+00 4.8836462e+00 5.1497573e+00 5.6017854e+00 6.0572271e+00 4.9234135e+00 4.2083251e+00 4.6141088e+00 5.8438001e+00 4.9203658e+00 4.6454279e+00 3.9344631e+00 4.8445846e+00 5.0616203e+00 4.6861498e+00 4.2461747e+00 5.2971691e+00 5.1730069e+00 4.7010637e+00 4.3301270e+00 4.5044423e+00 4.6786750e+00 4.1737274e+00 9.9498744e-01 7.0000000e-01 1.4594520e+00 1.0099505e+00 3.4641016e-01 8.1240384e-01 1.1618950e+00 1.5716234e+00 6.7823300e-01 6.1644140e-01 4.0000000e-01 5.9160798e-01 3.3166248e-01 3.8729833e-01 5.3851648e-01 4.1231056e-01 1.1224972e+00 6.7823300e-01 8.3066239e-01 1.0099505e+00 6.4807407e-01 5.2915026e-01 6.4807407e-01 1.0148892e+00 1.0246951e+00 5.3851648e-01 4.5825757e-01 4.7958315e-01 1.0099505e+00 9.6953597e-01 6.0827625e-01 1.0099505e+00 1.4177447e+00 6.4807407e-01 7.0000000e-01 1.8814888e+00 1.3000000e+00 6.0827625e-01 3.7416574e-01 1.1269428e+00 3.8729833e-01 1.1224972e+00 3.6055513e-01 8.0622577e-01 3.6124784e+00 3.2465366e+00 3.7868192e+00 2.9444864e+00 3.4698703e+00 3.1543621e+00 3.4073450e+00 2.3280893e+00 3.4146742e+00 2.7055499e+00 2.7147744e+00 2.9189039e+00 2.9832868e+00 3.3896903e+00 2.3366643e+00 3.2588341e+00 3.1464265e+00 2.7784888e+00 3.5468296e+00 2.7073973e+00 3.5085610e+00 2.7928480e+00 3.7709415e+00 3.3674916e+00 3.0935417e+00 3.2465366e+00 3.7121422e+00 3.8832976e+00 3.2264532e+00 2.3194827e+00 2.6758176e+00 2.5729361e+00 2.6608269e+00 3.8470768e+00 3.1400637e+00 3.1448370e+00 3.5411862e+00 3.3867388e+00 2.7239677e+00 2.8407745e+00 3.1032241e+00 3.2726136e+00 2.7892651e+00 2.3748684e+00 2.9223278e+00 2.7910571e+00 2.8548205e+00 3.0347982e+00 2.0566964e+00 2.8053520e+00 4.9061186e+00 3.9255573e+00 4.9223978e+00 4.3566042e+00 4.6978719e+00 5.7052607e+00 3.4263683e+00 5.2659282e+00 4.7349762e+00 5.2057660e+00 3.9774364e+00 4.2011903e+00 4.4833024e+00 3.9370039e+00 4.1146081e+00 4.2497059e+00 4.2918527e+00 5.7913729e+00 6.1343296e+00 3.9179076e+00 4.7275787e+00 3.7483330e+00 5.8360946e+00 3.8013156e+00 4.5760245e+00 4.9173163e+00 3.6633318e+00 3.6742346e+00 4.5066617e+00 4.7222876e+00 5.1788030e+00 5.5596762e+00 4.5453273e+00 3.8457769e+00 4.2883563e+00 5.3916602e+00 4.5022217e+00 4.2473521e+00 3.5693137e+00 4.4124823e+00 4.6411206e+00 4.2497059e+00 3.9255573e+00 4.8682646e+00 4.7391982e+00 4.2848571e+00 3.9887341e+00 4.1024383e+00 4.2649736e+00 3.8183766e+00 4.2426407e-01 5.4772256e-01 4.7958315e-01 8.6602540e-01 3.0000000e-01 4.8989795e-01 6.1644140e-01 1.3601471e+00 1.4933185e+00 9.5393920e-01 5.0990195e-01 1.2083046e+00 6.4807407e-01 8.6023253e-01 6.0000000e-01 4.5825757e-01 6.2449980e-01 5.4772256e-01 6.0827625e-01 4.5825757e-01 6.2449980e-01 6.0827625e-01 3.1622777e-01 4.2426407e-01 8.1240384e-01 9.4868330e-01 1.2083046e+00 4.7958315e-01 5.0000000e-01 9.1651514e-01 4.7958315e-01 4.6904158e-01 5.1961524e-01 4.2426407e-01 1.1090537e+00 3.1622777e-01 5.4772256e-01 8.1853528e-01 4.4721360e-01 6.7823300e-01 2.2360680e-01 7.7459667e-01 4.2426407e-01 4.2308392e+00 3.7854986e+00 4.3669211e+00 3.1272992e+00 3.9560081e+00 3.4899857e+00 3.9344631e+00 2.2781571e+00 3.9357337e+00 2.8827071e+00 2.6495283e+00 3.3361655e+00 3.2634338e+00 3.8209946e+00 2.6627054e+00 3.8353618e+00 3.4942810e+00 3.1160873e+00 3.8794329e+00 2.9495762e+00 3.9420807e+00 3.2202484e+00 4.1701319e+00 3.7828561e+00 3.5916570e+00 3.7907783e+00 4.2391037e+00 4.4147480e+00 3.6414283e+00 2.5980762e+00 2.8653098e+00 2.7549955e+00 2.9983329e+00 4.2225585e+00 3.4423829e+00 3.6414283e+00 4.1024383e+00 3.7549967e+00 3.0740852e+00 3.0626786e+00 3.3555923e+00 3.7229021e+00 3.1064449e+00 2.3388031e+00 3.2140317e+00 3.1654384e+00 3.2093613e+00 3.4957117e+00 2.0639767e+00 3.1400637e+00 5.3758720e+00 4.2638011e+00 5.4680892e+00 4.7989582e+00 5.1710734e+00 6.2801274e+00 3.5312887e+00 5.8137767e+00 5.1797683e+00 5.8077534e+00 4.4977772e+00 4.6368092e+00 5.0049975e+00 4.2272923e+00 4.4609416e+00 4.7423623e+00 4.7780749e+00 6.4397205e+00 6.6708320e+00 4.2190046e+00 5.2744668e+00 4.0620192e+00 6.3992187e+00 4.2284749e+00 5.1137071e+00 5.4963624e+00 4.0902323e+00 4.1121770e+00 4.9477268e+00 5.2886671e+00 5.7314920e+00 6.2401923e+00 4.9849774e+00 4.2871902e+00 4.6626173e+00 5.9883220e+00 4.9939964e+00 4.7318073e+00 3.9912404e+00 4.9618545e+00 5.1526692e+00 4.8031240e+00 4.2638011e+00 5.3972215e+00 5.2678269e+00 4.7968740e+00 4.3840620e+00 4.5934736e+00 4.7497368e+00 4.2178193e+00 7.8740079e-01 3.3166248e-01 5.0000000e-01 2.2360680e-01 4.6904158e-01 9.0553851e-01 1.0440307e+00 1.2369317e+00 7.0000000e-01 2.0000000e-01 8.3666003e-01 4.2426407e-01 4.4721360e-01 3.7416574e-01 6.7082039e-01 3.8729833e-01 4.4721360e-01 4.1231056e-01 2.2360680e-01 2.2360680e-01 2.2360680e-01 3.7416574e-01 3.7416574e-01 4.4721360e-01 7.3484692e-01 9.4868330e-01 3.3166248e-01 3.6055513e-01 5.4772256e-01 3.3166248e-01 7.4833148e-01 1.0000000e-01 2.4494897e-01 1.2288206e+00 6.6332496e-01 4.2426407e-01 6.0827625e-01 4.6904158e-01 4.2426407e-01 4.5825757e-01 4.2426407e-01 1.4142136e-01 3.9648455e+00 3.5623026e+00 4.1170378e+00 2.9866369e+00 3.7296112e+00 3.3256578e+00 3.7282704e+00 2.2113344e+00 3.6918830e+00 2.7802878e+00 2.5690465e+00 3.1543621e+00 3.0545049e+00 3.6249138e+00 2.4959968e+00 3.5818989e+00 3.3481338e+00 2.9206164e+00 3.6837481e+00 2.7820855e+00 3.7815341e+00 3.0049958e+00 3.9686270e+00 3.5791060e+00 3.3555923e+00 3.5454196e+00 3.9912404e+00 4.1892720e+00 3.4554305e+00 2.4020824e+00 2.7110883e+00 2.5942244e+00 2.8089144e+00 4.0509258e+00 3.3181320e+00 3.4583233e+00 3.8613469e+00 3.5383612e+00 2.9137605e+00 2.9189039e+00 3.2093613e+00 3.5242020e+00 2.9206164e+00 2.2561028e+00 3.0577770e+00 2.9899833e+00 3.0397368e+00 3.2771939e+00 1.9697716e+00 2.9698485e+00 5.2191953e+00 4.1206796e+00 5.2478567e+00 4.6162756e+00 4.9899900e+00 6.0448325e+00 3.4741906e+00 5.5803226e+00 4.9749372e+00 5.5973208e+00 4.3000000e+00 4.4474712e+00 4.7968740e+00 4.0975602e+00 4.3358967e+00 4.5661800e+00 4.5793013e+00 6.2040309e+00 6.4420494e+00 4.0472213e+00 5.0695167e+00 3.9395431e+00 6.1587336e+00 4.0373258e+00 4.9142650e+00 5.2621288e+00 3.9051248e+00 3.9357337e+00 4.7686476e+00 5.0447993e+00 5.4927225e+00 5.9849812e+00 4.8093659e+00 4.0865633e+00 4.4833024e+00 5.7463032e+00 4.8311489e+00 4.5398238e+00 3.8223030e+00 4.7455242e+00 4.9628621e+00 4.5902070e+00 4.1206796e+00 5.2009614e+00 5.0823223e+00 4.5989129e+00 4.2000000e+00 4.3977267e+00 4.5891176e+00 4.0607881e+00 5.5677644e-01 1.2845233e+00 6.7082039e-01 4.2426407e-01 3.4641016e-01 1.7916473e+00 1.9974984e+00 1.4317821e+00 9.2736185e-01 1.6124515e+00 1.1489125e+00 1.1575837e+00 1.0862780e+00 8.3066239e-01 9.1104336e-01 8.1240384e-01 6.4031242e-01 8.3066239e-01 1.0049876e+00 9.4339811e-01 4.6904158e-01 4.8989795e-01 1.1401754e+00 1.4491377e+00 1.7029386e+00 5.5677644e-01 7.0000000e-01 1.2569805e+00 5.5677644e-01 1.4142136e-01 8.6602540e-01 8.6023253e-01 6.2449980e-01 3.1622777e-01 9.5916630e-01 1.2609520e+00 4.2426407e-01 1.1575837e+00 3.6055513e-01 1.2083046e+00 7.2111026e-01 4.3794977e+00 3.9230090e+00 4.4977772e+00 3.0886890e+00 4.0435133e+00 3.5383612e+00 4.0767634e+00 2.1794495e+00 4.0360872e+00 2.8930952e+00 2.4939928e+00 3.4336569e+00 3.2326460e+00 3.9012818e+00 2.7367864e+00 3.9711459e+00 3.5707142e+00 3.1511903e+00 3.8768544e+00 2.9427878e+00 4.0570926e+00 3.2969683e+00 4.2083251e+00 3.8457769e+00 3.6905284e+00 3.9102430e+00 4.3324358e+00 4.5287967e+00 3.7229021e+00 2.6134269e+00 2.8337255e+00 2.7184554e+00 3.0413813e+00 4.2720019e+00 3.5085610e+00 3.7920970e+00 4.2320208e+00 3.7656341e+00 3.1543621e+00 3.0561414e+00 3.3615473e+00 3.8183766e+00 3.1320920e+00 2.2293497e+00 3.2449961e+00 3.2465366e+00 3.2771939e+00 3.5860842e+00 2.0049938e+00 3.1937439e+00 5.4972721e+00 4.3104524e+00 5.5821143e+00 4.8795492e+00 5.2706736e+00 6.3953108e+00 3.5028560e+00 5.9143892e+00 5.2316345e+00 5.9757845e+00 4.6292548e+00 4.7053161e+00 5.1176166e+00 4.2485292e+00 4.5276926e+00 4.8692915e+00 4.8774994e+00 6.6174013e+00 6.7557383e+00 4.2071368e+00 5.4074023e+00 4.1158231e+00 6.4984614e+00 4.2965102e+00 5.2488094e+00 5.6258333e+00 4.1677332e+00 4.2083251e+00 5.0259327e+00 5.4009258e+00 5.8300943e+00 6.4265076e+00 5.0645829e+00 4.3588989e+00 4.6968074e+00 6.1155539e+00 5.1322510e+00 4.8383882e+00 4.0853396e+00 5.0892043e+00 5.2735187e+00 4.9386233e+00 4.3104524e+00 5.5235858e+00 5.4064776e+00 4.9142650e+00 4.4294469e+00 4.7010637e+00 4.8887626e+00 4.3023250e+00 7.8740079e-01 3.4641016e-01 1.7320508e-01 7.2801099e-01 1.3114877e+00 1.5556349e+00 1.0099505e+00 5.0000000e-01 1.1000000e+00 7.5498344e-01 6.2449980e-01 7.0000000e-01 7.7459667e-01 5.2915026e-01 5.1961524e-01 2.0000000e-01 4.4721360e-01 5.0990195e-01 4.4721360e-01 2.6457513e-01 1.7320508e-01 6.5574385e-01 1.0440307e+00 1.2609520e+00 0.0000000e+00 3.4641016e-01 7.5498344e-01 0.0000000e+00 5.5677644e-01 3.7416574e-01 5.0000000e-01 9.3808315e-01 5.5677644e-01 6.5574385e-01 8.8317609e-01 2.6457513e-01 7.4161985e-01 3.4641016e-01 7.2801099e-01 2.6457513e-01 4.0435133e+00 3.6359318e+00 4.1856899e+00 2.9478806e+00 3.7709415e+00 3.3421550e+00 3.8065733e+00 2.1307276e+00 3.7389838e+00 2.7748874e+00 2.4556058e+00 3.2031235e+00 3.0133038e+00 3.6619667e+00 2.5258662e+00 3.6523965e+00 3.3852622e+00 2.9223278e+00 3.6687873e+00 2.7586228e+00 3.8457769e+00 3.0364453e+00 3.9799497e+00 3.6027767e+00 3.4014703e+00 3.6055513e+00 4.0348482e+00 4.2497059e+00 3.4942810e+00 2.3874673e+00 2.6720778e+00 2.5495098e+00 2.8178006e+00 4.0718546e+00 3.3496268e+00 3.5425979e+00 3.9293765e+00 3.5284558e+00 2.9495762e+00 2.9000000e+00 3.1984371e+00 3.5707142e+00 2.9189039e+00 2.1679483e+00 3.0626786e+00 3.0248967e+00 3.0675723e+00 3.3181320e+00 1.9104973e+00 2.9883106e+00 5.2924474e+00 4.1436699e+00 5.3113087e+00 4.6583259e+00 5.0467812e+00 6.1081912e+00 3.4525353e+00 5.6329388e+00 4.9979996e+00 5.6973678e+00 4.3749286e+00 4.4821870e+00 4.8600412e+00 4.1060930e+00 4.3760713e+00 4.6411206e+00 4.6324939e+00 6.3071388e+00 6.4876806e+00 4.0286474e+00 5.1468437e+00 3.9686270e+00 6.2112801e+00 4.0706265e+00 4.9919936e+00 5.3329167e+00 3.9446166e+00 3.9874804e+00 4.8114447e+00 5.1029403e+00 5.5443665e+00 6.0917978e+00 4.8538644e+00 4.1194660e+00 4.4933284e+00 5.8180753e+00 4.9142650e+00 4.5978256e+00 3.8729833e+00 4.8176758e+00 5.0338852e+00 4.6690470e+00 4.1436699e+00 5.2744668e+00 5.1652686e+00 4.6669048e+00 4.2201896e+00 4.4575778e+00 4.6722586e+00 4.1060930e+00 6.7823300e-01 9.3273791e-01 1.3674794e+00 5.8309519e-01 7.8740079e-01 3.4641016e-01 3.8729833e-01 3.8729833e-01 3.3166248e-01 3.6055513e-01 3.6055513e-01 9.4868330e-01 6.1644140e-01 7.8102497e-01 8.1240384e-01 5.4772256e-01 2.8284271e-01 3.7416574e-01 8.6602540e-01 8.5440037e-01 3.6055513e-01 4.5825757e-01 5.1961524e-01 7.8740079e-01 7.0710678e-01 3.0000000e-01 7.8740079e-01 1.2369317e+00 4.2426407e-01 5.0000000e-01 1.6792856e+00 1.1357817e+00 6.0827625e-01 5.4772256e-01 9.3273791e-01 3.3166248e-01 9.4868330e-01 1.0000000e-01 5.7445626e-01 3.8065733e+00 3.4554305e+00 3.9824616e+00 3.0708305e+00 3.6496575e+00 3.3331667e+00 3.6290495e+00 2.4124676e+00 3.5916570e+00 2.8705400e+00 2.7730849e+00 3.1176915e+00 3.0822070e+00 3.5791060e+00 2.5099801e+00 3.4496377e+00 3.3496268e+00 2.9257478e+00 3.6851052e+00 2.8372522e+00 3.7349699e+00 2.9597297e+00 3.9370039e+00 3.5411862e+00 3.2695565e+00 3.4322005e+00 3.8858718e+00 4.0841156e+00 3.4190642e+00 2.4372115e+00 2.7928480e+00 2.6795522e+00 2.8142495e+00 4.0348482e+00 3.3436507e+00 3.3778692e+00 3.7389838e+00 3.5199432e+00 2.9154759e+00 2.9849623e+00 3.2603681e+00 3.4684290e+00 2.9359837e+00 2.4494897e+00 3.0886890e+00 2.9782545e+00 3.0380915e+00 3.2140317e+00 2.1424285e+00 2.9782545e+00 5.1487863e+00 4.1243181e+00 5.1332251e+00 4.5628938e+00 4.9183331e+00 5.9118525e+00 3.5972211e+00 5.4635154e+00 4.9173163e+00 5.4497706e+00 4.2023803e+00 4.3965896e+00 4.6968074e+00 4.1255303e+00 4.3324358e+00 4.4833024e+00 4.5011110e+00 6.0282667e+00 6.3300869e+00 4.0681691e+00 4.9547957e+00 3.9560081e+00 6.0315835e+00 3.9912404e+00 4.8062459e+00 5.1283526e+00 3.8600518e+00 3.8858718e+00 4.7148701e+00 4.9173163e+00 5.3721504e+00 5.7887823e+00 4.7560488e+00 4.0336088e+00 4.4665423e+00 5.5991071e+00 4.7486840e+00 4.4631827e+00 3.7815341e+00 4.6292548e+00 4.8682646e+00 4.4698993e+00 4.1243181e+00 5.0970580e+00 4.9779514e+00 4.5033321e+00 4.1701319e+00 4.3162484e+00 4.5110974e+00 4.0323690e+00 4.5825757e-01 8.1853528e-01 1.2328828e+00 1.3638182e+00 8.6023253e-01 3.8729833e-01 9.9498744e-01 5.1961524e-01 6.0827625e-01 4.7958315e-01 6.6332496e-01 4.4721360e-01 3.0000000e-01 4.4721360e-01 2.8284271e-01 4.2426407e-01 4.4721360e-01 2.2360680e-01 3.0000000e-01 6.4031242e-01 8.1853528e-01 1.0816654e+00 3.4641016e-01 4.8989795e-01 7.6811457e-01 3.4641016e-01 6.4031242e-01 3.1622777e-01 3.8729833e-01 1.1832160e+00 5.3851648e-01 4.5825757e-01 6.1644140e-01 4.5825757e-01 5.0000000e-01 3.4641016e-01 5.9160798e-01 3.0000000e-01 3.9912404e+00 3.5637059e+00 4.1327957e+00 2.9444864e+00 3.7336309e+00 3.2848135e+00 3.7188708e+00 2.1307276e+00 3.7013511e+00 2.7166155e+00 2.5000000e+00 3.1336879e+00 3.0463092e+00 3.6041643e+00 2.4698178e+00 3.6027767e+00 3.3015148e+00 2.8948230e+00 3.6742346e+00 2.7477263e+00 3.7483330e+00 3.0033315e+00 3.9547440e+00 3.5580894e+00 3.3630343e+00 3.5608988e+00 4.0049969e+00 4.1928511e+00 3.4336569e+00 2.3874673e+00 2.6720778e+00 2.5573424e+00 2.7892651e+00 4.0174619e+00 3.2588341e+00 3.4365681e+00 3.8729833e+00 3.5369478e+00 2.8740216e+00 2.8757608e+00 3.1575307e+00 3.5057096e+00 2.8982753e+00 2.1863211e+00 3.0166206e+00 2.9546573e+00 3.0049958e+00 3.2726136e+00 1.9157244e+00 2.9376862e+00 5.1874849e+00 4.0779897e+00 5.2488094e+00 4.5891176e+00 4.9689033e+00 6.0506198e+00 3.3882149e+00 5.5812185e+00 4.9618545e+00 5.5982140e+00 4.2918527e+00 4.4305756e+00 4.7937459e+00 4.0521599e+00 4.2953463e+00 4.5497253e+00 4.5628938e+00 6.2112801e+00 6.4459289e+00 4.0162171e+00 5.0665570e+00 3.8897301e+00 6.1660360e+00 4.0236799e+00 4.9030603e+00 5.2649786e+00 3.8884444e+00 3.9115214e+00 4.7465777e+00 5.0517324e+00 5.5009090e+00 6.0041652e+00 4.7874837e+00 4.0681691e+00 4.4463468e+00 5.7645468e+00 4.8052055e+00 4.5188494e+00 3.7947332e+00 4.7486840e+00 4.9537864e+00 4.6000000e+00 4.0779897e+00 5.1903757e+00 5.0714889e+00 4.5978256e+00 4.1844952e+00 4.3874822e+00 4.5617979e+00 4.0224371e+00 5.8309519e-01 1.4317821e+00 1.6941074e+00 1.1269428e+00 6.1644140e-01 1.2569805e+00 8.8317609e-01 7.8740079e-01 8.2462113e-01 7.5498344e-01 6.5574385e-01 6.4807407e-01 3.0000000e-01 5.7445626e-01 6.5574385e-01 5.7445626e-01 3.1622777e-01 2.4494897e-01 7.8740079e-01 1.1747340e+00 1.3928388e+00 1.7320508e-01 3.6055513e-01 8.7177979e-01 1.7320508e-01 4.2426407e-01 5.1961524e-01 5.8309519e-01 7.9372539e-01 4.6904158e-01 7.6157731e-01 1.0344080e+00 2.0000000e-01 8.8317609e-01 3.0000000e-01 8.7177979e-01 3.7416574e-01 4.1785165e+00 3.7643060e+00 4.3162484e+00 3.0298515e+00 3.8897301e+00 3.4496377e+00 3.9344631e+00 2.1886069e+00 3.8639358e+00 2.8618176e+00 2.5019992e+00 3.3181320e+00 3.1064449e+00 3.7788887e+00 2.6324893e+00 3.7828561e+00 3.4942810e+00 3.0315013e+00 3.7643060e+00 2.8530685e+00 3.9623226e+00 3.1511903e+00 4.0877867e+00 3.7188708e+00 3.5242020e+00 3.7322915e+00 4.1581246e+00 4.3737855e+00 3.6083237e+00 2.4879711e+00 2.7586228e+00 2.6362853e+00 2.9240383e+00 4.1797129e+00 3.4539832e+00 3.6687873e+00 4.0583248e+00 3.6304270e+00 3.0610456e+00 2.9899833e+00 3.2954514e+00 3.6905284e+00 3.0215890e+00 2.2248595e+00 3.1638584e+00 3.1400637e+00 3.1780497e+00 3.4380227e+00 1.9748418e+00 3.0951575e+00 5.4092513e+00 4.2449971e+00 5.4350713e+00 4.7738873e+00 5.1633323e+00 6.2353829e+00 3.5256205e+00 5.7584720e+00 5.1097945e+00 5.8283788e+00 4.4977772e+00 4.5934736e+00 4.9809638e+00 4.1988094e+00 4.4743715e+00 4.7592016e+00 4.7528939e+00 6.4459289e+00 6.6075714e+00 4.1231056e+00 5.2706736e+00 4.0669399e+00 6.3364028e+00 4.1809090e+00 5.1176166e+00 5.4635154e+00 4.0558600e+00 4.1024383e+00 4.9234135e+00 5.2316345e+00 5.6683331e+00 6.2337790e+00 4.9648766e+00 4.2355637e+00 4.6021734e+00 5.9447456e+00 5.0338852e+00 4.7191101e+00 3.9862263e+00 4.9416596e+00 5.1526692e+00 4.7906158e+00 4.2449971e+00 5.3972215e+00 5.2867760e+00 4.7843495e+00 4.3243497e+00 4.5760245e+00 4.7916594e+00 4.2178193e+00 1.8083141e+00 2.0420578e+00 1.4662878e+00 1.0099505e+00 1.7320508e+00 1.2165525e+00 1.3190906e+00 1.1747340e+00 6.8556546e-01 1.1180340e+00 1.0295630e+00 8.6602540e-01 9.9498744e-01 1.1090537e+00 1.0344080e+00 6.7823300e-01 7.2111026e-01 1.2727922e+00 1.4764823e+00 1.7262677e+00 7.2801099e-01 7.4161985e-01 1.3190906e+00 7.2801099e-01 2.4494897e-01 9.8488578e-01 9.0553851e-01 7.8102497e-01 3.1622777e-01 1.1135529e+00 1.4177447e+00 6.1644140e-01 1.2409674e+00 4.7958315e-01 1.2884099e+00 8.2462113e-01 4.6882833e+00 4.2391037e+00 4.8135226e+00 3.4322005e+00 4.3692105e+00 3.8729833e+00 4.3931765e+00 2.5238859e+00 4.3577517e+00 3.2295511e+00 2.8390139e+00 3.7589892e+00 3.5707142e+00 4.2308392e+00 3.0643107e+00 4.2836900e+00 3.9000000e+00 3.4856850e+00 4.2154478e+00 3.2832910e+00 4.3794977e+00 3.6235342e+00 4.5442271e+00 4.1773197e+00 4.0124805e+00 4.2272923e+00 4.6551047e+00 4.8507731e+00 4.0521599e+00 2.9478806e+00 3.1764760e+00 3.0610456e+00 3.3749074e+00 4.6076024e+00 3.8379682e+00 4.1060930e+00 4.5486262e+00 4.1012193e+00 3.4828150e+00 3.3970576e+00 3.7013511e+00 4.1448764e+00 3.4684290e+00 2.5748786e+00 3.5818989e+00 3.5749126e+00 3.6083237e+00 3.9115214e+00 2.3452079e+00 3.5270384e+00 5.8189346e+00 4.6454279e+00 5.9059292e+00 5.2105662e+00 5.5982140e+00 6.7186308e+00 3.8379682e+00 6.2401923e+00 5.5668663e+00 6.2872888e+00 4.9487372e+00 5.0378567e+00 5.4415071e+00 4.5858478e+00 4.8559242e+00 5.1894123e+00 5.2048055e+00 6.9260378e+00 7.0851958e+00 4.5497253e+00 5.7271284e+00 4.4474712e+00 6.8242216e+00 4.6281746e+00 5.5686623e+00 5.9455866e+00 4.4977772e+00 4.5354162e+00 5.3572381e+00 5.7227616e+00 6.1554854e+00 6.7305275e+00 5.3953684e+00 4.6904158e+00 5.0338852e+00 6.4342832e+00 5.4497706e+00 5.1643005e+00 4.4124823e+00 5.4092513e+00 5.5955339e+00 5.2545219e+00 4.6454279e+00 5.8455111e+00 5.7245087e+00 5.2354560e+00 4.7644517e+00 5.0259327e+00 5.2057660e+00 4.6314145e+00 5.4772256e-01 4.6904158e-01 8.8881944e-01 5.5677644e-01 7.9372539e-01 8.7749644e-01 8.4261498e-01 1.2806248e+00 1.1489125e+00 1.3601471e+00 1.3416408e+00 1.0954451e+00 8.3666003e-01 8.7177979e-01 1.4177447e+00 1.4035669e+00 8.0622577e-01 6.8556546e-01 4.1231056e-01 1.3114877e+00 1.1313708e+00 5.9160798e-01 1.3114877e+00 1.7233688e+00 9.6953597e-01 9.5393920e-01 2.1447611e+00 1.6155494e+00 1.1000000e+00 1.0295630e+00 1.4317821e+00 8.3066239e-01 1.4560220e+00 6.5574385e-01 1.0816654e+00 3.9711459e+00 3.6851052e+00 4.1713307e+00 3.4684290e+00 3.8961519e+00 3.6810325e+00 3.8665230e+00 2.9017236e+00 3.8236109e+00 3.2832910e+00 3.2511536e+00 3.4205263e+00 3.4292856e+00 3.8716921e+00 2.8670542e+00 3.6469165e+00 3.6905284e+00 3.2771939e+00 3.9974992e+00 3.2233523e+00 4.0211939e+00 3.2526912e+00 4.2284749e+00 3.8444766e+00 3.5199432e+00 3.6496575e+00 4.1036569e+00 4.3011626e+00 3.7188708e+00 2.8106939e+00 3.1968735e+00 3.0886890e+00 3.1591138e+00 4.3474130e+00 3.7067506e+00 3.6400549e+00 3.9446166e+00 3.8196859e+00 3.2649655e+00 3.3749074e+00 3.6455452e+00 3.7536649e+00 3.2863353e+00 2.9291637e+00 3.4554305e+00 3.3181320e+00 3.3808283e+00 3.4914181e+00 2.6057628e+00 3.3271610e+00 5.3916602e+00 4.4485953e+00 5.3282267e+00 4.8352870e+00 5.1623638e+00 6.0835845e+00 4.0249224e+00 5.6595053e+00 5.1749396e+00 5.6053546e+00 4.4249294e+00 4.6636895e+00 4.9091751e+00 4.4654227e+00 4.6357308e+00 4.7138095e+00 4.7476310e+00 6.1562976e+00 6.5169011e+00 4.4056782e+00 5.1487863e+00 4.2906876e+00 6.2080593e+00 4.2649736e+00 5.0159745e+00 5.3103672e+00 4.1376322e+00 4.1641326e+00 4.9769469e+00 5.1068581e+00 5.5587768e+00 5.8932164e+00 5.0159745e+00 4.3116122e+00 4.7801674e+00 5.7471732e+00 4.9809638e+00 4.7138095e+00 4.0693980e+00 4.8238988e+00 5.0813384e+00 4.6518813e+00 4.4485953e+00 5.3047149e+00 5.1807335e+00 4.7138095e+00 4.4530888e+00 4.5530210e+00 4.7507894e+00 4.3335897e+00 6.1644140e-01 1.0908712e+00 6.4031242e-01 8.5440037e-01 1.0816654e+00 9.2195445e-01 1.4628739e+00 1.2727922e+00 1.4177447e+00 1.5811388e+00 1.2247449e+00 1.0488088e+00 1.1401754e+00 1.5779734e+00 1.5968719e+00 1.0440307e+00 6.5574385e-01 3.6055513e-01 1.5556349e+00 1.4352700e+00 9.6436508e-01 1.5556349e+00 1.9313208e+00 1.1832160e+00 1.1618950e+00 2.4289916e+00 1.7916473e+00 1.1618950e+00 9.3808315e-01 1.6703293e+00 8.7749644e-01 1.6431677e+00 8.3066239e-01 1.3228757e+00 3.7907783e+00 3.4842503e+00 3.9874804e+00 3.3926391e+00 3.7443290e+00 3.5171011e+00 3.6400549e+00 2.8705400e+00 3.6715120e+00 3.1464265e+00 3.2572995e+00 3.2403703e+00 3.3970576e+00 3.6945906e+00 2.7349589e+00 3.4785054e+00 3.4899857e+00 3.1654384e+00 3.9115214e+00 3.1416556e+00 3.7854986e+00 3.1272992e+00 4.0914545e+00 3.6878178e+00 3.3749074e+00 3.4899857e+00 3.9572718e+00 4.1109610e+00 3.5425979e+00 2.7568098e+00 3.1336879e+00 3.0397368e+00 3.0495901e+00 4.1689327e+00 3.5014283e+00 3.3955854e+00 3.7603191e+00 3.7403208e+00 3.0886890e+00 3.2726136e+00 3.5114100e+00 3.5679126e+00 3.1843367e+00 2.9154759e+00 3.3166248e+00 3.1448370e+00 3.2171416e+00 3.3391616e+00 2.5903668e+00 3.1827661e+00 5.1215232e+00 4.2555846e+00 5.1156622e+00 4.6238512e+00 4.9325450e+00 5.8711157e+00 3.8652296e+00 5.4598535e+00 5.0059964e+00 5.3347915e+00 4.1952354e+00 4.4799554e+00 4.6968074e+00 4.2918527e+00 4.4192760e+00 4.4698993e+00 4.5343136e+00 5.8855756e+00 6.3253458e+00 4.2883563e+00 4.9122296e+00 4.0853396e+00 6.0133186e+00 4.0951190e+00 4.7686476e+00 5.0892043e+00 3.9572718e+00 3.9547440e+00 4.7696960e+00 4.9132474e+00 5.3721504e+00 5.6364883e+00 4.8062459e+00 4.1340053e+00 4.6054316e+00 5.5434646e+00 4.7085029e+00 4.4877611e+00 3.8600518e+00 4.6076024e+00 4.8476799e+00 4.4384682e+00 4.2555846e+00 5.0616203e+00 4.9254441e+00 4.5011110e+00 4.2976738e+00 4.3416587e+00 4.4799554e+00 4.1133928e+00 5.1961524e-01 5.1961524e-01 3.8729833e-01 6.7082039e-01 4.1231056e-01 9.2736185e-01 7.8740079e-01 1.0049876e+00 1.0488088e+00 7.0710678e-01 5.2915026e-01 5.8309519e-01 1.0535654e+00 1.0630146e+00 5.3851648e-01 4.5825757e-01 3.8729833e-01 1.0099505e+00 8.3666003e-01 4.5825757e-01 1.0099505e+00 1.3601471e+00 6.4807407e-01 5.7445626e-01 1.8384776e+00 1.2369317e+00 6.7082039e-01 6.7823300e-01 1.0908712e+00 4.7958315e-01 1.0862780e+00 3.6055513e-01 7.5498344e-01 3.9509493e+00 3.5972211e+00 4.1303753e+00 3.2664966e+00 3.8105118e+00 3.5142567e+00 3.7643060e+00 2.6191602e+00 3.7603191e+00 3.0397368e+00 2.9949958e+00 3.2680269e+00 3.3015148e+00 3.7483330e+00 2.6720778e+00 3.5972211e+00 3.5071356e+00 3.1304952e+00 3.8704005e+00 3.0413813e+00 3.8665230e+00 3.1304952e+00 4.1158231e+00 3.7282704e+00 3.4365681e+00 3.5860842e+00 4.0521599e+00 4.2284749e+00 3.5791060e+00 2.6419690e+00 3.0000000e+00 2.8948230e+00 3.0000000e+00 4.2047592e+00 3.5014283e+00 3.5057096e+00 3.8858718e+00 3.7134889e+00 3.0822070e+00 3.1733263e+00 3.4568772e+00 3.6318040e+00 3.1272992e+00 2.6608269e+00 3.2710854e+00 3.1543621e+00 3.2109189e+00 3.3837849e+00 2.3302360e+00 3.1543621e+00 5.2602281e+00 4.2766810e+00 5.2678269e+00 4.7180504e+00 5.0507425e+00 6.0522723e+00 3.7603191e+00 5.6187187e+00 5.0852729e+00 5.5479726e+00 4.3243497e+00 4.5486262e+00 4.8270074e+00 4.2778499e+00 4.4508426e+00 4.5934736e+00 4.6497312e+00 6.1400326e+00 6.4768820e+00 4.2602817e+00 5.0705029e+00 4.0951190e+00 6.1822326e+00 4.1436699e+00 4.9295030e+00 5.2706736e+00 4.0074930e+00 4.0274061e+00 4.8569538e+00 5.0734604e+00 5.5226805e+00 5.9016947e+00 4.8928519e+00 4.2035699e+00 4.6551047e+00 5.7227616e+00 4.8528342e+00 4.6086874e+00 3.9217343e+00 4.7528939e+00 4.9819675e+00 4.5760245e+00 4.2766810e+00 5.2172790e+00 5.0813384e+00 4.6173586e+00 4.3255058e+00 4.4485953e+00 4.6162756e+00 4.1785165e+00 7.3484692e-01 3.1622777e-01 4.4721360e-01 2.4494897e-01 6.5574385e-01 4.1231056e-01 6.0000000e-01 5.5677644e-01 2.6457513e-01 1.7320508e-01 1.7320508e-01 5.4772256e-01 5.4772256e-01 3.4641016e-01 6.4807407e-01 8.1240384e-01 5.0000000e-01 3.8729833e-01 4.2426407e-01 5.0000000e-01 8.7177979e-01 1.7320508e-01 1.4142136e-01 1.3453624e+00 7.7459667e-01 3.7416574e-01 5.9160798e-01 5.8309519e-01 3.7416574e-01 5.9160798e-01 3.1622777e-01 2.4494897e-01 3.9749214e+00 3.5818989e+00 4.1340053e+00 3.0594117e+00 3.7589892e+00 3.3852622e+00 3.7496667e+00 2.3130067e+00 3.7215588e+00 2.8478062e+00 2.6758176e+00 3.1890437e+00 3.1224990e+00 3.6687873e+00 2.5396850e+00 3.5958309e+00 3.3985291e+00 2.9849623e+00 3.7349699e+00 2.8530685e+00 3.8131352e+00 3.0413813e+00 4.0162171e+00 3.6318040e+00 3.3852622e+00 3.5651087e+00 4.0187063e+00 4.2107007e+00 3.4957117e+00 2.4637370e+00 2.7874720e+00 2.6739484e+00 2.8618176e+00 4.1024383e+00 3.3749074e+00 3.4813790e+00 3.8794329e+00 3.5888717e+00 2.9647934e+00 2.9866369e+00 3.2832910e+00 3.5637059e+00 2.9782545e+00 2.3558438e+00 3.1192948e+00 3.0430248e+00 3.0919250e+00 3.3136083e+00 2.0493902e+00 3.0232433e+00 5.2421370e+00 4.1689327e+00 5.2668776e+00 4.6572524e+00 5.0179677e+00 6.0646517e+00 3.5510562e+00 5.6089215e+00 5.0169712e+00 5.5991071e+00 4.3162484e+00 4.4833024e+00 4.8155997e+00 4.1484937e+00 4.3680659e+00 4.5814845e+00 4.6119410e+00 6.2088646e+00 6.4668385e+00 4.1109610e+00 5.0813384e+00 3.9849718e+00 6.1830413e+00 4.0718546e+00 4.9325450e+00 5.2829916e+00 3.9382737e+00 3.9686270e+00 4.8020829e+00 5.0705029e+00 5.5163394e+00 5.9849812e+00 4.8404545e+00 4.1303753e+00 4.5453273e+00 5.7532599e+00 4.8476799e+00 4.5727453e+00 3.8561639e+00 4.7581509e+00 4.9769469e+00 4.5923850e+00 4.1689327e+00 5.2182373e+00 5.0921508e+00 4.6097722e+00 4.2379240e+00 4.4204072e+00 4.6065171e+00 4.1024383e+00 6.3245553e-01 5.0990195e-01 6.4807407e-01 1.3228757e+00 8.0622577e-01 1.0099505e+00 1.0723805e+00 8.1853528e-01 6.2449980e-01 7.1414284e-01 1.1747340e+00 1.1489125e+00 5.4772256e-01 6.4807407e-01 5.4772256e-01 1.1000000e+00 1.0535654e+00 5.4772256e-01 1.1000000e+00 1.5811388e+00 7.5498344e-01 8.6023253e-01 1.9621417e+00 1.4899664e+00 8.2462113e-01 6.4031242e-01 1.2409674e+00 6.1644140e-01 1.2922848e+00 4.6904158e-01 9.1651514e-01 3.5014283e+00 3.1827661e+00 3.6891733e+00 2.9291637e+00 3.3896903e+00 3.1368774e+00 3.3615473e+00 2.3769729e+00 3.3211444e+00 2.7404379e+00 2.7313001e+00 2.8930952e+00 2.9034462e+00 3.3436507e+00 2.3302360e+00 3.1606961e+00 3.1511903e+00 2.7331301e+00 3.4770677e+00 2.6795522e+00 3.5014283e+00 2.7294688e+00 3.7054015e+00 3.3120990e+00 3.0099834e+00 3.1543621e+00 3.6097091e+00 3.8065733e+00 3.1906112e+00 2.2737634e+00 2.6551836e+00 2.5475478e+00 2.6210685e+00 3.8144462e+00 3.1638584e+00 3.1272992e+00 3.4539832e+00 3.3015148e+00 2.7221315e+00 2.8319605e+00 3.0951575e+00 3.2280025e+00 2.7477263e+00 2.4062419e+00 2.9103264e+00 2.7748874e+00 2.8390139e+00 2.9698485e+00 2.0928450e+00 2.7856777e+00 4.8928519e+00 3.9166312e+00 4.8456166e+00 4.3162484e+00 4.6583259e+00 5.6124861e+00 3.4828150e+00 5.1749396e+00 4.6636895e+00 5.1468437e+00 3.9306488e+00 4.1496988e+00 4.4192760e+00 3.9331921e+00 4.1206796e+00 4.2201896e+00 4.2391037e+00 5.7105166e+00 6.0398675e+00 3.8704005e+00 4.6690470e+00 3.7603191e+00 5.7349804e+00 3.7496667e+00 4.5265881e+00 4.8321838e+00 3.6207734e+00 3.6455452e+00 4.4654227e+00 4.6249324e+00 5.0803543e+00 5.4607692e+00 4.5066617e+00 3.7894591e+00 4.2449971e+00 5.2915026e+00 4.4877611e+00 4.2035699e+00 3.5482390e+00 4.3428102e+00 4.5945620e+00 4.1821047e+00 3.9166312e+00 4.8176758e+00 4.7000000e+00 4.2296572e+00 3.9370039e+00 4.0521599e+00 4.2544095e+00 3.8065733e+00 5.4772256e-01 1.4142136e-01 7.4161985e-01 5.7445626e-01 6.4807407e-01 8.1853528e-01 4.3588989e-01 3.3166248e-01 4.3588989e-01 7.3484692e-01 7.7459667e-01 5.0990195e-01 3.7416574e-01 5.8309519e-01 7.5498344e-01 6.8556546e-01 5.4772256e-01 7.5498344e-01 1.0862780e+00 4.1231056e-01 3.7416574e-01 1.6278821e+00 9.4868330e-01 4.4721360e-01 4.1231056e-01 8.6023253e-01 1.4142136e-01 7.9372539e-01 2.4494897e-01 5.2915026e-01 3.9268308e+00 3.5341194e+00 4.0902323e+00 3.1080541e+00 3.7429935e+00 3.3704599e+00 3.6905284e+00 2.3937418e+00 3.6972963e+00 2.8618176e+00 2.7820855e+00 3.1638584e+00 3.1796226e+00 3.6414283e+00 2.5436195e+00 3.5594943e+00 3.3660065e+00 2.9916551e+00 3.7696154e+00 2.8879058e+00 3.7603191e+00 3.0413813e+00 4.0162171e+00 3.6124784e+00 3.3674916e+00 3.5369478e+00 3.9987498e+00 4.1725292e+00 3.4727511e+00 2.5079872e+00 2.8372522e+00 2.7294688e+00 2.8757608e+00 4.0828911e+00 3.3421550e+00 3.4146742e+00 3.8379682e+00 3.6193922e+00 2.9410882e+00 3.0166206e+00 3.2893768e+00 3.5298725e+00 2.9983329e+00 2.4474477e+00 3.1224990e+00 3.0166206e+00 3.0757113e+00 3.2954514e+00 2.1400935e+00 3.0199338e+00 5.1749396e+00 4.1496988e+00 5.2191953e+00 4.6162756e+00 4.9699095e+00 6.0116553e+00 3.5623026e+00 5.5623736e+00 4.9989999e+00 5.5181519e+00 4.2626283e+00 4.4609416e+00 4.7717921e+00 4.1460825e+00 4.3428102e+00 4.5265881e+00 4.5661800e+00 6.1163715e+00 6.4311741e+00 4.1303753e+00 5.0239427e+00 3.9623226e+00 6.1392182e+00 4.0570926e+00 4.8672374e+00 5.2220686e+00 3.9179076e+00 3.9306488e+00 4.7686476e+00 5.0229473e+00 5.4781384e+00 5.8940648e+00 4.8072861e+00 4.1036569e+00 4.5232732e+00 5.7061370e+00 4.7770284e+00 4.5199558e+00 3.8196859e+00 4.7095647e+00 4.9264592e+00 4.5486262e+00 4.1496988e+00 5.1584882e+00 5.0289164e+00 4.5705580e+00 4.2355637e+00 4.3794977e+00 4.5365185e+00 4.0607881e+00 5.0990195e-01 1.0816654e+00 4.3588989e-01 6.3245553e-01 5.7445626e-01 4.5825757e-01 3.0000000e-01 3.6055513e-01 7.3484692e-01 6.7823300e-01 2.8284271e-01 7.6157731e-01 8.6023253e-01 6.2449980e-01 6.7082039e-01 4.2426407e-01 6.2449980e-01 1.1489125e+00 3.6055513e-01 5.8309519e-01 1.4798649e+00 1.0954451e+00 5.8309519e-01 5.7445626e-01 7.8740079e-01 5.0990195e-01 8.7749644e-01 3.7416574e-01 5.0990195e-01 3.6110940e+00 3.2511536e+00 3.7775654e+00 2.7784888e+00 3.4161382e+00 3.0822070e+00 3.4322005e+00 2.1095023e+00 3.3630343e+00 2.6095977e+00 2.4494897e+00 2.8896367e+00 2.7802878e+00 3.3436507e+00 2.2605309e+00 3.2419130e+00 3.1192948e+00 2.6551836e+00 3.4073450e+00 2.5495098e+00 3.5298725e+00 2.7110883e+00 3.6810325e+00 3.2939338e+00 3.0364453e+00 3.2140317e+00 3.6565011e+00 3.8716921e+00 3.1843367e+00 2.1470911e+00 2.4959968e+00 2.3769729e+00 2.5475478e+00 3.7907783e+00 3.1128765e+00 3.1874755e+00 3.5312887e+00 3.2434549e+00 2.6776856e+00 2.7055499e+00 2.9899833e+00 3.2403703e+00 2.6627054e+00 2.1377558e+00 2.8266588e+00 2.7386128e+00 2.7928480e+00 2.9765752e+00 1.8439089e+00 2.7239677e+00 4.9598387e+00 3.8858718e+00 4.9295030e+00 4.3393548e+00 4.7095647e+00 5.7113921e+00 3.3391616e+00 5.2516664e+00 4.6765372e+00 5.2848841e+00 4.0062451e+00 4.1641326e+00 4.4911023e+00 3.8768544e+00 4.1133928e+00 4.2906876e+00 4.2860238e+00 5.8694122e+00 6.1139185e+00 3.7920970e+00 4.7644517e+00 3.7255872e+00 5.8215118e+00 3.7549967e+00 4.6162756e+00 4.9325450e+00 3.6290495e+00 3.6674242e+00 4.4922155e+00 4.7085029e+00 5.1584882e+00 5.6338264e+00 4.5354162e+00 3.7973675e+00 4.2166337e+00 5.4055527e+00 4.5672749e+00 4.2532341e+00 3.5623026e+00 4.4317040e+00 4.6722586e+00 4.2790186e+00 3.8858718e+00 4.9040799e+00 4.7947888e+00 4.3023250e+00 3.9242834e+00 4.1060930e+00 4.3289722e+00 3.8118237e+00 7.4161985e-01 4.5825757e-01 6.1644140e-01 7.4161985e-01 3.3166248e-01 3.0000000e-01 3.8729833e-01 6.7823300e-01 7.0710678e-01 4.2426407e-01 5.0990195e-01 6.7823300e-01 7.0000000e-01 6.2449980e-01 5.2915026e-01 7.0000000e-01 1.0295630e+00 3.6055513e-01 3.1622777e-01 1.5394804e+00 9.0553851e-01 3.1622777e-01 4.1231056e-01 7.7459667e-01 2.4494897e-01 7.4161985e-01 2.8284271e-01 4.6904158e-01 3.8858718e+00 3.4856850e+00 4.0459857e+00 3.0298515e+00 3.6864617e+00 3.3136083e+00 3.6441734e+00 2.3086793e+00 3.6482873e+00 2.7874720e+00 2.6944387e+00 3.1032241e+00 3.1096624e+00 3.5888717e+00 2.4718414e+00 3.5114100e+00 3.3090784e+00 2.9342802e+00 3.6972963e+00 2.8178006e+00 3.7067506e+00 2.9782545e+00 3.9560081e+00 3.5623026e+00 3.3136083e+00 3.4856850e+00 3.9484174e+00 4.1218928e+00 3.4146742e+00 2.4351591e+00 2.7622455e+00 2.6551836e+00 2.8089144e+00 4.0261644e+00 3.2848135e+00 3.3674916e+00 3.7907783e+00 3.5524639e+00 2.8827071e+00 2.9427878e+00 3.2280025e+00 3.4785054e+00 2.9308702e+00 2.3600847e+00 3.0577770e+00 2.9631065e+00 3.0166206e+00 3.2403703e+00 2.0445048e+00 2.9563491e+00 5.1244512e+00 4.0865633e+00 5.1710734e+00 4.5661800e+00 4.9173163e+00 5.9699246e+00 3.4885527e+00 5.5208695e+00 4.9446941e+00 5.4763126e+00 4.2107007e+00 4.4022721e+00 4.7191101e+00 4.0755368e+00 4.2731721e+00 4.4710178e+00 4.5177428e+00 6.0868711e+00 6.3827894e+00 4.0644803e+00 4.9739320e+00 3.8961519e+00 6.0967204e+00 3.9949969e+00 4.8218254e+00 5.1836281e+00 3.8561639e+00 3.8742741e+00 4.7116876e+00 4.9829710e+00 5.4323107e+00 5.8668561e+00 4.7486840e+00 4.0521599e+00 4.4743715e+00 5.6586217e+00 4.7265209e+00 4.4732538e+00 3.7616486e+00 4.6583259e+00 4.8713448e+00 4.4911023e+00 4.0865633e+00 5.1097945e+00 4.9769469e+00 4.5110974e+00 4.1689327e+00 4.3243497e+00 4.4855323e+00 4.0062451e+00 9.5916630e-01 9.4339811e-01 9.3808315e-01 7.7459667e-01 7.8740079e-01 7.4833148e-01 7.2801099e-01 8.0622577e-01 9.8488578e-01 9.3273791e-01 1.1532563e+00 7.7459667e-01 6.0000000e-01 9.5393920e-01 7.7459667e-01 7.0000000e-01 7.3484692e-01 5.1961524e-01 1.3416408e+00 5.3851648e-01 8.3066239e-01 1.0677078e+00 7.5498344e-01 8.0622577e-01 5.6568542e-01 8.6602540e-01 6.4031242e-01 4.5880279e+00 4.1641326e+00 4.7370877e+00 3.5651087e+00 4.3474130e+00 3.9127995e+00 4.3162484e+00 2.7313001e+00 4.3197222e+00 3.3196385e+00 3.1000000e+00 3.7389838e+00 3.6823905e+00 4.2272923e+00 3.0757113e+00 4.2023803e+00 3.9115214e+00 3.5355339e+00 4.2965102e+00 3.3808283e+00 4.3416587e+00 3.6193922e+00 4.5825757e+00 4.1928511e+00 3.9786933e+00 4.1665333e+00 4.6216880e+00 4.7979162e+00 4.0484565e+00 3.0166206e+00 3.3015148e+00 3.1906112e+00 3.4146742e+00 4.6411206e+00 3.8652296e+00 4.0261644e+00 4.4766059e+00 4.1653331e+00 3.4899857e+00 3.4971417e+00 3.7907783e+00 4.1243181e+00 3.5270384e+00 2.7892651e+00 3.6414283e+00 3.5791060e+00 3.6262929e+00 3.8923001e+00 2.5039968e+00 3.5594943e+00 5.7680153e+00 4.6850827e+00 5.8506410e+00 5.2057660e+00 5.5686623e+00 6.6580778e+00 3.9749214e+00 6.1991935e+00 5.5874860e+00 6.1692787e+00 4.8805737e+00 5.0428167e+00 5.3907328e+00 4.6540305e+00 4.8713448e+00 5.1283526e+00 5.1749396e+00 6.7926431e+00 7.0590368e+00 4.6486557e+00 5.6524331e+00 4.4821870e+00 6.7808554e+00 4.6335731e+00 5.4954527e+00 5.8719673e+00 4.4944410e+00 4.5144213e+00 5.3525695e+00 5.6674509e+00 6.1139185e+00 6.5825527e+00 5.3888774e+00 4.6936127e+00 5.0842895e+00 6.3553127e+00 5.3786615e+00 5.1283526e+00 4.3954522e+00 5.3394756e+00 5.5371473e+00 5.1730069e+00 4.6850827e+00 5.7810034e+00 5.6462377e+00 5.1788030e+00 4.7947888e+00 4.9849774e+00 5.1351728e+00 4.6281746e+00 4.7958315e-01 4.4721360e-01 2.0000000e-01 4.2426407e-01 4.4721360e-01 5.1961524e-01 4.7958315e-01 3.8729833e-01 9.2195445e-01 1.0723805e+00 5.2915026e-01 6.0000000e-01 6.7082039e-01 5.2915026e-01 9.1104336e-01 3.7416574e-01 5.0000000e-01 1.2489996e+00 8.6602540e-01 2.6457513e-01 5.4772256e-01 5.5677644e-01 5.9160798e-01 6.6332496e-01 5.7445626e-01 4.3588989e-01 3.6646964e+00 3.2465366e+00 3.8105118e+00 2.6627054e+00 3.4088121e+00 3.0149627e+00 3.4132096e+00 1.9131126e+00 3.3852622e+00 2.4535688e+00 2.2781571e+00 2.8248894e+00 2.7495454e+00 3.3120990e+00 2.1587033e+00 3.2710854e+00 3.0298515e+00 2.6191602e+00 3.3555923e+00 2.4677925e+00 3.4568772e+00 2.6795522e+00 3.6496575e+00 3.2771939e+00 3.0413813e+00 3.2310989e+00 3.6823905e+00 3.8704005e+00 3.1320920e+00 2.0832667e+00 2.3958297e+00 2.2847319e+00 2.4859606e+00 3.7336309e+00 3.0033315e+00 3.1416556e+00 3.5496479e+00 3.2202484e+00 2.5961510e+00 2.5942244e+00 2.9034462e+00 3.2109189e+00 2.6000000e+00 1.9544820e+00 2.7386128e+00 2.6814175e+00 2.7221315e+00 2.9614186e+00 1.6401219e+00 2.6476405e+00 4.8918299e+00 3.7907783e+00 4.9284886e+00 4.3011626e+00 4.6636895e+00 5.7367238e+00 3.1559468e+00 5.2773099e+00 4.6583259e+00 5.2782573e+00 3.9724048e+00 4.1194660e+00 4.4698993e+00 3.7603191e+00 3.9887341e+00 4.2308392e+00 4.2638011e+00 5.9076222e+00 6.1261734e+00 3.7296112e+00 4.7423623e+00 3.6041643e+00 5.8532043e+00 3.7054015e+00 4.5956501e+00 4.9598387e+00 3.5721142e+00 3.6083237e+00 4.4395946e+00 4.7455242e+00 5.1826634e+00 5.6947344e+00 4.4766059e+00 3.7749172e+00 4.1844952e+00 5.4267854e+00 4.5022217e+00 4.2261093e+00 3.4928498e+00 4.4192760e+00 4.6281746e+00 4.2520583e+00 3.7907783e+00 4.8764741e+00 4.7497368e+00 4.2591079e+00 3.8639358e+00 4.0681691e+00 4.2602817e+00 3.7389838e+00 5.3851648e-01 4.1231056e-01 5.7445626e-01 6.4031242e-01 3.7416574e-01 4.2426407e-01 7.4833148e-01 9.0553851e-01 1.1747340e+00 5.1961524e-01 7.5498344e-01 9.2736185e-01 5.1961524e-01 8.2462113e-01 5.0000000e-01 6.4807407e-01 1.2922848e+00 7.4833148e-01 5.4772256e-01 5.3851648e-01 6.4807407e-01 5.8309519e-01 5.7445626e-01 7.0710678e-01 5.4772256e-01 3.7629775e+00 3.3241540e+00 3.8974351e+00 2.7055499e+00 3.4971417e+00 3.0232433e+00 3.4727511e+00 1.9000000e+00 3.4626579e+00 2.4677925e+00 2.2803509e+00 2.8896367e+00 2.8160256e+00 3.3496268e+00 2.2338308e+00 3.3749074e+00 3.0413813e+00 2.6400758e+00 3.4423829e+00 2.5019992e+00 3.4957117e+00 2.7694765e+00 3.7080992e+00 3.3000000e+00 3.1272992e+00 3.3301652e+00 3.7696154e+00 3.9534795e+00 3.1843367e+00 2.1563859e+00 2.4310492e+00 2.3173260e+00 2.5475478e+00 3.7589892e+00 2.9949958e+00 3.1874755e+00 3.6373067e+00 3.3045423e+00 2.6172505e+00 2.6305893e+00 2.8948230e+00 3.2526912e+00 2.6551836e+00 1.9621417e+00 2.7622455e+00 2.6944387e+00 2.7495454e+00 3.0298515e+00 1.7088007e+00 2.6870058e+00 4.9355851e+00 3.8236109e+00 5.0059964e+00 4.3301270e+00 4.7180504e+00 5.8051701e+00 3.1352831e+00 5.3310412e+00 4.7106263e+00 5.3600373e+00 4.0509258e+00 4.1833001e+00 4.5530210e+00 3.8039453e+00 4.0546270e+00 4.3092923e+00 4.3092923e+00 5.9674115e+00 6.2016127e+00 3.7656341e+00 4.8270074e+00 3.6386811e+00 5.9203040e+00 3.7815341e+00 4.6551047e+00 5.0169712e+00 3.6455452e+00 3.6619667e+00 4.4966654e+00 4.8052055e+00 5.2583267e+00 5.7671483e+00 4.5398238e+00 3.8131352e+00 4.1785165e+00 5.5335341e+00 4.5585085e+00 4.2626283e+00 3.5454196e+00 4.5122057e+00 4.7148701e+00 4.3760713e+00 3.8236109e+00 4.9446941e+00 4.8321838e+00 4.3669211e+00 3.9446166e+00 4.1448764e+00 4.3150898e+00 3.7643060e+00 4.4721360e-01 5.4772256e-01 4.8989795e-01 3.6055513e-01 2.2360680e-01 6.0827625e-01 1.1269428e+00 1.3152946e+00 2.0000000e-01 4.4721360e-01 7.6811457e-01 2.0000000e-01 6.7082039e-01 4.2426407e-01 5.9160798e-01 9.1651514e-01 7.0000000e-01 6.4031242e-01 8.8317609e-01 3.0000000e-01 8.0622577e-01 4.8989795e-01 7.6811457e-01 3.6055513e-01 3.8845849e+00 3.4785054e+00 4.0249224e+00 2.7766887e+00 3.6027767e+00 3.1859065e+00 3.6537652e+00 1.9748418e+00 3.5749126e+00 2.6191602e+00 2.2912878e+00 3.0430248e+00 2.8354894e+00 3.5028560e+00 2.3622024e+00 3.4899857e+00 3.2341923e+00 2.7604347e+00 3.4899857e+00 2.5903668e+00 3.6945906e+00 2.8670542e+00 3.8105118e+00 3.4438351e+00 3.2357379e+00 3.4409301e+00 3.8678159e+00 4.0865633e+00 3.3331667e+00 2.2135944e+00 2.5019992e+00 2.3790755e+00 2.6495283e+00 3.9115214e+00 3.2031235e+00 3.3955854e+00 3.7682887e+00 3.3511192e+00 2.7964263e+00 2.7331301e+00 3.0413813e+00 3.4132096e+00 2.7495454e+00 2.0049938e+00 2.9017236e+00 2.8722813e+00 2.9103264e+00 3.1543621e+00 1.7406895e+00 2.8266588e+00 5.1410116e+00 3.9837169e+00 5.1487863e+00 4.5011110e+00 4.8877398e+00 5.9472683e+00 3.3045423e+00 5.4726593e+00 4.8311489e+00 5.5443665e+00 4.2166337e+00 4.3162484e+00 4.6968074e+00 3.9420807e+00 4.2154478e+00 4.4833024e+00 4.4743715e+00 6.1595454e+00 6.3206012e+00 3.8587563e+00 4.9869831e+00 3.8118237e+00 6.0481402e+00 3.9025633e+00 4.8373546e+00 5.1768716e+00 3.7788887e+00 3.8288379e+00 4.6486557e+00 4.9436828e+00 5.3795911e+00 5.9439044e+00 4.6904158e+00 3.9585351e+00 4.3370497e+00 5.6524331e+00 4.7634021e+00 4.4429720e+00 3.7148351e+00 4.6551047e+00 4.8723711e+00 4.5033321e+00 3.9837169e+00 5.1166395e+00 5.0079936e+00 4.5011110e+00 4.0484565e+00 4.2953463e+00 4.5221676e+00 3.9522146e+00 3.1622777e-01 3.4641016e-01 4.1231056e-01 4.1231056e-01 4.1231056e-01 7.9372539e-01 9.8488578e-01 4.4721360e-01 4.8989795e-01 6.2449980e-01 4.4721360e-01 8.0622577e-01 2.4494897e-01 3.3166248e-01 1.2489996e+00 7.2801099e-01 2.2360680e-01 5.0990195e-01 5.0000000e-01 4.5825757e-01 5.2915026e-01 4.7958315e-01 3.0000000e-01 3.8275318e+00 3.4088121e+00 3.9749214e+00 2.8337255e+00 3.5805028e+00 3.1733263e+00 3.5707142e+00 2.0639767e+00 3.5524639e+00 2.6115130e+00 2.4351591e+00 2.9899833e+00 2.9257478e+00 3.4741906e+00 2.3280893e+00 3.4380227e+00 3.1843367e+00 2.7820855e+00 3.5355339e+00 2.6362853e+00 3.6124784e+00 2.8530685e+00 3.8209946e+00 3.4380227e+00 3.2109189e+00 3.4000000e+00 3.8522721e+00 4.0373258e+00 3.2969683e+00 2.2583180e+00 2.5651511e+00 2.4535688e+00 2.6570661e+00 3.8961519e+00 3.1527766e+00 3.2939338e+00 3.7148351e+00 3.3985291e+00 2.7531800e+00 2.7622455e+00 3.0610456e+00 3.3719431e+00 2.7712813e+00 2.1118712e+00 2.9017236e+00 2.8372522e+00 2.8827071e+00 3.1288976e+00 1.8083141e+00 2.8124722e+00 5.0467812e+00 3.9534795e+00 5.0941143e+00 4.4609416e+00 4.8259714e+00 5.9000000e+00 3.3045423e+00 5.4396691e+00 4.8270074e+00 5.4350713e+00 4.1352146e+00 4.2883563e+00 4.6368092e+00 3.9268308e+00 4.1533119e+00 4.3931765e+00 4.4249294e+00 6.0580525e+00 6.2952363e+00 3.9000000e+00 4.9061186e+00 3.7643060e+00 6.0183054e+00 3.8768544e+00 4.7539457e+00 5.1185936e+00 3.7416574e+00 3.7709415e+00 4.6054316e+00 4.9071377e+00 5.3497664e+00 5.8455111e+00 4.6432747e+00 3.9382737e+00 4.3416587e+00 5.5955339e+00 4.6572524e+00 4.3840620e+00 3.6551334e+00 4.5858478e+00 4.7937459e+00 4.4226689e+00 3.9534795e+00 5.0378567e+00 4.9112117e+00 4.4294469e+00 4.0385641e+00 4.2343831e+00 4.4147480e+00 3.8961519e+00 1.4142136e-01 5.9160798e-01 5.7445626e-01 3.0000000e-01 6.0827625e-01 7.6811457e-01 5.0990195e-01 4.6904158e-01 3.6055513e-01 5.0990195e-01 9.6436508e-01 1.4142136e-01 3.0000000e-01 1.4071247e+00 8.7749644e-01 4.5825757e-01 5.4772256e-01 6.5574385e-01 3.3166248e-01 6.7823300e-01 2.2360680e-01 3.0000000e-01 3.8742741e+00 3.4957117e+00 4.0373258e+00 2.9983329e+00 3.6715120e+00 3.3090784e+00 3.6674242e+00 2.2759613e+00 3.6249138e+00 2.8000000e+00 2.6324893e+00 3.1176915e+00 3.0364453e+00 3.5846897e+00 2.4779023e+00 3.5014283e+00 3.3316662e+00 2.8982753e+00 3.6578682e+00 2.7802878e+00 3.7456642e+00 2.9597297e+00 3.9319207e+00 3.5411862e+00 3.2939338e+00 3.4727511e+00 3.9217343e+00 4.1231056e+00 3.4190642e+00 2.3874673e+00 2.7202941e+00 2.6038433e+00 2.7856777e+00 4.0249224e+00 3.3136083e+00 3.4073450e+00 3.7868192e+00 3.5028560e+00 2.8948230e+00 2.9240383e+00 3.2109189e+00 3.4799425e+00 2.9017236e+00 2.3151674e+00 3.0495901e+00 2.9647934e+00 3.0182777e+00 3.2264532e+00 2.0174241e+00 2.9512709e+00 5.1759057e+00 4.1048752e+00 5.1797683e+00 4.5760245e+00 4.9426713e+00 5.9690870e+00 3.5128336e+00 5.5108983e+00 4.9295030e+00 5.5190579e+00 4.2402830e+00 4.4056782e+00 4.7349762e+00 4.0914545e+00 4.3185646e+00 4.5144213e+00 4.5276926e+00 6.1139185e+00 6.3741666e+00 4.0336088e+00 5.0029991e+00 3.9306488e+00 6.0844063e+00 3.9962482e+00 4.8518038e+00 5.1865210e+00 3.8652296e+00 3.8961519e+00 4.7275787e+00 4.9699095e+00 5.4203321e+00 5.8847260e+00 4.7686476e+00 4.0435133e+00 4.4575778e+00 5.6630381e+00 4.7822589e+00 4.4899889e+00 3.7868192e+00 4.6765372e+00 4.9050994e+00 4.5188494e+00 4.1048752e+00 5.1400389e+00 5.0219518e+00 4.5387223e+00 4.1653331e+00 4.3439613e+00 4.5420260e+00 4.0323690e+00 5.7445626e-01 5.3851648e-01 3.0000000e-01 7.1414284e-01 8.5440037e-01 4.4721360e-01 3.4641016e-01 3.3166248e-01 4.4721360e-01 9.0000000e-01 1.4142136e-01 2.6457513e-01 1.3114877e+00 8.3066239e-01 5.0000000e-01 6.7823300e-01 5.7445626e-01 4.5825757e-01 6.3245553e-01 3.3166248e-01 2.2360680e-01 3.9509493e+00 3.5749126e+00 4.1133928e+00 3.0446675e+00 3.7389838e+00 3.3808283e+00 3.7509999e+00 2.3108440e+00 3.6959437e+00 2.8600699e+00 2.6551836e+00 3.1906112e+00 3.0789609e+00 3.6592349e+00 2.5416530e+00 3.5749126e+00 3.4088121e+00 2.9631065e+00 3.7067506e+00 2.8337255e+00 3.8275318e+00 3.0232433e+00 3.9949969e+00 3.6138622e+00 3.3630343e+00 3.5440090e+00 3.9899875e+00 4.1976184e+00 3.4914181e+00 2.4372115e+00 2.7676705e+00 2.6495283e+00 2.8460499e+00 4.0963398e+00 3.3911650e+00 3.4942810e+00 3.8626416e+00 3.5538711e+00 2.9698485e+00 2.9782545e+00 3.2756679e+00 3.5566838e+00 2.9597297e+00 2.3452079e+00 3.1144823e+00 3.0413813e+00 3.0903074e+00 3.2969683e+00 2.0469489e+00 3.0182777e+00 5.2602281e+00 4.1749251e+00 5.2564246e+00 4.6540305e+00 5.0209561e+00 6.0473135e+00 3.5721142e+00 5.5883808e+00 4.9979996e+00 5.6053546e+00 4.3197222e+00 4.4754888e+00 4.8104054e+00 4.1545156e+00 4.3874822e+00 4.5934736e+00 4.6065171e+00 6.2048368e+00 6.4459289e+00 4.0902323e+00 5.0823223e+00 4.0012498e+00 6.1595454e+00 4.0632499e+00 4.9355851e+00 5.2687759e+00 3.9344631e+00 3.9724048e+00 4.8010416e+00 5.0477718e+00 5.4936327e+00 5.9741108e+00 4.8414874e+00 4.1170378e+00 4.5310043e+00 5.7367238e+00 4.8672374e+00 4.5716518e+00 3.8626416e+00 4.7528939e+00 4.9819675e+00 4.5912961e+00 4.1749251e+00 5.2211110e+00 5.1029403e+00 4.6108568e+00 4.2272923e+00 4.4192760e+00 4.6270941e+00 4.1109610e+00 1.4142136e-01 7.6157731e-01 1.0392305e+00 1.2961481e+00 2.6457513e-01 5.0000000e-01 9.0553851e-01 2.6457513e-01 4.6904158e-01 4.5825757e-01 5.2915026e-01 9.7467943e-01 4.2426407e-01 5.8309519e-01 8.0622577e-01 3.1622777e-01 7.2111026e-01 2.2360680e-01 7.8740079e-01 3.7416574e-01 4.0422766e+00 3.6041643e+00 4.1749251e+00 2.9017236e+00 3.7536649e+00 3.2832910e+00 3.7603191e+00 2.0518285e+00 3.7296112e+00 2.6888659e+00 2.4041631e+00 3.1511903e+00 3.0149627e+00 3.6193922e+00 2.4718414e+00 3.6455452e+00 3.3090784e+00 2.8896367e+00 3.6537652e+00 2.7202941e+00 3.7735925e+00 3.0149627e+00 3.9534795e+00 3.5679126e+00 3.3882149e+00 3.5958309e+00 4.0311289e+00 4.2249260e+00 3.4467376e+00 2.3685439e+00 2.6324893e+00 2.5159491e+00 2.7838822e+00 4.0187063e+00 3.2603681e+00 3.4785054e+00 3.9127995e+00 3.5242020e+00 2.8827071e+00 2.8460499e+00 3.1368774e+00 3.5270384e+00 2.8861739e+00 2.1047565e+00 3.0049958e+00 2.9664794e+00 3.0099834e+00 3.2924155e+00 1.8493242e+00 2.9359837e+00 5.2172790e+00 4.0743098e+00 5.2820451e+00 4.6054316e+00 4.9919936e+00 6.0876925e+00 3.3451457e+00 5.6124861e+00 4.9689033e+00 5.6524331e+00 4.3278170e+00 4.4407207e+00 4.8238988e+00 4.0360872e+00 4.2965102e+00 4.5814845e+00 4.5880279e+00 6.2745518e+00 6.4699304e+00 3.9924930e+00 5.1048996e+00 3.8858718e+00 6.1975802e+00 4.0323690e+00 4.9426713e+00 5.3075418e+00 3.9000000e+00 3.9306488e+00 4.7602521e+00 5.0882217e+00 5.5308227e+00 6.0728906e+00 4.8010416e+00 4.0816663e+00 4.4452222e+00 5.8051701e+00 4.8414874e+00 4.5464272e+00 3.8118237e+00 4.7853944e+00 4.9849774e+00 4.6378875e+00 4.0743098e+00 5.2258971e+00 5.1097945e+00 4.6270941e+00 4.1833001e+00 4.4136153e+00 4.5978256e+00 4.0360872e+00 7.0710678e-01 1.0862780e+00 1.3190906e+00 1.7320508e-01 4.5825757e-01 8.6023253e-01 1.7320508e-01 5.0990195e-01 4.3588989e-01 5.4772256e-01 9.1104336e-01 5.0990195e-01 6.0000000e-01 8.4261498e-01 2.4494897e-01 7.6157731e-01 3.0000000e-01 7.8740079e-01 3.4641016e-01 3.9874804e+00 3.5594943e+00 4.1218928e+00 2.8460499e+00 3.6972963e+00 3.2434549e+00 3.7229021e+00 2.0074860e+00 3.6728735e+00 2.6551836e+00 2.3452079e+00 3.1096624e+00 2.9410882e+00 3.5749126e+00 2.4269322e+00 3.5902646e+00 3.2787193e+00 2.8372522e+00 3.5874782e+00 2.6645825e+00 3.7443290e+00 2.9580399e+00 3.8974351e+00 3.5199432e+00 3.3316662e+00 3.5397740e+00 3.9711459e+00 4.1749251e+00 3.4029399e+00 2.3043437e+00 2.5748786e+00 2.4556058e+00 2.7294688e+00 3.9761791e+00 3.2357379e+00 3.4496377e+00 3.8613469e+00 3.4554305e+00 2.8478062e+00 2.7964263e+00 3.0951575e+00 3.4842503e+00 2.8301943e+00 2.0518285e+00 2.9614186e+00 2.9291637e+00 2.9698485e+00 3.2403703e+00 1.7944358e+00 2.8913665e+00 5.1903757e+00 4.0373258e+00 5.2345009e+00 4.5661800e+00 4.9537864e+00 6.0382117e+00 3.3211444e+00 5.5623736e+00 4.9162994e+00 5.6169387e+00 4.2883563e+00 4.3931765e+00 4.7780749e+00 3.9962482e+00 4.2638011e+00 4.5464272e+00 4.5464272e+00 6.2377881e+00 6.4156060e+00 3.9370039e+00 5.0635956e+00 3.8548671e+00 6.1441029e+00 3.9824616e+00 4.9061186e+00 5.2621288e+00 3.8535698e+00 3.8923001e+00 4.7180504e+00 5.0368641e+00 5.4763126e+00 6.0315835e+00 4.7592016e+00 4.0348482e+00 4.4022721e+00 5.7515215e+00 4.8145612e+00 4.5088801e+00 3.7749172e+00 4.7391982e+00 4.9446941e+00 4.5902070e+00 4.0373258e+00 5.1874849e+00 5.0744458e+00 4.5814845e+00 4.1303753e+00 4.3703547e+00 4.5716518e+00 4.0037482e+00 7.8740079e-01 8.3666003e-01 6.5574385e-01 5.7445626e-01 3.1622777e-01 6.5574385e-01 1.1135529e+00 3.6055513e-01 4.6904158e-01 1.4387495e+00 1.0583005e+00 4.6904158e-01 6.4031242e-01 7.3484692e-01 5.4772256e-01 8.5440037e-01 3.7416574e-01 4.6904158e-01 3.7202150e+00 3.3541020e+00 3.8871583e+00 2.8774989e+00 3.5199432e+00 3.2031235e+00 3.5355339e+00 2.2022716e+00 3.4799425e+00 2.7000000e+00 2.5455844e+00 2.9849623e+00 2.9000000e+00 3.4612137e+00 2.3473389e+00 3.3451457e+00 3.2264532e+00 2.7874720e+00 3.5057096e+00 2.6645825e+00 3.6249138e+00 2.8124722e+00 3.7934153e+00 3.4249088e+00 3.1464265e+00 3.3181320e+00 3.7696154e+00 3.9736633e+00 3.2893768e+00 2.2561028e+00 2.6057628e+00 2.4919872e+00 2.6551836e+00 3.9051248e+00 3.2202484e+00 3.2863353e+00 3.6373067e+00 3.3526109e+00 2.7874720e+00 2.8071338e+00 3.1144823e+00 3.3555923e+00 2.7730849e+00 2.2293497e+00 2.9376862e+00 2.8600699e+00 2.9051678e+00 3.0886890e+00 1.9078784e+00 2.8319605e+00 5.0477718e+00 3.9824616e+00 5.0299105e+00 4.4530888e+00 4.8062459e+00 5.8223707e+00 3.4278273e+00 5.3721504e+00 4.7906158e+00 5.3712196e+00 4.0951190e+00 4.2638011e+00 4.5836667e+00 3.9635842e+00 4.1809090e+00 4.3692105e+00 4.3965896e+00 5.9774577e+00 6.2209324e+00 3.9064050e+00 4.8518038e+00 3.8105118e+00 5.9371710e+00 3.8496753e+00 4.7148701e+00 5.0487622e+00 3.7215588e+00 3.7643060e+00 4.5891176e+00 4.8301139e+00 5.2697249e+00 5.7428216e+00 4.6270941e+00 3.9166312e+00 4.3520110e+00 5.4972721e+00 4.6497312e+00 4.3646306e+00 3.6565011e+00 4.5210618e+00 4.7528939e+00 4.3485630e+00 3.9824616e+00 4.9969991e+00 4.8733972e+00 4.3760713e+00 4.0149720e+00 4.1976184e+00 4.4113490e+00 3.9153544e+00 3.4641016e-01 1.0440307e+00 9.7467943e-01 7.0710678e-01 1.0440307e+00 1.3784049e+00 7.1414284e-01 6.9282032e-01 1.9519221e+00 1.2247449e+00 8.1240384e-01 5.9160798e-01 1.1916375e+00 3.4641016e-01 1.0908712e+00 4.2426407e-01 8.3666003e-01 3.9974992e+00 3.6345564e+00 4.1725292e+00 3.3196385e+00 3.8665230e+00 3.5185224e+00 3.7868192e+00 2.6514147e+00 3.8013156e+00 3.0675723e+00 3.0430248e+00 3.3090784e+00 3.3630343e+00 3.7656341e+00 2.7294688e+00 3.6537652e+00 3.5114100e+00 3.1448370e+00 3.9458839e+00 3.0789609e+00 3.8832976e+00 3.1921779e+00 4.1581246e+00 3.7349699e+00 3.4871192e+00 3.6428011e+00 4.1024383e+00 4.2743421e+00 3.6110940e+00 2.7037012e+00 3.0446675e+00 2.9376862e+00 3.0479501e+00 4.2201896e+00 3.4942810e+00 3.5185224e+00 3.9306488e+00 3.7815341e+00 3.0935417e+00 3.2155870e+00 3.4583233e+00 3.6496575e+00 3.1733263e+00 2.7073973e+00 3.2939338e+00 3.1559468e+00 3.2280025e+00 3.4234486e+00 2.4124676e+00 3.1843367e+00 5.2782573e+00 4.3034870e+00 5.3084838e+00 4.7275787e+00 5.0793700e+00 6.0811183e+00 3.7696154e+00 5.6373753e+00 5.1176166e+00 5.5830099e+00 4.3669211e+00 4.5912961e+00 4.8754487e+00 4.3208795e+00 4.5055521e+00 4.6400431e+00 4.6679760e+00 6.1473572e+00 6.5192024e+00 4.2965102e+00 5.1166395e+00 4.1255303e+00 6.2120850e+00 4.1976184e+00 4.9527770e+00 5.2867760e+00 4.0583248e+00 4.0583248e+00 4.8928519e+00 5.0941143e+00 5.5614746e+00 5.9160798e+00 4.9345719e+00 4.2213742e+00 4.6432747e+00 5.7844619e+00 4.8785244e+00 4.6184413e+00 3.9534795e+00 4.8062459e+00 5.0348784e+00 4.6572524e+00 4.3034870e+00 5.2507142e+00 5.1273775e+00 4.6893496e+00 4.3886217e+00 4.4944410e+00 4.6411206e+00 4.1892720e+00 1.2609520e+00 1.1357817e+00 7.0710678e-01 1.2609520e+00 1.6309506e+00 9.0000000e-01 8.7177979e-01 2.1517435e+00 1.4899664e+00 9.6953597e-01 7.8102497e-01 1.3928388e+00 6.0000000e-01 1.3453624e+00 5.4772256e-01 1.0295630e+00 3.9471509e+00 3.6207734e+00 4.1364236e+00 3.4029399e+00 3.8587563e+00 3.5805028e+00 3.7815341e+00 2.8017851e+00 3.7881394e+00 3.1670175e+00 3.1843367e+00 3.3361655e+00 3.4132096e+00 3.7920970e+00 2.7838822e+00 3.6180105e+00 3.5707142e+00 3.2046841e+00 3.9736633e+00 3.1559468e+00 3.9089641e+00 3.2078030e+00 4.1797129e+00 3.7696154e+00 3.4813790e+00 3.6180105e+00 4.0804412e+00 4.2532341e+00 3.6386811e+00 2.7658633e+00 3.1320920e+00 3.0282008e+00 3.0967725e+00 4.2602817e+00 3.5707142e+00 3.5298725e+00 3.9025633e+00 3.8026307e+00 3.1543621e+00 3.2954514e+00 3.5440090e+00 3.6715120e+00 3.2264532e+00 2.8478062e+00 3.3630343e+00 3.2124757e+00 3.2832910e+00 3.4351128e+00 2.5337719e+00 3.2403703e+00 5.2820451e+00 4.3497126e+00 5.2782573e+00 4.7465777e+00 5.0793700e+00 6.0415230e+00 3.8871583e+00 5.6124861e+00 5.1234754e+00 5.5344376e+00 4.3508620e+00 4.6000000e+00 4.8528342e+00 4.3737855e+00 4.5365185e+00 4.6292548e+00 4.6701178e+00 6.0901560e+00 6.4853681e+00 4.3474130e+00 5.0852729e+00 4.1785165e+00 6.1749494e+00 4.2071368e+00 4.9345719e+00 5.2545219e+00 4.0706265e+00 4.0755368e+00 4.9010203e+00 5.0645829e+00 5.5272054e+00 5.8446557e+00 4.9406477e+00 4.2402830e+00 4.6904158e+00 5.7253821e+00 4.8744230e+00 4.6249324e+00 3.9761791e+00 4.7728398e+00 5.0129831e+00 4.6119410e+00 4.3497126e+00 5.2297227e+00 5.1019604e+00 4.6615448e+00 4.4022721e+00 4.4855323e+00 4.6411206e+00 4.2249260e+00 3.4641016e-01 7.5498344e-01 0.0000000e+00 5.5677644e-01 3.7416574e-01 5.0000000e-01 9.3808315e-01 5.5677644e-01 6.5574385e-01 8.8317609e-01 2.6457513e-01 7.4161985e-01 3.4641016e-01 7.2801099e-01 2.6457513e-01 4.0435133e+00 3.6359318e+00 4.1856899e+00 2.9478806e+00 3.7709415e+00 3.3421550e+00 3.8065733e+00 2.1307276e+00 3.7389838e+00 2.7748874e+00 2.4556058e+00 3.2031235e+00 3.0133038e+00 3.6619667e+00 2.5258662e+00 3.6523965e+00 3.3852622e+00 2.9223278e+00 3.6687873e+00 2.7586228e+00 3.8457769e+00 3.0364453e+00 3.9799497e+00 3.6027767e+00 3.4014703e+00 3.6055513e+00 4.0348482e+00 4.2497059e+00 3.4942810e+00 2.3874673e+00 2.6720778e+00 2.5495098e+00 2.8178006e+00 4.0718546e+00 3.3496268e+00 3.5425979e+00 3.9293765e+00 3.5284558e+00 2.9495762e+00 2.9000000e+00 3.1984371e+00 3.5707142e+00 2.9189039e+00 2.1679483e+00 3.0626786e+00 3.0248967e+00 3.0675723e+00 3.3181320e+00 1.9104973e+00 2.9883106e+00 5.2924474e+00 4.1436699e+00 5.3113087e+00 4.6583259e+00 5.0467812e+00 6.1081912e+00 3.4525353e+00 5.6329388e+00 4.9979996e+00 5.6973678e+00 4.3749286e+00 4.4821870e+00 4.8600412e+00 4.1060930e+00 4.3760713e+00 4.6411206e+00 4.6324939e+00 6.3071388e+00 6.4876806e+00 4.0286474e+00 5.1468437e+00 3.9686270e+00 6.2112801e+00 4.0706265e+00 4.9919936e+00 5.3329167e+00 3.9446166e+00 3.9874804e+00 4.8114447e+00 5.1029403e+00 5.5443665e+00 6.0917978e+00 4.8538644e+00 4.1194660e+00 4.4933284e+00 5.8180753e+00 4.9142650e+00 4.5978256e+00 3.8729833e+00 4.8176758e+00 5.0338852e+00 4.6690470e+00 4.1436699e+00 5.2744668e+00 5.1652686e+00 4.6669048e+00 4.2201896e+00 4.4575778e+00 4.6722586e+00 4.1060930e+00 5.9160798e-01 3.4641016e-01 6.4031242e-01 3.7416574e-01 3.3166248e-01 1.0392305e+00 6.0827625e-01 6.4031242e-01 9.4868330e-01 3.6055513e-01 7.2801099e-01 4.4721360e-01 6.5574385e-01 2.2360680e-01 4.2059482e+00 3.8131352e+00 4.3588989e+00 3.1796226e+00 3.9572718e+00 3.5707142e+00 3.9887341e+00 2.3874673e+00 3.9268308e+00 3.0033315e+00 2.7147744e+00 3.3970576e+00 3.2372828e+00 3.8716921e+00 2.7239677e+00 3.8183766e+00 3.6027767e+00 3.1527766e+00 3.8755645e+00 2.9916551e+00 4.0410395e+00 3.2280025e+00 4.1904654e+00 3.8236109e+00 3.5874782e+00 3.7788887e+00 4.2190046e+00 4.4294469e+00 3.6972963e+00 2.6038433e+00 2.9086079e+00 2.7892651e+00 3.0298515e+00 4.2918527e+00 3.5749126e+00 3.7269290e+00 4.1036569e+00 3.7349699e+00 3.1654384e+00 3.1288976e+00 3.4423829e+00 3.7749172e+00 3.1368774e+00 2.4207437e+00 3.2893768e+00 3.2449961e+00 3.2848135e+00 3.5142567e+00 2.1330729e+00 3.2046841e+00 5.4799635e+00 4.3577517e+00 5.4909016e+00 4.8682646e+00 5.2392748e+00 6.2904690e+00 3.6932371e+00 5.8266629e+00 5.2057660e+00 5.8566202e+00 4.5497253e+00 4.6808119e+00 5.0378567e+00 4.3197222e+00 4.5661800e+00 4.8145612e+00 4.8311489e+00 6.4730209e+00 6.6745786e+00 4.2579338e+00 5.3169540e+00 4.1773197e+00 6.3984373e+00 4.2649736e+00 5.1730069e+00 5.5172457e+00 4.1376322e+00 4.1833001e+00 5.0089919e+00 5.2915026e+00 5.7288742e+00 6.2489999e+00 5.0477718e+00 4.3301270e+00 4.7296934e+00 5.9791304e+00 5.0921508e+00 4.7979162e+00 4.0693980e+00 4.9869831e+00 5.2057660e+00 4.8207883e+00 4.3577517e+00 5.4534393e+00 5.3329167e+00 4.8311489e+00 4.4170126e+00 4.6400431e+00 4.8507731e+00 4.3150898e+00 7.5498344e-01 1.2083046e+00 4.5825757e-01 5.0990195e-01 1.5652476e+00 1.1401754e+00 7.0710678e-01 8.0622577e-01 8.7177979e-01 5.8309519e-01 9.5393920e-01 3.4641016e-01 5.4772256e-01 3.9166312e+00 3.5818989e+00 4.0951190e+00 3.1527766e+00 3.7509999e+00 3.4612137e+00 3.7682887e+00 2.4919872e+00 3.6972963e+00 2.9883106e+00 2.8248894e+00 3.2419130e+00 3.1416556e+00 3.7040518e+00 2.6210685e+00 3.5566838e+00 3.4914181e+00 3.0347982e+00 3.7563280e+00 2.9291637e+00 3.8807216e+00 3.0577770e+00 4.0360872e+00 3.6619667e+00 3.3734256e+00 3.5369478e+00 3.9837169e+00 4.1988094e+00 3.5411862e+00 2.5159491e+00 2.8757608e+00 2.7586228e+00 2.9137605e+00 4.1581246e+00 3.4914181e+00 3.5298725e+00 3.8535698e+00 3.5916570e+00 3.0512293e+00 3.0822070e+00 3.3793490e+00 3.5972211e+00 3.0315013e+00 2.5159491e+00 3.2046841e+00 3.1144823e+00 3.1654384e+00 3.3256578e+00 2.2045408e+00 3.0951575e+00 5.2971691e+00 4.2497059e+00 5.2516664e+00 4.6957428e+00 5.0497525e+00 6.0299254e+00 3.7215588e+00 5.5821143e+00 5.0249378e+00 5.5883808e+00 4.3324358e+00 4.5099889e+00 4.8155997e+00 4.2391037e+00 4.4564560e+00 4.6162756e+00 4.6314145e+00 6.1717096e+00 6.4358372e+00 4.1617304e+00 5.0813384e+00 4.0865633e+00 6.1424751e+00 4.0987803e+00 4.9446941e+00 5.2564246e+00 3.9736633e+00 4.0162171e+00 4.8373546e+00 5.0348784e+00 5.4799635e+00 5.9245253e+00 4.8774994e+00 4.1545156e+00 4.5934736e+00 5.7043843e+00 4.8969378e+00 4.6010868e+00 3.9127995e+00 4.7476310e+00 4.9929951e+00 4.5793013e+00 4.2497059e+00 5.2297227e+00 5.1117512e+00 4.6162756e+00 4.2684892e+00 4.4384682e+00 4.6604721e+00 4.1725292e+00 5.5677644e-01 3.7416574e-01 5.0000000e-01 9.3808315e-01 5.5677644e-01 6.5574385e-01 8.8317609e-01 2.6457513e-01 7.4161985e-01 3.4641016e-01 7.2801099e-01 2.6457513e-01 4.0435133e+00 3.6359318e+00 4.1856899e+00 2.9478806e+00 3.7709415e+00 3.3421550e+00 3.8065733e+00 2.1307276e+00 3.7389838e+00 2.7748874e+00 2.4556058e+00 3.2031235e+00 3.0133038e+00 3.6619667e+00 2.5258662e+00 3.6523965e+00 3.3852622e+00 2.9223278e+00 3.6687873e+00 2.7586228e+00 3.8457769e+00 3.0364453e+00 3.9799497e+00 3.6027767e+00 3.4014703e+00 3.6055513e+00 4.0348482e+00 4.2497059e+00 3.4942810e+00 2.3874673e+00 2.6720778e+00 2.5495098e+00 2.8178006e+00 4.0718546e+00 3.3496268e+00 3.5425979e+00 3.9293765e+00 3.5284558e+00 2.9495762e+00 2.9000000e+00 3.1984371e+00 3.5707142e+00 2.9189039e+00 2.1679483e+00 3.0626786e+00 3.0248967e+00 3.0675723e+00 3.3181320e+00 1.9104973e+00 2.9883106e+00 5.2924474e+00 4.1436699e+00 5.3113087e+00 4.6583259e+00 5.0467812e+00 6.1081912e+00 3.4525353e+00 5.6329388e+00 4.9979996e+00 5.6973678e+00 4.3749286e+00 4.4821870e+00 4.8600412e+00 4.1060930e+00 4.3760713e+00 4.6411206e+00 4.6324939e+00 6.3071388e+00 6.4876806e+00 4.0286474e+00 5.1468437e+00 3.9686270e+00 6.2112801e+00 4.0706265e+00 4.9919936e+00 5.3329167e+00 3.9446166e+00 3.9874804e+00 4.8114447e+00 5.1029403e+00 5.5443665e+00 6.0917978e+00 4.8538644e+00 4.1194660e+00 4.4933284e+00 5.8180753e+00 4.9142650e+00 4.5978256e+00 3.8729833e+00 4.8176758e+00 5.0338852e+00 4.6690470e+00 4.1436699e+00 5.2744668e+00 5.1652686e+00 4.6669048e+00 4.2201896e+00 4.4575778e+00 4.6722586e+00 4.1060930e+00 8.3066239e-01 7.8740079e-01 7.1414284e-01 2.0000000e-01 9.2736185e-01 1.2369317e+00 4.2426407e-01 1.1045361e+00 3.0000000e-01 1.1575837e+00 6.7823300e-01 4.4497191e+00 3.9962482e+00 4.5727453e+00 3.1937439e+00 4.1267421e+00 3.6304270e+00 4.1496988e+00 2.2912878e+00 4.1170378e+00 2.9883106e+00 2.6153394e+00 3.5142567e+00 3.3361655e+00 3.9874804e+00 2.8195744e+00 4.0435133e+00 3.6565011e+00 3.2449961e+00 3.9761791e+00 3.0430248e+00 4.1352146e+00 3.3808283e+00 4.3023250e+00 3.9357337e+00 3.7709415e+00 3.9862263e+00 4.4147480e+00 4.6076024e+00 3.8078866e+00 2.7073973e+00 2.9376862e+00 2.8231188e+00 3.1320920e+00 4.3646306e+00 3.5958309e+00 3.8626416e+00 4.3069711e+00 3.8626416e+00 3.2388269e+00 3.1559468e+00 3.4612137e+00 3.9012818e+00 3.2264532e+00 2.3430749e+00 3.3391616e+00 3.3316662e+00 3.3645208e+00 3.6687873e+00 2.1071308e+00 3.2832910e+00 5.5749439e+00 4.4022721e+00 5.6621551e+00 4.9668904e+00 5.3535035e+00 6.4761099e+00 3.6041643e+00 5.9983331e+00 5.3244718e+00 6.0440053e+00 4.7042534e+00 4.7937459e+00 5.1971146e+00 4.3439613e+00 4.6130250e+00 4.9446941e+00 4.9608467e+00 6.6850580e+00 6.8425142e+00 4.3104524e+00 5.4827001e+00 4.2047592e+00 6.5825527e+00 4.3840620e+00 5.3244718e+00 5.7035077e+00 4.2532341e+00 4.2906876e+00 5.1127292e+00 5.4817880e+00 5.9135438e+00 6.4915329e+00 5.1507281e+00 4.4474712e+00 4.7937459e+00 6.1919302e+00 5.2057660e+00 4.9203658e+00 4.1677332e+00 5.1652686e+00 5.3507009e+00 5.0109879e+00 4.4022721e+00 5.6008928e+00 5.4799635e+00 4.9909919e+00 4.5210618e+00 4.7812132e+00 4.9618545e+00 4.3874822e+00 2.6457513e-01 1.2727922e+00 7.5498344e-01 4.3588989e-01 6.0000000e-01 5.1961524e-01 4.1231056e-01 5.4772256e-01 3.6055513e-01 1.7320508e-01 3.9153544e+00 3.5242020e+00 4.0718546e+00 2.9715316e+00 3.6905284e+00 3.3060551e+00 3.6945906e+00 2.2181073e+00 3.6496575e+00 2.7748874e+00 2.5709920e+00 3.1272992e+00 3.0232433e+00 3.5958309e+00 2.4738634e+00 3.5355339e+00 3.3316662e+00 2.8948230e+00 3.6523965e+00 2.7622455e+00 3.7589892e+00 2.9698485e+00 3.9370039e+00 3.5496479e+00 3.3151169e+00 3.5014283e+00 3.9471509e+00 4.1496988e+00 3.4278273e+00 2.3748684e+00 2.6944387e+00 2.5768197e+00 2.7820855e+00 4.0274061e+00 3.3075671e+00 3.4307434e+00 3.8183766e+00 3.5028560e+00 2.8948230e+00 2.9034462e+00 3.1953091e+00 3.4942810e+00 2.8948230e+00 2.2583180e+00 3.0397368e+00 2.9681644e+00 3.0182777e+00 3.2419130e+00 1.9672316e+00 2.9478806e+00 5.1951901e+00 4.1024383e+00 5.2086467e+00 4.5891176e+00 4.9608467e+00 6.0024995e+00 3.4785054e+00 5.5398556e+00 4.9416596e+00 5.5587768e+00 4.2661458e+00 4.4170126e+00 4.7602521e+00 4.0816663e+00 4.3185646e+00 4.5365185e+00 4.5475268e+00 6.1611687e+00 6.4007812e+00 4.0236799e+00 5.0328918e+00 3.9255573e+00 6.1155539e+00 4.0062451e+00 4.8805737e+00 5.2211110e+00 3.8755645e+00 3.9089641e+00 4.7402532e+00 5.0019996e+00 5.4497706e+00 5.9371710e+00 4.7812132e+00 4.0558600e+00 4.4598206e+00 5.7000000e+00 4.8052055e+00 4.5099889e+00 3.7973675e+00 4.7063787e+00 4.9295030e+00 4.5497253e+00 4.1024383e+00 5.1672043e+00 5.0497525e+00 4.5628938e+00 4.1701319e+00 4.3646306e+00 4.5639895e+00 4.0398020e+00 1.3000000e+00 6.7823300e-01 4.2426407e-01 6.8556546e-01 5.4772256e-01 4.4721360e-01 5.1961524e-01 4.2426407e-01 2.4494897e-01 4.1060930e+00 3.7054015e+00 4.2626283e+00 3.1591138e+00 3.8820098e+00 3.4957117e+00 3.8704005e+00 2.3895606e+00 3.8483763e+00 2.9410882e+00 2.7531800e+00 3.3030289e+00 3.2357379e+00 3.7868192e+00 2.6476405e+00 3.7242449e+00 3.5057096e+00 3.1000000e+00 3.8483763e+00 2.9597297e+00 3.9242834e+00 3.1606961e+00 4.1340053e+00 3.7509999e+00 3.5099858e+00 3.6918830e+00 4.1460825e+00 4.3347434e+00 3.6110940e+00 2.5748786e+00 2.8896367e+00 2.7766887e+00 2.9748950e+00 4.2154478e+00 3.4770677e+00 3.5972211e+00 4.0062451e+00 3.7067506e+00 3.0740852e+00 3.0886890e+00 3.3882149e+00 3.6823905e+00 3.0903074e+00 2.4351591e+00 3.2264532e+00 3.1559468e+00 3.2031235e+00 3.4351128e+00 2.1307276e+00 3.1336879e+00 5.3535035e+00 4.2755117e+00 5.3907328e+00 4.7738873e+00 5.1341991e+00 6.1919302e+00 3.6345564e+00 5.7358522e+00 5.1371198e+00 5.7210139e+00 4.4350874e+00 4.6000000e+00 4.9365980e+00 4.2508823e+00 4.4698993e+00 4.6957428e+00 4.7318073e+00 6.3364028e+00 6.5924199e+00 4.2213742e+00 5.2019227e+00 4.0865633e+00 6.3111013e+00 4.1880783e+00 5.0527220e+00 5.4101756e+00 4.0533936e+00 4.0828911e+00 4.9173163e+00 5.1990384e+00 5.6435804e+00 6.1155539e+00 4.9547957e+00 4.2497059e+00 4.6604721e+00 5.8804762e+00 4.9598387e+00 4.6914816e+00 3.9686270e+00 4.8805737e+00 5.0941143e+00 4.7127487e+00 4.2755117e+00 5.3376025e+00 5.2086467e+00 4.7275787e+00 4.3520110e+00 4.5387223e+00 4.7180504e+00 4.2130749e+00 9.1104336e-01 1.3674794e+00 1.7262677e+00 7.6811457e-01 1.6462078e+00 9.1651514e-01 1.6278821e+00 1.1269428e+00 4.4530888e+00 4.0124805e+00 4.5607017e+00 3.0479501e+00 4.0718546e+00 3.5958309e+00 4.1821047e+00 2.1587033e+00 4.0816663e+00 2.9359837e+00 2.3811762e+00 3.5071356e+00 3.1685959e+00 3.9610605e+00 2.8035692e+00 4.0373258e+00 3.6578682e+00 3.1906112e+00 3.8183766e+00 2.9410882e+00 4.1557190e+00 3.3316662e+00 4.2047592e+00 3.8961519e+00 3.7376463e+00 3.9648455e+00 4.3588989e+00 4.5803930e+00 3.7802116e+00 2.6191602e+00 2.8106939e+00 2.6944387e+00 3.0692019e+00 4.3058100e+00 3.6027767e+00 3.9230090e+00 4.2988371e+00 3.7215588e+00 3.2465366e+00 3.0545049e+00 3.3926391e+00 3.8923001e+00 3.1432467e+00 2.1771541e+00 3.2832910e+00 3.3391616e+00 3.3481338e+00 3.6400549e+00 1.9824228e+00 3.2449961e+00 5.5830099e+00 4.3416587e+00 5.6258333e+00 4.9335586e+00 5.3244718e+00 6.4366140e+00 3.5213634e+00 5.9539903e+00 5.2325902e+00 6.0712437e+00 4.7053161e+00 4.7254629e+00 5.1633323e+00 4.2497059e+00 4.5596052e+00 4.9416596e+00 4.9376108e+00 6.7275553e+00 6.7594378e+00 4.1701319e+00 5.4708317e+00 4.1605288e+00 6.5222695e+00 4.3139309e+00 5.3329167e+00 5.6956123e+00 4.2000000e+00 4.2731721e+00 5.0586559e+00 5.4516053e+00 5.8532043e+00 6.5352888e+00 5.0950957e+00 4.4011362e+00 4.7275787e+00 6.1457302e+00 5.2297227e+00 4.9132474e+00 4.1521079e+00 5.1429563e+00 5.3272882e+00 4.9839743e+00 4.3416587e+00 5.5910643e+00 5.4808758e+00 4.9537864e+00 4.4192760e+00 4.7528939e+00 4.9909919e+00 4.3749286e+00 8.3666003e-01 1.1180340e+00 4.6904158e-01 9.6953597e-01 2.2360680e-01 1.0488088e+00 6.1644140e-01 4.4452222e+00 3.9912404e+00 4.5727453e+00 3.2434549e+00 4.1412558e+00 3.6469165e+00 4.1400483e+00 2.3515952e+00 4.1267421e+00 3.0149627e+00 2.6981475e+00 3.5199432e+00 3.3896903e+00 3.9974992e+00 2.8337255e+00 4.0435133e+00 3.6619667e+00 3.2695565e+00 4.0211939e+00 3.0822070e+00 4.1303753e+00 3.3985291e+00 4.3301270e+00 3.9509493e+00 3.7815341e+00 3.9912404e+00 4.4283180e+00 4.6119410e+00 3.8183766e+00 2.7440845e+00 2.9849623e+00 2.8722813e+00 3.1575307e+00 4.3829214e+00 3.6013886e+00 3.8470768e+00 4.3069711e+00 3.9038443e+00 3.2449961e+00 3.1937439e+00 3.4899857e+00 3.9064050e+00 3.2572995e+00 2.4103942e+00 3.3630343e+00 3.3376639e+00 3.3763886e+00 3.6796739e+00 2.1633308e+00 3.3015148e+00 5.5677644e+00 4.4204072e+00 5.6656862e+00 4.9749372e+00 5.3572381e+00 6.4791975e+00 3.6373067e+00 6.0049979e+00 5.3469618e+00 6.0274373e+00 4.7000000e+00 4.8104054e+00 5.2009614e+00 4.3714986e+00 4.6260134e+00 4.9406477e+00 4.9648766e+00 6.6640828e+00 6.8571131e+00 4.3520110e+00 5.4790510e+00 4.2190046e+00 6.5916614e+00 4.4022721e+00 5.3169540e+00 5.7000000e+00 4.2673177e+00 4.2953463e+00 5.1244512e+00 5.4854353e+00 5.9236813e+00 6.4699304e+00 5.1623638e+00 4.4609416e+00 4.8145612e+00 6.1951594e+00 5.1942276e+00 4.9203658e+00 4.1725292e+00 5.1652686e+00 5.3507009e+00 5.0109879e+00 4.4204072e+00 5.5973208e+00 5.4726593e+00 4.9949975e+00 4.5475268e+00 4.7853944e+00 4.9497475e+00 4.3920383e+00 4.7958315e-01 6.4807407e-01 5.0990195e-01 6.7082039e-01 5.4772256e-01 4.8989795e-01 3.7868192e+00 3.3570821e+00 3.9331921e+00 2.8178006e+00 3.5425979e+00 3.1432467e+00 3.5128336e+00 2.0663978e+00 3.5227830e+00 2.5709920e+00 2.4535688e+00 2.9376862e+00 2.9342802e+00 3.4380227e+00 2.2825424e+00 3.3955854e+00 3.1352831e+00 2.7730849e+00 3.5142567e+00 2.6267851e+00 3.5468296e+00 2.8195744e+00 3.7934153e+00 3.4161382e+00 3.1780497e+00 3.3600595e+00 3.8223030e+00 3.9887341e+00 3.2526912e+00 2.2516660e+00 2.5592968e+00 2.4556058e+00 2.6324893e+00 3.8587563e+00 3.1032241e+00 3.2280025e+00 3.6701499e+00 3.3852622e+00 2.7110883e+00 2.7386128e+00 3.0430248e+00 3.3316662e+00 2.7513633e+00 2.1189620e+00 2.8722813e+00 2.8035692e+00 2.8460499e+00 3.0951575e+00 1.7944358e+00 2.7784888e+00 4.9699095e+00 3.9012818e+00 5.0398413e+00 4.4147480e+00 4.7644517e+00 5.8532043e+00 3.2603681e+00 5.4018515e+00 4.7927028e+00 5.3581713e+00 4.0681691e+00 4.2402830e+00 4.5771170e+00 3.8742741e+00 4.0767634e+00 4.3162484e+00 4.3760713e+00 5.9958319e+00 6.2513998e+00 3.8807216e+00 4.8373546e+00 3.7013511e+00 5.9791304e+00 3.8288379e+00 4.6893496e+00 5.0724747e+00 3.6891733e+00 3.7134889e+00 4.5497253e+00 4.8713448e+00 5.3094256e+00 5.7879185e+00 4.5836667e+00 3.9038443e+00 4.3197222e+00 5.5389530e+00 4.5760245e+00 4.3324358e+00 3.5958309e+00 4.5232732e+00 4.7212287e+00 4.3485630e+00 3.9012818e+00 4.9709154e+00 4.8321838e+00 4.3577517e+00 3.9924930e+00 4.1737274e+00 4.3335897e+00 3.8405729e+00 9.9498744e-01 3.6055513e-01 9.4868330e-01 5.0000000e-01 7.4161985e-01 3.5791060e+00 3.1654384e+00 3.7336309e+00 2.7622455e+00 3.3852622e+00 2.9883106e+00 3.3120990e+00 2.0784610e+00 3.3406586e+00 2.4939928e+00 2.4839485e+00 2.7892651e+00 2.8530685e+00 3.2634338e+00 2.1817424e+00 3.2093613e+00 2.9765752e+00 2.6267851e+00 3.4263683e+00 2.5357445e+00 3.3719431e+00 2.6870058e+00 3.6523965e+00 3.2372828e+00 3.0116441e+00 3.1843367e+00 3.6469165e+00 3.8078866e+00 3.0967725e+00 2.1725561e+00 2.4939928e+00 2.3916521e+00 2.5179357e+00 3.7013511e+00 2.9495762e+00 3.0282008e+00 3.4785054e+00 3.2787193e+00 2.5573424e+00 2.6589472e+00 2.9137605e+00 3.1511903e+00 2.6419690e+00 2.1400935e+00 2.7495454e+00 2.6324893e+00 2.6962938e+00 2.9308702e+00 1.8411953e+00 2.6476405e+00 4.7864392e+00 3.7669616e+00 4.8507731e+00 4.2308392e+00 4.5880279e+00 5.6453521e+00 3.1906112e+00 5.1932649e+00 4.6281746e+00 5.1478151e+00 3.8884444e+00 4.0877867e+00 4.4022721e+00 3.7709415e+00 3.9661064e+00 4.1496988e+00 4.1856899e+00 5.7480431e+00 6.0671245e+00 3.7669616e+00 4.6529560e+00 3.5791060e+00 5.7758116e+00 3.6891733e+00 4.4877611e+00 4.8518038e+00 3.5468296e+00 3.5496479e+00 4.3897608e+00 4.6583259e+00 5.1166395e+00 5.5362442e+00 4.4294469e+00 3.7269290e+00 4.1388404e+00 5.3525695e+00 4.3920383e+00 4.1352146e+00 3.4380227e+00 4.3439613e+00 4.5541190e+00 4.1928511e+00 3.7669616e+00 4.7812132e+00 4.6540305e+00 4.2071368e+00 3.8716921e+00 4.0062451e+00 4.1509035e+00 3.6715120e+00 8.8317609e-01 3.0000000e-01 8.7177979e-01 3.7416574e-01 4.1206796e+00 3.6945906e+00 4.2555846e+00 2.9563491e+00 3.8223030e+00 3.3852622e+00 3.8626416e+00 2.1142375e+00 3.8065733e+00 2.7766887e+00 2.4372115e+00 3.2388269e+00 3.0545049e+00 3.7148351e+00 2.5475478e+00 3.7188708e+00 3.4190642e+00 2.9782545e+00 3.6945906e+00 2.7892651e+00 3.8807216e+00 3.0805844e+00 4.0236799e+00 3.6646964e+00 3.4612137e+00 3.6674242e+00 4.1000000e+00 4.3046487e+00 3.5355339e+00 2.4228083e+00 2.6925824e+00 2.5748786e+00 2.8548205e+00 4.1121770e+00 3.3778692e+00 3.5916570e+00 3.9937451e+00 3.5693137e+00 2.9883106e+00 2.9154759e+00 3.2341923e+00 3.6249138e+00 2.9546573e+00 2.1517435e+00 3.0935417e+00 3.0757113e+00 3.1080541e+00 3.3734256e+00 1.8814888e+00 3.0232433e+00 5.3235327e+00 4.1641326e+00 5.3646994e+00 4.7063787e+00 5.0852729e+00 6.1741396e+00 3.4394767e+00 5.7026310e+00 5.0467812e+00 5.7489129e+00 4.4170126e+00 4.5188494e+00 4.9040799e+00 4.1121770e+00 4.3749286e+00 4.6701178e+00 4.6850827e+00 6.3835727e+00 6.5436993e+00 4.0595566e+00 5.1903757e+00 3.9774364e+00 6.2793312e+00 4.1036569e+00 5.0428167e+00 5.4046276e+00 3.9761791e+00 4.0236799e+00 4.8456166e+00 5.1778374e+00 5.6080300e+00 6.1757591e+00 4.8836462e+00 4.1737274e+00 4.5497253e+00 5.8736701e+00 4.9457052e+00 4.6508064e+00 3.9051248e+00 4.8641546e+00 5.0665570e+00 4.7021272e+00 4.1641326e+00 5.3188345e+00 5.1990384e+00 4.6957428e+00 4.2449971e+00 4.4966654e+00 4.7031904e+00 4.1412558e+00 8.0622577e-01 2.4494897e-01 5.4772256e-01 3.8755645e+00 3.4856850e+00 4.0385641e+00 3.0626786e+00 3.6945906e+00 3.3136083e+00 3.6414283e+00 2.3515952e+00 3.6428011e+00 2.8195744e+00 2.7386128e+00 3.1192948e+00 3.1256999e+00 3.5860842e+00 2.5039968e+00 3.5114100e+00 3.3151169e+00 2.9308702e+00 3.7242449e+00 2.8354894e+00 3.7148351e+00 2.9949958e+00 3.9635842e+00 3.5510562e+00 3.3166248e+00 3.4885527e+00 3.9458839e+00 4.1243181e+00 3.4234486e+00 2.4596748e+00 2.7874720e+00 2.6776856e+00 2.8266588e+00 4.0286474e+00 3.2908965e+00 3.3674916e+00 3.7881394e+00 3.5693137e+00 2.8896367e+00 2.9698485e+00 3.2310989e+00 3.4756294e+00 2.9478806e+00 2.4062419e+00 3.0708305e+00 2.9597297e+00 3.0232433e+00 3.2434549e+00 2.1118712e+00 2.9698485e+00 5.1322510e+00 4.1036569e+00 5.1710734e+00 4.5617979e+00 4.9234135e+00 5.9581876e+00 3.5199432e+00 5.5045436e+00 4.9446941e+00 5.4763126e+00 4.2201896e+00 4.4136153e+00 4.7275787e+00 4.1048752e+00 4.3104524e+00 4.4888751e+00 4.5133136e+00 6.0638272e+00 6.3796552e+00 4.0767634e+00 4.9819675e+00 3.9217343e+00 6.0835845e+00 4.0124805e+00 4.8197510e+00 5.1662365e+00 3.8742741e+00 3.8845849e+00 4.7222876e+00 4.9648766e+00 5.4249424e+00 5.8412327e+00 4.7634021e+00 4.0472213e+00 4.4586994e+00 5.6621551e+00 4.7370877e+00 4.4665423e+00 3.7749172e+00 4.6669048e+00 4.8877398e+00 4.5155288e+00 4.1036569e+00 5.1137071e+00 4.9909919e+00 4.5354162e+00 4.1928511e+00 4.3358967e+00 4.4966654e+00 4.0112342e+00 8.6602540e-01 4.1231056e-01 4.2532341e+00 3.8131352e+00 4.3863424e+00 3.0967725e+00 3.9623226e+00 3.4914181e+00 3.9686270e+00 2.2315914e+00 3.9420807e+00 2.8809721e+00 2.5787594e+00 3.3555923e+00 3.2186954e+00 3.8301436e+00 2.6720778e+00 3.8548671e+00 3.5128336e+00 3.1016125e+00 3.8548671e+00 2.9240383e+00 3.9761791e+00 3.2218007e+00 4.1617304e+00 3.7815341e+00 3.5986108e+00 3.8052595e+00 4.2426407e+00 4.4339599e+00 3.6537652e+00 2.5729361e+00 2.8319605e+00 2.7166155e+00 2.9899833e+00 4.2261093e+00 3.4612137e+00 3.6837481e+00 4.1231056e+00 3.7296112e+00 3.0886890e+00 3.0446675e+00 3.3421550e+00 3.7376463e+00 3.0919250e+00 2.2847319e+00 3.2093613e+00 3.1764760e+00 3.2171416e+00 3.5028560e+00 2.0273135e+00 3.1416556e+00 5.4175640e+00 4.2743421e+00 5.4909016e+00 4.8145612e+00 5.1971146e+00 6.3000000e+00 3.5270384e+00 5.8266629e+00 5.1788030e+00 5.8566202e+00 4.5321077e+00 4.6465041e+00 5.0299105e+00 4.2308392e+00 4.4866469e+00 4.7812132e+00 4.7979162e+00 6.4853681e+00 6.6805688e+00 4.1964271e+00 5.3094256e+00 4.0804412e+00 6.4109282e+00 4.2367440e+00 5.1497573e+00 5.5208695e+00 4.1036569e+00 4.1352146e+00 4.9648766e+00 5.3028294e+00 5.7428216e+00 6.2841069e+00 5.0039984e+00 4.2930176e+00 4.6572524e+00 6.0124870e+00 5.0408333e+00 4.7560488e+00 4.0149720e+00 4.9909919e+00 5.1865210e+00 4.8373546e+00 4.2743421e+00 5.4313902e+00 5.3103672e+00 4.8270074e+00 4.3852024e+00 4.6184413e+00 4.7968740e+00 4.2402830e+00 5.0990195e-01 3.8496753e+00 3.4856850e+00 4.0211939e+00 3.0757113e+00 3.6810325e+00 3.3436507e+00 3.6551334e+00 2.3937418e+00 3.6262929e+00 2.8653098e+00 2.7604347e+00 3.1352831e+00 3.1032241e+00 3.6000000e+00 2.5199206e+00 3.4885527e+00 3.3570821e+00 2.9410882e+00 3.7080992e+00 2.8460499e+00 3.7496667e+00 2.9849623e+00 3.9610605e+00 3.5623026e+00 3.3015148e+00 3.4684290e+00 3.9230090e+00 4.1170378e+00 3.4380227e+00 2.4515301e+00 2.7982137e+00 2.6851443e+00 2.8301943e+00 4.0509258e+00 3.3451457e+00 3.3970576e+00 3.7749172e+00 3.5468296e+00 2.9240383e+00 2.9899833e+00 3.2649655e+00 3.4899857e+00 2.9512709e+00 2.4351591e+00 3.0967725e+00 2.9899833e+00 3.0495901e+00 3.2403703e+00 2.1307276e+00 2.9899833e+00 5.1672043e+00 4.1352146e+00 5.1672043e+00 4.5836667e+00 4.9416596e+00 5.9497899e+00 3.5846897e+00 5.4990908e+00 4.9446941e+00 5.4836119e+00 4.2296572e+00 4.4204072e+00 4.7275787e+00 4.1340053e+00 4.3428102e+00 4.5066617e+00 4.5265881e+00 6.0671245e+00 6.3671030e+00 4.0841156e+00 4.9859803e+00 3.9623226e+00 6.0704201e+00 4.0149720e+00 4.8342528e+00 5.1643005e+00 3.8820098e+00 3.9051248e+00 4.7370877e+00 4.9547957e+00 5.4101756e+00 5.8326666e+00 4.7780749e+00 4.0570926e+00 4.4833024e+00 5.6409219e+00 4.7686476e+00 4.4866469e+00 3.7986840e+00 4.6626173e+00 4.8959167e+00 4.5044423e+00 4.1352146e+00 5.1254268e+00 5.0049975e+00 4.5332108e+00 4.1928511e+00 4.3428102e+00 4.5299007e+00 4.0459857e+00 4.0422766e+00 3.6428011e+00 4.1940434e+00 3.0364453e+00 3.7986840e+00 3.4000000e+00 3.8131352e+00 2.2516660e+00 3.7643060e+00 2.8442925e+00 2.5961510e+00 3.2295511e+00 3.1000000e+00 3.7013511e+00 2.5632011e+00 3.6565011e+00 3.4278273e+00 2.9883106e+00 3.7349699e+00 2.8390139e+00 3.8652296e+00 3.0708305e+00 4.0336088e+00 3.6537652e+00 3.4263683e+00 3.6180105e+00 4.0607881e+00 4.2649736e+00 3.5298725e+00 2.4556058e+00 2.7622455e+00 2.6438608e+00 2.8722813e+00 4.1243181e+00 3.3985291e+00 3.5468296e+00 3.9382737e+00 3.5916570e+00 2.9916551e+00 2.9765752e+00 3.2771939e+00 3.6027767e+00 2.9816103e+00 2.2912878e+00 3.1256999e+00 3.0692019e+00 3.1144823e+00 3.3496268e+00 2.0049938e+00 3.0397368e+00 5.3047149e+00 4.1928511e+00 5.3254108e+00 4.6957428e+00 5.0695167e+00 6.1237244e+00 3.5369478e+00 5.6586217e+00 5.0447993e+00 5.6841886e+00 4.3806392e+00 4.5188494e+00 4.8733972e+00 4.1629317e+00 4.4068129e+00 4.6465041e+00 4.6593991e+00 6.2952363e+00 6.5145990e+00 4.1060930e+00 5.1497573e+00 4.0124805e+00 6.2345810e+00 4.1060930e+00 4.9989999e+00 5.3450912e+00 3.9761791e+00 4.0137264e+00 4.8435524e+00 5.1234754e+00 5.5668663e+00 6.0745370e+00 4.8836462e+00 4.1617304e+00 4.5585085e+00 5.8206529e+00 4.9173163e+00 4.6227697e+00 3.9000000e+00 4.8228622e+00 5.0408333e+00 4.6636895e+00 4.1928511e+00 5.2829916e+00 5.1643005e+00 4.6722586e+00 4.2638011e+00 4.4743715e+00 4.6754679e+00 4.1412558e+00 6.4031242e-01 2.6457513e-01 1.8867962e+00 6.5574385e-01 1.3784049e+00 7.3484692e-01 2.6776856e+00 5.1961524e-01 2.0322401e+00 2.6532998e+00 1.2288206e+00 1.6278821e+00 9.4868330e-01 1.8083141e+00 4.3588989e-01 1.4317821e+00 1.4866069e+00 1.3000000e+00 1.7832555e+00 1.1747340e+00 1.2124356e+00 1.0148892e+00 1.0049876e+00 7.8740079e-01 5.3851648e-01 4.5825757e-01 5.5677644e-01 1.0677078e+00 1.9104973e+00 1.9467922e+00 2.0124612e+00 1.5394804e+00 1.2041595e+00 1.6278821e+00 1.0583005e+00 3.3166248e-01 1.1832160e+00 1.5394804e+00 1.8000000e+00 1.6552945e+00 9.2736185e-01 1.5264338e+00 2.6324893e+00 1.5716234e+00 1.4212670e+00 1.4282857e+00 9.4868330e-01 2.6608269e+00 1.4899664e+00 1.8439089e+00 1.4491377e+00 1.4071247e+00 1.2449900e+00 1.4628739e+00 2.1213203e+00 2.2427661e+00 1.7029386e+00 1.3964240e+00 1.8357560e+00 8.7749644e-01 1.1045361e+00 1.1000000e+00 1.6217275e+00 1.6613248e+00 1.2369317e+00 1.0440307e+00 2.3430749e+00 2.5495098e+00 1.4491377e+00 1.3490738e+00 1.5874508e+00 2.2383029e+00 9.6953597e-01 1.2609520e+00 1.3747727e+00 9.8488578e-01 1.0246951e+00 1.3490738e+00 1.1532563e+00 1.5905974e+00 2.1023796e+00 1.4035669e+00 9.0553851e-01 1.4071247e+00 1.8165902e+00 1.5297059e+00 1.0816654e+00 1.1000000e+00 1.0000000e+00 1.3820275e+00 9.9498744e-01 1.4491377e+00 1.5132746e+00 1.5198684e+00 1.0908712e+00 1.1489125e+00 9.4868330e-01 1.4071247e+00 1.2529964e+00 6.4807407e-01 1.3820275e+00 4.2426407e-01 8.3066239e-01 2.6457513e-01 2.1400935e+00 4.2426407e-01 1.4352700e+00 2.1563859e+00 6.1644140e-01 1.2884099e+00 4.7958315e-01 1.2569805e+00 3.4641016e-01 8.2462113e-01 1.0099505e+00 1.0198039e+00 1.2845233e+00 6.5574385e-01 7.3484692e-01 8.1240384e-01 6.1644140e-01 4.1231056e-01 3.1622777e-01 6.4807407e-01 6.4807407e-01 5.0000000e-01 1.4491377e+00 1.4491377e+00 1.5297059e+00 1.0295630e+00 8.8317609e-01 1.0198039e+00 4.5825757e-01 3.7416574e-01 9.3273791e-01 9.3808315e-01 1.2609520e+00 1.1269428e+00 3.8729833e-01 1.0295630e+00 2.1118712e+00 1.0099505e+00 8.4261498e-01 8.4261498e-01 4.5825757e-01 2.1424285e+00 9.2195445e-01 1.8083141e+00 1.0630146e+00 1.6881943e+00 1.1832160e+00 1.4933185e+00 2.5000000e+00 1.6673332e+00 2.0566964e+00 1.5362291e+00 2.0880613e+00 7.8740079e-01 1.0246951e+00 1.2489996e+00 1.2165525e+00 1.3000000e+00 1.1313708e+00 1.0677078e+00 2.7166155e+00 2.9068884e+00 1.1874342e+00 1.5264338e+00 1.1000000e+00 2.6343880e+00 7.1414284e-01 1.3784049e+00 1.7262677e+00 6.1644140e-01 6.1644140e-01 1.3152946e+00 1.5427249e+00 1.9697716e+00 2.5436195e+00 1.3638182e+00 7.2801099e-01 1.2922848e+00 2.2203603e+00 1.4387495e+00 1.0488088e+00 6.1644140e-01 1.1958261e+00 1.4560220e+00 1.1224972e+00 1.0630146e+00 1.6613248e+00 1.5937377e+00 1.1224972e+00 9.5393920e-01 8.8881944e-01 1.2369317e+00 8.6023253e-01 1.8574176e+00 5.8309519e-01 1.3152946e+00 6.7082039e-01 2.7018512e+00 5.0990195e-01 2.0149442e+00 2.6514147e+00 1.2247449e+00 1.6370706e+00 8.5440037e-01 1.8601075e+00 5.4772256e-01 1.3638182e+00 1.5033296e+00 1.2083046e+00 1.7916473e+00 1.0535654e+00 1.2569805e+00 8.4852814e-01 9.2736185e-01 8.3066239e-01 6.0000000e-01 3.4641016e-01 3.1622777e-01 1.0049876e+00 1.9748418e+00 1.9544820e+00 2.0346990e+00 1.5684387e+00 1.0099505e+00 1.5556349e+00 1.0344080e+00 2.8284271e-01 1.1357817e+00 1.5427249e+00 1.7804494e+00 1.5968719e+00 8.6602540e-01 1.5362291e+00 2.6570661e+00 1.5427249e+00 1.4247807e+00 1.4177447e+00 9.6436508e-01 2.7147744e+00 1.4866069e+00 1.6155494e+00 1.2529964e+00 1.1874342e+00 9.8994949e-01 1.2124356e+00 1.9364917e+00 2.1354157e+00 1.5000000e+00 1.1401754e+00 1.6673332e+00 6.7823300e-01 8.5440037e-01 8.6023253e-01 1.4352700e+00 1.4662878e+00 1.0295630e+00 7.8740079e-01 2.2045408e+00 2.3515952e+00 1.2767145e+00 1.1357817e+00 1.4247807e+00 2.0542639e+00 7.8102497e-01 1.0392305e+00 1.1832160e+00 8.2462113e-01 8.6023253e-01 1.0908712e+00 9.5916630e-01 1.3928388e+00 1.9974984e+00 1.1489125e+00 7.0000000e-01 1.1789826e+00 1.6522712e+00 1.3228757e+00 8.3666003e-01 9.5916630e-01 7.8102497e-01 1.1575837e+00 8.2462113e-01 1.2529964e+00 1.2884099e+00 1.3114877e+00 8.8317609e-01 9.4339811e-01 7.1414284e-01 1.2124356e+00 1.0677078e+00 1.2845233e+00 7.3484692e-01 1.4899664e+00 9.7467943e-01 1.3892444e+00 5.1961524e-01 8.2462113e-01 8.5440037e-01 5.9160798e-01 1.1045361e+00 7.2801099e-01 1.5000000e+00 8.8881944e-01 5.9160798e-01 8.8881944e-01 3.1622777e-01 1.3638182e+00 7.8102497e-01 1.2369317e+00 1.0535654e+00 1.1224972e+00 1.3674794e+00 1.6093477e+00 1.7578396e+00 9.4868330e-01 6.8556546e-01 3.0000000e-01 4.3588989e-01 5.1961524e-01 1.3076697e+00 8.8881944e-01 1.3416408e+00 1.6155494e+00 8.9442719e-01 7.1414284e-01 2.0000000e-01 5.0990195e-01 1.1045361e+00 4.3588989e-01 9.1104336e-01 4.5825757e-01 7.6157731e-01 6.6332496e-01 9.6953597e-01 1.1135529e+00 5.4772256e-01 2.6608269e+00 1.3490738e+00 2.7018512e+00 1.9519221e+00 2.3537205e+00 3.5071356e+00 9.0000000e-01 3.0232433e+00 2.2293497e+00 3.2295511e+00 1.8734994e+00 1.7378147e+00 2.2516660e+00 1.2529964e+00 1.6613248e+00 2.0760539e+00 1.9974984e+00 3.8974351e+00 3.7868192e+00 1.1401754e+00 2.5806976e+00 1.2489996e+00 3.5874782e+00 1.3638182e+00 2.4433583e+00 2.8195744e+00 1.2767145e+00 1.3820275e+00 2.0639767e+00 2.5903668e+00 2.9376862e+00 3.7762415e+00 2.1047565e+00 1.4628739e+00 1.7378147e+00 3.2771939e+00 2.3706539e+00 1.9874607e+00 1.2767145e+00 2.2803509e+00 2.4186773e+00 2.1931712e+00 1.3490738e+00 2.6664583e+00 2.6019224e+00 2.0904545e+00 1.4282857e+00 1.8493242e+00 2.1587033e+00 1.4525839e+00 8.3066239e-01 5.5677644e-01 2.1587033e+00 2.4494897e-01 1.4832397e+00 2.0856654e+00 7.4833148e-01 1.1045361e+00 4.3588989e-01 1.3638182e+00 4.2426407e-01 9.2736185e-01 1.0000000e+00 6.7823300e-01 1.2449900e+00 8.0622577e-01 7.4833148e-01 4.6904158e-01 5.0990195e-01 3.8729833e-01 3.1622777e-01 3.7416574e-01 5.2915026e-01 5.1961524e-01 1.4628739e+00 1.4000000e+00 1.4899664e+00 1.0392305e+00 7.2111026e-01 1.1224972e+00 7.9372539e-01 3.7416574e-01 6.0827625e-01 1.0677078e+00 1.2206556e+00 1.0816654e+00 4.5825757e-01 9.8994949e-01 2.1071308e+00 1.0099505e+00 9.6436508e-01 9.2195445e-01 4.7958315e-01 2.1840330e+00 9.6436508e-01 1.8027756e+00 9.5393920e-01 1.5652476e+00 1.0677078e+00 1.4035669e+00 2.3685439e+00 1.6431677e+00 1.9052559e+00 1.2884099e+00 2.0928450e+00 8.1240384e-01 8.1853528e-01 1.1401754e+00 1.0677078e+00 1.2449900e+00 1.1401754e+00 9.6953597e-01 2.7092434e+00 2.7221315e+00 8.7749644e-01 1.4730920e+00 1.0723805e+00 2.4698178e+00 4.7958315e-01 1.3638182e+00 1.6431677e+00 4.6904158e-01 6.1644140e-01 1.1704700e+00 1.4071247e+00 1.7944358e+00 2.5396850e+00 1.2247449e+00 5.3851648e-01 1.1000000e+00 2.0904545e+00 1.4866069e+00 1.0000000e+00 6.4807407e-01 1.1180340e+00 1.3928388e+00 1.0677078e+00 9.5393920e-01 1.6062378e+00 1.5811388e+00 1.0392305e+00 6.7082039e-01 8.0622577e-01 1.3152946e+00 8.6023253e-01 8.6023253e-01 1.5264338e+00 9.1104336e-01 7.9372539e-01 1.4899664e+00 4.5825757e-01 8.8881944e-01 4.6904158e-01 9.1104336e-01 1.0535654e+00 3.0000000e-01 5.1961524e-01 8.0622577e-01 7.0710678e-01 7.3484692e-01 6.4031242e-01 8.0622577e-01 4.5825757e-01 7.3484692e-01 9.3273791e-01 1.1445523e+00 1.2041595e+00 3.7416574e-01 1.0630146e+00 8.5440037e-01 9.6436508e-01 6.2449980e-01 7.4161985e-01 4.1231056e-01 7.3484692e-01 1.0816654e+00 7.8740079e-01 4.5825757e-01 6.1644140e-01 3.1622777e-01 4.6904158e-01 5.5677644e-01 1.5066519e+00 3.3166248e-01 3.7416574e-01 3.1622777e-01 5.4772256e-01 1.6552945e+00 4.0000000e-01 2.0736441e+00 8.6023253e-01 2.1447611e+00 1.3527749e+00 1.7832555e+00 2.9495762e+00 9.4339811e-01 2.4617067e+00 1.7406895e+00 2.6248809e+00 1.2845233e+00 1.2247449e+00 1.7000000e+00 9.1104336e-01 1.2569805e+00 1.5132746e+00 1.3892444e+00 3.2634338e+00 3.2863353e+00 8.6023253e-01 2.0099751e+00 8.1240384e-01 3.0545049e+00 8.8317609e-01 1.8248288e+00 2.2158520e+00 7.6811457e-01 7.8102497e-01 1.5297059e+00 2.0174241e+00 2.4103942e+00 3.1527766e+00 1.5842980e+00 8.7177979e-01 1.1916375e+00 2.7568098e+00 1.7720045e+00 1.3527749e+00 6.8556546e-01 1.7262677e+00 1.8734994e+00 1.7000000e+00 8.6023253e-01 2.0808652e+00 2.0322401e+00 1.5905974e+00 1.0295630e+00 1.2884099e+00 1.5556349e+00 8.3066239e-01 2.2561028e+00 5.9160798e-01 1.5000000e+00 2.2759613e+00 7.1414284e-01 1.4662878e+00 4.8989795e-01 1.3964240e+00 5.7445626e-01 7.9372539e-01 1.1532563e+00 1.1269428e+00 1.4212670e+00 4.6904158e-01 9.3273791e-01 8.3066239e-01 6.7082039e-01 6.4807407e-01 5.5677644e-01 7.4161985e-01 5.9160798e-01 5.4772256e-01 1.6278821e+00 1.5842980e+00 1.6763055e+00 1.1874342e+00 7.8102497e-01 9.7467943e-01 3.7416574e-01 4.5825757e-01 1.0862780e+00 1.0148892e+00 1.3638182e+00 1.1747340e+00 4.2426407e-01 1.1789826e+00 2.2383029e+00 1.0908712e+00 9.2736185e-01 9.2736185e-01 6.4807407e-01 2.2847319e+00 1.0295630e+00 1.5811388e+00 9.2736185e-01 1.5556349e+00 1.0049876e+00 1.3038405e+00 2.3748684e+00 1.6278821e+00 1.9390719e+00 1.4317821e+00 1.9157244e+00 6.0827625e-01 9.0553851e-01 1.1090537e+00 1.1180340e+00 1.1401754e+00 9.3273791e-01 9.0000000e-01 2.5632011e+00 2.7892651e+00 1.1832160e+00 1.3638182e+00 9.6953597e-01 2.5238859e+00 6.6332496e-01 1.1874342e+00 1.5968719e+00 5.5677644e-01 4.5825757e-01 1.1489125e+00 1.4525839e+00 1.8734994e+00 2.4207437e+00 1.1958261e+00 6.4807407e-01 1.1747340e+00 2.1213203e+00 1.2083046e+00 8.5440037e-01 4.7958315e-01 1.0677078e+00 1.2845233e+00 1.0246951e+00 9.2736185e-01 1.4798649e+00 1.4035669e+00 9.9498744e-01 9.0553851e-01 7.3484692e-01 1.0000000e+00 6.7082039e-01 2.2181073e+00 8.3666003e-01 4.5825757e-01 1.5556349e+00 1.3190906e+00 1.9519221e+00 9.5916630e-01 2.2583180e+00 1.5937377e+00 1.2409674e+00 1.8493242e+00 9.3273791e-01 2.1283797e+00 1.4764823e+00 2.1863211e+00 1.8973666e+00 1.8947295e+00 2.1494185e+00 2.4859606e+00 2.6419690e+00 1.7748239e+00 8.4852814e-01 7.8740079e-01 7.2111026e-01 1.1401754e+00 2.2135944e+00 1.5165751e+00 2.0024984e+00 2.4372115e+00 1.8083141e+00 1.2569805e+00 9.7467943e-01 1.2845233e+00 1.9104973e+00 1.1747340e+00 1.4142136e-01 1.2165525e+00 1.3601471e+00 1.3379088e+00 1.7406895e+00 3.8729833e-01 1.2369317e+00 3.5085610e+00 2.2248595e+00 3.6290495e+00 2.8530685e+00 3.2572995e+00 4.4440972e+00 1.3928388e+00 3.9560081e+00 3.1843367e+00 4.1012193e+00 2.7276363e+00 2.6739484e+00 3.1654384e+00 2.1307276e+00 2.4839485e+00 2.9291637e+00 2.8982753e+00 4.7749346e+00 4.7465777e+00 2.0952327e+00 3.4770677e+00 2.0518285e+00 4.5343136e+00 2.2912878e+00 3.3196385e+00 3.7229021e+00 2.1771541e+00 2.2360680e+00 2.9849623e+00 3.5014283e+00 3.8807216e+00 4.6443514e+00 3.0232433e+00 2.3685439e+00 2.6324893e+00 4.2107007e+00 3.1953091e+00 2.8670542e+00 2.1118712e+00 3.1796226e+00 3.3136083e+00 3.0692019e+00 2.2248595e+00 3.5637059e+00 3.4727511e+00 2.9832868e+00 2.3811762e+00 2.7440845e+00 2.9647934e+00 2.2891046e+00 1.5811388e+00 2.1610183e+00 8.3666003e-01 1.1401754e+00 5.1961524e-01 1.4142136e+00 3.1622777e-01 1.0295630e+00 1.0099505e+00 8.3666003e-01 1.3000000e+00 9.3273791e-01 7.8740079e-01 6.1644140e-01 5.2915026e-01 3.6055513e-01 2.4494897e-01 3.1622777e-01 5.8309519e-01 6.4031242e-01 1.4832397e+00 1.4628739e+00 1.5362291e+00 1.0862780e+00 8.6023253e-01 1.2247449e+00 8.4261498e-01 3.1622777e-01 7.0000000e-01 1.1224972e+00 1.3152946e+00 1.1618950e+00 5.1961524e-01 1.0488088e+00 2.1679483e+00 1.0954451e+00 9.9498744e-01 9.8488578e-01 5.0000000e-01 2.2383029e+00 1.0344080e+00 1.9104973e+00 1.1357817e+00 1.6093477e+00 1.1575837e+00 1.5066519e+00 2.3769729e+00 1.7944358e+00 1.9052559e+00 1.3638182e+00 2.1307276e+00 9.1651514e-01 9.6436508e-01 1.2247449e+00 1.2727922e+00 1.4525839e+00 1.2727922e+00 1.0392305e+00 2.6907248e+00 2.7549955e+00 1.0246951e+00 1.5459625e+00 1.2609520e+00 2.4738634e+00 6.8556546e-01 1.4212670e+00 1.6309506e+00 6.7823300e-01 7.7459667e-01 1.3000000e+00 1.3784049e+00 1.8055470e+00 2.4959968e+00 1.3638182e+00 6.2449980e-01 1.1618950e+00 2.1142375e+00 1.5968719e+00 1.0677078e+00 8.1240384e-01 1.1874342e+00 1.5033296e+00 1.1747340e+00 1.1357817e+00 1.6792856e+00 1.6792856e+00 1.1747340e+00 8.7749644e-01 9.3273791e-01 1.4317821e+00 1.0000000e+00 9.2195445e-01 8.2462113e-01 1.0295630e+00 1.2206556e+00 5.4772256e-01 1.6309506e+00 7.8740079e-01 7.4833148e-01 1.2727922e+00 5.3851648e-01 1.3076697e+00 9.1651514e-01 1.5033296e+00 1.2247449e+00 1.2845233e+00 1.5165751e+00 1.8384776e+00 1.9078784e+00 1.0246951e+00 7.6157731e-01 5.2915026e-01 6.1644140e-01 6.3245553e-01 1.4560220e+00 7.0710678e-01 1.2369317e+00 1.7492856e+00 1.2767145e+00 5.4772256e-01 3.8729833e-01 6.2449980e-01 1.1789826e+00 6.4807407e-01 8.4852814e-01 5.0990195e-01 6.8556546e-01 6.2449980e-01 1.1000000e+00 9.7467943e-01 5.5677644e-01 2.6814175e+00 1.4317821e+00 2.8618176e+00 2.0736441e+00 2.4556058e+00 3.6918830e+00 7.6157731e-01 3.2202484e+00 2.4617067e+00 3.2954514e+00 1.9339080e+00 1.9104973e+00 2.3874673e+00 1.3638182e+00 1.6763055e+00 2.1118712e+00 2.1213203e+00 3.9924930e+00 4.0087405e+00 1.4525839e+00 2.6814175e+00 1.2369317e+00 3.8026307e+00 1.5394804e+00 2.5179357e+00 2.9698485e+00 1.4071247e+00 1.4352700e+00 2.1977261e+00 2.7820855e+00 3.1527766e+00 3.8871583e+00 2.2315914e+00 1.6340135e+00 1.9261360e+00 3.4626579e+00 2.3643181e+00 2.0784610e+00 1.3038405e+00 2.4062419e+00 2.5099801e+00 2.3021729e+00 1.4317821e+00 2.7604347e+00 2.6570661e+00 2.2000000e+00 1.6462078e+00 1.9570386e+00 2.1330729e+00 1.4764823e+00 1.5968719e+00 1.1357817e+00 1.9026298e+00 1.1269428e+00 2.2516660e+00 1.6155494e+00 1.2206556e+00 1.6522712e+00 8.8317609e-01 2.1400935e+00 1.4798649e+00 2.0371549e+00 1.8248288e+00 1.8708287e+00 2.1283797e+00 2.3937418e+00 2.5748786e+00 1.7492856e+00 9.2195445e-01 7.1414284e-01 6.7082039e-01 1.1532563e+00 2.1000000e+00 1.5524175e+00 2.0784610e+00 2.4062419e+00 1.6370706e+00 1.3453624e+00 9.1651514e-01 1.2083046e+00 1.8920888e+00 1.1357817e+00 3.6055513e-01 1.1958261e+00 1.4212670e+00 1.3711309e+00 1.7262677e+00 7.2111026e-01 1.2569805e+00 3.4467376e+00 2.1213203e+00 3.5185224e+00 2.7477263e+00 3.1591138e+00 4.3104524e+00 1.3228757e+00 3.8183766e+00 3.0116441e+00 4.0509258e+00 2.6925824e+00 2.5495098e+00 3.0740852e+00 1.9974984e+00 2.4083189e+00 2.8861739e+00 2.8089144e+00 4.7127487e+00 4.5716518e+00 1.8814888e+00 3.4029399e+00 1.9899749e+00 4.3783559e+00 2.1863211e+00 3.2603681e+00 3.6290495e+00 2.1000000e+00 2.1931712e+00 2.8670542e+00 3.3896903e+00 3.7376463e+00 4.5891176e+00 2.9068884e+00 2.2671568e+00 2.4779023e+00 4.0914545e+00 3.1654384e+00 2.7946377e+00 2.0808652e+00 3.1048349e+00 3.2357379e+00 3.0116441e+00 2.1213203e+00 3.4828150e+00 3.4161382e+00 2.9103264e+00 2.2360680e+00 2.6720778e+00 2.9495762e+00 2.2383029e+00 9.6953597e-01 5.5677644e-01 7.0710678e-01 8.3666003e-01 4.2426407e-01 6.0000000e-01 9.0553851e-01 7.6811457e-01 7.0000000e-01 4.0000000e-01 9.4868330e-01 6.4807407e-01 5.5677644e-01 7.3484692e-01 1.1045361e+00 1.1489125e+00 3.3166248e-01 9.6953597e-01 9.1651514e-01 1.0099505e+00 5.2915026e-01 9.5916630e-01 5.8309519e-01 5.1961524e-01 9.4868330e-01 8.5440037e-01 3.7416574e-01 7.0000000e-01 6.7082039e-01 4.5825757e-01 5.4772256e-01 1.5362291e+00 4.6904158e-01 3.6055513e-01 3.0000000e-01 3.8729833e-01 1.5779734e+00 3.6055513e-01 2.1189620e+00 1.0344080e+00 2.1656408e+00 1.4899664e+00 1.8466185e+00 3.0016662e+00 1.1747340e+00 2.5436195e+00 1.8814888e+00 2.5806976e+00 1.2083046e+00 1.3076697e+00 1.6911535e+00 1.0862780e+00 1.2922848e+00 1.4628739e+00 1.4628739e+00 3.2588341e+00 3.3660065e+00 1.1357817e+00 1.9824228e+00 9.3273791e-01 3.1272992e+00 9.1104336e-01 1.8275667e+00 2.2494444e+00 7.6157731e-01 7.8740079e-01 1.6155494e+00 2.0639767e+00 2.4617067e+00 3.1192948e+00 1.6552945e+00 1.0049876e+00 1.4730920e+00 2.7367864e+00 1.7578396e+00 1.4282857e+00 6.7823300e-01 1.6763055e+00 1.8493242e+00 1.5684387e+00 1.0344080e+00 2.0928450e+00 1.9949937e+00 1.5099669e+00 1.1000000e+00 1.2688578e+00 1.5264338e+00 9.4868330e-01 1.0723805e+00 9.4868330e-01 1.2727922e+00 1.1401754e+00 5.4772256e-01 7.3484692e-01 5.1961524e-01 1.5132746e+00 6.7823300e-01 1.1135529e+00 9.4868330e-01 9.1104336e-01 1.1489125e+00 1.3416408e+00 1.6186414e+00 9.9498744e-01 7.0710678e-01 5.8309519e-01 6.1644140e-01 5.8309519e-01 1.3490738e+00 1.2247449e+00 1.4317821e+00 1.4282857e+00 5.9160798e-01 9.4868330e-01 6.5574385e-01 7.8102497e-01 1.0816654e+00 4.8989795e-01 1.2247449e+00 7.3484692e-01 9.0000000e-01 8.4261498e-01 8.4261498e-01 1.3820275e+00 7.4161985e-01 2.7477263e+00 1.5198684e+00 2.5826343e+00 1.9442222e+00 2.3600847e+00 3.3421550e+00 1.4282857e+00 2.8478062e+00 2.1118712e+00 3.1717503e+00 1.8601075e+00 1.7058722e+00 2.1771541e+00 1.4764823e+00 1.8894444e+00 2.1307276e+00 1.9442222e+00 3.7656341e+00 3.6262929e+00 1.1180340e+00 2.5278449e+00 1.5264338e+00 3.3970576e+00 1.3379088e+00 2.4083189e+00 2.6608269e+00 1.2961481e+00 1.4491377e+00 2.0712315e+00 2.3832751e+00 2.7459060e+00 3.5958309e+00 2.1260292e+00 1.3820275e+00 1.7000000e+00 3.1032241e+00 2.4596748e+00 1.9646883e+00 1.3856406e+00 2.1886069e+00 2.4124676e+00 2.1260292e+00 1.5198684e+00 2.6343880e+00 2.6153394e+00 2.0639767e+00 1.4106736e+00 1.8248288e+00 2.2649503e+00 1.5811388e+00 1.2124356e+00 7.0000000e-01 5.5677644e-01 8.0622577e-01 7.4161985e-01 1.0677078e+00 5.4772256e-01 7.1414284e-01 5.0000000e-01 2.2360680e-01 5.0990195e-01 5.9160798e-01 7.1414284e-01 7.4161985e-01 2.4494897e-01 1.3601471e+00 1.2288206e+00 1.3304135e+00 9.0000000e-01 5.0000000e-01 7.4161985e-01 5.8309519e-01 6.4031242e-01 7.0710678e-01 7.9372539e-01 1.0099505e+00 7.6157731e-01 1.4142136e-01 8.4261498e-01 1.9209373e+00 7.4161985e-01 6.7823300e-01 6.4807407e-01 4.2426407e-01 2.0346990e+00 7.3484692e-01 1.7606817e+00 7.3484692e-01 1.7146428e+00 1.0049876e+00 1.4212670e+00 2.5219040e+00 1.3152946e+00 2.0396078e+00 1.3747727e+00 2.2068076e+00 8.7749644e-01 8.6023253e-01 1.2767145e+00 8.7749644e-01 1.1224972e+00 1.1618950e+00 9.8488578e-01 2.8301943e+00 2.8809721e+00 7.7459667e-01 1.5937377e+00 8.1240384e-01 2.6324893e+00 5.2915026e-01 1.4177447e+00 1.7748239e+00 4.3588989e-01 4.5825757e-01 1.1832160e+00 1.5716234e+00 1.9773720e+00 2.7018512e+00 1.2449900e+00 4.6904158e-01 9.4868330e-01 2.3108440e+00 1.4491377e+00 9.6436508e-01 4.3588989e-01 1.2884099e+00 1.4866069e+00 1.2845233e+00 7.3484692e-01 1.6822604e+00 1.6522712e+00 1.1958261e+00 7.3484692e-01 8.8317609e-01 1.2489996e+00 6.0827625e-01 1.3784049e+00 9.2736185e-01 6.4807407e-01 1.3038405e+00 5.3851648e-01 1.3674794e+00 6.4807407e-01 1.5427249e+00 1.2165525e+00 1.0630146e+00 1.2884099e+00 1.7029386e+00 1.8275667e+00 1.0049876e+00 4.4721360e-01 5.8309519e-01 6.0000000e-01 4.2426407e-01 1.5937377e+00 9.4868330e-01 1.1445523e+00 1.5811388e+00 1.2206556e+00 5.0990195e-01 5.7445626e-01 8.6602540e-01 1.1269428e+00 5.4772256e-01 9.4868330e-01 6.3245553e-01 6.2449980e-01 6.0827625e-01 9.2195445e-01 9.0000000e-01 5.1961524e-01 2.8017851e+00 1.6401219e+00 2.8618176e+00 2.1771541e+00 2.5436195e+00 3.6945906e+00 1.2727922e+00 3.2295511e+00 2.5416530e+00 3.2771939e+00 1.9078784e+00 1.9824228e+00 2.3874673e+00 1.6186414e+00 1.8734994e+00 2.1494185e+00 2.1633308e+00 3.9547440e+00 4.0484565e+00 1.6278821e+00 2.6814175e+00 1.4798649e+00 3.8105118e+00 1.5716234e+00 2.5337719e+00 2.9427878e+00 1.4352700e+00 1.4832397e+00 2.3000000e+00 2.7386128e+00 3.1400637e+00 3.7986840e+00 2.3366643e+00 1.6703293e+00 2.0856654e+00 3.4161382e+00 2.4392622e+00 2.1307276e+00 1.3638182e+00 2.3685439e+00 2.5416530e+00 2.2315914e+00 1.6401219e+00 2.7964263e+00 2.6870058e+00 2.1863211e+00 1.7233688e+00 1.9672316e+00 2.2022716e+00 1.6124515e+00 1.1135529e+00 1.1045361e+00 1.0392305e+00 1.3820275e+00 9.8488578e-01 7.8740079e-01 8.8317609e-01 7.6157731e-01 3.8729833e-01 1.4142136e-01 5.0990195e-01 6.7823300e-01 7.4161985e-01 1.4899664e+00 1.5427249e+00 1.6062378e+00 1.1224972e+00 1.0862780e+00 1.3114877e+00 7.9372539e-01 3.1622777e-01 9.0000000e-01 1.1489125e+00 1.4035669e+00 1.3152946e+00 6.4031242e-01 1.1224972e+00 2.2135944e+00 1.1916375e+00 1.0440307e+00 1.0440307e+00 5.5677644e-01 2.2293497e+00 1.0908712e+00 1.9924859e+00 1.3076697e+00 1.7058722e+00 1.3416408e+00 1.6278821e+00 2.4799194e+00 1.9235384e+00 2.0420578e+00 1.5748016e+00 2.1447611e+00 9.4868330e-01 1.1445523e+00 1.3114877e+00 1.4422205e+00 1.5459625e+00 1.3114877e+00 1.1916375e+00 2.7239677e+00 2.8827071e+00 1.2922848e+00 1.5968719e+00 1.3820275e+00 2.5961510e+00 8.5440037e-01 1.4899664e+00 1.7262677e+00 8.1240384e-01 8.8317609e-01 1.4525839e+00 1.5033296e+00 1.9287302e+00 2.5079872e+00 1.5033296e+00 8.6602540e-01 1.4317821e+00 2.1702534e+00 1.6401219e+00 1.2083046e+00 9.0553851e-01 1.2369317e+00 1.5620499e+00 1.1575837e+00 1.3076697e+00 1.7549929e+00 1.7146428e+00 1.2083046e+00 1.0630146e+00 1.0246951e+00 1.4662878e+00 1.1401754e+00 7.3484692e-01 1.0000000e+00 8.7749644e-01 5.5677644e-01 7.6157731e-01 9.4868330e-01 6.4807407e-01 8.5440037e-01 1.0099505e+00 1.2569805e+00 1.2247449e+00 4.1231056e-01 1.1916375e+00 1.0099505e+00 1.1224972e+00 7.6157731e-01 7.8740079e-01 2.0000000e-01 5.7445626e-01 1.1224972e+00 1.0148892e+00 4.4721360e-01 7.4161985e-01 5.1961524e-01 5.1961524e-01 7.3484692e-01 1.5937377e+00 4.6904158e-01 4.3588989e-01 3.8729833e-01 6.7082039e-01 1.7058722e+00 5.0000000e-01 1.9570386e+00 8.0622577e-01 2.1377558e+00 1.3416408e+00 1.7291616e+00 2.9614186e+00 8.8317609e-01 2.4959968e+00 1.8000000e+00 2.5455844e+00 1.2083046e+00 1.2369317e+00 1.6733201e+00 8.7177979e-01 1.1180340e+00 1.4000000e+00 1.3784049e+00 3.2218007e+00 3.3120990e+00 1.0246951e+00 1.9519221e+00 6.7082039e-01 3.0886890e+00 9.1104336e-01 1.7606817e+00 2.2226111e+00 7.6157731e-01 7.0710678e-01 1.5000000e+00 2.0639767e+00 2.4494897e+00 3.1288976e+00 1.5427249e+00 9.4339811e-01 1.2767145e+00 2.7586228e+00 1.6340135e+00 1.3190906e+00 5.8309519e-01 1.6941074e+00 1.8000000e+00 1.6431677e+00 8.0622577e-01 2.0199010e+00 1.9339080e+00 1.5297059e+00 1.0723805e+00 1.2449900e+00 1.4035669e+00 7.3484692e-01 9.0553851e-01 3.6055513e-01 1.1789826e+00 4.4721360e-01 1.0862780e+00 7.0710678e-01 7.2801099e-01 9.8994949e-01 1.2884099e+00 1.4832397e+00 7.0000000e-01 6.1644140e-01 5.2915026e-01 5.8309519e-01 2.8284271e-01 1.1832160e+00 8.1240384e-01 1.0246951e+00 1.2569805e+00 7.6811457e-01 4.6904158e-01 4.7958315e-01 4.7958315e-01 7.6811457e-01 2.4494897e-01 1.2000000e+00 3.7416574e-01 3.8729833e-01 3.8729833e-01 5.7445626e-01 1.3228757e+00 3.3166248e-01 2.5436195e+00 1.3453624e+00 2.4959968e+00 1.7832555e+00 2.2158520e+00 3.2848135e+00 1.2247449e+00 2.7874720e+00 2.0928450e+00 3.0033315e+00 1.6552945e+00 1.6155494e+00 2.0639767e+00 1.3638182e+00 1.7233688e+00 1.9339080e+00 1.7832555e+00 3.6083237e+00 3.6262929e+00 1.1618950e+00 2.3895606e+00 1.3000000e+00 3.3734256e+00 1.2369317e+00 2.2226111e+00 2.5416530e+00 1.1401754e+00 1.2083046e+00 1.9570386e+00 2.3021729e+00 2.7166155e+00 3.4510868e+00 2.0149442e+00 1.2288206e+00 1.5842980e+00 3.0643107e+00 2.2248595e+00 1.7663522e+00 1.1224972e+00 2.0663978e+00 2.2759613e+00 2.0149442e+00 1.3453624e+00 2.4859606e+00 2.4454039e+00 1.9493589e+00 1.3820275e+00 1.6703293e+00 2.0074860e+00 1.3190906e+00 9.8488578e-01 1.1269428e+00 8.1240384e-01 5.0990195e-01 7.0710678e-01 7.8102497e-01 9.0553851e-01 9.0553851e-01 1.0862780e+00 7.2801099e-01 1.2884099e+00 1.0862780e+00 1.1916375e+00 9.2736185e-01 8.1240384e-01 1.1313708e+00 1.2206556e+00 1.0488088e+00 2.6457513e-01 1.0954451e+00 9.3273791e-01 8.6602540e-01 8.1853528e-01 8.1240384e-01 1.7720045e+00 8.6023253e-01 1.0344080e+00 9.3273791e-01 7.5498344e-01 1.9261360e+00 9.0000000e-01 2.1142375e+00 9.6436508e-01 1.9416488e+00 1.3416408e+00 1.7058722e+00 2.7147744e+00 1.3490738e+00 2.2427661e+00 1.4560220e+00 2.5534291e+00 1.3038405e+00 1.0440307e+00 1.5362291e+00 9.1651514e-01 1.3000000e+00 1.5231546e+00 1.3490738e+00 3.1843367e+00 2.9681644e+00 5.3851648e-01 1.8894444e+00 1.0630146e+00 2.7748874e+00 7.1414284e-01 1.8055470e+00 2.0832667e+00 7.3484692e-01 9.4868330e-01 1.4035669e+00 1.8275667e+00 2.1260292e+00 3.0512293e+00 1.4491377e+00 8.5440037e-01 1.1789826e+00 2.4677925e+00 1.8627936e+00 1.3928388e+00 9.2736185e-01 1.5716234e+00 1.7549929e+00 1.5165751e+00 9.6436508e-01 1.9899749e+00 1.9748418e+00 1.4212670e+00 7.1414284e-01 1.2124356e+00 1.7000000e+00 1.0862780e+00 1.3711309e+00 6.2449980e-01 1.2845233e+00 9.9498744e-01 1.0000000e+00 1.2609520e+00 1.5588457e+00 1.7406895e+00 9.1651514e-01 4.3588989e-01 1.7320508e-01 2.6457513e-01 3.0000000e-01 1.3747727e+00 9.0000000e-01 1.2569805e+00 1.5394804e+00 9.0553851e-01 5.7445626e-01 2.4494897e-01 5.2915026e-01 1.0392305e+00 2.6457513e-01 8.7749644e-01 4.1231056e-01 6.0000000e-01 5.4772256e-01 8.4852814e-01 1.0295630e+00 4.2426407e-01 2.7386128e+00 1.4696938e+00 2.7386128e+00 2.0074860e+00 2.4248711e+00 3.5411862e+00 1.1000000e+00 3.0495901e+00 2.3043437e+00 3.2511536e+00 1.8841444e+00 1.8110770e+00 2.2912878e+00 1.4247807e+00 1.8055470e+00 2.1283797e+00 2.0273135e+00 3.8923001e+00 3.8548671e+00 1.2727922e+00 2.6191602e+00 1.3784049e+00 3.6262929e+00 1.4212670e+00 2.4677925e+00 2.8195744e+00 1.3228757e+00 1.4106736e+00 2.1494185e+00 2.5826343e+00 2.9681644e+00 3.7469988e+00 2.1977261e+00 1.4764823e+00 1.8000000e+00 3.3075671e+00 2.4248711e+00 2.0124612e+00 1.3076697e+00 2.3021729e+00 2.4799194e+00 2.2203603e+00 1.4696938e+00 2.7147744e+00 2.6551836e+00 2.1424285e+00 1.5297059e+00 1.8867962e+00 2.2045408e+00 1.5066519e+00 1.0440307e+00 8.6602540e-01 7.5498344e-01 9.1651514e-01 9.2195445e-01 1.0630146e+00 8.5440037e-01 5.2915026e-01 1.6522712e+00 1.5132746e+00 1.6278821e+00 1.1958261e+00 6.2449980e-01 6.8556546e-01 4.2426407e-01 8.6602540e-01 1.1747340e+00 9.3273791e-01 1.2409674e+00 1.0198039e+00 5.2915026e-01 1.1704700e+00 2.1236761e+00 9.7467943e-01 8.9442719e-01 8.6023253e-01 8.2462113e-01 2.2045408e+00 9.6953597e-01 1.4491377e+00 6.0000000e-01 1.6673332e+00 9.4339811e-01 1.2489996e+00 2.5019992e+00 1.2609520e+00 2.0736441e+00 1.4594520e+00 2.0074860e+00 7.0000000e-01 8.7177979e-01 1.1958261e+00 7.8102497e-01 7.8740079e-01 8.6602540e-01 9.4339811e-01 2.7147744e+00 2.8740216e+00 1.0677078e+00 1.4352700e+00 5.4772256e-01 2.6551836e+00 6.4807407e-01 1.2449900e+00 1.7691806e+00 5.0000000e-01 3.0000000e-01 1.0677078e+00 1.6643317e+00 2.0273135e+00 2.6381812e+00 1.1000000e+00 7.0710678e-01 1.0954451e+00 2.2847319e+00 1.0954451e+00 8.6602540e-01 2.2360680e-01 1.2083046e+00 1.2845233e+00 1.1618950e+00 6.0000000e-01 1.5066519e+00 1.3964240e+00 1.0440307e+00 8.3666003e-01 7.7459667e-01 8.6023253e-01 3.6055513e-01 9.8994949e-01 7.0710678e-01 4.3588989e-01 6.7823300e-01 1.0677078e+00 1.2489996e+00 5.5677644e-01 7.3484692e-01 7.7459667e-01 8.3666003e-01 3.4641016e-01 1.1489125e+00 9.0553851e-01 8.4261498e-01 9.8994949e-01 6.7082039e-01 5.4772256e-01 6.7082039e-01 7.5498344e-01 6.4031242e-01 3.7416574e-01 1.4282857e+00 5.4772256e-01 5.0000000e-01 4.5825757e-01 3.3166248e-01 1.4594520e+00 4.1231056e-01 2.3937418e+00 1.2922848e+00 2.3000000e+00 1.6911535e+00 2.0615528e+00 3.1128765e+00 1.3928388e+00 2.6438608e+00 1.9849433e+00 2.7748874e+00 1.4212670e+00 1.4662878e+00 1.8493242e+00 1.3190906e+00 1.5842980e+00 1.7146428e+00 1.6431677e+00 3.4146742e+00 3.4655447e+00 1.1874342e+00 2.1656408e+00 1.2449900e+00 3.2155870e+00 1.0535654e+00 2.0346990e+00 2.3706539e+00 9.4868330e-01 1.0488088e+00 1.8138357e+00 2.1400935e+00 2.5416530e+00 3.2388269e+00 1.8601075e+00 1.1357817e+00 1.6155494e+00 2.8301943e+00 2.0420578e+00 1.6370706e+00 9.6953597e-01 1.8248288e+00 2.0542639e+00 1.7146428e+00 1.2922848e+00 2.2934690e+00 2.2226111e+00 1.6852300e+00 1.2206556e+00 1.4594520e+00 1.8248288e+00 1.2409674e+00 5.0990195e-01 7.5498344e-01 7.7459667e-01 6.0000000e-01 6.7823300e-01 6.4031242e-01 1.6062378e+00 1.4212670e+00 1.5297059e+00 1.1747340e+00 4.2426407e-01 1.1045361e+00 1.0344080e+00 7.4833148e-01 5.7445626e-01 1.1916375e+00 1.2206556e+00 9.9498744e-01 6.2449980e-01 1.0770330e+00 2.1307276e+00 1.0295630e+00 1.0908712e+00 1.0246951e+00 7.5498344e-01 2.2825424e+00 1.0630146e+00 1.6881943e+00 7.0000000e-01 1.5000000e+00 8.6023253e-01 1.2609520e+00 2.2781571e+00 1.4696938e+00 1.7916473e+00 1.0295630e+00 2.1118712e+00 9.0553851e-01 6.0827625e-01 1.1045361e+00 7.8740079e-01 1.0908712e+00 1.1401754e+00 8.6023253e-01 2.7166155e+00 2.5709920e+00 4.3588989e-01 1.4594520e+00 9.1104336e-01 2.3537205e+00 3.6055513e-01 1.3416408e+00 1.6124515e+00 4.4721360e-01 6.1644140e-01 9.7467943e-01 1.3711309e+00 1.7029386e+00 2.5980762e+00 1.0392305e+00 3.6055513e-01 7.4161985e-01 2.0712315e+00 1.4525839e+00 9.0553851e-01 6.6332496e-01 1.1532563e+00 1.3490738e+00 1.1832160e+00 7.0000000e-01 1.5427249e+00 1.5620499e+00 1.0677078e+00 4.1231056e-01 7.9372539e-01 1.3076697e+00 7.3484692e-01 5.1961524e-01 6.4807407e-01 7.3484692e-01 8.6023253e-01 3.8729833e-01 1.2961481e+00 1.1575837e+00 1.2489996e+00 8.6023253e-01 5.8309519e-01 8.1240384e-01 7.5498344e-01 7.3484692e-01 6.2449980e-01 8.1240384e-01 9.7467943e-01 7.0000000e-01 3.0000000e-01 7.8740079e-01 1.8601075e+00 7.2111026e-01 6.7082039e-01 6.5574385e-01 4.3588989e-01 1.9974984e+00 7.2801099e-01 1.9157244e+00 8.6602540e-01 1.8138357e+00 1.1045361e+00 1.5524175e+00 2.5903668e+00 1.3490738e+00 2.0904545e+00 1.4212670e+00 2.3452079e+00 1.0583005e+00 9.7467943e-01 1.4071247e+00 9.8994949e-01 1.3000000e+00 1.3490738e+00 1.0954451e+00 2.9257478e+00 2.9410882e+00 7.4161985e-01 1.7349352e+00 9.6436508e-01 2.6832816e+00 6.7082039e-01 1.5556349e+00 1.8493242e+00 6.1644140e-01 6.6332496e-01 1.3076697e+00 1.6186414e+00 2.0346990e+00 2.7874720e+00 1.3784049e+00 5.3851648e-01 9.4339811e-01 2.4020824e+00 1.6278821e+00 1.0862780e+00 6.4807407e-01 1.4247807e+00 1.6431677e+00 1.4491377e+00 8.6602540e-01 1.8165902e+00 1.8165902e+00 1.3638182e+00 8.4261498e-01 1.0440307e+00 1.4387495e+00 7.7459667e-01 2.6457513e-01 6.5574385e-01 8.6602540e-01 4.8989795e-01 1.1445523e+00 1.1618950e+00 1.2288206e+00 7.5498344e-01 9.6436508e-01 1.0440307e+00 7.3484692e-01 5.7445626e-01 6.1644140e-01 8.3066239e-01 1.0295630e+00 9.5916630e-01 4.4721360e-01 7.4161985e-01 1.8466185e+00 8.3066239e-01 7.2111026e-01 7.0710678e-01 2.0000000e-01 1.8920888e+00 7.3484692e-01 2.1213203e+00 1.1832160e+00 1.9235384e+00 1.3964240e+00 1.7549929e+00 2.7166155e+00 1.6155494e+00 2.2494444e+00 1.6583124e+00 2.4103942e+00 1.1090537e+00 1.1832160e+00 1.5000000e+00 1.2767145e+00 1.4899664e+00 1.4456832e+00 1.3076697e+00 3.0116441e+00 3.0886890e+00 1.0862780e+00 1.8165902e+00 1.2247449e+00 2.8195744e+00 8.1240384e-01 1.6881943e+00 1.9672316e+00 7.4161985e-01 8.4261498e-01 1.5297059e+00 1.7291616e+00 2.1470911e+00 2.8213472e+00 1.5842980e+00 8.3666003e-01 1.3711309e+00 2.4372115e+00 1.7776389e+00 1.3152946e+00 8.1853528e-01 1.4628739e+00 1.7406895e+00 1.3892444e+00 1.1832160e+00 1.9519221e+00 1.9104973e+00 1.3820275e+00 1.0099505e+00 1.1489125e+00 1.5811388e+00 1.0723805e+00 4.8989795e-01 6.7823300e-01 6.2449980e-01 1.3928388e+00 1.4212670e+00 1.4899664e+00 1.0099505e+00 9.8994949e-01 1.2083046e+00 7.5498344e-01 3.4641016e-01 7.6811457e-01 1.0488088e+00 1.2767145e+00 1.1874342e+00 5.3851648e-01 1.0000000e+00 2.1023796e+00 1.0677078e+00 9.4339811e-01 9.3273791e-01 4.3588989e-01 2.1330729e+00 9.7467943e-01 1.9874607e+00 1.2124356e+00 1.7291616e+00 1.3038405e+00 1.6155494e+00 2.5159491e+00 1.8000000e+00 2.0663978e+00 1.5427249e+00 2.1954498e+00 9.4868330e-01 1.0908712e+00 1.3190906e+00 1.3341664e+00 1.4730920e+00 1.3038405e+00 1.1747340e+00 2.7892651e+00 2.9034462e+00 1.1704700e+00 1.6217275e+00 1.2845233e+00 2.6267851e+00 7.6811457e-01 1.5099669e+00 1.7663522e+00 7.2111026e-01 8.1240384e-01 1.4177447e+00 1.5362291e+00 1.9544820e+00 2.5865034e+00 1.4696938e+00 7.9372539e-01 1.3601471e+00 2.2158520e+00 1.6401219e+00 1.1916375e+00 8.2462113e-01 1.2609520e+00 1.5684387e+00 1.1832160e+00 1.2124356e+00 1.7720045e+00 1.7320508e+00 1.2083046e+00 9.7467943e-01 1.0049876e+00 1.4594520e+00 1.0677078e+00 4.2426407e-01 8.6602540e-01 1.7606817e+00 1.7146428e+00 1.7944358e+00 1.3638182e+00 8.8317609e-01 1.4491377e+00 1.0630146e+00 3.4641016e-01 8.1853528e-01 1.4071247e+00 1.5588457e+00 1.3892444e+00 7.5498344e-01 1.3114877e+00 2.4289916e+00 1.3490738e+00 1.2845233e+00 1.2609520e+00 7.9372539e-01 2.5119713e+00 1.3076697e+00 1.7748239e+00 1.1618950e+00 1.3527749e+00 1.0295630e+00 1.3304135e+00 2.1000000e+00 1.9697716e+00 1.6340135e+00 1.1224972e+00 1.9235384e+00 8.3666003e-01 8.1853528e-01 1.0099505e+00 1.3038405e+00 1.4456832e+00 1.1747340e+00 8.8317609e-01 2.4617067e+00 2.4637370e+00 1.0246951e+00 1.3379088e+00 1.3453624e+00 2.1863211e+00 6.5574385e-01 1.2489996e+00 1.3856406e+00 7.2111026e-01 8.3666003e-01 1.1357817e+00 1.1135529e+00 1.5165751e+00 2.2649503e+00 1.2000000e+00 5.9160798e-01 1.0816654e+00 1.8303005e+00 1.5000000e+00 9.4868330e-01 9.1651514e-01 9.7467943e-01 1.3190906e+00 1.0000000e+00 1.1618950e+00 1.4764823e+00 1.5099669e+00 1.0099505e+00 7.9372539e-01 8.0622577e-01 1.3747727e+00 1.0488088e+00 8.8881944e-01 1.9748418e+00 1.8973666e+00 1.9949937e+00 1.5362291e+00 7.7459667e-01 1.4071247e+00 9.5393920e-01 3.7416574e-01 1.0816654e+00 1.4764823e+00 1.6881943e+00 1.4866069e+00 7.8102497e-01 1.4899664e+00 2.6000000e+00 1.4491377e+00 1.3747727e+00 1.3453624e+00 9.5393920e-01 2.6776856e+00 1.4177447e+00 1.3747727e+00 9.7467943e-01 1.0630146e+00 7.3484692e-01 9.6436508e-01 1.8788294e+00 1.9339080e+00 1.4387495e+00 9.4868330e-01 1.5684387e+00 4.2426407e-01 5.5677644e-01 6.4807407e-01 1.1575837e+00 1.1618950e+00 7.6157731e-01 5.4772256e-01 2.1863211e+00 2.2649503e+00 1.0816654e+00 9.6436508e-01 1.1618950e+00 2.0049938e+00 5.1961524e-01 8.6023253e-01 1.1401754e+00 5.8309519e-01 6.1644140e-01 8.0622577e-01 9.4868330e-01 1.3341664e+00 2.0322401e+00 8.6023253e-01 5.0000000e-01 9.8488578e-01 1.6031220e+00 1.0816654e+00 6.0000000e-01 7.3484692e-01 6.0827625e-01 9.2736185e-01 6.4807407e-01 9.7467943e-01 1.1045361e+00 1.1045361e+00 6.3245553e-01 6.7082039e-01 4.1231056e-01 9.6436508e-01 8.1240384e-01 1.1958261e+00 1.0723805e+00 1.1789826e+00 7.2801099e-01 6.4031242e-01 6.0827625e-01 5.0990195e-01 7.5498344e-01 7.0710678e-01 6.0827625e-01 8.3666003e-01 6.6332496e-01 2.0000000e-01 6.8556546e-01 1.7464249e+00 5.7445626e-01 5.2915026e-01 4.6904158e-01 3.4641016e-01 1.8384776e+00 5.4772256e-01 1.8708287e+00 7.7459667e-01 1.8814888e+00 1.1789826e+00 1.5620499e+00 2.7092434e+00 1.1874342e+00 2.2405357e+00 1.5588457e+00 2.3430749e+00 9.7467943e-01 1.0000000e+00 1.4177447e+00 8.6602540e-01 1.1045361e+00 1.2369317e+00 1.1618950e+00 3.0049958e+00 3.0626786e+00 8.6023253e-01 1.7262677e+00 7.6157731e-01 2.8266588e+00 6.1644140e-01 1.5652476e+00 1.9672316e+00 4.7958315e-01 5.1961524e-01 1.3190906e+00 1.7748239e+00 2.1656408e+00 2.8774989e+00 1.3674794e+00 6.7823300e-01 1.1489125e+00 2.4698178e+00 1.5362291e+00 1.1357817e+00 4.3588989e-01 1.4212670e+00 1.5968719e+00 1.3601471e+00 7.7459667e-01 1.8248288e+00 1.7578396e+00 1.2767145e+00 8.1240384e-01 1.0000000e+00 1.3190906e+00 6.8556546e-01 4.2426407e-01 3.4641016e-01 4.6904158e-01 1.7378147e+00 1.2247449e+00 1.4456832e+00 1.7146428e+00 1.1618950e+00 7.8740079e-01 6.2449980e-01 9.4339811e-01 1.3000000e+00 5.4772256e-01 7.8740079e-01 7.7459667e-01 8.3066239e-01 8.1853528e-01 1.0344080e+00 7.9372539e-01 7.0000000e-01 3.0577770e+00 1.8411953e+00 3.0149627e+00 2.3452079e+00 2.7440845e+00 3.8196859e+00 1.4628739e+00 3.3361655e+00 2.6343880e+00 3.5014283e+00 2.1354157e+00 2.1330729e+00 2.5651511e+00 1.8055470e+00 2.1377558e+00 2.4041631e+00 2.3323808e+00 4.1376322e+00 4.1533119e+00 1.6583124e+00 2.8861739e+00 1.7349352e+00 3.9089641e+00 1.7233688e+00 2.7459060e+00 3.0822070e+00 1.6186414e+00 1.7088007e+00 2.4799194e+00 2.8390139e+00 3.2403703e+00 3.9610605e+00 2.5258662e+00 1.7916473e+00 2.1748563e+00 3.5510562e+00 2.7147744e+00 2.3194827e+00 1.6062378e+00 2.5514702e+00 2.7604347e+00 2.4372115e+00 1.8411953e+00 3.0033315e+00 2.9291637e+00 2.3958297e+00 1.8520259e+00 2.1656408e+00 2.4879711e+00 1.8439089e+00 1.4142136e-01 4.4721360e-01 1.5099669e+00 1.0099505e+00 1.4106736e+00 1.7029386e+00 1.0246951e+00 7.0710678e-01 3.0000000e-01 6.4031242e-01 1.2041595e+00 4.2426407e-01 7.2111026e-01 5.4772256e-01 7.5498344e-01 7.0000000e-01 1.0148892e+00 9.0000000e-01 5.7445626e-01 2.8722813e+00 1.5842980e+00 2.8861739e+00 2.1494185e+00 2.5632011e+00 3.6891733e+00 1.1045361e+00 3.1984371e+00 2.4372115e+00 3.4029399e+00 2.0346990e+00 1.9467922e+00 2.4372115e+00 1.5165751e+00 1.9052559e+00 2.2671568e+00 2.1771541e+00 4.0521599e+00 3.9912404e+00 1.3747727e+00 2.7658633e+00 1.4798649e+00 3.7709415e+00 1.5588457e+00 2.6191602e+00 2.9765752e+00 1.4628739e+00 1.5556349e+00 2.2825424e+00 2.7386128e+00 3.1144823e+00 3.9102430e+00 2.3280893e+00 1.6278821e+00 1.9313208e+00 3.4539832e+00 2.5632011e+00 2.1633308e+00 1.4491377e+00 2.4515301e+00 2.6191602e+00 2.3622024e+00 1.5842980e+00 2.8600699e+00 2.7964263e+00 2.2803509e+00 1.6522712e+00 2.0322401e+00 2.3430749e+00 1.6431677e+00 5.0990195e-01 1.6309506e+00 1.1224972e+00 1.5000000e+00 1.7832555e+00 1.1090537e+00 7.8740079e-01 4.3588989e-01 7.5498344e-01 1.3000000e+00 5.0990195e-01 6.4807407e-01 6.6332496e-01 8.3066239e-01 7.9372539e-01 1.0908712e+00 8.1853528e-01 6.7082039e-01 2.9983329e+00 1.7175564e+00 2.9949958e+00 2.2671568e+00 2.6851443e+00 3.7934153e+00 1.2247449e+00 3.3000000e+00 2.5495098e+00 3.5128336e+00 2.1447611e+00 2.0663978e+00 2.5495098e+00 1.6552945e+00 2.0420578e+00 2.3874673e+00 2.2891046e+00 4.1521079e+00 4.1000000e+00 1.4933185e+00 2.8792360e+00 1.6155494e+00 3.8729833e+00 1.6763055e+00 2.7313001e+00 3.0757113e+00 1.5811388e+00 1.6733201e+00 2.4062419e+00 2.8319605e+00 3.2155870e+00 4.0012498e+00 2.4535688e+00 1.7349352e+00 2.0420578e+00 3.5566838e+00 2.6851443e+00 2.2759613e+00 1.5684387e+00 2.5592968e+00 2.7386128e+00 2.4698178e+00 1.7175564e+00 2.9765752e+00 2.9154759e+00 2.3958297e+00 1.7748239e+00 2.1470911e+00 2.4637370e+00 1.7663522e+00 1.2806248e+00 8.3666003e-01 1.0246951e+00 1.3038405e+00 8.1853528e-01 4.2426407e-01 3.8729833e-01 5.9160798e-01 8.4261498e-01 1.4142136e-01 1.0954451e+00 3.7416574e-01 4.3588989e-01 3.8729833e-01 6.0827625e-01 1.1618950e+00 2.6457513e-01 2.5903668e+00 1.3892444e+00 2.5670995e+00 1.8814888e+00 2.2781571e+00 3.3808283e+00 1.2083046e+00 2.9000000e+00 2.1954498e+00 3.0495901e+00 1.6792856e+00 1.6763055e+00 2.1118712e+00 1.3784049e+00 1.7000000e+00 1.9442222e+00 1.8708287e+00 3.6959437e+00 3.7188708e+00 1.2609520e+00 2.4310492e+00 1.3000000e+00 3.4785054e+00 1.2688578e+00 2.2847319e+00 2.6419690e+00 1.1575837e+00 1.2409674e+00 2.0174241e+00 2.4124676e+00 2.8106939e+00 3.5369478e+00 2.0639767e+00 1.3379088e+00 1.7406895e+00 3.1224990e+00 2.2516660e+00 1.8547237e+00 1.1401754e+00 2.1047565e+00 2.3021729e+00 2.0049938e+00 1.3892444e+00 2.5416530e+00 2.4698178e+00 1.9493589e+00 1.4106736e+00 1.7058722e+00 2.0273135e+00 1.3784049e+00 9.0553851e-01 9.2195445e-01 9.0553851e-01 9.1104336e-01 1.1575837e+00 1.2609520e+00 9.5393920e-01 6.2449980e-01 1.1916375e+00 2.1817424e+00 1.0295630e+00 1.0723805e+00 1.0148892e+00 9.0000000e-01 2.3473389e+00 1.0908712e+00 1.4387495e+00 3.6055513e-01 1.4798649e+00 6.4807407e-01 1.0908712e+00 2.2693611e+00 1.2727922e+00 1.7916473e+00 1.0295630e+00 2.0149442e+00 8.1240384e-01 5.3851648e-01 1.0677078e+00 5.4772256e-01 8.3066239e-01 9.6953597e-01 7.3484692e-01 2.6495283e+00 2.5748786e+00 5.1961524e-01 1.3820275e+00 6.0827625e-01 2.3706539e+00 4.1231056e-01 1.2083046e+00 1.5937377e+00 4.2426407e-01 4.2426407e-01 8.1853528e-01 1.4212670e+00 1.7492856e+00 2.5826343e+00 8.8317609e-01 3.3166248e-01 5.5677644e-01 2.1142375e+00 1.2124356e+00 7.2111026e-01 4.6904158e-01 1.1445523e+00 1.2409674e+00 1.2083046e+00 3.6055513e-01 1.4212670e+00 1.4212670e+00 1.0392305e+00 4.7958315e-01 7.1414284e-01 1.0535654e+00 3.7416574e-01 7.2801099e-01 1.3190906e+00 1.1618950e+00 4.8989795e-01 7.4161985e-01 5.1961524e-01 7.1414284e-01 8.1240384e-01 1.5297059e+00 5.0990195e-01 5.1961524e-01 4.7958315e-01 8.5440037e-01 1.6583124e+00 5.7445626e-01 2.0371549e+00 8.7749644e-01 2.2825424e+00 1.4560220e+00 1.8411953e+00 3.1000000e+00 7.3484692e-01 2.6362853e+00 1.9287302e+00 2.6758176e+00 1.3638182e+00 1.3747727e+00 1.8220867e+00 9.1651514e-01 1.1704700e+00 1.5231546e+00 1.5165751e+00 3.3555923e+00 3.4423829e+00 1.1180340e+00 2.0904545e+00 7.0000000e-01 3.2280025e+00 1.0723805e+00 1.8920888e+00 2.3706539e+00 9.2736185e-01 8.6023253e-01 1.6155494e+00 2.2226111e+00 2.6000000e+00 3.2787193e+00 1.6552945e+00 1.1000000e+00 1.3674794e+00 2.9137605e+00 1.7291616e+00 1.4491377e+00 7.3484692e-01 1.8520259e+00 1.9287302e+00 1.8055470e+00 8.7749644e-01 2.1447611e+00 2.0542639e+00 1.6792856e+00 1.2124356e+00 1.3964240e+00 1.5000000e+00 8.3666003e-01 7.9372539e-01 1.1832160e+00 7.5498344e-01 1.1832160e+00 1.0295630e+00 4.6904158e-01 1.0440307e+00 2.0024984e+00 9.1104336e-01 7.0710678e-01 7.2111026e-01 6.4807407e-01 2.0297783e+00 8.3666003e-01 1.7776389e+00 9.8994949e-01 1.8920888e+00 1.2609520e+00 1.5684387e+00 2.7166155e+00 1.4247807e+00 2.2847319e+00 1.7406895e+00 2.2022716e+00 9.0000000e-01 1.1747340e+00 1.4317821e+00 1.1445523e+00 1.1832160e+00 1.1532563e+00 1.2041595e+00 2.8722813e+00 3.1272992e+00 1.3038405e+00 1.6673332e+00 9.1651514e-01 2.8722813e+00 8.8317609e-01 1.4798649e+00 1.9416488e+00 7.2801099e-01 6.0827625e-01 1.4071247e+00 1.8138357e+00 2.2293497e+00 2.7459060e+00 1.4456832e+00 9.0553851e-01 1.3784049e+00 2.4698178e+00 1.3928388e+00 1.1357817e+00 5.3851648e-01 1.4000000e+00 1.5588457e+00 1.3228757e+00 9.8994949e-01 1.7691806e+00 1.6583124e+00 1.2767145e+00 1.1135529e+00 1.0295630e+00 1.1575837e+00 7.5498344e-01 9.6436508e-01 1.2727922e+00 1.5264338e+00 1.3674794e+00 6.2449980e-01 1.2806248e+00 2.3958297e+00 1.2884099e+00 1.1618950e+00 1.1532563e+00 7.0000000e-01 2.4433583e+00 1.2206556e+00 1.7000000e+00 1.1357817e+00 1.4035669e+00 1.0488088e+00 1.3228757e+00 2.1886069e+00 1.9183326e+00 1.7464249e+00 1.2884099e+00 1.8601075e+00 6.7823300e-01 8.7749644e-01 1.0099505e+00 1.3038405e+00 1.3674794e+00 1.0488088e+00 8.8317609e-01 2.4454039e+00 2.5942244e+00 1.1789826e+00 1.3000000e+00 1.2609520e+00 2.3108440e+00 6.7082039e-01 1.1832160e+00 1.4282857e+00 6.6332496e-01 7.0710678e-01 1.1618950e+00 1.2165525e+00 1.6431677e+00 2.2516660e+00 1.2165525e+00 6.4031242e-01 1.1958261e+00 1.9000000e+00 1.3674794e+00 9.0553851e-01 7.7459667e-01 9.4339811e-01 1.2727922e+00 9.1651514e-01 1.1357817e+00 1.4491377e+00 1.4282857e+00 9.4868330e-01 8.7749644e-01 7.4161985e-01 1.2124356e+00 9.4868330e-01 1.0344080e+00 9.1651514e-01 8.6023253e-01 7.6157731e-01 7.1414284e-01 1.7291616e+00 8.3066239e-01 9.4868330e-01 8.7177979e-01 6.1644140e-01 1.8654758e+00 8.3666003e-01 2.2360680e+00 1.1224972e+00 2.0049938e+00 1.4317821e+00 1.8165902e+00 2.7676705e+00 1.4730920e+00 2.2847319e+00 1.5524175e+00 2.6134269e+00 1.3527749e+00 1.1575837e+00 1.6093477e+00 1.1180340e+00 1.4832397e+00 1.6217275e+00 1.4106736e+00 3.2109189e+00 3.0495901e+00 7.0710678e-01 1.9646883e+00 1.2165525e+00 2.8266588e+00 8.1240384e-01 1.8681542e+00 2.1047565e+00 8.1853528e-01 1.0148892e+00 1.5297059e+00 1.8303005e+00 2.1702534e+00 3.0495901e+00 1.5842980e+00 8.8317609e-01 1.2569805e+00 2.5179357e+00 1.9646883e+00 1.4525839e+00 9.9498744e-01 1.6248077e+00 1.8574176e+00 1.5779734e+00 1.1224972e+00 2.0760539e+00 2.0712315e+00 1.5132746e+00 8.7177979e-01 1.2884099e+00 1.7944358e+00 1.1789826e+00 5.1961524e-01 5.1961524e-01 7.1414284e-01 4.6904158e-01 1.2569805e+00 3.1622777e-01 1.7320508e-01 1.7320508e-01 6.4031242e-01 1.3228757e+00 2.2360680e-01 2.3727621e+00 1.2206556e+00 2.4758837e+00 1.7320508e+00 2.1236761e+00 3.3000000e+00 1.0295630e+00 2.8266588e+00 2.1447611e+00 2.8913665e+00 1.5297059e+00 1.5905974e+00 2.0099751e+00 1.2489996e+00 1.5132746e+00 1.7663522e+00 1.7378147e+00 3.5524639e+00 3.6619667e+00 1.2845233e+00 2.3000000e+00 1.0816654e+00 3.4205263e+00 1.2124356e+00 2.1213203e+00 2.5416530e+00 1.0677078e+00 1.0677078e+00 1.8894444e+00 2.3537205e+00 2.7640550e+00 3.4219877e+00 1.9339080e+00 1.2529964e+00 1.6340135e+00 3.0675723e+00 2.0273135e+00 1.6911535e+00 9.4868330e-01 2.0074860e+00 2.1633308e+00 1.9235384e+00 1.2206556e+00 2.3916521e+00 2.3021729e+00 1.8493242e+00 1.3820275e+00 1.5842980e+00 1.7916473e+00 1.1575837e+00 4.2426407e-01 9.8994949e-01 3.3166248e-01 9.3273791e-01 3.0000000e-01 5.8309519e-01 4.8989795e-01 8.6023253e-01 1.0954451e+00 3.7416574e-01 2.5922963e+00 1.3038405e+00 2.6570661e+00 1.9000000e+00 2.3021729e+00 3.4727511e+00 8.7749644e-01 2.9899833e+00 2.2203603e+00 3.1543621e+00 1.7860571e+00 1.7029386e+00 2.1977261e+00 1.2369317e+00 1.6124515e+00 1.9974984e+00 1.9364917e+00 3.8249183e+00 3.7762415e+00 1.1747340e+00 2.5179357e+00 1.1832160e+00 3.5651087e+00 1.3190906e+00 2.3685439e+00 2.7622455e+00 1.2124356e+00 1.2922848e+00 2.0248457e+00 2.5436195e+00 2.9103264e+00 3.7013511e+00 2.0663978e+00 1.4071247e+00 1.7146428e+00 3.2403703e+00 2.2847319e+00 1.9157244e+00 1.1789826e+00 2.2181073e+00 2.3600847e+00 2.1283797e+00 1.3038405e+00 2.6057628e+00 2.5317978e+00 2.0322401e+00 1.4142136e+00 1.7832555e+00 2.0639767e+00 1.3674794e+00 7.7459667e-01 5.0000000e-01 1.2609520e+00 2.6457513e-01 4.8989795e-01 4.2426407e-01 7.7459667e-01 1.4628739e+00 4.2426407e-01 2.3194827e+00 1.0392305e+00 2.4041631e+00 1.5905974e+00 2.0297783e+00 3.1968735e+00 7.9372539e-01 2.7018512e+00 1.9416488e+00 2.9103264e+00 1.5779734e+00 1.4560220e+00 1.9672316e+00 1.0246951e+00 1.4352700e+00 1.7860571e+00 1.6522712e+00 3.5454196e+00 3.5071356e+00 9.2736185e-01 2.2847319e+00 9.6953597e-01 3.2878564e+00 1.1224972e+00 2.1047565e+00 2.4839485e+00 1.0246951e+00 1.0630146e+00 1.7606817e+00 2.2737634e+00 2.6514147e+00 3.4409301e+00 1.8138357e+00 1.1224972e+00 1.3564660e+00 3.0166206e+00 2.0396078e+00 1.6217275e+00 9.6436508e-01 2.0049938e+00 2.1377558e+00 1.9773720e+00 1.0392305e+00 2.3473389e+00 2.3043437e+00 1.8574176e+00 1.2247449e+00 1.5620499e+00 1.8275667e+00 1.0816654e+00 8.0622577e-01 1.8841444e+00 7.1414284e-01 6.0000000e-01 5.8309519e-01 3.4641016e-01 1.9748418e+00 6.7823300e-01 1.8165902e+00 8.2462113e-01 1.7832555e+00 1.1000000e+00 1.4966630e+00 2.5961510e+00 1.3379088e+00 2.1213203e+00 1.4866069e+00 2.2427661e+00 9.0000000e-01 9.5916630e-01 1.3379088e+00 9.6436508e-01 1.1747340e+00 1.1958261e+00 1.0630146e+00 2.8722813e+00 2.9698485e+00 9.0553851e-01 1.6431677e+00 8.6023253e-01 2.7147744e+00 6.1644140e-01 1.4662878e+00 1.8357560e+00 5.0000000e-01 5.0000000e-01 1.2727922e+00 1.6401219e+00 2.0566964e+00 2.7349589e+00 1.3304135e+00 5.8309519e-01 1.0770330e+00 2.3706539e+00 1.4832397e+00 1.0344080e+00 4.5825757e-01 1.3341664e+00 1.5394804e+00 1.3076697e+00 8.2462113e-01 1.7406895e+00 1.6941074e+00 1.2369317e+00 8.3666003e-01 9.3808315e-01 1.2727922e+00 6.7082039e-01 1.1224972e+00 3.1622777e-01 4.5825757e-01 3.8729833e-01 5.9160798e-01 1.2288206e+00 2.6457513e-01 2.5357445e+00 1.3076697e+00 2.5039968e+00 1.8055470e+00 2.2113344e+00 3.3120990e+00 1.1489125e+00 2.8266588e+00 2.1023796e+00 3.0099834e+00 1.6431677e+00 1.5968719e+00 2.0542639e+00 1.2884099e+00 1.6401219e+00 1.9026298e+00 1.8055470e+00 3.6523965e+00 3.6373067e+00 1.1357817e+00 2.3811762e+00 1.2369317e+00 3.4029399e+00 1.1958261e+00 2.2360680e+00 2.5845696e+00 1.0954451e+00 1.1916375e+00 1.9416488e+00 2.3494680e+00 2.7386128e+00 3.5000000e+00 1.9899749e+00 1.2609520e+00 1.6401219e+00 3.0643107e+00 2.2113344e+00 1.7944358e+00 1.0954451e+00 2.0566964e+00 2.2494444e+00 1.9697716e+00 1.3076697e+00 2.4859606e+00 2.4248711e+00 1.9026298e+00 1.3228757e+00 1.6522712e+00 1.9924859e+00 1.3190906e+00 1.1916375e+00 1.3527749e+00 1.3228757e+00 1.7000000e+00 3.8729833e-01 1.2124356e+00 3.4971417e+00 2.2022716e+00 3.5874782e+00 2.8248894e+00 3.2295511e+00 4.3988635e+00 1.4071247e+00 3.9102430e+00 3.1336879e+00 4.0767634e+00 2.7018512e+00 2.6324893e+00 3.1272992e+00 2.1023796e+00 2.4677925e+00 2.9086079e+00 2.8670542e+00 4.7476310e+00 4.6936127e+00 2.0371549e+00 3.4452866e+00 2.0420578e+00 4.4833024e+00 2.2472205e+00 3.2954514e+00 3.6851052e+00 2.1400935e+00 2.2135944e+00 2.9512709e+00 3.4554305e+00 3.8288379e+00 4.6119410e+00 2.9899833e+00 2.3302360e+00 2.5980762e+00 4.1605288e+00 3.1859065e+00 2.8425341e+00 2.0928450e+00 3.1416556e+00 3.2832910e+00 3.0298515e+00 2.2022716e+00 3.5355339e+00 3.4496377e+00 2.9461840e+00 2.3302360e+00 2.7110883e+00 2.9580399e+00 2.2759613e+00 3.3166248e-01 2.2360680e-01 6.4031242e-01 1.3304135e+00 1.7320508e-01 2.3515952e+00 1.1000000e+00 2.4228083e+00 1.6552945e+00 2.0663978e+00 3.2388269e+00 8.8317609e-01 2.7549955e+00 2.0149442e+00 2.9017236e+00 1.5362291e+00 1.4866069e+00 1.9646883e+00 1.0862780e+00 1.4387495e+00 1.7606817e+00 1.6852300e+00 3.5608988e+00 3.5651087e+00 1.0440307e+00 2.2781571e+00 9.9498744e-01 3.3406586e+00 1.1090537e+00 2.1118712e+00 2.5099801e+00 9.8994949e-01 1.0392305e+00 1.8027756e+00 2.3021729e+00 2.6870058e+00 3.4394767e+00 1.8493242e+00 1.1618950e+00 1.4933185e+00 3.0182777e+00 2.0371549e+00 1.6552945e+00 9.2736185e-01 1.9824228e+00 2.1307276e+00 1.9131126e+00 1.1000000e+00 2.3622024e+00 2.2934690e+00 1.8165902e+00 1.2369317e+00 1.5459625e+00 1.8138357e+00 1.1135529e+00 1.4142136e-01 5.2915026e-01 1.4352700e+00 2.4494897e-01 2.3194827e+00 1.1832160e+00 2.3790755e+00 1.6401219e+00 2.0493902e+00 3.1906112e+00 1.1090537e+00 2.7092434e+00 2.0420578e+00 2.8124722e+00 1.4594520e+00 1.5099669e+00 1.9261360e+00 1.2369317e+00 1.5165751e+00 1.7175564e+00 1.6401219e+00 3.4481879e+00 3.5580894e+00 1.2083046e+00 2.2226111e+00 1.0862780e+00 3.3060551e+00 1.1401754e+00 2.0371549e+00 2.4269322e+00 1.0049876e+00 1.0049876e+00 1.8165902e+00 2.2293497e+00 2.6514147e+00 3.3105891e+00 1.8681542e+00 1.1401754e+00 1.5231546e+00 2.9698485e+00 1.9798990e+00 1.5968719e+00 9.0000000e-01 1.9235384e+00 2.1000000e+00 1.8627936e+00 1.1832160e+00 2.3130067e+00 2.2427661e+00 1.7916473e+00 1.3190906e+00 1.5099669e+00 1.7492856e+00 1.1000000e+00 5.0990195e-01 1.4142136e+00 1.4142136e-01 2.2803509e+00 1.1045361e+00 2.3452079e+00 1.6031220e+00 2.0049938e+00 3.1654384e+00 1.0246951e+00 2.6870058e+00 1.9924859e+00 2.7910571e+00 1.4247807e+00 1.4491377e+00 1.8841444e+00 1.1357817e+00 1.4282857e+00 1.6703293e+00 1.6093477e+00 3.4452866e+00 3.5185224e+00 1.1224972e+00 2.1863211e+00 1.0000000e+00 3.2787193e+00 1.0677078e+00 2.0124612e+00 2.4145393e+00 9.3273791e-01 9.5393920e-01 1.7606817e+00 2.2158520e+00 2.6210685e+00 3.3136083e+00 1.8083141e+00 1.1045361e+00 1.4899664e+00 2.9359837e+00 1.9442222e+00 1.5716234e+00 8.4261498e-01 1.8867962e+00 2.0518285e+00 1.8138357e+00 1.1045361e+00 2.2781571e+00 2.2022716e+00 1.7349352e+00 1.2328828e+00 1.4628739e+00 1.7146428e+00 1.0535654e+00 1.7606817e+00 5.4772256e-01 2.1213203e+00 1.0954451e+00 2.0049938e+00 1.3964240e+00 1.7776389e+00 2.8106939e+00 1.4317821e+00 2.3366643e+00 1.7058722e+00 2.4839485e+00 1.1445523e+00 1.2000000e+00 1.5652476e+00 1.1789826e+00 1.4212670e+00 1.4594520e+00 1.3379088e+00 3.1032241e+00 3.1780497e+00 1.0295630e+00 1.8814888e+00 1.1045361e+00 2.9171904e+00 8.1240384e-01 1.7349352e+00 2.0566964e+00 7.1414284e-01 7.9372539e-01 1.5427249e+00 1.8303005e+00 2.2472205e+00 2.9325757e+00 1.5968719e+00 8.3666003e-01 1.3416408e+00 2.5495098e+00 1.7776389e+00 1.3304135e+00 7.4161985e-01 1.5427249e+00 1.7860571e+00 1.4730920e+00 1.0954451e+00 2.0024984e+00 1.9519221e+00 1.4387495e+00 1.0099505e+00 1.1832160e+00 1.5684387e+00 9.9498744e-01 1.3038405e+00 3.6110940e+00 2.3622024e+00 3.6959437e+00 2.9748950e+00 3.3555923e+00 4.5232732e+00 1.6278821e+00 4.0472213e+00 3.3000000e+00 4.1460825e+00 2.7694765e+00 2.7676705e+00 3.2233523e+00 2.2737634e+00 2.5845696e+00 2.9849623e+00 2.9916551e+00 4.8321838e+00 4.8394215e+00 2.2494444e+00 3.5298725e+00 2.1817424e+00 4.6206060e+00 2.3622024e+00 3.3896903e+00 3.7934153e+00 2.2427661e+00 2.3130067e+00 3.0886890e+00 3.5707142e+00 3.9534795e+00 4.6797436e+00 3.1224990e+00 2.4698178e+00 2.8035692e+00 4.2497059e+00 3.2710854e+00 2.9647934e+00 2.1886069e+00 3.2186954e+00 3.3719431e+00 3.0740852e+00 2.3622024e+00 3.6373067e+00 3.5284558e+00 3.0149627e+00 2.4657656e+00 2.8035692e+00 3.0364453e+00 2.4062419e+00 2.3790755e+00 1.1747340e+00 2.4248711e+00 1.6941074e+00 2.0928450e+00 3.2465366e+00 1.0246951e+00 2.7676705e+00 2.0566964e+00 2.8861739e+00 1.5132746e+00 1.5165751e+00 1.9621417e+00 1.1789826e+00 1.4899664e+00 1.7578396e+00 1.7000000e+00 3.5454196e+00 3.5888717e+00 1.1401754e+00 2.2715633e+00 1.0677078e+00 3.3541020e+00 1.1224972e+00 2.1095023e+00 2.5039968e+00 9.9498744e-01 1.0440307e+00 1.8384776e+00 2.2956481e+00 2.6925824e+00 3.4088121e+00 1.8841444e+00 1.1832160e+00 1.5684387e+00 3.0066593e+00 2.0445048e+00 1.6703293e+00 9.3273791e-01 1.9646883e+00 2.1330729e+00 1.8788294e+00 1.1747340e+00 2.3685439e+00 2.2912878e+00 1.8027756e+00 1.2727922e+00 1.5427249e+00 1.8165902e+00 1.1532563e+00 1.3341664e+00 9.4868330e-01 9.0000000e-01 5.0990195e-01 1.5165751e+00 2.3430749e+00 1.3190906e+00 1.1532563e+00 9.5393920e-01 1.0535654e+00 1.1045361e+00 8.6602540e-01 1.5000000e+00 1.1489125e+00 7.4161985e-01 9.3273791e-01 1.6703293e+00 1.8165902e+00 1.8165902e+00 7.0710678e-01 1.4832397e+00 1.7175564e+00 1.4352700e+00 6.4031242e-01 1.1445523e+00 1.4798649e+00 1.3527749e+00 7.6157731e-01 1.3228757e+00 1.3527749e+00 1.7944358e+00 7.1414284e-01 1.4352700e+00 1.3784049e+00 1.4491377e+00 4.2426407e-01 8.8881944e-01 1.4525839e+00 9.5916630e-01 6.0827625e-01 1.1180340e+00 1.3341664e+00 5.5677644e-01 5.0000000e-01 9.6436508e-01 1.4142136e+00 1.0099505e+00 6.4807407e-01 1.2449900e+00 1.5684387e+00 7.4161985e-01 1.0770330e+00 2.3706539e+00 1.1180340e+00 1.9339080e+00 1.1618950e+00 2.0322401e+00 8.6602540e-01 6.3245553e-01 1.1357817e+00 2.6457513e-01 5.0990195e-01 9.0000000e-01 8.6602540e-01 2.7331301e+00 2.6495283e+00 6.7823300e-01 1.4071247e+00 3.1622777e-01 2.4879711e+00 5.4772256e-01 1.2529964e+00 1.7406895e+00 5.1961524e-01 4.7958315e-01 8.1240384e-01 1.6217275e+00 1.8894444e+00 2.7055499e+00 8.4261498e-01 6.4807407e-01 7.7459667e-01 2.2045408e+00 1.1135529e+00 8.3066239e-01 4.7958315e-01 1.2247449e+00 1.2124356e+00 1.2369317e+00 0.0000000e+00 1.4317821e+00 1.3747727e+00 1.0344080e+00 5.4772256e-01 7.7459667e-01 9.4868330e-01 3.3166248e-01 9.1104336e-01 6.1644140e-01 8.6023253e-01 2.6851443e+00 5.4772256e-01 7.1414284e-01 7.5498344e-01 1.0246951e+00 9.8994949e-01 5.0000000e-01 1.7406895e+00 1.5684387e+00 9.6436508e-01 7.8102497e-01 1.2845233e+00 1.2489996e+00 1.7378147e+00 4.0000000e-01 1.8165902e+00 1.0246951e+00 1.3490738e+00 5.3851648e-01 3.8729833e-01 1.4662878e+00 1.4456832e+00 7.8740079e-01 5.1961524e-01 4.5825757e-01 1.2409674e+00 7.9372539e-01 1.2961481e+00 1.3190906e+00 6.6332496e-01 9.8994949e-01 8.6602540e-01 1.5842980e+00 5.4772256e-01 5.9160798e-01 8.5440037e-01 1.5684387e+00 4.1231056e-01 6.7082039e-01 8.3066239e-01 1.3190906e+00 9.2736185e-01 1.1224972e+00 1.4730920e+00 5.0000000e-01 1.6703293e+00 1.8275667e+00 1.2206556e+00 6.0000000e-01 1.4282857e+00 6.4807407e-01 3.8729833e-01 6.0000000e-01 9.5916630e-01 9.3273791e-01 6.6332496e-01 2.4494897e-01 2.0346990e+00 1.9974984e+00 1.0148892e+00 8.4261498e-01 1.0148892e+00 1.7944358e+00 7.2801099e-01 6.4807407e-01 1.0295630e+00 8.1240384e-01 7.3484692e-01 3.3166248e-01 9.4868330e-01 1.2165525e+00 2.0124612e+00 4.2426407e-01 5.9160798e-01 5.3851648e-01 1.5716234e+00 7.8102497e-01 2.4494897e-01 8.6023253e-01 7.2801099e-01 7.4833148e-01 9.4868330e-01 7.4161985e-01 8.2462113e-01 9.0553851e-01 7.6157731e-01 7.2801099e-01 5.0000000e-01 7.4161985e-01 6.4807407e-01 1.3638182e+00 2.1794495e+00 1.0295630e+00 6.7082039e-01 1.0148892e+00 7.5498344e-01 6.6332496e-01 4.3588989e-01 1.2529964e+00 1.0295630e+00 5.5677644e-01 5.0000000e-01 1.7000000e+00 1.6792856e+00 1.4212670e+00 4.6904158e-01 1.3038405e+00 1.5264338e+00 1.0488088e+00 3.8729833e-01 8.5440037e-01 1.1357817e+00 1.0630146e+00 3.1622777e-01 9.2195445e-01 1.0148892e+00 1.7320508e+00 3.0000000e-01 1.0295630e+00 1.0000000e+00 1.2409674e+00 5.2915026e-01 5.1961524e-01 1.1874342e+00 5.8309519e-01 3.6055513e-01 8.1853528e-01 1.0770330e+00 3.8729833e-01 4.7958315e-01 6.4031242e-01 1.0099505e+00 6.3245553e-01 6.4807407e-01 1.0049876e+00 3.4799425e+00 5.2915026e-01 1.3379088e+00 9.6436508e-01 1.8734994e+00 1.8055470e+00 1.3601471e+00 2.5357445e+00 2.3706539e+00 1.7916473e+00 1.5842980e+00 8.1853528e-01 5.4772256e-01 2.4738634e+00 1.1747340e+00 2.6343880e+00 2.6457513e-01 2.1817424e+00 1.3076697e+00 8.0622577e-01 2.3086793e+00 2.2869193e+00 1.5748016e+00 1.0246951e+00 6.0827625e-01 8.8317609e-01 1.5779734e+00 2.0832667e+00 1.9748418e+00 5.4772256e-01 1.7146428e+00 1.6583124e+00 2.4269322e+00 1.3928388e+00 1.3820275e+00 1.6703293e+00 2.3706539e+00 1.1000000e+00 1.3674794e+00 1.6763055e+00 2.1307276e+00 1.7832555e+00 1.8973666e+00 2.2869193e+00 3.0282008e+00 2.2226111e+00 3.1144823e+00 1.8708287e+00 1.7233688e+00 2.2405357e+00 9.8994949e-01 1.3228757e+00 1.9339080e+00 1.9544820e+00 3.8236109e+00 3.7376463e+00 1.2609520e+00 2.5079872e+00 9.1104336e-01 3.5860842e+00 1.4730920e+00 2.3409400e+00 2.8354894e+00 1.3711309e+00 1.3638182e+00 1.9261360e+00 2.6907248e+00 2.9899833e+00 3.7934153e+00 1.9493589e+00 1.5652476e+00 1.6583124e+00 3.3181320e+00 2.1142375e+00 1.9026298e+00 1.2489996e+00 2.3086793e+00 2.3021729e+00 2.2538855e+00 1.1180340e+00 2.5337719e+00 2.4413111e+00 2.0832667e+00 1.5000000e+00 1.8411953e+00 1.9157244e+00 1.2727922e+00 8.7749644e-01 1.0148892e+00 1.4866069e+00 1.3638182e+00 9.9498744e-01 2.1095023e+00 2.0149442e+00 1.4662878e+00 1.1357817e+00 1.1357817e+00 9.2736185e-01 1.9899749e+00 9.2736185e-01 2.2135944e+00 6.0827625e-01 1.7320508e+00 9.8488578e-01 4.3588989e-01 1.8627936e+00 1.8466185e+00 1.1832160e+00 5.5677644e-01 2.6457513e-01 1.1045361e+00 1.2124356e+00 1.5937377e+00 1.4764823e+00 6.7823300e-01 1.4491377e+00 1.2206556e+00 1.9874607e+00 1.0488088e+00 1.1180340e+00 1.3747727e+00 1.9339080e+00 8.6602540e-01 1.1704700e+00 1.3527749e+00 1.6911535e+00 1.3784049e+00 1.5874508e+00 1.8466185e+00 1.4282857e+00 1.0295630e+00 6.2449980e-01 6.6332496e-01 1.2961481e+00 1.3228757e+00 1.0392305e+00 6.1644140e-01 1.9131126e+00 1.5716234e+00 1.1445523e+00 8.8881944e-01 1.4662878e+00 1.3928388e+00 1.0049876e+00 8.6023253e-01 8.8317609e-01 1.1575837e+00 1.1916375e+00 5.5677644e-01 7.3484692e-01 8.2462113e-01 1.8788294e+00 6.1644140e-01 9.1104336e-01 7.5498344e-01 1.2609520e+00 1.1704700e+00 7.3484692e-01 1.3190906e+00 8.0622577e-01 8.7177979e-01 1.0677078e+00 1.1618950e+00 8.7177979e-01 1.0677078e+00 9.2736185e-01 9.0000000e-01 8.3066239e-01 1.2124356e+00 1.1747340e+00 1.3784049e+00 1.5652476e+00 1.0198039e+00 2.2181073e+00 1.9000000e+00 1.2165525e+00 1.3038405e+00 8.6023253e-01 1.3892444e+00 2.3685439e+00 6.7082039e-01 2.2113344e+00 1.2247449e+00 1.8841444e+00 8.1240384e-01 8.1240384e-01 1.9544820e+00 1.8708287e+00 1.3000000e+00 1.1224972e+00 1.0198039e+00 9.3273791e-01 1.2727922e+00 1.8574176e+00 1.9157244e+00 8.0622577e-01 1.0535654e+00 1.3190906e+00 1.9949937e+00 9.9498744e-01 8.7177979e-01 1.1747340e+00 2.0322401e+00 6.3245553e-01 7.0710678e-01 1.2083046e+00 1.8947295e+00 1.3820275e+00 1.2529964e+00 1.8814888e+00 5.5677644e-01 5.4772256e-01 1.0677078e+00 9.0000000e-01 3.7416574e-01 4.8989795e-01 2.0976177e+00 2.2649503e+00 1.2288206e+00 7.8102497e-01 1.0049876e+00 2.0396078e+00 6.0827625e-01 6.4807407e-01 1.1575837e+00 6.1644140e-01 5.2915026e-01 6.5574385e-01 1.0862780e+00 1.4071247e+00 2.0024984e+00 6.7823300e-01 6.7082039e-01 1.0630146e+00 1.6031220e+00 7.0000000e-01 4.6904158e-01 6.4807407e-01 5.1961524e-01 6.7823300e-01 5.0990195e-01 8.6602540e-01 9.0553851e-01 8.1240384e-01 4.2426407e-01 7.4161985e-01 2.2360680e-01 5.5677644e-01 6.6332496e-01 5.7445626e-01 7.9372539e-01 8.1240384e-01 6.4031242e-01 3.8729833e-01 2.2248595e+00 2.1023796e+00 8.1240384e-01 9.0553851e-01 9.0553851e-01 1.9157244e+00 4.2426407e-01 8.0622577e-01 1.1789826e+00 5.5677644e-01 5.9160798e-01 3.7416574e-01 1.0344080e+00 1.2845233e+00 2.1633308e+00 4.3588989e-01 4.6904158e-01 6.6332496e-01 1.6062378e+00 9.1651514e-01 4.5825757e-01 7.1414284e-01 6.7823300e-01 7.6811457e-01 7.8102497e-01 6.3245553e-01 9.6436508e-01 9.8488578e-01 5.9160798e-01 3.7416574e-01 3.4641016e-01 8.3666003e-01 6.2449980e-01 1.3114877e+00 1.1357817e+00 5.2915026e-01 4.2426407e-01 1.7029386e+00 1.7233688e+00 1.3747727e+00 3.6055513e-01 1.3601471e+00 1.5165751e+00 8.8881944e-01 3.7416574e-01 7.3484692e-01 9.8994949e-01 9.6953597e-01 4.5825757e-01 7.0710678e-01 8.9442719e-01 1.6340135e+00 4.6904158e-01 9.0000000e-01 1.0723805e+00 1.1000000e+00 7.1414284e-01 5.0990195e-01 1.1045361e+00 1.7320508e-01 3.4641016e-01 4.6904158e-01 1.1357817e+00 4.8989795e-01 5.4772256e-01 3.7416574e-01 8.8881944e-01 4.3588989e-01 7.5498344e-01 1.0295630e+00 5.1961524e-01 1.0770330e+00 1.0862780e+00 2.9359837e+00 2.7766887e+00 6.5574385e-01 1.5842980e+00 3.3166248e-01 2.6419690e+00 6.7082039e-01 1.4628739e+00 1.9442222e+00 6.4807407e-01 6.7823300e-01 9.7467943e-01 1.8165902e+00 2.0493902e+00 2.9137605e+00 9.8994949e-01 8.4261498e-01 9.4339811e-01 2.3558438e+00 1.3000000e+00 1.0677078e+00 6.4807407e-01 1.4035669e+00 1.3711309e+00 1.3784049e+00 2.6457513e-01 1.6124515e+00 1.5427249e+00 1.1747340e+00 6.0827625e-01 9.6436508e-01 1.1445523e+00 5.8309519e-01 7.5498344e-01 1.0246951e+00 2.6851443e+00 2.6267851e+00 1.1045361e+00 1.3190906e+00 4.8989795e-01 2.5159491e+00 8.1240384e-01 1.2288206e+00 1.8138357e+00 7.8102497e-01 7.2801099e-01 8.3666003e-01 1.7691806e+00 1.9519221e+00 2.6944387e+00 8.0622577e-01 1.0295630e+00 1.1747340e+00 2.1587033e+00 9.2736185e-01 9.8488578e-01 7.2801099e-01 1.2165525e+00 1.0723805e+00 1.1445523e+00 5.0990195e-01 1.3453624e+00 1.1958261e+00 9.3273791e-01 7.7459667e-01 8.3666003e-01 7.8740079e-01 6.4031242e-01 5.8309519e-01 2.0049938e+00 2.1470911e+00 1.3747727e+00 6.4031242e-01 1.0246951e+00 1.9748418e+00 8.1853528e-01 5.4772256e-01 1.1747340e+00 8.3666003e-01 7.3484692e-01 5.3851648e-01 1.1916375e+00 1.4000000e+00 1.9773720e+00 5.0990195e-01 9.2195445e-01 1.1618950e+00 1.5394804e+00 3.8729833e-01 5.4772256e-01 8.3666003e-01 5.5677644e-01 4.4721360e-01 5.4772256e-01 9.0000000e-01 7.2111026e-01 5.4772256e-01 3.7416574e-01 8.6602540e-01 3.8729833e-01 3.0000000e-01 7.6157731e-01 1.9183326e+00 1.9519221e+00 1.1090537e+00 7.0000000e-01 1.1180340e+00 1.7204651e+00 7.0000000e-01 5.0990195e-01 8.8317609e-01 7.8740079e-01 7.2111026e-01 3.8729833e-01 7.8740079e-01 1.1045361e+00 1.8574176e+00 4.6904158e-01 5.7445626e-01 7.0000000e-01 1.4317821e+00 7.5498344e-01 1.4142136e-01 8.6023253e-01 5.1961524e-01 6.4807407e-01 7.6157731e-01 8.6602540e-01 7.3484692e-01 8.1240384e-01 6.1644140e-01 7.4161985e-01 3.6055513e-01 7.1414284e-01 7.2111026e-01 1.2206556e+00 2.9715316e+00 1.4177447e+00 2.9478806e+00 1.0198039e+00 2.5632011e+00 1.5033296e+00 1.1224972e+00 2.6495283e+00 2.5690465e+00 1.9773720e+00 1.4352700e+00 1.2409674e+00 4.1231056e-01 1.9748418e+00 2.4515301e+00 2.4186773e+00 1.0049876e+00 1.8357560e+00 1.9442222e+00 2.7018512e+00 1.6822604e+00 1.6552945e+00 1.9235384e+00 2.7331301e+00 1.3490738e+00 1.5297059e+00 1.9748418e+00 2.5748786e+00 2.0904545e+00 2.0273135e+00 2.5690465e+00 2.7018512e+00 1.5620499e+00 2.9223278e+00 4.1231056e-01 2.4939928e+00 1.7233688e+00 1.2922848e+00 2.6362853e+00 2.6400758e+00 1.8601075e+00 1.4525839e+00 9.6436508e-01 1.3490738e+00 1.8520259e+00 2.4248711e+00 2.2494444e+00 8.9442719e-01 2.0736441e+00 2.0371549e+00 2.7766887e+00 1.7832555e+00 1.7175564e+00 2.0322401e+00 2.6495283e+00 1.4730920e+00 1.7233688e+00 2.0124612e+00 2.3958297e+00 2.1400935e+00 2.2671568e+00 2.6248809e+00 1.7146428e+00 8.8317609e-01 2.5278449e+00 6.6332496e-01 1.5968719e+00 1.8788294e+00 7.2801099e-01 8.6602540e-01 1.1135529e+00 1.6522712e+00 1.9209373e+00 2.8948230e+00 1.1704700e+00 6.7823300e-01 7.3484692e-01 2.3194827e+00 1.6431677e+00 1.1445523e+00 8.7749644e-01 1.4628739e+00 1.5716234e+00 1.5066519e+00 6.7823300e-01 1.7578396e+00 1.7860571e+00 1.3453624e+00 5.8309519e-01 1.0862780e+00 1.5099669e+00 8.6602540e-01 1.6062378e+00 1.3747727e+00 1.2247449e+00 3.0000000e-01 6.5574385e-01 1.3076697e+00 1.2529964e+00 6.7823300e-01 7.9372539e-01 8.5440037e-01 1.3928388e+00 6.5574385e-01 1.2328828e+00 1.3490738e+00 9.1651514e-01 6.4807407e-01 7.4161985e-01 1.3820275e+00 3.7416574e-01 2.6457513e-01 6.0827625e-01 1.4071247e+00 2.2360680e-01 3.0000000e-01 5.7445626e-01 1.2247449e+00 7.3484692e-01 7.8740079e-01 1.2845233e+00 2.7658633e+00 7.3484692e-01 1.4525839e+00 1.9924859e+00 6.4031242e-01 5.7445626e-01 1.0677078e+00 1.8894444e+00 2.1656408e+00 2.9223278e+00 1.0816654e+00 8.8317609e-01 1.0677078e+00 2.4454039e+00 1.2247449e+00 1.0630146e+00 5.0000000e-01 1.4282857e+00 1.3964240e+00 1.3820275e+00 3.1622777e-01 1.6401219e+00 1.5329710e+00 1.1958261e+00 7.7459667e-01 9.6953597e-01 1.0295630e+00 4.5825757e-01 2.2912878e+00 1.5033296e+00 9.6953597e-01 2.4289916e+00 2.4248711e+00 1.7058722e+00 1.1224972e+00 6.7823300e-01 1.0630146e+00 1.7146428e+00 2.1840330e+00 2.0420578e+00 7.0000000e-01 1.9209373e+00 1.8055470e+00 2.5651511e+00 1.5588457e+00 1.5684387e+00 1.8384776e+00 2.4879711e+00 1.3038405e+00 1.5811388e+00 1.8384776e+00 2.2248595e+00 1.9313208e+00 2.0952327e+00 2.4248711e+00 1.1180340e+00 1.5066519e+00 1.7320508e-01 3.6055513e-01 7.7459667e-01 1.3228757e+00 1.6340135e+00 2.4617067e+00 8.1853528e-01 3.7416574e-01 8.3666003e-01 1.9339080e+00 1.1575837e+00 7.2801099e-01 4.3588989e-01 9.2736185e-01 1.0816654e+00 9.0000000e-01 5.4772256e-01 1.3228757e+00 1.2845233e+00 7.6811457e-01 2.4494897e-01 5.0990195e-01 1.0000000e+00 5.3851648e-01 6.6332496e-01 1.1832160e+00 1.0862780e+00 5.9160798e-01 7.7459667e-01 9.6953597e-01 1.4798649e+00 6.0000000e-01 1.0630146e+00 1.1618950e+00 1.1357817e+00 5.1961524e-01 5.0990195e-01 1.2165525e+00 4.1231056e-01 3.7416574e-01 6.9282032e-01 1.2529964e+00 3.1622777e-01 4.0000000e-01 6.1644140e-01 1.1532563e+00 6.2449980e-01 6.2449980e-01 1.0862780e+00 1.6124515e+00 1.5684387e+00 1.0246951e+00 3.4641016e-01 4.6904158e-01 1.0246951e+00 1.0583005e+00 1.3674794e+00 1.3747727e+00 7.4161985e-01 1.1704700e+00 9.4868330e-01 1.7088007e+00 7.4161985e-01 8.8317609e-01 1.0770330e+00 1.7406895e+00 6.4807407e-01 9.1651514e-01 1.0862780e+00 1.5198684e+00 1.1000000e+00 1.2845233e+00 1.5937377e+00 2.4494897e-01 8.7749644e-01 1.4422205e+00 1.7720045e+00 2.5475478e+00 9.1651514e-01 4.3588989e-01 9.2195445e-01 2.0566964e+00 1.1704700e+00 7.8740079e-01 2.8284271e-01 1.0148892e+00 1.1575837e+00 9.5916630e-01 5.1961524e-01 1.4071247e+00 1.3416408e+00 8.3666003e-01 3.8729833e-01 5.7445626e-01 9.8488578e-01 4.6904158e-01 8.4261498e-01 1.4352700e+00 1.7832555e+00 2.4839485e+00 8.8317609e-01 4.5825757e-01 9.0000000e-01 2.0615528e+00 1.0246951e+00 6.7823300e-01 1.4142136e-01 9.9498744e-01 1.1045361e+00 9.6953597e-01 4.7958315e-01 1.3341664e+00 1.2569805e+00 8.3666003e-01 5.5677644e-01 5.3851648e-01 8.1853528e-01 2.8284271e-01 9.8488578e-01 1.1357817e+00 1.9748418e+00 1.0000000e-01 7.8740079e-01 7.8740079e-01 1.4212670e+00 6.7823300e-01 4.3588989e-01 9.6436508e-01 6.1644140e-01 5.1961524e-01 7.9372539e-01 8.1240384e-01 6.7082039e-01 7.1414284e-01 5.7445626e-01 7.0710678e-01 4.6904158e-01 6.9282032e-01 7.9372539e-01 5.0990195e-01 1.2845233e+00 1.0392305e+00 1.1618950e+00 1.2041595e+00 9.1104336e-01 1.2845233e+00 8.8317609e-01 1.5748016e+00 7.1414284e-01 9.6953597e-01 1.0392305e+00 1.6217275e+00 8.3666003e-01 1.0770330e+00 1.0488088e+00 1.3379088e+00 1.0049876e+00 1.3453624e+00 1.4899664e+00 1.1618950e+00 1.1575837e+00 1.5394804e+00 1.4933185e+00 5.3851648e-01 1.4387495e+00 1.2083046e+00 1.9235384e+00 9.3273791e-01 1.0392305e+00 1.2247449e+00 1.8894444e+00 8.4852814e-01 1.1224972e+00 1.2247449e+00 1.5842980e+00 1.2922848e+00 1.5652476e+00 1.8165902e+00 1.9824228e+00 2.3452079e+00 2.3832751e+00 9.2736185e-01 1.8761663e+00 1.8947295e+00 2.6172505e+00 1.5811388e+00 1.6522712e+00 1.8083141e+00 2.7055499e+00 1.3820275e+00 1.5588457e+00 1.9000000e+00 2.4939928e+00 2.0099751e+00 2.0346990e+00 2.5238859e+00 8.6602540e-01 8.7749644e-01 1.4106736e+00 6.4031242e-01 5.0990195e-01 1.0000000e+00 6.2449980e-01 4.6904158e-01 7.7459667e-01 8.4261498e-01 6.4807407e-01 6.6332496e-01 5.4772256e-01 7.4161985e-01 5.0000000e-01 6.7082039e-01 8.3666003e-01 5.8309519e-01 1.9078784e+00 1.1916375e+00 5.9160798e-01 5.5677644e-01 9.4868330e-01 1.1445523e+00 1.0440307e+00 6.4807407e-01 1.3000000e+00 1.3304135e+00 9.2195445e-01 5.0990195e-01 5.8309519e-01 1.0488088e+00 5.3851648e-01 1.9442222e+00 1.2961481e+00 7.1414284e-01 9.8488578e-01 1.1916375e+00 1.2688578e+00 1.3964240e+00 7.7459667e-01 1.3228757e+00 1.4387495e+00 1.2206556e+00 8.1240384e-01 9.1651514e-01 1.2247449e+00 7.8102497e-01 1.5427249e+00 1.5198684e+00 2.1977261e+00 1.0862780e+00 1.1269428e+00 1.2845233e+00 2.2045408e+00 9.4339811e-01 1.1357817e+00 1.3453624e+00 1.8920888e+00 1.5297059e+00 1.7029386e+00 2.1189620e+00 6.8556546e-01 1.1180340e+00 7.6157731e-01 5.0000000e-01 8.4261498e-01 1.1135529e+00 6.2449980e-01 4.3588989e-01 7.0000000e-01 1.1916375e+00 7.2111026e-01 2.4494897e-01 9.6436508e-01 8.1240384e-01 5.9160798e-01 6.7823300e-01 8.1240384e-01 8.3066239e-01 7.6157731e-01 8.1240384e-01 6.6332496e-01 7.9372539e-01 3.8729833e-01 6.2449980e-01 6.4807407e-01 1.1269428e+00 1.2247449e+00 1.0770330e+00 4.7958315e-01 1.4628739e+00 1.3711309e+00 9.4868330e-01 6.2449980e-01 6.7082039e-01 9.0000000e-01 3.1622777e-01 4.1231056e-01 3.6055513e-01 1.2247449e+00 5.5677644e-01 5.7445626e-01 3.6055513e-01 9.5916630e-01 4.6904158e-01 7.8740079e-01 1.0908712e+00 5.4772256e-01 1.2124356e+00 3.4641016e-01 2.4494897e-01 4.2426407e-01 1.0630146e+00 6.0827625e-01 6.2449980e-01 1.1224972e+00 1.2369317e+00 8.1240384e-01 6.9282032e-01 2.4494897e-01 9.4339811e-01 5.1961524e-01 8.1853528e-01 1.1224972e+00 1.4317821e+00 1.3747727e+00 1.0344080e+00 5.4772256e-01 7.7459667e-01 9.4868330e-01 3.3166248e-01 3.1622777e-01 7.3484692e-01 1.3076697e+00 8.4261498e-01 8.0622577e-01 1.3190906e+00 6.1644140e-01 1.2845233e+00 7.9372539e-01 6.2449980e-01 1.2569805e+00 7.8102497e-01 3.6055513e-01 6.7082039e-01 9.4868330e-01 5.8309519e-01 1.0677078e+00 6.5574385e-01 6.1644140e-01 6.4031242e-01 7.6811457e-01 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-euclidean-ml.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-euclidean-ml.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b7552021bf9a0606c36628f9432e8f0afe8d765 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-euclidean-ml.txt @@ -0,0 +1 @@ + 4.0515260e+00 4.2121458e+00 3.7357405e+00 4.2313317e+00 3.9136009e+00 4.3843298e+00 3.9811426e+00 4.3624182e+00 4.0642508e+00 4.2105933e+00 4.0747226e+00 3.9068586e+00 4.1637004e+00 4.4303203e+00 4.1841564e+00 4.1063279e+00 4.1862390e+00 4.0719925e+00 4.2227579e+00 4.3173531e+00 3.8811067e+00 3.7577567e+00 4.0623722e+00 3.9882453e+00 4.0432671e+00 3.9085109e+00 4.0283414e+00 4.0846110e+00 3.6459235e+00 3.9544001e+00 4.1134244e+00 4.1805752e+00 3.5121011e+00 4.2747789e+00 4.1048323e+00 3.9269426e+00 3.8932032e+00 3.8281172e+00 3.7288430e+00 4.0863477e+00 4.1527428e+00 4.1646409e+00 4.2027433e+00 3.8441594e+00 4.8419117e+00 4.2455384e+00 3.7622220e+00 4.3967923e+00 4.4663183e+00 4.0435853e+00 4.0421692e+00 4.3124625e+00 4.6499961e+00 4.5595743e+00 3.4230430e+00 4.2612266e+00 3.5676603e+00 4.0866580e+00 4.2307103e+00 3.8521940e+00 3.9951183e+00 3.1022409e+00 3.7290193e+00 4.1931517e+00 4.1127027e+00 3.6633651e+00 4.0235815e+00 3.9729858e+00 4.1980132e+00 4.1579993e+00 3.9948955e+00 3.9081966e+00 3.9031152e+00 3.5069036e+00 4.0015727e+00 3.6763496e+00 3.6614339e+00 3.6227109e+00 3.7357992e+00 4.0170026e+00 3.5216829e+00 3.9322227e+00 3.9094621e+00 4.0170286e+00 4.3264246e+00 4.3435483e+00 4.0788635e+00 4.4761765e+00 3.8468186e+00 4.1490333e+00 4.2800007e+00 4.2260191e+00 4.3031858e+00 4.1897413e+00 4.0530244e+00 3.5893641e+00 4.2186615e+00 3.7979503e+00 4.0915473e+00 4.1343073e+00 4.5063851e+00 3.6394889e+00 4.2508448e+00 3.7160826e+00 4.0105262e+00 4.1578269e+00 4.0290590e+00 3.6971819e+00 3.9414087e+00 4.2522313e+00 4.4091714e+00 4.1542292e+00 3.9594691e+00 4.0923600e+00 4.0855497e+00 3.8253075e+00 4.3034717e+00 4.0976731e+00 4.1316523e+00 4.0872717e+00 4.2643353e+00 3.8887280e+00 3.9411273e+00 3.8848001e+00 4.3481996e+00 3.8716733e+00 3.9084684e+00 3.7546361e+00 3.9354816e+00 3.8293694e+00 3.7568515e+00 3.7184961e+00 3.8404278e+00 4.2570811e+00 4.1423777e+00 4.0291411e+00 4.2094682e+00 3.6127418e+00 4.0459839e+00 3.7737985e+00 3.7647653e+00 3.9762006e+00 3.8999512e+00 3.8509090e+00 3.8975941e+00 3.8432839e+00 4.2109046e+00 4.1339124e+00 3.5898873e+00 4.0794519e+00 4.3504966e+00 3.8862612e+00 3.8332931e+00 4.2190310e+00 4.1366595e+00 3.7220268e+00 4.1250795e+00 3.3169452e+00 4.0757181e+00 3.6487114e+00 3.9513724e+00 4.0735549e+00 3.9137880e+00 3.9656942e+00 3.7724953e+00 4.0505153e+00 3.9062302e+00 4.5671852e+00 3.7542175e+00 4.3731708e+00 3.6733907e+00 4.4667545e+00 4.1004635e+00 4.0530038e+00 4.0346958e+00 4.2145752e+00 4.4298637e+00 4.2982360e+00 4.0878239e+00 4.4061563e+00 4.2115971e+00 3.8263277e+00 3.8603258e+00 3.8572375e+00 4.1051910e+00 4.3787786e+00 4.5309659e+00 4.0047055e+00 4.1308854e+00 3.6283561e+00 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-hamming-ml.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-hamming-ml.txt new file mode 100644 index 0000000000000000000000000000000000000000..bc4e1ddcb6e1e8699570ecc410e2cb0cfdba2507 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-hamming-ml.txt @@ -0,0 +1 @@ + 4.6000000e-01 4.3000000e-01 4.3000000e-01 5.4000000e-01 4.1000000e-01 5.3000000e-01 4.3000000e-01 5.9000000e-01 4.8000000e-01 4.7000000e-01 4.6000000e-01 4.9000000e-01 4.5000000e-01 5.5000000e-01 5.3000000e-01 4.5000000e-01 4.8000000e-01 4.7000000e-01 4.8000000e-01 5.1000000e-01 4.9000000e-01 4.4000000e-01 4.9000000e-01 4.7000000e-01 4.9000000e-01 4.7000000e-01 5.2000000e-01 4.7000000e-01 4.2000000e-01 4.9000000e-01 4.7000000e-01 5.5000000e-01 3.9000000e-01 5.5000000e-01 4.6000000e-01 4.5000000e-01 4.0000000e-01 4.8000000e-01 4.5000000e-01 4.8000000e-01 4.8000000e-01 5.0000000e-01 4.8000000e-01 4.5000000e-01 6.4000000e-01 5.7000000e-01 4.6000000e-01 5.4000000e-01 5.6000000e-01 4.8000000e-01 4.8000000e-01 5.3000000e-01 5.4000000e-01 5.3000000e-01 4.5000000e-01 5.8000000e-01 4.2000000e-01 5.4000000e-01 6.0000000e-01 5.1000000e-01 4.6000000e-01 4.1000000e-01 4.4000000e-01 5.6000000e-01 5.4000000e-01 4.8000000e-01 4.8000000e-01 5.1000000e-01 5.2000000e-01 5.5000000e-01 4.5000000e-01 4.3000000e-01 4.7000000e-01 4.7000000e-01 5.6000000e-01 4.9000000e-01 4.8000000e-01 4.5000000e-01 4.9000000e-01 4.7000000e-01 4.5000000e-01 4.5000000e-01 5.6000000e-01 4.9000000e-01 5.8000000e-01 5.4000000e-01 4.6000000e-01 5.8000000e-01 5.3000000e-01 5.4000000e-01 5.5000000e-01 5.0000000e-01 5.2000000e-01 4.8000000e-01 5.0000000e-01 3.8000000e-01 5.3000000e-01 4.8000000e-01 5.1000000e-01 4.8000000e-01 5.2000000e-01 4.7000000e-01 5.0000000e-01 4.3000000e-01 4.8000000e-01 5.2000000e-01 5.0000000e-01 4.2000000e-01 4.2000000e-01 4.7000000e-01 5.4000000e-01 5.1000000e-01 5.4000000e-01 5.1000000e-01 4.8000000e-01 4.7000000e-01 5.2000000e-01 5.2000000e-01 5.4000000e-01 5.4000000e-01 5.0000000e-01 4.5000000e-01 4.4000000e-01 4.1000000e-01 5.7000000e-01 4.6000000e-01 5.1000000e-01 5.2000000e-01 5.0000000e-01 4.8000000e-01 5.0000000e-01 4.4000000e-01 5.3000000e-01 5.2000000e-01 4.9000000e-01 5.7000000e-01 5.8000000e-01 4.9000000e-01 5.1000000e-01 4.5000000e-01 5.3000000e-01 4.5000000e-01 4.4000000e-01 3.5000000e-01 4.2000000e-01 5.3000000e-01 5.2000000e-01 5.0000000e-01 3.8000000e-01 5.2000000e-01 5.6000000e-01 4.7000000e-01 4.4000000e-01 5.1000000e-01 5.7000000e-01 4.5000000e-01 5.7000000e-01 4.3000000e-01 5.1000000e-01 3.8000000e-01 5.3000000e-01 4.8000000e-01 4.4000000e-01 5.0000000e-01 4.8000000e-01 5.0000000e-01 4.7000000e-01 6.4000000e-01 4.9000000e-01 5.2000000e-01 4.8000000e-01 5.6000000e-01 4.3000000e-01 4.8000000e-01 4.7000000e-01 6.0000000e-01 5.4000000e-01 5.5000000e-01 4.0000000e-01 5.5000000e-01 5.6000000e-01 4.9000000e-01 5.0000000e-01 4.3000000e-01 5.7000000e-01 5.0000000e-01 5.7000000e-01 4.9000000e-01 4.2000000e-01 3.9000000e-01 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-jaccard-ml.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-jaccard-ml.txt new file mode 100644 index 0000000000000000000000000000000000000000..a7570d8c3fbdf63bb2240c964941d9e48bc2ad3c --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-jaccard-ml.txt @@ -0,0 +1 @@ + 6.5714286e-01 6.0563380e-01 6.3235294e-01 7.3972603e-01 6.0294118e-01 7.3611111e-01 6.4179104e-01 7.7631579e-01 6.4000000e-01 6.6197183e-01 6.6666667e-01 7.0000000e-01 6.4285714e-01 7.7464789e-01 7.1621622e-01 6.4285714e-01 6.8571429e-01 6.4383562e-01 6.6666667e-01 6.5384615e-01 6.6216216e-01 6.1971831e-01 6.5333333e-01 6.5277778e-01 6.7123288e-01 6.4383562e-01 6.5000000e-01 6.3513514e-01 6.0000000e-01 6.7123288e-01 6.3513514e-01 7.4324324e-01 5.5714286e-01 7.0512821e-01 6.3888889e-01 6.0000000e-01 5.6338028e-01 6.3157895e-01 6.0810811e-01 6.2337662e-01 6.4000000e-01 6.5789474e-01 6.3157895e-01 5.6962025e-01 7.5294118e-01 7.1250000e-01 6.2162162e-01 6.7500000e-01 7.2727273e-01 6.2337662e-01 6.2337662e-01 6.7948718e-01 6.5853659e-01 6.6250000e-01 6.3380282e-01 7.3417722e-01 6.0869565e-01 7.2000000e-01 7.5949367e-01 6.4556962e-01 6.3013699e-01 5.9420290e-01 6.2857143e-01 7.1794872e-01 7.3972603e-01 6.4864865e-01 6.4864865e-01 6.8918919e-01 6.6666667e-01 7.0512821e-01 6.2500000e-01 6.2318841e-01 6.6197183e-01 6.5277778e-01 6.9135802e-01 6.6216216e-01 6.6666667e-01 6.4285714e-01 6.6216216e-01 6.8115942e-01 6.2500000e-01 6.2500000e-01 7.3684211e-01 6.4473684e-01 7.3417722e-01 7.1052632e-01 6.3888889e-01 7.3417722e-01 6.5432099e-01 6.9230769e-01 7.1428571e-01 6.7567568e-01 6.7532468e-01 6.7605634e-01 6.5789474e-01 5.4285714e-01 6.9736842e-01 6.2337662e-01 6.6233766e-01 6.7605634e-01 7.0270270e-01 6.1842105e-01 6.7567568e-01 6.2318841e-01 6.7605634e-01 6.9333333e-01 7.1428571e-01 6.0000000e-01 6.0000000e-01 6.6197183e-01 6.9230769e-01 6.8000000e-01 7.2000000e-01 6.5384615e-01 6.5753425e-01 6.6197183e-01 7.1232877e-01 6.9333333e-01 7.5000000e-01 7.1052632e-01 6.7567568e-01 6.4285714e-01 6.0273973e-01 5.8571429e-01 6.9512195e-01 6.3013699e-01 6.8918919e-01 7.0270270e-01 6.6666667e-01 6.8571429e-01 6.6666667e-01 6.1111111e-01 7.0666667e-01 6.6666667e-01 6.5333333e-01 6.8674699e-01 7.0731707e-01 6.3636364e-01 6.3750000e-01 6.1643836e-01 6.5432099e-01 5.8441558e-01 5.8666667e-01 4.7297297e-01 5.5263158e-01 6.9736842e-01 6.9333333e-01 6.5789474e-01 5.7575758e-01 6.7532468e-01 7.0886076e-01 6.4383562e-01 5.8666667e-01 6.6233766e-01 7.5000000e-01 6.2500000e-01 7.7027027e-01 6.0563380e-01 6.8000000e-01 5.6716418e-01 6.7948718e-01 6.4864865e-01 6.1971831e-01 7.1428571e-01 6.5753425e-01 6.7567568e-01 6.6197183e-01 7.7108434e-01 6.6216216e-01 7.1232877e-01 6.4000000e-01 7.0886076e-01 6.0563380e-01 6.2337662e-01 6.2666667e-01 7.7922078e-01 7.2972973e-01 7.5342466e-01 5.7971014e-01 7.3333333e-01 7.0886076e-01 6.6216216e-01 6.4102564e-01 5.8904110e-01 7.3076923e-01 6.4102564e-01 7.1250000e-01 6.4473684e-01 5.9154930e-01 5.3424658e-01 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-jensenshannon-ml-iris.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-jensenshannon-ml-iris.txt new file mode 100644 index 0000000000000000000000000000000000000000..da698cf511e6983e1db1bbed6e2974f3480a6903 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-jensenshannon-ml-iris.txt @@ -0,0 +1 @@ +0.0211635609063 0.00455072769716 0.0230610904531 0.0076674324982 0.037571216894 0.029561354778 0.0115281186735 0.0225809070507 0.0346801442638 0.00321049176948 0.0232839774828 0.0321124517082 0.0244179197971 0.0331466156799 0.0373949302575 0.0411984503375 0.0218945865519 0.0198268474453 0.02395616278 0.0254898420418 0.0394901943037 0.0396613298853 0.0621120626322 0.0458316817045 0.0334832834948 0.0445794256135 0.00775602650151 0.00770188279153 0.0277044809709 0.0292851269343 0.0408206135002 0.0384837880405 0.0229145225178 0.0346801442638 0.017155900548 0.0186865079856 0.0346801442638 0.011778601551 0.0109570078484 0.0244803928224 0.0609237090857 0.0125274661674 0.0713079215249 0.05072181848 0.0329702193648 0.018118079192 0.0129441131729 0.00461235131171 0.0077204189151 0.190781073622 0.196235539354 0.202381067744 0.215567934651 0.208951210729 0.208395222197 0.202977772245 0.185995150024 0.197488445796 0.207754344906 0.207231776416 0.200895721783 0.202370257926 0.208839694602 0.184151316466 0.18979501874 0.211864590783 0.187854399445 0.231134943838 0.195836809821 0.220082308081 0.191451897661 0.227329222402 0.204586412278 0.192443163994 0.193684928543 0.206841791869 0.21612354251 0.209268704489 0.175345617131 0.197941218478 0.190625337098 0.191065854858 0.2317867516 0.214902945463 0.200203629275 0.200116177839 0.216845735492 0.194043462589 0.208271280018 0.210985756639 0.203659220099 0.197020978632 0.188475437149 0.205376756706 0.190989482965 0.1980172695 0.194499957306 0.176357663314 0.198492265793 0.255232551639 0.244270007892 0.240469208946 0.23837051036 0.248414598574 0.246817944636 0.244919131711 0.239985639856 0.249741998486 0.238825041235 0.224881988223 0.240479022193 0.236919216915 0.253134884385 0.257281336145 0.239143010746 0.231252341207 0.230464321684 0.26688757037 0.243702807017 0.239741931201 0.243722504108 0.250777226737 0.230838149152 0.233779458319 0.227365052742 0.226996712309 0.224529623997 0.248876761269 0.223504306637 0.241222705588 0.218359591571 0.251783757155 0.22178058433 0.237922879169 0.243259140467 0.243757719218 0.229784431814 0.223834512884 0.231417699032 0.245855002542 0.23260880661 0.244270007892 0.24412721812 0.245364556958 0.239069534798 0.242476824971 0.231950344971 0.238821966724 0.23119389821 0.0191037071088 0.0192689125135 0.0279599225292 0.0400056720024 0.0369973592153 0.0168401225107 0.0156647141811 0.0317569365649 0.0209196472407 0.0261095572505 0.0295911292198 0.0387034711929 0.047943015361 0.0502801086558 0.0505076233319 0.0276985510653 0.0178344200842 0.0354647529806 0.0132311775272 0.0439058315568 0.0587698655317 0.0548749800113 0.0420211683289 0.0158475875817 0.0410205075223 0.0159821398213 0.0151652303532 0.0238719428054 0.0190485214781 0.0351129659726 0.0545720530766 0.0439213935019 0.0317569365649 0.0241815879409 0.0259117209292 0.0317569365649 0.0173211662353 0.0138864344566 0.0338981856531 0.0429537854169 0.027658485714 0.0691172321094 0.0500059403041 0.0236011037029 0.0316644090037 0.0201837094834 0.0228863104939 0.0134861623597 0.176517909274 0.183281450302 0.188265462996 0.20119658342 0.194697326208 0.195209942657 0.190674274015 0.172425697578 0.182894065786 0.195529592383 0.192026007893 0.188346396823 0.186051479032 0.19538200246 0.171605310091 0.175766658214 0.199864266754 0.173408334646 0.215875435175 0.181358449055 0.208526316653 0.177419239992 0.212710197663 0.190468934035 0.178153770213 0.179556589614 0.19192211318 0.202468559318 0.196181327665 0.160572766746 0.183327527516 0.175701303909 0.177066663037 0.218355819513 0.203310616701 0.188843124957 0.186323930321 0.201194011774 0.18173319992 0.194510318604 0.197386404553 0.190483994401 0.182718294182 0.174255518011 0.19205782762 0.178239088983 0.18513760318 0.180597338326 0.163063102971 0.185284857996 0.243887274146 0.231624187925 0.22689829944 0.225289762668 0.235796354542 0.23269059518 0.23306609907 0.225602345189 0.235244584021 0.226892475392 0.212543999067 0.226908361887 0.223757309255 0.240296170501 0.245569279789 0.227339668618 0.2180947426 0.217889650333 0.252259964829 0.228879839341 0.227150610245 0.231836962279 0.236076260811 0.217244760533 0.221438124324 0.213671912157 0.213819376581 0.212040793299 0.235827974309 0.209053467969 0.226615210725 0.205271111175 0.238869689413 0.207939309627 0.223898822147 0.229226063436 0.232630777303 0.217026651272 0.211532427176 0.218347693285 0.233460132247 0.219891922362 0.231624187925 0.231652249658 0.233525349836 0.226377769419 0.228579062405 0.219098380821 0.227789794229 0.219023772057 0.0212386043587 0.00993825296406 0.0336976816686 0.0262325070397 0.0107568964379 0.0200399473123 0.0369530877134 0.00706121377315 0.0225180018442 0.0345620434634 0.0288649599558 0.0352792061476 0.0352526366714 0.0385518621347 0.0178346265809 0.0156087458393 0.0212893461987 0.0244762891905 0.0356848493955 0.0412118431681 0.0577499958146 0.0449060313177 0.0316682156452 0.0402876009485 0.00791017688182 0.00777689270989 0.0262859463939 0.0275691765497 0.0363841779992 0.0426229028778 0.0258430808451 0.0369530877134 0.0171494695134 0.0197038085728 0.0369530877134 0.00856221073911 0.010146504576 0.0213442662268 0.0572142712511 0.0116574543859 0.0671597340405 0.047388301579 0.0285557929122 0.0192111185981 0.0112749020632 0.00781127840012 0.00637566729419 0.187210918471 0.192623672543 0.198833727144 0.212008654042 0.205367416257 0.204958566039 0.199402528264 0.182409867249 0.193987091024 0.204155295526 0.20374075502 0.197257634781 0.198980554413 0.205364330922 0.180426094029 0.186163209648 0.208359044162 0.184479344493 0.227592539467 0.192334488284 0.216529219774 0.187806950452 0.223855994439 0.201226354807 0.188864300604 0.190066520684 0.203335651256 0.212548662023 0.205705049083 0.171742464799 0.194417377469 0.187136601809 0.187472552212 0.228344421279 0.211429948522 0.196622478767 0.196530972542 0.21335054643 0.190497911091 0.204702393397 0.207598118603 0.200155023454 0.193467129006 0.184880183147 0.201857382862 0.187517863683 0.194486736804 0.1909406597 0.172553592377 0.194927231832 0.251743344729 0.240762357546 0.236947962879 0.234942968898 0.244909063494 0.243388177909 0.24143957892 0.236617606758 0.24633077256 0.235257992461 0.221275459366 0.23695229759 0.23334624948 0.249598367646 0.253700089415 0.235542233543 0.227782636512 0.227013807453 0.263469639225 0.240293112196 0.236160757703 0.240179126335 0.247395319298 0.227257451928 0.23025606552 0.223937789122 0.223399862869 0.220967129276 0.245363860699 0.220116506797 0.237779687596 0.214888164759 0.248252329967 0.218347705592 0.234681014401 0.239690494574 0.240217402996 0.22632629355 0.220260809644 0.227813787503 0.242262375922 0.228918020841 0.240762357546 0.240592325032 0.241778783496 0.235418026861 0.23890352284 0.228365058816 0.235271978928 0.227703766766 0.0251699105319 0.0326109277538 0.029278801732 0.0117605763436 0.00495713045566 0.032971458625 0.022273270218 0.00845866705418 0.0338325850006 0.0418060793613 0.0560571569439 0.0475989809058 0.0526432986362 0.0287512950603 0.0156470261333 0.0286833299321 0.0125318521449 0.039628171731 0.0605879245284 0.051592881751 0.0247889558 0.0185457610439 0.0360813596602 0.0162897964903 0.0233731835598 0.00555113851114 0.00851608036789 0.039350861172 0.0494281040416 0.0428445793936 0.032971458625 0.0361084743768 0.0382083791018 0.032971458625 0.0135564720949 0.0133460812565 0.0359059029584 0.0525998249753 0.020448013216 0.0653401649712 0.0366222774812 0.0276779812669 0.0199994530533 0.0115734561992 0.0214333278479 0.0186461579961 0.171344593808 0.177166238774 0.182950771401 0.19643196185 0.18986301898 0.188443393542 0.18388535541 0.166562175459 0.177783941311 0.188923487579 0.187724110496 0.182156573883 0.18272910062 0.189078094755 0.165787292858 0.170722554665 0.192539814536 0.167433166664 0.21234151671 0.17610118578 0.201339136255 0.172496446246 0.207869320447 0.184234771078 0.173084677744 0.174586008872 0.187343267555 0.197067369338 0.190065322687 0.155992913972 0.178370192697 0.170834599332 0.171756811444 0.21215391799 0.195543956872 0.181382419503 0.180878423055 0.197648250997 0.174630568935 0.189049602981 0.190809942592 0.184007315234 0.177572802284 0.169158986096 0.1858235382 0.171054750208 0.178472858167 0.175024341592 0.15843173338 0.179125844986 0.236753289776 0.225336913605 0.221457751336 0.21877528886 0.229546376269 0.227338714151 0.226000082599 0.220106179064 0.230241030133 0.220420771483 0.206398010187 0.221506177578 0.218254053746 0.234550382603 0.23950257292 0.221077875617 0.211789394262 0.210958467875 0.247726054061 0.224160699687 0.221293898641 0.225242596712 0.231164838975 0.212084684776 0.21483758197 0.207582855086 0.208324546741 0.205668770285 0.22999948579 0.203519866038 0.221791807814 0.198729512666 0.233119883684 0.201955632148 0.21744774227 0.224658382044 0.22554531899 0.210282327898 0.205086194314 0.212901784527 0.227685054369 0.214992030153 0.225336913605 0.225426421062 0.227294020009 0.22122180599 0.223891772502 0.213328572484 0.220627825622 0.212027719306 0.036692370716 0.0274221847228 0.014614486903 0.0257905543192 0.038185072385 0.00854173398239 0.0228846598272 0.0362880440778 0.0247966202157 0.0338575762449 0.0341810302892 0.0403839419732 0.023192138006 0.0228332335778 0.0207802721216 0.030246984472 0.0385095591836 0.036116458124 0.063670015249 0.0456331337141 0.0387265099713 0.0454622939774 0.0128829753328 0.0153687384621 0.0290580106985 0.032571197138 0.0439484983687 0.0345946330706 0.0178789804494 0.038185072385 0.0229066226947 0.0243703411158 0.038185072385 0.0145921399018 0.0157758022112 0.0246899780508 0.0667942861058 0.00859371091119 0.0713780561444 0.0493343894065 0.0370078971529 0.0136450272229 0.0138896306008 0.00617904291603 0.0146027872105 0.19304474601 0.19797909852 0.204564547012 0.217893788171 0.211240589753 0.210085035577 0.204424468033 0.187966151726 0.199846283114 0.209201380502 0.209876418912 0.202509063074 0.205495616388 0.210676243708 0.185852822947 0.192014733821 0.213129345848 0.190059083655 0.233894763867 0.198141527364 0.221234996275 0.193689434624 0.229701750232 0.206631480423 0.194727732257 0.195938025333 0.209362001884 0.218147207364 0.211029564766 0.177869147322 0.200327033561 0.193124484677 0.193233901741 0.233604044389 0.215980508747 0.201289146742 0.20219168761 0.219726845187 0.195458087393 0.2103246028 0.212820091698 0.205396680761 0.199290845186 0.190742394929 0.207189399227 0.192521418757 0.199651552643 0.196594932336 0.178468769167 0.200295584792 0.256297768876 0.245841451519 0.242438509968 0.240033073248 0.249980802879 0.248953385462 0.246144223104 0.242178797272 0.252036489845 0.240176361939 0.226412773569 0.242454491215 0.238768549206 0.254841315698 0.258625650226 0.240494667361 0.232976534038 0.231927166971 0.269283834821 0.246140263748 0.241374087503 0.245035624054 0.253144665918 0.232868387014 0.235226383286 0.229279397026 0.228861516729 0.226064745168 0.250630665997 0.225726655668 0.243583203961 0.220042394187 0.253511231548 0.2237596548 0.239872842457 0.245497904196 0.24478307529 0.231328796826 0.225307213023 0.233256809435 0.247442229489 0.234444929147 0.245841451519 0.245661961251 0.246724980668 0.240848644418 0.244659004118 0.233675626419 0.239814102397 0.232532592403 0.010524058973 0.0347497758249 0.0310026365608 0.0636683508445 0.039628310023 0.0339732471818 0.0632599742009 0.0607622080336 0.0610552648732 0.0274939888458 0.0321794296029 0.0203038890155 0.0225566538528 0.0181521200419 0.0426282898435 0.00971744861179 0.0573638408809 0.0304112802741 0.0463628234513 0.044509344874 0.0125060810098 0.0372012029006 0.0399195029174 0.0351572922113 0.0381714857339 0.0236066809352 0.0675880085279 0.0489234884353 0.0636683508445 0.0451372647506 0.0495218266562 0.0636683508445 0.028718795999 0.0363358460459 0.0247409309981 0.0536494939568 0.0291783067693 0.0362475310016 0.0206193569389 0.0238060051702 0.0365127412376 0.0303247636874 0.0382706081182 0.036679138207 0.165252454208 0.168745392776 0.176697416201 0.190075579294 0.183193768644 0.182210296577 0.174895117306 0.159516185843 0.172780618769 0.179424300801 0.183362052205 0.17275366841 0.180884475296 0.18272692365 0.155645508044 0.163596126812 0.183814684533 0.163944686708 0.206939183794 0.170981324059 0.191238016882 0.165171506195 0.202635613449 0.180157192696 0.16688029242 0.167662828735 0.182473473654 0.189606814944 0.182144568907 0.150494922446 0.17311022882 0.166528964674 0.165043072843 0.205731384902 0.18659197245 0.17105591364 0.173799739615 0.193545885155 0.166211621507 0.181959703917 0.185636136233 0.177047042786 0.171588556623 0.162758165885 0.178831153511 0.164197394115 0.170920859204 0.168528635782 0.148460744764 0.171573948268 0.226522867074 0.216861787556 0.214094925757 0.211961277469 0.220987866614 0.22168305754 0.216782699249 0.215609692292 0.225208444508 0.210312198283 0.19661028383 0.214074476024 0.209773195915 0.225810880474 0.228551359916 0.210341321513 0.204691741777 0.203336697222 0.242485382573 0.21963599647 0.211892193047 0.215282949931 0.226705435666 0.20418234927 0.205942096193 0.201754356567 0.199749686219 0.196656401255 0.221913123953 0.199165134473 0.216656797893 0.191759529503 0.224569670715 0.196349964299 0.213992874847 0.217230566883 0.214548114667 0.2028246956 0.195690210734 0.20400781198 0.217750478797 0.204445613083 0.216861787556 0.216379424168 0.21668692278 0.211041069144 0.216249554038 0.204373397921 0.209459569208 0.203359671893 0.0284940982012 0.0283835072119 0.0582564069663 0.0317209110303 0.0290062929149 0.0575581968066 0.0518675712793 0.0525497818792 0.0214648817816 0.0289820919427 0.0151981567712 0.0194868108708 0.00772151270155 0.0396885548083 0.0133170749495 0.0480498930165 0.0406834920646 0.0454173876936 0.04374952779 0.0223043370554 0.0304932603619 0.0333669476098 0.0323541790178 0.036462611527 0.0283937271683 0.0581656862224 0.0386849486073 0.0582564069663 0.0386824403573 0.0427767064205 0.0582564069663 0.0225670168648 0.0303996112373 0.0186317385432 0.0589532282724 0.020129496567 0.0456219811369 0.0271705146906 0.0266114081755 0.0281840659315 0.0237276312035 0.0300017258072 0.0304084467621 0.174689674341 0.17830904459 0.186122916272 0.199541551099 0.192698821274 0.191439303409 0.184399484383 0.168993025372 0.182083678728 0.188980455315 0.192641208359 0.182376656778 0.189869605957 0.192034662906 0.165406381187 0.173160863593 0.193190156667 0.172952807322 0.216356837462 0.18028635421 0.200707489616 0.174765006311 0.211946253402 0.189197004074 0.176338357547 0.17720731475 0.191796191467 0.199121585044 0.191634817003 0.159923924784 0.182459504488 0.175769947329 0.174536678956 0.215011640541 0.195898920801 0.180555890973 0.183304141459 0.202828623711 0.175640593326 0.191448592698 0.194762075203 0.186406863824 0.181008054094 0.172240816201 0.188223844291 0.17346231425 0.180325575914 0.177965844821 0.158332658267 0.181046361448 0.235882031296 0.226280867303 0.2235366831 0.221221709251 0.230404936567 0.23094802366 0.226136073658 0.224736021115 0.234431734165 0.219824894986 0.20619515856 0.223526372128 0.219308937798 0.235287233784 0.23807753807 0.219908336162 0.214027462834 0.212631745032 0.251732773763 0.228838671706 0.221440978506 0.224753704594 0.235866097652 0.213724598783 0.215380278296 0.210994508636 0.209321687173 0.206162323946 0.231346876087 0.208300913946 0.225928825898 0.201080283138 0.234037288778 0.20558958438 0.222856381147 0.226751911512 0.223989137906 0.212135251626 0.205214537461 0.213595258296 0.2273163389 0.21417146415 0.226280867303 0.225846388312 0.226229092302 0.220705781832 0.225781259333 0.213928177909 0.218913775078 0.212729498479 0.0122225873329 0.0303322491715 0.0105162282326 0.0130161869455 0.0294681125528 0.031169289575 0.0445674903412 0.0424428041907 0.0471592401326 0.0242919299586 0.0151911030837 0.0250458377851 0.0159588466859 0.0393890228389 0.0501712969027 0.0573610210315 0.0347635318983 0.0244162409612 0.040396894165 0.00489128055225 0.0130158047868 0.0162739668734 0.0181749821427 0.0399100872217 0.0416234365466 0.032217222914 0.0303322491715 0.0260818708259 0.0277812891175 0.0303322491715 0.0068887146948 0.00350057866506 0.0298024545939 0.056647752597 0.0131029257559 0.0689399130874 0.0438694576111 0.0295733202179 0.0148293487362 0.005187559828 0.00994170320116 0.00857601759458 0.181761248694 0.187453410696 0.193365623784 0.206702523841 0.20011934013 0.199105672278 0.194191029325 0.176999836949 0.188302627791 0.199111466491 0.198126208998 0.192301121465 0.193121251528 0.199652739338 0.175765384319 0.180985589904 0.202947496477 0.178262931918 0.22241465847 0.18663850283 0.211489015658 0.182706386145 0.218266373994 0.195039865626 0.18346554188 0.184856636434 0.197755074291 0.207324505424 0.200404409787 0.166355990223 0.188830148216 0.181378679541 0.182125858248 0.222660838403 0.205968099039 0.191576935017 0.19121911341 0.207887116649 0.185081160877 0.199380829938 0.201554837448 0.194543615891 0.187991163757 0.179524780118 0.19631300534 0.181726234556 0.188970696545 0.185468734774 0.168191837054 0.18953883133 0.246767069406 0.235545780286 0.231684267956 0.229269594484 0.239724337717 0.237749571543 0.236212316891 0.230682790909 0.240645700931 0.230405224861 0.216420479968 0.231715542723 0.228337424754 0.244594612682 0.249193956399 0.230909382279 0.222229420235 0.221427946934 0.257965809127 0.234573740528 0.231288571496 0.235259005866 0.241607850531 0.22220070955 0.225060949621 0.218149643482 0.218415896436 0.21585883122 0.24017332069 0.214149237729 0.232167950695 0.20925074028 0.243199182069 0.21253980165 0.228281003551 0.23468620257 0.235446691383 0.22074773222 0.215228869367 0.222922571895 0.237553097068 0.224606387466 0.235545780286 0.235534393045 0.23712429287 0.230940484692 0.233917063813 0.223401305554 0.230524046304 0.222353817706 0.0346270873711 0.0222428303765 0.0130402644662 0.0348466257078 0.042829178942 0.0549568638218 0.0464424131108 0.050271964255 0.0260503884653 0.0122224116333 0.0282180922789 0.011864843965 0.0376053109772 0.060340947297 0.0487164281844 0.0285013587126 0.0163929694658 0.0334500762426 0.015996373074 0.0216948948211 0.00981357617646 0.00897169179454 0.0351677992971 0.0524329239391 0.0436506734112 0.0346270873711 0.0336931600411 0.03612022228 0.0346270873711 0.0123155461924 0.0128144174355 0.033561339537 0.0480641708164 0.0212422700005 0.0628734973132 0.0366806543871 0.0231396795589 0.0230741684915 0.0123098386274 0.0219470818919 0.0170687771133 0.170097980345 0.176050748737 0.181762587161 0.195138740624 0.188553715994 0.187634353283 0.182931238354 0.165421712546 0.176600578903 0.187912731345 0.186408453678 0.181027641681 0.181322068987 0.188146844457 0.16448627936 0.169388121003 0.191757508168 0.166524283083 0.21084441712 0.17494262847 0.200480456222 0.171127562134 0.206682857942 0.183402734812 0.171811556423 0.173255302855 0.186064001811 0.195873759085 0.189008503285 0.154586199139 0.177136590503 0.16961214015 0.170511848112 0.211247624618 0.194873193684 0.18053463387 0.179673493778 0.196193226513 0.173758955601 0.187869379999 0.19001738823 0.183074417621 0.176342969787 0.167870586049 0.184832516957 0.170273119593 0.177542554096 0.173865162824 0.156824879402 0.178069468543 0.235952767235 0.224377142544 0.220334312937 0.217941307072 0.228582134377 0.226295522057 0.225204079848 0.219149120214 0.229153457047 0.219423743811 0.20530168342 0.220370010221 0.217084867796 0.233463162138 0.238411309618 0.220004052761 0.210872881275 0.210171938201 0.24654768975 0.223020715486 0.220176358035 0.224293060856 0.230089603615 0.210845620347 0.213914309618 0.206670271948 0.207126565579 0.204661896322 0.228953899388 0.202543633745 0.220637247329 0.197849243585 0.232039444595 0.201016080923 0.216786754649 0.223327252818 0.224678101179 0.209454984614 0.204079198003 0.211687536154 0.226538202286 0.213579234366 0.224377142544 0.224425108032 0.226231350025 0.219899730556 0.222577135927 0.212192019374 0.21976273048 0.211209202307 0.0316629149872 0.033505533415 0.00599304401229 0.03147088677 0.0569379974042 0.0709823822809 0.0748230813085 0.0531369685873 0.043263968218 0.0546416139704 0.0249055105449 0.0688386171987 0.0687094353901 0.0814189949505 0.0424145094995 0.0312264925083 0.0671690041442 0.0297074253675 0.0326159908833 0.0331671559449 0.0312681130066 0.0653641254742 0.040141041955 0.0490986378456 0.0 0.0426893927085 0.0408370899258 0.0 0.0368318621027 0.029200211213 0.0578784327643 0.069522041979 0.0411420259607 0.0955605905857 0.0684916485028 0.0536985636371 0.0361283833003 0.0349236407736 0.0326544016244 0.0320790517512 0.190734279342 0.198011093099 0.202165335147 0.215193803756 0.208989236133 0.207943677959 0.205067684162 0.186855165408 0.196324830352 0.210203923195 0.205342231011 0.203427359944 0.198526873832 0.208498767129 0.187766259392 0.1906844311 0.213518747065 0.185598548292 0.229746939288 0.194805777978 0.222821572969 0.192481412892 0.225723793976 0.202375384198 0.192457483521 0.194300696695 0.205376522136 0.216660688755 0.21030774241 0.175307222553 0.197000980201 0.189066511629 0.191539232379 0.231058906578 0.21669613367 0.203523564636 0.200666530244 0.214595210264 0.195827171333 0.208641958794 0.209561099462 0.203960485003 0.196717491572 0.188766309975 0.205678014795 0.191492051166 0.198961164508 0.194672996958 0.180152450124 0.19944864987 0.257583228235 0.245178524187 0.240481186058 0.23786630337 0.249341975217 0.245210894146 0.246468005973 0.237456371003 0.247563146561 0.241300303041 0.22729752986 0.240555698528 0.237993038095 0.254193700204 0.26033321069 0.24220764546 0.231128442611 0.230799434891 0.264694157473 0.241194058993 0.241588310222 0.245985985156 0.248083056968 0.231516408669 0.235215479132 0.226198260689 0.228320459149 0.22623565919 0.249391170367 0.221152204365 0.239284874476 0.218351963925 0.252686589685 0.220530747351 0.234477098822 0.243363395844 0.246969168578 0.229990071021 0.225895881072 0.232959826282 0.248113114083 0.23570223574 0.245178524187 0.245562733947 0.248226439579 0.241702239505 0.242775171886 0.233515238499 0.242256602421 0.232453320509 0.0221776604768 0.0292076409984 0.0225953199419 0.0344078822964 0.0402556862186 0.0443490345462 0.0247422055695 0.0212582761966 0.0262237412261 0.0239779350196 0.0420497572884 0.0414593565817 0.0638943455501 0.0444256278823 0.0324613404347 0.0464717210574 0.0064847144584 0.00810593532016 0.026613709743 0.0281809240896 0.0431707040779 0.0364933096346 0.0236549105265 0.0316629149872 0.0188389154871 0.0197111271958 0.0316629149872 0.0126413659503 0.00989228745945 0.0276229976961 0.0619054176788 0.0136582341261 0.0735855911944 0.0517713161376 0.0346942423053 0.0171636471405 0.0128780143687 0.00330427938484 0.00787705209324 0.191124461218 0.196709270957 0.202716444922 0.215924187936 0.209335641351 0.208652638742 0.203456445375 0.186385899088 0.197740844714 0.208277146555 0.207460837635 0.201437849638 0.202451222155 0.209128071387 0.184787202976 0.190226937612 0.212288039878 0.187958804478 0.231460569504 0.196093364986 0.220613648389 0.191903262961 0.227580912528 0.204703238288 0.192798319471 0.194099784682 0.207098250381 0.21653588119 0.209689452484 0.175692486622 0.198220686642 0.190843207535 0.19145100341 0.232063526554 0.215320322312 0.200757345911 0.200512766736 0.217080327154 0.194471953875 0.2086592247 0.211165769014 0.203992872465 0.197349559187 0.188849659131 0.205722712353 0.191296031353 0.198394567468 0.194851113014 0.177048060287 0.198893335106 0.255751598489 0.244696550693 0.240850735029 0.238657915403 0.248846650839 0.247061872969 0.245367004129 0.240135191988 0.249950401792 0.239377278919 0.225435027987 0.240867925442 0.23738991955 0.253602763959 0.257909304325 0.239755581779 0.231578379023 0.230802663983 0.267123052444 0.243889033036 0.240266927764 0.244253437447 0.250943098487 0.231284290644 0.234232349856 0.227603903464 0.227483301065 0.225010355342 0.249291083828 0.223656027478 0.241455021635 0.21867583866 0.252237135554 0.222012069338 0.237944922778 0.2436864771 0.244348021388 0.230119265967 0.224342678419 0.231928535106 0.246422479994 0.233277995952 0.244696550693 0.244602643666 0.245964063641 0.239692017082 0.242916090829 0.232449793011 0.23942553099 0.231611684555 0.0349328180738 0.0397488289561 0.055917859907 0.0466657680267 0.0537525131124 0.0312322620487 0.0204661899168 0.0273925121636 0.0188335643607 0.0409848131484 0.0582072876054 0.056071962696 0.0229170555223 0.0261517042618 0.0397135231185 0.0177392332242 0.0260266328079 0.00803879586998 0.0153514357558 0.0448019039458 0.0436873202641 0.0393784019825 0.033505533415 0.038918396453 0.040710313775 0.033505533415 0.0158373818638 0.0159973219202 0.0374102115892 0.0608056403948 0.0178404535904 0.0681680501025 0.0368277650919 0.0342153028534 0.0136005609896 0.0114725513671 0.0202654226306 0.0215111320227 0.175502940168 0.180846739943 0.186993890383 0.200622200655 0.194047326964 0.191871659177 0.187230724864 0.170446969951 0.181958118895 0.192296146604 0.192168805538 0.185737701873 0.187567790504 0.1926934047 0.169562979332 0.174903941965 0.195627236518 0.171332536122 0.216941277953 0.180224282629 0.204375817171 0.176708588212 0.212007481629 0.187940100384 0.177271729963 0.178782860675 0.191678059195 0.200974345147 0.193702992688 0.160469688943 0.182595805427 0.175146841545 0.17584337797 0.215706304999 0.198413689274 0.184386485081 0.184856323095 0.20232915317 0.177913816132 0.192982627694 0.194328346433 0.187558388958 0.181714052911 0.173349805963 0.189464804214 0.174374123803 0.181953747446 0.178997842818 0.162709307879 0.18281187754 0.239644460978 0.228724428122 0.225246554022 0.222159074766 0.232927392687 0.231188577573 0.229024014707 0.22394884582 0.234228075319 0.223668927512 0.209861178703 0.225307285274 0.221985913786 0.238104571085 0.242774657148 0.224369518131 0.215280858443 0.214174032708 0.25182022511 0.228290074367 0.224826938646 0.228427350702 0.235193041024 0.216001866886 0.218122104545 0.211215702011 0.212099059638 0.209083204086 0.233569980649 0.207419375116 0.225880589953 0.202184861075 0.236687676647 0.205660738951 0.22091809464 0.228766193737 0.228457617824 0.2135856342 0.208453819381 0.216659972673 0.231192094033 0.218856194539 0.228724428122 0.228811270004 0.230578167797 0.224983578773 0.22794936407 0.216954366886 0.223518672063 0.215168993038 0.0278789967436 0.0521696459286 0.0689795584164 0.0720246274977 0.0510464689946 0.0421745394626 0.053582971262 0.0252834975098 0.0677158937278 0.0652657188093 0.081318384881 0.0463957610979 0.0317140261778 0.0668416555065 0.0279143378417 0.0293650428541 0.0349789935753 0.032697569141 0.0634994948437 0.0398508689254 0.0464805914619 0.00599304401229 0.0382168939676 0.0359888514026 0.00599304401229 0.0356302780251 0.0278103138868 0.0553135387293 0.0681148770417 0.0401494228711 0.0950529579724 0.0698373790182 0.0522664102967 0.0364245082526 0.034367526255 0.0307005764611 0.0296340954647 0.193320448722 0.200616479264 0.204805927895 0.217738543992 0.211505662739 0.210916031972 0.207785188245 0.189492055249 0.199011305592 0.212849559963 0.207930120156 0.205973985295 0.201080290256 0.211364107387 0.190111543422 0.193149888648 0.216396870129 0.188564248953 0.232124397575 0.197509520178 0.225563508571 0.194908404083 0.228408782968 0.205404773753 0.195016829794 0.196780548006 0.207983584103 0.219251719916 0.21299620972 0.177753842585 0.19963357851 0.19173429638 0.194103048534 0.233951642516 0.219652294406 0.206249008964 0.203257559758 0.217055047586 0.19863330849 0.211258733702 0.212590735452 0.206794766477 0.199327419787 0.191301214309 0.208462930841 0.194441169877 0.201765843334 0.197324504463 0.182225897174 0.202147597456 0.260363424846 0.247928312505 0.243139798114 0.240805098305 0.252082485905 0.248010938223 0.249316339351 0.240374954583 0.250342905364 0.243926059402 0.229857687769 0.243199557315 0.240557269117 0.256813113392 0.262812568913 0.244726906585 0.233983032632 0.233739246967 0.267372287242 0.243942332388 0.244149194945 0.248660562989 0.250891907974 0.234045856002 0.23797517084 0.229108542601 0.230855414047 0.228916694642 0.252083674667 0.224056856634 0.242001030284 0.221239323161 0.255322806495 0.223424493307 0.237685672547 0.245823282675 0.249646734812 0.232903558602 0.228555612396 0.235462898266 0.250614129287 0.237926457957 0.247928312505 0.248245352669 0.250761236826 0.244030479155 0.2452417146 0.236085335476 0.244925556651 0.235313123462 0.0296919493074 0.0549103775111 0.0590022859872 0.0450958795243 0.0436647014416 0.0451669494409 0.0401697758406 0.0620690815544 0.0404063812339 0.0856236153109 0.0591687282212 0.0490473517415 0.0683619493373 0.0275851844543 0.0264002504943 0.0446945676427 0.0461763497794 0.0638640733472 0.0232220049486 0.0233353107646 0.03147088677 0.029201781247 0.02614478673 0.03147088677 0.0350355717384 0.030428654072 0.0452764113597 0.0802967236314 0.0328354116031 0.0941098407344 0.0724718577687 0.0562014612922 0.0313029110017 0.0340889421853 0.0234757814211 0.028925036543 0.210407140423 0.216202187825 0.221880775368 0.234954371989 0.228487320903 0.227668142527 0.22288748901 0.205844703323 0.216768667446 0.227711464843 0.226263348504 0.220970493431 0.220784685064 0.228189601628 0.204608420295 0.209669658318 0.231537789973 0.206793805641 0.250139733355 0.215157813925 0.239903556316 0.211352210266 0.246303099122 0.223431243026 0.212079033799 0.213468334673 0.225996065584 0.235701634712 0.228967589943 0.195079844754 0.217288259849 0.209835756349 0.210818201018 0.25087781482 0.234509225035 0.220284749566 0.219817558162 0.235704379779 0.213924917847 0.22786813663 0.229992970272 0.223192642095 0.216540668547 0.208207378637 0.224921456698 0.210576921517 0.217728441709 0.214138769918 0.196963968339 0.21825274764 0.274633184392 0.263620373951 0.259724001387 0.257434131046 0.267733388911 0.265627371082 0.264299751314 0.258574475793 0.268388644672 0.258492710734 0.244710620006 0.259750243754 0.256426981572 0.272472244255 0.27686351493 0.258914849135 0.250487159092 0.249742739323 0.285410306304 0.262307563551 0.259345413586 0.26329314732 0.269271128247 0.250334873532 0.253300294048 0.246383898221 0.246645581278 0.244211963707 0.268141898451 0.242252606427 0.260005586654 0.237699783889 0.271104326635 0.240825446457 0.256147548483 0.26253800174 0.263413026859 0.249061635853 0.243583443282 0.251070491042 0.265469741093 0.25252673858 0.263620373951 0.263585528386 0.265041995624 0.258842865142 0.261802853748 0.251583944502 0.25855292944 0.250657339544 0.0450102465608 0.0439198537957 0.0420878714528 0.0489743500788 0.0458798154287 0.0561577170329 0.0578224624858 0.0224176386409 0.0849412968827 0.0784422731853 0.0630254855321 0.0686145922194 0.0402128784166 0.0342259139129 0.0607491308771 0.0616063147121 0.059057582132 0.0469260494382 0.0248556117621 0.0569379974042 0.0246670677105 0.0228986845775 0.0569379974042 0.0437638412118 0.0433305015411 0.0375189879884 0.0808012493057 0.0411311531308 0.089015155435 0.0787045494767 0.0568803303557 0.0468151856286 0.0457099341419 0.0358166687321 0.0382966404493 0.218181156993 0.223322073096 0.229705702275 0.242392790988 0.23577882008 0.236467641295 0.230139466345 0.213525276303 0.225126391191 0.234563959305 0.23447409507 0.227593305984 0.22968375989 0.236629811874 0.210530415308 0.216784944512 0.23930372472 0.216469414915 0.257297585894 0.22354090813 0.246798396633 0.218282233397 0.254457430072 0.233053108231 0.219729861221 0.220661425884 0.234112165808 0.242944509178 0.236406584132 0.202708452811 0.225406734885 0.218378296681 0.218342011887 0.259279663879 0.242430236301 0.227193609953 0.227261836804 0.24357213448 0.22167035443 0.235341335514 0.239265397892 0.231386700827 0.224381906232 0.215751708357 0.232947742221 0.219218926008 0.225693206986 0.221969156729 0.202171293512 0.225894654473 0.281426284779 0.270908280604 0.267090828143 0.26583132699 0.274949583689 0.273930107263 0.271660675229 0.267616788632 0.276815360824 0.264923167376 0.251110814116 0.267050687079 0.263175899022 0.279239724537 0.282486166675 0.264820551157 0.258570659963 0.257930961428 0.293412787858 0.270816835713 0.265787467516 0.269896000193 0.277962792777 0.257183140616 0.260538043514 0.255036127386 0.253324298915 0.251219664681 0.275354649609 0.251349757403 0.268235077166 0.245978035775 0.277988121804 0.249516964722 0.266387651101 0.269264891567 0.269706692396 0.257221982881 0.25041421232 0.257531332229 0.271532129624 0.257608408712 0.270908280604 0.270491687514 0.271003440471 0.264326332823 0.268486578685 0.258229704408 0.264793848318 0.258283260113 0.0140423845301 0.0233496953457 0.0357817640834 0.0194594148752 0.0561842963236 0.0207161808072 0.0344686045315 0.0532665757163 0.0656105748711 0.0611304155975 0.0376479555399 0.0422417749013 0.0418045042693 0.0514369987371 0.0551924216967 0.0370785412495 0.0618826263881 0.03552992519 0.0709823822809 0.0406476055096 0.0445130802003 0.0709823822809 0.0367370595656 0.0436433053629 0.0176515558758 0.0714383400943 0.0313405988749 0.050902359898 0.0456873150128 0.0406736463161 0.0404939048403 0.0386201712918 0.0390017962403 0.0411563720519 0.190383467974 0.193150151335 0.201647820189 0.214732592431 0.207848794505 0.207203203998 0.199017728171 0.184517441065 0.198117570692 0.203251095462 0.208611510757 0.196706601418 0.206520396425 0.207659337014 0.179547279859 0.188402996857 0.207901541524 0.18984126915 0.231436366396 0.196328732424 0.214604717337 0.189868309751 0.227504737805 0.2057488472 0.191940214233 0.192467873609 0.207646738607 0.21397919575 0.206530920079 0.175883310987 0.198349858418 0.192082967323 0.190004696209 0.230325216181 0.21052421867 0.194679583814 0.198537353627 0.218586319181 0.19070413186 0.206580728089 0.210890308648 0.201869808993 0.196665077614 0.187817228574 0.203604184545 0.189253631177 0.195640755776 0.193545341254 0.172360847921 0.196255157011 0.249220192749 0.240515221189 0.238164043403 0.236348677214 0.244540315717 0.246252369823 0.240132469075 0.240621741867 0.249888930273 0.233326376677 0.219986372028 0.238112203328 0.233455949013 0.249164983161 0.25077275089 0.233019708703 0.229068571188 0.227556818352 0.266813634827 0.244493984417 0.235169888951 0.238293435462 0.251527743788 0.228140449415 0.22959779378 0.226587756924 0.223543468869 0.220396683922 0.245620426642 0.22441324809 0.241383050303 0.216373265669 0.24802824928 0.221314439433 0.239346728325 0.241091845042 0.237050180919 0.227111645095 0.219282181885 0.227591404442 0.240665010845 0.227138628142 0.240515221189 0.239782829874 0.239319392462 0.23385508337 0.24006053231 0.227964392353 0.231962468731 0.227162089828 0.0243523838323 0.0383436294161 0.0281380877138 0.0591143980174 0.023507742642 0.0377968944731 0.0517794728194 0.0731209286425 0.0626942772583 0.0386453724111 0.0461236944312 0.0433886463071 0.057222198299 0.0591551673076 0.0319956615202 0.0701506857494 0.0422353525103 0.0748230813085 0.0387325777977 0.0428806382505 0.0748230813085 0.0409657262208 0.047385502674 0.0175421295668 0.0657295550805 0.0386908764688 0.0489968109439 0.0522686619491 0.0387311691946 0.0491554938498 0.0442532671202 0.0441014308007 0.0436449779054 0.189947462454 0.193087358051 0.201270443197 0.213957860003 0.207091706444 0.207812220084 0.199357780455 0.184445706942 0.197758177741 0.203406879958 0.207785745488 0.196588475912 0.205402521621 0.207935882191 0.179126107639 0.187763747972 0.208638518258 0.190249811145 0.22994679767 0.196055336563 0.215105618909 0.189122223025 0.226906503622 0.206245399814 0.191418910324 0.191795589288 0.206939834769 0.213506326546 0.206505332082 0.175157210084 0.197857598212 0.191658112797 0.189588115864 0.230508642351 0.211553886467 0.195374420383 0.198156887541 0.217288762795 0.191332101287 0.206198782834 0.211486527696 0.202202827305 0.19621322526 0.187298385594 0.203764973183 0.190101114406 0.196046751208 0.193325009164 0.171164264517 0.19631141813 0.249660253112 0.240527632421 0.23771162293 0.236702658605 0.244516745342 0.245937622906 0.240621381598 0.240549902948 0.249413960629 0.233305723303 0.219774348622 0.237625603888 0.232924324305 0.248768260048 0.250380844287 0.232789805762 0.22924781342 0.228117670835 0.26599273559 0.24389404773 0.234785533178 0.238373023947 0.251062908639 0.227440481837 0.229791016779 0.226764157548 0.223002288166 0.220422035353 0.245352612988 0.224391473735 0.240777024278 0.216738025139 0.247654798968 0.221447853711 0.240056634641 0.240035093698 0.237386138185 0.227558813593 0.219321439562 0.226978987712 0.240167124817 0.22597544824 0.240527632421 0.2396924683 0.239078218682 0.232902821621 0.239060496039 0.227569835839 0.232339810664 0.227659905228 0.0141262101806 0.0139426926457 0.0350538423884 0.0193552608508 0.0431621025158 0.0440916637552 0.050896637678 0.0388189182549 0.0267566278127 0.024110231253 0.0232035130335 0.0336464874245 0.0349533341335 0.0219308383764 0.0572621322316 0.0349099564127 0.0531369685873 0.0252590392656 0.0298245046475 0.0531369685873 0.0175869571119 0.0244711956848 0.00818635303924 0.0514811245358 0.0194723442375 0.0509148981601 0.038941584783 0.0196470806889 0.0301479553419 0.021545096414 0.0245644202822 0.0217515624084 0.179463055971 0.184039565703 0.191058390156 0.204133065196 0.197353411589 0.197439799103 0.1907070948 0.174350095292 0.18671934138 0.195225461177 0.19666314681 0.188285080293 0.192912863971 0.197716084636 0.17106321505 0.177948538218 0.199885832792 0.178001143095 0.220003811923 0.185034059424 0.207478284578 0.179492397587 0.21650741229 0.194560853934 0.181055185718 0.181934852801 0.196069170377 0.204292703623 0.197354097622 0.164139489747 0.187014857055 0.180129327357 0.179477085752 0.220692949894 0.202951258529 0.187497059139 0.188415486818 0.206311756974 0.182082560815 0.196599300923 0.200515380101 0.192263706104 0.185773424375 0.176983033355 0.193914579783 0.179773695055 0.186365398569 0.183085748173 0.163066216827 0.18672092116 0.242702110891 0.232274391832 0.228788679171 0.227187602483 0.236388804345 0.235969651611 0.232778101812 0.229721372697 0.23914299349 0.226115326683 0.212181006801 0.228757804803 0.224715842477 0.240932159296 0.244193462731 0.226111600887 0.219855639469 0.218968698082 0.256162056313 0.233278273993 0.227208648321 0.231128251362 0.240452766308 0.218806638317 0.221623839858 0.216518120679 0.214708469871 0.212229381986 0.23697508889 0.213254322456 0.230501952576 0.207030794754 0.239662752997 0.210997516317 0.22840539478 0.231383198724 0.230834439598 0.218316993527 0.211375460714 0.218990694003 0.233092437868 0.219339375552 0.232274391832 0.231855607362 0.232408829329 0.226038981221 0.230519762371 0.219567778072 0.225824086027 0.219230412501 0.0195919993919 0.0221059172753 0.0271326704392 0.0528905379198 0.0431586822848 0.0385447030867 0.0255010287112 0.0262337606525 0.0170321830128 0.0195302099147 0.0206521036595 0.0209833716129 0.0252645250533 0.0550811186683 0.0394746523074 0.043263968218 0.0280088992059 0.0316978756724 0.043263968218 0.00932281475944 0.0154549635915 0.0220221996956 0.04619442006 0.0176558634743 0.0549187053198 0.0347531723104 0.0154010655624 0.0249961358537 0.0130624709681 0.021086975526 0.0157582275316 0.172494143831 0.17784850126 0.184169405165 0.197413015598 0.190717679771 0.190383314088 0.184688114733 0.167622718241 0.179385018024 0.189454833136 0.189254205537 0.182497405034 0.184783379021 0.190756581821 0.165553322788 0.171383967321 0.193742345805 0.169993474917 0.213189630746 0.17771520654 0.201947261672 0.173029090008 0.209395719039 0.186777092552 0.174149245532 0.175318744446 0.188797436083 0.197902799323 0.191019058185 0.156992121883 0.179797341784 0.172560525004 0.172720884671 0.213854773981 0.196871318612 0.181938976962 0.181811193063 0.198969640765 0.17576606357 0.19002752539 0.193102069722 0.185493626505 0.178790364297 0.170132074883 0.187191891105 0.172843021691 0.179777298661 0.176222723299 0.157641466463 0.180195116525 0.237394679003 0.226280310947 0.222447934209 0.220486140395 0.230450693082 0.229006895923 0.227001818993 0.222289337207 0.232008422548 0.22075701885 0.20666547313 0.222449960987 0.218801277251 0.235156691974 0.239347508119 0.221054539901 0.213261323555 0.212504634094 0.249237472588 0.225979854618 0.221636903122 0.225713392695 0.233125083698 0.212685206963 0.215719410439 0.209455227207 0.208792490533 0.206361366722 0.230902205737 0.20571314342 0.223403407555 0.200311655198 0.233802587518 0.20384593219 0.22048704521 0.225216247618 0.225812871456 0.211806271505 0.205652934938 0.213231447371 0.227786843309 0.214377387143 0.226280310947 0.226104307704 0.22732908173 0.220904746241 0.224415757753 0.21378854989 0.220845147853 0.213178189936 0.0385029210536 0.0191331286834 0.0412210559221 0.0479132957057 0.0465498029846 0.0439952648454 0.0294155998226 0.0263022819525 0.0288814535105 0.0321813612841 0.0366154046916 0.0324760763417 0.0515944791638 0.0310049526439 0.0546416139704 0.0338597056505 0.0376153728239 0.0546416139704 0.019563854062 0.0269885058553 0.0157505744896 0.0625368339241 0.0143844790412 0.0526157254036 0.0338348827289 0.0297234721938 0.0233631827985 0.0204547357021 0.0243203298193 0.026443786847 0.18161798851 0.18540629351 0.193056292253 0.206460086953 0.199649422865 0.198358533748 0.191516052491 0.176005251549 0.188914967022 0.196119500233 0.199392563722 0.189524653623 0.196344377596 0.19896940691 0.172616127427 0.180167039066 0.200264745011 0.179650753185 0.223145799502 0.187130729579 0.207841346365 0.181781654149 0.218763807382 0.195938920487 0.183272877978 0.184194077304 0.198599402775 0.206127033545 0.198682577368 0.166796826532 0.189310437328 0.182538488189 0.181515358431 0.221921151125 0.202966250725 0.187732725258 0.190303161279 0.209524247949 0.182729260129 0.198439370358 0.201593038612 0.193392410161 0.187922687561 0.179193994752 0.195211914017 0.180441261226 0.187358375156 0.184927566912 0.165517695891 0.188083050798 0.242939707589 0.233299699182 0.23049760933 0.228144979761 0.237419943564 0.237777043946 0.233178399857 0.23147925362 0.241203272786 0.226929567318 0.213318762235 0.230491320835 0.22634238089 0.242302330141 0.245163744774 0.227035678455 0.220985219764 0.21961554026 0.258484704802 0.235572463293 0.228516087928 0.231839786454 0.242586485114 0.220732170317 0.222439032331 0.217865646283 0.216378419732 0.213247698263 0.238336887242 0.215052759841 0.232719204269 0.208046041848 0.241045913549 0.212450914632 0.229495311164 0.23369764439 0.231101958719 0.219113353825 0.212320151032 0.220660185426 0.234399345217 0.221293359798 0.233299699182 0.23289508713 0.233336932661 0.227805970609 0.232744111879 0.220997609023 0.226042688917 0.219773770977 0.0487507947542 0.0650775470184 0.057802762893 0.0304021403296 0.00977564963899 0.0440829229362 0.0178656109143 0.0223657443481 0.0145412613726 0.00880579384939 0.0433599813023 0.0513293545711 0.0472054655688 0.0249055105449 0.0346274013058 0.0356855998153 0.0249055105449 0.0197624673252 0.0147740519949 0.0419438715965 0.0491548979957 0.0286642180871 0.0731736765881 0.0474587573553 0.0307413987988 0.0281173399333 0.0193986394444 0.0247050709585 0.0190246608336 0.173083486457 0.179910481276 0.184747521108 0.19795391577 0.191518465927 0.190900207622 0.18706914222 0.168885152715 0.179192090216 0.192134059909 0.188561922702 0.185169221179 0.182516578227 0.191341288573 0.168884190059 0.172666616329 0.195883736852 0.16891577804 0.213018522015 0.177613800133 0.204946600226 0.174427531668 0.209108112252 0.18591519295 0.174796071764 0.17642769541 0.188436163643 0.199161967465 0.19263437332 0.157387090389 0.179769711315 0.171986018804 0.173714059835 0.214316704261 0.199152104404 0.185242989169 0.182953007753 0.198045578814 0.177854485907 0.191103831493 0.192902410163 0.18652468984 0.179244739552 0.170950373519 0.188227253613 0.173938849831 0.181251003885 0.177034455953 0.160977434421 0.181661357468 0.240293898195 0.228034626835 0.223480275138 0.221169492968 0.232239647508 0.228872448909 0.229260803782 0.221433214134 0.231450162781 0.223643381382 0.209415344527 0.223528489107 0.220601809879 0.237045012584 0.242726403737 0.224366911478 0.21417342735 0.213777217999 0.24873924373 0.225124576112 0.224039797111 0.228474279829 0.232185938187 0.214138987375 0.217816173262 0.209554716543 0.210717178803 0.208592377005 0.232371287988 0.204873194809 0.222962175481 0.201230387345 0.23556954796 0.203837920113 0.218977104053 0.226289614933 0.229286064361 0.212971252918 0.208146125074 0.215343203422 0.230520772996 0.217614435398 0.228034626835 0.228243837858 0.230522424537 0.223850190554 0.225634530741 0.215935214332 0.224460188266 0.215143400901 0.0529022439667 0.0328752197893 0.0555054115849 0.0509289255649 0.0173017354019 0.040824127775 0.0418711547682 0.0429127577978 0.0455543968368 0.0222834470095 0.0700549868865 0.0480571802481 0.0688386171987 0.0442386440219 0.048830469586 0.0688386171987 0.0328274300443 0.0405886029945 0.0207406620607 0.0561033512724 0.0322786585229 0.0341942563123 0.0291137581017 0.0267606033099 0.0411628160219 0.0351933008888 0.0409598634365 0.0395653722748 0.170381496838 0.173513369262 0.181763628401 0.194913312213 0.188005094963 0.187597093173 0.17963993246 0.164619720579 0.178109956535 0.183964962678 0.188586214824 0.177259498897 0.186421186364 0.18797705999 0.159970598511 0.168451386355 0.188698976448 0.169860506279 0.211615177079 0.176329007245 0.195682012245 0.169937526308 0.20770892717 0.185927394166 0.171947667368 0.172526710735 0.187654893417 0.194331077481 0.186965121806 0.155693053512 0.178340485408 0.171986662107 0.170058435784 0.210831670623 0.191498228781 0.175622787806 0.178712133706 0.198589692402 0.171227708945 0.186830515333 0.191211132234 0.182219297429 0.176703062328 0.167807776518 0.183929379926 0.16962686739 0.17602523241 0.173642929989 0.152568053554 0.176555503125 0.230732284086 0.221405569072 0.21873883425 0.217008773205 0.22548132942 0.226701619289 0.221306518291 0.22096326048 0.23027897199 0.21448417882 0.200865540743 0.218691208961 0.214158679542 0.230111756153 0.232289297369 0.214283536851 0.209653108975 0.208315017711 0.24732302577 0.224778673487 0.216104443077 0.219500448511 0.231884032027 0.208661452368 0.210499772687 0.206990362059 0.20415679031 0.201176497026 0.226427503413 0.204626996142 0.221691815993 0.19686908479 0.228928610762 0.20163871009 0.219806895143 0.22162291443 0.218587303851 0.207804967644 0.200129766869 0.208295752101 0.221764477978 0.208127749312 0.221405569072 0.220756657587 0.220625985458 0.214861357139 0.220620889076 0.208723632287 0.213494112425 0.208081504586 0.0844496882978 0.080315980567 0.0726849367116 0.0675030089859 0.0473153931529 0.0443066374773 0.0646752376508 0.0680246382237 0.0621370759065 0.0478849585017 0.0214355468841 0.0687094353901 0.0384979333887 0.0389190825118 0.0687094353901 0.0480894783324 0.0504544201599 0.0366660205236 0.0908834253131 0.0410486802894 0.0843383154277 0.0744888741312 0.0620377042787 0.0466247584157 0.0490662247741 0.0410809318858 0.0466044522535 0.220241217585 0.22387872958 0.231567441105 0.244549509651 0.237801597966 0.237271702597 0.229957304486 0.214803305719 0.2275731622 0.234289966045 0.237659204867 0.227701989162 0.234344570768 0.237727323575 0.210730852647 0.218580436475 0.238765139748 0.218842181584 0.260585713889 0.225852980679 0.24576980875 0.220083510611 0.25691340974 0.234991633089 0.221816502308 0.222561867727 0.236939418607 0.244255467135 0.237073335368 0.205416544089 0.227870869354 0.221241762596 0.220094090971 0.260317043933 0.241447551617 0.226019474356 0.228752673734 0.247333244315 0.221529692284 0.236780633698 0.24056209021 0.232170242771 0.226474325634 0.217767662464 0.233885787279 0.219595234935 0.226160651319 0.223600212873 0.203287025744 0.22672247966 0.280139937217 0.271046573965 0.268296536378 0.26646171863 0.275059767728 0.275799812567 0.270911764394 0.269815722172 0.27914751079 0.264301608642 0.250949666543 0.26825814336 0.263926860434 0.279625941989 0.2816892989 0.264092216423 0.259287884013 0.257990452056 0.295945646215 0.273550874886 0.265902495939 0.269211685027 0.28055869892 0.258431707188 0.260338655828 0.256388822593 0.254096852299 0.25120005211 0.275959599762 0.25362897924 0.27069009133 0.246633770083 0.278453866291 0.251048870754 0.268244717954 0.271056483898 0.268212813274 0.257487053623 0.250194192056 0.258191856723 0.27145388403 0.257986657626 0.271046573965 0.2704506544 0.270310564507 0.264635332559 0.270115829289 0.258629632749 0.263204545545 0.257890609764 0.0600044713459 0.054351041098 0.0187381084361 0.0598557442646 0.0614469307754 0.0531453686192 0.0525559397425 0.0279315026787 0.094761292833 0.0773971393828 0.0814189949505 0.0655620569523 0.0700255275487 0.0814189949505 0.0520201647503 0.0579117136152 0.0488956649362 0.0419109171187 0.0567137285928 0.0208614229037 0.0306610868801 0.0327090237565 0.063272034339 0.0543984191577 0.0634480421324 0.0583685669148 0.139330779418 0.142986837848 0.150850053523 0.163810831232 0.156868051014 0.157669598862 0.149679456655 0.133871337528 0.147188409072 0.153968295801 0.157417010427 0.14689076955 0.155379198936 0.157713790383 0.129254210759 0.137253284329 0.159227064857 0.139693977567 0.180206197156 0.145463442392 0.166351059616 0.138682374547 0.176816693259 0.155870230339 0.140840856643 0.141328264666 0.156536274226 0.163539791349 0.156545980147 0.124345584519 0.147307265103 0.141019689746 0.139034333305 0.180682036747 0.1624502749 0.146314826392 0.147811298228 0.167221256708 0.141400345074 0.156004354912 0.161263479124 0.152006654871 0.145684418167 0.136675034398 0.153561404536 0.139874017863 0.145889334783 0.142806737922 0.121109447078 0.146069682444 0.201853472765 0.191504661606 0.188213817168 0.18712354961 0.1956147304 0.196211110416 0.19205227926 0.19059963575 0.199675257584 0.184878502918 0.170804202645 0.188147863911 0.18370042204 0.200019806255 0.20290821197 0.184684396544 0.179556147674 0.178663646288 0.216648538359 0.194032671841 0.185998827234 0.190015746161 0.201299319844 0.177907547001 0.180731098286 0.176760615884 0.17358596254 0.171156072474 0.196260390732 0.174185108777 0.190914661822 0.166819613367 0.198798087344 0.171315193398 0.190200635461 0.190703604042 0.189694426068 0.178004531696 0.170196606131 0.177783458136 0.19179082566 0.177644952 0.191504661606 0.190881968726 0.191068709685 0.184514101166 0.189756786146 0.178407147108 0.184631515769 0.178548671216 0.0324892056253 0.0484887435869 0.0393579503362 0.0472627188893 0.0192847169709 0.0232472318507 0.0583393494412 0.0585791036352 0.0611786752117 0.0424145094995 0.0604358052165 0.0620651155443 0.0424145094995 0.037432002363 0.036885144463 0.057932237922 0.0663347563067 0.0402054510934 0.0745837939532 0.0379481013657 0.0474009418109 0.0343119409392 0.0339409730754 0.0428079642087 0.0427340086613 0.16139435599 0.167055199688 0.172679145019 0.186588672878 0.18018023169 0.176484226078 0.173177363378 0.15635152751 0.167324305619 0.178559723881 0.177731707828 0.172313382954 0.172981201837 0.177656055027 0.157022451257 0.161367937512 0.181005231952 0.155624650937 0.203264920982 0.165557822324 0.190457367134 0.163325089652 0.197312648791 0.172046353812 0.163261037864 0.165144860989 0.177247951111 0.186978615056 0.179504291425 0.146841839918 0.168174392768 0.160512412099 0.161906209121 0.200546381048 0.18360708151 0.170619997941 0.170849280459 0.188248015891 0.163499893332 0.178863271671 0.178580924982 0.172741578769 0.16748001244 0.159472149167 0.174802823761 0.159227769495 0.167358477359 0.164720514491 0.151099028747 0.168548224145 0.225620984689 0.214383995774 0.210968404368 0.206923044041 0.218629792329 0.216162853062 0.214556733684 0.208383921822 0.219163632298 0.210075568948 0.196412311391 0.211088115641 0.208225582965 0.224211015109 0.229824216763 0.21125046128 0.200361910494 0.199102744226 0.237092122358 0.213257676298 0.21126821314 0.214648561609 0.219950980033 0.202248505777 0.203853239286 0.195906673599 0.198467217831 0.195092454721 0.219319110187 0.191906900165 0.211043854216 0.187166023617 0.222703227226 0.190377176965 0.20432458647 0.215124925944 0.214931156714 0.198560742198 0.194613360236 0.203185148475 0.217932610212 0.206623397839 0.214383995774 0.214797954846 0.217376030313 0.212326968407 0.214327312553 0.203281369316 0.21006441216 0.200554878155 0.0431984510448 0.0262542814372 0.0292765976694 0.0197548242369 0.011556553192 0.0420248516295 0.0609848282508 0.0559281666693 0.0312264925083 0.0398958448421 0.0413044920489 0.0312264925083 0.0264369738429 0.0230439739916 0.0462734733613 0.0414691510708 0.0363662025945 0.071550533242 0.0478849716213 0.0291862789915 0.0369373377392 0.0270714127462 0.0334218260536 0.0262390277171 0.165544038214 0.172891912863 0.17727312869 0.190354892388 0.183958646909 0.183879480011 0.180336742003 0.161635841791 0.171548979047 0.185413091762 0.180663093483 0.178298498301 0.174219977581 0.184181187608 0.161990271375 0.165191063063 0.189309277337 0.161423020955 0.205054842396 0.170020243784 0.198514733988 0.166940816324 0.201451973118 0.178556962169 0.167238778058 0.168913749918 0.180647428918 0.191850429195 0.185573186785 0.149626920851 0.172104358108 0.164216849771 0.166272040954 0.207167511585 0.192763981398 0.178906141081 0.175593499508 0.189955336349 0.171151190119 0.183759195847 0.185737635433 0.179470325207 0.171692649892 0.163416602952 0.18110112813 0.167100843514 0.174311352225 0.169649991905 0.153736698586 0.174561747041 0.233945473753 0.221154951746 0.216216020369 0.214168470951 0.225368727897 0.22143399553 0.222723035108 0.213934293134 0.223870685298 0.217024022208 0.202620827758 0.216260896263 0.213476245827 0.230060267172 0.236168299839 0.217779153489 0.207119858677 0.206977473585 0.241093686538 0.217416199365 0.217140656671 0.221883614074 0.224541883596 0.206836488872 0.211062122527 0.202310625247 0.203579796415 0.201763166599 0.225319290313 0.197343747333 0.215321920645 0.194216980733 0.228558415828 0.196533366942 0.211711953148 0.218804815465 0.22300715182 0.206091661798 0.201387938181 0.208241563837 0.223688965104 0.210605474313 0.221154951746 0.221416959944 0.223922313478 0.216868041009 0.218202757079 0.208934179216 0.218220121204 0.208484033719 0.0428988991781 0.0449811252912 0.038369173012 0.0392012066073 0.0184411809504 0.0770158611592 0.0591685049971 0.0671690041442 0.0499388239897 0.0544215157144 0.0671690041442 0.0346140690794 0.0413101969584 0.0321994698404 0.0440967531043 0.0383047062906 0.0298070621094 0.0211708137004 0.0201129458309 0.0453565917011 0.0368886973605 0.0457257341 0.0417220412167 0.154888546678 0.158813196403 0.166441835812 0.179672088583 0.172784191158 0.17260621351 0.165322327284 0.149403283235 0.162445964052 0.169819706795 0.172790429714 0.162919256631 0.17010598628 0.17291506116 0.145591206314 0.153172124666 0.174534430185 0.15398983773 0.196191934512 0.160693736573 0.182015889553 0.154710886954 0.192325902157 0.170351903358 0.156482289316 0.157229639215 0.171983255038 0.179460677481 0.172268582678 0.139849276668 0.162711676043 0.156097286205 0.154728919391 0.195984213978 0.177559464338 0.161865850494 0.163584898864 0.182768842876 0.156718657607 0.171791912863 0.175973376944 0.167287390852 0.161244255475 0.152349968293 0.168972557751 0.154707872737 0.161224201041 0.158337859598 0.137882544324 0.161653779265 0.217498297387 0.207268525118 0.204089016051 0.202387117484 0.211405750921 0.211656794766 0.207586435206 0.20562940887 0.215067539532 0.200874708618 0.186922162094 0.204055283767 0.199813802793 0.216054855672 0.219141272905 0.20087129472 0.194993585948 0.193928687775 0.232251037143 0.209370889696 0.202145172225 0.205917531589 0.216546254935 0.194031863501 0.196450064794 0.191939021682 0.189735506736 0.187016932169 0.212133736422 0.189132050882 0.20640648386 0.182100826622 0.214796842045 0.186466235268 0.20445164291 0.206912827034 0.205504201388 0.193322781156 0.186101115818 0.194015369065 0.208047565025 0.194373832921 0.207268525118 0.20679029341 0.207231461284 0.201073842632 0.205977385627 0.194517602543 0.200437951551 0.194023674059 0.00847168263945 0.0208969725179 0.0218078109788 0.0404437599311 0.0404194345362 0.0297098891496 0.0297074253675 0.0216763215811 0.0230614305273 0.0297074253675 0.00860159575866 0.00340785264521 0.0287758992091 0.0571909561512 0.0141236699669 0.0709946391549 0.0479055513747 0.0306293087394 0.0170492128659 0.00888265836541 0.00729150357409 0.00480661141663 0.185289458233 0.191085055337 0.196910034804 0.210145347321 0.203571296435 0.202882056675 0.197912476038 0.180625340213 0.191835734795 0.202787038295 0.201526915714 0.195916323017 0.19637797116 0.203353873438 0.179306027922 0.184472082084 0.206754233077 0.181958697279 0.225649748274 0.19019500565 0.21522963857 0.186167360837 0.221735787446 0.198765098442 0.186973637291 0.18833349586 0.201196357535 0.21085114286 0.204041973491 0.169797982896 0.192333522046 0.184882922721 0.185665053896 0.226331622925 0.209833971543 0.195365654989 0.194769866304 0.211153682947 0.188870228152 0.202929999244 0.20531727443 0.198262875463 0.19151438955 0.183035158868 0.19999216658 0.185562442931 0.19270971507 0.189054601453 0.171539131405 0.193197031986 0.250465285504 0.239173402368 0.23520366736 0.232978158323 0.24334022521 0.241285239552 0.239942028126 0.234265108703 0.244131225098 0.234017030201 0.220001112132 0.235226825533 0.231841004595 0.248118070359 0.252690451382 0.234464488853 0.225903274535 0.225189555796 0.261354129729 0.238022768459 0.234821661628 0.238891339667 0.245085625014 0.225666229038 0.228735290931 0.22181584168 0.221922833386 0.219499858076 0.243732621444 0.217749348385 0.235627115362 0.212972717548 0.246730042299 0.216195919385 0.232029501648 0.238052252824 0.239120375862 0.224484292562 0.218871170879 0.226408868705 0.241049615623 0.227943328268 0.239173402368 0.239135618661 0.240673256099 0.234329166611 0.237299131316 0.226939754937 0.234208016817 0.226098822397 0.028402190164 0.0277439229346 0.038946334352 0.0434213038922 0.0291676419928 0.0326159908833 0.0134911389606 0.0149220924049 0.0326159908833 0.0134816006656 0.0104081517294 0.0265932070523 0.0554420028459 0.0189257472352 0.0720390188254 0.0531694571518 0.0303305078503 0.0242591305562 0.0161087615284 0.011068875208 0.00482735633945 0.188743108882 0.194722342773 0.200407653053 0.213430694909 0.206860229667 0.206917746824 0.201757002065 0.18426566592 0.195342886433 0.206526515083 0.204777293747 0.199508643938 0.199425600774 0.207211939812 0.182702196026 0.187804249003 0.210815779569 0.185880854144 0.228533589019 0.193748347964 0.21913688541 0.189440254064 0.225129338462 0.202750726696 0.19038113591 0.191653574921 0.204515978518 0.214295374936 0.207718295645 0.173066791358 0.195766348142 0.188344856347 0.189125824359 0.230149564934 0.214039936134 0.199354571186 0.198257058594 0.214135463178 0.192868986061 0.206423136152 0.209356843732 0.20214026995 0.194966833942 0.186438002469 0.20377859508 0.189699928978 0.196612341236 0.192629244536 0.174503529883 0.196914127595 0.254336052592 0.242870282486 0.238667846113 0.23688365824 0.247015930548 0.244839615824 0.243870689439 0.237954961473 0.247598002179 0.237655720218 0.223546452001 0.238671394435 0.23524462783 0.251589019272 0.256100611398 0.237973407633 0.229710932979 0.229189966161 0.264623863258 0.241418386796 0.238285878732 0.24258651618 0.248557401899 0.228985563027 0.232518055884 0.22563381547 0.2253177885 0.223189662674 0.247286475663 0.221462369267 0.239019854286 0.21687609732 0.250217711381 0.219989961903 0.23614243802 0.241179806044 0.242913875985 0.228427928816 0.222559090866 0.229759973658 0.244438457877 0.230953863516 0.242870282486 0.24276526561 0.244179265793 0.237465205634 0.24045622955 0.230407994296 0.238017253402 0.230045288889 0.0082487413397 0.0434871339043 0.050183840328 0.0462946366306 0.0331671559449 0.0413860283481 0.0432754400997 0.0331671559449 0.018728526127 0.0181135727037 0.0407852007406 0.0552412031248 0.0241124765906 0.0672915663182 0.036051090003 0.0318240646756 0.0214815502931 0.0159437959725 0.0254901889174 0.0237539942631 0.169264556488 0.175091115152 0.180818741393 0.194404360875 0.187867354301 0.185963216048 0.181699481724 0.164435072081 0.175589139186 0.186821392192 0.185627969522 0.180155862933 0.18064011609 0.186712516664 0.164002900607 0.168780956251 0.190185205445 0.164923288811 0.210475012613 0.173888729012 0.199146471591 0.170598213889 0.205685349652 0.18167215365 0.171034804287 0.172628140609 0.185232711805 0.19500403819 0.187902476327 0.154050585176 0.176234935944 0.168650273349 0.169706859713 0.209769138775 0.193110247226 0.179199013537 0.178806517751 0.195681872133 0.172338947581 0.186953230165 0.188260629529 0.181677967227 0.175468629894 0.167135725316 0.183547713996 0.168593151982 0.176177479228 0.172880341359 0.156935998004 0.176943539051 0.234533528357 0.223126396017 0.219327759561 0.216348929156 0.227347260416 0.225044163552 0.22369577874 0.21767535265 0.227960059154 0.218355967949 0.204394726122 0.219392188471 0.216234012192 0.232478694207 0.237601395838 0.219130755018 0.209451421522 0.208536786671 0.245551542374 0.221905162641 0.219288471778 0.22312655653 0.228847315313 0.210092965448 0.212618708514 0.205172062073 0.20633435877 0.203530506813 0.227844403478 0.201098042061 0.219576265526 0.196351165226 0.231028528894 0.199557870197 0.214705957114 0.222733230705 0.223437599857 0.207886214359 0.202974139337 0.210949037245 0.225748458168 0.213347187038 0.223126396017 0.223291835541 0.22533034675 0.219465519892 0.221962474599 0.211307137623 0.21852957733 0.209700938041 0.0419192621384 0.0545713872547 0.0501857282151 0.0312681130066 0.0402402021553 0.0420008929211 0.0312681130066 0.0205720172252 0.0184919891428 0.0424913715031 0.0489285308529 0.0286939286865 0.0683097144827 0.0399734095489 0.0293256914093 0.0276858239832 0.0194684720042 0.0280123772406 0.0234918354003 0.166859723597 0.173331371512 0.178503598003 0.191909917223 0.185423378094 0.184241312774 0.180294315558 0.162400014304 0.173055799755 0.185412361634 0.18273757472 0.178554599617 0.177148633502 0.184812731656 0.162323255063 0.166439616176 0.188986532191 0.162572794611 0.207449709654 0.171422042516 0.198077549025 0.168235674576 0.203119984389 0.179508471538 0.16860424661 0.170241216483 0.182496759111 0.192879913246 0.186103766816 0.151333877107 0.173669495408 0.165942821486 0.167423536544 0.20787297933 0.192134128169 0.178241744028 0.176630454655 0.192503529595 0.170982423968 0.184797056786 0.186354645979 0.179907483835 0.173050611212 0.164731478826 0.181684378357 0.167089130276 0.174542724285 0.170681059367 0.154769008136 0.175102602238 0.233527638993 0.221524217045 0.217249882254 0.214634557666 0.225748190551 0.222754126699 0.222507410575 0.215313006261 0.225475910208 0.217028556203 0.202867049651 0.217307455338 0.214308520933 0.230711314018 0.236268919515 0.217806003587 0.207670960165 0.207072717123 0.242941912447 0.219250459655 0.217623775648 0.221838573376 0.226272530404 0.207953270239 0.211176611808 0.20315950921 0.204399143496 0.201993427277 0.226020220858 0.198708591851 0.217018221505 0.194631582156 0.229236199557 0.197470332905 0.212630809879 0.22033552246 0.22249437564 0.206324343096 0.201514537553 0.209042945777 0.224134795171 0.211456208554 0.221524217045 0.221736417649 0.223988271389 0.217633390228 0.219633609699 0.209536083539 0.217632171671 0.20838956304 0.0775399671204 0.0564468400456 0.0653641254742 0.0395849667657 0.0441943006701 0.0653641254742 0.03373111328 0.0393588608039 0.0260318537498 0.035188052496 0.0394930245033 0.0375459624937 0.0389958606199 0.0129896263362 0.048815943545 0.0379517413039 0.0436570210079 0.0373605585088 0.163502150984 0.168337389523 0.175155703097 0.187828039408 0.181028588214 0.182647655516 0.175454197959 0.158708602469 0.170954310136 0.179762949884 0.180496225683 0.172501221065 0.176828601599 0.182533215894 0.154901122018 0.161684635697 0.185118234991 0.163277975005 0.203127118484 0.169348081929 0.192443927773 0.163103682661 0.200509349698 0.179853786658 0.164993784705 0.165655282459 0.179962811264 0.188228038198 0.18173609183 0.147930089008 0.171080786567 0.164375611634 0.163483874158 0.205438086531 0.18853460221 0.172643498492 0.17244334411 0.189729944562 0.167174105351 0.180637454384 0.185804185303 0.177096116234 0.169809585441 0.16090449309 0.178551065139 0.165213876 0.171240797871 0.16732581913 0.146067131815 0.17119760345 0.227732558213 0.216775565291 0.212818856201 0.212113111804 0.220864451794 0.220275362854 0.217805693503 0.214378859193 0.223348154292 0.21056133718 0.196361313338 0.212749259626 0.208612136858 0.225027947273 0.228363013794 0.210350767964 0.204552905568 0.204069917831 0.240058060786 0.217392662406 0.211260278871 0.215701291359 0.224730833936 0.202526361799 0.206282759299 0.201292044309 0.198558189974 0.196671901675 0.221200953228 0.197951565037 0.214539723027 0.191917757906 0.223779418483 0.195733699704 0.214045901526 0.214810423689 0.215727246675 0.203293848315 0.195827563807 0.20277537878 0.217057373264 0.202583470922 0.216775565291 0.216238379997 0.216660429864 0.209514540125 0.213990052328 0.203581443905 0.210749726957 0.20422943306 0.0299803388219 0.040141041955 0.0494042382248 0.0475047073328 0.040141041955 0.0460070623429 0.0427394298505 0.0575631845334 0.0966299998606 0.0399614977189 0.101837465377 0.0750240618009 0.0697188576907 0.0332240827502 0.042809511279 0.0352142478257 0.0438103448171 0.215592317841 0.220449330264 0.226776190885 0.240218246846 0.233773884944 0.231038348034 0.2263684672 0.210465175429 0.221881119192 0.231308080404 0.231995396207 0.22508238649 0.227350588366 0.232024663305 0.209334152567 0.215020396004 0.234337406165 0.211132081266 0.256379513335 0.220156177626 0.242726282533 0.216799299323 0.251315628789 0.227298889535 0.217343977664 0.218830240402 0.231491464759 0.240364579333 0.233021642066 0.20102218505 0.222551706707 0.215242680103 0.215887525017 0.254517907032 0.236803444285 0.223122921939 0.224639449766 0.242029857582 0.217221787473 0.232566133597 0.233478733428 0.226945320336 0.221662735537 0.213507733767 0.228892766884 0.213808892567 0.221389781107 0.218899946715 0.202924474402 0.222409930936 0.277044937084 0.267058523642 0.264053120566 0.260683081125 0.271161003688 0.269928478944 0.266921380471 0.262757571495 0.272983826376 0.261803183737 0.248535164351 0.264118904646 0.260747941814 0.276361888176 0.280348586054 0.262426412526 0.254046125774 0.252677731845 0.290308221249 0.267228122274 0.26327783075 0.266417210913 0.273921992864 0.255063180539 0.256547903477 0.250174111671 0.251094888905 0.247813627121 0.2719924919 0.246585755223 0.264876118769 0.241182097008 0.275004799417 0.244784301617 0.259319666846 0.267703173929 0.266005774781 0.252196034878 0.247119094967 0.255516011217 0.269407340011 0.257485027934 0.267058523642 0.267089999571 0.268509786469 0.263477813268 0.266862086523 0.25569939087 0.261126117571 0.253527997613 0.0490986378456 0.0295882981502 0.0295703235206 0.0490986378456 0.0321772405698 0.0329624694956 0.0320791928311 0.0819581869701 0.0243777845713 0.0815880274595 0.0630031242432 0.0521832400773 0.0270041961787 0.0316626367995 0.0225970983534 0.0306135777155 0.209138400452 0.213486068388 0.2205444529 0.233810061497 0.227135531522 0.225853564299 0.21966357841 0.203852341272 0.216088869802 0.224306040557 0.226217923772 0.217746213648 0.22224285579 0.226486749722 0.201086071725 0.207931744175 0.228270944293 0.206490835508 0.249940445551 0.214362660634 0.235990805565 0.209564571075 0.245741550277 0.222850058752 0.210799114332 0.211874421056 0.225608964554 0.23378761328 0.226547651045 0.194192088088 0.216536885951 0.209533041634 0.209201443093 0.249253656365 0.230961033564 0.21611849601 0.218017866257 0.236081990375 0.21084689547 0.226091432124 0.228781524913 0.221104911259 0.215367366824 0.206800674523 0.222911320613 0.208230596605 0.21525709201 0.2125575014 0.193883560936 0.215963986139 0.270701972881 0.26093677072 0.257916700448 0.255512820108 0.265026258573 0.264740784654 0.260931231555 0.258198696768 0.267948592812 0.254868213876 0.241356571396 0.257920982238 0.254009770883 0.269860597717 0.272941762013 0.255029971614 0.248480879151 0.247232962401 0.285073136127 0.262202525959 0.256323297606 0.259707446043 0.269155247223 0.248322830219 0.250262594392 0.245086205405 0.244160084795 0.241180503071 0.265837705385 0.241871800867 0.259549733542 0.235634358004 0.268589453275 0.239657575868 0.255932774798 0.261005427367 0.2590787222 0.246704864465 0.240323606031 0.248446059436 0.262200385961 0.249216212931 0.26093677072 0.260623330072 0.261243034875 0.255650557301 0.260116706756 0.248814449864 0.254094104786 0.247584466928 0.0426893927085 0.0408370899258 0.0 0.0368318621027 0.029200211213 0.0578784327643 0.069522041979 0.0411420259607 0.0955605905857 0.0684916485028 0.0536985636371 0.0361283833003 0.0349236407736 0.0326544016244 0.0320790517512 0.190734279342 0.198011093099 0.202165335147 0.215193803756 0.208989236133 0.207943677959 0.205067684162 0.186855165408 0.196324830352 0.210203923195 0.205342231011 0.203427359944 0.198526873832 0.208498767129 0.187766259392 0.1906844311 0.213518747065 0.185598548292 0.229746939288 0.194805777978 0.222821572969 0.192481412892 0.225723793976 0.202375384198 0.192457483521 0.194300696695 0.205376522136 0.216660688755 0.21030774241 0.175307222553 0.197000980201 0.189066511629 0.191539232379 0.231058906578 0.21669613367 0.203523564636 0.200666530244 0.214595210264 0.195827171333 0.208641958794 0.209561099462 0.203960485003 0.196717491572 0.188766309975 0.205678014795 0.191492051166 0.198961164508 0.194672996958 0.180152450124 0.19944864987 0.257583228235 0.245178524187 0.240481186058 0.23786630337 0.249341975217 0.245210894146 0.246468005973 0.237456371003 0.247563146561 0.241300303041 0.22729752986 0.240555698528 0.237993038095 0.254193700204 0.26033321069 0.24220764546 0.231128442611 0.230799434891 0.264694157473 0.241194058993 0.241588310222 0.245985985156 0.248083056968 0.231516408669 0.235215479132 0.226198260689 0.228320459149 0.22623565919 0.249391170367 0.221152204365 0.239284874476 0.218351963925 0.252686589685 0.220530747351 0.234477098822 0.243363395844 0.246969168578 0.229990071021 0.225895881072 0.232959826282 0.248113114083 0.23570223574 0.245178524187 0.245562733947 0.248226439579 0.241702239505 0.242775171886 0.233515238499 0.242256602421 0.232453320509 0.00485178735022 0.0426893927085 0.0245520805084 0.0237321483943 0.0251494297711 0.057422445578 0.0278324002426 0.0740340192529 0.0616449531864 0.0345266403523 0.0352178925007 0.0280808122885 0.0215364121522 0.0177797202497 0.195939824645 0.201850357058 0.207610278022 0.22033675889 0.213750209485 0.214735564684 0.209038553623 0.191585516698 0.202707820911 0.213610139259 0.211883129405 0.206450810174 0.206559465565 0.214810867748 0.189369070647 0.194741318593 0.218356798216 0.193913039155 0.235021949805 0.201158850164 0.226304640977 0.196279111135 0.23226696484 0.210758787397 0.197506357802 0.198589557713 0.211650666116 0.221261000242 0.214919567324 0.180148757389 0.203013849771 0.195747568982 0.196259855385 0.237643665501 0.221708411792 0.206639148011 0.205357745264 0.220920753341 0.200419916968 0.213509698507 0.217293606067 0.209702604063 0.202159105945 0.193545439121 0.211227865592 0.19759997516 0.20414742205 0.199914048013 0.180698578828 0.204233409175 0.261355583351 0.249944219156 0.245612323364 0.244419283687 0.254044690674 0.252080319195 0.251117898529 0.245501499007 0.254799073865 0.244461494615 0.230320341653 0.245583982907 0.241986600586 0.258340089378 0.262471019952 0.244539880639 0.237114058797 0.236754636273 0.271527597514 0.248603215251 0.244975611097 0.24946627049 0.255826675762 0.23571262824 0.239663820665 0.233206292475 0.232061847402 0.230234276049 0.254229520181 0.229085095534 0.246138012907 0.224434087127 0.257016267918 0.227571722833 0.244299258458 0.247702557023 0.249766808341 0.235948695396 0.229554249737 0.236400217176 0.250952182681 0.236961759284 0.249944219156 0.249686907558 0.250743450736 0.243657848264 0.246990711027 0.237179418187 0.244877764453 0.237415960787 0.0408370899258 0.0273499265107 0.025297636378 0.0296282714156 0.0603715739764 0.030303105355 0.0787085816014 0.0655434565706 0.0387042108075 0.0365503327535 0.0303622028421 0.0226096284705 0.0196557817863 0.19925839426 0.205348957591 0.210921560248 0.223617852816 0.217069506306 0.218059817218 0.212575335145 0.194999027921 0.205926088655 0.217171129009 0.215009852018 0.21001079042 0.209452929226 0.218136520475 0.193003747556 0.198137341753 0.221866239829 0.197043564846 0.238162085485 0.204392911714 0.229893095054 0.199683809546 0.235440202166 0.213909407049 0.200827966888 0.201961005661 0.214826820158 0.224639586072 0.218358620882 0.183440825957 0.206248208954 0.198918059014 0.19962810203 0.240932955881 0.225232933618 0.210279009964 0.208738673233 0.223984027141 0.203935797463 0.216876482587 0.220527121607 0.21308659534 0.205456328664 0.196890655988 0.214607347176 0.201007750183 0.207588221909 0.203264328774 0.184313736826 0.207665740899 0.26489357675 0.253366014308 0.248941435732 0.247733075772 0.257464720601 0.255265649267 0.254603866324 0.248608337617 0.25792057227 0.248007634376 0.233863042555 0.24891723403 0.245404277418 0.261753780229 0.266030956859 0.248122124098 0.240457509587 0.240148573616 0.27462290691 0.251686093628 0.248460344614 0.252996524531 0.258897040073 0.239091218679 0.243138472416 0.236454818573 0.235503469176 0.233728803563 0.257606144443 0.232210377675 0.249277823428 0.227793973728 0.260419107201 0.230810446264 0.247340816609 0.251008018719 0.253372216044 0.239328849004 0.233077723245 0.239855175697 0.254460096493 0.240510971982 0.253366014308 0.253147704183 0.254305992093 0.247178452498 0.250316773817 0.240645130337 0.248503359474 0.240885126472 0.0368318621027 0.029200211213 0.0578784327643 0.069522041979 0.0411420259607 0.0955605905857 0.0684916485028 0.0536985636371 0.0361283833003 0.0349236407736 0.0326544016244 0.0320790517512 0.190734279342 0.198011093099 0.202165335147 0.215193803756 0.208989236133 0.207943677959 0.205067684162 0.186855165408 0.196324830352 0.210203923195 0.205342231011 0.203427359944 0.198526873832 0.208498767129 0.187766259392 0.1906844311 0.213518747065 0.185598548292 0.229746939288 0.194805777978 0.222821572969 0.192481412892 0.225723793976 0.202375384198 0.192457483521 0.194300696695 0.205376522136 0.216660688755 0.21030774241 0.175307222553 0.197000980201 0.189066511629 0.191539232379 0.231058906578 0.21669613367 0.203523564636 0.200666530244 0.214595210264 0.195827171333 0.208641958794 0.209561099462 0.203960485003 0.196717491572 0.188766309975 0.205678014795 0.191492051166 0.198961164508 0.194672996958 0.180152450124 0.19944864987 0.257583228235 0.245178524187 0.240481186058 0.23786630337 0.249341975217 0.245210894146 0.246468005973 0.237456371003 0.247563146561 0.241300303041 0.22729752986 0.240555698528 0.237993038095 0.254193700204 0.26033321069 0.24220764546 0.231128442611 0.230799434891 0.264694157473 0.241194058993 0.241588310222 0.245985985156 0.248083056968 0.231516408669 0.235215479132 0.226198260689 0.228320459149 0.22623565919 0.249391170367 0.221152204365 0.239284874476 0.218351963925 0.252686589685 0.220530747351 0.234477098822 0.243363395844 0.246969168578 0.229990071021 0.225895881072 0.232959826282 0.248113114083 0.23570223574 0.245178524187 0.245562733947 0.248226439579 0.241702239505 0.242775171886 0.233515238499 0.242256602421 0.232453320509 0.00792313459309 0.0236297776546 0.0536541076705 0.0108412074571 0.0628560371629 0.0400426717019 0.0242916508179 0.0172043768705 0.0050674059167 0.0120480352419 0.00909567999576 0.179733982337 0.185130641595 0.191359647755 0.204666509458 0.198016972069 0.197255576955 0.19185518721 0.174855164332 0.186481505005 0.196685913747 0.196375987191 0.189833405887 0.19172374648 0.197739787295 0.173088361774 0.178764981726 0.200732295255 0.17675687262 0.220477540317 0.184804954654 0.209049846749 0.180446207623 0.21646451476 0.193507677512 0.181414841832 0.18267689502 0.195938395299 0.20515640915 0.198204629073 0.164323672477 0.186951627799 0.179636188812 0.180004434454 0.220785829324 0.203765417111 0.189073881786 0.189075562692 0.206144383335 0.182845346787 0.197260508087 0.199879524686 0.192526504243 0.186000212457 0.177429453542 0.194272636643 0.179755047797 0.186852872988 0.183420017951 0.165408476828 0.187374971211 0.244379342624 0.233352874625 0.229596132577 0.227371143644 0.2375226222 0.23596534417 0.233967797192 0.229101525181 0.238946455726 0.22794079194 0.213947298319 0.229612039594 0.226054866131 0.242325328031 0.24658946328 0.228320886035 0.220245475488 0.219410638455 0.256223296024 0.232925784221 0.228888220536 0.232841814871 0.240004491346 0.219971839687 0.222802209556 0.216357175156 0.216093165101 0.213536808192 0.238014479196 0.212556057937 0.230415334062 0.207278762186 0.240959781593 0.210762423837 0.226970181506 0.23251461018 0.23290234378 0.218739342276 0.212847200349 0.220551656017 0.235068599786 0.221910374672 0.233352874625 0.233237981586 0.234568034713 0.228343429058 0.231717374059 0.221050886534 0.227947933137 0.220165226053 0.0299322879907 0.05484354778 0.015508827535 0.0698377856312 0.0461226756997 0.0288439268589 0.0179749812614 0.00820193608475 0.0104514607363 0.00601471721254 0.182232775094 0.188144985482 0.193867682363 0.20711590793 0.200550766912 0.199860135361 0.195016228938 0.177611309591 0.188739284934 0.199919451707 0.198412537874 0.193032154463 0.193186123937 0.200329430243 0.176446801251 0.181459762374 0.203862717343 0.178811701467 0.222599641879 0.187102653143 0.212418919228 0.183165138771 0.218668582765 0.195650642874 0.183922319896 0.18531418569 0.198099986213 0.207874048966 0.201087073424 0.166709980365 0.189246782627 0.18175655241 0.182635613511 0.223327464443 0.206968516624 0.19255440527 0.191763016548 0.208041469681 0.185943960269 0.199929552497 0.20225187193 0.195263692383 0.188456709089 0.17999008547 0.196992188976 0.182563902533 0.189736470349 0.186019084029 0.168664903455 0.190216873808 0.247702840069 0.236282170601 0.232244216334 0.230002139075 0.240457584895 0.238254033101 0.237105182737 0.231183514354 0.241076068443 0.231215767875 0.217161214732 0.232270602033 0.228935795245 0.245246208475 0.249963377759 0.231700745278 0.222930449716 0.222251471523 0.258324331925 0.234942120984 0.231973156153 0.236088516952 0.242009296663 0.222723564262 0.225860019318 0.218781249758 0.219012595092 0.216618271437 0.240821050718 0.214649402949 0.232567858569 0.209986385677 0.243846113816 0.213146433073 0.228924161819 0.235098611969 0.236391467186 0.22153411273 0.216011138881 0.223520339681 0.238239770023 0.225155295827 0.236282170601 0.236275025927 0.237908750738 0.231525069379 0.234355153325 0.224056763193 0.231485450395 0.223215654925 0.0572284762647 0.0227453897084 0.0528238726337 0.0444991634471 0.0266973769114 0.0336948312224 0.0272062333147 0.0274688740262 0.0263328670099 0.185716682176 0.189934662812 0.1972487923 0.210230033124 0.203429572326 0.203652674494 0.196491149306 0.180504651022 0.193104816748 0.200892549998 0.203064104164 0.193989394378 0.199601579765 0.203900303764 0.17670118478 0.184039790634 0.205684310622 0.1846555251 0.226113704537 0.191415178407 0.212986837934 0.185538541574 0.222740004307 0.201086740863 0.187280443615 0.188038576609 0.202414184433 0.210238732317 0.203278048935 0.170511460418 0.193354539773 0.186626010428 0.185640639557 0.226777734968 0.208697723096 0.193060716385 0.194490643156 0.212667601723 0.188009393157 0.2026405567 0.206872630148 0.198376957217 0.192017886181 0.18319542151 0.200010008529 0.185964041385 0.192410951726 0.189280207199 0.168712331151 0.192752182621 0.248024768226 0.23796255467 0.234657432476 0.23319215601 0.242043627351 0.242092609424 0.238343194449 0.236048752979 0.245336704526 0.231521041315 0.21770196943 0.234612870361 0.230403022013 0.246515101463 0.249324779094 0.231381623939 0.225835327084 0.224876205525 0.262239370649 0.239554652873 0.232726560614 0.236544998844 0.246724791051 0.22460575232 0.227286958934 0.222708966341 0.220419587826 0.21790450046 0.242699459353 0.219658545965 0.236700307439 0.213086341068 0.245286981729 0.217239309033 0.234909245332 0.237182720463 0.236050820735 0.224251890124 0.21698485009 0.224622112179 0.238475066919 0.224611061526 0.23796255467 0.237436165661 0.237675287343 0.231370754771 0.236291823604 0.225200181658 0.231029643716 0.224953381888 0.0635710838178 0.0592624543316 0.0596058092469 0.0328544820604 0.0698260168465 0.0573261822931 0.0634460229613 0.0541080958794 0.147303482686 0.155161448288 0.159136079545 0.171063643845 0.16463221595 0.168584971583 0.163624194761 0.144235266953 0.153827968777 0.168063795028 0.16179307599 0.160206770568 0.155398151635 0.167887347752 0.142965424509 0.146100735749 0.17375554158 0.146517107633 0.184102282814 0.152518687773 0.182006446517 0.147493939017 0.182975421708 0.163616999091 0.148716120222 0.149770660992 0.161958247648 0.173135111896 0.168022513735 0.130738265008 0.153920373487 0.146537313722 0.147925357539 0.190546691654 0.177990062346 0.162980599048 0.157241520972 0.169863812022 0.155438284157 0.165389918434 0.170707644688 0.163197102596 0.153422018191 0.144858486622 0.164315178145 0.152440808389 0.158128021971 0.151920639439 0.132537826475 0.157359920068 0.217237278816 0.203578319465 0.19760287759 0.197919551969 0.207681519923 0.203644803794 0.206313583309 0.1971606419 0.205828867849 0.199064489236 0.184178187026 0.197538822775 0.194404518771 0.211337912042 0.217143803133 0.199166671372 0.190313841849 0.191119829867 0.222105237734 0.199176357415 0.198307304 0.204224647581 0.206706114847 0.187412194782 0.19389709622 0.185837912363 0.184448440446 0.184112718669 0.207064291919 0.180760878547 0.196874753064 0.177987251583 0.20993106085 0.180009687643 0.197504007472 0.198552660709 0.205899002329 0.189953313758 0.183706289376 0.188863124638 0.204480568311 0.189510910124 0.203578319465 0.203449868624 0.205307715981 0.196398052452 0.198053210544 0.190139115088 0.201200460168 0.192215464603 0.0646648846724 0.0408252785942 0.0324283536149 0.0110096321254 0.0094227049932 0.0109851717283 0.0161323040352 0.185995265043 0.190666336997 0.197500031875 0.21094278484 0.204249573992 0.202798103731 0.196994111724 0.180742040387 0.192881751338 0.201790619427 0.203110749465 0.195155158145 0.19908437034 0.203454592708 0.178505994536 0.184932353957 0.205646229373 0.183039730424 0.227253690432 0.191142107437 0.213742423108 0.186621634482 0.222820224457 0.199555206103 0.187692696694 0.188884746385 0.202513734055 0.21103182776 0.203761324581 0.170936996707 0.193374027451 0.18623653615 0.18612791719 0.226436319176 0.208431967216 0.193707164322 0.195058461584 0.2131353075 0.187987297837 0.203202157658 0.20562939159 0.19810682266 0.192261721083 0.183685994256 0.199939039445 0.185109577754 0.192293556305 0.189460942551 0.171326016098 0.193018202765 0.248893705524 0.238594153414 0.235368547023 0.232809197602 0.242745772985 0.241996085058 0.238752248121 0.235253956997 0.245180784501 0.232837883436 0.219103668122 0.235388183401 0.231636120508 0.247694764978 0.251385734184 0.233178069062 0.225757404345 0.224585782777 0.262534762143 0.239353867417 0.234157942476 0.23769286224 0.246342255252 0.225805082888 0.227891511242 0.222153883963 0.221706146684 0.218742321816 0.243483255972 0.218775046696 0.236736505477 0.212768083313 0.246367071263 0.216653745648 0.232866084107 0.238586937872 0.237342638049 0.224021718097 0.217958679267 0.226108360277 0.24024082191 0.227355271774 0.238594153414 0.238405022146 0.239431466759 0.233734880392 0.237715653864 0.226470518154 0.232346541994 0.225139690924 0.0393671458325 0.0464638919444 0.0721210062546 0.0652058473437 0.0727980489441 0.069475743339 0.146377403101 0.147841270546 0.157364583964 0.169967544666 0.162961576643 0.163688135507 0.153695971045 0.140223917866 0.154815274304 0.157460458795 0.165356253736 0.150768971529 0.165320051187 0.163744020488 0.133177827162 0.143578449734 0.163063976092 0.148488500757 0.186880468442 0.153029883361 0.168852310214 0.144817839236 0.183493098196 0.16367577587 0.147767272784 0.147687188567 0.164075138054 0.168705452589 0.161392920433 0.132534765042 0.154766041608 0.149414499828 0.145576557217 0.186084208163 0.165901662347 0.149128920765 0.153742006284 0.175201329509 0.146090630422 0.161672202019 0.168031911823 0.15768748388 0.152605178523 0.14358929792 0.159222856143 0.14586039418 0.151244472229 0.149339889326 0.125727972716 0.151529925609 0.203450036676 0.194986217471 0.192843589773 0.192004248179 0.198946853705 0.202034655336 0.194735870429 0.197390062155 0.205967080811 0.187074482741 0.173679535364 0.192730113791 0.187498820793 0.203203985607 0.204052975425 0.186370806955 0.184428712838 0.182999565721 0.222535792393 0.200873648 0.188899014225 0.192203777807 0.208005111614 0.182384645276 0.184037705225 0.182740791406 0.177549631149 0.174643342307 0.20005255491 0.181451046073 0.197344936488 0.172060390986 0.202165775813 0.177622921879 0.197550181919 0.195373313831 0.190875275066 0.18253037262 0.173366080571 0.181382900577 0.194116360457 0.17989694523 0.194986217471 0.19390780748 0.192735187036 0.186889353803 0.194252690611 0.181881177771 0.185754237755 0.182012475847 0.0362542669235 0.0433946419111 0.0395938166279 0.0499100911085 0.0488639489089 0.15152574063 0.154669324023 0.162831337388 0.176665753207 0.169806006203 0.167122046596 0.160378494232 0.145396880889 0.158882941041 0.165181343889 0.170013544811 0.158841213295 0.168049497633 0.168033584387 0.142281111905 0.150191536414 0.168801703096 0.149137142763 0.194382185315 0.156984666205 0.176687245859 0.151908690894 0.188914920448 0.165149458367 0.153257832095 0.154263633953 0.168972071115 0.175883337588 0.16793063653 0.137286345822 0.159386690667 0.152763325671 0.151315442368 0.191108253021 0.171290308569 0.156330262179 0.159994057675 0.180780718652 0.151317533557 0.168120728135 0.170508979962 0.162341150711 0.157837504705 0.149168793021 0.164327797527 0.148926027403 0.156192253462 0.154516403486 0.136169004568 0.157264478091 0.212122717934 0.202635989676 0.200296956824 0.197168424809 0.206818081536 0.207593997357 0.202129844535 0.201194661862 0.211287068634 0.196367072918 0.182828097116 0.200324517328 0.196191886272 0.212106652571 0.215234691898 0.196754062665 0.19012565359 0.188386972878 0.22899541165 0.20586463613 0.198258080181 0.201204812212 0.21275581912 0.190751178898 0.191559171703 0.187109767024 0.186199376174 0.182482910799 0.207969239625 0.184720534783 0.20291190811 0.176982703379 0.210810911009 0.181756418439 0.198660937707 0.204191111601 0.200384835859 0.187985877445 0.181554202617 0.190580156178 0.204342491841 0.191957847677 0.202635989676 0.20235052312 0.203098119616 0.198224746232 0.20315819974 0.190687755597 0.195275148422 0.188602851388 0.0403137962831 0.0283224608052 0.0352856337592 0.0279159520938 0.163417587591 0.169024399252 0.175174902733 0.188097949492 0.181377843525 0.182339093803 0.176249889638 0.158817342465 0.170474967966 0.180845899763 0.180001842158 0.173609983768 0.175496658011 0.182387588854 0.15630806646 0.162058645803 0.185720747493 0.161911269413 0.203372519665 0.168871283524 0.193698104443 0.163602773962 0.200347540332 0.178768462478 0.164992621499 0.165987648079 0.179610648238 0.188805808549 0.182291142535 0.147635227715 0.17074779736 0.163623388142 0.163626611748 0.205461058801 0.189137857415 0.173807850394 0.172761367844 0.189359771077 0.167597338583 0.181003226921 0.18512092453 0.177130623568 0.169726367846 0.160952549622 0.178668367454 0.164953979441 0.171439694143 0.167334380068 0.147661742228 0.171525073941 0.229212799489 0.217687295638 0.213458314816 0.212251579761 0.221837277994 0.220248120289 0.218836902814 0.21380890761 0.22315649106 0.21209021333 0.197773787684 0.213427195478 0.209691510886 0.226221325989 0.230427027381 0.212200169545 0.204828617154 0.204406576244 0.240127225685 0.217034360511 0.212651201199 0.2171572787 0.224326708779 0.203421180278 0.207247009432 0.201076078606 0.199634752126 0.197699005741 0.222082174457 0.197241869749 0.214400679015 0.192020712279 0.224886788727 0.195424460906 0.212817607264 0.215705919361 0.217495203752 0.20360497892 0.196993475509 0.204019508797 0.218720046506 0.204677118987 0.217687295638 0.217405004007 0.218489214457 0.2114130463 0.214943199157 0.204771656731 0.212548494217 0.204988233676 0.0127227257693 0.0140144534262 0.021205315625 0.187358882688 0.192125766059 0.198772205734 0.212374766999 0.205757524042 0.203466313878 0.198269360384 0.182075536022 0.193992765379 0.203217006858 0.204331991647 0.196763084721 0.20014614007 0.2043270841 0.180514052654 0.186571402116 0.206603961592 0.183553088594 0.228871000555 0.192232411854 0.214999691886 0.188338267885 0.22392031363 0.199986970587 0.189109313009 0.19048409561 0.20374267521 0.212452607057 0.205039311477 0.17250608603 0.194596025922 0.187333202847 0.187569910566 0.227244357321 0.209244321292 0.19501056691 0.196469921009 0.214533216851 0.189073691369 0.204563213894 0.206128514596 0.199072106837 0.193573357583 0.185159768848 0.200995780718 0.185854759801 0.193344854477 0.190733738309 0.173803583444 0.194263918799 0.250041858008 0.239752334137 0.236636793113 0.233547933384 0.243918830588 0.242901503454 0.239756635176 0.235879076786 0.246072511959 0.234292093183 0.220682667006 0.236686092505 0.233134556981 0.249085035733 0.25310029637 0.234845006722 0.226672837999 0.225370202913 0.263585873652 0.240269679341 0.235701118126 0.239046163418 0.247138992266 0.227341018945 0.229062028698 0.222899030248 0.223273394137 0.220071420598 0.244719204688 0.219434280561 0.237757183282 0.213627898609 0.247720909818 0.217420020786 0.232895251914 0.240194731922 0.23871780496 0.22484832656 0.219342733041 0.227741527766 0.241902288188 0.229541957119 0.239752334137 0.239709455557 0.241056941465 0.235717844261 0.239326740269 0.227988125157 0.23374803561 0.226117504317 0.0112944223112 0.0116717916683 0.180315550232 0.185624806253 0.191893759643 0.205310880338 0.198677901623 0.19742928403 0.192207723586 0.175346071899 0.186991091141 0.197103740487 0.197010559796 0.19035952375 0.192415460068 0.198031907427 0.173783350974 0.179445795208 0.200920544981 0.176980189616 0.221316628359 0.185291341794 0.209338461592 0.181164395028 0.216995536327 0.193672787851 0.182024521085 0.183353435463 0.196543976916 0.205721030365 0.198641096205 0.165041173069 0.187513275437 0.180170480519 0.180593580969 0.221064954649 0.203852710847 0.189347093282 0.189636739108 0.206917162302 0.183105626465 0.197802407018 0.200023916345 0.192826802002 0.18656768388 0.178054301819 0.194629767109 0.179904508376 0.187157083025 0.183925453374 0.166391248738 0.187799823192 0.244629672801 0.233720966397 0.230103074977 0.227589285523 0.237898238239 0.236372028201 0.234191133105 0.229406521443 0.239389014631 0.228371263352 0.214461216321 0.2301324354 0.226622699222 0.242825477857 0.247136546528 0.228837795311 0.220544275821 0.219592617307 0.256764787312 0.233410014962 0.229423132068 0.233225877209 0.240428033421 0.220595144087 0.223137647662 0.216631996383 0.216685610877 0.213950565713 0.238461242313 0.212870718316 0.230920602382 0.207535413146 0.241449474994 0.211057657029 0.226977435726 0.233226691247 0.233226664174 0.218957536154 0.213267398065 0.221167604245 0.235644719391 0.222751284499 0.233720966397 0.233655964463 0.235074683268 0.229091941731 0.232416283617 0.221592631388 0.228271321964 0.220395124759 0.00983853465038 0.190743576675 0.196127634014 0.202306832097 0.215593264431 0.208988714901 0.208014681254 0.202752493595 0.185879141861 0.197391448173 0.207587390017 0.207246286244 0.200818808941 0.202436920976 0.208560198594 0.184214467342 0.189842910423 0.211501430369 0.187510793393 0.23133568248 0.195719341744 0.219810583637 0.19153274103 0.227260064133 0.204197085901 0.192430421495 0.193730481177 0.206830708645 0.216081015857 0.209114627207 0.175418662775 0.197889059256 0.19054759391 0.191035254803 0.231501988345 0.214455580052 0.199914298524 0.200065006525 0.216984298716 0.193736240961 0.208206242937 0.210580217034 0.203385972256 0.196973524191 0.188474338185 0.205152454389 0.190585220715 0.197746685322 0.194398694242 0.176663593729 0.198324488838 0.254937931723 0.244068220209 0.240384243666 0.238035456407 0.248220627185 0.246646653405 0.244595211757 0.23972473422 0.249602645305 0.238680104062 0.224803483418 0.240405804306 0.236887764418 0.253050369586 0.257246240499 0.239074958955 0.230985078994 0.230097737916 0.266839316033 0.24359819756 0.239685124735 0.243538571704 0.250621888643 0.230851769093 0.233547789712 0.227075078845 0.226983547477 0.224362834405 0.248743336169 0.223247552937 0.241135379781 0.21805286342 0.251689329115 0.22150661959 0.237406179341 0.243353541542 0.243526559835 0.229448331316 0.22367406721 0.231427017129 0.245837459247 0.232818717405 0.244068220209 0.243969807123 0.245289155672 0.239200193755 0.242559723366 0.231895813526 0.238589343178 0.230870674099 0.185074856292 0.190966638679 0.196734232482 0.209858428647 0.203274864625 0.203041999473 0.197926990268 0.180506604609 0.191676192961 0.202741147438 0.201237653931 0.195771907735 0.19601488206 0.203403274574 0.179018659177 0.184172394714 0.206916175569 0.182062920029 0.225161143908 0.190059350101 0.215302655172 0.18583273214 0.22154130677 0.198918819466 0.186732254392 0.188033674574 0.200939126942 0.210648020541 0.203966819203 0.169461460201 0.19212652304 0.184698761261 0.185447917615 0.226382707341 0.210090272929 0.195464472523 0.194576182922 0.210724866996 0.188972223666 0.202749851185 0.205495551665 0.198311837225 0.191308228071 0.1827836447 0.199987032182 0.185758986102 0.192762378199 0.188912535548 0.170985151469 0.193136210612 0.250560354729 0.239150130043 0.235042618318 0.233086785485 0.243308731763 0.241203268173 0.2400598963 0.234273096316 0.244008938502 0.233948328457 0.219858019146 0.235053540533 0.231632132621 0.247968147104 0.252509320758 0.234318201257 0.225941055535 0.225341346975 0.261132458323 0.237859251815 0.23464919225 0.238863315744 0.244976238699 0.225403382703 0.228750181247 0.221868483944 0.221696049716 0.219446034661 0.243630311449 0.217754591911 0.235449762585 0.213055210612 0.246589228494 0.216230229788 0.232311179578 0.237695560547 0.239155145074 0.22460119101 0.218814227997 0.226159982187 0.240839111604 0.227492031494 0.239150130043 0.239069291581 0.240533107829 0.233959974366 0.236956995194 0.226761267667 0.234246750663 0.226212511867 0.0174000566092 0.0121264323023 0.0260599074483 0.0195345881682 0.024716388707 0.0269505563041 0.00951579401108 0.00952789620934 0.0312682326376 0.021380704298 0.0249359987416 0.0321633377276 0.0221499569656 0.0250465767598 0.00649156808823 0.035247677191 0.0178478945632 0.0452164673822 0.00796037757126 0.0457327534983 0.00806434689496 0.0382898633561 0.0225581753549 0.00212523780258 0.00635071079008 0.0188691425113 0.0279463141708 0.0242753243704 0.0170805625395 0.00904309726647 0.0106287996797 0.00382969063087 0.0441552932431 0.0411601284763 0.0356126616505 0.0116846154421 0.0333280322148 0.0231237862627 0.0194233884188 0.0266405905658 0.0193741592831 0.00647009737397 0.00313195595137 0.0192809490983 0.0198825976901 0.0184223649953 0.00589033700008 0.0274923472821 0.0151107135826 0.0780209291989 0.0597893086125 0.0526478480904 0.0519801851129 0.0640907142958 0.0582643284706 0.0646025548306 0.0523589334483 0.0615531482061 0.0598796956679 0.0449628875056 0.0527423072945 0.051324556652 0.0686409960047 0.0805660524071 0.0623345264313 0.0443847427682 0.0466830846559 0.0795542446923 0.0559362746494 0.057180756356 0.0643259703348 0.063211257271 0.0437185245372 0.0513548290636 0.0393714351609 0.0417127661704 0.0422926634719 0.0628873923745 0.0360959787877 0.0527047257983 0.0325588237609 0.0667976247829 0.0335624409497 0.0547114607912 0.0561052885987 0.069799650238 0.0449738444715 0.0432370258673 0.0470356297838 0.065014861143 0.055075271212 0.0597893086125 0.0609892947965 0.0676680770887 0.0593149961508 0.0554983088895 0.0479751568133 0.0662596895747 0.0497728280187 0.01649842894 0.0270940163297 0.0209738779605 0.0204474607028 0.0105739124512 0.0137437284214 0.0226997190651 0.0150100972387 0.0323011347894 0.008153166122 0.0475382748664 0.0187641297777 0.0164404692163 0.0144508320868 0.0210394349685 0.0305556358824 0.0486242638836 0.0214513889049 0.030175982789 0.0140964441541 0.0400575333251 0.0288561044949 0.0169609734513 0.0143755139823 0.0284025548343 0.0224203703593 0.013792641556 0.0304826758057 0.0219984307058 0.027438003111 0.0138498079587 0.0391014082904 0.0268826742795 0.0187520448645 0.0110691342578 0.0424853466078 0.0102534616754 0.0160596134656 0.0266767705353 0.0127998581546 0.0173245890268 0.0173211449901 0.0131739480428 0.0158792885006 0.00835247262611 0.012879803971 0.0267489620569 0.00596710410688 0.0651865992814 0.0501303259948 0.0467631748034 0.0452702235248 0.0544981935174 0.0559804285713 0.0526556031199 0.0527154428326 0.0609295585885 0.0469864956417 0.0318305696362 0.0467870360621 0.0428839020559 0.0596952123639 0.0682904935263 0.0490145651142 0.0373470202066 0.0372051258398 0.0783094346225 0.0573164765228 0.0464381891239 0.0518006344835 0.0637213875725 0.037328539174 0.0398159521041 0.0364375689163 0.0327311081772 0.0300536558581 0.0548465086523 0.039011355091 0.052932116237 0.0253006236285 0.0581288867478 0.0321437027692 0.0554616174667 0.0518535767409 0.0554912699649 0.0361633495108 0.0300500951908 0.0376868875379 0.053920841562 0.0443787428504 0.0501303259948 0.0504194914628 0.0549441033997 0.0487769599128 0.0505784847321 0.0377653392745 0.0513716565226 0.0379306609676 0.0148794236891 0.00906915259144 0.016817766784 0.022666965263 0.0181414830259 0.00943690730089 0.0254552863313 0.0160108606893 0.0217205062473 0.032481574081 0.0125336713193 0.0301048876528 0.0144114156753 0.0283145714635 0.0236499286545 0.0356994826174 0.00980454037789 0.0380382046842 0.0138535372004 0.0270349861178 0.0179310476065 0.0105970849446 0.0106446588122 0.0120133548138 0.0166102052911 0.0152998463146 0.0290596443937 0.00834773888805 0.0173051001714 0.012006228531 0.0322817993752 0.0342847484172 0.0334965405575 0.00578703582339 0.0267498608594 0.0233284219943 0.00836772170811 0.018341518653 0.0127097608473 0.00603575216863 0.0145919151911 0.0109073587446 0.0221533308504 0.0160929276419 0.00858765501382 0.0355326614102 0.0120318414802 0.067539995406 0.0482957753815 0.0406895564252 0.0402187129364 0.0525505335689 0.046337446086 0.0538706159523 0.0410532995186 0.049945680623 0.0498002070389 0.0356573113194 0.0408170339224 0.03998131445 0.0570983300794 0.0703114871106 0.0527515586 0.0326360388464 0.0357703215059 0.068007735392 0.0448145788863 0.0463929144792 0.0539072356938 0.0519007533329 0.0322898342044 0.0406511091494 0.027662402635 0.0308780067072 0.0322628111538 0.0510866561777 0.025649802677 0.0412344607513 0.0218269690426 0.0551778627391 0.0220763570226 0.0446670171533 0.0446820028935 0.060359178521 0.0338187065026 0.0337343667693 0.0362783001067 0.0544202026485 0.046225200341 0.0482957753815 0.049817335882 0.0576169439653 0.0494636606912 0.0440581542748 0.0371733017103 0.0573289834367 0.0394045266195 0.00716257307188 0.0232372547893 0.0296783885761 0.0325204811189 0.0212497773179 0.0292620976856 0.016439517739 0.0284506794787 0.0345599570635 0.018188478274 0.0407426749726 0.0271225123173 0.0318719827355 0.0364884226289 0.021914442716 0.0227786086069 0.0376078412936 0.0256329664506 0.0146652900265 0.0257412263731 0.0241649286356 0.0229439407062 0.0136364254073 0.0100256292567 0.0184950349026 0.0419365600148 0.0198805169881 0.0290470401931 0.0259349477967 0.0239003990661 0.037192775807 0.0407761513521 0.0178664543062 0.0194803036782 0.0346542430628 0.0113663417752 0.0228609184952 0.0221099611853 0.0198250112005 0.0281996969801 0.0190943935979 0.0354944682629 0.027502181016 0.0232700909093 0.0459502516894 0.0236639254111 0.0598327139142 0.0386582188727 0.0283018389706 0.0317793366202 0.0424462733589 0.0338166029949 0.0467225177273 0.0306128740578 0.0370882424143 0.0426365040044 0.0306518342203 0.028353389025 0.0289452185335 0.045605512774 0.0609187137277 0.0456096520871 0.0247062397964 0.0307047013286 0.0541889879817 0.0321986089116 0.0369056583991 0.0461635888574 0.0394191509814 0.0202672234717 0.0339543216254 0.0203331670034 0.0216962768111 0.0275014797571 0.0396207876643 0.019383687668 0.028134515225 0.0203542968498 0.0436399460151 0.0166979961449 0.0388212853573 0.0305366541923 0.0544557347145 0.0282093601187 0.0297076171269 0.0264388860156 0.0445799816631 0.0375526043804 0.0386582188727 0.0404030430489 0.0493940445937 0.0396161416365 0.0302144214958 0.0282464575757 0.0525063270042 0.0345543356833 0.0213910735206 0.0254312508458 0.0257342205184 0.0165221855109 0.0259539784544 0.0158835031429 0.0233831935041 0.0339323139257 0.0162106434865 0.03399674531 0.0200386549433 0.0299171917849 0.0320747556874 0.028046974659 0.0176794481153 0.0368388291758 0.0185008751091 0.0214981879903 0.0241691252685 0.0175651807134 0.0158907875652 0.0122369735355 0.0109776452166 0.015527622801 0.0354957768624 0.014819189185 0.0241388300803 0.019062303667 0.0287269405771 0.0357916006232 0.0364633531028 0.011219279972 0.0225748368915 0.0292557862917 0.00702356235419 0.0224830610185 0.0181511844266 0.0136555064616 0.0214280218685 0.0152776051594 0.0301845131917 0.0223495731118 0.0167956602264 0.0389756608983 0.0178914144765 0.0630604023291 0.0430080788574 0.0341031378994 0.0365519407683 0.0470199755056 0.0406269394348 0.0499352678431 0.0370580183618 0.0441324571638 0.0450148609009 0.0313792244576 0.0341228348643 0.0333031398497 0.0505703458181 0.0642434790604 0.0476293944045 0.0288843329998 0.0334940865056 0.0612862785232 0.0392274534904 0.040346557275 0.0490663667656 0.0464449738085 0.0249899515531 0.0366261362911 0.0249803957153 0.0245501998624 0.0286632518672 0.0448796558538 0.024023128213 0.0352285170514 0.0213779538928 0.0486983458625 0.0204530056806 0.043719713027 0.0366461987398 0.0563678077617 0.0312461294161 0.0303695774583 0.0296679302141 0.0480887950749 0.0392929320337 0.0430080788574 0.0443169978812 0.0521158245642 0.0424602914349 0.0361040078467 0.0312787145737 0.0538034695951 0.0366723303295 0.0189709615579 0.0257111384326 0.0217335533305 0.0223113040739 0.027967478664 0.0234852927562 0.0436322798908 0.00521461133699 0.0364760096592 0.0272343470762 0.018116669378 0.0277674536165 0.043201573857 0.0213285903305 0.0304538340544 0.0273512817022 0.0293661558134 0.0151289313008 0.0243064809516 0.0249356313294 0.024322988602 0.0196946095768 0.0139855052687 0.0405716245072 0.0223909261135 0.0287463352875 0.0239629151594 0.02510185342 0.0224608355139 0.0285849443101 0.0178309380123 0.0374526670612 0.0202528662781 0.0157931802813 0.00761690092841 0.00770880409418 0.0208073209186 0.0270724449013 0.00859765119326 0.0186885305588 0.0137210864523 0.0193875507074 0.0459800217652 0.015147695259 0.0594631949225 0.0420406539118 0.0381002519704 0.0316288068581 0.0464453358384 0.0430647918893 0.0450678160713 0.0372936406921 0.0478953066773 0.0442824164473 0.0325191406563 0.038458833697 0.0379877190085 0.0530105166244 0.0661049064219 0.0485790002934 0.0252530768184 0.0252616659632 0.0666194586026 0.0445179442461 0.0429682351205 0.0475934680999 0.0500384221554 0.032835448251 0.0334890161181 0.0210425012042 0.0304165560005 0.0269992218058 0.0464858418191 0.0236376116141 0.0409389296383 0.0119097107153 0.0510342004912 0.0165862044563 0.0364051705359 0.0459765436849 0.0532158463913 0.0240697227805 0.0285944307415 0.0355069812685 0.0512442268801 0.0481793211849 0.0420406539118 0.0442662890139 0.05312949223 0.0494910921385 0.04499219501 0.0346009573898 0.0502278687979 0.0300299308142 0.0232712606741 0.0301762988443 0.00654363258115 0.0383536762695 0.0073760670349 0.0549696818035 0.0187358469678 0.0230006125585 0.0248620926321 0.0112006081505 0.0374302122761 0.0507791829944 0.0291552453818 0.0203658790931 0.0243768337268 0.0405838171216 0.0318523232399 0.0264398107213 0.0241549255092 0.0342108755533 0.021966370396 0.0115756992435 0.0406700397742 0.029726336077 0.0360763557135 0.0237708872008 0.0347952708329 0.0167090325333 0.0113314779127 0.0183460384347 0.0474972085699 0.0106130759732 0.0188803713912 0.0264255690706 0.0134988723184 0.025504997589 0.027405254367 0.0141844800377 0.0190580694839 0.0107985492476 0.0215712414492 0.0353201768965 0.0121413245456 0.0563908913649 0.043304104353 0.0426898087169 0.0394771848203 0.0476531796683 0.0529352282385 0.044079995111 0.0508430194559 0.0587105683651 0.0390993709526 0.0249779507582 0.042747127932 0.0380731496814 0.053623295371 0.0609715530482 0.0414798961609 0.0320700568798 0.0299307088952 0.0756552859532 0.0564187262812 0.0401315540974 0.0437426630802 0.0619393205223 0.0343990170803 0.0321000148697 0.0335451545545 0.0286757976711 0.0228629245983 0.0490706959168 0.039335399235 0.0517108395757 0.0207931533413 0.0521719534959 0.0306385429933 0.0529657791748 0.0494073245643 0.0465244230409 0.0294935309982 0.022387741137 0.033135656028 0.0474637239198 0.0404408008061 0.043304104353 0.0434045699957 0.0474449484031 0.0438694244062 0.0478136370998 0.032205230585 0.0422362620829 0.0295056722481 0.0179188644218 0.028584000913 0.0304649482776 0.0216593575612 0.0411663680687 0.024518088592 0.0182283990095 0.00873472135302 0.0327024039756 0.0205661418233 0.0530659348987 0.0158790060301 0.0434559310925 0.0108179884547 0.0451149656888 0.0268976993783 0.0108384529361 0.0115766662184 0.0275567255166 0.0316971869351 0.0249562865626 0.0177154908046 0.0178955252093 0.0182906823384 0.00749636648732 0.0477714342488 0.038203551745 0.0295629098692 0.0151014852938 0.0424264199032 0.016651504005 0.0233361298106 0.0296064297332 0.0193940010564 0.0143559792056 0.00822362335298 0.0204472045407 0.0141062231631 0.0150969431722 0.00961358010122 0.0230069897016 0.0136344497691 0.0781873312389 0.061922358127 0.0567947708263 0.0549074799203 0.0663268940474 0.0637272258979 0.0651276548535 0.0583171690756 0.0677292446726 0.060191106251 0.0450946120505 0.0568830058441 0.0543288790766 0.0714589426004 0.081454303397 0.0624243269582 0.0472314410611 0.0479124253475 0.0858307227677 0.0627914211132 0.0589518720089 0.0648453559762 0.0697319385158 0.0476614784634 0.0522209851297 0.0435983831723 0.0443141443319 0.0427834724857 0.0660408790701 0.0423473900154 0.0592034189384 0.034371623803 0.0697342027164 0.0381294864628 0.0595840773258 0.0612390496755 0.0689539919437 0.0466415215244 0.0431628346368 0.0495434525796 0.0666477691564 0.0566659496435 0.061922358127 0.062735676927 0.0682003243846 0.0612178236271 0.0603270178223 0.0499653486319 0.0649071391116 0.0500436367076 0.0339571590708 0.013301666182 0.0294613107742 0.0254168369791 0.0187830848109 0.0337456927151 0.0151760493477 0.0360233288761 0.0161149469416 0.039042024755 0.00229536147376 0.0468249873675 0.0157583667263 0.0310761119725 0.0155497505138 0.0090301180649 0.0126416375855 0.0110159110748 0.0254616235228 0.0242814349621 0.0236690592627 0.00236651040215 0.00842631126501 0.0122777482071 0.0387720000407 0.041740632348 0.0402615455592 0.013434165421 0.0259957062278 0.0279382933191 0.0176919201528 0.0210030594474 0.0190515742522 0.00605687883869 0.0125440326934 0.0183812478057 0.0234838433483 0.0213287295776 0.0102611349583 0.0367608397052 0.018305882063 0.0762459812633 0.0565232340764 0.0480647092458 0.0470080033305 0.0607210126742 0.0515562009886 0.0623134210102 0.0445281266442 0.0542656274802 0.0589172543408 0.0450145677229 0.0482495838943 0.0484339717661 0.0652417317109 0.0793204584838 0.0620264746962 0.0400173133601 0.0433798691859 0.0725797896424 0.0481813389954 0.055284998644 0.0628522019597 0.0554630904838 0.0404443368976 0.0493602212467 0.0332419109523 0.0398075629785 0.0413677301877 0.0589057964055 0.0278286603835 0.0454781228443 0.029186418008 0.0632373035893 0.027173160002 0.0466041993476 0.0516248397682 0.0694549695494 0.0414073101396 0.0429302830553 0.0451579600752 0.0633364240737 0.0552241510377 0.0565232340764 0.0584051969715 0.0667610558404 0.0584355181495 0.0512925402879 0.046128531904 0.0664605075068 0.0478081299752 0.0403784266437 0.00849189377523 0.0578244327435 0.0213782060591 0.0260735654855 0.0286868543518 0.0107633182991 0.0429130184438 0.049112317265 0.0332704837119 0.015321761445 0.0277153223765 0.0397499694056 0.0358925712782 0.0304111104426 0.027505083584 0.0362377250231 0.020296537393 0.0117771620381 0.0454349567531 0.033203078919 0.0404550655622 0.028050968973 0.0329121522515 0.0157822820327 0.0128529655968 0.0212960295437 0.0481179953609 0.0170390332384 0.0197624290813 0.029414246654 0.0176689832365 0.0290804953813 0.0317312604538 0.0173770193477 0.0255273516204 0.0167054579942 0.0259572392414 0.0381174742782 0.0168503391466 0.0510138836142 0.0385473731826 0.0388016187658 0.0368178557203 0.04276997017 0.0503778656709 0.0392641023806 0.0497809957465 0.0564266766196 0.0332095636962 0.0188695135337 0.0387787813789 0.0331502464834 0.0483979502244 0.0548055143427 0.035228159998 0.0294466884888 0.0272290139414 0.0724784935896 0.0548011964122 0.0344489111929 0.0380672364964 0.060026483594 0.0303284751736 0.0272545178904 0.0327801045139 0.0239410636139 0.0177611799925 0.0444007657806 0.0400513163792 0.0497786040376 0.0204852863736 0.0470867569115 0.0308376722615 0.0532970554221 0.0452748414675 0.0407821021663 0.0268849282918 0.0168086928609 0.0279020988959 0.0414910752652 0.0343097482389 0.0385473731826 0.0381367753126 0.0413101510581 0.0377465227401 0.0435171810289 0.0268955341281 0.0365057689544 0.0254190380854 0.0372013435687 0.018490846954 0.023945912793 0.0440067159299 0.0253810829497 0.0423576975539 0.0266775910883 0.0276067076791 0.0155964706338 0.0512008225103 0.0249293141549 0.0224091031216 0.0208182862063 0.0201027144741 0.0218258381078 0.00416795120123 0.0250523436876 0.0291897433081 0.0336104473732 0.0126474260294 0.0179897427224 0.0236687976248 0.0357767564718 0.0479080621505 0.0493839683144 0.0213027411218 0.0127962715487 0.0389577422313 0.0207982711984 0.0248766740175 0.0272195414617 0.0164396805465 0.0239043019084 0.0253433507519 0.0357454256498 0.0316012688091 0.0218891275488 0.046006369731 0.0279699723289 0.0753592714385 0.0538300830176 0.0427234551893 0.0442120918411 0.0575724115573 0.0438794711912 0.0617203772126 0.0368175055007 0.0452394206226 0.0586608041232 0.0462735571883 0.0428932945735 0.0449361857949 0.0608531076963 0.0771129194067 0.0618336393757 0.0380658785095 0.0436894906412 0.0627047512052 0.0382553066725 0.0531191059331 0.0620656917263 0.0459127944105 0.0362899248016 0.0492167826913 0.0301637294202 0.0380460619309 0.0426550687382 0.0544072702012 0.0218332584664 0.0362322493618 0.031226533309 0.0587827461321 0.024852970378 0.0417700516252 0.0442659791406 0.0702283886386 0.0412678777108 0.0447863140602 0.0428258891548 0.0608093994885 0.0534400200237 0.0538300830176 0.0561072465285 0.0656581075266 0.0558523559264 0.0444818994194 0.044500683531 0.0680831562837 0.0488303143353 0.0536500814259 0.0217777943298 0.0182308184172 0.0213271967089 0.017640751735 0.0384313065823 0.0491331799987 0.0285490579199 0.0236508921207 0.0203518801552 0.0410544418794 0.0345949638149 0.024163451076 0.0208164937907 0.0331698057229 0.0214370208347 0.0129093004816 0.0378630437774 0.0285080143021 0.0349561724295 0.0213643314537 0.0378207671811 0.023156173716 0.0144257922467 0.0164328495191 0.0458898771597 0.0137078716838 0.0180512548912 0.0303444429836 0.0166949845236 0.0239375979831 0.0248141920509 0.0164642247089 0.0221495310709 0.0136759772653 0.0203492925476 0.0297801495496 0.012327304817 0.0589145352863 0.0454329273476 0.0436909431618 0.0429329583507 0.0496681092117 0.0546717056664 0.0472190839202 0.0531335572006 0.0601545762173 0.0404993410456 0.025351107679 0.0436326686228 0.0384109589864 0.0546942484238 0.0614849395874 0.0420121432296 0.0350678306139 0.034181943564 0.076607832627 0.0574938051354 0.0407284888751 0.0455392391661 0.0634559846389 0.0340449392101 0.0346886110004 0.0365094436091 0.0283668149646 0.0247441178114 0.0505723350307 0.0414268809452 0.0526572068528 0.0247442404176 0.0533283030157 0.0333480302269 0.0569330422551 0.0488445949836 0.0485166318417 0.0334202567015 0.0241088713298 0.0327605074387 0.0477602460683 0.037977730422 0.0454329273476 0.0450703466816 0.0481686005759 0.0425586735361 0.0473020173719 0.0326189496433 0.0442268465034 0.033265894657 0.0406164099076 0.0563656658624 0.0369501005762 0.0596090654503 0.0304778147307 0.0384204581231 0.0270915625525 0.0693260105947 0.0372136698768 0.037023479673 0.0317062741776 0.0317712182279 0.034804368211 0.0223060266021 0.0435100417127 0.047004084469 0.0362329082931 0.0256397756303 0.0233719185841 0.035627421568 0.0521858971919 0.0650552610656 0.0654396577163 0.0372909018916 0.0208395075735 0.0532980934411 0.0387978654626 0.0393043110859 0.0433091405548 0.0302415541747 0.0340064333643 0.0421117035102 0.0478257550421 0.0466283489206 0.035247716101 0.054937797688 0.0434605477125 0.0930034854114 0.0710598303107 0.0590352084097 0.0604460830393 0.0745555173324 0.0571183440581 0.0793617023165 0.0484952151811 0.0566053521726 0.0768259736839 0.0646780127707 0.0592344115045 0.0623544010763 0.0773513341111 0.0945306112415 0.0799933849368 0.0552426925494 0.0610368934489 0.0726391747026 0.0486086004123 0.0708765879781 0.0800292786375 0.0558578611463 0.0537011940437 0.0672777153371 0.0461852109805 0.0561622363977 0.0610513630375 0.0708198771797 0.0350965268909 0.0484124521051 0.0486964562823 0.075256407672 0.04111323881 0.0515712020719 0.0592740141065 0.0884497661149 0.0586350703024 0.0632023881374 0.0606979638812 0.078320587954 0.0707259147977 0.0710598303107 0.0736338137855 0.0835800603427 0.0732101393079 0.0599496433571 0.0625510181289 0.0864139348042 0.0667637091982 0.0350728110176 0.0244007367668 0.0194418255357 0.0278046770383 0.0387260088041 0.0187288873365 0.0305873095592 0.0241694671072 0.0257451620145 0.0153815378858 0.021353060898 0.0215496497445 0.0200984831417 0.0151985245998 0.0110228413253 0.0387908454863 0.0190085239065 0.026530841158 0.0213969993651 0.0238500818663 0.0245406806879 0.0294364678495 0.0140120927131 0.0331219747793 0.0211978333105 0.0108265764026 0.00897607251111 0.00677241917437 0.0173770286262 0.0245814114194 0.00563326172159 0.0204952689406 0.0138047466575 0.0168569359655 0.0438273371107 0.0133334601758 0.0592456323654 0.0408071286879 0.0355509485261 0.031081872872 0.0452073820968 0.0410054777303 0.04495248578 0.0356498623047 0.0456510923283 0.0431383529174 0.0306345228853 0.0358468154266 0.0353265194622 0.0511623196634 0.0646276367384 0.0471382277373 0.0240229200194 0.0254553208119 0.0642596486532 0.0418982548195 0.0409421092482 0.0466753277343 0.0478887558589 0.0293373407147 0.0326161841904 0.0195735225778 0.0272641873276 0.0254981680323 0.0447040552558 0.0215611560931 0.0381253844376 0.0111199895155 0.0491745036263 0.0145691145727 0.0368088577033 0.0425091408325 0.0528722213324 0.0238501784613 0.0272505069941 0.0325614342759 0.0492627638247 0.0449950723976 0.0408071286879 0.042880253884 0.0517160325388 0.0466599102029 0.0415966376912 0.0321745745193 0.0499813496989 0.030016506883 0.0195067443548 0.034042657808 0.0387050626348 0.0607833234632 0.0322025711177 0.0402462250605 0.019510297358 0.0548235012014 0.0429595771314 0.0252279466187 0.0223273919125 0.0407231129516 0.0368354815518 0.0293953937656 0.0290463736365 0.0328461116776 0.035143771121 0.0215923461726 0.0549385181088 0.0388660143681 0.023623079783 0.0246479181765 0.0539903453268 0.0196033552608 0.0309786977565 0.0425462811063 0.0289476729073 0.0283702078661 0.0228452205014 0.0295421719187 0.0252210967901 0.0230772437036 0.0240590413191 0.0135013916275 0.0218148808282 0.0760114892469 0.0634029220478 0.0607879784498 0.0607163777171 0.0675569624906 0.0711706523576 0.0650651993965 0.0685468614076 0.0760185520266 0.0575507664821 0.0425210776149 0.0606855343213 0.0555229333703 0.0720565340813 0.0774071503121 0.0581416488422 0.0527363337967 0.0521637490438 0.0926239124524 0.0722776295267 0.0578783465588 0.0627903946651 0.0789206671037 0.0503951188312 0.0527646858335 0.0526096570134 0.04527903594 0.0427992547678 0.0682205850017 0.0547141937568 0.067807383273 0.0414244261778 0.0707718291801 0.0483573376556 0.0717861683592 0.0644987372167 0.0647006499463 0.0513517515126 0.0419564687506 0.0495341433982 0.064364362053 0.0518587226049 0.0634029220478 0.0627776825589 0.0645131806296 0.0578143875392 0.0631581345522 0.0499505499876 0.0600491597535 0.0513712453732 0.034450057717 0.0238219725869 0.0465207238958 0.0139550218762 0.0437148052069 0.00245848843359 0.0406705408218 0.027996084796 0.00617634742576 0.0042140797155 0.0226171443798 0.0276920922451 0.023535776763 0.0178395839466 0.0140356715542 0.0166022608919 0.00395476408572 0.0457707350729 0.0404789526881 0.0327219703849 0.0114454148489 0.0362680793242 0.0217463268752 0.0196365744138 0.030477863462 0.0206103562172 0.0102714385383 0.00460445870022 0.0203218526125 0.0212018784388 0.0183586998171 0.00829854248447 0.0218572079865 0.0144443422105 0.0767877803745 0.0594466868469 0.0529468255635 0.0532520366965 0.0637146030163 0.0600960587419 0.0639510014921 0.0553587219012 0.0637257572972 0.0581054381403 0.0427611569751 0.0529559974475 0.050488809742 0.0679805704334 0.0784814462329 0.0599903091584 0.0453120703317 0.0472956572051 0.081207762841 0.0585100350392 0.0557351056658 0.0628545029747 0.0657746195642 0.0431635890019 0.0505766161122 0.0416755044323 0.0404647152471 0.0409948112567 0.0627553433594 0.0398795409571 0.0548556307871 0.0337749376373 0.0662751646447 0.0362650420971 0.058753352182 0.0559719307576 0.0677796526261 0.0456851568449 0.0415580901724 0.0455930571155 0.0632638085815 0.0519953365762 0.0594466868469 0.0601182129397 0.0655928087235 0.0568949371894 0.0552051980285 0.0466604473635 0.0640269526764 0.0493532376221 0.0428114080859 0.0513187599237 0.0353300715155 0.0136841990953 0.0339659047401 0.0392151216672 0.0331598693815 0.0346578423583 0.0330024342773 0.038276947888 0.0230224626975 0.0145213724276 0.0501490398304 0.0358866478447 0.0428680377048 0.0326728263648 0.0285835471973 0.0062386073831 0.0158573158736 0.0257280664001 0.0503050577684 0.0188536314021 0.0230369129683 0.0250256284162 0.0171680840121 0.0324912467925 0.0363869094834 0.0177612063031 0.0250245943265 0.0179627656197 0.0294197347692 0.0465091219099 0.0203095862842 0.0478795030574 0.0357982238192 0.0376241763265 0.0315623347361 0.0401002610089 0.0474897864671 0.0350582543035 0.0460362585126 0.0538318698513 0.0325365856585 0.0213227378076 0.0377990397126 0.0335693240845 0.0471274543161 0.054885621667 0.0360897261843 0.0253548565171 0.0209548211511 0.0704293001167 0.0527939534511 0.0346935966786 0.0364130601336 0.0572327947958 0.0318390512051 0.0244040617426 0.0286768378156 0.0261566126157 0.0173773142125 0.0423900706098 0.037171182215 0.0481110975007 0.0159454061909 0.0456669379702 0.0274665151098 0.0469607798152 0.0462908705234 0.039158298024 0.0212460794033 0.0171141394847 0.0299475002492 0.0420369583583 0.0395076063195 0.0357982238192 0.0363456286371 0.0414629362584 0.0409765644808 0.0445581081298 0.027819794971 0.035217696192 0.0204081888775 0.0536229831874 0.0147412411033 0.0555896434003 0.0257773616784 0.0440411962897 0.0177255540439 0.0193829905731 0.0239978426404 0.0256940264499 0.0393410530504 0.0352411367288 0.0221731284836 0.0182277280594 0.0123391761488 0.020654487001 0.0493059373458 0.0475681206642 0.0451873269558 0.025880190654 0.0390288508413 0.0309214453223 0.0313196281309 0.0264802426158 0.0266703711652 0.0198006836859 0.019520741807 0.0278514155812 0.0221034761072 0.026690732588 0.0196134707881 0.0412756734602 0.0265178671443 0.0867397306197 0.0682110021203 0.0611304199736 0.0570363597121 0.0725160802101 0.0632079822129 0.072465417084 0.0544582268199 0.0658094706322 0.0704919404627 0.0569226677141 0.0614294730407 0.0618668588016 0.0780403185985 0.0918397178914 0.0740264863472 0.0508436174709 0.0525989509117 0.0847012354501 0.0597190404435 0.0681089165817 0.0742388101657 0.0664380426823 0.0545769816583 0.0603124830305 0.0434291774759 0.0533790593767 0.0526730162139 0.07136820435 0.037381607524 0.0577096830472 0.0386410478706 0.0759869972218 0.0373998132392 0.052181569916 0.0660810261842 0.0798969360666 0.0510826914494 0.0540234946407 0.0588039304452 0.0763291167757 0.0694007087698 0.0682110021203 0.0704124305268 0.0789271737863 0.0724038719993 0.0657040131714 0.0590995697111 0.0765722724394 0.0574793382897 0.0411299322154 0.0539204969946 0.0448971315706 0.0161163886115 0.0424587591617 0.0433134103038 0.0424269061508 0.0282464178608 0.029088245744 0.0394507490162 0.0585960215177 0.0377541724349 0.0451043153526 0.0458829699472 0.0321616028135 0.0557124503126 0.0614547711288 0.0392057260171 0.0177559051904 0.0564954090624 0.0332181102648 0.0405454141429 0.0436595776199 0.0393478274847 0.0472383546112 0.0407140770645 0.0569892712332 0.049354627832 0.0439022116296 0.0637553975882 0.0455099918129 0.0646100490562 0.0426539647843 0.028431151743 0.0378227253234 0.0447657124399 0.0278050988657 0.0537117960824 0.0274550112394 0.027109787916 0.0505464931112 0.0435971104256 0.0283504838988 0.0329648689469 0.0443909167392 0.0625701957077 0.0530229796398 0.0343871989004 0.0426240079793 0.0396498771349 0.0213457948378 0.0419360502864 0.0525916757896 0.0283713421426 0.0258314536376 0.0439902997437 0.0303827915475 0.0319578433558 0.0415135400801 0.039276736137 0.0267873256159 0.0192565547583 0.03784586336 0.0425882783228 0.0300770949457 0.0411024644378 0.0235206108502 0.0627241786637 0.0400442811976 0.0439864971889 0.0336917004451 0.0474026229045 0.0427127785344 0.0426539647843 0.0447428873557 0.0545498150062 0.042821329639 0.024917555179 0.03656154349 0.0624685036836 0.0466134489709 0.0464211898017 0.0148261628982 0.0328892390973 0.0156382282878 0.00785541359441 0.0118772597644 0.013233811524 0.0262299374219 0.024092235964 0.0223052815816 0.00384479195153 0.00794260597132 0.0107672255318 0.0397240757159 0.0410257993957 0.038935751255 0.0130110302225 0.0282819504394 0.0262547979726 0.0181226466418 0.0211289335782 0.0182692961983 0.00567846812613 0.0110316054291 0.0179271098732 0.0214946645806 0.0199268176637 0.00875561948865 0.0354271933282 0.0171443662393 0.0766374045646 0.0572939392451 0.0492966948245 0.0478544225205 0.061544844174 0.0531089657897 0.0627070970919 0.0461191081801 0.0559975469422 0.0592703107177 0.045198111152 0.0494826907565 0.0493817865713 0.0662451441692 0.0799247658409 0.0623534855885 0.040791427856 0.0437433118438 0.0743922416686 0.0500539193261 0.0559768175635 0.0632764008918 0.057263588801 0.0415573436738 0.0497522962913 0.0342757495228 0.040553840562 0.0415809282216 0.0599519771943 0.0293556022635 0.0472716928172 0.029440558171 0.0642586667075 0.0282006776448 0.047766217977 0.0531327322745 0.069584244341 0.041867047458 0.0430265316703 0.045945636772 0.0640480645613 0.0558532996544 0.0572939392451 0.0591020248311 0.0672221887664 0.0591786574244 0.0527229760336 0.0467939943149 0.066452337221 0.048010057481 0.0426662887331 0.0439949614302 0.0453715955589 0.0447907897725 0.0421151539334 0.0471958607455 0.0276193449237 0.02275846799 0.0605343055308 0.046215555164 0.0540603153716 0.0428037480825 0.0313795261955 0.0125172459763 0.0208290281635 0.0350621941996 0.0569552641601 0.0299458792012 0.0309610087229 0.0366049420462 0.0292005950568 0.0426658539169 0.046550389751 0.0288402250941 0.037809939324 0.0299619998536 0.0401350153602 0.0525912191682 0.0310232912468 0.0370292782789 0.029362531619 0.0351405044644 0.0315813022426 0.0330583005053 0.0477931213785 0.0264557013575 0.0497838425895 0.0546676669155 0.0214340498054 0.0132666230167 0.0351245595911 0.0284887636401 0.0394555006358 0.0430107543153 0.024001610215 0.0265746605534 0.0212961513987 0.0686985381679 0.055308045978 0.0261438582005 0.0256904480148 0.0588231449389 0.030013743601 0.0177237336601 0.0340579413817 0.023239083403 0.0129096702298 0.0366510262704 0.0448114548715 0.0501265325324 0.0238298010541 0.0385248366721 0.0348349791307 0.0531258509004 0.0432244806886 0.0265717263897 0.0222990802833 0.0105547424712 0.0247433535936 0.0319856839059 0.0308056274733 0.029362531619 0.0282110860995 0.0297242114734 0.0317000113527 0.0411003820059 0.0219347750579 0.022168792283 0.0155469808263 0.0395024062804 0.0287670845389 0.00713435108734 0.00340555052012 0.0220748170877 0.0261325674803 0.0225086838709 0.0197301659136 0.0143163055062 0.0179547860371 0.00552830002832 0.044759241534 0.0400746442935 0.0324889323762 0.0105741309237 0.0352991764051 0.0223168808509 0.0183878728912 0.0306904112299 0.0206021475442 0.0104104939928 0.00670538845305 0.0199820984844 0.0226302237702 0.0187233601872 0.00907856174289 0.0219615297998 0.0143637742128 0.0753337380263 0.0579434032885 0.0513377916805 0.0521965044751 0.0621695045027 0.0588078748161 0.0626419440897 0.0544695113035 0.0624620281749 0.0565017669041 0.0411290585403 0.0513195597187 0.0487054775012 0.0662358469866 0.0766400648909 0.0582604755345 0.0441853596565 0.0463597810918 0.0797172873623 0.0573362873289 0.0539615186802 0.0612879452506 0.064613107429 0.0413483548752 0.0492060616579 0.0408536005927 0.0386658835072 0.0395835329499 0.0611338973657 0.0393645393569 0.053572584104 0.0330686361703 0.0645571164168 0.0355933171917 0.0584689678276 0.0540828717859 0.066313152361 0.0447064134304 0.0401381607957 0.0437269026711 0.0614075519202 0.0498319714223 0.0579434032885 0.0585128670581 0.0638402708268 0.0548281142484 0.0533071471302 0.0449195692472 0.0626153729552 0.0482343239424 0.0295703841711 0.0366619395227 0.036500768924 0.0216100790796 0.0202086133386 0.0291081498137 0.0538445159183 0.0304641791012 0.0384602037434 0.0388505887816 0.0184939827468 0.0431509831641 0.0514497599393 0.0311190761962 0.0193480902941 0.0458820296239 0.0240997287473 0.0258856149523 0.0318135695083 0.0318488388141 0.0408906139312 0.0292269134036 0.0455476970026 0.0384416242221 0.0355459730354 0.0604270677753 0.0357756191383 0.0579552498509 0.0353240752803 0.0225716123758 0.0257247517645 0.0383804782921 0.0215488097029 0.044948702922 0.0168022708851 0.0235401078242 0.0440963094143 0.0364932029322 0.0228797040221 0.0280879909327 0.0410984380147 0.0600604954457 0.0480533666552 0.0218775898923 0.029791578282 0.04158778439 0.0178882014032 0.0370867411707 0.0460836281119 0.0252155578724 0.0208740877353 0.0346851323104 0.0150019768994 0.0257835645737 0.0322493089661 0.0342156649906 0.0116183721538 0.0144931943243 0.0240188836176 0.0389068297986 0.0144502424291 0.0276541092905 0.0250061652639 0.0558771163058 0.0271661677907 0.0351271284352 0.0289684152137 0.0442230773604 0.0424650907505 0.0353240752803 0.0384614305736 0.0501641618566 0.0418657156844 0.0254781137454 0.0303709238998 0.055175185082 0.0355533707256 0.0226236551837 0.0257243733887 0.0188708962976 0.0280458447088 0.0259495603965 0.0358126700891 0.0173972925493 0.0203550537734 0.0241984077655 0.0326658712857 0.0374251933899 0.0415458358848 0.0220997016335 0.0314739029711 0.0297599572502 0.0224642058136 0.0101652715813 0.0184552115135 0.0190795074292 0.0255522841638 0.0188568594492 0.0233889500734 0.0229626929389 0.0201746110209 0.0490887418108 0.0229752614583 0.0721999639917 0.0528489482775 0.0457665690796 0.0402580156331 0.0570067559398 0.0466251225309 0.0575932728503 0.0376765605581 0.0495760090258 0.0573857799099 0.0457294834507 0.0461836275015 0.0478961825174 0.0628300939828 0.0782978077723 0.0617431168606 0.0349090738753 0.0372003973766 0.0687801137491 0.0442160827041 0.0545072221083 0.0604041835816 0.0503536267186 0.0412302683921 0.0462335606677 0.0265634879228 0.0409252862943 0.0403112510912 0.055713517152 0.0210444978159 0.042126696634 0.0241765196843 0.060672423249 0.020816933598 0.0350778856202 0.052005350197 0.067095717986 0.0355534496705 0.0422916670752 0.0461036815572 0.0628103650139 0.0591144676161 0.0528489482775 0.055715116829 0.0658580956838 0.0605104799512 0.0516473901424 0.0459913703308 0.0644951804376 0.0433395766961 0.00476396676703 0.0174479971383 0.0262117873028 0.0230803954362 0.0185627883328 0.00806620839217 0.0113814933623 0.00390319674762 0.0428177321428 0.0406615445683 0.0354624532828 0.0102263088249 0.0317971018832 0.0234656694869 0.0177926588758 0.0262276626577 0.0188776295133 0.00499606040594 0.00424685036617 0.0184558479833 0.02090066744 0.0184013332257 0.00554993882929 0.0277916235291 0.0146255258466 0.0766584518429 0.0582536091399 0.0509151171955 0.0506702158494 0.0625265075224 0.0566765790267 0.063296553303 0.0510181236531 0.0599592936046 0.0584198089247 0.0435074153396 0.0509940717271 0.0495661398107 0.0669266401341 0.0789376730305 0.0608280979649 0.0430167703447 0.0455496571569 0.0778333721022 0.054368608181 0.0555188693765 0.0628704456678 0.0616793859568 0.0418722056261 0.0499801315934 0.0381178178645 0.0399704213931 0.0409195428074 0.0612188756554 0.0349680364553 0.0510653686933 0.0315069690942 0.065089713199 0.0323745393338 0.0538917621299 0.0541667478451 0.0685063182149 0.0437802642661 0.0419063387522 0.0452698567868 0.063322234724 0.0532615551019 0.0582536091399 0.0594215850469 0.0661130238288 0.0575059193505 0.0535703049783 0.046311202915 0.0650382074097 0.0485914933238 0.018842155525 0.0240370427448 0.0209528738511 0.0208089534878 0.0111203801188 0.015917150662 0.00453488271341 0.0421322819802 0.0391458330884 0.0331083714381 0.00824403626512 0.0325132311882 0.0224847085725 0.015999516676 0.0277730715816 0.0186363801442 0.00708833477439 0.00642676690132 0.0178233234532 0.0220593051536 0.0178006297585 0.00678573265748 0.0253531080362 0.0132629896024 0.0741187095157 0.0561450172019 0.0491350925935 0.0497514221438 0.060382347286 0.0560370322524 0.0611402268324 0.051356658754 0.059586423134 0.0554899035837 0.04031824984 0.0491508161478 0.0470289167752 0.0645318276086 0.0757421493114 0.057544117742 0.0418388253062 0.0443100927117 0.0770487593095 0.0543425693403 0.0526585588221 0.0601234502371 0.0616298008584 0.039475560154 0.0476974484773 0.0379820027229 0.0371681460661 0.0383173623723 0.0591794106435 0.0360653613059 0.0506856040282 0.0307481929538 0.0627839311984 0.0325910275487 0.055237903563 0.0520576344331 0.0655568890209 0.042566036842 0.0391094232808 0.0423459347432 0.0602723002528 0.0493981873195 0.0561450172019 0.0569656980973 0.0629553672806 0.0540102942581 0.0513493159685 0.0435185067862 0.0620208318713 0.0466647868495 0.0214518595921 0.0250574648372 0.0327035392179 0.0101396500324 0.0173409936704 0.0207342919251 0.0332931627481 0.0438902497615 0.0452760516117 0.0173962021214 0.0155474932413 0.035097178823 0.0167075078514 0.0219356609327 0.0232161362242 0.0132718217012 0.0215035441799 0.0212520758854 0.0323731403418 0.0276797560909 0.0185474301296 0.0436301136913 0.0240030156204 0.0722858985812 0.0511085237891 0.0406650357841 0.0417405611462 0.0549851372416 0.0429543701734 0.0585838550979 0.0363293620395 0.0449605458738 0.0553495140321 0.0426335340052 0.0408304262584 0.0422933209142 0.0585800490211 0.0742997883793 0.058525226517 0.035206446299 0.0404435198283 0.0627381786217 0.038449263747 0.0501920171677 0.058888502058 0.0460241869732 0.0337463818569 0.0458812434451 0.0278046680998 0.0349131438742 0.0389869853015 0.0521722266345 0.0209043609517 0.0359181281747 0.0276204608178 0.056526179998 0.0222941226577 0.041152359144 0.0428797366789 0.0667722352073 0.0380782189511 0.0410414680557 0.0398735425148 0.0580112990116 0.0505852294836 0.0511085237891 0.0532571789631 0.0625496034306 0.0531021220011 0.042888351609 0.0413906647006 0.0644729984699 0.0453457651066 0.0107504885543 0.0445819304752 0.0242663168605 0.0336280858548 0.0265479358211 0.0206001571473 0.0282052030653 0.0325495864256 0.0168933846577 0.0294835383052 0.0291726320507 0.0086711740192 0.0221542204142 0.0179304565478 0.022368606911 0.0297212987281 0.0149126627655 0.0323363820236 0.0229519593576 0.0235384954017 0.0445361789109 0.0198724736323 0.0521573964273 0.0325036248406 0.025391360945 0.0274230805005 0.0366454630316 0.0344942582431 0.0390192491133 0.0331598239249 0.0393605141281 0.0342759827638 0.021260474927 0.0254073365966 0.0234580906639 0.0407813070352 0.054069225305 0.037293221414 0.0193616327469 0.0235535155332 0.0561408138747 0.0363119747552 0.0299684113953 0.0382284111131 0.0425406057591 0.0161350959097 0.0256650379468 0.0189027762255 0.0143744986934 0.0179840539103 0.0351859317755 0.0236434364907 0.0314452790447 0.0139598707264 0.0389431870684 0.016485382228 0.040355084472 0.0299825744277 0.0456481354326 0.0213868007101 0.0199817088813 0.0197684998025 0.0379808456048 0.0313521152981 0.0325036248406 0.0336827412775 0.0416843797906 0.0334784161986 0.0289224474022 0.0207816321212 0.0432746333929 0.0259935830061 0.0406061367838 0.0235468720047 0.0318323205013 0.0219961670771 0.0255808203638 0.0205571609912 0.0226267329863 0.013012280745 0.0369778751619 0.0187789289183 0.00874641080149 0.0197571101094 0.00977736627462 0.0202312308031 0.0257037864622 0.00771970434192 0.0231557657352 0.0133099999073 0.0187324692629 0.0392432332024 0.0115155558073 0.0539655210169 0.0370438046358 0.0333786958054 0.0316409822149 0.0414621149977 0.0426991016561 0.0406517401284 0.0403678402162 0.0480644681966 0.0361424947464 0.0218113942904 0.0334641673727 0.0302365918541 0.0468956611505 0.0577004528593 0.0391757625612 0.0236163775334 0.0242576354959 0.0653230280715 0.0452817250312 0.0345762397733 0.0404850805623 0.0511603238121 0.024886725311 0.0274569982987 0.0236904007661 0.0206352481789 0.0182697542476 0.041544522984 0.0289437440201 0.0406091261712 0.0126309522282 0.0451825068417 0.020490830418 0.0442568377481 0.0395946754396 0.0458654268305 0.0228937718071 0.0192636370802 0.0258703030154 0.0425840964507 0.0360074541747 0.0370438046358 0.0378930233244 0.0444471390747 0.0387351356827 0.0382610925586 0.0256300024801 0.0425154846229 0.0258478343265 0.0236633695184 0.0174990292841 0.0186530571476 0.0611247172591 0.0557656094279 0.0466088592976 0.0282320418304 0.0445464770565 0.0341524834412 0.0362512556468 0.0421364706395 0.0353354631726 0.0231187500774 0.0150626098763 0.0358189243099 0.0298015850374 0.0324439491366 0.0223980477721 0.0244141427415 0.0302418773665 0.0942328467355 0.076594072426 0.0693014297828 0.0689934026371 0.0808708035071 0.0745545238332 0.0811424703773 0.0680895982601 0.0772898278285 0.0757784502044 0.0604959493699 0.069358828284 0.0677179794145 0.0851546659241 0.0961465377952 0.0777040409423 0.0614342341624 0.0635105029946 0.0949910709403 0.0710640834394 0.0733442971825 0.0804630717269 0.0785569975811 0.0599979412685 0.0679000809486 0.0561320615274 0.0579270123928 0.0585056430456 0.0796324819571 0.0514612322157 0.068283919556 0.0494122791964 0.083373938553 0.0501855689957 0.06973964597 0.0718399524308 0.0852557355766 0.0618964253913 0.0591154896454 0.0630863991576 0.0809010142666 0.069276699042 0.076594072426 0.0775503896407 0.0833112406891 0.0743754315619 0.0713482849075 0.0642332894623 0.0813844341388 0.0662752735857 0.00943572253542 0.0115403490897 0.0385513754293 0.041736873589 0.0399182937318 0.0122452242861 0.025058464158 0.0280391379811 0.0165428935252 0.0220426648475 0.0191966494038 0.00476868066193 0.0119136882752 0.0182274158907 0.024378991238 0.0214350053307 0.00987681971674 0.0356319079498 0.0179231346829 0.0755450486118 0.0557883449648 0.0471764532756 0.0467952668235 0.0599617395979 0.0511011457957 0.0617632501287 0.0445144536833 0.0538325742859 0.0579584947727 0.0439095831377 0.0473266714409 0.047305404175 0.0642647315012 0.0781620294368 0.0608980895696 0.0396397814207 0.0431908772896 0.0719383279912 0.0477762451878 0.0541744509705 0.0619776318533 0.0551486398926 0.0392023772277 0.0486708484659 0.0332061436773 0.0385651962783 0.0405238673503 0.0580675371179 0.0281169946403 0.0449308552075 0.0290979509914 0.0622896414172 0.0272386507233 0.0473564201885 0.0503681043652 0.0686223309305 0.0411717919112 0.0420509879955 0.0438795889294 0.0621492769732 0.0535535915584 0.0557883449648 0.0575324110618 0.0656578520536 0.0569417414102 0.0500298962763 0.0450037013757 0.0656341911967 0.0473715492692 0.0144468889514 0.0470085725986 0.0485138320241 0.0451352115307 0.0199583230651 0.0301372822106 0.0318368515531 0.0256571286264 0.0278614622113 0.0258405224944 0.0121251490044 0.0124421067497 0.0257425497103 0.0259848999587 0.0265128839547 0.0147071440313 0.0356921243154 0.0239599037157 0.0844599977072 0.0649098127865 0.0563152793656 0.0552526867175 0.0691043038035 0.0592804769565 0.0705635348052 0.0516880380121 0.0615515055365 0.0669939251635 0.0527850317966 0.0564919445965 0.0566781222463 0.0735436571696 0.0873943668972 0.0699246931044 0.0483722118201 0.0515510652048 0.079719756552 0.0550353446586 0.0634817595673 0.0710367571435 0.0623974106591 0.0485852577555 0.0576004808055 0.0413084590066 0.0479219849808 0.0493882028299 0.0672450344951 0.0348287223508 0.0527462211198 0.037276801135 0.071549415301 0.0351894067592 0.0529630080357 0.0594111357934 0.0773657257414 0.0496448829109 0.0507905960575 0.0532464315334 0.0714643731585 0.0625646663061 0.0649098127865 0.0667401518449 0.0748051995393 0.0661923309263 0.0591726016457 0.0543093310288 0.074196762744 0.0559244370052 0.043526425057 0.0386335179446 0.0321768451862 0.00974615024856 0.0352347635745 0.0201959159339 0.0180776754132 0.0269400303578 0.0177526168011 0.0076128290146 0.00378003726334 0.0176983136317 0.0184021944475 0.015957334363 0.00467338620778 0.0252008449064 0.0123712673884 0.075769333126 0.0581585948517 0.051685391535 0.0510927438975 0.0624824329901 0.058237684953 0.0625760535583 0.0529652916573 0.0618856654756 0.0574514448673 0.0423317456956 0.0517508019275 0.0497149058646 0.0670867680773 0.0782168275888 0.0597219475669 0.0433096265158 0.0451925797267 0.0797528207091 0.0566461202307 0.0551309318768 0.0620350591031 0.0638200944876 0.0424059873805 0.0493045876457 0.0391604065434 0.0398454975082 0.039967724192 0.0615633801452 0.0371201263022 0.0531118088353 0.0313373664803 0.0653089870936 0.0335830893361 0.0556009421638 0.055317918307 0.0671296861942 0.0435900410315 0.0407047621897 0.0451219309698 0.062876852421 0.0526327547566 0.0581585948517 0.0591116735406 0.0652217833265 0.0570769673892 0.0545681643866 0.0459758175248 0.0634453480612 0.0477419996054 0.0302678050916 0.043643410877 0.0344015081898 0.0370220423378 0.041870658286 0.0264826423168 0.0239447061259 0.0294219290852 0.0381639993795 0.046622906961 0.0276160450358 0.0433656713185 0.0358877725536 0.0394027280044 0.0640596529703 0.0352660320463 0.0428200645336 0.0215929365207 0.0157178006612 0.00848045847957 0.0252717757761 0.0193974269851 0.0287059984697 0.018482386953 0.0255997786212 0.0310533244304 0.0267766622161 0.0163561213819 0.0202134806234 0.03120585866 0.04895305148 0.036414957876 0.00526673250197 0.012342309222 0.0430330254803 0.0254800237585 0.0266262246906 0.032239986602 0.0289090953163 0.0180202124552 0.0199181330431 0.00657470209208 0.019948180111 0.0209059906389 0.0237059104211 0.0188029876251 0.0211536929916 0.0148162018356 0.0289733910382 0.0123381921604 0.0242362829274 0.0258181102869 0.0413288399769 0.0100525363381 0.0238857865216 0.0223322555234 0.0341921837249 0.0380927560603 0.0215929365207 0.0255329039423 0.0383043472154 0.0356000313746 0.0249953874006 0.0211460552822 0.0407734262534 0.0193178864072 0.0180029141367 0.0318989553395 0.055546862882 0.0233316606029 0.0289827460324 0.0288090712213 0.0227692137274 0.0384790428766 0.0423072029606 0.0235668927239 0.02923399269 0.0234314824709 0.0353361736228 0.0517306479462 0.0262806947106 0.0449202216804 0.0352666691701 0.0392752718621 0.0317034826189 0.0393329164331 0.0490036652351 0.0325915526781 0.0480657848217 0.0556144972514 0.0314856186317 0.0229568301755 0.0394863344353 0.0351981784458 0.0468732286627 0.0534614036052 0.0352961935447 0.0267660200432 0.0206247795688 0.0716485928619 0.0553558677376 0.0350658679333 0.0348297205048 0.0591015265332 0.0349050611526 0.0239450314084 0.0312292238968 0.0291976883203 0.0191245738332 0.0424715605102 0.0407160306554 0.0507428891398 0.0195019979736 0.0455419926359 0.03094049167 0.0480027022309 0.0486981223658 0.0364405293098 0.0216724201002 0.0185311393183 0.0322264249099 0.0418711782883 0.0415641388928 0.0352666691701 0.0357541599092 0.040359691621 0.0422344237589 0.0468672273606 0.0294846892119 0.0324923805449 0.019122055634 0.028756827183 0.0587035417373 0.0144079071022 0.0301136242831 0.0361947314748 0.0239369814187 0.0355016994114 0.0354103580658 0.0251937444079 0.0240593800606 0.0195703439645 0.0308533101673 0.0370972551577 0.0220259748313 0.0576270076145 0.0487199724465 0.0508215730415 0.0469075647824 0.0527931212734 0.0620087731623 0.046977227863 0.0607033064427 0.0681905343994 0.0417090362137 0.0294084394516 0.0508408090071 0.0450400867986 0.0589677823649 0.0627613332544 0.0433082894199 0.0402642195426 0.0363046359117 0.084449006206 0.0666097386489 0.0449981598795 0.0463289168121 0.0716590868723 0.0429897098207 0.0369198960753 0.0432687121664 0.0364322199569 0.0287560795721 0.0553568599314 0.0500592177291 0.0617693212505 0.0302484927047 0.057817398636 0.0410079662048 0.0620054930234 0.0578523465697 0.0464641684152 0.0365865801942 0.0272374209649 0.0399576916682 0.0513227964118 0.0446516670985 0.0487199724465 0.0480806958126 0.0495453699635 0.0482845333883 0.0560302897599 0.0385013240981 0.0415333749992 0.0339802993211 0.0315416974034 0.0191639032899 0.00845591360235 0.0214341775937 0.0115218935447 0.00798589270321 0.013178045677 0.0100207917484 0.0199483776485 0.012776598265 0.00707708079363 0.0310463483447 0.00779811122226 0.0665120827305 0.0484731432285 0.0421114253952 0.0418216626354 0.0527853739739 0.0493966141428 0.0532439640509 0.0450980317427 0.0534929652418 0.0482563107324 0.0334028573772 0.0421738253769 0.0400650763191 0.0574010770653 0.0690115183659 0.0507807835016 0.033887277172 0.0360916940356 0.0712074753299 0.0488889567075 0.0456112729946 0.052712754383 0.0558191941722 0.0328832629679 0.0398769847778 0.0305626616722 0.03027845702 0.0307126203306 0.051853149134 0.0304315085387 0.0449208583046 0.0225669791691 0.0556104755493 0.0254498384131 0.0488668504899 0.0462046921677 0.0583599392562 0.0343786096194 0.0317076229625 0.0356254179774 0.0534761774586 0.0442401179536 0.0484731432285 0.0494784680372 0.0560638562362 0.0481022882275 0.0453399462887 0.0364100969213 0.0549637988767 0.0386182470618 0.0499647144567 0.0286991839096 0.0337581082348 0.0374427591873 0.0282526339036 0.0355267981937 0.0350362485208 0.0478325170984 0.0425063748067 0.0336958297594 0.0552821351039 0.0385952701325 0.0756759815417 0.0533281139759 0.0401812481707 0.0447968354881 0.0564105044414 0.0391525826608 0.0629279047421 0.0332827070938 0.0388499692511 0.059944716429 0.0494848197832 0.0402828974015 0.0438747097228 0.0580998054312 0.0757410641548 0.0628856838636 0.039846534973 0.047063496141 0.0543336344875 0.0312551117596 0.052807685198 0.0627916823231 0.0390112066642 0.0353058185357 0.0513654740192 0.0323261929775 0.0392211101217 0.0463708307148 0.0519963158873 0.0234224809867 0.0301000678074 0.0372829629985 0.056085164213 0.0288004220361 0.0417416575715 0.0389119081863 0.0720657500645 0.0444323135884 0.0487706488559 0.0429521653792 0.0596874437499 0.052997284605 0.0533281139759 0.055723410021 0.0657462146584 0.0546473494099 0.0397492903292 0.0452841873006 0.0707319601823 0.0522103619845 0.0233361726138 0.027152976334 0.0145101369991 0.0239084572879 0.0231796409398 0.016731423623 0.010101659051 0.00781108168527 0.0186261838058 0.0315054768721 0.011535154356 0.0661583467836 0.0529737197777 0.0515726376237 0.0472342284059 0.0573866872941 0.0602508051558 0.0535888133028 0.0563499220883 0.0655740867856 0.0494619373879 0.0355566546043 0.0516986354459 0.0478914383755 0.0636133913461 0.0714227137745 0.0519652065027 0.040040966538 0.0379888138015 0.0833863881089 0.0624232672218 0.0504889561622 0.0539483262888 0.0682863371673 0.0434492287718 0.0419221148541 0.0393420375143 0.0383919560321 0.0330409365388 0.0586345177546 0.0426935993753 0.0582011555148 0.0271038932712 0.0620596992058 0.0353264927481 0.0565229896235 0.0582751327845 0.0564224406826 0.0375222198637 0.032781658946 0.0431629716317 0.0579468986629 0.0506284295544 0.0529737197777 0.0534601982596 0.057907553496 0.0543043024926 0.0568716124285 0.0423649825393 0.0520169525452 0.0387128090446 0.0188041113809 0.0118952838684 0.0140246174547 0.0212962400935 0.00885470160798 0.025142494638 0.0164130694781 0.0148836892075 0.0382106616301 0.012548123562 0.0595024177002 0.0405144987261 0.0336829979036 0.0339109092342 0.0447786612887 0.0412528753098 0.0460796810618 0.0378073897699 0.0456289595962 0.0415318567716 0.0274434917532 0.0337586538145 0.0320559171837 0.0493065770936 0.0620181140557 0.044443934423 0.0259210454652 0.0290199212383 0.0631931226882 0.0415500215307 0.0381432011516 0.0457001329437 0.0482419653282 0.0247624956339 0.0326912275918 0.0231122641396 0.0226732232029 0.0241582823353 0.0435758556102 0.024717419625 0.037259551901 0.0161507334564 0.0474557435456 0.0186437176733 0.0428749718429 0.0381563349544 0.0522572394535 0.0270598018866 0.0256825354187 0.028101885414 0.0461630275758 0.0383904744963 0.0405144987261 0.041758354552 0.0492909187408 0.0413606774947 0.0372601462253 0.0289047461458 0.049343864353 0.0319066136889 0.0140884736377 0.0220949123029 0.0294588701998 0.0141915109934 0.0236402055251 0.0202701530019 0.0222961106051 0.0508328337578 0.0209048958304 0.0623063919994 0.0435137888223 0.0379179155361 0.0310595169631 0.0477275300573 0.0401401417297 0.0476510837343 0.0326069267264 0.0442002914704 0.048031576146 0.0373260310255 0.0383688546713 0.0396828967833 0.0540671732006 0.0691161945626 0.052697233895 0.0256698443155 0.0271866198766 0.063343063446 0.0401717345523 0.0456835007162 0.0508390224232 0.0457136947621 0.0340506342939 0.0366331778515 0.0185292352758 0.0332180639746 0.031402826069 0.0470047522912 0.0178796862446 0.0373117201537 0.0146755143259 0.0519441438124 0.0134308953908 0.0305516636587 0.0455547559496 0.0574314455133 0.025677142017 0.0334820400224 0.038185075996 0.053981408775 0.0519396327628 0.0435137888223 0.0464090712113 0.0566586435278 0.0526391071675 0.0449104072539 0.0375180555166 0.0549667946861 0.0334290223836 0.0161979126548 0.0212360948185 0.00313302296585 0.0148689509772 0.00704616989296 0.0135603719097 0.0384674432624 0.00748847746612 0.0612097252086 0.0442840466006 0.040253243803 0.0360606427738 0.0487530949526 0.0470778914902 0.0473392259982 0.0422963534873 0.051949068182 0.0444929580638 0.0309270188278 0.040473799777 0.0386243677637 0.0547837147046 0.066413370926 0.0479885282668 0.0287291459439 0.0288822795748 0.0702829288423 0.0483322868723 0.0432975336344 0.0484818516534 0.0543652596123 0.0329738645592 0.0348525988976 0.0258401695463 0.029652318833 0.0266204166929 0.0488217477328 0.0282325775461 0.0443695558327 0.0152728890442 0.0529346931915 0.0211960241124 0.0432358961175 0.0470042201915 0.0535566647123 0.027654993588 0.0276975587847 0.0349524016669 0.051450438001 0.0457471816551 0.0442840466006 0.0457673454519 0.0531390087147 0.0482613634351 0.0459084957324 0.0344895940573 0.0501063288839 0.0320407745768 0.00918896575074 0.0152928703979 0.0213827580606 0.0175694634428 0.00562421953864 0.0321021314886 0.0136468651148 0.0732793088732 0.0542749513511 0.0465599433205 0.0461499050441 0.0585282720374 0.0518386762248 0.0596896497046 0.0460357977086 0.0551020502351 0.055347044484 0.0408456006547 0.0466734650365 0.0457685420886 0.0629790052567 0.0758414718388 0.0580725583953 0.0386295601195 0.0415657641172 0.0731303485703 0.0495368191967 0.0520897347287 0.0595893389246 0.0567976430466 0.0379647331116 0.046441942626 0.0333063038869 0.036500108881 0.0377849182347 0.0570420811998 0.030012797008 0.0462545479693 0.027461418846 0.0610786707463 0.0275181743774 0.0490679602747 0.0500650525841 0.0657243645716 0.0396831631678 0.0390548397455 0.0418579268325 0.0600259300869 0.0509169565607 0.0542749513511 0.0557017357111 0.0631094362549 0.0546387182457 0.049518990394 0.0428637051261 0.0625010516077 0.0450876329039 0.0212339329669 0.0205215987455 0.0193863377449 0.00780222226267 0.0244911121423 0.0160871853235 0.0794295187203 0.0616053956912 0.0547043851777 0.0543405312398 0.065903416382 0.0608093966938 0.066232208671 0.0551996275352 0.0641635601661 0.0610614868167 0.0459223913813 0.0547672174246 0.0529488520021 0.0703578675954 0.081658744309 0.063265127216 0.046621662518 0.0487339053303 0.0819943915105 0.0586031447424 0.058550915637 0.0656481691263 0.065908662167 0.0454276311919 0.0529363521846 0.0420305180364 0.0431442291715 0.0436296366503 0.0648039964872 0.0390809908814 0.0552779379516 0.0347675148936 0.0685677387884 0.0363124697872 0.0577513229251 0.0579440183076 0.0708163109663 0.0470812852612 0.0443909494169 0.0483964045026 0.0662606542355 0.055662814312 0.0616053956912 0.0625961650479 0.0687432253304 0.0602433308395 0.0572909174214 0.0493875071422 0.0671416550914 0.051430941132 0.0176886906331 0.00927892520724 0.0135248076976 0.0386449359276 0.00800171044068 0.0600153322548 0.0424684845259 0.0378068586886 0.0345103555887 0.0469162632965 0.044830307306 0.0461600332306 0.040366688607 0.0496446456688 0.0429723253644 0.0292480429291 0.0380026884561 0.0362133523808 0.0526530252718 0.0646507321938 0.046401756397 0.0269368048123 0.0278152961494 0.0678508831968 0.0459682894465 0.0412431425852 0.0469952418705 0.0521326959742 0.0302237793371 0.0333696851677 0.0240543524356 0.0271406206916 0.0250182744726 0.0466959485275 0.0265020349694 0.0419000008026 0.0139599809083 0.0507909794153 0.0193885955935 0.0423195771966 0.0441873849773 0.0525088605043 0.0263754966172 0.0262639235251 0.0325133748369 0.0494223408625 0.0434143928247 0.0424684845259 0.0439360734198 0.0514706200386 0.0459476778298 0.0431249041549 0.0322850478478 0.0492075262735 0.0310084454102 0.0100495790147 0.0163467110294 0.0344303173981 0.0138069903297 0.0725561849391 0.0577945355153 0.0549392051976 0.0494983401957 0.0622636335656 0.0613281176125 0.0591564733558 0.055493289997 0.0660163516694 0.0564238014063 0.0428263617367 0.0551692935595 0.0528843814502 0.0687090576791 0.0786138592889 0.0595588928727 0.0427108568825 0.041401774003 0.084635719422 0.0620469795992 0.0566375025559 0.0605458826833 0.0680826326606 0.0475957607451 0.0475121922821 0.0395532575369 0.0436869591597 0.0392259763169 0.0629613789201 0.0403138291944 0.0584854937624 0.0290090498587 0.0669476358426 0.0346983343078 0.0538333844175 0.0617823249939 0.0639146571596 0.0406990904981 0.0395983575205 0.0488304003282 0.0645174644364 0.0580105192199 0.0577945355153 0.0590354282227 0.0651460923012 0.0612394393036 0.0606595939265 0.0481508588685 0.059835663962 0.0439114917806 0.0129734005291 0.03341718436 0.00522839839082 0.0644629130549 0.0490781090479 0.0460393397147 0.042060104717 0.0535473784021 0.0537667869164 0.051142158888 0.0493088817338 0.0587609555936 0.047452874403 0.0333145084294 0.0462018313471 0.0433659094036 0.0595851004773 0.0694769331379 0.0504124171924 0.034671039268 0.0338977868767 0.0768809318577 0.0551957563061 0.0471765984426 0.0517762151648 0.0612752535588 0.0380650031758 0.0388085089346 0.0327052071067 0.0338902731124 0.0299610722521 0.054082097785 0.0351427472718 0.0511360689963 0.0213341577068 0.0578680354373 0.0282202368919 0.0499673113862 0.0525352197686 0.0557073834724 0.0329893658613 0.0303826410135 0.0390336792828 0.055051644837 0.0480885204528 0.0490781090479 0.0500556489468 0.0560168186449 0.0513666437929 0.0513150683738 0.038531174408 0.0517653307967 0.0358776775011 0.0293027668161 0.00949293329263 0.0725916210374 0.0547194436592 0.0483620571735 0.0469816749901 0.0590799074957 0.0545464429945 0.0590974756513 0.0490311503881 0.0583273766433 0.0546626805606 0.0398779297173 0.0484777367952 0.0468025950712 0.0639880374892 0.0757199402524 0.0573199482995 0.0393352512936 0.0411552751652 0.0764775433632 0.0532445829203 0.052349146311 0.0590579753428 0.0602574471507 0.039602885829 0.0459481099263 0.0349175810863 0.037150941259 0.03692168916 0.0582151479375 0.0331340211018 0.0497159727507 0.0271028830882 0.0621502493207 0.0292960379946 0.0512053897158 0.0526539904442 0.0643939446385 0.0395489605444 0.0378591872997 0.0425337328718 0.0602822057384 0.0511975943751 0.0547194436592 0.0559279154126 0.0626694858218 0.0551041885347 0.0518894661445 0.0431638732605 0.0608387750183 0.0441361499894 0.0310183369902 0.0871660444405 0.0733823196322 0.0689340787316 0.0705597518969 0.0774366556509 0.07861295118 0.076322371958 0.075585060054 0.0826717778434 0.0681219966699 0.0528565530205 0.0687776982924 0.0640973745197 0.0810751053908 0.0869333145725 0.0682988428223 0.0623918658396 0.0630905228705 0.0989058396189 0.0780506774957 0.0672923155095 0.0734447484338 0.0852286487915 0.0580045491026 0.0635565107431 0.0611199283903 0.0538632888957 0.0534691027903 0.0772908944799 0.0610905623861 0.073927736475 0.0514266311669 0.0797776498939 0.0563654161709 0.0797411714169 0.0709112220147 0.075991910188 0.061929266059 0.0528794637266 0.0580761513446 0.0735774043698 0.0591743277341 0.0733823196322 0.0727567267189 0.0745131906994 0.065799040936 0.0698581828462 0.0592195179672 0.0715468662712 0.0627789092372 0.0648080233561 0.0484745494015 0.0442686485072 0.0419227062634 0.0529072690322 0.05220865754 0.0515658331236 0.0480206916873 0.056947174509 0.0470499747083 0.0323100366631 0.0443750009709 0.0415450201967 0.0583606796016 0.0686531977281 0.0497286282257 0.0341488382347 0.0345013563823 0.0748626932863 0.0530450676854 0.0459172064129 0.0515384326883 0.0594738121093 0.0355453778886 0.038659716641 0.0319368788596 0.0317165879728 0.0293867131129 0.0529269518286 0.0336846365247 0.0489212862277 0.021422361173 0.0566364033836 0.0272163294484 0.0501093106191 0.0498104699827 0.056059086848 0.0332712049783 0.0299486671345 0.0369730112559 0.0537844555125 0.0455932312627 0.0484745494015 0.0493458255088 0.0553162838774 0.0492693292197 0.0486803630647 0.0369835817896 0.0522579331221 0.0364683447074 0.022730708667 0.036743783492 0.0359076620395 0.0204805867516 0.0463990865864 0.0147686048767 0.0549817963395 0.0525592871928 0.0196223614467 0.0349129145261 0.0366443799136 0.0327544499352 0.0228629827418 0.017026958725 0.0209966358066 0.0388626349727 0.035298115438 0.0567980979705 0.0582058906835 0.0248891314561 0.0145753449597 0.0570907866116 0.0413833987479 0.0269969183741 0.0492024913366 0.039440986454 0.0359176091053 0.0265520996515 0.0615044403055 0.0540461620767 0.0485288037826 0.0239710979892 0.0540724881457 0.0603640513646 0.0428978851084 0.0134027017241 0.0368991356344 0.0354211161184 0.0355257446359 0.0210753154172 0.0377446845484 0.022730708667 0.0201673641607 0.0164841811953 0.0313109932769 0.041027522952 0.0326196770584 0.0184701671719 0.0295244972329 0.0144112105736 0.0158826147242 0.00448936000965 0.0256749628733 0.0117360219999 0.0336843126425 0.0324372887253 0.0146677582401 0.0224513170291 0.0144322007261 0.0126899376427 0.0122323800999 0.0277700509569 0.0197834641463 0.0180901487399 0.0184584697146 0.0418096588931 0.0367452397055 0.0108947935426 0.0131136689852 0.0371795334759 0.0204476192567 0.0118634455346 0.0280193213775 0.0206906520081 0.0208413846069 0.00805992628737 0.0397245591306 0.032104964073 0.0301985227624 0.0107001908888 0.0330988349255 0.0415195660786 0.0230606485279 0.0236410923325 0.0187109927435 0.0222023475244 0.0175662614613 0.0151089228932 0.0279798538754 0.0 0.00504787707871 0.0188703006517 0.0219245561497 0.0212095981034 0.0149942492526 0.0252687339312 0.016225955903 0.014982874816 0.0165713440517 0.0153992347708 0.0258128425881 0.0233194300829 0.0216404069707 0.0254243329386 0.0254506863873 0.000788850240312 0.00972288497974 0.0186083951584 0.0381473811219 0.0294157845108 0.0147578085456 0.0211609731312 0.0342335739858 0.0241609615185 0.0173732430671 0.0259324451415 0.0264222187829 0.0114741578552 0.0193298399608 0.0206022299244 0.0166568971164 0.0229188388297 0.0118905814083 0.0295550989457 0.0189848877848 0.0268759492012 0.0164070102936 0.0252554335694 0.0350869023834 0.0115237799469 0.0366507700029 0.0195520445986 0.0253794363549 0.0152320827299 0.0231766024476 0.028592244401 0.0144112105736 0.0173074040909 0.0296651493536 0.0243710502336 0.0103105434217 0.0155263675354 0.0374184940592 0.0231136537684 0.0190194510466 0.0188364876977 0.0221985054079 0.0214172478398 0.0257446692843 0.0273354856863 0.0275203255805 0.0156705691302 0.0195445751869 0.0258686776409 0.0435616108671 0.0331590462603 0.00822908256455 0.0111578554098 0.0408350390305 0.0282065307084 0.0237933699021 0.0272090918986 0.029489839001 0.0211107451245 0.0171676820259 0.0146997004559 0.0226821224304 0.022183640748 0.0185118691459 0.0264356522916 0.0241910879615 0.0208215741795 0.0237366538469 0.0205889692169 0.0263075431581 0.0263185412116 0.036342074994 0.0103523538982 0.0247947799759 0.0232770954007 0.0303205821473 0.0382875192266 0.0158826147242 0.0205185838207 0.033936913628 0.0342591359421 0.0252819239657 0.0211775313941 0.0366164619483 0.0168683582115 0.0265527528137 0.0122930639405 0.0356399190513 0.0329283261088 0.0161748547301 0.0260907486468 0.0165355786656 0.0155013603686 0.00871939649167 0.0250375042482 0.0205784254424 0.0221880849182 0.0226228234946 0.0402265547715 0.0380348851944 0.0126404460089 0.0132955588731 0.037673161045 0.023685130291 0.0159536871846 0.0317445670434 0.0244407629294 0.0250650773838 0.00665080674841 0.0431354773139 0.0336884150562 0.0346100496205 0.00755310734613 0.037025240188 0.043753914844 0.0237910793513 0.023601769275 0.0229675330633 0.0262374537149 0.0207694947791 0.0142462256068 0.0294419901123 0.00448936000965 0.00600179744469 0.0181950411243 0.0225874743282 0.0220819669003 0.0185630904749 0.0261141108628 0.0202600233978 0.0359510556228 0.0122181959079 0.00715556619596 0.0393252590156 0.0398773260728 0.015944130912 0.025117898688 0.0279596047113 0.0495072405762 0.0438343802676 0.0223301740975 0.0291958566192 0.0238057945893 0.0121408308676 0.0320439133203 0.0386704894061 0.0116681269474 0.0246115626131 0.0320654848123 0.02212022544 0.0306066666749 0.0360151785428 0.0212925403107 0.0265520435189 0.0096564754612 0.0336990775918 0.0258669646258 0.0271355620099 0.0255831511409 0.0192288539502 0.0492946436623 0.0275425360484 0.0388140188539 0.0303333899385 0.0366778253264 0.0435686919256 0.0256749628733 0.0298872725089 0.043124071299 0.0391147976424 0.020010154166 0.0305524053833 0.0506217525372 0.0340993001213 0.0427032875962 0.0428000340065 0.0127191401929 0.0244302586973 0.0258873530415 0.0224665589838 0.0196473040025 0.0259734946343 0.0180766430627 0.0245847379502 0.0205530555257 0.0515531804399 0.047284161103 0.0168752313645 0.0093274994833 0.0472940785154 0.0299859804517 0.013568861355 0.0349261393238 0.0278394065303 0.0233159306106 0.018729490125 0.0474594716238 0.0428441003445 0.0340535271365 0.0192623858156 0.0396592952666 0.0474504224755 0.0346317498496 0.0155232846365 0.0221965807346 0.023519540409 0.0251795457747 0.0186807942123 0.0328466600284 0.0117360219999 0.0111390258469 0.0171063233969 0.027248122956 0.0326787410905 0.0216187767654 0.0174724607588 0.0153838329478 0.013043913361 0.0463610530412 0.0437380208469 0.0239671160531 0.0322222363953 0.0387763357271 0.0597848214293 0.0513617728094 0.0233595904168 0.0301944308891 0.0320013483014 0.010613155035 0.0399275999718 0.0464560281456 0.0134988892532 0.0290788786594 0.0367911394695 0.0175534572334 0.0343523037935 0.0386269072909 0.0314326304477 0.0171757591643 0.0105270444576 0.0306360966619 0.0365489530298 0.0211256372062 0.0155275027866 0.0282406353658 0.0565789653078 0.0282583663219 0.0416523037157 0.0359394330813 0.0459783038684 0.0506220203623 0.0336843126425 0.0381881672141 0.0517807652888 0.0474506190651 0.0289707556044 0.0360504295798 0.0570578425896 0.0371145976129 0.0460576692202 0.0464080290911 0.0220712004031 0.0312574889523 0.0332251791601 0.054841891687 0.0503036463483 0.028999517533 0.0360798173432 0.0193249539307 0.00826557354917 0.0383933246971 0.0453200679143 0.00495350657916 0.0300295268949 0.0391229254289 0.0271682846269 0.036533385441 0.0426841669003 0.0272844902637 0.0287077471132 0.00927183865749 0.0394174170837 0.0313084618098 0.0314758507766 0.0267668687054 0.022518491913 0.05600898249 0.0343402195218 0.045509854552 0.0363226467926 0.0425348706975 0.0488168350062 0.0324372887253 0.0364696219213 0.0493441352532 0.0445105561012 0.0238995483109 0.0369592605884 0.0574925847452 0.0411978099793 0.0155890245102 0.0251635522565 0.0177733966699 0.020295344741 0.0224627747939 0.00622985531203 0.0261058920982 0.0236064364637 0.0550881017687 0.0493624804622 0.00949195374034 0.00547982782741 0.0508785947136 0.0251610996387 0.0119430843146 0.0365988456521 0.0213251727582 0.0179868212343 0.0207990673061 0.0485594746656 0.044214664825 0.0334335462828 0.0201922684831 0.0401754502972 0.0535325351547 0.0317074448278 0.0123261383208 0.0244676333996 0.0171629247157 0.0177983318365 0.0115555789303 0.021116940732 0.0146677582401 0.0105358367361 0.00915254671069 0.0167177891777 0.0294167459865 0.0147897849251 0.0123457776793 0.0164773765795 0.0252103273152 0.0171988861049 0.0305685435552 0.0365843208441 0.0175183238357 0.0218496748957 0.0205878945245 0.0593121863314 0.0470793832619 0.0159816216856 0.020744505382 0.0508661739809 0.018760262956 0.0128710885205 0.0300992820345 0.0117566522917 0.00679248320348 0.0280357325772 0.040552704264 0.0415859654681 0.0232256372519 0.0295874345059 0.0314690999231 0.0507965688951 0.0314591977122 0.0256867489287 0.0204093797109 0.00501434925534 0.0122277574576 0.0226603353781 0.0187158051887 0.0224513170291 0.020695499337 0.0231928239165 0.0198154038419 0.0292814261752 0.0103125125409 0.0227651885673 0.0153489133169 0.00921470910295 0.0183064776985 0.0377227049932 0.0290274791546 0.0152667053733 0.0215933253328 0.0343731361054 0.0245700487863 0.0169471424987 0.0257260078813 0.0268671065769 0.0111334970897 0.0193681705086 0.0211865368155 0.0163734248392 0.0228777878657 0.0117963493804 0.030068869871 0.0193762721713 0.027229886316 0.0161367068103 0.025740037188 0.0358416431275 0.0109673463454 0.0364509080414 0.0199965660095 0.0252914478428 0.014773865842 0.0226846344514 0.0279231861054 0.0144322007261 0.0171240275822 0.0292730788831 0.0236979129564 0.00966001570023 0.0151974508598 0.0372251985508 0.023311727536 0.0176051360114 0.032564167101 0.0208965631668 0.0168197313548 0.0207764664023 0.0423976172234 0.033280884693 0.00922898632458 0.0197200489933 0.0360385863631 0.00893473638299 0.014132357355 0.0250685285695 0.0103719683171 0.0167517993882 0.0135716425012 0.0350532380107 0.027879799306 0.0265658749664 0.015993421345 0.0286771298489 0.0428550440411 0.0151980773887 0.0298292088786 0.0196261415194 0.0184891599574 0.00655621912452 0.016322105066 0.0195353045374 0.0126899376427 0.0127701290018 0.0223217848231 0.0157154460048 0.0129568955631 0.00690277207156 0.0299954575682 0.0193817024498 0.0216771607077 0.0225658582257 0.0286138040807 0.0305011727447 0.0368382394098 0.0388439321615 0.0148355509953 0.0174423915339 0.0380129595202 0.0258082909988 0.0229842208153 0.0373470514825 0.0277476701907 0.0308564780706 0.00775830938446 0.0476084837369 0.0347450599297 0.0411478727988 0.00231111578025 0.0424821924039 0.0488975441679 0.0213563138315 0.0271270574956 0.0304501786922 0.0318897260431 0.0231190177025 0.0126379860304 0.0283589858381 0.0122323800999 0.0114136835682 0.0186791916183 0.0206672138954 0.0199079464104 0.0222007080182 0.0303110417953 0.0280827256688 0.0197052367937 0.0449418080277 0.0438182248518 0.0562345701188 0.0602081091792 0.0243728506009 0.019370550695 0.0596171194363 0.0411146925258 0.0330451422406 0.0550957050319 0.039836592047 0.0399228025142 0.0284759591968 0.0663825437409 0.0558252777705 0.0548034680532 0.0236830779253 0.0595333433641 0.0686676458986 0.0397842689041 0.0197958382609 0.0446061287137 0.0392287195509 0.0347118369491 0.0164026290561 0.0305214779366 0.0277700509569 0.0235155079857 0.0135888018548 0.0240589544851 0.0380160024194 0.0333951182547 0.0242014401746 0.0377621051763 0.0314790157987 0.029423203836 0.0582327389784 0.0535477924002 0.0121411421616 0.00926081168701 0.0551978876015 0.028043323191 0.0176337854836 0.041735927557 0.023998617859 0.0217227463265 0.0246395690903 0.0532994548372 0.0483234850835 0.0380931811444 0.0229416680066 0.0449797181572 0.059280772983 0.0338814552602 0.0120128740103 0.0301325195322 0.0203844916972 0.0200232099081 0.0110576598728 0.0182627991321 0.0197834641463 0.0150522414851 0.006556855609 0.0144048387324 0.0315801243453 0.0179150623078 0.0119668288225 0.022167313587 0.00841936493113 0.0453128226707 0.029523676844 0.0223084484022 0.0276272783534 0.0327625901905 0.0158536182647 0.0147737513682 0.0106741877313 0.0162753926733 0.0159900539559 0.0215767754577 0.023165172617 0.0247814128516 0.0137331692872 0.0264980088885 0.0153005942866 0.0291348842471 0.0254286093168 0.0364522562324 0.00599431682769 0.0189173783639 0.0184393411187 0.0301213577678 0.0340540018144 0.0180901487399 0.0215314467503 0.0337154513722 0.0315978293722 0.024169684578 0.0166816873996 0.0356875981931 0.0143747226708 0.0514837021891 0.0372994668391 0.0230531280792 0.0250236859971 0.0398047566678 0.021934356719 0.0118568359564 0.016712157857 0.0198275637831 0.0143476538676 0.0244078681037 0.0292462046489 0.0328036706334 0.014376575397 0.0286902071785 0.0204063466033 0.0328369650405 0.0322219054124 0.0320787692664 0.00266433410273 0.0165423262191 0.0215926529236 0.03047036768 0.0358252300263 0.0184584697146 0.0213100670766 0.032046547675 0.0333108429689 0.0306570115485 0.018573514939 0.030845411182 0.00824349209933 0.0254197321026 0.047324533609 0.0530498030585 0.0193482837408 0.0436475526218 0.0516271254066 0.0457976820229 0.0502335440929 0.0569904536613 0.0344485460271 0.0478896186827 0.0272539439051 0.0572698534085 0.0358919394369 0.050424643016 0.0434868500285 0.0309009333379 0.0632686594285 0.0501928388473 0.0594250482186 0.0482632028717 0.0482478127894 0.0570074387196 0.0418096588931 0.0448198518438 0.0553205633247 0.0514202209421 0.0325934353049 0.0491031454545 0.0660730408504 0.0548573842682 0.041501827818 0.0494594306994 0.00785967991178 0.0297803384368 0.0414124759052 0.0250716250932 0.0363814861914 0.0430927179021 0.0324719682551 0.0232534554573 0.00557282966442 0.0375065288364 0.0368003051347 0.0279998159154 0.0252506405295 0.0244125277036 0.0601405054627 0.0351799654171 0.0460355764213 0.0372310571496 0.0466115069454 0.0500875517655 0.0367452397055 0.0406580228721 0.0534802351733 0.0469702184582 0.0259083864948 0.0383091416944 0.0609916135179 0.0430915691708 0.0113258711014 0.0432937210726 0.0175511998728 0.0124157338497 0.03212454916 0.0158561794962 0.0176896387613 0.0143093876737 0.043181186929 0.0362893217044 0.0315177649353 0.0141883840024 0.0359022033885 0.0492746305333 0.0223018781484 0.0211045193185 0.0229404408443 0.0181288833884 0.0110415500412 0.00837364985146 0.0172572597582 0.0108947935426 0.00733209366776 0.0131427681285 0.0115359384743 0.0199994152339 0.0092535804352 0.0217603350968 0.0184515208125 0.0501255669434 0.0279388443296 0.0142651752221 0.0382528821443 0.0251771073359 0.0222405400165 0.018907996804 0.050407441851 0.0445874581383 0.03644061978 0.0176520694999 0.0424414179548 0.05338489352 0.0323923780445 0.0108812710336 0.0260958051981 0.0217902651406 0.0213471493056 0.0109405604951 0.0249968133743 0.0131136689852 0.00893536297262 0.00802513881767 0.0192978256402 0.0302167707341 0.018365059649 0.0130926236805 0.0184689475202 0.0343186729394 0.0436186327673 0.0296745080858 0.0408423177906 0.0469164023153 0.0321355072481 0.0293927572919 0.0115197032526 0.0423686398976 0.036129628995 0.0335484782832 0.0259949361948 0.0269704035297 0.0607621523939 0.0380404513983 0.049798653181 0.0409231346593 0.0474755392541 0.0535032395417 0.0371795334759 0.0413092694389 0.054257484038 0.0493594143559 0.0284802931744 0.0415978746211 0.0622229836323 0.0453773607077 0.0190484002067 0.0207749590973 0.00729318592678 0.0172314224853 0.0208211767145 0.0287420582694 0.0242194382748 0.0225231335589 0.0240241380028 0.0229680498334 0.0402905798782 0.0150429891355 0.0374592753112 0.0199314954492 0.0195088829088 0.00836639606005 0.0247669201274 0.0222507048525 0.0204476192567 0.021382719754 0.0305241597933 0.0212891172726 0.0134776031268 0.0107610654817 0.0367912026131 0.0227467739819 0.0252412358335 0.0153803531506 0.0101093922522 0.0191555088988 0.0375470144869 0.0363071087647 0.0222024666973 0.021689493319 0.0288400411309 0.0426974513075 0.0286740878663 0.0220177373135 0.0125507954062 0.0111145943691 0.0144555489867 0.0195277194831 0.0258649050915 0.0118634455346 0.0120062047089 0.0205457113931 0.0226933950128 0.0265812358015 0.010518368073 0.0210005232169 0.00605049088221 0.0227443548737 0.0240543202468 0.0298445720969 0.0127076622649 0.0212764877573 0.0130936058244 0.0350960563748 0.00616350137707 0.0220053566886 0.029182207808 0.0470447673611 0.0143549158293 0.0270200109504 0.0261798064669 0.0399469917707 0.0417589617676 0.0280193213775 0.0317524179632 0.0441157592928 0.0402109444472 0.0286518076954 0.0255338040061 0.0460635600013 0.0240522825965 0.0109052701432 0.0235077295524 0.0318665250498 0.0308330797717 0.0201941994246 0.026209699134 0.024272445381 0.0437154276666 0.0215651164399 0.0334110813047 0.0182660118628 0.0127706309369 0.00547043300996 0.0236736081076 0.0193715054877 0.0206906520081 0.0206326054685 0.0278093020752 0.0196854448654 0.0196839348285 0.00687772387853 0.0318861086105 0.0187829482374 0.026787715043 0.0349795665731 0.0377560197701 0.0169430774361 0.0294826475268 0.02554791035 0.044564230482 0.0307872765104 0.0282156909894 0.0140157312571 0.00304825224888 0.013131876158 0.0254598849649 0.0242359050423 0.0208413846069 0.0206178921833 0.0265921223132 0.024263714379 0.0287692622655 0.0105411880456 0.0255889461915 0.0107722057824 0.040112260752 0.0281920691871 0.0346799127455 0.00547299312148 0.0351698801996 0.0413927767406 0.0178561632488 0.0295704831304 0.0240442618733 0.028433519767 0.0198981190422 0.0164655446546 0.0293872770207 0.00805992628737 0.0103936152637 0.0224915115769 0.0226675446032 0.0164308167554 0.0187959028502 0.0318543120786 0.0236941138036 0.0214366809685 0.02158460699 0.0453234846239 0.0100348820296 0.0205571695519 0.0349449705288 0.0594353543617 0.0269232145172 0.0378563722335 0.0357646095878 0.0508614713562 0.0504482642845 0.0397245591306 0.0434432071263 0.055747628056 0.0497669350857 0.035138779746 0.0361053959246 0.0583555321158 0.0365217793435 0.0331608473129 0.0326376645366 0.0244797200401 0.0260351758605 0.0198255233977 0.055257342683 0.030607412773 0.0406724640229 0.0316826493706 0.0417015250124 0.044714144963 0.032104964073 0.0358439539437 0.0485265392209 0.0417397589401 0.0211023329973 0.0328093106913 0.055937896155 0.0382216948189 0.039178382683 0.0116462448464 0.0328449320294 0.0356452166019 0.0431040247851 0.0127555033307 0.0192172916283 0.0248029464024 0.0398126039657 0.0387676066679 0.0301985227624 0.0325088097853 0.0421224110282 0.0389248491362 0.0344395222458 0.0235149407659 0.0407276725105 0.0194230824244 0.0402634745964 0.0467109968717 0.0198309327046 0.0277799641062 0.0285372209353 0.0306922978338 0.0217975015009 0.0133715864954 0.0282760151712 0.0107001908888 0.0106288988311 0.0196086000788 0.0208164998238 0.0183683750797 0.0208677693371 0.0306825719595 0.0267116346537 0.0244223076771 0.0326854873354 0.0507787766717 0.0180800830921 0.0283453513368 0.0285692206738 0.0439964220236 0.0435330479692 0.0330988349255 0.0364104267178 0.047999984958 0.0430530022579 0.0322085934623 0.0282999450485 0.049271623839 0.0273166054796 0.0425206430225 0.0621747559979 0.0316259435967 0.0474306721161 0.0460270405303 0.055722110458 0.0616108763567 0.0415195660786 0.0463779068274 0.0600405303926 0.058487923658 0.0428330727641 0.0451145046508 0.0622811849491 0.040848815271 0.0429266615699 0.0304603009077 0.0328680598837 0.0193092495687 0.0257358921646 0.0276472175985 0.0230606485279 0.0242829569209 0.0335562675322 0.0240112096757 0.0023427193432 0.0215758461563 0.0440130376785 0.0333268924093 0.0336594835101 0.0267459293135 0.0300685155468 0.0190916149163 0.0302108808069 0.0236410923325 0.0197983357166 0.0116623663768 0.025981149508 0.0407083432987 0.0270506742353 0.00533601555818 0.0243947872794 0.0165388277645 0.0203993556991 0.0306449706863 0.0351570407904 0.0187109927435 0.0216936002715 0.0328125704384 0.0328483395342 0.0289711567156 0.0177290185247 0.0324417191457 0.00990245486371 0.0144435719572 0.0253854499058 0.0235470613048 0.0222023475244 0.0213735089495 0.0257216217897 0.0239916366178 0.0307770932602 0.0118559544137 0.0237036848381 0.0117425310805 0.0184555467145 0.0157796168272 0.0175662614613 0.0166625646078 0.0231975140243 0.0146299258577 0.0171445810537 0.00397360286698 0.029169512627 0.0192796522734 0.0184254094366 0.0151089228932 0.0104342480435 0.00810789324855 0.0108902089943 0.0236280097789 0.017384613998 0.0213096795304 0.0252727380791 0.0279798538754 0.0244605767611 0.021500625639 0.00796997392989 0.0256665045822 0.0176058458155 0.0292950203769 0.0310442784549 0.00504787707871 0.0188703006517 0.0219245561497 0.0212095981034 0.0149942492526 0.0252687339312 0.016225955903 0.0138989004364 0.0180767927652 0.0222193332382 0.0141002986592 0.0215877207325 0.0172352062998 0.0156454524782 0.031383424491 0.0212505739868 0.0142951058056 0.0253431933269 0.0219030212003 0.0156518397703 0.0263438271284 0.0285058962486 0.0193626993311 0.0417261059969 0.0313743437253 0.0260801912789 0.0155074292908 0.0227467684355 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-jensenshannon-ml.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-jensenshannon-ml.txt new file mode 100644 index 0000000000000000000000000000000000000000..8ed5b9653f4ed88e146d2d5dc5b032537b426f8b --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-jensenshannon-ml.txt @@ -0,0 +1 @@ +0.320369972991 0.338972466 0.308199372323 0.3452431902 0.310024768313 0.357115225615 0.311131096357 0.357391534414 0.329718053755 0.347365921475 0.335272625287 0.336451560653 0.33015370606 0.369628769749 0.344499490029 0.321622508707 0.345377707016 0.321007207534 0.350728979121 0.32809430086 0.30207071308 0.291663252492 0.30760470102 0.315976639534 0.308132467187 0.313014586878 0.310463895925 0.321091616502 0.290044394125 0.322213459935 0.315509196522 0.3331114403 0.281071919202 0.320854431887 0.332190658438 0.299342730178 0.313528775154 0.310049073937 0.288821516545 0.307662081954 0.328387688508 0.317185603454 0.332046170365 0.291912213887 0.37870970117 0.336080073379 0.304593343921 0.330138983604 0.355071759299 0.311946140607 0.302025400768 0.330940761586 0.351140062502 0.354772884287 0.272605322053 0.327957349848 0.28871110366 0.320821172951 0.340976919806 0.30757488831 0.320975346884 0.252776262329 0.314549731907 0.326876483 0.337684418756 0.296520013735 0.31493077245 0.327721982167 0.325802862624 0.341908184107 0.300481749419 0.312499767894 0.301061762121 0.27665157989 0.3082566692 0.287466396145 0.288313694552 0.296629698731 0.283556095025 0.322489360684 0.280765581604 0.297958166613 0.313189657041 0.303470399659 0.348652898212 0.331594734387 0.299446687464 0.339047458559 0.286979246044 0.316326095312 0.321618884109 0.330065896317 0.324500638067 0.328300795872 0.309002568222 0.262587468469 0.31974123777 0.286316182293 0.321162329165 0.328160620315 0.356618051635 0.289733970648 0.344507756538 0.301485561986 0.335785898715 0.322635066518 0.331480718646 0.297897604494 0.306942928189 0.350843442517 0.342585296966 0.341311053315 0.306780105123 0.313401804298 0.319978145568 0.302460397612 0.346105758567 0.312802351189 0.331552275517 0.321624157344 0.318798118247 0.301906095501 0.301585920138 0.314556178985 0.333215221158 0.306929663844 0.317083256901 0.309667679181 0.306529028004 0.30865993751 0.296031907986 0.28742420979 0.311584483038 0.319043629504 0.330278008622 0.314466433681 0.327937382021 0.296448162218 0.307033121385 0.296391953011 0.292691206116 0.297146209653 0.307929858983 0.291863681454 0.307300188104 0.306597817799 0.34718100163 0.317436210259 0.29952626739 0.330762834707 0.334951064852 0.323806678898 0.296203706701 0.33398466797 0.344931265559 0.293948734727 0.332764639313 0.272651853935 0.317324315923 0.300493570867 0.307008231016 0.333263322802 0.31390648462 0.332416491248 0.314766869708 0.321015549211 0.322909289307 0.356882966656 0.310596945263 0.343939748528 0.286269629586 0.33173459898 0.323848483719 0.305841388975 0.319266258167 0.34012363898 0.3443280395 0.353885654057 0.320544729867 0.353280499623 0.315621795536 0.312176062734 0.301562130879 0.312061680573 0.312642847966 0.326222109701 0.357417912858 0.313083593142 0.334033412713 0.295630506074 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-minkowski-3.2-ml-iris.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-minkowski-3.2-ml-iris.txt new file mode 100644 index 0000000000000000000000000000000000000000..dc396c8c16032b9657101532f7e08e6aa04b2aea --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-minkowski-3.2-ml-iris.txt @@ -0,0 +1 @@ + 5.0817745e-01 4.4535192e-01 5.6700421e-01 1.2418578e-01 4.8927739e-01 5.0180477e-01 1.4096146e-01 8.1242502e-01 4.1586001e-01 3.2586371e-01 3.2586371e-01 5.2942799e-01 8.6137722e-01 7.7039952e-01 9.7270522e-01 4.5581864e-01 1.0000000e-01 6.3861009e-01 3.0546431e-01 3.7427929e-01 2.5251796e-01 5.6700421e-01 3.8776762e-01 5.2942799e-01 5.0905001e-01 2.5651975e-01 1.2418578e-01 1.2418578e-01 4.5470518e-01 4.5470518e-01 3.2816937e-01 6.0181382e-01 7.3457830e-01 4.1586001e-01 3.2586371e-01 4.0147421e-01 4.1586001e-01 7.6752131e-01 1.2418578e-01 1.4096146e-01 1.2396136e+00 7.1462831e-01 4.1449626e-01 5.3588338e-01 5.2942799e-01 3.2352160e-01 5.2862779e-01 2.5251796e-01 2.0656129e-01 3.5031395e+00 3.2158090e+00 3.6682165e+00 2.7164367e+00 3.3288934e+00 3.1477087e+00 3.4033622e+00 2.0308266e+00 3.3209346e+00 2.5912926e+00 2.3257069e+00 2.8912179e+00 2.7273721e+00 3.3660466e+00 2.2876649e+00 3.1664710e+00 3.1642132e+00 2.7448172e+00 3.2474124e+00 2.5734684e+00 3.5025969e+00 2.6980573e+00 3.5983434e+00 3.3515288e+00 3.0113552e+00 3.1469325e+00 3.5526357e+00 3.7475562e+00 3.1812462e+00 2.1818668e+00 2.4927109e+00 2.3909738e+00 2.5729378e+00 3.7711998e+00 3.1620401e+00 3.1916270e+00 3.4478147e+00 3.1312883e+00 2.7541224e+00 2.6886547e+00 3.0483897e+00 3.2685282e+00 2.6752185e+00 2.0587064e+00 2.8619072e+00 2.8416143e+00 2.8554471e+00 2.9845926e+00 1.7697734e+00 2.7640668e+00 4.7690606e+00 3.8067806e+00 4.6866422e+00 4.2843668e+00 4.5417384e+00 5.4120246e+00 3.2161426e+00 5.0569442e+00 4.5165793e+00 4.9462324e+00 3.8595100e+00 4.0249346e+00 4.2787236e+00 3.7387507e+00 3.9160762e+00 4.0938708e+00 4.2028863e+00 5.5316487e+00 5.7297286e+00 3.6968486e+00 4.5074741e+00 3.6330985e+00 5.5146761e+00 3.6293227e+00 4.4495340e+00 4.7599229e+00 3.5255287e+00 3.6076762e+00 4.3339547e+00 4.5590471e+00 4.8997298e+00 5.2856169e+00 4.3511402e+00 3.7760534e+00 4.2460554e+00 5.0103780e+00 4.3808704e+00 4.1939019e+00 3.5087649e+00 4.2018804e+00 4.4140402e+00 3.9807996e+00 3.8067806e+00 4.6775324e+00 4.5250934e+00 4.0376133e+00 3.7473276e+00 3.9523060e+00 4.1709262e+00 3.7872951e+00 2.5251796e-01 3.0546431e-01 6.0060595e-01 9.5035453e-01 4.4535192e-01 4.0293660e-01 5.0090417e-01 1.4096146e-01 7.6752131e-01 4.1449626e-01 1.2418578e-01 6.2024833e-01 1.1845977e+00 1.4700179e+00 9.4309624e-01 5.0905001e-01 1.0003617e+00 8.0358695e-01 5.8851328e-01 7.0826681e-01 6.6384020e-01 4.3456114e-01 5.6700421e-01 2.0656129e-01 4.2667565e-01 5.2942799e-01 4.4417983e-01 2.8192292e-01 2.1269358e-01 5.7324170e-01 1.1056650e+00 1.2393677e+00 1.4096146e-01 2.5251796e-01 6.8961791e-01 1.4096146e-01 5.0090417e-01 4.1449626e-01 5.0270183e-01 7.3535471e-01 5.0905001e-01 5.7324170e-01 8.5690100e-01 1.2418578e-01 8.0587320e-01 3.2352160e-01 7.3496673e-01 3.0275928e-01 3.5601468e+00 3.2472699e+00 3.7137483e+00 2.6693888e+00 3.3563815e+00 3.1472333e+00 3.4276314e+00 1.9506288e+00 3.3563695e+00 2.5739370e+00 2.1870094e+00 2.9033014e+00 2.6860278e+00 3.3789262e+00 2.2884830e+00 3.2153154e+00 3.1667333e+00 2.7423060e+00 3.2269725e+00 2.5465772e+00 3.5123782e+00 2.7147889e+00 3.6030381e+00 3.3619470e+00 3.0427908e+00 3.1888219e+00 3.5910272e+00 3.7805671e+00 3.1921903e+00 2.1611020e+00 2.4491518e+00 2.3430978e+00 2.5700421e+00 3.7741357e+00 3.1615131e+00 3.2084454e+00 3.4884789e+00 3.1228939e+00 2.7575407e+00 2.6617768e+00 3.0343591e+00 3.2842184e+00 2.6656374e+00 1.9595652e+00 2.8539100e+00 2.8474367e+00 2.8585579e+00 3.0059712e+00 1.6867642e+00 2.7634340e+00 4.7806735e+00 3.8055585e+00 4.7194850e+00 4.2963997e+00 4.5579706e+00 5.4507801e+00 3.1945300e+00 5.0903533e+00 4.5297786e+00 4.9814379e+00 3.8841455e+00 4.0376849e+00 4.3069372e+00 3.7284750e+00 3.9173293e+00 4.1124749e+00 4.2221165e+00 5.5759608e+00 5.7633066e+00 3.6758942e+00 4.5370189e+00 3.6312130e+00 5.5536680e+00 3.6416405e+00 4.4736906e+00 4.7961103e+00 3.5380868e+00 3.6203213e+00 4.3467079e+00 4.5977693e+00 4.9380624e+00 5.3421274e+00 4.3637834e+00 3.7899304e+00 4.2477635e+00 5.0602038e+00 4.3953045e+00 4.2110583e+00 3.5192753e+00 4.2358121e+00 4.4378207e+00 4.0189525e+00 3.8055585e+00 4.7017335e+00 4.5483787e+00 4.0656879e+00 3.7516222e+00 3.9742971e+00 4.1845313e+00 3.7939847e+00 2.1269358e-01 4.4535192e-01 8.9366705e-01 2.1845981e-01 3.4378533e-01 3.7427929e-01 2.5651975e-01 7.7039952e-01 3.2586371e-01 2.1845981e-01 4.2667565e-01 1.2113327e+00 1.3801284e+00 8.7175869e-01 4.4651726e-01 1.0719360e+00 6.5223271e-01 7.3813096e-01 5.7867728e-01 4.4535192e-01 5.2655962e-01 6.0611244e-01 3.8776762e-01 4.0176783e-01 5.3588338e-01 5.0905001e-01 3.0000000e-01 3.0546431e-01 7.1169738e-01 9.4309624e-01 1.1327825e+00 2.5651975e-01 3.0275928e-01 8.1067767e-01 2.5651975e-01 3.2352160e-01 4.2538717e-01 3.7427929e-01 9.0252542e-01 3.0000000e-01 5.1138698e-01 7.7869083e-01 2.1845981e-01 6.6384020e-01 1.2418578e-01 6.9325418e-01 3.0546431e-01 3.7098973e+00 3.3770904e+00 3.8553941e+00 2.7868575e+00 3.4895316e+00 3.2571492e+00 3.5499573e+00 2.0646687e+00 3.4944845e+00 2.6743800e+00 2.3196869e+00 3.0181476e+00 2.8270253e+00 3.4973911e+00 2.3997585e+00 3.3600102e+00 3.2716172e+00 2.8619072e+00 3.3597438e+00 2.6649106e+00 3.6203213e+00 2.8440609e+00 3.7280682e+00 3.4822008e+00 3.1786890e+00 3.3296038e+00 3.7325066e+00 3.9121945e+00 3.3084060e+00 2.2888897e+00 2.5683989e+00 2.4649412e+00 2.6906230e+00 3.8866112e+00 3.2625043e+00 3.3219248e+00 3.6264668e+00 3.2609948e+00 2.8656468e+00 2.7738624e+00 3.1430282e+00 3.4033622e+00 2.7865812e+00 2.0797392e+00 2.9638836e+00 2.9589097e+00 2.9695568e+00 3.1337459e+00 1.7991433e+00 2.8758936e+00 4.8875515e+00 3.9111857e+00 4.8490379e+00 4.4107143e+00 4.6725771e+00 5.5854254e+00 3.2933477e+00 5.2226262e+00 4.6541348e+00 5.1068487e+00 4.0049607e+00 4.1564977e+00 4.4321573e+00 3.8331006e+00 4.0161098e+00 4.2255639e+00 4.3417782e+00 5.7091264e+00 5.8970064e+00 3.7961619e+00 4.6611065e+00 3.7313856e+00 5.6903014e+00 3.7618406e+00 4.5942943e+00 4.9290197e+00 3.6553612e+00 3.7333492e+00 4.4613366e+00 4.7342792e+00 5.0749049e+00 5.4844039e+00 4.4774673e+00 3.9102500e+00 4.3611782e+00 5.2016658e+00 4.5034762e+00 4.3281161e+00 3.6300436e+00 4.3648112e+00 4.5562166e+00 4.1482002e+00 3.9111857e+00 4.8218416e+00 4.6648403e+00 4.1879434e+00 3.8717400e+00 4.0945154e+00 4.2919258e+00 3.9013483e+00 5.6700421e-01 9.9714776e-01 3.0546431e-01 4.4417983e-01 2.5251796e-01 3.0275928e-01 8.8835966e-01 3.2586371e-01 2.1845981e-01 4.4651726e-01 1.3360558e+00 1.5022608e+00 9.9714776e-01 5.6769031e-01 1.1765359e+00 7.6752131e-01 8.1354181e-01 6.9325418e-01 6.2092891e-01 5.4292906e-01 4.5470518e-01 4.0293660e-01 4.5581864e-01 6.4704320e-01 6.2024833e-01 1.4096146e-01 2.0656129e-01 8.1354181e-01 1.0574300e+00 1.2554784e+00 3.0275928e-01 4.4535192e-01 9.2264612e-01 3.0275928e-01 2.5251796e-01 5.2862779e-01 5.0592043e-01 8.0358695e-01 2.5251796e-01 5.6454040e-01 7.9878917e-01 2.1845981e-01 7.6752131e-01 1.2418578e-01 8.1242502e-01 4.1449626e-01 3.5875094e+00 3.2277825e+00 3.7190120e+00 2.6019240e+00 3.3414931e+00 3.0741797e+00 3.3904673e+00 1.8683030e+00 3.3506325e+00 2.4892190e+00 2.1209506e+00 2.8530088e+00 2.6606291e+00 3.3264150e+00 2.2345869e+00 3.2325480e+00 3.0894572e+00 2.6859989e+00 3.1954750e+00 2.4836725e+00 3.4467337e+00 2.6928468e+00 3.5602810e+00 3.3090659e+00 3.0346426e+00 3.1953687e+00 3.5930845e+00 3.7635112e+00 3.1392617e+00 2.1242643e+00 2.3839455e+00 2.2806773e+00 2.5225548e+00 3.7070070e+00 3.0760590e+00 3.1551922e+00 3.4865435e+00 3.1033781e+00 2.6867856e+00 2.5906376e+00 2.9536363e+00 3.2348458e+00 2.6148507e+00 1.8841403e+00 2.7819255e+00 2.7801917e+00 2.7920574e+00 2.9774862e+00 1.6195190e+00 2.7001131e+00 4.7151191e+00 3.7310738e+00 4.6963107e+00 4.2348119e+00 4.5036643e+00 5.4345951e+00 3.1040223e+00 5.0660245e+00 4.4858951e+00 4.9576471e+00 3.8485743e+00 3.9894963e+00 4.2781102e+00 3.6535208e+00 3.8473084e+00 4.0656969e+00 4.1736133e+00 5.5611269e+00 5.7439963e+00 3.6142694e+00 4.5082936e+00 3.5527533e+00 5.5400450e+00 3.5988819e+00 4.4321573e+00 4.7754556e+00 3.4913787e+00 3.5638529e+00 4.2915574e+00 4.5844335e+00 4.9269527e+00 5.3501611e+00 4.3091163e+00 3.7395252e+00 4.1763853e+00 5.0687940e+00 4.3363292e+00 4.1568278e+00 3.4594086e+00 4.2175903e+00 4.4004449e+00 4.0139427e+00 3.7310738e+00 4.6611132e+00 4.5083524e+00 4.0415593e+00 3.7070350e+00 3.9354060e+00 4.1243443e+00 3.7225506e+00 4.8927739e-01 4.1449626e-01 2.0656129e-01 8.1242502e-01 5.0270183e-01 4.0293660e-01 2.8192292e-01 6.0611244e-01 8.2305664e-01 8.2899253e-01 9.3824087e-01 4.5581864e-01 1.4096146e-01 7.1840099e-01 2.1845981e-01 4.5470518e-01 2.1845981e-01 4.9674312e-01 4.2418962e-01 5.1607523e-01 6.0551856e-01 2.8192292e-01 2.1269358e-01 2.4837156e-01 4.5470518e-01 5.1607523e-01 4.2667565e-01 5.0991930e-01 6.8917100e-01 5.0270183e-01 4.1312257e-01 5.0180477e-01 5.0270183e-01 7.4549115e-01 2.1269358e-01 1.4096146e-01 1.3190071e+00 6.4755655e-01 4.1449626e-01 5.1691876e-01 6.0611244e-01 2.5251796e-01 4.9674312e-01 3.0546431e-01 3.0000000e-01 3.5310961e+00 3.2313174e+00 3.6912396e+00 2.7363446e+00 3.3486156e+00 3.1550780e+00 3.4146950e+00 2.0587064e+00 3.3422688e+00 2.6000813e+00 2.3658814e+00 2.9005672e+00 2.7581254e+00 3.3764180e+00 2.2982662e+00 3.1914715e+00 3.1684808e+00 2.7581145e+00 3.2719146e+00 2.5906376e+00 3.5076679e+00 2.7164648e+00 3.6146980e+00 3.3629944e+00 3.0317688e+00 3.1699749e+00 3.5767944e+00 3.7653940e+00 3.1912695e+00 2.2046610e+00 2.5131017e+00 2.4132939e+00 2.5882494e+00 3.7797776e+00 3.1649733e+00 3.1986968e+00 3.4685882e+00 3.1575873e+00 2.7599092e+00 2.7031874e+00 3.0575551e+00 3.2787144e+00 2.6914804e+00 2.0914773e+00 2.8714673e+00 2.8482104e+00 2.8631525e+00 3.0002861e+00 1.8009624e+00 2.7738624e+00 4.7744685e+00 3.8132783e+00 4.7036953e+00 4.2925903e+00 4.5507995e+00 5.4317036e+00 3.2245243e+00 5.0748136e+00 4.5314818e+00 4.9621679e+00 3.8715927e+00 4.0372136e+00 4.2937599e+00 3.7469906e+00 3.9213497e+00 4.1030149e+00 4.2136261e+00 5.5512721e+00 5.7499082e+00 3.7127205e+00 4.5218897e+00 3.6377830e+00 5.5357771e+00 3.6429670e+00 4.4609633e+00 4.7775824e+00 3.5373240e+00 3.6158814e+00 4.3437318e+00 4.5790474e+00 4.9211035e+00 5.3110568e+00 4.3608329e+00 3.7876656e+00 4.2543813e+00 5.0356467e+00 4.3872625e+00 4.2028863e+00 3.5161021e+00 4.2189979e+00 4.4261470e+00 4.0000622e+00 3.8132783e+00 4.6893387e+00 4.5361087e+00 4.0527696e+00 3.7622948e+00 3.9645936e+00 4.1768667e+00 3.7924679e+00 8.6137722e-01 5.7867728e-01 1.2470767e+00 8.6361309e-01 2.8192292e-01 6.9369532e-01 9.8450810e-01 1.2949422e+00 5.7324170e-01 5.3588338e-01 4.0000000e-01 4.8135521e-01 3.0546431e-01 3.2816937e-01 5.0817745e-01 3.4378533e-01 9.4558103e-01 6.2024833e-01 6.9728513e-01 9.2288144e-01 5.6700421e-01 4.3691963e-01 5.4292906e-01 8.7202528e-01 8.9095811e-01 5.0817745e-01 3.6171588e-01 3.8934542e-01 8.6361309e-01 7.9878917e-01 5.0592043e-01 8.6361309e-01 1.1959482e+00 5.4292906e-01 5.6454040e-01 1.6807352e+00 1.1055064e+00 5.0592043e-01 3.2586371e-01 9.7779835e-01 3.2816937e-01 9.4558103e-01 2.8507955e-01 6.6827038e-01 3.1533911e+00 2.8840079e+00 3.3274872e+00 2.5335921e+00 3.0169509e+00 2.8661222e+00 3.0732956e+00 1.9492232e+00 3.0013391e+00 2.3437032e+00 2.3116343e+00 2.5873149e+00 2.5591371e+00 3.0631725e+00 2.0220740e+00 2.8270253e+00 2.8656468e+00 2.4892190e+00 3.0178921e+00 2.3656538e+00 3.1846482e+00 2.4132559e+00 3.3163294e+00 3.0590735e+00 2.6993871e+00 2.8174914e+00 3.2310326e+00 3.4162231e+00 2.8802219e+00 1.9932786e+00 2.3173648e+00 2.2314118e+00 2.3212593e+00 3.4779999e+00 2.8654680e+00 2.8662571e+00 3.1113805e+00 2.8927401e+00 2.4634131e+00 2.4685230e+00 2.7948819e+00 2.9596963e+00 2.4341346e+00 2.0039447e+00 2.6000813e+00 2.5498770e+00 2.5700421e+00 2.6813098e+00 1.7123398e+00 2.4913669e+00 4.4418755e+00 3.5123791e+00 4.3488707e+00 3.9713081e+00 4.2172545e+00 5.0700045e+00 2.9631582e+00 4.7239900e+00 4.2113881e+00 4.5979409e+00 3.5255287e+00 3.7162377e+00 3.9448212e+00 3.4598280e+00 3.6097419e+00 3.7620043e+00 3.8810240e+00 5.1822310e+00 5.3953096e+00 3.4508156e+00 4.1665786e+00 3.3353616e+00 5.1763300e+00 3.3260356e+00 4.1143832e+00 4.4201622e+00 3.2188998e+00 3.2929599e+00 4.0183758e+00 4.2229849e+00 4.5637045e+00 4.9290256e+00 4.0343724e+00 3.4708900e+00 3.9559935e+00 4.6576736e+00 4.0502252e+00 3.8718131e+00 3.1963475e+00 3.8610636e+00 4.0785553e+00 3.6345765e+00 3.5123791e+00 4.3416284e+00 4.1864302e+00 3.7018916e+00 3.4568305e+00 3.6254423e+00 3.8415026e+00 3.4775621e+00 4.0293660e-01 5.0905001e-01 3.8934542e-01 8.1130291e-01 2.5251796e-01 4.2538717e-01 4.8927739e-01 1.2406194e+00 1.3074132e+00 8.5233811e-01 5.0090417e-01 1.1185330e+00 5.6700421e-01 8.1099042e-01 5.3022554e-01 4.1449626e-01 5.3665999e-01 5.0905001e-01 5.0592043e-01 4.1449626e-01 6.0181382e-01 6.0060595e-01 2.5651975e-01 3.4583729e-01 8.0064372e-01 8.1558458e-01 1.0597541e+00 3.8934542e-01 4.2667565e-01 9.0074515e-01 3.8934542e-01 4.1586001e-01 5.0180477e-01 4.0293660e-01 1.1003197e+00 2.5651975e-01 4.5581864e-01 6.6539428e-01 4.1312257e-01 5.7324170e-01 2.0656129e-01 7.1504098e-01 4.0293660e-01 3.6583368e+00 3.3018939e+00 3.7934214e+00 2.7118627e+00 3.4196168e+00 3.1646752e+00 3.4663954e+00 1.9965608e+00 3.4302944e+00 2.5753574e+00 2.2837561e+00 2.9283888e+00 2.7788099e+00 3.4116298e+00 2.3101107e+00 3.3028359e+00 3.1719381e+00 2.7826178e+00 3.2957091e+00 2.5882494e+00 3.5217244e+00 2.7724782e+00 3.6509512e+00 3.3998935e+00 3.1126354e+00 3.2681313e+00 3.6719821e+00 3.8384263e+00 3.2202056e+00 2.2240476e+00 2.4960474e+00 2.3970928e+00 2.6119950e+00 3.7951491e+00 3.1592993e+00 3.2300555e+00 3.5604418e+00 3.2025128e+00 2.7701355e+00 2.6892823e+00 3.0524247e+00 3.3177721e+00 2.7092568e+00 2.0227167e+00 2.8731220e+00 2.8671099e+00 2.8775912e+00 3.0586720e+00 1.7332099e+00 2.7865812e+00 4.7866828e+00 3.8123695e+00 4.7714708e+00 4.3189924e+00 4.5796358e+00 5.5132325e+00 3.1921277e+00 5.1489022e+00 4.5737586e+00 5.0249531e+00 3.9185849e+00 4.0697987e+00 4.3502657e+00 3.7349501e+00 3.9102370e+00 4.1311343e+00 4.2548570e+00 5.6362307e+00 5.8240252e+00 3.7174048e+00 4.5773480e+00 3.6270581e+00 5.6209145e+00 3.6774027e+00 4.5072397e+00 4.8555167e+00 3.5675580e+00 3.6401392e+00 4.3693804e+00 4.6657186e+00 5.0062061e+00 5.4227201e+00 4.3844239e+00 3.8261182e+00 4.2718480e+00 5.1373047e+00 4.4043123e+00 4.2383633e+00 3.5347392e+00 4.2868650e+00 4.4668117e+00 4.0716645e+00 3.8123695e+00 4.7338066e+00 4.5734052e+00 4.1036179e+00 3.7882079e+00 4.0078491e+00 4.1922661e+00 3.8027591e+00 6.8961791e-01 3.0546431e-01 4.4417983e-01 2.0656129e-01 4.1586001e-01 7.6625946e-01 8.9687438e-01 1.0919712e+00 5.7867728e-01 1.5422108e-01 7.3851529e-01 4.0293660e-01 4.1312257e-01 3.2586371e-01 5.7257017e-01 3.2816937e-01 4.1312257e-01 4.0147421e-01 2.0656129e-01 2.0656129e-01 2.0656129e-01 3.2586371e-01 3.2586371e-01 4.1312257e-01 7.0437330e-01 8.5205778e-01 3.0546431e-01 3.2352160e-01 5.0905001e-01 3.0546431e-01 6.5172743e-01 1.0000000e-01 2.1269358e-01 1.1283882e+00 6.1092863e-01 4.0293660e-01 5.0592043e-01 4.1586001e-01 4.0293660e-01 4.1449626e-01 3.7255734e-01 1.2418578e-01 3.4445326e+00 3.1392617e+00 3.6011035e+00 2.6118700e+00 3.2516941e+00 3.0511838e+00 3.3218097e+00 1.9189245e+00 3.2468925e+00 2.4924452e+00 2.2081024e+00 2.8038661e+00 2.6291264e+00 3.2767369e+00 2.1964719e+00 3.1025274e+00 3.0696611e+00 2.6485861e+00 3.1554034e+00 2.4715204e+00 3.4135983e+00 2.6151245e+00 3.5092032e+00 3.2604423e+00 2.9354140e+00 3.0782101e+00 3.4818889e+00 3.6726568e+00 3.0922811e+00 2.0843471e+00 2.3874354e+00 2.2845234e+00 2.4794505e+00 3.6775470e+00 3.0659000e+00 3.1055388e+00 3.3775462e+00 3.0430948e+00 2.6597612e+00 2.5873149e+00 2.9471553e+00 3.1807044e+00 2.5795723e+00 1.9450499e+00 2.7640668e+00 2.7473221e+00 2.7611864e+00 2.9015702e+00 1.6626642e+00 2.6693888e+00 4.6823704e+00 3.7130994e+00 4.6117428e+00 4.1946425e+00 4.4565357e+00 5.3399939e+00 3.1168466e+00 4.9805386e+00 4.4303862e+00 4.8738189e+00 3.7806643e+00 3.9387918e+00 4.2018804e+00 3.6441274e+00 3.8290120e+00 4.0132700e+00 4.1177139e+00 5.4615788e+00 5.6559440e+00 3.5983434e+00 4.4321573e+00 3.5405803e+00 5.4429455e+00 3.5441556e+00 4.3687483e+00 4.6853394e+00 3.4399664e+00 3.5203203e+00 4.2473048e+00 4.4861009e+00 4.8281381e+00 5.2242271e+00 4.2652659e+00 3.6876909e+00 4.1503255e+00 4.9488209e+00 4.2966585e+00 4.1071698e+00 3.4205830e+00 4.1292490e+00 4.3363292e+00 3.9150359e+00 3.7130994e+00 4.5977729e+00 4.4473292e+00 3.9643224e+00 3.6603913e+00 3.8715927e+00 4.0861975e+00 3.6954796e+00 5.0991930e-01 1.1327825e+00 5.7257017e-01 4.0293660e-01 3.0811765e-01 1.5771666e+00 1.7488874e+00 1.2431040e+00 8.1273630e-01 1.4170618e+00 1.0106392e+00 1.0389435e+00 9.3824087e-01 7.3813096e-01 7.5976039e-01 6.6491075e-01 6.0611244e-01 6.9728513e-01 8.8861541e-01 8.5177726e-01 3.8776762e-01 4.2538717e-01 1.0346741e+00 1.2943100e+00 1.5015203e+00 5.0991930e-01 6.2482915e-01 1.1473003e+00 5.0991930e-01 1.2418578e-01 7.6752131e-01 7.4586719e-01 6.0181382e-01 3.0275928e-01 7.7869083e-01 1.0440187e+00 4.0293660e-01 1.0120221e+00 3.2352160e-01 1.0597541e+00 6.4704320e-01 3.7504939e+00 3.3717768e+00 3.8731169e+00 2.7062054e+00 3.4865562e+00 3.1921903e+00 3.5262546e+00 1.9522524e+00 3.5018009e+00 2.5914913e+00 2.1818668e+00 2.9807120e+00 2.7874290e+00 3.4557351e+00 2.3604042e+00 3.3915488e+00 3.2027420e+00 2.8150728e+00 3.3206640e+00 2.6018930e+00 3.5642457e+00 2.8360166e+00 3.6902583e+00 3.4394878e+00 3.1847477e+00 3.3503379e+00 3.7461474e+00 3.9068076e+00 3.2666666e+00 2.2590074e+00 2.4950353e+00 2.3935209e+00 2.6534332e+00 3.8259590e+00 3.1834936e+00 3.2834077e+00 3.6377049e+00 3.2390016e+00 2.8060305e+00 2.7012392e+00 3.0647279e+00 3.3658240e+00 2.7423171e+00 1.9645331e+00 2.8984764e+00 2.9033203e+00 2.9139413e+00 3.1189900e+00 1.7118795e+00 2.8228127e+00 4.8290847e+00 3.8416142e+00 4.8350745e+00 4.3569606e+00 4.6261788e+00 5.5774554e+00 3.1958228e+00 5.2067803e+00 4.6153241e+00 5.0947934e+00 3.9803199e+00 4.1159553e+00 4.4131159e+00 3.7587872e+00 3.9513472e+00 4.1881498e+00 4.3024754e+00 5.7071195e+00 5.8839539e+00 3.7280682e+00 4.6419531e+00 3.6578722e+00 5.6843788e+00 3.7276068e+00 4.5625120e+00 4.9179194e+00 3.6182608e+00 3.6866535e+00 4.4136707e+00 4.7307689e+00 5.0723886e+00 5.5062533e+00 4.4301849e+00 3.8690719e+00 4.2943891e+00 5.2192815e+00 4.4536259e+00 4.2828634e+00 3.5797958e+00 4.3570079e+00 4.5278761e+00 4.1542558e+00 3.8416142e+00 4.7899951e+00 4.6341170e+00 4.1740602e+00 3.8316735e+00 4.0656969e+00 4.2413113e+00 3.8376713e+00 6.8961791e-01 3.0811765e-01 1.4096146e-01 6.4755655e-01 1.1229906e+00 1.3835747e+00 8.6361309e-01 4.2667565e-01 9.4009473e-01 7.0784540e-01 5.3665999e-01 6.2482915e-01 6.3977563e-01 4.3691963e-01 4.4651726e-01 1.5422108e-01 3.7598397e-01 4.4535192e-01 3.7598397e-01 2.1845981e-01 1.4096146e-01 5.5419992e-01 1.0065841e+00 1.1474460e+00 0.0000000e+00 3.0811765e-01 6.5223271e-01 0.0000000e+00 5.0991930e-01 3.2586371e-01 4.2667565e-01 8.3172002e-01 5.0991930e-01 5.6769031e-01 7.5082357e-01 2.1845981e-01 7.0479928e-01 3.0811765e-01 6.4755655e-01 2.1845981e-01 3.4865562e+00 3.1726595e+00 3.6377960e+00 2.5987470e+00 3.2814045e+00 3.0627375e+00 3.3515846e+00 1.8841865e+00 3.2769379e+00 2.5038079e+00 2.1311468e+00 2.8311678e+00 2.6104387e+00 3.2962520e+00 2.2214438e+00 3.1433122e+00 3.0878634e+00 2.6552472e+00 3.1570103e+00 2.4668912e+00 3.4394878e+00 2.6411293e+00 3.5233648e+00 3.2747247e+00 2.9659871e+00 3.1154783e+00 3.5134741e+00 3.7059620e+00 3.1148696e+00 2.0851901e+00 2.3731428e+00 2.2655571e+00 2.4927109e+00 3.6920087e+00 3.0823446e+00 3.1337459e+00 3.4135200e+00 3.0481703e+00 2.6780487e+00 2.5874301e+00 2.9489507e+00 3.2027420e+00 2.5873149e+00 1.8973383e+00 2.7738355e+00 2.7632614e+00 2.7778954e+00 2.9269923e+00 1.6390769e+00 2.6848587e+00 4.7106706e+00 3.7313856e+00 4.6446321e+00 4.2142736e+00 4.4836580e+00 5.3716885e+00 3.1250284e+00 5.0074019e+00 4.4485220e+00 4.9128219e+00 3.8150636e+00 3.9624529e+00 4.2358121e+00 3.6602286e+00 3.8605980e+00 4.0488387e+00 4.1418643e+00 5.4970002e+00 5.6855224e+00 3.5964347e+00 4.4685630e+00 3.5634461e+00 5.4730406e+00 3.5693950e+00 4.3989089e+00 4.7150659e+00 3.4668130e+00 3.5464993e+00 4.2723380e+00 4.5155386e+00 4.8594290e+00 5.2647079e+00 4.2921213e+00 3.7064459e+00 4.1581964e+00 4.9913682e+00 4.3286007e+00 4.1303097e+00 3.4468286e+00 4.1669742e+00 4.3729308e+00 3.9624170e+00 3.7313856e+00 4.6297577e+00 4.4844827e+00 4.0056359e+00 3.6817961e+00 3.9035218e+00 4.1179678e+00 3.7164366e+00 6.2024833e-01 8.1304731e-01 1.1868139e+00 4.8036801e-01 7.1799256e-01 2.8192292e-01 3.2816937e-01 3.2816937e-01 3.0546431e-01 3.2352160e-01 3.2352160e-01 8.5205778e-01 4.8927739e-01 6.6384020e-01 7.3496673e-01 4.5581864e-01 2.4837156e-01 3.2586371e-01 7.6752131e-01 7.4549115e-01 3.2352160e-01 4.1449626e-01 5.0180477e-01 6.8961791e-01 5.8851328e-01 2.5251796e-01 6.8961791e-01 1.0919712e+00 3.7255734e-01 4.2667565e-01 1.4993782e+00 1.0344911e+00 5.0592043e-01 4.5581864e-01 8.1304731e-01 3.0546431e-01 8.5205778e-01 1.0000000e-01 4.9766035e-01 3.3472053e+00 3.0922811e+00 3.5254266e+00 2.6661987e+00 3.2094276e+00 3.0570957e+00 3.2869053e+00 2.0190980e+00 3.1913594e+00 2.5206151e+00 2.3403819e+00 2.7928582e+00 2.6680945e+00 3.2615924e+00 2.2070201e+00 3.0233425e+00 3.0716969e+00 2.6575076e+00 3.1694367e+00 2.5088543e+00 3.4030318e+00 2.5954147e+00 3.4988409e+00 3.2483608e+00 2.8891737e+00 3.0123702e+00 3.4182420e+00 3.6203759e+00 3.0811775e+00 2.1190324e+00 2.4416796e+00 2.3440712e+00 2.4897570e+00 3.6753309e+00 3.0715435e+00 3.0851463e+00 3.3123070e+00 3.0424689e+00 2.6625505e+00 2.6241824e+00 2.9689697e+00 3.1616811e+00 2.5961850e+00 2.0559262e+00 2.7803619e+00 2.7462372e+00 2.7639489e+00 2.8736288e+00 1.7674365e+00 2.6773131e+00 4.6660957e+00 3.7173526e+00 4.5567672e+00 4.1782968e+00 4.4326194e+00 5.2720689e+00 3.1469325e+00 4.9232255e+00 4.4057732e+00 4.8164157e+00 3.7433882e+00 3.9194796e+00 4.1567419e+00 3.6582432e+00 3.8303544e+00 3.9861488e+00 4.0892044e+00 5.3882212e+00 5.5946413e+00 3.6180819e+00 4.3839191e+00 3.5469476e+00 5.3734444e+00 3.5262672e+00 4.3306501e+00 4.6237863e+00 3.4237160e+00 3.5051302e+00 4.2288456e+00 4.4201622e+00 4.7609637e+00 5.1280035e+00 4.2469785e+00 3.6684143e+00 4.1480002e+00 4.8602572e+00 4.2765700e+00 4.0824098e+00 3.4092877e+00 4.0737132e+00 4.2991233e+00 3.8524190e+00 3.7173526e+00 4.5590471e+00 4.4107160e+00 3.9202843e+00 3.6509512e+00 3.8388884e+00 4.0680120e+00 3.6894983e+00 4.1449626e-01 6.6539428e-01 1.0717668e+00 1.1847335e+00 7.0776547e-01 3.2816937e-01 9.2095040e-01 4.4651726e-01 6.0060595e-01 3.8934542e-01 6.1092863e-01 3.7598397e-01 3.0000000e-01 4.1312257e-01 2.4837156e-01 4.0293660e-01 4.1312257e-01 2.0656129e-01 3.0000000e-01 6.0611244e-01 7.3535471e-01 9.3801395e-01 3.0811765e-01 4.2538717e-01 7.1462831e-01 3.0811765e-01 5.2574978e-01 3.0275928e-01 3.2816937e-01 1.1107977e+00 4.5470518e-01 4.1449626e-01 4.8927739e-01 4.1449626e-01 4.4417983e-01 2.8192292e-01 5.2942799e-01 2.5251796e-01 3.4297053e+00 3.0906838e+00 3.5704156e+00 2.5301680e+00 3.2062204e+00 2.9663489e+00 3.2615889e+00 1.8330979e+00 3.2074600e+00 2.4030878e+00 2.1292724e+00 2.7344480e+00 2.5716369e+00 3.2053511e+00 2.1242643e+00 3.0798277e+00 2.9831836e+00 2.5729378e+00 3.0964590e+00 2.3917863e+00 3.3353616e+00 2.5635110e+00 3.4441347e+00 3.1882407e+00 2.8938821e+00 3.0477086e+00 3.4484194e+00 3.6265826e+00 3.0209783e+00 2.0203134e+00 2.3063579e+00 2.2046610e+00 2.4100833e+00 3.5972040e+00 2.9748436e+00 3.0349291e+00 3.3414931e+00 2.9918962e+00 2.5764694e+00 2.5038051e+00 2.8573838e+00 3.1113597e+00 2.5079404e+00 1.8623849e+00 2.6799601e+00 2.6656374e+00 2.6804452e+00 2.8458006e+00 1.5870088e+00 2.5906376e+00 4.6056614e+00 3.6293396e+00 4.5625120e+00 4.1184849e+00 4.3862724e+00 5.2957861e+00 3.0253131e+00 4.9300368e+00 4.3656957e+00 4.8256905e+00 3.7228356e+00 3.8717400e+00 4.1487889e+00 3.5605424e+00 3.7509165e+00 3.9489970e+00 4.0502806e+00 5.4193574e+00 5.6096505e+00 3.5201263e+00 4.3797165e+00 3.4555095e+00 5.4004015e+00 3.4805320e+00 4.3069452e+00 4.6373516e+00 3.3738930e+00 3.4478147e+00 4.1762321e+00 4.4428877e+00 4.7870294e+00 5.1982218e+00 4.1948678e+00 3.6180819e+00 4.0668114e+00 4.9227056e+00 4.2245318e+00 4.0358897e+00 3.3459883e+00 4.0835979e+00 4.2783731e+00 3.8797354e+00 3.6293396e+00 4.5370189e+00 4.3879553e+00 3.9155334e+00 3.5955337e+00 3.8113970e+00 4.0131848e+00 3.6132595e+00 5.2862779e-01 1.2431040e+00 1.5013525e+00 9.7779835e-01 5.3588338e-01 1.0669582e+00 8.1385214e-01 6.6432544e-01 7.2823007e-01 6.5223271e-01 5.1138698e-01 5.6700421e-01 2.5251796e-01 4.6472023e-01 5.6769031e-01 4.9766035e-01 2.5651975e-01 2.1269358e-01 6.6432544e-01 1.1134787e+00 1.2632199e+00 1.4096146e-01 2.8507955e-01 7.6787403e-01 1.4096146e-01 4.0293660e-01 4.4651726e-01 5.1691876e-01 7.1840099e-01 4.1586001e-01 6.3108414e-01 8.7021234e-01 2.0000000e-01 8.1385214e-01 2.5251796e-01 7.6787403e-01 3.2586371e-01 3.6025735e+00 3.2810515e+00 3.7511944e+00 2.6894009e+00 3.3904673e+00 3.1636869e+00 3.4574937e+00 1.9666356e+00 3.3893691e+00 2.5954173e+00 2.1997395e+00 2.9322283e+00 2.7092568e+00 3.4012145e+00 2.3186758e+00 3.2568914e+00 3.1861493e+00 2.7595194e+00 3.2561045e+00 2.5646808e+00 3.5381764e+00 2.7476411e+00 3.6278993e+00 3.3809159e+00 3.0768226e+00 3.2277675e+00 3.6265617e+00 3.8150532e+00 3.2176230e+00 2.1864840e+00 2.4668912e+00 2.3596992e+00 2.5949561e+00 3.7935487e+00 3.1789378e+00 3.2360886e+00 3.5252258e+00 3.1522058e+00 2.7777040e+00 2.6819136e+00 3.0473722e+00 3.3079290e+00 2.6886547e+00 1.9757309e+00 2.8726212e+00 2.8654680e+00 2.8788483e+00 3.0349462e+00 1.7160413e+00 2.7852734e+00 4.8087107e+00 3.8282466e+00 4.7531334e+00 4.3176393e+00 4.5857287e+00 5.4831923e+00 3.2147850e+00 5.1185883e+00 4.5544260e+00 5.0194259e+00 3.9185849e+00 4.0655452e+00 4.3416283e+00 3.7535680e+00 3.9509795e+00 4.1478442e+00 4.2472736e+00 5.6096505e+00 5.7957776e+00 3.6945993e+00 4.5734622e+00 3.6568202e+00 5.5854254e+00 3.6720840e+00 4.5038991e+00 4.8262859e+00 3.5684917e+00 3.6474985e+00 4.3740189e+00 4.6282931e+00 4.9713928e+00 5.3806679e+00 4.3928114e+00 3.8121990e+00 4.2612863e+00 5.1032991e+00 4.4267055e+00 4.2347444e+00 3.5464871e+00 4.2738510e+00 4.4745238e+00 4.0663411e+00 3.8282466e+00 4.7338066e+00 4.5852690e+00 4.1075310e+00 3.7823897e+00 4.0070636e+00 4.2156933e+00 3.8157950e+00 1.6177449e+00 1.7454671e+00 1.2604558e+00 8.6361309e-01 1.4955532e+00 1.0118409e+00 1.1594648e+00 9.6204649e-01 6.2081167e-01 9.1750357e-01 8.7504951e-01 7.6752131e-01 8.0660588e-01 9.5965467e-01 9.2859317e-01 5.7324170e-01 6.2205176e-01 1.1313840e+00 1.2653669e+00 1.4930627e+00 6.4755655e-01 7.0479928e-01 1.2236003e+00 6.4755655e-01 2.1269358e-01 8.5105559e-01 7.7360126e-01 7.1169738e-01 2.5651975e-01 8.7229670e-01 1.1327578e+00 5.3588338e-01 1.0269295e+00 3.8934542e-01 1.1042097e+00 7.2823007e-01 4.0317004e+00 3.6659830e+00 4.1618561e+00 3.0123702e+00 3.7804276e+00 3.4970843e+00 3.8244351e+00 2.2591077e+00 3.7930789e+00 2.8953397e+00 2.4889124e+00 3.2809188e+00 3.0866488e+00 3.7578933e+00 2.6595288e+00 3.6754272e+00 3.5073435e+00 3.1173742e+00 3.6212723e+00 2.9065572e+00 3.8667462e+00 3.1302383e+00 3.9918403e+00 3.7416229e+00 3.4760444e+00 3.6375992e+00 4.0358101e+00 4.2016915e+00 3.5683934e+00 2.5569968e+00 2.8007817e+00 2.6989368e+00 2.9539253e+00 4.1306024e+00 3.4882801e+00 3.5831257e+00 3.9280671e+00 3.5362697e+00 3.1099883e+00 3.0065416e+00 3.3706887e+00 3.6672620e+00 3.0442126e+00 2.2719663e+00 3.2032390e+00 3.2071637e+00 3.2176230e+00 3.4155491e+00 2.0139971e+00 3.1260028e+00 5.1310217e+00 4.1456639e+00 5.1323742e+00 4.6609614e+00 4.9284761e+00 5.8739676e+00 3.4984873e+00 5.5048216e+00 4.9175276e+00 5.3898806e+00 4.2781762e+00 4.4176533e+00 4.7107211e+00 4.0621414e+00 4.2494597e+00 4.4865569e+00 4.6045396e+00 6.0012333e+00 6.1816086e+00 4.0339598e+00 4.9390284e+00 3.9601358e+00 5.9803696e+00 4.0277694e+00 4.8626276e+00 5.2147981e+00 3.9185849e+00 3.9887029e+00 4.7161140e+00 5.0257341e+00 5.3673499e+00 5.7939320e+00 4.7320534e+00 4.1713411e+00 4.5995433e+00 5.5085511e+00 4.7536729e+00 4.5857356e+00 3.8819510e+00 4.6519178e+00 4.8256399e+00 4.4430890e+00 4.1456639e+00 5.0898961e+00 4.9316646e+00 4.4680158e+00 4.1325542e+00 4.3648035e+00 4.5412859e+00 4.1418557e+00 4.5581864e-01 4.1586001e-01 7.7074935e-01 5.0991930e-01 7.1840099e-01 7.2486328e-01 7.3145860e-01 1.2122249e+00 9.2112464e-01 1.1384810e+00 1.1451403e+00 9.1163729e-01 7.0386584e-01 7.4855857e-01 1.2220203e+00 1.1947245e+00 6.6827038e-01 6.2081167e-01 3.4378533e-01 1.1229906e+00 9.9348625e-01 5.2942799e-01 1.1229906e+00 1.5344133e+00 8.2275389e-01 8.5233811e-01 1.8985661e+00 1.4692412e+00 8.9653332e-01 8.7420176e-01 1.2431040e+00 7.3813096e-01 1.2951131e+00 5.5419992e-01 9.3801395e-01 3.5789198e+00 3.3663244e+00 3.7753619e+00 3.0049442e+00 3.4909841e+00 3.3695525e+00 3.5654259e+00 2.3989172e+00 3.4663502e+00 2.8427326e+00 2.7185849e+00 3.0894572e+00 3.0108764e+00 3.5617386e+00 2.5173832e+00 3.2758681e+00 3.3732554e+00 2.9816791e+00 3.4895316e+00 2.8451507e+00 3.6905956e+00 2.8989400e+00 3.8036776e+00 3.5549103e+00 3.1734856e+00 3.2772927e+00 3.6834126e+00 3.8868430e+00 3.3809159e+00 2.4588872e+00 2.7850016e+00 2.6918796e+00 2.8113773e+00 3.9804187e+00 3.3742776e+00 3.3692592e+00 3.5726491e+00 3.3587234e+00 2.9691171e+00 2.9539253e+00 3.2926883e+00 3.4584304e+00 2.9217347e+00 2.4321061e+00 3.0988783e+00 3.0546600e+00 3.0736357e+00 3.1699903e+00 2.1306832e+00 2.9913743e+00 4.9420128e+00 4.0177712e+00 4.8123874e+00 4.4703485e+00 4.7113827e+00 5.5147622e+00 3.4715574e+00 5.1811127e+00 4.6944291e+00 5.0587041e+00 4.0117533e+00 4.2085851e+00 4.4199792e+00 3.9616570e+00 4.1103933e+00 4.2537610e+00 4.3721243e+00 5.6218420e+00 5.8419148e+00 3.9412893e+00 4.6390186e+00 3.8408636e+00 5.6159291e+00 3.8175051e+00 4.5984929e+00 4.8771654e+00 3.7143727e+00 3.7943375e+00 4.5141564e+00 4.6734732e+00 5.0086627e+00 5.3396700e+00 4.5298770e+00 3.9647930e+00 4.4561969e+00 5.0778756e+00 4.5477422e+00 4.3671210e+00 3.6996802e+00 4.3269400e+00 4.5602465e+00 4.0901232e+00 4.0177712e+00 4.8233796e+00 4.6689006e+00 4.1757336e+00 3.9466531e+00 4.1130674e+00 4.3408596e+00 3.9840684e+00 5.3588338e-01 9.7098574e-01 6.0611244e-01 7.4549115e-01 1.0101422e+00 8.1242502e-01 1.2342162e+00 1.1486378e+00 1.1959482e+00 1.4468211e+00 1.0906388e+00 9.4287188e-01 1.0346741e+00 1.3793330e+00 1.4148192e+00 1.0065841e+00 5.5419992e-01 2.8507955e-01 1.3835747e+00 1.2681309e+00 9.0679720e-01 1.3835747e+00 1.6801917e+00 1.0588560e+00 1.0122141e+00 2.2040881e+00 1.5564198e+00 1.0122141e+00 7.7553525e-01 1.4987155e+00 7.4893123e-01 1.4320120e+00 7.3813096e-01 1.1765359e+00 3.3186105e+00 3.0934278e+00 3.5115632e+00 2.9015832e+00 3.2557855e+00 3.1381850e+00 3.2787144e+00 2.3983798e+00 3.2261964e+00 2.6655261e+00 2.7738368e+00 2.8425716e+00 2.9377092e+00 3.3097860e+00 2.3365894e+00 3.0236933e+00 3.1147370e+00 2.7988444e+00 3.3431646e+00 2.7201960e+00 3.4033622e+00 2.7009102e+00 3.5863979e+00 3.3171611e+00 2.9439491e+00 3.0327979e+00 3.4475678e+00 3.6195561e+00 3.1337459e+00 2.3758157e+00 2.6957302e+00 2.6219409e+00 2.6429556e+00 3.7305206e+00 3.1152653e+00 3.0762634e+00 3.3088561e+00 3.2115055e+00 2.7318540e+00 2.8101506e+00 3.0967820e+00 3.1998457e+00 2.7619926e+00 2.4596921e+00 2.9002737e+00 2.8148869e+00 2.8449691e+00 2.9378173e+00 2.1723936e+00 2.7843048e+00 4.6358686e+00 3.7621042e+00 4.5316360e+00 4.1928583e+00 4.4221843e+00 5.2364242e+00 3.2682245e+00 4.9072991e+00 4.4428425e+00 4.7561724e+00 3.7219581e+00 3.9498605e+00 4.1390009e+00 3.7275066e+00 3.8377652e+00 3.9569614e+00 4.0917968e+00 5.3289557e+00 5.5738695e+00 3.7540308e+00 4.3457024e+00 3.5797958e+00 5.3465693e+00 3.5720882e+00 4.3012547e+00 4.5936468e+00 3.4616111e+00 3.5205889e+00 4.2389017e+00 4.4031390e+00 4.7432976e+00 5.0569442e+00 4.2531342e+00 3.7092459e+00 4.2038056e+00 4.8064634e+00 4.2402361e+00 4.0806404e+00 3.4276314e+00 4.0438546e+00 4.2676463e+00 3.8085992e+00 3.7621042e+00 4.5272919e+00 4.3667579e+00 3.8946701e+00 3.7163265e+00 3.8338395e+00 4.0342445e+00 3.7061759e+00 4.4651726e-01 4.4651726e-01 3.2816937e-01 5.7257017e-01 3.4378533e-01 8.2384013e-01 6.6432544e-01 8.0758367e-01 9.3048953e-01 5.8851328e-01 4.3691963e-01 5.1691876e-01 8.8062848e-01 8.9917007e-01 5.0817745e-01 3.6171588e-01 3.2816937e-01 8.6361309e-01 7.3851529e-01 4.1449626e-01 8.6361309e-01 1.1845977e+00 5.4292906e-01 4.9766035e-01 1.6754036e+00 1.0919712e+00 5.3309112e-01 6.2024833e-01 9.7098574e-01 3.8934542e-01 9.3824087e-01 2.8507955e-01 6.5223271e-01 3.5185448e+00 3.2633258e+00 3.6996953e+00 2.8710255e+00 3.3892942e+00 3.2497279e+00 3.4561374e+00 2.2371784e+00 3.3772302e+00 2.7023432e+00 2.5704711e+00 2.9638836e+00 2.8904978e+00 3.4483274e+00 2.3826791e+00 3.1954061e+00 3.2493673e+00 2.8645447e+00 3.3669805e+00 2.7184506e+00 3.5654259e+00 2.7812639e+00 3.6908684e+00 3.4451701e+00 3.0736340e+00 3.1881331e+00 3.6017790e+00 3.7914024e+00 3.2604423e+00 2.3308454e+00 2.6548674e+00 2.5630676e+00 2.6859989e+00 3.8615219e+00 3.2492317e+00 3.2498302e+00 3.4856775e+00 3.2460061e+00 2.8456767e+00 2.8220742e+00 3.1709561e+00 3.3452644e+00 2.7965957e+00 2.2780262e+00 2.9733693e+00 2.9362769e+00 2.9511072e+00 3.0600825e+00 1.9688013e+00 2.8661222e+00 4.8176767e+00 3.8889176e+00 4.7230291e+00 4.3578295e+00 4.5962942e+00 5.4442203e+00 3.3242177e+00 5.1039076e+00 4.5914416e+00 4.9653393e+00 3.8994399e+00 4.0931001e+00 4.3174903e+00 3.8262108e+00 3.9673816e+00 4.1302370e+00 4.2654212e+00 5.5551457e+00 5.7673205e+00 3.8189943e+00 4.5366342e+00 3.7059360e+00 5.5500825e+00 3.6985459e+00 4.4934936e+00 4.7995387e+00 3.5922369e+00 3.6724425e+00 4.3963259e+00 4.6010378e+00 4.9364818e+00 5.2936070e+00 4.4094664e+00 3.8558772e+00 4.3453589e+00 5.0159331e+00 4.4225169e+00 4.2579435e+00 3.5745624e+00 4.2301614e+00 4.4459076e+00 3.9875954e+00 3.8889176e+00 4.7169919e+00 4.5531173e+00 4.0619315e+00 3.8238093e+00 3.9999729e+00 4.2141826e+00 3.8611742e+00 6.3808075e-01 3.0275928e-01 3.7598397e-01 2.1269358e-01 5.6769031e-01 3.4378533e-01 5.3022554e-01 5.0991930e-01 2.1845981e-01 1.4096146e-01 1.4096146e-01 4.5581864e-01 4.5581864e-01 3.0811765e-01 6.0670504e-01 7.3496673e-01 4.2667565e-01 3.2816937e-01 4.0293660e-01 4.2667565e-01 7.6787403e-01 1.4096146e-01 1.2418578e-01 1.2394907e+00 7.1504098e-01 3.2586371e-01 5.2942799e-01 5.2862779e-01 3.2586371e-01 5.2942799e-01 2.5651975e-01 2.1269358e-01 3.4944845e+00 3.2032390e+00 3.6588207e+00 2.7040077e+00 3.3172489e+00 3.1387381e+00 3.3902207e+00 2.0195610e+00 3.3129652e+00 2.5744164e+00 2.3173648e+00 2.8753045e+00 2.7215057e+00 3.3565935e+00 2.2694598e+00 3.1556501e+00 3.1511848e+00 2.7390328e+00 3.2351115e+00 2.5646808e+00 3.4858646e+00 2.6854398e+00 3.5885398e+00 3.3452644e+00 3.0014619e+00 3.1359624e+00 3.5442447e+00 3.7351231e+00 3.1683717e+00 2.1722580e+00 2.4832809e+00 2.3831271e+00 2.5617005e+00 3.7607269e+00 3.1489919e+00 3.1764760e+00 3.4370400e+00 3.1222134e+00 2.7420671e+00 2.6759392e+00 3.0406669e+00 3.2584404e+00 2.6649106e+00 2.0477765e+00 2.8508344e+00 2.8325946e+00 2.8443188e+00 2.9745020e+00 1.7495699e+00 2.7521074e+00 4.7498176e+00 3.7908064e+00 4.6736601e+00 4.2736523e+00 4.5261084e+00 5.4025762e+00 3.1986968e+00 5.0495127e+00 4.5070435e+00 4.9284820e+00 3.8418637e+00 4.0108142e+00 4.2628455e+00 3.7198158e+00 3.8891307e+00 4.0719001e+00 4.1917075e+00 5.5215376e+00 5.7192826e+00 3.6876129e+00 4.4897240e+00 3.6129201e+00 5.5066558e+00 3.6138577e+00 4.4349731e+00 4.7514299e+00 3.5090368e+00 3.5920050e+00 4.3185209e+00 4.5521574e+00 4.8905855e+00 5.2768100e+00 4.3339547e+00 3.7672401e+00 4.2403934e+00 4.9963306e+00 4.3598652e+00 4.1826701e+00 3.4920978e+00 4.1853524e+00 4.3933832e+00 3.9574195e+00 3.7908064e+00 4.6611791e+00 4.5034762e+00 4.0149574e+00 3.7307866e+00 3.9355645e+00 4.1498459e+00 3.7732223e+00 6.0551856e-01 4.4535192e-01 6.0670504e-01 1.1765359e+00 6.9325418e-01 9.2288144e-01 9.3637892e-01 7.3535471e-01 5.3665999e-01 5.8914551e-01 1.0576043e+00 1.0106392e+00 4.5581864e-01 5.4292906e-01 4.5581864e-01 9.4009473e-01 8.6290690e-01 4.5581864e-01 9.4009473e-01 1.3885563e+00 6.5223271e-01 7.4740267e-01 1.7041201e+00 1.3421549e+00 7.2823007e-01 6.0611244e-01 1.0653845e+00 6.0121055e-01 1.1521791e+00 4.1586001e-01 7.7919451e-01 3.1037808e+00 2.8727295e+00 3.2914954e+00 2.5112138e+00 2.9950832e+00 2.8632951e+00 3.0711321e+00 1.9332545e+00 2.9709745e+00 2.3448578e+00 2.2688022e+00 2.5914913e+00 2.5183808e+00 3.0579528e+00 2.0217308e+00 2.7906520e+00 2.8719896e+00 2.4738237e+00 2.9926636e+00 2.3440712e+00 3.1967616e+00 2.3980102e+00 3.3005331e+00 3.0483897e+00 2.6752185e+00 2.7868575e+00 3.1931777e+00 3.3968373e+00 2.8794765e+00 1.9640287e+00 2.2899742e+00 2.1990648e+00 2.3082381e+00 3.4762640e+00 2.8726212e+00 2.8752807e+00 3.0841055e+00 2.8599559e+00 2.4658566e+00 2.4543822e+00 2.7852734e+00 2.9558536e+00 2.4184985e+00 1.9730073e+00 2.5941661e+00 2.5490308e+00 2.5692104e+00 2.6676432e+00 1.6855044e+00 2.4875166e+00 4.4549901e+00 3.5192877e+00 4.3283747e+00 3.9701062e+00 4.2192020e+00 5.0364062e+00 2.9740218e+00 4.6944291e+00 4.1953299e+00 4.5849301e+00 3.5249823e+00 3.7114178e+00 3.9340128e+00 3.4663826e+00 3.6308220e+00 3.7719045e+00 3.8752244e+00 5.1489675e+00 5.3620178e+00 3.4363773e+00 4.1584261e+00 3.3485848e+00 5.1375979e+00 3.3209346e+00 4.1101337e+00 4.3926615e+00 3.2186045e+00 3.2982828e+00 4.0192434e+00 4.1885158e+00 4.5274663e+00 4.8785522e+00 4.0373008e+00 3.4619693e+00 3.9494193e+00 4.6147130e+00 4.0642632e+00 3.8698115e+00 3.2042572e+00 3.8459316e+00 4.0795080e+00 3.6227082e+00 3.5192877e+00 4.3377723e+00 4.1907472e+00 3.6992844e+00 3.4507210e+00 3.6230931e+00 3.8568809e+00 3.4855556e+00 4.5581864e-01 1.2418578e-01 6.2660376e-01 5.1607523e-01 5.2655962e-01 8.0096515e-01 4.0438741e-01 3.0546431e-01 4.0438741e-01 6.4806901e-01 7.1504098e-01 4.4535192e-01 3.2586371e-01 4.9857388e-01 7.0784540e-01 6.2081167e-01 4.5581864e-01 7.0784540e-01 9.3824087e-01 4.0147421e-01 3.2586371e-01 1.5252485e+00 8.1558458e-01 3.7598397e-01 4.0147421e-01 8.1099042e-01 1.2418578e-01 6.9006418e-01 2.1269358e-01 5.0270183e-01 3.4104878e+00 3.1150013e+00 3.5735680e+00 2.6813198e+00 3.2413086e+00 3.0598576e+00 3.2985843e+00 2.0418831e+00 3.2329790e+00 2.5171713e+00 2.3816204e+00 2.7937685e+00 2.7102198e+00 3.2724336e+00 2.2054062e+00 3.0737397e+00 3.0650685e+00 2.6738621e+00 3.1983741e+00 2.5253420e+00 3.3951420e+00 2.6185785e+00 3.5201263e+00 3.2642011e+00 2.9245132e+00 3.0559405e+00 3.4672191e+00 3.6501426e+00 3.0869409e+00 2.1449779e+00 2.4611582e+00 2.3678836e+00 2.5038051e+00 3.6798850e+00 3.0627375e+00 3.0833417e+00 3.3518108e+00 3.0810282e+00 2.6595270e+00 2.6323570e+00 2.9747184e+00 3.1719581e+00 2.6119950e+00 2.0875308e+00 2.7837517e+00 2.7481947e+00 2.7653278e+00 2.8959432e+00 1.7918633e+00 2.6810089e+00 4.6579399e+00 3.7114178e+00 4.5860934e+00 4.1845117e+00 4.4368376e+00 5.3138890e+00 3.1392617e+00 4.9608959e+00 4.4280037e+00 4.8387532e+00 3.7530908e+00 3.9304148e+00 4.1764880e+00 3.6510310e+00 3.8111653e+00 3.9838913e+00 4.1019789e+00 5.4302306e+00 5.6352651e+00 3.6334268e+00 4.4011799e+00 3.5332521e+00 5.4201202e+00 3.5378545e+00 4.3430510e+00 4.6603717e+00 3.4302376e+00 3.5053533e+00 4.2335883e+00 4.4640423e+00 4.8059592e+00 5.1881280e+00 4.2497073e+00 3.6834126e+00 4.1572779e+00 4.9128775e+00 4.2687104e+00 4.0908836e+00 3.4061169e+00 4.0989195e+00 4.3064904e+00 3.8759115e+00 3.7114178e+00 4.5707958e+00 4.4147019e+00 3.9326468e+00 3.6624594e+00 3.8494244e+00 4.0586633e+00 3.6843892e+00 4.0176783e-01 9.3801395e-01 3.7427929e-01 6.0551856e-01 4.9766035e-01 4.1449626e-01 2.5251796e-01 3.2352160e-01 7.0437330e-01 6.2024833e-01 2.4837156e-01 7.0826681e-01 8.1099042e-01 5.3665999e-01 5.7257017e-01 4.0293660e-01 5.3665999e-01 1.0321505e+00 3.2352160e-01 4.9857388e-01 1.2654843e+00 1.0181000e+00 4.9857388e-01 4.6472023e-01 6.6432544e-01 4.4535192e-01 8.1354181e-01 3.2586371e-01 4.4535192e-01 3.1652953e+00 2.9034751e+00 3.3383293e+00 2.4277398e+00 3.0113552e+00 2.8500355e+00 3.0981427e+00 1.7594421e+00 2.9944056e+00 2.3105335e+00 2.0559262e+00 2.5987706e+00 2.4171653e+00 3.0605340e+00 2.0054351e+00 2.8372675e+00 2.8748086e+00 2.4385827e+00 2.9411544e+00 2.2761106e+00 3.2149087e+00 2.3896630e+00 3.2878368e+00 3.0415738e+00 2.6906230e+00 2.8216976e+00 3.2222602e+00 3.4304873e+00 2.8822802e+00 1.8816502e+00 2.1994544e+00 2.0961718e+00 2.2729984e+00 3.4713427e+00 2.8746311e+00 2.8977380e+00 3.1239380e+00 2.8149627e+00 2.4626518e+00 2.3988202e+00 2.7512943e+00 2.9634715e+00 2.3744738e+00 1.7861398e+00 2.5679553e+00 2.5438761e+00 2.5602722e+00 2.6724144e+00 1.5132025e+00 2.4693940e+00 4.4818617e+00 3.5188715e+00 4.3693901e+00 3.9814082e+00 4.2430316e+00 5.0846750e+00 2.9378173e+00 4.7308926e+00 4.2026915e+00 4.6369546e+00 3.5592955e+00 3.7219741e+00 3.9702025e+00 3.4565374e+00 3.6485303e+00 3.8059948e+00 3.8952692e+00 5.2045888e+00 5.4038637e+00 3.3942456e+00 4.2018404e+00 3.3550631e+00 5.1838582e+00 3.3280757e+00 4.1439346e+00 4.4349731e+00 3.2284912e+00 3.3133518e+00 4.0354963e+00 4.2293106e+00 4.5707958e+00 4.9486891e+00 4.0555804e+00 3.4667821e+00 3.9402495e+00 4.6817169e+00 4.0952984e+00 3.8891597e+00 3.2181054e+00 3.8906833e+00 4.1179678e+00 3.6792093e+00 3.5188715e+00 4.3738746e+00 4.2318888e+00 3.7415007e+00 3.4482727e+00 3.6509580e+00 3.8867812e+00 3.4956677e+00 6.2660376e-01 4.1449626e-01 4.8927739e-01 7.0479928e-01 3.0546431e-01 2.5251796e-01 3.2816937e-01 5.7324170e-01 6.2538346e-01 3.7255734e-01 4.4535192e-01 5.7324170e-01 6.2482915e-01 5.3665999e-01 4.3691963e-01 6.2482915e-01 8.7420176e-01 3.2352160e-01 2.5651975e-01 1.4293465e+00 7.7360126e-01 2.5651975e-01 4.0147421e-01 7.1504098e-01 2.1269358e-01 6.2660376e-01 2.4837156e-01 4.1586001e-01 3.4011512e+00 3.1015495e+00 3.5629124e+00 2.6446848e+00 3.2242409e+00 3.0444970e+00 3.2854349e+00 1.9922212e+00 3.2208624e+00 2.4875432e+00 2.3235341e+00 2.7738624e+00 2.6761538e+00 3.2590031e+00 2.1770137e+00 3.0609726e+00 3.0488669e+00 2.6564689e+00 3.1671679e+00 2.4967542e+00 3.3778209e+00 2.5968629e+00 3.5012162e+00 3.2523394e+00 2.9093820e+00 3.0417674e+00 3.4541339e+00 3.6357801e+00 3.0695657e+00 2.1117686e+00 2.4265922e+00 2.3324013e+00 2.4794505e+00 3.6641654e+00 3.0465086e+00 3.0686943e+00 3.3395333e+00 3.0541897e+00 2.6428278e+00 2.6018930e+00 2.9558536e+00 3.1589081e+00 2.5867906e+00 2.0334278e+00 2.7624503e+00 2.7347909e+00 2.7481947e+00 2.8804789e+00 1.7294430e+00 2.6604040e+00 4.6390099e+00 3.6904099e+00 4.5721680e+00 4.1717456e+00 4.4201622e+00 5.3038306e+00 3.1101376e+00 4.9521292e+00 4.4131751e+00 4.8218478e+00 3.7351231e+00 3.9119157e+00 4.1593600e+00 3.6239123e+00 3.7806200e+00 3.9616940e+00 4.0893976e+00 5.4208566e+00 5.6225133e+00 3.6099406e+00 4.3833809e+00 3.5087649e+00 5.4106224e+00 3.5167400e+00 4.3287713e+00 4.6517741e+00 3.4091049e+00 3.4875352e+00 4.2154392e+00 4.4559638e+00 4.7948032e+00 5.1800729e+00 4.2298456e+00 3.6705550e+00 4.1464752e+00 4.8981257e+00 4.2482702e+00 4.0788778e+00 3.3871264e+00 4.0817153e+00 4.2852718e+00 3.8517038e+00 3.6904099e+00 4.5544260e+00 4.3933832e+00 3.9084933e+00 3.6377874e+00 3.8310704e+00 4.0381483e+00 3.6684338e+00 7.9016429e-01 9.0454394e-01 7.7553525e-01 6.5633874e-01 6.8961791e-01 6.5172743e-01 6.4755655e-01 6.9325418e-01 8.5690100e-01 7.5871717e-01 9.8800009e-01 6.3977563e-01 5.0503591e-01 9.0852141e-01 6.3977563e-01 6.2482915e-01 6.2605182e-01 4.4651726e-01 1.3039319e+00 4.5470518e-01 6.8801986e-01 9.4492923e-01 6.5223271e-01 6.9325418e-01 4.9674312e-01 7.6752131e-01 5.2574978e-01 3.9950977e+00 3.6682165e+00 4.1454421e+00 3.1171350e+00 3.7869887e+00 3.5623665e+00 3.8418637e+00 2.4093459e+00 3.7913585e+00 2.9787373e+00 2.6930133e+00 3.3123070e+00 3.1668302e+00 3.7985007e+00 2.6980573e+00 3.6472316e+00 3.5682291e+00 3.1756360e+00 3.6828708e+00 2.9891564e+00 3.9102500e+00 3.1455588e+00 4.0375495e+00 3.7881557e+00 3.4756264e+00 3.6204175e+00 4.0288578e+00 4.2043522e+00 3.6069560e+00 2.6127852e+00 2.9004348e+00 2.8010550e+00 3.0013391e+00 4.1901031e+00 3.5584876e+00 3.6126340e+00 3.9170234e+00 3.5823448e+00 3.1646752e+00 3.0923554e+00 3.4563987e+00 3.7021702e+00 3.1018442e+00 2.4341346e+00 3.2724336e+00 3.2604423e+00 3.2715632e+00 3.4335342e+00 2.1375243e+00 3.1807243e+00 5.1732049e+00 4.2085267e+00 5.1402548e+00 4.7090394e+00 4.9640507e+00 5.8783901e+00 3.5970425e+00 5.5195747e+00 4.9586651e+00 5.3905797e+00 4.2919639e+00 4.4545908e+00 4.7214902e+00 4.1323720e+00 4.2962344e+00 4.5078390e+00 4.6379987e+00 5.9985593e+00 6.1927610e+00 4.1173292e+00 4.9467209e+00 4.0217355e+00 5.9855018e+00 4.0597680e+00 4.8845913e+00 5.2228901e+00 3.9505682e+00 4.0262006e+00 4.7557226e+00 5.0295898e+00 5.3695643e+00 5.7704875e+00 4.7697480e+00 4.2124808e+00 4.6690776e+00 5.4857949e+00 4.7867344e+00 4.6237863e+00 3.9220577e+00 4.6512574e+00 4.8397561e+00 4.4244727e+00 4.2085267e+00 5.1102370e+00 4.9464234e+00 4.4688286e+00 4.1733964e+00 4.3844239e+00 4.5752087e+00 4.1957914e+00 3.8934542e-01 3.7598397e-01 1.5422108e-01 3.4583729e-01 3.7598397e-01 4.4651726e-01 3.8934542e-01 3.2816937e-01 8.2929029e-01 9.3610001e-01 4.3691963e-01 5.3022554e-01 5.3309112e-01 4.3691963e-01 7.5976039e-01 3.2586371e-01 4.2667565e-01 1.0733200e+00 7.4777660e-01 2.1845981e-01 5.0905001e-01 4.3456114e-01 5.2942799e-01 5.5492130e-01 4.6472023e-01 3.7427929e-01 3.2191540e+00 2.9033203e+00 3.3725057e+00 2.3744738e+00 3.0162346e+00 2.8254861e+00 3.0850817e+00 1.6867642e+00 3.0206125e+00 2.2489449e+00 1.9859316e+00 2.5612285e+00 2.4037412e+00 3.0483897e+00 1.9482601e+00 2.8711841e+00 2.8361445e+00 2.4280197e+00 2.9151666e+00 2.2428341e+00 3.1709561e+00 2.3770599e+00 3.2772927e+00 3.0392407e+00 2.7044574e+00 2.8456337e+00 3.2543813e+00 3.4363773e+00 2.8560815e+00 1.8517858e+00 2.1570512e+00 2.0577182e+00 2.2449618e+00 3.4472201e+00 2.8333788e+00 2.8654874e+00 3.1455372e+00 2.8102985e+00 2.4278629e+00 2.3504126e+00 2.7240842e+00 2.9511072e+00 2.3468577e+00 1.7140774e+00 2.5325623e+00 2.5220817e+00 2.5303132e+00 2.6704164e+00 1.4096199e+00 2.4355523e+00 4.4339908e+00 3.4713427e+00 4.3742064e+00 3.9639546e+00 4.2144772e+00 5.1104621e+00 2.8721481e+00 4.7555981e+00 4.1997133e+00 4.6264002e+00 3.5337158e+00 3.6986235e+00 3.9580816e+00 3.3951420e+00 3.5651172e+00 3.7578933e+00 3.8852294e+00 5.2312618e+00 5.4232729e+00 3.3678461e+00 4.1846468e+00 3.2909043e+00 5.2164277e+00 3.3005331e+00 4.1286019e+00 4.4583488e+00 3.1948184e+00 3.2785487e+00 4.0052019e+00 4.2627019e+00 4.5989546e+00 4.9978258e+00 4.0193656e+00 3.4602150e+00 3.9315374e+00 4.7096962e+00 4.0441539e+00 3.8751788e+00 3.1769821e+00 3.8841455e+00 4.0829381e+00 3.6559398e+00 3.4713427e+00 4.3535851e+00 4.1922661e+00 3.7063225e+00 3.4135466e+00 3.6262912e+00 3.8337160e+00 3.4586921e+00 4.5470518e-01 3.4378533e-01 4.9766035e-01 5.6631629e-01 3.2586371e-01 3.7255734e-01 6.5172743e-01 7.6625946e-01 9.7356960e-01 4.4651726e-01 7.0784540e-01 8.1273630e-01 4.4651726e-01 6.8757066e-01 4.4417983e-01 6.0670504e-01 1.1521791e+00 6.5172743e-01 4.5581864e-01 4.5470518e-01 5.6700421e-01 4.8036801e-01 5.1607523e-01 5.8851328e-01 5.0905001e-01 3.1972361e+00 2.8360340e+00 3.3243092e+00 2.2696891e+00 2.9531300e+00 2.6835197e+00 2.9981183e+00 1.5916843e+00 2.9546153e+00 2.1366783e+00 1.9099663e+00 2.4717637e+00 2.3219731e+00 2.9300203e+00 1.8705419e+00 2.8448793e+00 2.7044574e+00 2.2951567e+00 2.8430073e+00 2.1220080e+00 3.0654291e+00 2.3117864e+00 3.1749624e+00 2.9091307e+00 2.6433897e+00 2.8065044e+00 3.2000771e+00 3.3714688e+00 2.7511201e+00 1.7679293e+00 2.0426611e+00 1.9423536e+00 2.1457242e+00 3.3172489e+00 2.6940968e+00 2.7682296e+00 3.0935247e+00 2.7391698e+00 2.2996943e+00 2.2360451e+00 2.5729378e+00 2.8382774e+00 2.2413445e+00 1.6312555e+00 2.4031247e+00 2.3848740e+00 2.4037412e+00 2.5843380e+00 1.3803845e+00 2.3178393e+00 4.3373464e+00 3.3555449e+00 4.3029534e+00 3.8394246e+00 4.1166152e+00 5.0345534e+00 2.7564428e+00 4.6628709e+00 4.0929284e+00 4.5724955e+00 3.4657942e+00 3.6038441e+00 3.8912788e+00 3.2935105e+00 3.4985926e+00 3.6938082e+00 3.7771525e+00 5.1600819e+00 5.3477989e+00 3.2453592e+00 4.1245629e+00 3.1885527e+00 5.1389533e+00 3.2183480e+00 4.0411872e+00 4.3734530e+00 3.1116430e+00 3.1793624e+00 3.9065553e+00 4.1815080e+00 4.5288943e+00 4.9506208e+00 3.9281139e+00 3.3421539e+00 3.7789119e+00 4.6812838e+00 3.9623295e+00 3.7603559e+00 3.0782101e+00 3.8325036e+00 4.0241284e+00 3.6474081e+00 3.3555449e+00 4.2739171e+00 4.1339606e+00 3.6720159e+00 3.3349237e+00 3.5512382e+00 3.7511837e+00 3.3364095e+00 4.1312257e-01 5.0905001e-01 4.2538717e-01 3.2352160e-01 2.0656129e-01 5.0592043e-01 1.1017858e+00 1.2234738e+00 1.5422108e-01 4.1312257e-01 6.3924842e-01 1.5422108e-01 6.1968386e-01 4.0293660e-01 5.2942799e-01 7.7919451e-01 6.2482915e-01 5.6631629e-01 8.1385214e-01 2.5251796e-01 8.0032200e-01 4.2538717e-01 7.1462831e-01 3.2352160e-01 3.3601225e+00 3.0492285e+00 3.5130686e+00 2.4784234e+00 3.1574358e+00 2.9495683e+00 3.2305582e+00 1.7639552e+00 3.1543365e+00 2.3872777e+00 2.0066796e+00 2.7104259e+00 2.4866453e+00 3.1794134e+00 2.0999661e+00 3.0164205e+00 2.9733298e+00 2.5409084e+00 3.0313923e+00 2.3496997e+00 3.3211033e+00 2.5173832e+00 3.4035007e+00 3.1599783e+00 2.8424094e+00 2.9896107e+00 3.3894792e+00 3.5821206e+00 2.9960387e+00 1.9633030e+00 2.2546134e+00 2.1472921e+00 2.3729779e+00 3.5766918e+00 2.9692947e+00 3.0147040e+00 3.2887803e+00 2.9233984e+00 2.5628362e+00 2.4694536e+00 2.8371552e+00 3.0850817e+00 2.4681135e+00 1.7749726e+00 2.6585961e+00 2.6493446e+00 2.6623632e+00 2.8060305e+00 1.5124582e+00 2.5679553e+00 4.5912390e+00 3.6144502e+00 4.5212874e+00 4.0982070e+00 4.3637125e+00 5.2494547e+00 3.0086587e+00 4.8875515e+00 4.3294620e+00 4.7880147e+00 3.6912876e+00 3.8418637e+00 4.1117747e+00 3.5413188e+00 3.7389462e+00 3.9250135e+00 4.0233529e+00 5.3754694e+00 5.5627643e+00 3.4785161e+00 4.3436980e+00 3.4455964e+00 5.3512930e+00 3.4471566e+00 4.2776053e+00 4.5941143e+00 3.3449470e+00 3.4269051e+00 4.1524717e+00 4.3946634e+00 4.7366258e+00 5.1414650e+00 4.1713411e+00 3.5895201e+00 4.0467919e+00 4.8635964e+00 4.2075047e+00 4.0127353e+00 3.3273395e+00 4.0411872e+00 4.2480617e+00 3.8321687e+00 3.6144502e+00 4.5072985e+00 4.3598062e+00 3.8780834e+00 3.5586316e+00 3.7805671e+00 3.9971028e+00 3.6003219e+00 2.5651975e-01 2.8192292e-01 3.4378533e-01 3.4378533e-01 4.0147421e-01 7.1840099e-01 8.5690100e-01 3.7598397e-01 4.2538717e-01 5.3665999e-01 3.7598397e-01 6.6827038e-01 2.1269358e-01 3.0546431e-01 1.1320702e+00 6.2988288e-01 2.0656129e-01 4.4535192e-01 4.2667565e-01 4.1449626e-01 4.3691963e-01 3.8934542e-01 2.5251796e-01 3.3428183e+00 3.0232018e+00 3.4944845e+00 2.4950353e+00 3.1381402e+00 2.9363801e+00 3.2027420e+00 1.8084630e+00 3.1409294e+00 2.3642733e+00 2.1113036e+00 2.6784604e+00 2.5283251e+00 3.1625374e+00 2.0667297e+00 2.9950041e+00 2.9473422e+00 2.5410503e+00 3.0407257e+00 2.3596992e+00 3.2858223e+00 2.4986337e+00 3.3960124e+00 3.1519721e+00 2.8255193e+00 2.9686973e+00 3.3765772e+00 3.5575681e+00 2.9720515e+00 1.9732878e+00 2.2758449e+00 2.1765379e+00 2.3630256e+00 3.5606213e+00 2.9432282e+00 2.9813163e+00 3.2672636e+00 2.9349850e+00 2.5393641e+00 2.4678343e+00 2.8348218e+00 3.0655803e+00 2.4649412e+00 1.8381372e+00 2.6459992e+00 2.6324803e+00 2.6428278e+00 2.7886501e+00 1.5384446e+00 2.5500177e+00 4.5509522e+00 3.5863729e+00 4.4953238e+00 4.0776551e+00 4.3319640e+00 5.2308062e+00 2.9880146e+00 4.8736353e+00 4.3174903e+00 4.7496159e+00 3.6545040e+00 3.8173510e+00 4.0797075e+00 3.5129177e+00 3.6850739e+00 3.8789949e+00 4.0011311e+00 5.3516635e+00 5.5447338e+00 3.4854203e+00 4.3070102e+00 3.4066692e+00 5.3366535e+00 3.4209331e+00 4.2472818e+00 4.5769661e+00 3.3144678e+00 3.3951450e+00 4.1229838e+00 4.3815083e+00 4.7200939e+00 5.1200990e+00 4.1381062e+00 3.5750015e+00 4.0416512e+00 4.8355880e+00 4.1628805e+00 3.9898962e+00 3.2934163e+00 4.0073765e+00 4.2053647e+00 3.7839552e+00 3.5863729e+00 4.4735121e+00 4.3145846e+00 3.8316735e+00 3.5355330e+00 3.7466071e+00 3.9521135e+00 3.5718733e+00 1.2418578e-01 5.2942799e-01 4.9766035e-01 2.5251796e-01 6.0060595e-01 7.1462831e-01 4.4535192e-01 3.8776762e-01 3.2352160e-01 4.4535192e-01 8.5434758e-01 1.2418578e-01 2.5251796e-01 1.2643026e+00 8.1354181e-01 4.1449626e-01 4.5581864e-01 5.6769031e-01 3.0546431e-01 6.2024833e-01 2.0656129e-01 2.5251796e-01 3.3898078e+00 3.1105347e+00 3.5575681e+00 2.6249526e+00 3.2229246e+00 3.0488669e+00 3.3004172e+00 1.9465831e+00 3.2118493e+00 2.4993166e+00 2.2473120e+00 2.7928582e+00 2.6296047e+00 3.2639046e+00 2.1933937e+00 3.0559188e+00 3.0673749e+00 2.6440180e+00 3.1486786e+00 2.4776707e+00 3.4056271e+00 2.5954147e+00 3.4958702e+00 3.2483608e+00 2.9041534e+00 3.0378828e+00 3.4425295e+00 3.6411503e+00 3.0811775e+00 2.0851901e+00 2.3997585e+00 2.2980893e+00 2.4741664e+00 3.6714798e+00 3.0661139e+00 3.0923102e+00 3.3390355e+00 3.0288896e+00 2.6566259e+00 2.5949561e+00 2.9511072e+00 3.1662394e+00 2.5768305e+00 1.9764051e+00 2.7650187e+00 2.7420671e+00 2.7570191e+00 2.8802219e+00 1.6913411e+00 2.6662783e+00 4.6723657e+00 3.7109297e+00 4.5802461e+00 4.1829734e+00 4.4414351e+00 5.3024507e+00 3.1246867e+00 4.9479218e+00 4.4123750e+00 4.8421359e+00 3.7582429e+00 3.9238367e+00 4.1750713e+00 3.6455011e+00 3.8262353e+00 3.9966275e+00 4.0997246e+00 5.4219259e+00 5.6210533e+00 3.5985833e+00 4.4045665e+00 3.5402439e+00 5.4041845e+00 3.5288526e+00 4.3467079e+00 4.6509698e+00 3.4261305e+00 3.5087649e+00 4.2340479e+00 4.4487072e+00 4.7898591e+00 5.1726632e+00 4.2521321e+00 3.6728562e+00 4.1446028e+00 4.9002452e+00 4.2845042e+00 4.0915924e+00 3.4110551e+00 4.0971854e+00 4.3142588e+00 3.8789274e+00 3.7109297e+00 4.5753785e+00 4.4261431e+00 3.9377466e+00 3.6482464e+00 3.8509694e+00 4.0749843e+00 3.6894983e+00 5.1607523e-01 4.5470518e-01 2.5251796e-01 7.0086313e-01 8.1067767e-01 3.7598397e-01 2.8192292e-01 3.0546431e-01 3.7598397e-01 8.2654509e-01 1.2418578e-01 2.1845981e-01 1.1754055e+00 8.0326782e-01 4.2667565e-01 5.7324170e-01 4.9766035e-01 4.1449626e-01 6.0551856e-01 3.0546431e-01 2.0656129e-01 3.4780839e+00 3.2028668e+00 3.6478832e+00 2.7001131e+00 3.3123070e+00 3.1424188e+00 3.3940268e+00 2.0081113e+00 3.3027430e+00 2.5846998e+00 2.2899742e+00 2.8843735e+00 2.7014135e+00 3.3579678e+00 2.2804674e+00 3.1447330e+00 3.1614572e+00 2.7347909e+00 3.2266676e+00 2.5600441e+00 3.4989115e+00 2.6835197e+00 3.5848035e+00 3.3425343e+00 2.9944056e+00 3.1272113e+00 3.5315985e+00 3.7321938e+00 3.1736230e+00 2.1642821e+00 2.4763086e+00 2.3729779e+00 2.5613679e+00 3.7645411e+00 3.1602773e+00 3.1861493e+00 3.4298218e+00 3.1090174e+00 2.7503801e+00 2.6773131e+00 3.0414782e+00 3.2606191e+00 2.6626548e+00 2.0308266e+00 2.8549070e+00 2.8371552e+00 2.8500790e+00 2.9720515e+00 1.7439430e+00 2.7570191e+00 4.7646254e+00 3.8019108e+00 4.6714768e+00 4.2777154e+00 4.5341669e+00 5.3940437e+00 3.2096520e+00 5.0408889e+00 4.5037829e+00 4.9318274e+00 3.8493108e+00 4.0147814e+00 4.2656755e+00 3.7323432e+00 3.9122146e+00 4.0862794e+00 4.1939019e+00 5.5136120e+00 5.7113100e+00 3.6836404e+00 4.4947801e+00 3.6298047e+00 5.4953655e+00 3.6181784e+00 4.4396174e+00 4.7440323e+00 3.5161021e+00 3.6013159e+00 4.3259034e+00 4.5411167e+00 4.8804165e+00 5.2620015e+00 4.3431589e+00 3.7666196e+00 4.2394195e+00 4.9871255e+00 4.3755778e+00 4.1864815e+00 3.5032323e+00 4.1868319e+00 4.4036244e+00 3.9638383e+00 3.8019108e+00 4.6672392e+00 4.5155386e+00 4.0245873e+00 3.7349501e+00 3.9420153e+00 4.1660972e+00 3.7835217e+00 1.2418578e-01 7.0826681e-01 9.4125538e-01 1.1340084e+00 2.1845981e-01 4.4417983e-01 8.2105460e-01 2.1845981e-01 3.8776762e-01 4.1449626e-01 4.2418962e-01 9.1075311e-01 3.7255734e-01 4.8036801e-01 6.6827038e-01 2.5651975e-01 6.4704320e-01 2.0656129e-01 6.8961791e-01 3.2586371e-01 3.4686627e+00 3.1154621e+00 3.6024772e+00 2.5108475e+00 3.2290313e+00 2.9704704e+00 3.2809332e+00 1.7903952e+00 3.2349033e+00 2.3960250e+00 2.0600195e+00 2.7476411e+00 2.5610667e+00 3.2181149e+00 2.1323638e+00 3.1154281e+00 2.9881598e+00 2.5786309e+00 3.0947136e+00 2.3839455e+00 3.3448197e+00 2.5821869e+00 3.4532666e+00 3.1998457e+00 2.9200439e+00 3.0794219e+00 3.4771054e+00 3.6510733e+00 3.0328831e+00 2.0197525e+00 2.2893157e+00 2.1858172e+00 2.4166535e+00 3.6030381e+00 2.9770247e+00 3.0492285e+00 3.3713329e+00 2.9974031e+00 2.5833316e+00 2.4944673e+00 2.8535197e+00 3.1260028e+00 2.5104998e+00 1.8109223e+00 2.6804452e+00 2.6742360e+00 2.6875169e+00 2.8656044e+00 1.5447938e+00 2.5961850e+00 4.6147552e+00 3.6320149e+00 4.5850999e+00 4.1288948e+00 4.3989089e+00 5.3208661e+00 3.0146208e+00 4.9525575e+00 4.3778283e+00 4.8485483e+00 3.7416375e+00 3.8836706e+00 4.1692394e+00 3.5584719e+00 3.7545764e+00 3.9635178e+00 4.0653249e+00 5.4465238e+00 5.6318041e+00 3.5148434e+00 4.4004449e+00 3.4571917e+00 5.4256316e+00 3.4931266e+00 4.3243671e+00 4.6617210e+00 3.3863989e+00 3.4595139e+00 4.1872611e+00 4.4691596e+00 4.8126955e+00 5.2323771e+00 4.2057897e+00 3.6309135e+00 4.0714444e+00 4.9544547e+00 4.2355968e+00 4.0495222e+00 3.3563815e+00 4.1075398e+00 4.2957899e+00 3.9065020e+00 3.6320149e+00 4.5543025e+00 4.4046818e+00 3.9362563e+00 3.6038441e+00 3.8285790e+00 4.0238937e+00 3.6204282e+00 6.2538346e-01 1.0167353e+00 1.1763980e+00 1.4096146e-01 4.1449626e-01 7.4740267e-01 1.4096146e-01 4.4535192e-01 3.7427929e-01 4.5581864e-01 8.2135873e-01 4.4535192e-01 5.0503591e-01 7.3145860e-01 2.1269358e-01 7.1421512e-01 2.5251796e-01 6.8961791e-01 2.8192292e-01 3.4295980e+00 3.0905489e+00 3.5700123e+00 2.4944673e+00 3.2020292e+00 2.9613737e+00 3.2617087e+00 1.7750284e+00 3.2049793e+00 2.3909366e+00 2.0308266e+00 2.7326472e+00 2.5286673e+00 3.2028668e+00 2.1181082e+00 3.0792693e+00 2.9816970e+00 2.5624932e+00 3.0681391e+00 2.3677174e+00 3.3352475e+00 2.5566444e+00 3.4334259e+00 3.1839972e+00 2.8907702e+00 3.0462904e+00 3.4448498e+00 3.6256155e+00 3.0181476e+00 1.9946242e+00 2.2719663e+00 2.1665831e+00 2.3980102e+00 3.5922217e+00 2.9733478e+00 3.0355056e+00 3.3410264e+00 2.9673667e+00 2.5744164e+00 2.4820750e+00 2.8455141e+00 3.1100045e+00 2.4920874e+00 1.7903952e+00 2.6704164e+00 2.6637326e+00 2.6767607e+00 2.8425716e+00 1.5257596e+00 2.5839288e+00 4.6057175e+00 3.6244539e+00 4.5619285e+00 4.1170543e+00 4.3856360e+00 5.2953657e+00 3.0110441e+00 4.9290739e+00 4.3593510e+00 4.8266994e+00 3.7227460e+00 3.8675033e+00 4.1480696e+00 3.5505922e+00 3.7479505e+00 3.9489183e+00 4.0495222e+00 5.4213759e+00 5.6069704e+00 3.4988409e+00 4.3796539e+00 3.4519560e+00 5.3990720e+00 3.4751739e+00 4.3070102e+00 4.6372963e+00 3.3701472e+00 3.4467337e+00 4.1738909e+00 4.4422690e+00 4.7852959e+00 5.2004339e+00 4.1925494e+00 3.6148707e+00 4.0613681e+00 4.9222119e+00 4.2248103e+00 4.0355816e+00 3.3448336e+00 4.0832977e+00 4.2781022e+00 3.8793995e+00 3.6244539e+00 4.5369609e+00 4.3880177e+00 3.9147164e+00 3.5857963e+00 3.8105301e+00 4.0134966e+00 3.6122845e+00 7.1799256e-01 8.0358695e-01 5.5419992e-01 4.6472023e-01 2.5651975e-01 5.5419992e-01 1.0198386e+00 3.2352160e-01 4.1586001e-01 1.2565757e+00 1.0054037e+00 4.1586001e-01 5.2574978e-01 6.4806901e-01 4.5581864e-01 8.0619006e-01 3.2586371e-01 4.1586001e-01 3.3274681e+00 3.0643176e+00 3.5031390e+00 2.5831315e+00 3.1734856e+00 3.0256804e+00 3.2593968e+00 1.9049236e+00 3.1662394e+00 2.4587503e+00 2.1948123e+00 2.7522526e+00 2.5874301e+00 3.2341367e+00 2.1493214e+00 2.9966141e+00 3.0389019e+00 2.6214821e+00 3.0978571e+00 2.4463233e+00 3.3673968e+00 2.5500177e+00 3.4578354e+00 3.2240818e+00 2.8578051e+00 2.9828212e+00 3.3905763e+00 3.5904118e+00 3.0455175e+00 2.0467937e+00 2.3640301e+00 2.2638728e+00 2.4385827e+00 3.6424937e+00 3.0387448e+00 3.0543001e+00 3.2867025e+00 2.9810914e+00 2.6291524e+00 2.5579619e+00 2.9291061e+00 3.1351569e+00 2.5421955e+00 1.9274228e+00 2.7359835e+00 2.7196686e+00 2.7293044e+00 2.8418790e+00 1.6234861e+00 2.6349941e+00 4.6268918e+00 3.6735954e+00 4.5276539e+00 4.1519514e+00 4.3981255e+00 5.2510005e+00 3.0847983e+00 4.9049143e+00 4.3738893e+00 4.7804645e+00 3.7059360e+00 3.8806135e+00 4.1210200e+00 3.6007179e+00 3.7674167e+00 3.9401211e+00 4.0632074e+00 5.3683319e+00 5.5675337e+00 3.5650560e+00 4.3467079e+00 3.4964385e+00 5.3534247e+00 3.4817971e+00 4.3007421e+00 4.6057628e+00 3.3796707e+00 3.4684743e+00 4.1910954e+00 4.4033511e+00 4.7374076e+00 5.1107389e+00 4.2056854e+00 3.6417452e+00 4.1251907e+00 4.8290847e+00 4.2339606e+00 4.0576409e+00 3.3702841e+00 4.0376849e+00 4.2550416e+00 3.8015574e+00 3.6735954e+00 4.5249462e+00 4.3662620e+00 3.8699102e+00 3.5979726e+00 3.8007870e+00 4.0252278e+00 3.6568095e+00 3.0811765e-01 1.0065841e+00 9.1075311e-01 6.2538346e-01 1.0065841e+00 1.2125198e+00 7.0086313e-01 6.1623531e-01 1.8279039e+00 1.0613462e+00 6.9369532e-01 4.8135521e-01 1.1149070e+00 3.0811765e-01 9.7098574e-01 4.0293660e-01 8.0358695e-01 3.4154940e+00 3.1439160e+00 3.5872997e+00 2.8054691e+00 3.2839149e+00 3.1127876e+00 3.3274872e+00 2.2159139e+00 3.2598167e+00 2.6167778e+00 2.5758644e+00 2.8523754e+00 2.8256291e+00 3.3122081e+00 2.3003824e+00 3.0947136e+00 3.1160876e+00 2.7384939e+00 3.2940867e+00 2.6281170e+00 3.4401593e+00 2.6851662e+00 3.5758474e+00 3.3024121e+00 2.9636544e+00 3.0850893e+00 3.4935692e+00 3.6787177e+00 3.1382691e+00 2.2643860e+00 2.5838312e+00 2.4957147e+00 2.5876691e+00 3.7272092e+00 3.1148696e+00 3.1192689e+00 3.3731473e+00 3.1641238e+00 2.7164367e+00 2.7371177e+00 3.0433470e+00 3.2094276e+00 2.6989752e+00 2.2729593e+00 2.8576425e+00 2.7954161e+00 2.8234677e+00 2.9407805e+00 1.9980146e+00 2.7511201e+00 4.6993349e+00 3.7716613e+00 4.6090409e+00 4.2170163e+00 4.4740971e+00 5.3233695e+00 3.2312218e+00 4.9715358e+00 4.4649192e+00 4.8634712e+00 3.7907269e+00 3.9777091e+00 4.2102908e+00 3.7293867e+00 3.8887827e+00 4.0321207e+00 4.1304736e+00 5.4336694e+00 5.6535520e+00 3.7088191e+00 4.4333012e+00 3.6017014e+00 5.4287623e+00 3.5939935e+00 4.3696884e+00 4.6684884e+00 3.4865359e+00 3.5518450e+00 4.2777882e+00 4.4716883e+00 4.8204359e+00 5.1830573e+00 4.2975164e+00 3.7189281e+00 4.1915116e+00 4.9282164e+00 4.3126073e+00 4.1182993e+00 3.4568393e+00 4.1297239e+00 4.3496867e+00 3.9207320e+00 3.7716613e+00 4.6018276e+00 4.4564872e+00 3.9827168e+00 3.7295388e+00 3.8905364e+00 4.1037903e+00 3.7281480e+00 1.1474460e+00 1.0344911e+00 7.0043186e-01 1.1474460e+00 1.4311891e+00 8.2654509e-01 7.6787403e-01 1.9730918e+00 1.3073038e+00 7.9878917e-01 6.2407309e-01 1.2632199e+00 5.0503591e-01 1.1833480e+00 5.0905001e-01 9.4080461e-01 3.4392518e+00 3.2008338e+00 3.6261197e+00 2.9076510e+00 3.3439089e+00 3.2073032e+00 3.3907558e+00 2.3329978e+00 3.3168472e+00 2.7081478e+00 2.6929215e+00 2.9283888e+00 2.9264154e+00 3.3942456e+00 2.3848677e+00 3.1312883e+00 3.2027420e+00 2.8385969e+00 3.3781905e+00 2.7324845e+00 3.5133135e+00 2.7602023e+00 3.6563535e+00 3.3905763e+00 3.0256209e+00 3.1312883e+00 3.5423793e+00 3.7299679e+00 3.2179031e+00 2.3661539e+00 2.6906231e+00 2.6054995e+00 2.6801752e+00 3.8138933e+00 3.2027420e+00 3.1888037e+00 3.4187265e+00 3.2459231e+00 2.8060305e+00 2.8359967e+00 3.1453916e+00 3.2886661e+00 2.7943622e+00 2.3874574e+00 2.9533314e+00 2.8877105e+00 2.9141136e+00 3.0147886e+00 2.0992326e+00 2.8425716e+00 4.7630756e+00 3.8535531e+00 4.6550014e+00 4.2947468e+00 4.5389196e+00 5.3632740e+00 3.3234239e+00 5.0232338e+00 4.5363757e+00 4.8985515e+00 3.8441304e+00 4.0476997e+00 4.2599433e+00 3.8106152e+00 3.9516603e+00 4.0850903e+00 4.1995425e+00 5.4671477e+00 5.6957748e+00 3.8037734e+00 4.4771379e+00 3.6783395e+00 5.4690202e+00 3.6632177e+00 4.4259826e+00 4.7160634e+00 3.5560806e+00 3.6239123e+00 4.3464973e+00 4.5187406e+00 4.8619146e+00 5.2001625e+00 4.3635746e+00 3.7979761e+00 4.2843668e+00 4.9451734e+00 4.3709882e+00 4.1899199e+00 3.5299194e+00 4.1707976e+00 4.3972344e+00 3.9457376e+00 3.8535531e+00 4.6546556e+00 4.5024055e+00 4.0227020e+00 3.8004969e+00 3.9484773e+00 4.1635108e+00 3.8079860e+00 3.0811765e-01 6.5223271e-01 0.0000000e+00 5.0991930e-01 3.2586371e-01 4.2667565e-01 8.3172002e-01 5.0991930e-01 5.6769031e-01 7.5082357e-01 2.1845981e-01 7.0479928e-01 3.0811765e-01 6.4755655e-01 2.1845981e-01 3.4865562e+00 3.1726595e+00 3.6377960e+00 2.5987470e+00 3.2814045e+00 3.0627375e+00 3.3515846e+00 1.8841865e+00 3.2769379e+00 2.5038079e+00 2.1311468e+00 2.8311678e+00 2.6104387e+00 3.2962520e+00 2.2214438e+00 3.1433122e+00 3.0878634e+00 2.6552472e+00 3.1570103e+00 2.4668912e+00 3.4394878e+00 2.6411293e+00 3.5233648e+00 3.2747247e+00 2.9659871e+00 3.1154783e+00 3.5134741e+00 3.7059620e+00 3.1148696e+00 2.0851901e+00 2.3731428e+00 2.2655571e+00 2.4927109e+00 3.6920087e+00 3.0823446e+00 3.1337459e+00 3.4135200e+00 3.0481703e+00 2.6780487e+00 2.5874301e+00 2.9489507e+00 3.2027420e+00 2.5873149e+00 1.8973383e+00 2.7738355e+00 2.7632614e+00 2.7778954e+00 2.9269923e+00 1.6390769e+00 2.6848587e+00 4.7106706e+00 3.7313856e+00 4.6446321e+00 4.2142736e+00 4.4836580e+00 5.3716885e+00 3.1250284e+00 5.0074019e+00 4.4485220e+00 4.9128219e+00 3.8150636e+00 3.9624529e+00 4.2358121e+00 3.6602286e+00 3.8605980e+00 4.0488387e+00 4.1418643e+00 5.4970002e+00 5.6855224e+00 3.5964347e+00 4.4685630e+00 3.5634461e+00 5.4730406e+00 3.5693950e+00 4.3989089e+00 4.7150659e+00 3.4668130e+00 3.5464993e+00 4.2723380e+00 4.5155386e+00 4.8594290e+00 5.2647079e+00 4.2921213e+00 3.7064459e+00 4.1581964e+00 4.9913682e+00 4.3286007e+00 4.1303097e+00 3.4468286e+00 4.1669742e+00 4.3729308e+00 3.9624170e+00 3.7313856e+00 4.6297577e+00 4.4844827e+00 4.0056359e+00 3.6817961e+00 3.9035218e+00 4.1179678e+00 3.7164366e+00 5.2942799e-01 3.0811765e-01 6.0611244e-01 3.2586371e-01 3.0546431e-01 9.4125538e-01 6.0060595e-01 5.2574978e-01 8.1558458e-01 2.8507955e-01 6.4755655e-01 4.1312257e-01 5.5419992e-01 2.0656129e-01 3.7045940e+00 3.4142500e+00 3.8690719e+00 2.8688189e+00 3.5226542e+00 3.3385842e+00 3.6010215e+00 2.1580776e+00 3.5196916e+00 2.7652601e+00 2.4083873e+00 3.0820950e+00 2.8783309e+00 3.5617386e+00 2.4693940e+00 3.3658240e+00 3.3558214e+00 2.9322808e+00 3.4112518e+00 2.7424260e+00 3.6945405e+00 2.8867565e+00 3.7848217e+00 3.5471494e+00 3.2076743e+00 3.3449470e+00 3.7498842e+00 3.9450818e+00 3.3735875e+00 2.3490515e+00 2.6490839e+00 2.5444216e+00 2.7549369e+00 3.9621873e+00 3.3527310e+00 3.3865418e+00 3.6475099e+00 3.3024121e+00 2.9459653e+00 2.8566322e+00 3.2311957e+00 3.4653703e+00 2.8535197e+00 2.1708533e+00 3.0455175e+00 3.0364473e+00 3.0465086e+00 3.1799184e+00 1.8842354e+00 2.9509414e+00 4.9594922e+00 3.9924292e+00 4.8844442e+00 4.4804205e+00 4.7354764e+00 5.6130421e+00 3.3873806e+00 5.2583931e+00 4.7090394e+00 5.1413739e+00 4.0532097e+00 4.2156327e+00 4.4735121e+00 3.9153764e+00 4.0928954e+00 4.2826383e+00 4.4004808e+00 5.7341534e+00 5.9271927e+00 3.8700742e+00 4.7016733e+00 3.8156003e+00 5.7155096e+00 3.8175051e+00 4.6462020e+00 4.9620553e+00 3.7143727e+00 3.8000004e+00 4.5254820e+00 4.7613782e+00 5.0991856e+00 5.4888822e+00 4.5411167e+00 3.9718373e+00 4.4397363e+00 5.2074442e+00 4.5701358e+00 4.3916992e+00 3.6996802e+00 4.3970196e+00 4.6045465e+00 4.1691696e+00 3.9924292e+00 4.8725396e+00 4.7150659e+00 4.2256400e+00 3.9292780e+00 4.1454529e+00 4.3599285e+00 3.9798670e+00 6.5223271e-01 1.1268457e+00 4.1449626e-01 5.0090417e-01 1.3784393e+00 1.1053488e+00 5.8851328e-01 6.6827038e-01 7.6787403e-01 4.8036801e-01 9.0852141e-01 2.8192292e-01 5.0905001e-01 3.5117473e+00 3.2719724e+00 3.6961290e+00 2.8060101e+00 3.3799936e+00 3.2401159e+00 3.4709594e+00 2.1293854e+00 3.3643376e+00 2.6848587e+00 2.4115946e+00 2.9723937e+00 2.7984009e+00 3.4455106e+00 2.3749088e+00 3.1913397e+00 3.2574960e+00 2.8320532e+00 3.3150921e+00 2.6637326e+00 3.5883493e+00 2.7640668e+00 3.6695251e+00 3.4317240e+00 3.0617355e+00 3.1820648e+00 3.5855784e+00 3.7950050e+00 3.2620096e+00 2.2645766e+00 2.5831070e+00 2.4810276e+00 2.6563403e+00 3.8575846e+00 3.2574960e+00 3.2718360e+00 3.4856613e+00 3.1913594e+00 2.8466990e+00 2.7801709e+00 3.1437608e+00 3.3466419e+00 2.7595194e+00 2.1498672e+00 2.9543365e+00 2.9330570e+00 2.9459653e+00 3.0511838e+00 1.8555964e+00 2.8534301e+00 4.8490742e+00 3.8962785e+00 4.7308926e+00 4.3643842e+00 4.6144072e+00 5.4442665e+00 3.3129652e+00 5.0997539e+00 4.5816539e+00 4.9883395e+00 3.9213002e+00 4.0961125e+00 4.3313403e+00 3.8279951e+00 4.0003537e+00 4.1625074e+00 4.2731561e+00 5.5604940e+00 5.7635900e+00 3.7812981e+00 4.5580745e+00 3.7236571e+00 5.5437155e+00 3.6992145e+00 4.5120086e+00 4.8012240e+00 3.5989213e+00 3.6872980e+00 4.4084575e+00 4.5949523e+00 4.9306472e+00 5.2918657e+00 4.4250143e+00 3.8510143e+00 4.3338058e+00 5.0198276e+00 4.4571663e+00 4.2687771e+00 3.5910375e+00 4.2454653e+00 4.4729144e+00 4.0139676e+00 3.8962785e+00 4.7377574e+00 4.5853438e+00 4.0877338e+00 3.8179781e+00 4.0161568e+00 4.2490407e+00 3.8755800e+00 5.0991930e-01 3.2586371e-01 4.2667565e-01 8.3172002e-01 5.0991930e-01 5.6769031e-01 7.5082357e-01 2.1845981e-01 7.0479928e-01 3.0811765e-01 6.4755655e-01 2.1845981e-01 3.4865562e+00 3.1726595e+00 3.6377960e+00 2.5987470e+00 3.2814045e+00 3.0627375e+00 3.3515846e+00 1.8841865e+00 3.2769379e+00 2.5038079e+00 2.1311468e+00 2.8311678e+00 2.6104387e+00 3.2962520e+00 2.2214438e+00 3.1433122e+00 3.0878634e+00 2.6552472e+00 3.1570103e+00 2.4668912e+00 3.4394878e+00 2.6411293e+00 3.5233648e+00 3.2747247e+00 2.9659871e+00 3.1154783e+00 3.5134741e+00 3.7059620e+00 3.1148696e+00 2.0851901e+00 2.3731428e+00 2.2655571e+00 2.4927109e+00 3.6920087e+00 3.0823446e+00 3.1337459e+00 3.4135200e+00 3.0481703e+00 2.6780487e+00 2.5874301e+00 2.9489507e+00 3.2027420e+00 2.5873149e+00 1.8973383e+00 2.7738355e+00 2.7632614e+00 2.7778954e+00 2.9269923e+00 1.6390769e+00 2.6848587e+00 4.7106706e+00 3.7313856e+00 4.6446321e+00 4.2142736e+00 4.4836580e+00 5.3716885e+00 3.1250284e+00 5.0074019e+00 4.4485220e+00 4.9128219e+00 3.8150636e+00 3.9624529e+00 4.2358121e+00 3.6602286e+00 3.8605980e+00 4.0488387e+00 4.1418643e+00 5.4970002e+00 5.6855224e+00 3.5964347e+00 4.4685630e+00 3.5634461e+00 5.4730406e+00 3.5693950e+00 4.3989089e+00 4.7150659e+00 3.4668130e+00 3.5464993e+00 4.2723380e+00 4.5155386e+00 4.8594290e+00 5.2647079e+00 4.2921213e+00 3.7064459e+00 4.1581964e+00 4.9913682e+00 4.3286007e+00 4.1303097e+00 3.4468286e+00 4.1669742e+00 4.3729308e+00 3.9624170e+00 3.7313856e+00 4.6297577e+00 4.4844827e+00 4.0056359e+00 3.6817961e+00 3.9035218e+00 4.1179678e+00 3.7164366e+00 7.3813096e-01 6.8961791e-01 7.0086313e-01 2.0000000e-01 7.3805807e-01 1.0030700e+00 4.0293660e-01 9.4352681e-01 2.5251796e-01 1.0120221e+00 6.2024833e-01 3.8265307e+00 3.4552560e+00 3.9537404e+00 2.8022534e+00 3.5701225e+00 3.2863508e+00 3.6126198e+00 2.0524386e+00 3.5845127e+00 2.6848587e+00 2.2888897e+00 3.0684384e+00 2.8791325e+00 3.5464993e+00 2.4469125e+00 3.4686755e+00 3.2961206e+00 2.9072057e+00 3.4107902e+00 2.6959009e+00 3.6545040e+00 2.9195876e+00 3.7806187e+00 3.5312474e+00 3.2669151e+00 3.4295849e+00 3.8277021e+00 3.9909030e+00 3.3562690e+00 2.3465937e+00 2.5906376e+00 2.4892531e+00 2.7423171e+00 3.9193693e+00 3.2780620e+00 3.3708389e+00 3.7190229e+00 3.3268984e+00 2.8983020e+00 2.7954161e+00 3.1611584e+00 3.4557351e+00 2.8328337e+00 2.0658700e+00 2.9919517e+00 2.9960210e+00 3.0059712e+00 3.2048547e+00 1.8038968e+00 2.9141136e+00 4.9189452e+00 3.9342203e+00 4.9208723e+00 4.4494735e+00 4.7160542e+00 5.6635213e+00 3.2909043e+00 5.2946188e+00 4.7062325e+00 5.1779277e+00 4.0657707e+00 4.2053647e+00 4.4986279e+00 3.8509694e+00 4.0384339e+00 4.2739171e+00 4.3927415e+00 5.7909894e+00 5.9706827e+00 3.8237409e+00 4.7267599e+00 3.7490739e+00 5.7704875e+00 3.8154018e+00 4.6503268e+00 5.0044958e+00 3.7060524e+00 3.7762575e+00 4.5037232e+00 4.8164539e+00 5.1574084e+00 5.5860081e+00 4.5195237e+00 3.9601358e+00 4.3901702e+00 5.2992055e+00 4.5412859e+00 4.3739561e+00 3.6694918e+00 4.4403343e+00 4.6130415e+00 4.2323959e+00 3.9342203e+00 4.8773871e+00 4.7190595e+00 4.2559866e+00 3.9201797e+00 4.1523445e+00 4.3289315e+00 3.9302319e+00 2.1845981e-01 1.1486378e+00 7.0784540e-01 4.0438741e-01 5.0503591e-01 4.4651726e-01 4.0147421e-01 5.0905001e-01 3.2352160e-01 1.4096146e-01 3.4156574e+00 3.1235447e+00 3.5778307e+00 2.6097685e+00 3.2346686e+00 3.0478400e+00 3.3101102e+00 1.9193093e+00 3.2270948e+00 2.4922287e+00 2.2081369e+00 2.7965957e+00 2.6184141e+00 3.2685282e+00 2.1916898e+00 3.0773654e+00 3.0673749e+00 2.6423274e+00 3.1444983e+00 2.4678343e+00 3.4088888e+00 2.6016025e+00 3.4988409e+00 3.2521427e+00 2.9171710e+00 3.0559188e+00 3.4597125e+00 3.6553612e+00 3.0847983e+00 2.0765921e+00 2.3848740e+00 2.2817008e+00 2.4722095e+00 3.6724425e+00 3.0650478e+00 3.0981264e+00 3.3567173e+00 3.0288896e+00 2.6566259e+00 2.5851693e+00 2.9455446e+00 3.1719381e+00 2.5729378e+00 1.9450955e+00 2.7611864e+00 2.7431084e+00 2.7570191e+00 2.8884401e+00 1.6625998e+00 2.6648989e+00 4.6768871e+00 3.7101281e+00 4.5948688e+00 4.1876541e+00 4.4480565e+00 5.3202405e+00 3.1169790e+00 4.9630576e+00 4.4189653e+00 4.8572313e+00 3.7684708e+00 3.9292780e+00 4.1872611e+00 3.6418662e+00 3.8262353e+00 4.0041417e+00 4.1076175e+00 5.4411191e+00 5.6370076e+00 3.5929878e+00 4.4174698e+00 3.5389106e+00 5.4223305e+00 3.5340177e+00 4.3569684e+00 4.6672392e+00 3.4309563e+00 3.5133135e+00 4.2392500e+00 4.4661721e+00 4.8075242e+00 5.1977119e+00 4.2572858e+00 3.6784045e+00 4.1454521e+00 4.9233665e+00 4.2900309e+00 4.0984960e+00 3.4145942e+00 4.1120703e+00 4.3243538e+00 3.8957047e+00 3.7101281e+00 4.5857922e+00 4.4360042e+00 3.9497198e+00 3.6509512e+00 3.8600234e+00 4.0800357e+00 3.6915258e+00 1.2223099e+00 6.2024833e-01 3.7255734e-01 6.2081167e-01 5.0905001e-01 3.7598397e-01 4.4651726e-01 3.4583729e-01 2.1269358e-01 3.6091470e+00 3.3105724e+00 3.7708932e+00 2.7979838e+00 3.4251430e+00 3.2391031e+00 3.4951642e+00 2.1075335e+00 3.4235403e+00 2.6687055e+00 2.3989464e+00 2.9762945e+00 2.8216056e+00 3.4603628e+00 2.3673218e+00 3.2680041e+00 3.2498302e+00 2.8414525e+00 3.3361912e+00 2.6626548e+00 3.5849794e+00 2.7906520e+00 3.6926714e+00 3.4497714e+00 3.1105675e+00 3.2468925e+00 3.6557661e+00 3.8432801e+00 3.2705166e+00 2.2719663e+00 2.5786309e+00 2.4784234e+00 2.6629602e+00 3.8619321e+00 3.2465133e+00 3.2780765e+00 3.5475145e+00 3.2266676e+00 2.8416143e+00 2.7719788e+00 3.1392934e+00 3.3624692e+00 2.7656089e+00 2.1335398e+00 2.9496515e+00 2.9338590e+00 2.9447165e+00 3.0808399e+00 1.8330979e+00 2.8520904e+00 4.8482992e+00 3.8884996e+00 4.7814945e+00 4.3763964e+00 4.6280797e+00 5.5131379e+00 3.2922206e+00 5.1594703e+00 4.6125121e+00 5.0342965e+00 3.9453171e+00 4.1137002e+00 4.3683295e+00 3.8151836e+00 3.9816719e+00 4.1715493e+00 4.2963195e+00 5.6322635e+00 5.8289682e+00 3.7874513e+00 4.5945190e+00 3.7079546e+00 5.6180203e+00 3.7164611e+00 4.5394421e+00 4.8614468e+00 3.6107037e+00 3.6929889e+00 4.4201622e+00 4.6634723e+00 5.0015266e+00 5.3906681e+00 4.4348302e+00 3.8718490e+00 4.3427947e+00 5.1078309e+00 4.4583488e+00 4.2864208e+00 3.5920050e+00 4.2919639e+00 4.4953238e+00 4.0619633e+00 3.8884996e+00 4.7650352e+00 4.6046026e+00 4.1173867e+00 3.8320624e+00 4.0389546e+00 4.2480032e+00 3.8727359e+00 9.0049692e-01 1.2307737e+00 1.5483011e+00 7.1462831e-01 1.5272277e+00 9.0074515e-01 1.4700179e+00 1.0331736e+00 3.7896333e+00 3.4304205e+00 3.9179666e+00 2.7683644e+00 3.5321772e+00 3.2685282e+00 3.5962433e+00 2.0250421e+00 3.5485736e+00 2.6642702e+00 2.2244833e+00 3.0435803e+00 2.8325748e+00 3.5230967e+00 2.4205131e+00 3.4307077e+00 3.2815626e+00 2.8843735e+00 3.3658240e+00 2.6687055e+00 3.6389628e+00 2.8830783e+00 3.7490739e+00 3.5087649e+00 3.2305801e+00 3.3908902e+00 3.7876239e+00 3.9561876e+00 3.3306114e+00 2.3112968e+00 2.5604155e+00 2.4585271e+00 2.7122813e+00 3.8971376e+00 3.2667813e+00 3.3674720e+00 3.6849783e+00 3.2837729e+00 2.8840079e+00 2.7685572e+00 3.1442943e+00 3.4335342e+00 2.8028287e+00 2.0286682e+00 2.9704704e+00 2.9822537e+00 2.9868163e+00 3.1741954e+00 1.7644184e+00 2.8908296e+00 4.8985114e+00 3.9102500e+00 4.8863496e+00 4.4272873e+00 4.6888407e+00 5.6294495e+00 3.2706756e+00 5.2636641e+00 4.6765452e+00 5.1547576e+00 4.0378383e+00 4.1743230e+00 4.4638518e+00 3.8230269e+00 4.0056625e+00 4.2450961e+00 4.3676124e+00 5.7745449e+00 5.9344852e+00 3.7932062e+00 4.6942925e+00 3.7245053e+00 5.7354045e+00 3.7814598e+00 4.6271849e+00 4.9763401e+00 3.6736483e+00 3.7511498e+00 4.4747039e+00 4.7841150e+00 5.1205765e+00 5.5660104e+00 4.4889834e+00 3.9348528e+00 4.3728356e+00 5.2548517e+00 4.5226167e+00 4.3526639e+00 3.6449787e+00 4.4041536e+00 4.5787890e+00 4.1879339e+00 3.9102500e+00 4.8490587e+00 4.6897155e+00 4.2150171e+00 3.8841455e+00 4.1203091e+00 4.3121165e+00 3.9109678e+00 6.7975091e-01 9.0056222e-01 4.1586001e-01 8.2275389e-01 2.0656129e-01 9.4287188e-01 6.0121055e-01 3.8264361e+00 3.4551376e+00 3.9537404e+00 2.8149627e+00 3.5710248e+00 3.2874334e+00 3.6122384e+00 2.0711789e+00 3.5849006e+00 2.6879715e+00 2.3281827e+00 3.0685922e+00 2.8946126e+00 3.5468964e+00 2.4478108e+00 3.4686755e+00 3.2962520e+00 2.9098194e+00 3.4214793e+00 2.7033034e+00 3.6543993e+00 2.9209919e+00 3.7841436e+00 3.5321717e+00 3.2673909e+00 3.4297053e+00 3.8284763e+00 3.9909892e+00 3.3567173e+00 2.3533545e+00 2.6019240e+00 2.5015675e+00 2.7452885e+00 3.9207248e+00 3.2781950e+00 3.3698144e+00 3.7190229e+00 3.3356294e+00 2.8984764e+00 2.8022534e+00 3.1646752e+00 3.4558535e+00 2.8373077e+00 2.0905239e+00 2.9944056e+00 2.9961831e+00 3.0065426e+00 3.2053509e+00 1.8216743e+00 2.9155237e+00 4.9187518e+00 3.9355645e+00 4.9209267e+00 4.4497146e+00 4.7161140e+00 5.6635613e+00 3.2956846e+00 5.2947833e+00 4.7084108e+00 5.1767384e+00 4.0656879e+00 4.2065257e+00 4.4986941e+00 3.8543544e+00 4.0391220e+00 4.2738429e+00 4.3928114e+00 5.7890564e+00 5.9715517e+00 3.8320624e+00 4.7267005e+00 3.7498842e+00 5.7708014e+00 3.8168398e+00 4.6501080e+00 5.0044433e+00 3.7068836e+00 3.7763550e+00 4.5042646e+00 4.8165110e+00 5.1578102e+00 5.5839155e+00 4.5200609e+00 3.9608542e+00 4.3918790e+00 5.2992517e+00 4.5407542e+00 4.3739561e+00 3.6695956e+00 4.4403343e+00 4.6130415e+00 4.2323959e+00 3.9355645e+00 4.8773316e+00 4.7188476e+00 4.2560614e+00 3.9234348e+00 4.1524235e+00 4.3283407e+00 3.9303212e+00 3.8934542e-01 5.4292906e-01 4.4535192e-01 5.3309112e-01 4.5581864e-01 4.2538717e-01 3.3319064e+00 3.0058998e+00 3.4822680e+00 2.4967542e+00 3.1249915e+00 2.9284660e+00 3.1836200e+00 1.8265014e+00 3.1331426e+00 2.3481462e+00 2.1458939e+00 2.6572703e+00 2.5437119e+00 3.1519721e+00 2.0470220e+00 2.9815576e+00 2.9302134e+00 2.5421955e+00 3.0374850e+00 2.3632684e+00 3.2598750e+00 2.4873223e+00 3.3884269e+00 3.1477087e+00 2.8156804e+00 2.9556616e+00 3.3682605e+00 3.5401725e+00 2.9561205e+00 1.9790422e+00 2.2832934e+00 2.1885968e+00 2.3571494e+00 3.5486864e+00 2.9260462e+00 2.9587612e+00 3.2530866e+00 2.9361879e+00 2.5256527e+00 2.4631898e+00 2.8325946e+00 3.0534395e+00 2.4619105e+00 1.8618589e+00 2.6377354e+00 2.6235630e+00 2.6314198e+00 2.7785210e+00 1.5475473e+00 2.5392051e+00 4.5179415e+00 3.5641186e+00 4.4752183e+00 4.0626016e+00 4.3069105e+00 5.2164277e+00 2.9689697e+00 4.8634846e+00 4.3067423e+00 4.7194915e+00 3.6262912e+00 3.7979761e+00 4.0547736e+00 3.4875352e+00 3.6400497e+00 3.8418637e+00 3.9849753e+00 5.3352888e+00 5.5294519e+00 3.4830211e+00 4.2776053e+00 3.3760149e+00 5.3253207e+00 3.4004918e+00 4.2238184e+00 4.5645220e+00 3.2914954e+00 3.3718862e+00 4.0995928e+00 4.3725648e+00 4.7075069e+00 5.1063282e+00 4.1113292e+00 3.5651462e+00 4.0375056e+00 4.8132427e+00 4.1268905e+00 3.9732869e+00 3.2685282e+00 3.9810803e+00 4.1706050e+00 3.7449914e+00 3.5641186e+00 4.4464848e+00 4.2774083e+00 3.7941767e+00 3.5148434e+00 3.7206115e+00 3.9162695e+00 3.5510950e+00 8.6137722e-01 3.2352160e-01 7.6166891e-01 4.2667565e-01 6.2660376e-01 3.0634640e+00 2.7392828e+00 3.2125175e+00 2.3391296e+00 2.8734025e+00 2.6707502e+00 2.9145708e+00 1.7569738e+00 2.8671376e+00 2.1479276e+00 2.1308063e+00 2.4108292e+00 2.3854031e+00 2.8851564e+00 1.8368900e+00 2.7201546e+00 2.6724144e+00 2.2982662e+00 2.8483417e+00 2.1701312e+00 3.0045018e+00 2.2531409e+00 3.1444983e+00 2.8783309e+00 2.5586145e+00 2.6967931e+00 3.1073497e+00 3.2779401e+00 2.7018605e+00 1.8104298e+00 2.1219691e+00 2.0368741e+00 2.1367260e+00 3.2905600e+00 2.6692615e+00 2.6939411e+00 2.9863438e+00 2.7320931e+00 2.2698938e+00 2.2722516e+00 2.5933163e+00 2.7845473e+00 2.2472326e+00 1.8195937e+00 2.4037412e+00 2.3571494e+00 2.3781826e+00 2.5200525e+00 1.5411691e+00 2.3001580e+00 4.2694227e+00 3.3237039e+00 4.2115652e+00 3.7930080e+00 4.0498216e+00 4.9425633e+00 2.7652100e+00 4.5847429e+00 4.0464464e+00 4.4666326e+00 3.3738930e+00 3.5479683e+00 3.8004969e+00 3.2711669e+00 3.4346585e+00 3.6043418e+00 3.7146255e+00 5.0600559e+00 5.2639977e+00 3.2609948e+00 4.0260071e+00 3.1481222e+00 5.0506841e+00 3.1599876e+00 3.9594081e+00 4.2851208e+00 3.0501817e+00 3.1181310e+00 3.8476631e+00 4.0931004e+00 4.4378867e+00 4.8317916e+00 3.8652515e+00 3.2970551e+00 3.7653550e+00 4.5583070e+00 3.8836720e+00 3.7008091e+00 3.0188386e+00 3.7282629e+00 3.9300286e+00 3.5186510e+00 3.3237039e+00 4.1891573e+00 4.0376133e+00 3.5648733e+00 3.2885200e+00 3.4693398e+00 3.6732275e+00 3.2917360e+00 8.1385214e-01 2.5251796e-01 7.6787403e-01 3.2586371e-01 3.5846101e+00 3.2546607e+00 3.7315988e+00 2.6609901e+00 3.3659358e+00 3.1439065e+00 3.4298218e+00 1.9383545e+00 3.3723944e+00 2.5580763e+00 2.1777421e+00 2.8983020e+00 2.6954219e+00 3.3808052e+00 2.2790175e+00 3.2344170e+00 3.1579733e+00 2.7462372e+00 3.2292608e+00 2.5444216e+00 3.5028333e+00 2.7205595e+00 3.6067948e+00 3.3670797e+00 3.0557792e+00 3.2048395e+00 3.6088607e+00 3.7891577e+00 3.1900581e+00 2.1641873e+00 2.4447974e+00 2.3408917e+00 2.5700421e+00 3.7710363e+00 3.1506190e+00 3.2040124e+00 3.5027314e+00 3.1322650e+00 2.7512730e+00 2.6533250e+00 3.0299528e+00 3.2862185e+00 2.6656374e+00 1.9477421e+00 2.8481000e+00 2.8454952e+00 2.8544453e+00 3.0132514e+00 1.6658308e+00 2.7590026e+00 4.7688362e+00 3.7943375e+00 4.7263320e+00 4.2949506e+00 4.5532150e+00 5.4636648e+00 3.1768366e+00 5.1030228e+00 4.5342701e+00 4.9831843e+00 3.8820426e+00 4.0358897e+00 4.3088496e+00 3.7133362e+00 3.8949006e+00 4.1025163e+00 4.2237423e+00 5.5888590e+00 5.7742361e+00 3.6743314e+00 4.5370189e+00 3.6141649e+00 5.5687868e+00 3.6395551e+00 4.4736906e+00 4.8085584e+00 3.5338163e+00 3.6144782e+00 4.3417782e+00 4.6138035e+00 4.9524148e+00 5.3625968e+00 4.3570317e+00 3.7932922e+00 4.2488997e+00 5.0747397e+00 4.3832471e+00 4.2110583e+00 3.5113289e+00 4.2399031e+00 4.4320962e+00 4.0189525e+00 3.7943375e+00 4.7000551e+00 4.5409269e+00 4.0612006e+00 3.7475562e+00 3.9722979e+00 4.1719819e+00 3.7859347e+00 6.9325418e-01 2.1269358e-01 5.0905001e-01 3.3337914e+00 3.0376046e+00 3.4948415e+00 2.6099670e+00 3.1641230e+00 2.9745020e+00 3.2202056e+00 1.9796375e+00 3.1511769e+00 2.4469125e+00 2.3235342e+00 2.7196435e+00 2.6337042e+00 3.1881331e+00 2.1375243e+00 2.9985516e+00 2.9847499e+00 2.5867906e+00 3.1255136e+00 2.4464131e+00 3.3203249e+00 2.5432298e+00 3.4386456e+00 3.1757436e+00 2.8453413e+00 2.9797458e+00 3.3872988e+00 3.5731577e+00 3.0079222e+00 2.0710306e+00 2.3862284e+00 2.2923690e+00 2.4260574e+00 3.5964347e+00 2.9822786e+00 3.0067893e+00 3.2740296e+00 3.0040546e+00 2.5786309e+00 2.5579141e+00 2.8891491e+00 3.0885642e+00 2.5333642e+00 2.0283816e+00 2.7031874e+00 2.6626548e+00 2.6835197e+00 2.8149627e+00 1.7472675e+00 2.6016025e+00 4.5864727e+00 3.6358644e+00 4.5092329e+00 4.1008711e+00 4.3608329e+00 5.2329560e+00 3.0685922e+00 4.8761643e+00 4.3448624e+00 4.7688607e+00 3.6817961e+00 3.8534030e+00 4.1033021e+00 3.5811154e+00 3.7530357e+00 3.9183591e+00 4.0199092e+00 5.3504583e+00 5.5556442e+00 3.5517562e+00 4.3306939e+00 3.4641481e+00 5.3377017e+00 3.4637450e+00 4.2663890e+00 4.5772917e+00 3.3571533e+00 3.4296698e+00 4.1575709e+00 4.3797497e+00 4.7253427e+00 5.1097682e+00 4.1763898e+00 3.5983434e+00 4.0666282e+00 4.8419079e+00 4.2005634e+00 4.0083071e+00 3.3318481e+00 4.0278210e+00 4.2396851e+00 3.8171357e+00 3.6358644e+00 4.4969460e+00 4.3490518e+00 3.8705614e+00 3.5905415e+00 3.7766172e+00 3.9906340e+00 3.6052686e+00 7.6752131e-01 4.0147421e-01 3.6660608e+00 3.3135273e+00 3.8017611e+00 2.7018605e+00 3.4275679e+00 3.1699903e+00 3.4789136e+00 1.9730403e+00 3.4358679e+00 2.5840983e+00 2.2331309e+00 2.9422991e+00 2.7581254e+00 3.4189217e+00 2.3233512e+00 3.3121677e+00 3.1836200e+00 2.7812918e+00 3.2896000e+00 2.5816639e+00 3.5379744e+00 2.7795823e+00 3.6532797e+00 3.4029480e+00 3.1195329e+00 3.2770643e+00 3.6772238e+00 3.8493740e+00 3.2305582e+00 2.2173292e+00 2.4840285e+00 2.3814525e+00 2.6148507e+00 3.8019334e+00 3.1710836e+00 3.2447990e+00 3.5700242e+00 3.1955870e+00 2.7803619e+00 2.6879415e+00 3.0521985e+00 3.3264150e+00 2.7089627e+00 1.9908167e+00 2.8775912e+00 2.8744403e+00 2.8857836e+00 3.0658390e+00 1.7171798e+00 2.7936066e+00 4.8056033e+00 3.8247106e+00 4.7834029e+00 4.3283723e+00 4.5943507e+00 5.5219241e+00 3.2001457e+00 5.1552806e+00 4.5786596e+00 5.0423887e+00 3.9353963e+00 4.0804944e+00 4.3648743e+00 3.7469906e+00 3.9346929e+00 4.1523445e+00 4.2650653e+00 5.6468786e+00 5.8321617e+00 3.7127205e+00 4.5943003e+00 3.6444925e+00 5.6275915e+00 3.6885686e+00 4.5212945e+00 4.8635596e+00 3.5807904e+00 3.6545040e+00 4.3827087e+00 4.6717461e+00 5.0136174e+00 5.4320857e+00 4.3994790e+00 3.8323332e+00 4.2736523e+00 5.1501184e+00 4.4249262e+00 4.2490074e+00 3.5500567e+00 4.3022895e+00 4.4864974e+00 4.0933482e+00 3.8247106e+00 4.7495571e+00 4.5943072e+00 4.1245629e+00 3.7976741e+00 4.0232438e+00 4.2129603e+00 3.8158144e+00 4.4535192e-01 3.3681634e+00 3.1015495e+00 3.5417515e+00 2.6663854e+00 3.2198557e+00 3.0579528e+00 3.2934163e+00 2.0153916e+00 3.2040320e+00 2.5204039e+00 2.3388377e+00 2.7956674e+00 2.6725726e+00 3.2655357e+00 2.2078644e+00 3.0402181e+00 3.0721050e+00 2.6595270e+00 3.1749624e+00 2.5094912e+00 3.4048516e+00 2.6019240e+00 3.5045178e+00 3.2523394e+00 2.8999277e+00 3.0267460e+00 3.4333346e+00 3.6317584e+00 3.0844423e+00 2.1209506e+00 2.4419061e+00 2.3443191e+00 2.4920874e+00 3.6775470e+00 3.0715602e+00 3.0884019e+00 3.3261336e+00 3.0501817e+00 2.6631094e+00 2.6243758e+00 2.9691171e+00 3.1659032e+00 2.5983106e+00 2.0538718e+00 2.7808700e+00 2.7473221e+00 2.7650187e+00 2.8804789e+00 1.7660585e+00 2.6784604e+00 4.6691123e+00 3.7183181e+00 4.5689156e+00 4.1821417e+00 4.4377562e+00 5.2873851e+00 3.1455384e+00 4.9362269e+00 4.4131751e+00 4.8285697e+00 3.7508315e+00 3.9249912e+00 4.1665786e+00 3.6588207e+00 3.8312584e+00 3.9914600e+00 4.0953360e+00 5.4042844e+00 5.6094349e+00 3.6203759e+00 4.3940519e+00 3.5472449e+00 5.3896044e+00 3.5318477e+00 4.3383367e+00 4.6370771e+00 3.4283809e+00 3.5084967e+00 4.2335104e+00 4.4348302e+00 4.7765764e+00 5.1494118e+00 4.2515997e+00 3.6735311e+00 4.1503255e+00 4.8803856e+00 4.2802235e+00 4.0874500e+00 3.4119017e+00 4.0856134e+00 4.3069340e+00 3.8658667e+00 3.7183181e+00 4.5670800e+00 4.4180998e+00 3.9298460e+00 3.6561219e+00 3.8459316e+00 4.0712063e+00 3.6910219e+00 3.5300704e+00 3.2300705e+00 3.6894189e+00 2.6906230e+00 3.3402581e+00 3.1455455e+00 3.4142500e+00 1.9871921e+00 3.3364095e+00 2.5801041e+00 2.2579027e+00 2.8953397e+00 2.7040361e+00 3.3706887e+00 2.2848507e+00 3.1889632e+00 3.1641787e+00 2.7405950e+00 3.2351115e+00 2.5567836e+00 3.5066271e+00 2.7031874e+00 3.5985833e+00 3.3547156e+00 3.0245025e+00 3.1656773e+00 3.5695690e+00 3.7624530e+00 3.1847809e+00 2.1665831e+00 2.4678343e+00 2.3636654e+00 2.5680682e+00 3.7710578e+00 3.1606607e+00 3.1985717e+00 3.4665002e+00 3.1244487e+00 2.7540755e+00 2.6724144e+00 3.0392407e+00 3.2747247e+00 2.6671530e+00 2.0066796e+00 2.8554471e+00 2.8427684e+00 2.8549070e+00 2.9928504e+00 1.7230625e+00 2.7611864e+00 4.7742557e+00 3.8047268e+00 4.7018935e+00 4.2892152e+00 4.5488617e+00 5.4303909e+00 3.2037606e+00 5.0724791e+00 4.5217060e+00 4.9623634e+00 3.8707551e+00 4.0296740e+00 4.2915574e+00 3.7321091e+00 3.9154512e+00 4.1022778e+00 4.2113304e+00 5.5520135e+00 5.7453700e+00 3.6849669e+00 4.5212945e+00 3.6308222e+00 5.5330176e+00 3.6335075e+00 4.4607162e+00 4.7770551e+00 3.5299194e+00 3.6126659e+00 4.3390241e+00 4.5771358e+00 4.9175276e+00 5.3118739e+00 4.3561658e+00 3.7812981e+00 4.2455646e+00 5.0340960e+00 4.3872001e+00 4.2015182e+00 3.5126820e+00 4.2176412e+00 4.4249262e+00 3.9985367e+00 3.8047268e+00 4.6887893e+00 4.5358705e+00 4.0502685e+00 3.7475470e+00 3.9619683e+00 4.1767972e+00 3.7895730e+00 6.0611244e-01 2.1845981e-01 1.6212669e+00 5.6769031e-01 1.3103855e+00 7.0437330e-01 2.2923690e+00 4.4651726e-01 1.8497891e+00 2.2196852e+00 1.1283882e+00 1.3099706e+00 9.0827783e-01 1.5790055e+00 3.7427929e-01 1.4018200e+00 1.2701139e+00 1.1341579e+00 1.5133392e+00 1.1134787e+00 1.0264409e+00 8.7202528e-01 9.2264612e-01 6.6432544e-01 4.5470518e-01 4.1449626e-01 4.3456114e-01 1.0085601e+00 1.5838351e+00 1.6415861e+00 1.6742876e+00 1.3140585e+00 1.0496979e+00 1.6013574e+00 1.0054037e+00 3.0546431e-01 1.0168833e+00 1.4293465e+00 1.5774037e+00 1.5278635e+00 9.0252542e-01 1.2994764e+00 2.2231652e+00 1.4317371e+00 1.3207609e+00 1.3224963e+00 8.3649708e-01 2.2607507e+00 1.3421549e+00 1.5412452e+00 1.2539702e+00 1.2643026e+00 1.0324775e+00 1.2342162e+00 1.9387309e+00 2.1209313e+00 1.6105602e+00 1.1912106e+00 1.5832517e+00 7.2486328e-01 8.5585239e-01 9.4009473e-01 1.3873503e+00 1.3945703e+00 1.0313560e+00 8.7720955e-01 2.0658700e+00 2.2655571e+00 1.2460824e+00 1.1834841e+00 1.4368020e+00 2.0378171e+00 7.9878917e-01 1.0960883e+00 1.3102767e+00 8.5105559e-01 9.2480363e-01 1.0805899e+00 1.1043883e+00 1.4313279e+00 1.8006336e+00 1.1235486e+00 7.6625946e-01 1.1633029e+00 1.5390703e+00 1.2493717e+00 9.0965328e-01 1.0182895e+00 8.6983677e-01 1.1880428e+00 9.2095040e-01 1.2539702e+00 1.3335022e+00 1.3109705e+00 9.5035453e-01 9.2112464e-01 7.6166891e-01 1.1418127e+00 1.1276971e+00 5.6700421e-01 1.1449732e+00 4.0293660e-01 7.3813096e-01 2.1845981e-01 1.7551534e+00 3.4583729e-01 1.2603076e+00 1.7354460e+00 5.3588338e-01 1.0777972e+00 3.8934542e-01 1.0669582e+00 3.0811765e-01 8.0294841e-01 7.8768770e-01 1.0018083e+00 1.0175773e+00 5.5419992e-01 5.9426792e-01 7.3496673e-01 4.8927739e-01 3.4378533e-01 2.5651975e-01 5.2655962e-01 5.4292906e-01 4.4417983e-01 1.1634384e+00 1.1527805e+00 1.2020363e+00 8.1521713e-01 7.2526325e-01 1.0018083e+00 4.1449626e-01 3.2586371e-01 9.0277242e-01 8.3172002e-01 1.0440187e+00 9.7779835e-01 3.2816937e-01 8.1521713e-01 1.7083888e+00 8.6361309e-01 7.3145860e-01 7.3145860e-01 3.6171588e-01 1.7816674e+00 7.6914805e-01 1.6177449e+00 8.3060013e-01 1.4732400e+00 1.1107977e+00 1.3546017e+00 2.2147080e+00 1.5404344e+00 1.8624350e+00 1.3603471e+00 1.7544191e+00 6.8961791e-01 8.7478495e-01 1.0733200e+00 9.5271386e-01 1.0466623e+00 9.9348625e-01 1.0085601e+00 2.3452277e+00 2.5288464e+00 1.0480665e+00 1.3130641e+00 8.9653332e-01 2.3282127e+00 5.8914551e-01 1.2436109e+00 1.5625142e+00 4.8927739e-01 4.8927739e-01 1.1593224e+00 1.3813076e+00 1.7138020e+00 2.1603815e+00 1.1866786e+00 6.4755655e-01 1.1521791e+00 1.8620175e+00 1.2565757e+00 1.0067784e+00 4.8927739e-01 1.0056742e+00 1.2594846e+00 9.3049742e-01 8.3060013e-01 1.4762619e+00 1.3817041e+00 9.4558103e-01 7.9613242e-01 7.7074935e-01 1.0627606e+00 7.0776547e-01 1.5593809e+00 4.8036801e-01 1.2165505e+00 6.1151102e-01 2.2871743e+00 4.0176783e-01 1.7963441e+00 2.1851225e+00 1.0906388e+00 1.2884575e+00 8.0619006e-01 1.6156775e+00 5.0905001e-01 1.3093850e+00 1.2434795e+00 1.0262547e+00 1.4875372e+00 1.0069726e+00 1.0669582e+00 7.4511469e-01 8.2384013e-01 6.9728513e-01 5.3022554e-01 3.0811765e-01 2.5651975e-01 9.2264612e-01 1.6478667e+00 1.6180636e+00 1.6694817e+00 1.3199714e+00 9.2288144e-01 1.5068702e+00 9.2859317e-01 2.4837156e-01 9.3238528e-01 1.3813076e+00 1.5238543e+00 1.4346522e+00 8.1130291e-01 1.2794849e+00 2.2234347e+00 1.3629833e+00 1.2671726e+00 1.2652657e+00 8.1810461e-01 2.3116343e+00 1.2988558e+00 1.3410314e+00 1.1276971e+00 1.0590298e+00 8.2552685e-01 1.0264409e+00 1.7485421e+00 2.0171203e+00 1.4118594e+00 9.7949166e-01 1.3980896e+00 5.7324170e-01 6.6317860e-01 7.4586719e-01 1.2603076e+00 1.2604558e+00 8.7504951e-01 6.6432544e-01 1.8915404e+00 2.0711789e+00 1.1178264e+00 9.9368623e-01 1.3223897e+00 1.8515012e+00 6.6384020e-01 8.9303452e-01 1.1107977e+00 7.2823007e-01 8.1099042e-01 8.7170815e-01 9.0876485e-01 1.2370832e+00 1.6626615e+00 9.2112464e-01 6.2482915e-01 9.7377870e-01 1.3752391e+00 1.0720678e+00 7.0386584e-01 9.0876485e-01 6.8917100e-01 1.0120221e+00 8.0294841e-01 1.1276971e+00 1.1329323e+00 1.1353806e+00 8.1385214e-01 7.7588000e-01 5.8914551e-01 9.8054887e-01 1.0085601e+00 1.0879524e+00 6.2605182e-01 1.2079117e+00 8.2305664e-01 1.1903922e+00 4.4651726e-01 6.5648056e-01 7.4164639e-01 5.2942799e-01 8.9852394e-01 6.4755655e-01 1.3035649e+00 7.7074935e-01 4.8135521e-01 7.7074935e-01 2.5651975e-01 1.1022599e+00 6.8917100e-01 1.0627606e+00 8.6290690e-01 9.7759114e-01 1.1868139e+00 1.3969297e+00 1.4333755e+00 7.6166891e-01 5.6075294e-01 2.5251796e-01 3.7427929e-01 4.4651726e-01 1.1444449e+00 7.7074935e-01 1.1571858e+00 1.3491011e+00 8.2624515e-01 7.0086313e-01 2.0000000e-01 4.4535192e-01 8.9852394e-01 3.7427929e-01 7.7885297e-01 4.1449626e-01 7.0826681e-01 6.1092863e-01 8.2275389e-01 1.0198386e+00 5.0905001e-01 2.2002582e+00 1.1640914e+00 2.2347161e+00 1.6833015e+00 1.9584639e+00 2.9773446e+00 7.2852070e-01 2.5984158e+00 1.9494155e+00 2.5625921e+00 1.4644662e+00 1.4491244e+00 1.8190688e+00 1.0934620e+00 1.3861754e+00 1.6265426e+00 1.6626615e+00 3.1878246e+00 3.2549253e+00 1.0346741e+00 2.0606771e+00 1.0425476e+00 3.0882196e+00 1.1022599e+00 1.9692383e+00 2.3537589e+00 1.0082605e+00 1.0950112e+00 1.7332099e+00 2.1942739e+00 2.5032087e+00 3.0886055e+00 1.7538274e+00 1.2342162e+00 1.6237100e+00 2.7181432e+00 1.8926658e+00 1.6507294e+00 1.0082605e+00 1.8244836e+00 1.9254808e+00 1.7303440e+00 1.1640914e+00 2.1641182e+00 2.0565627e+00 1.6435752e+00 1.1782910e+00 1.4699978e+00 1.7142546e+00 1.2095267e+00 8.0326782e-01 5.0991930e-01 1.8350577e+00 2.1269358e-01 1.3537729e+00 1.7146525e+00 6.5172743e-01 8.5585239e-01 4.0438741e-01 1.1847335e+00 3.4583729e-01 9.0252542e-01 8.2372435e-01 6.2024833e-01 1.0324775e+00 6.6827038e-01 6.5172743e-01 3.8776762e-01 4.4535192e-01 3.2816937e-01 2.5651975e-01 3.2586371e-01 4.3691963e-01 5.0180477e-01 1.2342162e+00 1.1573546e+00 1.2172454e+00 8.7848692e-01 6.2205176e-01 1.1016264e+00 6.9006418e-01 3.2586371e-01 5.2371571e-01 9.4492923e-01 1.0646687e+00 1.0101422e+00 4.1449626e-01 8.2552685e-01 1.7679545e+00 9.2288144e-01 8.3888121e-01 8.2929029e-01 3.8934542e-01 1.8776878e+00 8.5434758e-01 1.5481649e+00 7.9613242e-01 1.3657247e+00 1.0085601e+00 1.2641849e+00 2.1002817e+00 1.6030661e+00 1.7482192e+00 1.2100024e+00 1.7005893e+00 6.6491075e-01 7.3535471e-01 9.7949166e-01 8.8358844e-01 1.0423677e+00 9.5498315e-01 9.1051084e-01 2.2737459e+00 2.4086493e+00 7.2486328e-01 1.2326306e+00 9.4832302e-01 2.2096958e+00 3.8934542e-01 1.1729895e+00 1.4561933e+00 3.8776762e-01 4.8927739e-01 1.0574300e+00 1.2643026e+00 1.5918956e+00 2.0914667e+00 1.0906388e+00 5.0817745e-01 1.0182895e+00 1.7457596e+00 1.2250414e+00 9.1663180e-01 5.4292906e-01 9.1750357e-01 1.1891470e+00 8.8358844e-01 7.9613242e-01 1.3916739e+00 1.3267389e+00 8.9303452e-01 5.3309112e-01 6.9325418e-01 1.0574013e+00 7.0776547e-01 7.0776547e-01 1.3071453e+00 9.0049692e-01 6.9006418e-01 1.2079117e+00 3.6171588e-01 7.1791510e-01 4.1586001e-01 9.0049692e-01 1.0069726e+00 2.5251796e-01 4.4651726e-01 6.9325418e-01 6.2538346e-01 5.9426792e-01 5.6631629e-01 6.6827038e-01 4.1449626e-01 7.0437330e-01 9.0277242e-01 1.1055069e+00 1.0496979e+00 3.2586371e-01 1.0083666e+00 7.4164639e-01 8.3888121e-01 6.0181382e-01 6.3861009e-01 3.4378533e-01 6.3808075e-01 1.0101422e+00 6.8961791e-01 4.1449626e-01 5.3588338e-01 2.5651975e-01 4.1586001e-01 5.0991930e-01 1.2869134e+00 3.0546431e-01 3.2586371e-01 3.0275928e-01 5.0905001e-01 1.5278635e+00 4.0000000e-01 1.7279861e+00 7.4586719e-01 1.7831878e+00 1.1718516e+00 1.4824233e+00 2.5111349e+00 8.3620494e-01 2.1256928e+00 1.4719311e+00 2.0814452e+00 1.0175773e+00 1.0014633e+00 1.3875139e+00 7.7885297e-01 1.1473003e+00 1.2144845e+00 1.1591754e+00 2.6773585e+00 2.7900071e+00 7.0776547e-01 1.6151673e+00 7.3496673e-01 2.6263773e+00 7.2526325e-01 1.4645804e+00 1.8755806e+00 6.3924842e-01 6.2407309e-01 1.2731262e+00 1.7507664e+00 2.0635966e+00 2.6116811e+00 1.3129189e+00 7.4855857e-01 1.1149070e+00 2.3160147e+00 1.4246028e+00 1.1229843e+00 5.6075294e-01 1.4120836e+00 1.5094575e+00 1.4108494e+00 7.4586719e-01 1.6884234e+00 1.6211869e+00 1.3017208e+00 8.1521713e-01 1.0401425e+00 1.2452704e+00 6.9728513e-01 1.8185955e+00 4.8135521e-01 1.2509218e+00 1.8049926e+00 5.8914551e-01 1.2205493e+00 4.2538717e-01 1.1912106e+00 4.6472023e-01 7.1840099e-01 8.9207714e-01 1.1017858e+00 1.1127329e+00 4.1586001e-01 7.8197925e-01 8.0326782e-01 5.7257017e-01 5.2655962e-01 4.3456114e-01 6.2660376e-01 4.8135521e-01 4.5581864e-01 1.3318128e+00 1.2468939e+00 1.3144065e+00 9.4935318e-01 6.6384020e-01 9.1075311e-01 3.2586371e-01 4.1449626e-01 1.0130748e+00 8.3280511e-01 1.0906119e+00 9.6204649e-01 3.4583729e-01 9.3296062e-01 1.7901543e+00 8.7170815e-01 7.3805807e-01 7.3805807e-01 5.2655962e-01 1.9041928e+00 8.1521713e-01 1.4138821e+00 7.3805807e-01 1.3166957e+00 9.2264612e-01 1.1533602e+00 2.0690479e+00 1.4700179e+00 1.7092525e+00 1.2231847e+00 1.5870088e+00 5.0592043e-01 7.5791688e-01 9.0575661e-01 9.1750357e-01 9.1802948e-01 8.1304731e-01 8.1638392e-01 2.1978861e+00 2.3802944e+00 1.1107977e+00 1.1386292e+00 7.9878917e-01 2.1900222e+00 6.1092863e-01 1.0480665e+00 1.4148192e+00 5.0991930e-01 3.6171588e-01 9.7825559e-01 1.2593659e+00 1.5912764e+00 2.0615043e+00 1.0056742e+00 5.6700421e-01 1.0137836e+00 1.7695175e+00 1.0597541e+00 8.0619006e-01 3.8934542e-01 8.6513410e-01 1.0755693e+00 8.4050231e-01 7.3805807e-01 1.2832075e+00 1.1947245e+00 8.0660588e-01 8.2105460e-01 5.9426792e-01 8.6983677e-01 5.3309112e-01 1.9083318e+00 6.7975091e-01 4.1449626e-01 1.2452704e+00 1.1763980e+00 1.6420607e+00 7.9016429e-01 1.9365498e+00 1.3172979e+00 1.0653845e+00 1.5684812e+00 8.1304731e-01 1.7169601e+00 1.2768639e+00 1.8804140e+00 1.6311692e+00 1.6315809e+00 1.8424891e+00 2.1489929e+00 2.2038673e+00 1.4613032e+00 8.0587320e-01 6.8961791e-01 6.4704320e-01 9.7949166e-01 1.9250543e+00 1.2802798e+00 1.5824669e+00 2.0485534e+00 1.5790055e+00 1.0078327e+00 8.2305664e-01 1.1498269e+00 1.5838351e+00 1.0137836e+00 1.2418578e-01 1.0230441e+00 1.1119327e+00 1.0941064e+00 1.4719311e+00 3.2816937e-01 1.0165138e+00 2.9338155e+00 1.9158303e+00 3.0455280e+00 2.4635485e+00 2.7430309e+00 3.7921012e+00 1.2632199e+00 3.4105293e+00 2.7619926e+00 3.3261421e+00 2.2045198e+00 2.2598424e+00 2.6204307e+00 1.8330979e+00 2.0701646e+00 2.3622531e+00 2.4525409e+00 3.9619101e+00 4.0743074e+00 1.8315269e+00 2.8475224e+00 1.7388184e+00 3.9054939e+00 1.9111264e+00 2.7377517e+00 3.1510494e+00 1.7964653e+00 1.8350071e+00 2.5277506e+00 2.9970778e+00 3.3196868e+00 3.8532018e+00 2.5453122e+00 2.0312250e+00 2.3887539e+00 3.5269824e+00 2.5986705e+00 2.4210417e+00 1.7228354e+00 2.6125646e+00 2.7062349e+00 2.4839132e+00 1.9158303e+00 2.9502077e+00 2.8139128e+00 2.4180244e+00 1.9947426e+00 2.2550764e+00 2.3956104e+00 1.9332869e+00 1.4468211e+00 1.8027242e+00 7.3851529e-01 9.0658670e-01 5.0180477e-01 1.2418578e+00 2.5651975e-01 1.0022010e+00 8.6361309e-01 7.3851529e-01 1.1055064e+00 7.8197925e-01 6.8961791e-01 4.8927739e-01 5.0270183e-01 3.2352160e-01 2.1269358e-01 2.5651975e-01 4.9857388e-01 6.0611244e-01 1.2633451e+00 1.2342162e+00 1.2794849e+00 9.3824087e-01 7.0776547e-01 1.2014753e+00 7.0429250e-01 2.5651975e-01 6.2482915e-01 1.0329901e+00 1.1593224e+00 1.1069580e+00 5.0180477e-01 8.9712482e-01 1.8394959e+00 1.0181000e+00 9.2095040e-01 9.2047746e-01 4.4417983e-01 1.9314297e+00 9.4103005e-01 1.6328100e+00 9.3238528e-01 1.3969297e+00 1.0389435e+00 1.3327491e+00 2.0961718e+00 1.7103548e+00 1.7405652e+00 1.2330392e+00 1.7474965e+00 7.7919451e-01 8.1810461e-01 1.0613462e+00 1.0417249e+00 1.2331989e+00 1.0974061e+00 9.4125538e-01 2.2568188e+00 2.4127176e+00 8.4050231e-01 1.3145067e+00 1.0960883e+00 2.1973666e+00 5.6075294e-01 1.2221471e+00 1.4467170e+00 5.7324170e-01 6.3977563e-01 1.1341579e+00 1.2436109e+00 1.5826476e+00 2.0476065e+00 1.1847335e+00 5.3665999e-01 1.0391247e+00 1.7521201e+00 1.3293211e+00 9.4492923e-01 6.9369532e-01 1.0019724e+00 1.3083079e+00 1.0406064e+00 9.3238528e-01 1.4580335e+00 1.4387122e+00 1.0576043e+00 7.0233835e-01 8.1304731e-01 1.1697902e+00 8.2372435e-01 7.6914805e-01 7.2823007e-01 8.7504951e-01 1.0611732e+00 4.5581864e-01 1.5204521e+00 6.6432544e-01 6.5172743e-01 1.0866092e+00 4.5470518e-01 1.0573285e+00 9.0074515e-01 1.3083079e+00 1.0613462e+00 1.2123540e+00 1.4190961e+00 1.6754036e+00 1.6596797e+00 8.9095811e-01 6.1947990e-01 4.2418962e-01 4.8927739e-01 6.0551856e-01 1.2951131e+00 6.2538346e-01 1.0030700e+00 1.5663312e+00 1.1396406e+00 4.5581864e-01 3.2816937e-01 5.3665999e-01 1.0166932e+00 6.0670504e-01 6.9167458e-01 4.4535192e-01 5.6075294e-01 5.3665999e-01 1.0182895e+00 9.1075311e-01 5.0991930e-01 2.2632657e+00 1.2601890e+00 2.4384530e+00 1.8269304e+00 2.0927845e+00 3.1870761e+00 6.4290921e-01 2.8096725e+00 2.1462316e+00 2.6900593e+00 1.5901181e+00 1.6364474e+00 2.0101738e+00 1.1729895e+00 1.4078246e+00 1.7083888e+00 1.8278268e+00 3.3435703e+00 3.4604677e+00 1.2331989e+00 2.2206574e+00 1.0719360e+00 3.3068858e+00 1.3163598e+00 2.0994872e+00 2.5539296e+00 1.1948578e+00 1.1991899e+00 1.8828324e+00 2.4245766e+00 2.7358293e+00 3.2702869e+00 1.8959565e+00 1.4312787e+00 1.7665622e+00 2.9527671e+00 1.9255490e+00 1.7860690e+00 1.0796583e+00 2.0205937e+00 2.0647798e+00 1.9168750e+00 1.2601890e+00 2.3069539e+00 2.1608869e+00 1.8128438e+00 1.3838212e+00 1.6376058e+00 1.7220696e+00 1.2768639e+00 1.2687651e+00 1.0344911e+00 1.5320003e+00 9.7779835e-01 1.8837258e+00 1.2979752e+00 1.0012667e+00 1.3957794e+00 7.2526325e-01 1.6850672e+00 1.2372418e+00 1.7004805e+00 1.4979666e+00 1.5611922e+00 1.7745022e+00 2.0153916e+00 2.0815027e+00 1.3830210e+00 8.1242502e-01 5.8914551e-01 5.7257017e-01 9.5676647e-01 1.7518264e+00 1.2724737e+00 1.6669115e+00 1.9675324e+00 1.4200435e+00 1.1136605e+00 7.1881659e-01 1.0072663e+00 1.5134954e+00 9.3238528e-01 3.2352160e-01 9.5222919e-01 1.1681971e+00 1.1043332e+00 1.4120836e+00 6.2205176e-01 1.0078327e+00 2.8028143e+00 1.7525933e+00 2.8815987e+00 2.2944257e+00 2.5825907e+00 3.6132031e+00 1.1179743e+00 3.2286633e+00 2.5673494e+00 3.2133201e+00 2.1127170e+00 2.0867931e+00 2.4721080e+00 1.6626615e+00 1.9456450e+00 2.2607446e+00 2.2983453e+00 3.8335668e+00 3.8818411e+00 1.6299374e+00 2.7127377e+00 1.6132118e+00 3.7182722e+00 1.7559391e+00 2.6123294e+00 2.9966900e+00 1.6625128e+00 1.7303440e+00 2.3560577e+00 2.8340159e+00 3.1407514e+00 3.7366777e+00 2.3765195e+00 1.8701780e+00 2.1933937e+00 3.3657099e+00 2.5066503e+00 2.2797241e+00 1.6331631e+00 2.4808010e+00 2.5698271e+00 2.3770285e+00 1.7525933e+00 2.8053367e+00 2.6963680e+00 2.2934334e+00 1.8202060e+00 2.1229819e+00 2.3231793e+00 1.8122257e+00 8.5462626e-01 5.0991930e-01 6.2538346e-01 8.0358695e-01 3.7255734e-01 5.3022554e-01 8.2105460e-01 6.0900723e-01 6.2482915e-01 3.0844217e-01 7.9580667e-01 5.4292906e-01 5.0991930e-01 7.0437330e-01 9.7270522e-01 9.9532071e-01 3.0546431e-01 7.9878917e-01 7.2343175e-01 7.8768770e-01 4.2418962e-01 9.0876485e-01 5.2862779e-01 4.4651726e-01 8.5205778e-01 7.4164639e-01 3.2586371e-01 5.7867728e-01 5.3309112e-01 4.1449626e-01 4.5581864e-01 1.2131545e+00 3.8776762e-01 3.2352160e-01 2.5251796e-01 3.2816937e-01 1.3221405e+00 2.8507955e-01 1.8873850e+00 9.2859317e-01 1.8730683e+00 1.4111029e+00 1.6550480e+00 2.6320302e+00 1.0406064e+00 2.2657813e+00 1.6658308e+00 2.1339968e+00 1.0072663e+00 1.1444449e+00 1.4417207e+00 8.9971984e-01 1.1192426e+00 1.2342162e+00 1.3367840e+00 2.7726042e+00 2.9277580e+00 9.9368623e-01 1.6694974e+00 7.8197925e-01 2.7493700e+00 7.5976039e-01 1.5849874e+00 1.9802196e+00 6.4290921e-01 7.1799256e-01 1.4445746e+00 1.8216794e+00 2.1462316e+00 2.6367554e+00 1.4616539e+00 9.2264612e-01 1.4088394e+00 2.3235034e+00 1.5120955e+00 1.3224963e+00 6.2024833e-01 1.4078246e+00 1.5587730e+00 1.2801437e+00 9.2859317e-01 1.8096161e+00 1.6710566e+00 1.2378278e+00 8.9653332e-01 1.0864449e+00 1.3071453e+00 9.0827783e-01 8.9159388e-01 7.7763126e-01 1.0417249e+00 9.1802948e-01 5.0905001e-01 6.2605182e-01 4.4651726e-01 1.2379511e+00 6.2024833e-01 9.5571254e-01 8.1558458e-01 7.5976039e-01 9.2944046e-01 1.0661822e+00 1.2662457e+00 8.2342214e-01 5.8851328e-01 5.1691876e-01 5.3588338e-01 5.1691876e-01 1.1717125e+00 9.6838716e-01 1.2601890e+00 1.1258723e+00 4.8135521e-01 8.3649708e-01 5.5419992e-01 6.2407309e-01 9.0965328e-01 4.2538717e-01 1.0906388e+00 5.9426792e-01 8.1638392e-01 7.3145860e-01 7.3145860e-01 1.1880428e+00 6.3861009e-01 2.2927296e+00 1.2766755e+00 2.1156916e+00 1.6869465e+00 1.9835684e+00 2.8209672e+00 1.2028939e+00 2.4458200e+00 1.8683030e+00 2.5149752e+00 1.4746001e+00 1.4371043e+00 1.7501772e+00 1.2500343e+00 1.5991931e+00 1.7211928e+00 1.6271057e+00 3.0580852e+00 3.1168283e+00 1.0328064e+00 2.0203543e+00 1.2344562e+00 2.9146252e+00 1.0941064e+00 1.9515265e+00 2.2002582e+00 1.0531192e+00 1.1790011e+00 1.7600233e+00 1.9895190e+00 2.3106402e+00 2.8876509e+00 1.7983401e+00 1.1763719e+00 1.6118154e+00 2.5100676e+00 2.0039716e+00 1.6449456e+00 1.1276917e+00 1.7245185e+00 1.9495298e+00 1.6638124e+00 1.2766755e+00 2.1512175e+00 2.1034605e+00 1.6449189e+00 1.1924295e+00 1.4645804e+00 1.8408873e+00 1.3037063e+00 1.1269972e+00 6.2482915e-01 5.0991930e-01 6.6827038e-01 7.0479928e-01 8.8358844e-01 4.5581864e-01 7.0086313e-01 4.2667565e-01 2.0656129e-01 4.4535192e-01 5.2942799e-01 7.0086313e-01 6.3861009e-01 2.1269358e-01 1.2261087e+00 1.0119857e+00 1.1001291e+00 8.1638392e-01 4.2667565e-01 7.0479928e-01 5.1691876e-01 6.0611244e-01 6.2538346e-01 6.9006418e-01 8.3812833e-01 6.4290921e-01 1.2418578e-01 7.3145860e-01 1.6044563e+00 6.2660376e-01 5.7324170e-01 5.6700421e-01 4.0293660e-01 1.7981158e+00 6.4806901e-01 1.5090287e+00 5.9426792e-01 1.4258804e+00 9.2264612e-01 1.2221471e+00 2.1613095e+00 1.2165505e+00 1.7814077e+00 1.1712156e+00 1.7475837e+00 7.0233835e-01 7.0776547e-01 1.0386594e+00 7.0233835e-01 1.0228981e+00 9.8450810e-01 8.5105559e-01 2.3257048e+00 2.4547248e+00 7.1504098e-01 1.2838690e+00 6.9369532e-01 2.2753334e+00 4.3691963e-01 1.1508502e+00 1.5109753e+00 4.0438741e-01 4.1449626e-01 1.0168833e+00 1.3670543e+00 1.6898941e+00 2.2253038e+00 1.0655560e+00 4.1586001e-01 9.0827783e-01 1.9262937e+00 1.2075315e+00 8.3888121e-01 4.0438741e-01 1.0401425e+00 1.2250414e+00 1.0755693e+00 5.9426792e-01 1.3866792e+00 1.3487634e+00 1.0056742e+00 5.9426792e-01 7.2526325e-01 1.0425476e+00 5.0592043e-01 1.2125198e+00 9.0252542e-01 5.4292906e-01 1.0679144e+00 4.5470518e-01 1.2307737e+00 5.6700421e-01 1.3629833e+00 1.1271488e+00 9.3592296e-01 1.1329323e+00 1.4903933e+00 1.5826638e+00 9.2264612e-01 3.7598397e-01 5.1691876e-01 5.3022554e-01 3.4583729e-01 1.5102079e+00 9.0478973e-01 9.6664346e-01 1.3678655e+00 1.0012667e+00 5.0090417e-01 4.9766035e-01 8.1130291e-01 1.0331736e+00 4.5581864e-01 7.6955924e-01 6.0551856e-01 6.0181382e-01 6.0060595e-01 8.1242502e-01 7.2852070e-01 5.0180477e-01 2.4944334e+00 1.5259640e+00 2.4897635e+00 2.0286682e+00 2.2758462e+00 3.2467454e+00 1.0417249e+00 2.8819633e+00 2.2804674e+00 2.7472449e+00 1.6234861e+00 1.7644184e+00 2.0587064e+00 1.4533724e+00 1.6559784e+00 1.8347926e+00 1.9605308e+00 3.3855928e+00 3.5452222e+00 1.4540815e+00 2.2852232e+00 1.3536716e+00 3.3617477e+00 1.3717027e+00 2.2096171e+00 2.5931780e+00 1.2603076e+00 1.3371180e+00 2.0643410e+00 2.4233813e+00 2.7521037e+00 3.2246201e+00 2.0784533e+00 1.5405106e+00 2.0088441e+00 2.9099860e+00 2.1140685e+00 1.9448322e+00 1.2330392e+00 2.0122105e+00 2.1687358e+00 1.8353933e+00 1.5259640e+00 2.4321505e+00 2.2783778e+00 1.8251179e+00 1.4795374e+00 1.7068208e+00 1.9049236e+00 1.5165339e+00 1.1004794e+00 9.4753140e-01 9.4125538e-01 1.1763719e+00 8.5105559e-01 6.6432544e-01 7.2526325e-01 6.4290921e-01 3.2816937e-01 1.2418578e-01 4.4535192e-01 6.2024833e-01 7.0479928e-01 1.2172454e+00 1.3021788e+00 1.3289150e+00 9.6141901e-01 8.9366705e-01 1.3003320e+00 7.1840099e-01 3.0275928e-01 8.2654509e-01 1.1056650e+00 1.2497790e+00 1.2234738e+00 6.0611244e-01 9.6141901e-01 1.8661545e+00 1.1149070e+00 1.0038051e+00 1.0038051e+00 5.0991930e-01 1.8886923e+00 1.0132664e+00 1.7427900e+00 1.0573285e+00 1.5462225e+00 1.2230220e+00 1.4700179e+00 2.2554582e+00 1.8183902e+00 1.9191337e+00 1.4359851e+00 1.8399871e+00 8.1558458e-01 9.6664346e-01 1.1754055e+00 1.1548215e+00 1.2523175e+00 1.1229906e+00 1.1149070e+00 2.3868096e+00 2.5734684e+00 1.0665149e+00 1.4148192e+00 1.1763719e+00 2.3591336e+00 6.6317860e-01 1.3545005e+00 1.6178623e+00 6.3735887e-01 7.2526325e-01 1.2709820e+00 1.4169523e+00 1.7425222e+00 2.1449779e+00 1.3015611e+00 7.4777660e-01 1.2601890e+00 1.8513630e+00 1.3897316e+00 1.1185330e+00 7.6625946e-01 1.0919712e+00 1.3783420e+00 1.0120221e+00 1.0573285e+00 1.5860263e+00 1.5022608e+00 1.0597541e+00 8.3060013e-01 8.9095811e-01 1.2107055e+00 9.5498315e-01 5.9426792e-01 8.8835966e-01 7.2486328e-01 4.3456114e-01 6.3108414e-01 7.9580667e-01 5.4292906e-01 8.0619006e-01 1.0003942e+00 1.2057554e+00 1.1282371e+00 4.0147421e-01 1.0482443e+00 8.3812833e-01 9.3049742e-01 6.4290921e-01 6.6432544e-01 2.0000000e-01 4.9766035e-01 1.1016264e+00 8.7202528e-01 4.1312257e-01 6.2660376e-01 4.4651726e-01 5.0180477e-01 5.9426792e-01 1.3172979e+00 3.8776762e-01 3.7427929e-01 3.2816937e-01 6.1151102e-01 1.5338492e+00 4.2667565e-01 1.6536633e+00 6.6827038e-01 1.8195408e+00 1.1798960e+00 1.4588731e+00 2.5552364e+00 7.7039952e-01 2.1764356e+00 1.5179392e+00 2.0659196e+00 1.0072663e+00 1.0165138e+00 1.4077317e+00 7.0523271e-01 9.7441804e-01 1.1290808e+00 1.1879078e+00 2.7003420e+00 2.8251568e+00 8.7478495e-01 1.6113870e+00 5.7257017e-01 2.6756977e+00 7.5976039e-01 1.4611141e+00 1.9290721e+00 6.4290921e-01 5.8851328e-01 1.2509218e+00 1.8216794e+00 2.1226924e+00 2.6556584e+00 1.2741904e+00 8.1527569e-01 1.1396406e+00 2.3658814e+00 1.3219975e+00 1.1377990e+00 4.8036801e-01 1.4418088e+00 1.4695582e+00 1.4097125e+00 6.6827038e-01 1.6762567e+00 1.5624022e+00 1.2731262e+00 8.4812820e-01 1.0423677e+00 1.1235486e+00 6.3808075e-01 7.0328431e-01 2.8507955e-01 9.7377870e-01 3.7598397e-01 8.9971984e-01 6.2538346e-01 6.2988288e-01 8.4591037e-01 1.1042097e+00 1.1949615e+00 5.7867728e-01 6.0121055e-01 4.2418962e-01 4.8036801e-01 2.4837156e-01 1.0588560e+00 6.3735887e-01 8.4050231e-01 1.0216438e+00 6.0900723e-01 3.8776762e-01 3.8934542e-01 3.8934542e-01 6.0900723e-01 2.1269358e-01 1.0100718e+00 3.2586371e-01 3.2816937e-01 3.2816937e-01 4.6472023e-01 1.1765359e+00 3.0546431e-01 2.1603815e+00 1.1833480e+00 2.0696037e+00 1.5733646e+00 1.8844302e+00 2.7913211e+00 1.0279631e+00 2.4069427e+00 1.8096161e+00 2.4013270e+00 1.3194762e+00 1.3641156e+00 1.6852518e+00 1.1847335e+00 1.5344133e+00 1.5901181e+00 1.5133392e+00 2.9601125e+00 3.0929882e+00 9.7994716e-01 1.9359434e+00 1.1341579e+00 2.8969791e+00 1.0267435e+00 1.8174459e+00 2.1353579e+00 9.5498315e-01 1.0067464e+00 1.6752254e+00 1.9600024e+00 2.3015655e+00 2.8161147e+00 1.7177705e+00 1.0636401e+00 1.5095556e+00 2.5229584e+00 1.8388413e+00 1.5016471e+00 9.4558103e-01 1.6620056e+00 1.8661202e+00 1.6246433e+00 1.1833480e+00 2.0524784e+00 1.9917352e+00 1.5896248e+00 1.1449732e+00 1.3635198e+00 1.6539414e+00 1.1377990e+00 7.8695083e-01 1.0194752e+00 6.9369532e-01 4.4535192e-01 6.2538346e-01 7.1169738e-01 8.2684479e-01 7.5791688e-01 8.9971984e-01 7.0394675e-01 1.0777972e+00 8.9366705e-01 9.7548738e-01 7.3805807e-01 6.9369532e-01 9.9348625e-01 1.2013436e+00 9.4287188e-01 2.1845981e-01 9.1163729e-01 7.8197925e-01 7.4777660e-01 8.0096515e-01 6.3735887e-01 1.5043029e+00 7.0776547e-01 8.7021234e-01 7.8197925e-01 7.0784540e-01 1.6629594e+00 7.2852070e-01 1.7521201e+00 7.5705927e-01 1.5812904e+00 1.1798960e+00 1.4306494e+00 2.2994849e+00 1.3047221e+00 1.9342059e+00 1.3259654e+00 2.0165210e+00 1.0919404e+00 8.7720955e-01 1.2180145e+00 7.1881659e-01 1.0466623e+00 1.2389598e+00 1.1426203e+00 2.5872805e+00 2.5766735e+00 5.0817745e-01 1.4924169e+00 8.3060013e-01 2.3982377e+00 5.8914551e-01 1.4728952e+00 1.7209381e+00 6.3808075e-01 8.3649708e-01 1.1916257e+00 1.5183917e+00 1.7983401e+00 2.4620092e+00 1.2174316e+00 7.4549115e-01 1.1136343e+00 1.9965599e+00 1.5255331e+00 1.1891470e+00 8.2384013e-01 1.2304904e+00 1.3937115e+00 1.1842231e+00 7.5705927e-01 1.6132118e+00 1.5725854e+00 1.1127329e+00 5.8914551e-01 9.8054887e-01 1.4089719e+00 9.0521488e-01 1.1043332e+00 5.3665999e-01 1.1040512e+00 8.6137722e-01 8.5335130e-01 1.0692258e+00 1.3395518e+00 1.4121163e+00 7.2343175e-01 4.0438741e-01 1.4096146e-01 2.1845981e-01 2.5251796e-01 1.2340567e+00 7.2852070e-01 1.0216438e+00 1.2599182e+00 7.7360126e-01 5.1607523e-01 2.1269358e-01 5.0270183e-01 8.3345577e-01 2.1845981e-01 7.4893123e-01 3.4378533e-01 5.3022554e-01 4.5581864e-01 6.9167458e-01 9.4080461e-01 3.4583729e-01 2.3056888e+00 1.2961380e+00 2.2790932e+00 1.7645599e+00 2.0520955e+00 3.0186066e+00 8.9827435e-01 2.6386155e+00 2.0191749e+00 2.5992685e+00 1.4843324e+00 1.5325189e+00 1.8691652e+00 1.2554784e+00 1.5582387e+00 1.7070813e+00 1.7171798e+00 3.2008583e+00 3.3121677e+00 1.1313840e+00 2.1147926e+00 1.1879078e+00 3.1280700e+00 1.1681971e+00 2.0145868e+00 2.3728666e+00 1.0720678e+00 1.1437669e+00 1.8347926e+00 2.2027051e+00 2.5315934e+00 3.0688850e+00 1.8636112e+00 1.2768639e+00 1.7126039e+00 2.7381221e+00 1.9739212e+00 1.7039473e+00 1.0573285e+00 1.8507968e+00 2.0095044e+00 1.7591313e+00 1.2961380e+00 2.2339736e+00 2.1358764e+00 1.7106141e+00 1.2731262e+00 1.5241199e+00 1.7828037e+00 1.2869134e+00 8.7720955e-01 7.4777660e-01 6.5223271e-01 7.1881659e-01 7.6914805e-01 9.3999899e-01 8.0619006e-01 4.2418962e-01 1.4104707e+00 1.2144845e+00 1.3128167e+00 1.0056742e+00 5.3665999e-01 5.6075294e-01 3.4583729e-01 8.1130291e-01 9.7730901e-01 7.8197925e-01 9.9089002e-01 8.0353565e-01 4.3691963e-01 9.6095130e-01 1.7110336e+00 7.7033318e-01 7.5196795e-01 7.0776547e-01 6.5648056e-01 1.8915404e+00 7.9878917e-01 1.2730931e+00 5.3022554e-01 1.4349259e+00 8.3620494e-01 1.0733200e+00 2.1767273e+00 1.0960883e+00 1.8048569e+00 1.2035173e+00 1.6539414e+00 6.2482915e-01 7.0523271e-01 1.0184370e+00 7.1169738e-01 6.6432544e-01 7.0480730e-01 8.1527569e-01 2.3116343e+00 2.4505705e+00 1.0085601e+00 1.2063335e+00 4.5581864e-01 2.3022338e+00 5.6700421e-01 1.0655560e+00 1.5550492e+00 4.4417983e-01 2.5251796e-01 8.8358844e-01 1.4559276e+00 1.7532140e+00 2.2755980e+00 8.9653332e-01 5.5160819e-01 9.1163729e-01 1.9862884e+00 9.1163729e-01 7.6752131e-01 2.0656129e-01 1.0632598e+00 1.0516761e+00 1.0391247e+00 5.3022554e-01 1.2756158e+00 1.1406052e+00 8.7720955e-01 7.3851529e-01 6.5633874e-01 7.0776547e-01 3.2352160e-01 9.1273187e-01 7.0043186e-01 3.7427929e-01 5.7324170e-01 9.3615100e-01 1.0733200e+00 5.0991930e-01 5.9426792e-01 6.5633874e-01 6.7975091e-01 3.0811765e-01 1.1056650e+00 7.7360126e-01 7.0429250e-01 8.2552685e-01 5.7257017e-01 5.0905001e-01 6.1968386e-01 6.5223271e-01 6.0611244e-01 3.2586371e-01 1.2028939e+00 5.0905001e-01 4.2667565e-01 4.1449626e-01 3.0546431e-01 1.2470767e+00 4.0147421e-01 2.1213832e+00 1.1521791e+00 2.0070710e+00 1.6126950e+00 1.8637576e+00 2.7490677e+00 1.2370832e+00 2.3910690e+00 1.8274132e+00 2.3004229e+00 1.1979861e+00 1.3368881e+00 1.5972416e+00 1.1093572e+00 1.3693737e+00 1.4644753e+00 1.5211725e+00 2.9013543e+00 3.0559175e+00 1.0590298e+00 1.8374244e+00 1.0423677e+00 2.8588399e+00 9.4309624e-01 1.7735968e+00 2.0979142e+00 8.5205778e-01 9.4287188e-01 1.6546836e+00 1.9109434e+00 2.2424413e+00 2.7118839e+00 1.6774684e+00 1.1029298e+00 1.6007141e+00 2.3898698e+00 1.7557336e+00 1.5191033e+00 8.5462626e-01 1.5344007e+00 1.7571295e+00 1.3898545e+00 1.1521791e+00 1.9987470e+00 1.8815752e+00 1.4085850e+00 1.0646687e+00 1.2740417e+00 1.5577803e+00 1.1296247e+00 4.0176783e-01 6.5223271e-01 6.3977563e-01 5.3022554e-01 5.7324170e-01 5.2574978e-01 1.4438552e+00 1.2221471e+00 1.3131724e+00 1.0406064e+00 3.4583729e-01 9.5943875e-01 9.2859317e-01 6.5172743e-01 5.1607523e-01 9.7548738e-01 1.0611732e+00 8.6137722e-01 5.3665999e-01 9.4854455e-01 1.8311457e+00 8.7420176e-01 8.7170815e-01 8.4050231e-01 6.5223271e-01 2.0303919e+00 8.9917007e-01 1.3866318e+00 5.7867728e-01 1.2002762e+00 7.4740267e-01 1.0440187e+00 1.9213397e+00 1.4087466e+00 1.5433565e+00 9.2836103e-01 1.6392533e+00 7.7360126e-01 5.0592043e-01 8.5585239e-01 6.8961791e-01 9.5035453e-01 9.5498315e-01 7.0776547e-01 2.1812146e+00 2.2081369e+00 3.7427929e-01 1.1335961e+00 7.7885297e-01 2.0291151e+00 3.2352160e-01 1.0661822e+00 1.3165513e+00 3.7598397e-01 5.3588338e-01 8.2305664e-01 1.1437730e+00 1.4415965e+00 2.0902718e+00 8.7848692e-01 3.2352160e-01 7.0479928e-01 1.6865203e+00 1.1904611e+00 7.5791688e-01 5.5492130e-01 8.9207714e-01 1.0805899e+00 9.6271042e-01 5.7867728e-01 1.2256881e+00 1.2481462e+00 8.8358844e-01 4.0147421e-01 6.4405773e-01 1.0887986e+00 5.9426792e-01 4.4651726e-01 5.4292906e-01 7.0437330e-01 7.0776547e-01 3.2816937e-01 1.2134101e+00 9.8820253e-01 1.0733200e+00 8.1099042e-01 4.9857388e-01 7.2172678e-01 6.5223271e-01 6.3808075e-01 5.3665999e-01 6.9369532e-01 8.2305664e-01 6.2482915e-01 2.5251796e-01 7.1799256e-01 1.5895397e+00 6.2205176e-01 5.7257017e-01 5.6769031e-01 4.0438741e-01 1.7935777e+00 6.4755655e-01 1.6267976e+00 7.4777660e-01 1.4807336e+00 9.7270522e-01 1.3173487e+00 2.1839601e+00 1.2277129e+00 1.7938033e+00 1.1948932e+00 1.8448199e+00 8.7383925e-01 8.2305664e-01 1.1418127e+00 8.4591037e-01 1.2153720e+00 1.1640914e+00 9.1163729e-01 2.3638833e+00 2.4815883e+00 6.3861009e-01 1.3946921e+00 8.5434758e-01 2.2902807e+00 6.1151102e-01 1.2452704e+00 1.5325394e+00 6.0121055e-01 6.1092863e-01 1.1228379e+00 1.3752705e+00 1.7103060e+00 2.2560685e+00 1.1879078e+00 4.5470518e-01 9.0454394e-01 1.9729066e+00 1.3650300e+00 9.0521488e-01 6.0670504e-01 1.1454006e+00 1.3674559e+00 1.2262704e+00 7.4777660e-01 1.4820085e+00 1.4947429e+00 1.1729895e+00 7.3145860e-01 8.7720955e-01 1.2163831e+00 6.5633874e-01 2.1845981e-01 5.6769031e-01 7.4777660e-01 4.2538717e-01 9.5099818e-01 9.7994716e-01 1.0119857e+00 6.5223271e-01 8.3888121e-01 1.0038051e+00 5.9426792e-01 4.6472023e-01 6.0121055e-01 8.0326782e-01 9.2836103e-01 9.0876485e-01 3.7598397e-01 6.3861009e-01 1.5602029e+00 8.0326782e-01 7.0129382e-01 7.0043186e-01 2.0000000e-01 1.6208239e+00 7.0437330e-01 1.8619092e+00 9.6271042e-01 1.6849072e+00 1.3188999e+00 1.5860263e+00 2.4084158e+00 1.5142414e+00 2.0543079e+00 1.5230852e+00 1.9980352e+00 9.4375082e-01 1.0588560e+00 1.3035649e+00 1.0035600e+00 1.2499342e+00 1.2459608e+00 1.2225634e+00 2.5586145e+00 2.7210925e+00 8.9366705e-01 1.5500052e+00 1.0014633e+00 2.5139485e+00 6.9369532e-01 1.4790710e+00 1.7580510e+00 6.2660376e-01 7.0429250e-01 1.3804167e+00 1.5625881e+00 1.8966943e+00 2.3518757e+00 1.4139741e+00 8.0358695e-01 1.3075101e+00 2.0455018e+00 1.5153654e+00 1.2234738e+00 6.6539428e-01 1.2342162e+00 1.5049644e+00 1.1591754e+00 9.6271042e-01 1.7107332e+00 1.6328100e+00 1.1880428e+00 8.3812833e-01 1.0106392e+00 1.3267389e+00 8.9767734e-01 4.2538717e-01 6.2024833e-01 6.0181382e-01 1.1431021e+00 1.1948932e+00 1.2269747e+00 8.6361309e-01 8.2552685e-01 1.2002640e+00 6.5223271e-01 3.0811765e-01 7.1462831e-01 1.0067784e+00 1.1396406e+00 1.1147518e+00 5.0817745e-01 8.5335130e-01 1.7711504e+00 1.0085601e+00 9.0454394e-01 9.0277242e-01 4.0438741e-01 1.8140813e+00 9.1075311e-01 1.7412567e+00 9.8054887e-01 1.5527694e+00 1.2155004e+00 1.4692412e+00 2.2702600e+00 1.7126039e+00 1.9279661e+00 1.4238090e+00 1.8539569e+00 8.1558458e-01 9.5035453e-01 1.1763980e+00 1.0621081e+00 1.2047214e+00 1.1205013e+00 1.1134787e+00 2.4108292e+00 2.5851693e+00 9.6095130e-01 1.4178113e+00 1.0879524e+00 2.3751496e+00 6.0900723e-01 1.3570688e+00 1.6277043e+00 5.7015910e-01 6.6491075e-01 1.2652657e+00 1.4292566e+00 1.7566567e+00 2.1846001e+00 1.2961380e+00 7.1840099e-01 1.2329148e+00 1.8795815e+00 1.3897316e+00 1.1149070e+00 6.8757066e-01 1.0960883e+00 1.3785366e+00 1.0168833e+00 9.8054887e-01 1.5871961e+00 1.5043071e+00 1.0597541e+00 7.7033318e-01 8.8861541e-01 1.2058675e+00 8.9134001e-01 3.4583729e-01 8.1130291e-01 1.5090287e+00 1.4644753e+00 1.5150043e+00 1.1847335e+00 8.1385214e-01 1.4041085e+00 8.9917007e-01 3.0811765e-01 6.6539428e-01 1.2643026e+00 1.3836712e+00 1.3112758e+00 7.0784540e-01 1.1353806e+00 2.0777059e+00 1.2396136e+00 1.1498269e+00 1.1474460e+00 6.9006418e-01 2.1775976e+00 1.1752673e+00 1.4613032e+00 1.0391247e+00 1.1810170e+00 8.7504951e-01 1.1390131e+00 1.8670836e+00 1.9048338e+00 1.5205305e+00 1.0228981e+00 1.5676403e+00 6.7975091e-01 6.6539428e-01 8.7175869e-01 1.1533602e+00 1.2459608e+00 9.7730901e-01 7.5082357e-01 2.0536508e+00 2.1838261e+00 8.9095811e-01 1.1306949e+00 1.2394907e+00 1.9665910e+00 5.6769031e-01 1.0425476e+00 1.2324706e+00 6.4704320e-01 7.3851529e-01 9.5476489e-01 1.0198386e+00 1.3510699e+00 1.8411319e+00 1.0100718e+00 5.2942799e-01 9.3801395e-01 1.5112621e+00 1.2002762e+00 7.7763126e-01 8.2899253e-01 8.2305664e-01 1.1377990e+00 9.1663180e-01 1.0391247e+00 1.2653669e+00 1.2757312e+00 9.2288144e-01 6.4405773e-01 6.6827038e-01 1.0851476e+00 9.3048953e-01 7.7074935e-01 1.6569692e+00 1.5391185e+00 1.6134578e+00 1.2794849e+00 7.1504098e-01 1.3197776e+00 7.9613242e-01 3.2586371e-01 8.6165877e-01 1.2653669e+00 1.4028652e+00 1.2701139e+00 6.6384020e-01 1.2172454e+00 2.1489775e+00 1.2262704e+00 1.1578646e+00 1.1452867e+00 7.9613242e-01 2.2808589e+00 1.1959482e+00 1.1500393e+00 9.1075311e-01 9.3999899e-01 6.4806901e-01 8.5434758e-01 1.6806723e+00 1.8184542e+00 1.3334814e+00 8.5205778e-01 1.2702636e+00 3.4583729e-01 4.3456114e-01 5.6700421e-01 1.0389435e+00 1.0122141e+00 6.4290921e-01 5.0905001e-01 1.8419636e+00 1.9902374e+00 9.3801395e-01 8.1810461e-01 1.1069580e+00 1.7940242e+00 4.4651726e-01 7.4740267e-01 1.0346741e+00 5.1691876e-01 6.0121055e-01 6.6827038e-01 8.5205778e-01 1.1776640e+00 1.6778021e+00 7.0776547e-01 4.2667565e-01 7.8695083e-01 1.3400806e+00 8.6165877e-01 5.3022554e-01 7.0437330e-01 5.0592043e-01 8.1273630e-01 6.0670504e-01 9.1075311e-01 9.7270522e-01 9.4352681e-01 6.0551856e-01 5.7257017e-01 3.4378533e-01 7.5705927e-01 8.0064372e-01 1.0450018e+00 8.4812820e-01 9.3847194e-01 6.2988288e-01 6.0611244e-01 6.0060595e-01 5.0090417e-01 7.0784540e-01 6.2538346e-01 5.0592043e-01 6.6932542e-01 5.5492130e-01 1.5422108e-01 5.6075294e-01 1.4235605e+00 4.6472023e-01 4.2418962e-01 3.8776762e-01 2.8192292e-01 1.5978583e+00 4.5581864e-01 1.6256459e+00 6.5633874e-01 1.5986180e+00 1.1106412e+00 1.3708966e+00 2.3519748e+00 1.1147518e+00 1.9798165e+00 1.3654173e+00 1.8856245e+00 7.7033318e-01 8.5335130e-01 1.1771643e+00 6.8076724e-01 9.7270522e-01 1.0165138e+00 1.0391247e+00 2.5081056e+00 2.6437138e+00 7.6716823e-01 1.4120836e+00 6.1947990e-01 2.4692682e+00 4.8927739e-01 1.3077572e+00 1.7030709e+00 3.8934542e-01 4.4651726e-01 1.1594648e+00 1.5551984e+00 1.8760773e+00 2.3977345e+00 1.1868139e+00 6.2024833e-01 1.1056650e+00 2.0821572e+00 1.2794849e+00 1.0244319e+00 3.7427929e-01 1.1646003e+00 1.3139135e+00 1.1119327e+00 6.5633874e-01 1.5344007e+00 1.4333755e+00 1.0386594e+00 6.3735887e-01 8.2372435e-01 1.0901359e+00 6.2081167e-01 3.4583729e-01 2.8192292e-01 4.1586001e-01 1.6237100e+00 1.0540105e+00 1.1816401e+00 1.4110536e+00 9.8450810e-01 6.6432544e-01 5.3665999e-01 9.0454394e-01 1.1389644e+00 5.0905001e-01 7.1799256e-01 7.1504098e-01 7.3813096e-01 7.2783368e-01 8.7021234e-01 6.9006418e-01 6.2482915e-01 2.6619364e+00 1.6754669e+00 2.5821869e+00 2.1421834e+00 2.4107926e+00 3.3209792e+00 1.2036484e+00 2.9531363e+00 2.3720162e+00 2.8824828e+00 1.7671769e+00 1.8842354e+00 2.1714345e+00 1.6176764e+00 1.8723516e+00 2.0134817e+00 2.0676751e+00 3.4808493e+00 3.6264553e+00 1.5230852e+00 2.4135751e+00 1.5351194e+00 3.4281547e+00 1.4948868e+00 2.3378347e+00 2.6680945e+00 1.3977032e+00 1.4832928e+00 2.1976523e+00 2.4795532e+00 2.8157449e+00 3.2956170e+00 2.2214438e+00 1.6336229e+00 2.1064881e+00 2.9775369e+00 2.2994849e+00 2.0603946e+00 1.3916739e+00 2.1189748e+00 2.3204945e+00 1.9672068e+00 1.6754669e+00 2.5635110e+00 2.4436082e+00 1.9753271e+00 1.6077195e+00 1.8374244e+00 2.0981613e+00 1.6585806e+00 1.2418578e-01 3.7598397e-01 1.3405045e+00 8.3812833e-01 1.1437669e+00 1.3915412e+00 8.9095811e-01 6.2538346e-01 2.5251796e-01 6.0611244e-01 9.6791960e-01 3.4583729e-01 6.2205176e-01 4.5581864e-01 6.5223271e-01 5.7867728e-01 8.2619017e-01 8.2654509e-01 4.6472023e-01 2.4061696e+00 1.3868130e+00 2.3985329e+00 1.8751958e+00 2.1591630e+00 3.1397173e+00 8.9852394e-01 2.7599154e+00 2.1335771e+00 2.7193241e+00 1.6021202e+00 1.6415861e+00 1.9851797e+00 1.3336069e+00 1.6224878e+00 1.8082080e+00 1.8350829e+00 3.3292261e+00 3.4297053e+00 1.2340567e+00 2.2298076e+00 1.2654843e+00 3.2489933e+00 1.2770118e+00 2.1337366e+00 2.4988032e+00 1.1786349e+00 1.2545301e+00 1.9393053e+00 2.3288114e+00 2.6536325e+00 3.2010862e+00 1.9648876e+00 1.3964978e+00 1.8188234e+00 2.8588023e+00 2.0766308e+00 1.8216743e+00 1.1634384e+00 1.9698860e+00 2.1147926e+00 1.8660999e+00 1.3868130e+00 2.3472906e+00 2.2417376e+00 1.8131734e+00 1.3752391e+00 1.6372749e+00 1.8856245e+00 1.3922071e+00 4.0176783e-01 1.4467170e+00 9.3049742e-01 1.2002762e+00 1.4411886e+00 9.4375082e-01 6.6432544e-01 3.7427929e-01 7.0784540e-01 1.0466623e+00 4.0176783e-01 5.6700421e-01 5.5492130e-01 6.9728513e-01 6.4405773e-01 8.7170815e-01 7.3535471e-01 5.3309112e-01 2.5193321e+00 1.5039793e+00 2.4895662e+00 1.9791576e+00 2.2673478e+00 3.2268480e+00 1.0014633e+00 2.8466240e+00 2.2303173e+00 2.8133325e+00 1.6962564e+00 1.7458338e+00 2.0805039e+00 1.4552205e+00 1.7454671e+00 1.9165907e+00 1.9332869e+00 3.4131779e+00 3.5208177e+00 1.3379696e+00 2.3275025e+00 1.3866044e+00 3.3340853e+00 1.3784233e+00 2.2317775e+00 2.5822073e+00 1.2828332e+00 1.3595018e+00 2.0485193e+00 2.4057315e+00 2.7355566e+00 3.2722484e+00 2.0762069e+00 1.4905436e+00 1.9191337e+00 2.9375895e+00 2.1864773e+00 1.9213461e+00 1.2702636e+00 2.0582667e+00 2.2206505e+00 1.9521784e+00 1.5039793e+00 2.4497583e+00 2.3480580e+00 1.9124077e+00 1.4817438e+00 1.7372199e+00 1.9937367e+00 1.5016471e+00 1.2122249e+00 6.7975091e-01 8.4050231e-01 1.0796583e+00 6.6539428e-01 3.4583729e-01 3.2816937e-01 5.2942799e-01 7.3145860e-01 1.2418578e-01 9.1163729e-01 3.2586371e-01 3.7427929e-01 3.2816937e-01 5.0592043e-01 1.0122141e+00 2.1845981e-01 2.2481791e+00 1.2631020e+00 2.1874158e+00 1.7295419e+00 1.9965608e+00 2.9333950e+00 1.0072663e+00 2.5632712e+00 1.9670002e+00 2.4858980e+00 1.3655398e+00 1.4724669e+00 1.7716601e+00 1.2125198e+00 1.4903113e+00 1.6105641e+00 1.6572339e+00 3.0940465e+00 3.2344170e+00 1.1332978e+00 2.0129643e+00 1.1341579e+00 3.0445772e+00 1.0864449e+00 1.9287276e+00 2.2802541e+00 9.8820253e-01 1.0688498e+00 1.7838044e+00 2.1039999e+00 2.4365934e+00 2.9349538e+00 1.8084630e+00 1.2266837e+00 1.7026843e+00 2.6138892e+00 1.8911946e+00 1.6476803e+00 9.7949166e-01 1.7305789e+00 1.9168750e+00 1.6065247e+00 1.2631020e+00 2.1541966e+00 2.0395401e+00 1.5896248e+00 1.1996741e+00 1.4306494e+00 1.6928004e+00 1.2436109e+00 7.5791688e-01 8.1242502e-01 7.6625946e-01 7.5976039e-01 1.0289803e+00 1.1332978e+00 7.9613242e-01 5.3665999e-01 1.1149070e+00 1.9007091e+00 9.2836103e-01 9.3610001e-01 9.1858284e-01 8.1638392e-01 2.1493214e+00 1.0132664e+00 1.1680362e+00 3.2352160e-01 1.2372418e+00 5.4292906e-01 8.7170815e-01 1.9366254e+00 1.1486378e+00 1.5564198e+00 8.7420176e-01 1.5682049e+00 6.6491075e-01 4.5470518e-01 8.8358844e-01 4.5581864e-01 8.0326782e-01 7.9878917e-01 5.9426792e-01 2.1460410e+00 2.1931311e+00 5.0180477e-01 1.0950112e+00 5.0592043e-01 2.0545952e+00 3.4378533e-01 9.3923979e-01 1.3512935e+00 3.4583729e-01 3.4583729e-01 6.6539428e-01 1.2670555e+00 1.5369942e+00 2.1465859e+00 7.2526325e-01 3.0546431e-01 5.0991930e-01 1.8206746e+00 9.8054887e-01 5.7015910e-01 3.8776762e-01 9.6664346e-01 9.9089002e-01 1.0262547e+00 3.2352160e-01 1.1127329e+00 1.1166017e+00 8.7848692e-01 3.8934542e-01 5.8914551e-01 8.8062848e-01 3.2586371e-01 6.4755655e-01 1.3011270e+00 1.0122141e+00 4.2538717e-01 6.2660376e-01 4.4651726e-01 7.0086313e-01 6.3735887e-01 1.2926374e+00 4.0176783e-01 4.2288438e-01 3.8934542e-01 8.0619006e-01 1.5230852e+00 4.6472023e-01 1.6933635e+00 7.0233835e-01 1.9584922e+00 1.2594846e+00 1.5411691e+00 2.6785768e+00 6.2605182e-01 2.3003744e+00 1.6284481e+00 2.1882128e+00 1.1729895e+00 1.1500393e+00 1.5577059e+00 7.1881659e-01 9.8985697e-01 1.2389598e+00 1.3108618e+00 2.8217641e+00 2.9357847e+00 9.3026633e-01 1.7457596e+00 5.7867728e-01 2.7994225e+00 9.3610001e-01 1.5801828e+00 2.0692197e+00 8.2384013e-01 7.4740267e-01 1.3410314e+00 1.9783833e+00 2.2683159e+00 2.8062463e+00 1.3610783e+00 9.7249562e-01 1.1868139e+00 2.5244698e+00 1.3852951e+00 1.2460824e+00 6.3808075e-01 1.6077195e+00 1.5873000e+00 1.5826476e+00 7.0233835e-01 1.7831878e+00 1.6667819e+00 1.4276261e+00 9.9519977e-01 1.1984588e+00 1.1903343e+00 7.0386584e-01 7.1840099e-01 1.1107977e+00 5.8624446e-01 9.8495853e-01 8.7504951e-01 4.1586001e-01 8.7720955e-01 1.5824669e+00 7.5976039e-01 5.5160819e-01 5.7741073e-01 5.4292906e-01 1.6736318e+00 6.7975091e-01 1.5883552e+00 8.2552685e-01 1.5948732e+00 1.1332978e+00 1.3595997e+00 2.3503762e+00 1.2554784e+00 1.9862884e+00 1.4596621e+00 1.8378727e+00 7.2852070e-01 9.6204649e-01 1.1697902e+00 9.6664346e-01 9.6271042e-01 9.5676647e-01 1.0496979e+00 2.4751922e+00 2.6546397e+00 1.2224367e+00 1.3843268e+00 7.2343175e-01 2.4751922e+00 7.5082357e-01 1.2832075e+00 1.7000773e+00 6.2988288e-01 5.0592043e-01 1.1833351e+00 1.5613251e+00 1.8886923e+00 2.3645560e+00 1.2016233e+00 7.5791688e-01 1.2125198e+00 2.0748074e+00 1.2155370e+00 1.0244319e+00 4.5470518e-01 1.1485394e+00 1.2770118e+00 1.0720678e+00 8.2552685e-01 1.5113992e+00 1.3835368e+00 1.0035600e+00 9.5571254e-01 8.2234151e-01 1.0120221e+00 6.5223271e-01 8.3888121e-01 1.1486378e+00 1.2994764e+00 1.2307737e+00 6.0181382e-01 1.0483827e+00 1.9867752e+00 1.1408504e+00 1.0391247e+00 1.0361698e+00 5.7867728e-01 2.0669733e+00 1.0646687e+00 1.4623898e+00 9.5866719e-01 1.2497790e+00 9.3048953e-01 1.1765359e+00 1.9666356e+00 1.8175297e+00 1.6242657e+00 1.1520347e+00 1.5603665e+00 5.7324170e-01 7.0233835e-01 8.8887100e-01 1.0919404e+00 1.1355826e+00 8.9712482e-01 8.1385214e-01 2.1052360e+00 2.2845234e+00 1.0166932e+00 1.1341579e+00 1.1332978e+00 2.0738150e+00 5.3309112e-01 1.0588560e+00 1.3224963e+00 5.5492130e-01 6.2538346e-01 9.8450810e-01 1.1271488e+00 1.4561933e+00 1.8911946e+00 1.0230441e+00 5.2574978e-01 1.0056742e+00 1.5916843e+00 1.1355826e+00 8.2105460e-01 7.1504098e-01 8.1527569e-01 1.1176720e+00 8.2899253e-01 9.5866719e-01 1.2943100e+00 1.2429818e+00 8.5205778e-01 7.0233835e-01 6.2660376e-01 9.8054887e-01 8.3649708e-01 8.7822463e-01 8.2899253e-01 8.1099042e-01 7.0826681e-01 5.8914551e-01 1.5042268e+00 7.3813096e-01 8.1558458e-01 7.4855857e-01 6.0121055e-01 1.6260946e+00 7.0386584e-01 1.8605327e+00 8.8503502e-01 1.6493191e+00 1.2601890e+00 1.5390703e+00 2.3592515e+00 1.4088394e+00 1.9940473e+00 1.4245508e+00 2.0716002e+00 1.1004436e+00 9.8820253e-01 1.2927814e+00 9.0056222e-01 1.2208301e+00 1.3194807e+00 1.1996741e+00 2.6153308e+00 2.6539963e+00 6.2538346e-01 1.5687169e+00 9.5271386e-01 2.4562038e+00 6.6491075e-01 1.5249255e+00 1.7538274e+00 6.6539428e-01 8.2619017e-01 1.3131724e+00 1.5409345e+00 1.8470010e+00 2.4533073e+00 1.3504603e+00 7.7039952e-01 1.2057554e+00 2.0352149e+00 1.6006330e+00 1.2331989e+00 8.0660588e-01 1.2747177e+00 1.5040391e+00 1.2426449e+00 8.8503502e-01 1.7019078e+00 1.6700310e+00 1.2144845e+00 7.4855857e-01 1.0401425e+00 1.4600567e+00 9.3296062e-01 5.0180477e-01 4.4651726e-01 6.2149089e-01 4.1586001e-01 1.0078327e+00 3.0275928e-01 1.4096146e-01 1.4096146e-01 6.0611244e-01 1.1536782e+00 2.0656129e-01 2.0491051e+00 1.0646687e+00 2.0979729e+00 1.5528443e+00 1.8279176e+00 2.8469870e+00 8.2234151e-01 2.4692682e+00 1.8399871e+00 2.3632803e+00 1.2493717e+00 1.3312249e+00 1.6756749e+00 1.0425476e+00 1.3092012e+00 1.4505265e+00 1.5123788e+00 2.9884772e+00 3.1361386e+00 1.0755693e+00 1.9017004e+00 9.3801395e-01 2.9635613e+00 9.8054887e-01 1.7833384e+00 2.1970231e+00 8.6513410e-01 8.9742724e-01 1.6159903e+00 2.0524973e+00 2.3760856e+00 2.8811560e+00 1.6399646e+00 1.0934620e+00 1.5205305e+00 2.5867433e+00 1.6928004e+00 1.4836711e+00 7.9580667e-01 1.6659943e+00 1.7839298e+00 1.5792930e+00 1.0646687e+00 2.0113485e+00 1.8901379e+00 1.5067717e+00 1.0950112e+00 1.3129189e+00 1.4875372e+00 1.0389435e+00 4.0293660e-01 8.0499049e-01 3.0546431e-01 7.8197925e-01 2.5251796e-01 5.1691876e-01 4.2538717e-01 7.4740267e-01 1.0181000e+00 3.2586371e-01 2.1717162e+00 1.1533602e+00 2.2234347e+00 1.6690840e+00 1.9433381e+00 2.9713636e+00 7.2486328e-01 2.5929835e+00 1.9489982e+00 2.5241649e+00 1.4089364e+00 1.4425304e+00 1.8012344e+00 1.0919712e+00 1.3726860e+00 1.5830057e+00 1.6408468e+00 3.1546522e+00 3.2544456e+00 1.0406064e+00 2.0352149e+00 1.0168833e+00 3.0859269e+00 1.0901359e+00 1.9325796e+00 2.3348454e+00 9.8054887e-01 1.0379132e+00 1.7250039e+00 2.1825260e+00 2.4995667e+00 3.0529994e+00 1.7458338e+00 1.2167151e+00 1.6214915e+00 2.7108297e+00 1.8418195e+00 1.6195190e+00 9.3847194e-01 1.7995863e+00 1.9034198e+00 1.7022897e+00 1.1533602e+00 2.1413027e+00 2.0233319e+00 1.6211869e+00 1.1770266e+00 1.4411886e+00 1.6502968e+00 1.1644030e+00 6.5633874e-01 4.4417983e-01 1.1332978e+00 2.1845981e-01 4.2538717e-01 3.4583729e-01 7.1504098e-01 1.4080793e+00 3.4583729e-01 1.8866180e+00 8.7848692e-01 1.9819543e+00 1.3312249e+00 1.6523803e+00 2.6988671e+00 6.9006418e-01 2.3100474e+00 1.6455737e+00 2.2934334e+00 1.2426449e+00 1.1905954e+00 1.5932297e+00 8.9095811e-01 1.2681309e+00 1.4065584e+00 1.3487634e+00 2.8835141e+00 2.9705897e+00 7.3805807e-01 1.8205354e+00 8.5462626e-01 2.8117234e+00 9.3049742e-01 1.6679957e+00 2.0758969e+00 8.4050231e-01 8.3060013e-01 1.4419145e+00 1.9521697e+00 2.2599493e+00 2.8310619e+00 1.4807336e+00 9.4558103e-01 1.2404967e+00 2.5235709e+00 1.6070713e+00 1.3102444e+00 7.5705927e-01 1.6281130e+00 1.7021627e+00 1.6240596e+00 8.7848692e-01 1.8790831e+00 1.8155245e+00 1.5040391e+00 1.0014633e+00 1.2481462e+00 1.4334902e+00 8.6165877e-01 6.6827038e-01 1.5475692e+00 5.8914551e-01 5.0503591e-01 4.9857388e-01 3.0811765e-01 1.7160413e+00 5.7324170e-01 1.5795964e+00 6.5648056e-01 1.4967461e+00 1.0182895e+00 1.3034549e+00 2.2380042e+00 1.2266837e+00 1.8619092e+00 1.2701139e+00 1.8007564e+00 7.2852070e-01 7.9016429e-01 1.0989735e+00 7.5705927e-01 1.0406064e+00 1.0184370e+00 9.3999899e-01 2.3886514e+00 2.5357185e+00 8.2684479e-01 1.3424112e+00 7.0776547e-01 2.3522207e+00 4.8927739e-01 1.2205493e+00 1.5832517e+00 4.2667565e-01 4.4417983e-01 1.0974061e+00 1.4319225e+00 1.7587110e+00 2.2711652e+00 1.1390131e+00 5.1691876e-01 1.0163549e+00 1.9782498e+00 1.2532075e+00 9.2859317e-01 4.1449626e-01 1.0852663e+00 1.2786117e+00 1.0887986e+00 6.5648056e-01 1.4596621e+00 1.3991741e+00 1.0313560e+00 6.6932542e-01 7.7553525e-01 1.0741917e+00 5.7257017e-01 9.4558103e-01 2.5651975e-01 4.1449626e-01 3.2816937e-01 4.8135521e-01 1.0908017e+00 2.1845981e-01 2.1701312e+00 1.1752673e+00 2.1084262e+00 1.6352583e+00 1.9101184e+00 2.8518881e+00 9.7825559e-01 2.4781934e+00 1.8745369e+00 2.4235816e+00 1.3078976e+00 1.3842113e+00 1.6965018e+00 1.1329323e+00 1.4319225e+00 1.5496439e+00 1.5691346e+00 3.0266197e+00 3.1503439e+00 1.0244319e+00 1.9425540e+00 1.0627606e+00 2.9623467e+00 1.0056742e+00 1.8539828e+00 2.2026387e+00 9.1163729e-01 9.9475949e-01 1.6952454e+00 2.0275673e+00 2.3581240e+00 2.8793190e+00 1.7227544e+00 1.1332978e+00 1.6029963e+00 2.5482247e+00 1.8278913e+00 1.5611067e+00 9.1163729e-01 1.6653066e+00 1.8462692e+00 1.5634147e+00 1.1752673e+00 2.0757295e+00 1.9739212e+00 1.5320003e+00 1.1179743e+00 1.3567326e+00 1.6362950e+00 1.1594648e+00 9.9475949e-01 1.1004436e+00 1.0720678e+00 1.4108494e+00 3.2816937e-01 9.8054887e-01 2.9240179e+00 1.9013501e+00 3.0016960e+00 2.4403742e+00 2.7185134e+00 3.7481490e+00 1.2643026e+00 3.3676733e+00 2.7249658e+00 3.2951180e+00 2.1701459e+00 2.2231652e+00 2.5778372e+00 1.8193838e+00 2.0594742e+00 2.3383666e+00 2.4210417e+00 3.9277558e+00 4.0319248e+00 1.8011138e+00 2.8105150e+00 1.7324239e+00 3.8595400e+00 1.8657887e+00 2.7098209e+00 3.1083486e+00 1.7551534e+00 1.8090259e+00 2.5002193e+00 2.9463843e+00 3.2688068e+00 3.8087204e+00 2.5182043e+00 1.9933741e+00 2.3692479e+00 3.4705738e+00 2.5885717e+00 2.3959721e+00 1.7005893e+00 2.5655126e+00 2.6734142e+00 2.4311441e+00 1.9013501e+00 2.9205331e+00 2.7876433e+00 2.3735872e+00 1.9516947e+00 2.2170194e+00 2.3879674e+00 1.9213461e+00 3.0546431e-01 2.0656129e-01 6.0611244e-01 1.2246352e+00 1.4096146e-01 1.9777274e+00 9.7249562e-01 2.0297383e+00 1.4616539e+00 1.7458338e+00 2.7737198e+00 7.5082357e-01 2.3931826e+00 1.7478866e+00 2.3213742e+00 1.2131545e+00 1.2498134e+00 1.6130724e+00 9.3824087e-01 1.2565757e+00 1.4029855e+00 1.4325768e+00 2.9414941e+00 3.0577671e+00 8.7720955e-01 1.8438146e+00 8.6956871e-01 2.8895427e+00 9.1310225e-01 1.7228354e+00 2.1321061e+00 8.0499049e-01 8.3345577e-01 1.5318874e+00 1.9898963e+00 2.3090270e+00 2.8491218e+00 1.5587730e+00 1.0122141e+00 1.4162017e+00 2.5326059e+00 1.6463627e+00 1.4047678e+00 7.3805807e-01 1.6165635e+00 1.7228488e+00 1.5520745e+00 9.7249562e-01 1.9420274e+00 1.8372522e+00 1.4628493e+00 1.0030700e+00 1.2523175e+00 1.4531349e+00 9.5571254e-01 1.2418578e-01 5.0270183e-01 1.2603076e+00 2.1269358e-01 1.9932786e+00 1.0168833e+00 1.9946994e+00 1.4557537e+00 1.7495699e+00 2.7337358e+00 9.0575661e-01 2.3519748e+00 1.7324239e+00 2.2796281e+00 1.1801240e+00 1.2450709e+00 1.5872286e+00 1.0267435e+00 1.3336069e+00 1.4152303e+00 1.4096199e+00 2.8778917e+00 3.0268604e+00 1.0067464e+00 1.8215944e+00 9.3824087e-01 2.8471683e+00 9.0658670e-01 1.6933635e+00 2.0801243e+00 8.0758367e-01 8.3783744e-01 1.5390703e+00 1.9310038e+00 2.2599493e+00 2.7651778e+00 1.5728839e+00 9.7949166e-01 1.4165336e+00 2.4822593e+00 1.6510537e+00 1.3842113e+00 7.5755387e-01 1.5773217e+00 1.7253276e+00 1.5255331e+00 1.0168833e+00 1.9287244e+00 1.8366596e+00 1.4599710e+00 1.0339865e+00 1.2378278e+00 1.4537266e+00 9.7249562e-01 5.0090417e-01 1.2507669e+00 1.2418578e-01 1.9589833e+00 9.7270522e-01 1.9792779e+00 1.4437673e+00 1.7230625e+00 2.7260686e+00 8.6012420e-01 2.3478326e+00 1.7190893e+00 2.2590861e+00 1.1454006e+00 1.2174316e+00 1.5614941e+00 9.5476489e-01 1.2555979e+00 1.3635198e+00 1.3969297e+00 2.8759951e+00 3.0161959e+00 9.4558103e-01 1.7925890e+00 8.6983677e-01 2.8416706e+00 8.6513410e-01 1.6742876e+00 2.0756986e+00 7.5871717e-01 7.9613242e-01 1.5107481e+00 1.9286915e+00 2.2531942e+00 2.7669732e+00 1.5384446e+00 9.7270522e-01 1.4111029e+00 2.4671050e+00 1.6105641e+00 1.3717027e+00 7.0429250e-01 1.5517600e+00 1.6837214e+00 1.4807336e+00 9.7270522e-01 1.9032219e+00 1.7953587e+00 1.4097072e+00 9.7855477e-01 1.2036484e+00 1.4110536e+00 9.4309624e-01 1.5090287e+00 5.0905001e-01 1.8619092e+00 9.1163729e-01 1.7230625e+00 1.3188999e+00 1.5883552e+00 2.4588872e+00 1.3193952e+00 2.0946464e+00 1.5338492e+00 2.0321740e+00 9.5099818e-01 1.0604511e+00 1.3277861e+00 9.3296062e-01 1.2221471e+00 1.2470767e+00 1.2266837e+00 2.6106370e+00 2.7667028e+00 8.7420176e-01 1.5746612e+00 8.9852394e-01 2.5679581e+00 6.9369532e-01 1.4905436e+00 1.8028753e+00 6.2149089e-01 6.9006418e-01 1.3813076e+00 1.6199747e+00 1.9552274e+00 2.4344864e+00 1.4148192e+00 8.0358695e-01 1.3039319e+00 2.1287551e+00 1.5153654e+00 1.2246352e+00 6.2660376e-01 1.2741904e+00 1.5160122e+00 1.2047214e+00 9.1163729e-01 1.7242097e+00 1.6420607e+00 1.2064640e+00 8.3812833e-01 1.0168833e+00 1.3257654e+00 8.6137722e-01 1.1533602e+00 3.1382691e+00 2.1485328e+00 3.1786790e+00 2.6799312e+00 2.9354140e+00 3.9353144e+00 1.5252485e+00 3.5658557e+00 2.9475994e+00 3.4455976e+00 2.3167786e+00 2.4320363e+00 2.7459122e+00 2.0598189e+00 2.2501104e+00 2.5013206e+00 2.6321552e+00 4.0910078e+00 4.2293986e+00 2.0521052e+00 2.9731112e+00 1.9619929e+00 4.0491656e+00 2.0481101e+00 2.8946126e+00 3.2860707e+00 1.9342059e+00 2.0025214e+00 2.7210925e+00 3.1148548e+00 3.4424959e+00 3.9360563e+00 2.7333517e+00 2.2078200e+00 2.6383936e+00 3.6047462e+00 2.7713578e+00 2.6121617e+00 1.8925840e+00 2.7075477e+00 2.8419886e+00 2.5215069e+00 2.1485328e+00 3.1102248e+00 2.9517129e+00 2.5041493e+00 2.1435335e+00 2.3887866e+00 2.5633372e+00 2.1544995e+00 2.0467316e+00 1.0576043e+00 2.0528819e+00 1.5379283e+00 1.8096161e+00 2.8029161e+00 8.6012420e-01 2.4272793e+00 1.8028753e+00 2.3372930e+00 1.2144845e+00 1.2985682e+00 1.6312555e+00 1.0166932e+00 1.3073038e+00 1.4333755e+00 1.4843487e+00 2.9588514e+00 3.0950947e+00 9.7949166e-01 1.8647706e+00 9.3615100e-01 2.9181741e+00 9.3049742e-01 1.7594421e+00 2.1522124e+00 8.2342214e-01 8.7720955e-01 1.5965946e+00 1.9973159e+00 2.3235032e+00 2.8379387e+00 1.6211988e+00 1.0588560e+00 1.5076049e+00 2.5254157e+00 1.6945041e+00 1.4637418e+00 7.8197925e-01 1.6130724e+00 1.7539916e+00 1.5193574e+00 1.0576043e+00 1.9849009e+00 1.8691652e+00 1.4607586e+00 1.0375119e+00 1.2741904e+00 1.4947429e+00 1.0361698e+00 1.0621081e+00 8.3649708e-01 7.6590510e-01 4.0176783e-01 1.3455136e+00 1.8827665e+00 1.1093572e+00 9.5676647e-01 9.0852141e-01 9.4309624e-01 8.9852394e-01 6.8076724e-01 1.2002762e+00 9.7825559e-01 7.0479928e-01 7.8197925e-01 1.4637418e+00 1.5390703e+00 1.4628493e+00 6.2538346e-01 1.2208301e+00 1.4754770e+00 1.2162549e+00 5.2574978e-01 1.0104465e+00 1.2832075e+00 1.1810170e+00 6.1947990e-01 1.1242402e+00 1.1718516e+00 1.6295015e+00 5.8914551e-01 1.2063335e+00 1.1879206e+00 1.4041085e+00 4.0293660e-01 7.7074935e-01 1.2709820e+00 7.7869083e-01 5.0592043e-01 9.7441804e-01 1.0621081e+00 5.0991930e-01 4.4417983e-01 8.3888121e-01 1.1770266e+00 8.6361309e-01 6.0670504e-01 1.0324775e+00 1.3844611e+00 6.2660376e-01 8.8695363e-01 2.0692197e+00 9.7441804e-01 1.6995747e+00 1.0122141e+00 1.6372749e+00 7.6752131e-01 6.0551856e-01 1.0244319e+00 2.1845981e-01 5.0090417e-01 7.2852070e-01 7.4777660e-01 2.2645802e+00 2.3019759e+00 5.7324170e-01 1.1833351e+00 2.5651975e-01 2.1907335e+00 5.0905001e-01 1.0330459e+00 1.5124582e+00 4.4651726e-01 3.8934542e-01 6.9369532e-01 1.4517959e+00 1.7036156e+00 2.3021295e+00 7.0429250e-01 5.6700421e-01 6.3977563e-01 1.9782093e+00 8.7229670e-01 6.8801986e-01 3.8934542e-01 1.1199472e+00 9.9519977e-01 1.1263042e+00 0.0000000e+00 1.1697902e+00 1.0851476e+00 9.2859317e-01 5.0905001e-01 7.1504098e-01 7.7763126e-01 3.0546431e-01 8.2135873e-01 6.0121055e-01 7.6716823e-01 2.3579605e+00 4.5581864e-01 5.8914551e-01 6.5223271e-01 8.9095811e-01 8.2552685e-01 4.4417983e-01 1.5124582e+00 1.3844611e+00 8.1810461e-01 6.6384020e-01 1.0516761e+00 1.0733200e+00 1.3725949e+00 3.0844217e-01 1.6183051e+00 8.9095811e-01 1.1426203e+00 4.5470518e-01 3.2816937e-01 1.2604558e+00 1.2459608e+00 7.1799256e-01 5.0180477e-01 3.6171588e-01 1.0269295e+00 7.1840099e-01 1.0531192e+00 1.1093572e+00 6.1092863e-01 8.4591037e-01 7.4777660e-01 1.3693737e+00 5.0905001e-01 4.8135521e-01 8.0619006e-01 1.3844611e+00 3.4378533e-01 5.3309112e-01 7.3813096e-01 1.0901359e+00 8.1273630e-01 9.6141901e-01 1.2978356e+00 4.2667565e-01 1.4573287e+00 1.5826638e+00 1.0904758e+00 5.0503591e-01 1.1258723e+00 5.4292906e-01 3.2816937e-01 5.3022554e-01 7.7869083e-01 7.5871717e-01 5.5492130e-01 2.1269358e-01 1.6596342e+00 1.6919202e+00 8.3280511e-01 7.0429250e-01 8.7202528e-01 1.5772389e+00 7.0394675e-01 5.2655962e-01 9.2836103e-01 8.0064372e-01 7.0437330e-01 3.0546431e-01 9.0478973e-01 1.1271488e+00 1.7235501e+00 4.0293660e-01 5.2942799e-01 4.5470518e-01 1.4317371e+00 6.8917100e-01 2.1269358e-01 8.1099042e-01 6.2988288e-01 6.5172743e-01 7.6166891e-01 6.2660376e-01 6.5648056e-01 7.6625946e-01 6.1947990e-01 6.4755655e-01 4.2667565e-01 6.2660376e-01 5.6700421e-01 1.2113327e+00 1.8396098e+00 8.7504951e-01 5.7257017e-01 8.3280511e-01 7.0784540e-01 5.5492130e-01 3.7427929e-01 1.0284501e+00 8.7420176e-01 5.0991930e-01 4.4417983e-01 1.4089719e+00 1.4387122e+00 1.1127329e+00 4.1586001e-01 1.1205013e+00 1.3344634e+00 9.3048953e-01 3.2816937e-01 7.4164639e-01 1.0244319e+00 9.3999899e-01 2.5651975e-01 8.1242502e-01 9.1858284e-01 1.4955532e+00 2.5251796e-01 8.7420176e-01 8.5335130e-01 1.2045536e+00 4.3691963e-01 4.4651726e-01 1.0480665e+00 4.9857388e-01 2.8507955e-01 7.3535471e-01 8.8695363e-01 3.2816937e-01 3.8934542e-01 6.0611244e-01 8.6361309e-01 6.0551856e-01 5.2655962e-01 8.3783744e-01 3.0351721e+00 4.2418962e-01 1.0941064e+00 7.5705927e-01 1.6559784e+00 1.5582387e+00 1.2112034e+00 2.1967372e+00 2.0692197e+00 1.5564198e+00 1.3693737e+00 8.0096515e-01 4.5581864e-01 2.0330276e+00 1.0137836e+00 2.3142399e+00 2.1845981e-01 1.9017011e+00 1.1228379e+00 6.6827038e-01 2.0223026e+00 1.9969203e+00 1.3792358e+00 8.7478495e-01 5.2371571e-01 8.1385214e-01 1.3793330e+00 1.7664528e+00 1.6569692e+00 5.0905001e-01 1.4644753e+00 1.4341959e+00 2.1204309e+00 1.2632199e+00 1.1880428e+00 1.5405106e+00 2.0692197e+00 9.4009473e-01 1.1355826e+00 1.4992973e+00 1.8311457e+00 1.5765737e+00 1.6311692e+00 1.9969203e+00 2.6670272e+00 1.9783833e+00 2.5784641e+00 1.6572339e+00 1.5613865e+00 1.9842916e+00 8.6110333e-01 1.0720678e+00 1.6180482e+00 1.7140774e+00 3.2123303e+00 3.2542669e+00 1.1332978e+00 2.1449779e+00 7.5976039e-01 3.1540626e+00 1.4088394e+00 1.9797139e+00 2.4825886e+00 1.3075101e+00 1.2330392e+00 1.6629594e+00 2.4148300e+00 2.6746409e+00 3.2573703e+00 1.6686069e+00 1.4322723e+00 1.4341959e+00 2.9471490e+00 1.6864366e+00 1.6385322e+00 1.1320702e+00 2.0632091e+00 1.9468380e+00 2.0389505e+00 9.7441804e-01 2.1303950e+00 2.0095672e+00 1.8517858e+00 1.4168607e+00 1.6483152e+00 1.5346983e+00 1.0866092e+00 7.2486328e-01 8.7202528e-01 1.2988558e+00 1.1847335e+00 8.6137722e-01 1.8265471e+00 1.7177705e+00 1.2107055e+00 9.9368623e-01 9.5866719e-01 7.3805807e-01 1.6506221e+00 7.3805807e-01 1.9449573e+00 5.0592043e-01 1.5350426e+00 7.8695083e-01 3.7427929e-01 1.6553809e+00 1.6249178e+00 1.0168833e+00 5.0991930e-01 2.1845981e-01 9.7270522e-01 1.0264409e+00 1.3817041e+00 1.2768639e+00 5.7324170e-01 1.1634384e+00 1.0611732e+00 1.7483574e+00 9.3048953e-01 9.0056222e-01 1.2340567e+00 1.6995747e+00 6.8076724e-01 9.1883539e-01 1.1718516e+00 1.4616896e+00 1.2125198e+00 1.2951888e+00 1.6249178e+00 1.2028939e+00 8.7420176e-01 5.3665999e-01 5.5492130e-01 1.1340084e+00 1.0720678e+00 8.3345577e-01 5.3588338e-01 1.5520745e+00 1.3258714e+00 9.5099818e-01 7.7074935e-01 1.2604558e+00 1.1891470e+00 9.2264612e-01 8.1099042e-01 7.7039952e-01 1.0389435e+00 1.0054794e+00 4.3456114e-01 6.2605182e-01 7.2823007e-01 1.5784191e+00 4.8927739e-01 7.5976039e-01 6.5223271e-01 1.0692258e+00 9.8985697e-01 6.3808075e-01 1.1178200e+00 6.6827038e-01 7.4855857e-01 8.6513410e-01 1.0122141e+00 7.6787403e-01 9.3615100e-01 7.5835500e-01 8.2654509e-01 6.9728513e-01 9.9519977e-01 9.7356960e-01 1.1306887e+00 1.2197188e+00 8.0353565e-01 1.7933375e+00 1.5916843e+00 1.0118409e+00 1.0089164e+00 7.0776547e-01 1.1591754e+00 1.8437762e+00 5.3309112e-01 1.8278913e+00 9.6838716e-01 1.4843324e+00 6.3735887e-01 7.3496673e-01 1.5570415e+00 1.5003972e+00 1.0421979e+00 9.7759114e-01 8.9070384e-01 7.8197925e-01 1.0329598e+00 1.4388174e+00 1.5204340e+00 6.9325418e-01 9.4309624e-01 1.0339865e+00 1.6134578e+00 8.0660588e-01 7.0523271e-01 1.0406064e+00 1.6372749e+00 5.1303949e-01 5.8851328e-01 1.0072663e+00 1.4951106e+00 1.0950112e+00 1.0934620e+00 1.5213929e+00 5.0991930e-01 4.5581864e-01 9.3615100e-01 7.6590510e-01 3.2586371e-01 4.2538717e-01 1.7942496e+00 1.9566981e+00 1.0636401e+00 6.6384020e-01 9.2264612e-01 1.7814077e+00 5.2371571e-01 6.0670504e-01 1.0120221e+00 4.8927739e-01 4.3691963e-01 5.6769031e-01 8.9366705e-01 1.1948578e+00 1.6982795e+00 5.7324170e-01 5.7257017e-01 8.3060013e-01 1.3824965e+00 5.7867728e-01 4.1586001e-01 5.4292906e-01 4.4651726e-01 5.7324170e-01 4.4535192e-01 7.6752131e-01 8.2105460e-01 6.9369532e-01 3.4583729e-01 7.0479928e-01 2.0656129e-01 4.3456114e-01 6.1092863e-01 4.6472023e-01 7.1840099e-01 6.9369532e-01 5.6631629e-01 3.2816937e-01 1.8058693e+00 1.8261179e+00 6.3735887e-01 7.0328431e-01 8.2684479e-01 1.6791597e+00 4.0293660e-01 6.6827038e-01 9.7377870e-01 5.0991930e-01 4.8135521e-01 3.2586371e-01 8.7021234e-01 1.1327825e+00 1.7839298e+00 3.7427929e-01 4.1586001e-01 5.5492130e-01 1.3916739e+00 7.7919451e-01 4.1449626e-01 5.8914551e-01 5.7324170e-01 6.0900723e-01 6.2407309e-01 6.0551856e-01 7.5705927e-01 7.8695083e-01 4.8135521e-01 3.2586371e-01 3.0811765e-01 7.3851529e-01 5.3665999e-01 1.1524979e+00 1.0244319e+00 4.3691963e-01 3.7255734e-01 1.4090646e+00 1.5060944e+00 1.0810263e+00 2.8507955e-01 1.2406194e+00 1.3336069e+00 7.1791510e-01 3.2586371e-01 5.9426792e-01 8.2552685e-01 8.2275389e-01 4.1449626e-01 5.8851328e-01 7.5196795e-01 1.3415658e+00 4.1586001e-01 7.2852070e-01 8.9159388e-01 9.7249562e-01 5.8914551e-01 4.4535192e-01 9.4352681e-01 1.4096146e-01 3.0811765e-01 4.1586001e-01 1.0244319e+00 4.2538717e-01 4.5581864e-01 3.2586371e-01 7.0869559e-01 3.7427929e-01 6.5223271e-01 9.2836103e-01 4.4651726e-01 8.8695363e-01 8.9971984e-01 2.4227359e+00 2.4243464e+00 5.5419992e-01 1.3235313e+00 3.0546431e-01 2.3149695e+00 6.1151102e-01 1.2036484e+00 1.6520677e+00 5.4292906e-01 5.7324170e-01 8.2305664e-01 1.5788188e+00 1.8238348e+00 2.4554026e+00 8.2552685e-01 7.0429250e-01 7.7588000e-01 2.0959492e+00 1.0466623e+00 8.6513410e-01 5.4292906e-01 1.2497790e+00 1.1215059e+00 1.2436109e+00 2.1845981e-01 1.3165513e+00 1.2256881e+00 1.0406064e+00 6.0060595e-01 8.5434758e-01 9.6664346e-01 5.1691876e-01 6.5223271e-01 8.4050231e-01 2.2451458e+00 2.2996030e+00 9.7270522e-01 1.1594648e+00 4.2538717e-01 2.1936248e+00 6.9369532e-01 1.0119857e+00 1.5297036e+00 6.6384020e-01 6.2988288e-01 7.0386584e-01 1.5113992e+00 1.7140171e+00 2.2868482e+00 6.9325418e-01 9.4080461e-01 1.0406064e+00 1.9734538e+00 7.5835500e-01 7.8695083e-01 6.2988288e-01 1.1158787e+00 9.4832302e-01 1.1055069e+00 5.0090417e-01 1.1452867e+00 1.0056742e+00 9.0277242e-01 6.3977563e-01 7.3851529e-01 6.6432544e-01 6.0611244e-01 5.1691876e-01 1.6983410e+00 1.8377590e+00 1.1500393e+00 5.6631629e-01 8.6012420e-01 1.6864433e+00 6.6539428e-01 4.5581864e-01 9.7356960e-01 6.6932542e-01 5.9426792e-01 4.5470518e-01 9.7548738e-01 1.1573546e+00 1.6772907e+00 4.4535192e-01 8.2929029e-01 9.8450810e-01 1.3812107e+00 3.2816937e-01 5.0905001e-01 6.6932542e-01 5.0991930e-01 3.7598397e-01 5.0905001e-01 7.2852070e-01 6.4704320e-01 4.5581864e-01 3.2586371e-01 7.4777660e-01 3.2816937e-01 2.5251796e-01 6.3108414e-01 1.5573817e+00 1.6420607e+00 9.0575661e-01 5.7867728e-01 9.7441804e-01 1.4917344e+00 6.2482915e-01 4.0176783e-01 7.7039952e-01 7.1799256e-01 6.4704320e-01 3.2816937e-01 7.1799256e-01 9.7270522e-01 1.5593809e+00 4.1586001e-01 4.6472023e-01 5.6454040e-01 1.2601890e+00 6.5223271e-01 1.2418578e-01 7.6716823e-01 4.4651726e-01 6.0670504e-01 6.1947990e-01 7.4777660e-01 5.9426792e-01 7.2172678e-01 5.3588338e-01 6.2660376e-01 3.2352160e-01 5.8914551e-01 6.4704320e-01 1.2013436e+00 2.3665136e+00 1.1771643e+00 2.4806944e+00 1.0018083e+00 2.1098467e+00 1.2627078e+00 8.8503502e-01 2.2024869e+00 2.1511385e+00 1.6189643e+00 1.1368070e+00 1.0688498e+00 3.4378533e-01 1.6188960e+00 1.9698860e+00 1.9254808e+00 8.8861541e-01 1.5832517e+00 1.5978297e+00 2.2712062e+00 1.4277162e+00 1.3610783e+00 1.6849072e+00 2.2645802e+00 1.1106525e+00 1.2665468e+00 1.6689743e+00 2.0995265e+00 1.7457596e+00 1.7532140e+00 2.1511385e+00 2.2712062e+00 1.3276804e+00 2.5485519e+00 3.4378533e-01 2.1870851e+00 1.4266198e+00 1.0379132e+00 2.3072128e+00 2.2736138e+00 1.6156775e+00 1.2095267e+00 8.3888121e-01 1.2277129e+00 1.6151153e+00 2.0528819e+00 1.8792214e+00 8.2624515e-01 1.7265353e+00 1.7004805e+00 2.3953564e+00 1.5733646e+00 1.4691764e+00 1.8497891e+00 2.3019759e+00 1.2238809e+00 1.4266198e+00 1.7962897e+00 2.1027465e+00 1.8635467e+00 1.9008621e+00 2.2439391e+00 1.3353353e+00 7.2526325e-01 2.1293320e+00 5.5492130e-01 1.2776560e+00 1.5193574e+00 6.2988288e-01 8.1130291e-01 8.6912228e-01 1.3752391e+00 1.6044563e+00 2.3474075e+00 9.1883539e-01 6.2024833e-01 6.4806901e-01 1.9000365e+00 1.3674559e+00 9.6664346e-01 8.1354181e-01 1.1751082e+00 1.2304904e+00 1.2256933e+00 5.7324170e-01 1.3628690e+00 1.4089364e+00 1.0866132e+00 4.8036801e-01 8.9971984e-01 1.3044654e+00 8.1130291e-01 1.3916739e+00 1.1500393e+00 9.6838716e-01 2.5251796e-01 5.5419992e-01 1.0573285e+00 1.0284501e+00 5.7324170e-01 7.1840099e-01 6.6317860e-01 1.1434428e+00 5.6769031e-01 9.7855477e-01 1.1106525e+00 8.2899253e-01 6.0670504e-01 6.2660376e-01 1.1449732e+00 3.2586371e-01 2.1845981e-01 6.0060595e-01 1.1833351e+00 2.0656129e-01 2.5251796e-01 5.1607523e-01 9.6324667e-01 5.9426792e-01 7.1799256e-01 1.0879524e+00 2.4372751e+00 7.0437330e-01 1.2331989e+00 1.7427900e+00 6.0611244e-01 5.1607523e-01 9.3615100e-01 1.6812503e+00 1.9411754e+00 2.5109747e+00 9.3801395e-01 7.7039952e-01 8.6513410e-01 2.2052183e+00 9.6324667e-01 8.9917007e-01 4.2667565e-01 1.3224963e+00 1.1912106e+00 1.3084046e+00 2.5651975e-01 1.3897316e+00 1.2541242e+00 1.1120775e+00 7.1504098e-01 9.1051084e-01 8.1521713e-01 3.6171588e-01 2.0209349e+00 1.2627078e+00 7.9878917e-01 2.1431239e+00 2.1198551e+00 1.5016009e+00 9.6141901e-01 6.2024833e-01 1.0083666e+00 1.5022608e+00 1.8803649e+00 1.7557336e+00 6.2482915e-01 1.6044563e+00 1.5582387e+00 2.2435182e+00 1.3836712e+00 1.3199714e+00 1.6568705e+00 2.1907335e+00 1.0796583e+00 1.2825987e+00 1.6205332e+00 1.9460721e+00 1.6995133e+00 1.7678302e+00 2.1198551e+00 9.1750357e-01 1.2756158e+00 1.4096146e-01 3.2352160e-01 7.1504098e-01 1.1242402e+00 1.4312787e+00 2.0223464e+00 7.3535471e-01 3.2586371e-01 7.3851529e-01 1.6386882e+00 9.4477932e-01 6.4755655e-01 3.7427929e-01 7.3805807e-01 8.6165877e-01 7.2852070e-01 5.0905001e-01 1.0922991e+00 1.0175773e+00 6.0900723e-01 2.1269358e-01 4.0176783e-01 8.2372435e-01 4.5470518e-01 5.5492130e-01 9.8495853e-01 9.0521488e-01 5.2942799e-01 6.3977563e-01 7.9878917e-01 1.2832075e+00 5.3022554e-01 8.3060013e-01 9.4500268e-01 1.0244319e+00 4.4651726e-01 4.0176783e-01 1.0230441e+00 3.4378533e-01 3.2586371e-01 6.1623531e-01 1.0330459e+00 2.5651975e-01 4.0000000e-01 5.3588338e-01 9.5676647e-01 5.3665999e-01 5.3665999e-01 9.0521488e-01 1.3865084e+00 1.3669552e+00 8.6012420e-01 2.8192292e-01 4.1586001e-01 8.4050231e-01 8.7383925e-01 1.1355826e+00 1.1712156e+00 6.2660376e-01 9.8985697e-01 8.5205778e-01 1.4909823e+00 6.3861009e-01 7.2526325e-01 9.4854455e-01 1.5124582e+00 5.6700421e-01 7.7919451e-01 8.9971984e-01 1.2483814e+00 9.4009473e-01 1.0879524e+00 1.4147273e+00 2.1269358e-01 8.1354181e-01 1.2441035e+00 1.5551238e+00 2.1137172e+00 8.2899253e-01 3.7427929e-01 8.2929029e-01 1.7587110e+00 9.6095130e-01 7.1799256e-01 2.4837156e-01 8.3280511e-01 9.3797093e-01 7.9016429e-01 4.4651726e-01 1.1833351e+00 1.0724413e+00 6.6932542e-01 3.2816937e-01 4.6472023e-01 8.0467258e-01 3.8776762e-01 7.3145860e-01 1.2564564e+00 1.5558094e+00 2.0983278e+00 7.5082357e-01 3.6171588e-01 7.6590510e-01 1.7862655e+00 8.4050231e-01 6.2024833e-01 1.2418578e-01 8.6137722e-01 8.9852394e-01 8.5462626e-01 3.8934542e-01 1.1192362e+00 1.0078327e+00 7.0386584e-01 5.0991930e-01 4.5470518e-01 6.6539428e-01 2.4837156e-01 8.5690100e-01 1.0344911e+00 1.6689743e+00 1.0000000e-01 6.8961791e-01 7.1799256e-01 1.3207609e+00 6.2024833e-01 3.7427929e-01 8.3888121e-01 5.3588338e-01 4.2288438e-01 6.4405773e-01 6.9369532e-01 5.3309112e-01 5.8914551e-01 4.6472023e-01 6.2538346e-01 4.1586001e-01 6.1623531e-01 6.4405773e-01 4.0176783e-01 1.0175773e+00 8.9303452e-01 1.0122141e+00 1.1161766e+00 7.7885297e-01 1.0755693e+00 8.1385214e-01 1.3792358e+00 5.8914551e-01 8.5462626e-01 8.7848692e-01 1.4517959e+00 7.3851529e-01 9.4854455e-01 8.6263408e-01 1.0941064e+00 8.3783744e-01 1.1172689e+00 1.3545005e+00 1.0391247e+00 1.0389435e+00 1.3163598e+00 1.3379696e+00 4.5470518e-01 1.1951875e+00 1.0632598e+00 1.6796759e+00 7.8197925e-01 8.3345577e-01 1.0540105e+00 1.7036156e+00 6.9167458e-01 8.8503502e-01 1.0279631e+00 1.3693737e+00 1.1192426e+00 1.3077572e+00 1.6183051e+00 1.6694974e+00 1.9094934e+00 1.9895190e+00 8.2384013e-01 1.6634400e+00 1.6218244e+00 2.2178691e+00 1.3008161e+00 1.3567326e+00 1.4994715e+00 2.3021295e+00 1.1763719e+00 1.3024224e+00 1.5535909e+00 2.0373882e+00 1.6756749e+00 1.7981158e+00 2.1739455e+00 7.6752131e-01 8.1354181e-01 1.3198846e+00 6.0611244e-01 4.4535192e-01 8.5335130e-01 5.3665999e-01 3.8776762e-01 6.3977563e-01 7.0429250e-01 5.2655962e-01 5.5492130e-01 4.5581864e-01 6.3861009e-01 4.2667565e-01 6.1151102e-01 6.6932542e-01 5.1691876e-01 1.5922648e+00 1.0054794e+00 4.8135521e-01 4.3456114e-01 7.6955924e-01 9.6664346e-01 8.9687438e-01 5.6700421e-01 1.0421979e+00 1.1001291e+00 8.2929029e-01 4.4535192e-01 5.1691876e-01 8.9712482e-01 4.5470518e-01 1.6914476e+00 1.1340084e+00 5.8914551e-01 8.5105559e-01 9.7548738e-01 1.0864449e+00 1.1160770e+00 6.3977563e-01 1.0720678e+00 1.2163831e+00 1.0047836e+00 6.9369532e-01 7.2343175e-01 1.0613462e+00 6.2407309e-01 1.4238090e+00 1.3511716e+00 1.9067300e+00 9.3824087e-01 1.0331736e+00 1.1327825e+00 1.9782093e+00 9.0454394e-01 1.0244319e+00 1.1833480e+00 1.5948732e+00 1.3360558e+00 1.5461469e+00 1.8900319e+00 6.2081167e-01 9.1750357e-01 6.4290921e-01 4.4417983e-01 7.0429250e-01 8.7229670e-01 5.3665999e-01 4.0438741e-01 5.6454040e-01 1.0054794e+00 5.7015910e-01 2.1269358e-01 7.5705927e-01 7.3496673e-01 5.2942799e-01 6.2024833e-01 6.6491075e-01 6.8801986e-01 6.1947990e-01 7.2172678e-01 5.5492130e-01 6.9006418e-01 3.2816937e-01 5.3665999e-01 5.6700421e-01 9.7779835e-01 1.0014633e+00 9.4854455e-01 3.8934542e-01 1.2342162e+00 1.1043332e+00 7.9580667e-01 5.3665999e-01 5.7257017e-01 7.2852070e-01 3.0275928e-01 3.4378533e-01 3.2352160e-01 1.1199472e+00 5.0991930e-01 4.6472023e-01 2.8507955e-01 7.7869083e-01 4.1586001e-01 7.1799256e-01 1.0132664e+00 5.0905001e-01 9.9519977e-01 3.0811765e-01 2.1269358e-01 4.0293660e-01 8.3060013e-01 5.0592043e-01 5.3665999e-01 9.3049742e-01 1.1263042e+00 8.0064372e-01 6.1623531e-01 2.1269358e-01 7.7588000e-01 4.4651726e-01 7.2783368e-01 1.0329901e+00 1.1697902e+00 1.0851476e+00 9.2859317e-01 5.0905001e-01 7.1504098e-01 7.7763126e-01 3.0546431e-01 2.5651975e-01 7.0437330e-01 1.0573285e+00 7.3145860e-01 6.9325418e-01 1.0901359e+00 5.3588338e-01 1.0175773e+00 6.4405773e-01 5.3665999e-01 1.0078327e+00 6.2407309e-01 3.2352160e-01 5.7257017e-01 8.5205778e-01 5.1691876e-01 9.4022486e-01 5.6769031e-01 4.8927739e-01 6.0611244e-01 6.0900723e-01 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-minkowski-3.2-ml.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-minkowski-3.2-ml.txt new file mode 100644 index 0000000000000000000000000000000000000000..daa81110a2be1a670f6163a8b255b2c6ecd5ccaa --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-minkowski-3.2-ml.txt @@ -0,0 +1 @@ + 2.0215050e+00 2.0988154e+00 1.8614681e+00 2.0510161e+00 1.9210911e+00 2.1323516e+00 1.9565454e+00 2.1029889e+00 1.9617871e+00 2.0544792e+00 2.0357408e+00 1.8811414e+00 2.0694693e+00 2.1245977e+00 2.0632165e+00 2.0452823e+00 2.0249330e+00 1.9635489e+00 2.0508580e+00 2.0838578e+00 1.9324052e+00 1.8224609e+00 1.9795343e+00 1.9536534e+00 1.9694910e+00 1.9075569e+00 1.9590397e+00 2.0022087e+00 1.8814000e+00 1.8884208e+00 1.9961121e+00 2.0215351e+00 1.7515769e+00 2.0756437e+00 2.0109476e+00 1.9234849e+00 1.9160076e+00 1.8550862e+00 1.7733640e+00 2.0071906e+00 2.0209542e+00 2.0616569e+00 2.0565503e+00 1.9083573e+00 2.2732431e+00 1.9975503e+00 1.9080072e+00 2.1437809e+00 2.1296295e+00 1.9739085e+00 1.9834166e+00 2.1078664e+00 2.2016840e+00 2.2080962e+00 1.7340579e+00 2.0549287e+00 1.7331748e+00 1.9559688e+00 2.0343364e+00 1.8736929e+00 1.9730416e+00 1.5308944e+00 1.8421831e+00 2.0174240e+00 2.0137378e+00 1.7956151e+00 1.9606596e+00 1.9074857e+00 2.0413879e+00 2.0070305e+00 1.9584677e+00 1.8977851e+00 1.9176239e+00 1.7067419e+00 1.9461927e+00 1.8431700e+00 1.8284576e+00 1.7778704e+00 1.8350329e+00 2.0175415e+00 1.7459063e+00 1.9242505e+00 1.8757370e+00 1.9312506e+00 2.0574808e+00 2.0894636e+00 1.9780203e+00 2.1374036e+00 1.8900436e+00 2.0273032e+00 2.0681953e+00 2.0234699e+00 2.0666449e+00 2.0663485e+00 1.9281402e+00 1.7846314e+00 2.0372479e+00 1.8831230e+00 2.0186015e+00 2.0193231e+00 2.2022665e+00 1.8145737e+00 2.0466545e+00 1.8092421e+00 1.9600687e+00 2.0322961e+00 1.9556364e+00 1.8266422e+00 1.9950345e+00 2.1038429e+00 2.1164145e+00 2.0188062e+00 1.8863331e+00 2.0006971e+00 1.9971068e+00 1.8771862e+00 2.1148855e+00 1.9570638e+00 1.9859615e+00 2.0030854e+00 2.0737344e+00 1.9739259e+00 1.9266524e+00 1.9200535e+00 2.1376689e+00 1.8944425e+00 1.9330553e+00 1.8561590e+00 1.9422954e+00 1.8874178e+00 1.8624808e+00 1.8265563e+00 1.8840519e+00 2.0515092e+00 2.0174226e+00 1.9771196e+00 2.0635988e+00 1.7334466e+00 1.9912604e+00 1.8915711e+00 1.8262636e+00 1.9369173e+00 1.9560446e+00 1.9549934e+00 1.9279230e+00 1.9021073e+00 2.0113391e+00 2.0305786e+00 1.8066806e+00 1.9656739e+00 2.1219217e+00 1.8820250e+00 1.8936826e+00 2.0565131e+00 1.9839441e+00 1.8553479e+00 1.9923760e+00 1.6393276e+00 1.9786440e+00 1.8274394e+00 1.9322611e+00 2.0404318e+00 1.9216532e+00 1.9361171e+00 1.8401373e+00 1.9908059e+00 1.9495117e+00 2.1975655e+00 1.8413913e+00 2.1528773e+00 1.8434374e+00 2.1668863e+00 2.0429273e+00 1.9980016e+00 1.9790129e+00 2.0264829e+00 2.1478843e+00 2.0899600e+00 2.0280670e+00 2.1210881e+00 1.9993891e+00 1.8646871e+00 1.9099983e+00 1.9263353e+00 2.0042495e+00 2.1365919e+00 2.1830279e+00 1.9631961e+00 2.0880004e+00 1.8348369e+00 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-minkowski-5.8-ml-iris.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-minkowski-5.8-ml-iris.txt new file mode 100644 index 0000000000000000000000000000000000000000..aa26b0439f568f97c95bee1b04204f24c9a1f3e0 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-minkowski-5.8-ml-iris.txt @@ -0,0 +1 @@ + 5.0042326e-01 4.1210927e-01 5.2133179e-01 1.1269424e-01 4.2362917e-01 5.0001522e-01 1.2085435e-01 7.4262850e-01 4.0127250e-01 3.0482299e-01 3.0482299e-01 5.0436965e-01 8.0923926e-01 7.1629168e-01 9.1424701e-01 4.1317535e-01 1.0000000e-01 6.0366256e-01 3.0017653e-01 3.3813251e-01 2.2573593e-01 5.2133179e-01 3.4080442e-01 5.0436965e-01 5.0043084e-01 2.2608083e-01 1.1269424e-01 1.1269424e-01 4.1315633e-01 4.1315633e-01 3.0490481e-01 6.0000952e-01 7.0462550e-01 4.0127250e-01 3.0482299e-01 4.0002221e-01 4.0127250e-01 7.1621748e-01 1.1269424e-01 1.2085435e-01 1.2036864e+00 7.0088477e-01 4.0125062e-01 5.0476836e-01 5.0436965e-01 3.0474106e-01 5.0436235e-01 2.2573593e-01 2.0061436e-01 3.3243227e+00 3.1068812e+00 3.5145413e+00 2.6080595e+00 3.2075731e+00 3.1014454e+00 3.3055260e+00 1.9156198e+00 3.2079238e+00 2.5066441e+00 2.1498493e+00 2.8059664e+00 2.6093989e+00 3.3021953e+00 2.2070266e+00 3.0158454e+00 3.1034764e+00 2.7009878e+00 3.1081779e+00 2.5032992e+00 3.4074959e+00 2.6050088e+00 3.5035589e+00 3.3011884e+00 2.9065890e+00 3.0117336e+00 3.4118782e+00 3.6094426e+00 3.1038958e+00 2.1042326e+00 2.4058620e+00 2.3063407e+00 2.5029614e+00 3.7025335e+00 3.1034636e+00 3.1057006e+00 3.3110189e+00 3.0065909e+00 2.7025941e+00 2.6047974e+00 3.0013665e+00 3.2025221e+00 2.6029242e+00 1.9242109e+00 2.8024935e+00 2.8013151e+00 2.8022622e+00 2.9036582e+00 1.6267693e+00 2.7028014e+00 4.6144526e+00 3.7071079e+00 4.5121787e+00 4.2031939e+00 4.4087839e+00 5.2153194e+00 3.1086291e+00 4.9093646e+00 4.4044245e+00 4.7202040e+00 3.7119486e+00 3.9066365e+00 4.1123628e+00 3.6114402e+00 3.7307413e+00 3.9194642e+00 4.1043951e+00 5.3177489e+00 5.5157728e+00 3.6035661e+00 4.3162097e+00 3.5127031e+00 5.3163123e+00 3.5077296e+00 4.3088507e+00 4.6100803e+00 3.4082578e+00 3.5068380e+00 4.2080636e+00 4.4113183e+00 4.7149608e+00 5.0316727e+00 4.2105572e+00 3.7024462e+00 4.2007769e+00 4.7331529e+00 4.2173557e+00 4.1039096e+00 3.4076329e+00 4.0157626e+00 4.2194897e+00 3.7329396e+00 3.7071079e+00 4.5119962e+00 4.3218071e+00 3.8249612e+00 3.6093673e+00 3.8105293e+00 4.0166459e+00 3.7050109e+00 2.2573593e-01 3.0017653e-01 6.0000317e-01 9.0534502e-01 4.1210927e-01 4.0004442e-01 5.0000761e-01 1.2085435e-01 7.1621748e-01 4.0125062e-01 1.1269424e-01 6.0184622e-01 1.0776294e+00 1.4092540e+00 9.0508756e-01 5.0043084e-01 9.0181717e-01 8.0004602e-01 5.2491131e-01 7.0017011e-01 6.1119267e-01 3.6452132e-01 5.2133179e-01 2.0061436e-01 4.0246123e-01 5.0436965e-01 4.1209001e-01 2.4170870e-01 2.0121983e-01 5.2167829e-01 1.1001015e+00 1.2036862e+00 1.2085435e-01 2.2573593e-01 6.3164977e-01 1.2085435e-01 5.0000761e-01 4.0125062e-01 5.0002283e-01 7.0462844e-01 5.0043084e-01 5.2167829e-01 8.0888055e-01 1.1269424e-01 8.0008884e-01 3.0474106e-01 7.0462697e-01 3.0008832e-01 3.3416860e+00 3.1112912e+00 3.5249966e+00 2.6033557e+00 3.2127499e+00 3.1015178e+00 3.3078313e+00 1.9025708e+00 3.2150318e+00 2.5060738e+00 2.1061951e+00 2.8068283e+00 2.6040016e+00 3.3032134e+00 2.2072454e+00 3.0286102e+00 3.1035443e+00 2.7011973e+00 3.1070853e+00 2.5014549e+00 3.4078435e+00 2.6080511e+00 3.5048916e+00 3.3021665e+00 2.9125999e+00 3.0213627e+00 3.4211337e+00 3.6148618e+00 3.1047537e+00 2.1027003e+00 2.4016639e+00 2.3011929e+00 2.5032633e+00 3.7028303e+00 3.1034629e+00 3.1065984e+00 3.3192072e+00 3.0078209e+00 2.7027260e+00 2.6031664e+00 3.0009332e+00 3.2037232e+00 2.6027120e+00 1.9031578e+00 2.8022915e+00 2.8015662e+00 2.8024715e+00 2.9065359e+00 1.6099792e+00 2.7029416e+00 4.6149181e+00 3.7071538e+00 4.5172866e+00 4.2039132e+00 4.4099272e+00 5.2224057e+00 3.1078968e+00 4.9146298e+00 4.4063795e+00 4.7253524e+00 3.7145622e+00 3.9080413e+00 4.1161770e+00 3.6111646e+00 3.7308314e+00 3.9209137e+00 4.1060063e+00 5.3254977e+00 5.5222404e+00 3.6024247e+00 4.3201293e+00 3.5126957e+00 5.3240486e+00 3.5093499e+00 4.3111749e+00 4.6158382e+00 3.4095576e+00 3.5076152e+00 4.2090727e+00 4.4184242e+00 4.7227808e+00 5.0458491e+00 4.2115634e+00 3.7037441e+00 4.2010125e+00 4.7466313e+00 4.2180733e+00 4.1050714e+00 3.4081972e+00 4.0212972e+00 4.2220584e+00 3.7407842e+00 3.7071538e+00 4.5144444e+00 4.3240980e+00 3.8290678e+00 3.6105228e+00 3.8128297e+00 4.0172657e+00 3.7052380e+00 2.0121983e-01 4.1210927e-01 7.9153339e-01 2.0181667e-01 3.0915245e-01 3.3813251e-01 2.2608083e-01 7.1629168e-01 3.0482299e-01 2.0181667e-01 4.0246123e-01 1.1281267e+00 1.2633045e+00 7.8890721e-01 4.1212852e-01 1.0095370e+00 6.0964891e-01 7.0470720e-01 5.2201750e-01 4.1210927e-01 4.5784410e-01 6.0017982e-01 3.4080442e-01 3.4342562e-01 5.0476836e-01 5.0043084e-01 3.0000000e-01 3.0017653e-01 7.0025283e-01 9.0508756e-01 1.0426513e+00 2.2608083e-01 3.0008832e-01 8.0046605e-01 2.2608083e-01 3.0474106e-01 4.0243965e-01 3.3813251e-01 9.0002570e-01 3.0000000e-01 4.3213914e-01 6.8170466e-01 2.0181667e-01 6.1119267e-01 1.1269424e-01 6.3178534e-01 3.0017653e-01 3.4595765e+00 3.2168311e+00 3.6364650e+00 2.7037323e+00 3.3192099e+00 3.2017763e+00 3.4107328e+00 2.0033798e+00 3.3237063e+00 2.6050967e+00 2.2121910e+00 2.9077087e+00 2.7085154e+00 3.4047917e+00 2.3071665e+00 3.1428042e+00 3.2033135e+00 2.8024935e+00 3.2103481e+00 2.6021247e+00 3.5076152e+00 2.7127272e+00 3.6073242e+00 3.4038884e+00 3.0203881e+00 3.1325879e+00 3.5317021e+00 3.7210979e+00 3.2059139e+00 2.2051638e+00 2.5023084e+00 2.4021168e+00 2.6048201e+00 3.8033004e+00 3.2030448e+00 3.2074921e+00 3.4286399e+00 3.1131211e+00 2.8028008e+00 2.7031257e+00 3.1010004e+00 3.3055260e+00 2.7040740e+00 2.0050309e+00 2.9023862e+00 2.9020767e+00 2.9028421e+00 3.0107283e+00 1.7089863e+00 2.8033666e+00 4.7142986e+00 3.8066401e+00 4.6226512e+00 4.3047830e+00 4.5107876e+00 5.3296471e+00 3.2068572e+00 5.0203871e+00 4.5089338e+00 4.8299744e+00 3.8170042e+00 4.0095939e+00 4.2200398e+00 3.7100654e+00 3.8275330e+00 4.0209836e+00 4.2079639e+00 5.4332277e+00 5.6287689e+00 3.7032748e+00 4.4237036e+00 3.6112573e+00 5.4319232e+00 3.6111754e+00 4.4135512e+00 4.7221364e+00 3.5107924e+00 3.6081749e+00 4.3098514e+00 4.5261773e+00 4.8309399e+00 5.1593152e+00 4.3120751e+00 3.8056232e+00 4.3015640e+00 4.8592534e+00 4.3174320e+00 4.2064763e+00 3.5083248e+00 4.1268500e+00 4.3236383e+00 3.8471097e+00 3.8066401e+00 4.6166518e+00 4.4251081e+00 3.9318948e+00 3.7118930e+00 3.9150333e+00 4.1165034e+00 3.8051417e+00 5.2133179e-01 9.0160400e-01 3.0017653e-01 4.1209001e-01 2.2573593e-01 3.0008832e-01 8.2418002e-01 3.0482299e-01 2.0181667e-01 4.1212852e-01 1.2363278e+00 1.3741498e+00 9.0160400e-01 5.2133802e-01 1.1133986e+00 7.1621748e-01 8.0051036e-01 6.3178534e-01 5.6347121e-01 5.0517282e-01 4.1315633e-01 4.0004442e-01 4.1317535e-01 6.0948212e-01 6.0184622e-01 1.2085435e-01 2.0061436e-01 8.0051036e-01 1.0087250e+00 1.1527669e+00 3.0008832e-01 4.1210927e-01 9.0142636e-01 3.0008832e-01 2.2573593e-01 5.0436235e-01 4.5148429e-01 8.0004602e-01 2.2573593e-01 4.8342635e-01 7.2044167e-01 2.0181667e-01 7.1621748e-01 1.1269424e-01 7.4262850e-01 4.0125062e-01 3.2983364e+00 3.0300451e+00 3.4603347e+00 2.5053901e+00 3.1338090e+00 3.0030658e+00 3.2183845e+00 1.8040969e+00 3.1419971e+00 2.4075162e+00 2.0123013e+00 2.7132680e+00 2.5163999e+00 3.2086215e+00 2.1132077e+00 2.9750754e+00 3.0049127e+00 2.6055197e+00 3.0177719e+00 2.4040962e+00 3.3110162e+00 2.5253371e+00 3.4126529e+00 3.2074182e+00 2.8380954e+00 2.9580787e+00 3.3536443e+00 3.5347730e+00 3.0101869e+00 2.0123796e+00 2.3038195e+00 2.2036797e+00 2.4099203e+00 3.6051707e+00 3.0042758e+00 3.0123228e+00 3.2490712e+00 2.9241808e+00 2.6047889e+00 2.5049231e+00 2.9016211e+00 3.1100277e+00 2.5081992e+00 1.8056342e+00 2.7040060e+00 2.7039988e+00 2.7050721e+00 2.8205713e+00 1.5147271e+00 2.6060742e+00 4.5183778e+00 3.6090052e+00 4.4337691e+00 4.1072664e+00 4.3151164e+00 5.1425125e+00 3.0092613e+00 4.8303615e+00 4.3139066e+00 4.6422789e+00 3.6259317e+00 3.8146285e+00 4.0301568e+00 3.5133848e+00 3.6358680e+00 3.8290678e+00 4.0124919e+00 5.2471177e+00 5.4403962e+00 3.5051114e+00 4.2343452e+00 3.4149831e+00 5.2455706e+00 3.4177035e+00 4.2200398e+00 4.5335328e+00 3.3168776e+00 3.4123846e+00 4.1140176e+00 4.3402553e+00 4.6459028e+00 4.9843016e+00 4.1167964e+00 3.6096226e+00 4.1026403e+00 4.6849407e+00 4.1230798e+00 4.0100505e+00 3.3123688e+00 3.9407837e+00 4.1330547e+00 3.6700537e+00 3.6090052e+00 4.4237036e+00 4.2343452e+00 3.7463488e+00 3.5181052e+00 3.7227931e+00 3.9220791e+00 3.6072781e+00 4.2362917e-01 4.0125062e-01 2.0061436e-01 7.4262850e-01 5.0002283e-01 4.0004442e-01 2.4170870e-01 6.0017982e-01 7.4329527e-01 8.0250123e-01 8.5406674e-01 4.1317535e-01 1.2085435e-01 7.0096858e-01 2.0181667e-01 4.1315633e-01 2.0181667e-01 4.5077696e-01 3.6259865e-01 5.0084481e-01 6.0017665e-01 2.4170870e-01 2.0121983e-01 2.2538848e-01 4.1315633e-01 5.0084481e-01 4.0246123e-01 5.0043842e-01 6.3164729e-01 5.0002283e-01 4.0122873e-01 5.0001522e-01 5.0002283e-01 6.7616723e-01 2.0121983e-01 1.2085435e-01 1.3008771e+00 6.0948506e-01 4.0125062e-01 5.0085236e-01 6.0017982e-01 2.2573593e-01 4.5077696e-01 3.0017653e-01 3.0000000e-01 3.3320240e+00 3.1087192e+00 3.5191371e+00 2.6110181e+00 3.2098845e+00 3.1016129e+00 3.3064697e+00 1.9242109e+00 3.2110200e+00 2.5072065e+00 2.1702438e+00 2.8063347e+00 2.6144115e+00 3.3026483e+00 2.2074446e+00 3.0213781e+00 3.1035271e+00 2.7015967e+00 3.1108570e+00 2.5049231e+00 3.4076266e+00 2.6065485e+00 3.5045818e+00 3.3016829e+00 2.9091905e+00 3.0158857e+00 3.4160038e+00 3.6117923e+00 3.1042949e+00 2.1068047e+00 2.4087956e+00 2.3099309e+00 2.5038387e+00 3.7027671e+00 3.1034919e+00 3.1060428e+00 3.3145595e+00 3.0095593e+00 2.7026925e+00 2.6061038e+00 3.0017811e+00 3.2030205e+00 2.6039803e+00 1.9366876e+00 2.8028640e+00 2.8014482e+00 2.8024453e+00 2.9049136e+00 1.6388635e+00 2.7031257e+00 4.6146430e+00 3.7072412e+00 4.5144508e+00 4.2035048e+00 4.4092709e+00 5.2185448e+00 3.1091788e+00 4.9117351e+00 4.4054277e+00 4.7224997e+00 3.7130507e+00 3.9073151e+00 4.1140274e+00 3.6117351e+00 3.7308330e+00 3.9200674e+00 4.1050815e+00 5.3212796e+00 5.5187578e+00 3.6046347e+00 4.3179262e+00 3.5127783e+00 5.3198559e+00 3.5085510e+00 4.3098508e+00 4.6126513e+00 3.4088749e+00 3.5071604e+00 4.2085176e+00 4.4144980e+00 4.7185095e+00 5.0381903e+00 4.2110099e+00 3.7030413e+00 4.2009868e+00 4.7393218e+00 4.2176488e+00 4.1043951e+00 3.4078683e+00 4.0181902e+00 4.2205976e+00 3.7363838e+00 3.7072412e+00 4.5130595e+00 4.3227928e+00 3.8267408e+00 3.6102542e+00 3.8115096e+00 4.0168944e+00 3.7051079e+00 8.0923926e-01 5.2201750e-01 1.1270411e+00 8.0928056e-01 2.4170870e-01 6.3178782e-01 9.1471442e-01 1.1573074e+00 5.2167829e-01 5.0476836e-01 4.0000000e-01 4.2270142e-01 3.0017653e-01 3.0490481e-01 5.0042326e-01 3.0915245e-01 8.5440680e-01 6.0184622e-01 6.3192325e-01 9.0142681e-01 5.2133179e-01 4.0363334e-01 5.0517282e-01 7.8890806e-01 8.2421923e-01 5.0042326e-01 3.1328089e-01 3.4085233e-01 8.0928056e-01 7.2044167e-01 4.5148429e-01 8.0928056e-01 1.0782211e+00 5.0517282e-01 4.8342635e-01 1.6097492e+00 1.0215068e+00 4.5148429e-01 3.0482299e-01 9.1446938e-01 3.0490481e-01 8.5440680e-01 2.4195741e-01 6.1135434e-01 3.0143288e+00 2.8035152e+00 3.2080663e+00 2.3476141e+00 2.9053991e+00 2.8028019e+00 3.0030626e+00 1.7519158e+00 2.9045816e+00 2.2149484e+00 2.0887699e+00 2.5048522e+00 2.3645147e+00 3.0018766e+00 1.9120303e+00 2.7085154e+00 2.8028008e+00 2.4075162e+00 2.8284908e+00 2.2272457e+00 3.1054022e+00 2.3075573e+00 3.2060163e+00 3.0018874e+00 2.6044486e+00 2.7064438e+00 3.1073418e+00 3.3054063e+00 2.8034238e+00 1.8447840e+00 2.1492024e+00 2.0607272e+00 2.2122063e+00 3.4028104e+00 2.8028007e+00 2.8036182e+00 3.0057998e+00 2.7234787e+00 2.4027927e+00 2.3234132e+00 2.7070699e+00 2.9017335e+00 2.3151346e+00 1.8036834e+00 2.5072065e+00 2.5017313e+00 2.5032633e+00 2.6031823e+00 1.5292174e+00 2.4058519e+00 4.3116266e+00 3.4064593e+00 4.2076930e+00 3.9021503e+00 4.1063936e+00 4.9099401e+00 2.8141516e+00 4.6055969e+00 4.1036742e+00 4.4145324e+00 3.4082578e+00 3.6052799e+00 3.8082804e+00 3.3123693e+00 3.4273179e+00 3.6154977e+00 3.8026444e+00 5.0117750e+00 5.2107474e+00 3.3130198e+00 4.0114753e+00 3.2109395e+00 5.0107787e+00 3.2067490e+00 4.0058313e+00 4.3058539e+00 3.1067996e+00 3.2049797e+00 3.9061098e+00 4.1066170e+00 4.4095056e+00 4.7221364e+00 3.9082316e+00 3.4019453e+00 3.9014304e+00 4.4232188e+00 3.9139973e+00 3.8023591e+00 3.1057392e+00 3.7104219e+00 3.9150553e+00 3.4248402e+00 3.4064593e+00 4.2084919e+00 4.0172759e+00 3.5193527e+00 3.3100431e+00 3.5073655e+00 3.7133435e+00 3.4036743e+00 4.0004442e-01 5.0043084e-01 3.4085233e-01 8.0046764e-01 2.2573593e-01 4.0243965e-01 4.2362917e-01 1.2036925e+00 1.1896595e+00 8.0879776e-01 5.0000761e-01 1.1006371e+00 5.2133179e-01 8.0046685e-01 5.0437695e-01 4.0125062e-01 5.0477564e-01 5.0043084e-01 4.5148429e-01 4.0125062e-01 6.0000952e-01 6.0000317e-01 2.2608083e-01 3.0922892e-01 8.0000160e-01 7.4269314e-01 9.6572569e-01 3.4085233e-01 4.0246123e-01 9.0000136e-01 3.4085233e-01 4.0127250e-01 5.0001522e-01 4.0004442e-01 1.1000003e+00 2.2608083e-01 4.1317535e-01 5.7609230e-01 4.0122873e-01 5.2167829e-01 2.0061436e-01 7.0088627e-01 4.0004442e-01 3.3852404e+00 3.1245391e+00 3.5521657e+00 2.6057331e+00 3.2281303e+00 3.1021033e+00 3.3145497e+00 1.9088256e+00 3.2358110e+00 2.5040476e+00 2.1337832e+00 2.8091158e+00 2.6173653e+00 3.3068237e+00 2.2078368e+00 3.0635687e+00 3.1029264e+00 2.7045714e+00 3.1156892e+00 2.5038387e+00 3.4072735e+00 2.6199287e+00 3.5105217e+00 3.3061800e+00 2.9316687e+00 3.0488379e+00 3.4462681e+00 3.6292576e+00 3.1074604e+00 2.1103491e+00 2.4046650e+00 2.3052527e+00 2.5074705e+00 3.7037846e+00 3.1023805e+00 3.1087156e+00 3.3416864e+00 3.0212423e+00 2.7029308e+00 2.6036513e+00 3.0012006e+00 3.2078939e+00 2.6064541e+00 1.9145304e+00 2.8026114e+00 2.8028068e+00 2.8033825e+00 2.9167099e+00 1.6147493e+00 2.7040740e+00 4.6133719e+00 3.7058811e+00 4.5290217e+00 4.2056470e+00 4.4115634e+00 5.2381327e+00 3.1057013e+00 4.9271590e+00 4.4118721e+00 4.7354168e+00 3.7201124e+00 3.9113698e+00 4.1247181e+00 3.6087856e+00 3.7244383e+00 3.9212835e+00 4.1101783e+00 5.3422962e+00 5.5362181e+00 3.6046999e+00 4.3279835e+00 3.5095358e+00 5.3412086e+00 3.5135120e+00 4.3162096e+00 4.6297141e+00 3.4124092e+00 3.5088081e+00 4.2105763e+00 4.4358170e+00 4.7408876e+00 5.0762364e+00 4.2125085e+00 3.7079173e+00 4.2021973e+00 4.7752666e+00 4.2166536e+00 4.1080028e+00 3.4084548e+00 4.0338654e+00 4.2256165e+00 3.7563734e+00 3.7058811e+00 4.5190617e+00 4.3264209e+00 3.8360186e+00 3.6136974e+00 3.8177300e+00 4.0156240e+00 3.7048582e+00 6.3164977e-01 3.0017653e-01 4.1209001e-01 2.0061436e-01 4.0127250e-01 7.0911112e-01 8.2458409e-01 1.0207396e+00 5.2201750e-01 1.2699992e-01 7.0470867e-01 4.0004442e-01 4.0122873e-01 3.0482299e-01 5.2167208e-01 3.0490481e-01 4.0122873e-01 4.0002221e-01 2.0061436e-01 2.0061436e-01 2.0061436e-01 3.0482299e-01 3.0482299e-01 4.0122873e-01 7.0008584e-01 8.0879701e-01 3.0017653e-01 3.0474106e-01 5.0043084e-01 3.0017653e-01 6.0964597e-01 1.0000000e-01 2.0121983e-01 1.1019599e+00 6.0035305e-01 4.0004442e-01 4.5148429e-01 4.0127250e-01 4.0004442e-01 4.0125062e-01 3.3808272e-01 1.1269424e-01 3.2369541e+00 3.0101869e+00 3.4219340e+00 2.5073576e+00 3.1113295e+00 3.0016913e+00 3.2074921e+00 1.8128536e+00 3.1127326e+00 2.4076937e+00 2.0429861e+00 2.7074657e+00 2.5087337e+00 3.2029987e+00 2.1087640e+00 2.9250474e+00 3.0040848e+00 2.6011837e+00 3.0090716e+00 2.4029250e+00 3.3087901e+00 2.5074281e+00 3.4046875e+00 3.2018065e+00 2.8107271e+00 2.9185950e+00 3.3183094e+00 3.5134617e+00 3.0049285e+00 2.0041542e+00 2.3049133e+00 2.2050331e+00 2.4035997e+00 3.6030023e+00 3.0040438e+00 3.0070658e+00 3.2168317e+00 2.9083216e+00 2.6031436e+00 2.5048522e+00 2.9013423e+00 3.1034810e+00 2.5032729e+00 1.8201043e+00 2.7028014e+00 2.7016556e+00 2.7027522e+00 2.8056775e+00 1.5256523e+00 2.6033557e+00 4.5162553e+00 3.6081006e+00 4.4160732e+00 4.1039121e+00 4.3103378e+00 5.1203327e+00 3.0096880e+00 4.8129366e+00 4.3058720e+00 4.6249088e+00 3.6148619e+00 3.8081633e+00 4.0157626e+00 3.5129206e+00 3.6349703e+00 3.8226858e+00 4.0057080e+00 5.2232912e+00 5.4204287e+00 3.5035589e+00 4.2200398e+00 3.4145570e+00 5.2217206e+00 3.4096180e+00 4.2110197e+00 4.5140458e+00 3.3101076e+00 3.4081996e+00 4.1095117e+00 4.3161641e+00 4.6204721e+00 4.9419857e+00 4.1123051e+00 3.6033860e+00 4.1009647e+00 4.6434791e+00 4.1197833e+00 4.0049425e+00 3.3090452e+00 3.9205015e+00 4.1230798e+00 3.6413278e+00 3.6081006e+00 4.4145323e+00 4.2254713e+00 3.7302938e+00 3.5112285e+00 3.7130507e+00 3.9190472e+00 3.6058055e+00 5.0043842e-01 1.0426513e+00 5.2167208e-01 4.0004442e-01 3.0026460e-01 1.4542931e+00 1.5965783e+00 1.1269511e+00 7.4262964e-01 1.3253871e+00 9.3306807e-01 1.0032293e+00 8.5406674e-01 7.0470720e-01 7.0633229e-01 5.7608844e-01 6.0017982e-01 6.3192325e-01 8.2418071e-01 8.0879625e-01 3.4080442e-01 4.0243965e-01 1.0030871e+00 1.2189645e+00 1.3741465e+00 5.0043842e-01 6.0201716e-01 1.1055705e+00 5.0043842e-01 1.1269424e-01 7.1621748e-01 6.7616902e-01 6.0000952e-01 3.0008832e-01 6.8170466e-01 9.3735629e-01 4.0004442e-01 9.3308853e-01 3.0474106e-01 9.6572569e-01 6.0948212e-01 3.4311880e+00 3.1440065e+00 3.5828092e+00 2.6061623e+00 3.2490712e+00 3.1047537e+00 3.3265679e+00 1.9024467e+00 3.2610547e+00 2.5066443e+00 2.1042326e+00 2.8182771e+00 2.6268573e+00 3.3136174e+00 2.2177383e+00 3.1042292e+00 3.1056084e+00 2.7106185e+00 3.1258664e+00 2.5072166e+00 3.4123850e+00 2.6397031e+00 3.5191318e+00 3.3125861e+00 2.9569988e+00 3.0825000e+00 3.4750557e+00 3.6484459e+00 3.1148203e+00 2.1231535e+00 2.4058952e+00 2.3063814e+00 2.5167763e+00 3.7071732e+00 3.1042001e+00 3.1166462e+00 3.3690976e+00 3.0370401e+00 2.7067267e+00 2.6060811e+00 3.0024163e+00 3.2157547e+00 2.6139440e+00 1.9029771e+00 2.8056558e+00 2.8068283e+00 2.8077255e+00 2.9323793e+00 1.6119586e+00 2.7091848e+00 4.6187512e+00 3.7092298e+00 4.5442576e+00 4.2099019e+00 4.4180513e+00 5.2548586e+00 3.1079005e+00 4.9407795e+00 4.4195588e+00 4.7516511e+00 3.7329384e+00 3.9191954e+00 4.1389224e+00 3.6127211e+00 3.7328453e+00 3.9318950e+00 4.1174259e+00 5.3601143e+00 5.5513974e+00 3.6073242e+00 4.3425018e+00 3.5138357e+00 5.3586950e+00 3.5235095e+00 4.3257995e+00 4.6452056e+00 3.4217238e+00 3.5154314e+00 4.2169032e+00 4.4544908e+00 4.7602896e+00 5.1057502e+00 4.2193718e+00 3.7147036e+00 4.2043114e+00 4.8058872e+00 4.2239687e+00 4.1138950e+00 3.4146523e+00 4.0526593e+00 4.2382079e+00 3.7847403e+00 3.7092298e+00 4.5291248e+00 4.3385161e+00 3.8547029e+00 3.6228903e+00 3.8290678e+00 4.0228342e+00 3.7082809e+00 6.3164977e-01 3.0026460e-01 1.2085435e-01 6.0948506e-01 1.0143978e+00 1.3131369e+00 8.0928056e-01 4.0246123e-01 8.5409862e-01 7.0016860e-01 5.0477564e-01 6.0201716e-01 5.6595908e-01 4.0363334e-01 4.1212852e-01 1.2699992e-01 3.3818226e-01 4.1210927e-01 3.3818226e-01 2.0181667e-01 1.2085435e-01 5.0855077e-01 1.0001598e+00 1.1055707e+00 0.0000000e+00 3.0026460e-01 6.0964891e-01 0.0000000e+00 5.0043842e-01 3.0482299e-01 4.0246123e-01 8.0254500e-01 5.0043842e-01 5.2133802e-01 7.0556260e-01 2.0181667e-01 7.0008735e-01 3.0026460e-01 6.0948506e-01 2.0181667e-01 3.2490712e+00 3.0153168e+00 3.4297841e+00 2.5067523e+00 3.1166337e+00 3.0027816e+00 3.2112793e+00 1.8068048e+00 3.1183051e+00 2.4116924e+00 2.0138832e+00 2.7116615e+00 2.5059537e+00 3.2048192e+00 2.1144760e+00 2.9351753e+00 3.0063019e+00 2.6019122e+00 3.0106587e+00 2.4030297e+00 3.3125861e+00 2.5120719e+00 3.4068163e+00 3.2029877e+00 2.8162444e+00 2.9267417e+00 3.3252407e+00 3.5189464e+00 3.0077107e+00 2.0051350e+00 2.3037132e+00 2.2028146e+00 2.4058620e+00 3.6044981e+00 3.0062070e+00 3.0107283e+00 3.2237456e+00 2.9105093e+00 2.6052541e+00 2.5062865e+00 2.9018772e+00 3.1056084e+00 2.5048522e+00 1.8082911e+00 2.7043948e+00 2.7029415e+00 2.7046027e+00 2.8091099e+00 1.5248852e+00 2.6055127e+00 4.5209020e+00 3.6112573e+00 4.4212031e+00 4.1056541e+00 4.3138986e+00 5.1255338e+00 3.0133997e+00 4.8167235e+00 4.3081273e+00 4.6319211e+00 3.6205854e+00 3.8114965e+00 4.0212972e+00 3.5173798e+00 3.6449970e+00 3.8299342e+00 4.0081754e+00 5.2290121e+00 5.4254411e+00 3.5039202e+00 4.2264145e+00 3.4198378e+00 5.2270034e+00 3.4138008e+00 4.2149806e+00 4.5183778e+00 3.3145502e+00 3.4118179e+00 4.1129687e+00 4.3210760e+00 4.6261633e+00 4.9512603e+00 4.1165035e+00 3.6051692e+00 4.1014742e+00 4.6540056e+00 4.1257291e+00 4.0071257e+00 3.3129914e+00 3.9274863e+00 4.1301604e+00 3.6542046e+00 3.6112573e+00 4.4192311e+00 4.2328883e+00 3.7399948e+00 3.5155767e+00 3.7180846e+00 3.9250546e+00 3.6083191e+00 6.0184622e-01 7.4263078e-01 1.1138955e+00 4.2268438e-01 7.0096708e-01 2.4170870e-01 3.0490481e-01 3.0490481e-01 3.0017653e-01 3.0474106e-01 3.0474106e-01 8.0879701e-01 4.2362917e-01 6.1119267e-01 7.0462697e-01 4.1317535e-01 2.2538848e-01 3.0482299e-01 7.1621748e-01 6.7616723e-01 3.0474106e-01 4.0125062e-01 5.0001522e-01 6.3164977e-01 5.2491131e-01 2.2573593e-01 6.3164977e-01 1.0207396e+00 3.3808272e-01 4.0246123e-01 1.4180463e+00 1.0030868e+00 4.5148429e-01 4.1317535e-01 7.4263078e-01 3.0017653e-01 8.0879701e-01 1.0000000e-01 4.5078948e-01 3.2116783e+00 3.0049285e+00 3.4072983e+00 2.5182898e+00 3.1051604e+00 3.0020136e+00 3.2049016e+00 1.8469618e+00 3.1036832e+00 2.4099081e+00 2.1180493e+00 2.7068820e+00 2.5224740e+00 3.2021231e+00 2.1097449e+00 2.9077617e+00 3.0041462e+00 2.6022422e+00 3.0134290e+00 2.4087504e+00 3.3085101e+00 2.5050799e+00 3.4038679e+00 3.2010814e+00 2.8036959e+00 2.9060895e+00 3.3058271e+00 3.5063866e+00 3.0043212e+00 2.0122773e+00 2.3159426e+00 2.2186306e+00 2.4051454e+00 3.6029749e+00 3.0041461e+00 3.0062373e+00 3.2059465e+00 2.9096170e+00 2.6032656e+00 2.5097004e+00 2.9028411e+00 3.1023606e+00 2.5057847e+00 1.8685354e+00 2.7039990e+00 2.7016498e+00 2.7029428e+00 2.8028074e+00 1.5747520e+00 2.6039937e+00 4.5157550e+00 3.6083209e+00 4.4088451e+00 4.1031691e+00 4.3089952e+00 5.1095334e+00 3.0117336e+00 4.8052574e+00 4.3035619e+00 4.6175091e+00 3.6116958e+00 3.8067089e+00 4.0107159e+00 3.5138361e+00 3.6350483e+00 3.8210210e+00 4.0037985e+00 5.2113565e+00 5.4105254e+00 3.5063553e+00 4.2147222e+00 3.4147657e+00 5.2097995e+00 3.4081036e+00 4.2080425e+00 4.5057296e+00 3.3089414e+00 3.4074852e+00 4.1084282e+00 4.3058539e+00 4.6088153e+00 4.9193995e+00 4.1112251e+00 3.6020843e+00 4.1009356e+00 4.6223848e+00 4.1190046e+00 4.0036188e+00 3.3085886e+00 3.9129256e+00 4.1197933e+00 3.6305006e+00 3.6083209e+00 4.4113183e+00 4.2225427e+00 3.7249938e+00 3.5105217e+00 3.7103007e+00 3.9184088e+00 3.6056580e+00 4.0125062e-01 5.7609230e-01 1.0095367e+00 1.0776296e+00 6.3322667e-01 3.0490481e-01 9.0140221e-01 4.1212852e-01 6.0000317e-01 3.4085233e-01 6.0035305e-01 3.3818226e-01 3.0000000e-01 4.0122873e-01 2.2538848e-01 4.0004442e-01 4.0122873e-01 2.0061436e-01 3.0000000e-01 6.0017982e-01 7.0462844e-01 8.5406616e-01 3.0026460e-01 4.0243965e-01 7.0088477e-01 3.0026460e-01 4.5783248e-01 3.0008832e-01 3.0490481e-01 1.1002025e+00 4.1315633e-01 4.0125062e-01 4.2362917e-01 4.0125062e-01 4.1209001e-01 2.4170870e-01 5.0436965e-01 2.2573593e-01 3.1712557e+00 2.9203034e+00 3.3425817e+00 2.4092081e+00 3.0228582e+00 2.9024211e+00 3.1131137e+00 1.7168003e+00 3.0276611e+00 2.3094323e+00 1.9540727e+00 2.6109956e+00 2.4153242e+00 3.1056218e+00 2.0123796e+00 2.8520945e+00 2.9050328e+00 2.5029614e+00 2.9148948e+00 2.3042831e+00 3.2109395e+00 2.4161682e+00 3.3086859e+00 3.1042389e+00 2.7244207e+00 2.8394157e+00 3.2369857e+00 3.4247142e+00 2.9077271e+00 1.9085444e+00 2.2064916e+00 2.1068047e+00 2.3066817e+00 3.5042241e+00 2.9048033e+00 2.9102290e+00 3.1338090e+00 2.8169587e+00 2.5042601e+00 2.4061715e+00 2.8017212e+00 3.0065627e+00 2.4058322e+00 1.7261843e+00 2.6037439e+00 2.6027120e+00 2.6040234e+00 2.7127458e+00 1.4350761e+00 2.5049231e+00 4.4189015e+00 3.5095669e+00 4.3257995e+00 4.0057109e+00 4.2135057e+00 5.0324952e+00 2.9113810e+00 4.7221382e+00 4.2099962e+00 4.5353918e+00 3.5215862e+00 3.7118930e+00 3.9240025e+00 3.4150232e+00 3.5401623e+00 3.7282910e+00 3.9092259e+00 5.1365012e+00 5.3314853e+00 3.4049933e+00 4.1286955e+00 3.3168890e+00 5.1347989e+00 3.3143385e+00 4.1161770e+00 4.4243750e+00 3.2143454e+00 3.3110189e+00 4.0125032e+00 4.2289520e+00 4.5343227e+00 4.8661173e+00 4.0156353e+00 3.5063553e+00 4.0017163e+00 4.5675364e+00 4.0235140e+00 3.9076272e+00 3.2116700e+00 3.8321139e+00 4.0301570e+00 3.5598557e+00 3.5095669e+00 4.3201293e+00 4.1322798e+00 3.6413292e+00 3.4157005e+00 3.6188994e+00 3.8226858e+00 3.5071409e+00 5.0436235e-01 1.1269511e+00 1.4180734e+00 9.1446938e-01 5.0476836e-01 9.6593231e-01 8.0051115e-01 6.1119558e-01 7.0176271e-01 6.0964891e-01 4.3213914e-01 5.2133179e-01 2.2573593e-01 4.1420960e-01 5.2133802e-01 4.5078948e-01 2.2608083e-01 2.0121983e-01 6.1119558e-01 1.1005364e+00 1.2089192e+00 1.2085435e-01 2.4195741e-01 7.1621884e-01 1.2085435e-01 4.0004442e-01 4.1212852e-01 5.0085236e-01 7.0096858e-01 4.0127250e-01 5.6394820e-01 8.0967961e-01 2.0000000e-01 8.0051115e-01 2.2573593e-01 7.1621884e-01 3.0482299e-01 3.3545239e+00 3.1166331e+00 3.5333785e+00 2.6054739e+00 3.2183845e+00 3.1025789e+00 3.3116521e+00 1.9046783e+00 3.2211369e+00 2.5096353e+00 2.1074907e+00 2.8107054e+00 2.6064541e+00 3.3051050e+00 2.2121875e+00 3.0393610e+00 3.1054994e+00 2.7022579e+00 3.1107490e+00 2.5027328e+00 3.4112739e+00 2.6129479e+00 3.5073688e+00 3.3035252e+00 2.9185900e+00 3.0300451e+00 3.4286400e+00 3.6205854e+00 3.1074470e+00 2.1053074e+00 2.4030297e+00 2.3022754e+00 2.5057763e+00 3.7043108e+00 3.1053329e+00 3.1100313e+00 3.3265652e+00 3.0118276e+00 2.7046025e+00 2.6052853e+00 3.0016501e+00 3.2059133e+00 2.6047974e+00 1.9052628e+00 2.8038694e+00 2.8028007e+00 2.8041967e+00 2.9102290e+00 1.6179159e+00 2.7049931e+00 4.6192199e+00 3.7100254e+00 4.5225779e+00 4.2056438e+00 4.4133506e+00 5.2278849e+00 3.1114444e+00 4.9186970e+00 4.4088300e+00 4.7323336e+00 3.7201124e+00 3.9113387e+00 4.1217116e+00 3.6152935e+00 3.7397620e+00 3.9276515e+00 4.1085246e+00 5.3314853e+00 5.5274937e+00 3.6037456e+00 4.3264210e+00 3.5173586e+00 5.3296471e+00 3.5134601e+00 4.3151165e+00 4.6204664e+00 3.4137985e+00 3.5110031e+00 4.2123903e+00 4.4237218e+00 4.7288133e+00 5.0555470e+00 4.2155430e+00 3.7056457e+00 4.2016096e+00 4.7574592e+00 4.2235569e+00 4.1072664e+00 3.4118179e+00 4.0283196e+00 4.2288238e+00 3.7532858e+00 3.7100254e+00 4.5190617e+00 4.3311362e+00 3.8383398e+00 3.6148683e+00 3.8177286e+00 4.0227665e+00 3.7075359e+00 1.5237054e+00 1.5778323e+00 1.1528553e+00 8.0928056e-01 1.4109657e+00 9.0296858e-01 1.1060939e+00 8.5617086e-01 6.0184934e-01 8.2671175e-01 8.1112984e-01 7.1621748e-01 7.2113820e-01 9.0642722e-01 9.0166476e-01 5.2167829e-01 5.6347978e-01 1.1011719e+00 1.1531951e+00 1.3523685e+00 6.0948506e-01 7.0008735e-01 1.2012929e+00 6.0948506e-01 2.0121983e-01 8.0488008e-01 7.1636719e-01 7.0025283e-01 2.2608083e-01 7.4418186e-01 9.6702272e-01 5.0476836e-01 9.0657583e-01 3.4085233e-01 1.0214933e+00 7.0176271e-01 3.7102713e+00 3.4382051e+00 3.8712380e+00 2.9060895e+00 3.5425492e+00 3.4047913e+00 3.6240078e+00 2.2025238e+00 3.5521653e+00 2.8062729e+00 2.4042873e+00 3.1166330e+00 2.9229849e+00 3.6127194e+00 2.5155829e+00 3.3866455e+00 3.4056098e+00 3.0096888e+00 3.4232171e+00 2.8068501e+00 3.7118528e+00 2.9335034e+00 3.8176417e+00 3.6116893e+00 3.2480452e+00 3.3690976e+00 3.7643838e+00 3.9429243e+00 3.4137984e+00 2.4191998e+00 2.7057317e+00 2.6060678e+00 2.8148779e+00 4.0071259e+00 3.4042418e+00 3.4154455e+00 3.6592943e+00 3.3320889e+00 3.0065584e+00 2.9059779e+00 3.3025806e+00 3.5145393e+00 2.9126049e+00 2.2031052e+00 3.1056091e+00 3.1065947e+00 3.1074470e+00 3.2280982e+00 1.9100994e+00 3.0087060e+00 4.9179684e+00 4.0090033e+00 4.8406432e+00 4.5097222e+00 4.7173415e+00 5.5505575e+00 3.4073974e+00 5.2376127e+00 4.7184838e+00 5.0477042e+00 4.0301568e+00 4.2181242e+00 4.4357103e+00 3.9120615e+00 4.0296437e+00 4.2295175e+00 4.4165186e+00 5.6553854e+00 5.8478137e+00 3.9072483e+00 4.6391758e+00 3.8129545e+00 5.6540008e+00 3.8217034e+00 4.6242406e+00 4.9412981e+00 3.7201124e+00 3.8146271e+00 4.5162248e+00 4.7490801e+00 5.0547228e+00 5.3951639e+00 4.5184830e+00 4.0138270e+00 4.5043856e+00 5.0949990e+00 4.5225786e+00 4.4133506e+00 3.7138970e+00 4.3475342e+00 4.5353918e+00 4.0747727e+00 4.0090033e+00 4.8274110e+00 4.6357670e+00 4.1493188e+00 3.9212879e+00 4.1268500e+00 4.3214438e+00 4.0081754e+00 4.1317535e-01 4.0127250e-01 7.1629303e-01 5.0043842e-01 7.0096858e-01 6.3912709e-01 7.0184453e-01 1.2003596e+00 7.9871893e-01 1.0286506e+00 1.0433442e+00 8.2635069e-01 6.3309012e-01 6.7626502e-01 1.1286016e+00 1.0782105e+00 6.1135434e-01 6.0184934e-01 3.0915245e-01 1.0143978e+00 9.0155393e-01 5.0436965e-01 1.0143978e+00 1.4324323e+00 7.4329414e-01 8.0879776e-01 1.7570482e+00 1.4092511e+00 8.1343016e-01 7.8895472e-01 1.1269511e+00 7.0470720e-01 1.2189701e+00 5.0855077e-01 8.5406616e-01 3.5025396e+00 3.3027388e+00 3.7022129e+00 2.8281704e+00 3.4036672e+00 3.3025779e+00 3.5030234e+00 2.1725076e+00 3.4018155e+00 2.7109019e+00 2.4518621e+00 3.0049127e+00 2.8364042e+00 3.5019450e+00 2.4088882e+00 3.2025657e+00 3.3031143e+00 2.9050277e+00 3.3192099e+00 2.7159616e+00 3.6057054e+00 2.8056568e+00 3.7048624e+00 3.5016345e+00 3.1026586e+00 3.2026875e+00 3.6024856e+00 3.8034160e+00 3.3035252e+00 2.3226028e+00 2.6270968e+00 2.5319718e+00 2.7081195e+00 3.9029099e+00 3.3031170e+00 3.3039553e+00 3.5023855e+00 3.2150432e+00 2.9028412e+00 2.8148779e+00 3.2051933e+00 3.4018781e+00 2.8098127e+00 2.1974660e+00 3.0055598e+00 3.0017653e+00 3.0030650e+00 3.1026235e+00 1.9002712e+00 2.9047832e+00 4.8115512e+00 3.9065683e+00 4.7047990e+00 4.4023911e+00 4.6064349e+00 5.4038141e+00 3.3119500e+00 5.1019028e+00 4.6029848e+00 4.9110422e+00 3.9076509e+00 4.1051819e+00 4.3067850e+00 3.8114951e+00 3.9246405e+00 4.1145310e+00 4.3025710e+00 5.5046681e+00 5.7049556e+00 3.8098343e+00 4.5095384e+00 3.7106240e+00 5.5035834e+00 3.7063915e+00 4.5052925e+00 4.8020893e+00 3.6066590e+00 3.7052383e+00 4.4062090e+00 4.6017113e+00 4.9033376e+00 5.2065497e+00 4.4082090e+00 3.9018737e+00 4.4013937e+00 4.9097097e+00 4.4135256e+00 4.3024877e+00 3.6059708e+00 4.2076410e+00 4.4136664e+00 3.9189006e+00 3.9065683e+00 4.7076752e+00 4.5157700e+00 4.0166034e+00 3.8091065e+00 4.0069397e+00 4.2129114e+00 3.9040721e+00 5.0476836e-01 9.1422402e-01 6.0017982e-01 6.7616723e-01 1.0001903e+00 7.4262850e-01 1.1298636e+00 1.1055799e+00 1.0782211e+00 1.4043036e+00 1.0207260e+00 9.0508712e-01 1.0030871e+00 1.2632996e+00 1.3253497e+00 1.0001598e+00 5.0855077e-01 2.4195741e-01 1.3131369e+00 1.2089895e+00 9.0007572e-01 1.3131369e+00 1.5263518e+00 1.0087393e+00 9.3308891e-01 2.1138769e+00 1.4140515e+00 9.3308891e-01 6.8160885e-01 1.4180436e+00 6.7626681e-01 1.3018145e+00 7.0470720e-01 1.1133986e+00 3.2054626e+00 3.0041787e+00 3.4044439e+00 2.6382589e+00 3.1129223e+00 3.0138245e+00 3.2030205e+00 2.1566438e+00 3.1086927e+00 2.4554557e+00 2.5269479e+00 2.7127202e+00 2.6737930e+00 3.2074207e+00 2.1510232e+00 2.9068053e+00 3.0077106e+00 2.6369414e+00 3.0816280e+00 2.4971338e+00 3.3055260e+00 2.5325155e+00 3.4206210e+00 3.2100081e+00 2.8135926e+00 2.9088609e+00 3.3100014e+00 3.5053029e+00 3.0107283e+00 2.1554609e+00 2.4508792e+00 2.3794578e+00 2.4537333e+00 3.6090037e+00 3.0077114e+00 3.0034200e+00 3.2047284e+00 2.9729700e+00 2.6131590e+00 2.5821442e+00 2.9309340e+00 3.1060464e+00 2.5610212e+00 2.2285414e+00 2.7317035e+00 2.7106184e+00 2.7159615e+00 2.8134622e+00 1.9767345e+00 2.6270952e+00 4.5095106e+00 3.6117736e+00 4.4050179e+00 4.1034650e+00 4.3058769e+00 5.1048430e+00 3.0395885e+00 4.8030341e+00 4.3077256e+00 4.6095748e+00 3.6067573e+00 3.8091370e+00 4.0067454e+00 3.5235094e+00 3.6257071e+00 3.8125141e+00 4.0031827e+00 5.2054101e+00 5.4066794e+00 3.5404367e+00 4.2082468e+00 3.4146523e+00 5.2054259e+00 3.4138230e+00 4.2042865e+00 4.5025743e+00 3.3123786e+00 3.4067938e+00 4.1072911e+00 4.3032007e+00 4.6053784e+00 4.9093646e+00 4.1089590e+00 3.6062594e+00 4.1061436e+00 4.6117560e+00 4.1111295e+00 4.0026055e+00 3.3078313e+00 3.9072844e+00 4.1120111e+00 3.6177796e+00 3.6117736e+00 4.4064445e+00 4.2133758e+00 3.7157992e+00 3.5215805e+00 3.7072609e+00 3.9105673e+00 3.6051689e+00 4.1212852e-01 4.1212852e-01 3.0490481e-01 5.2167208e-01 3.0915245e-01 8.0097499e-01 6.1119558e-01 6.9518117e-01 9.0168933e-01 5.2491131e-01 4.0363334e-01 5.0085236e-01 7.8940551e-01 8.2462252e-01 5.0042326e-01 3.1328089e-01 3.0490481e-01 8.0928056e-01 7.0470867e-01 4.0125062e-01 8.0928056e-01 1.0776294e+00 5.0517282e-01 4.5078948e-01 1.6096629e+00 1.0207396e+00 4.5847767e-01 6.0184622e-01 9.1422402e-01 3.4085233e-01 8.5406674e-01 2.4195741e-01 6.0964891e-01 3.4079041e+00 3.2018548e+00 3.6045966e+00 2.7227151e+00 3.3029106e+00 3.2014779e+00 3.4016816e+00 2.0608234e+00 3.3024690e+00 2.6067721e+00 2.3393392e+00 2.9023862e+00 2.7310942e+00 3.4010299e+00 2.3048574e+00 3.1044057e+00 3.2014774e+00 2.8036023e+00 3.2152055e+00 2.6124447e+00 3.5030234e+00 2.7035171e+00 3.6034258e+00 3.4010358e+00 3.0022434e+00 3.1033306e+00 3.5041120e+00 3.7031277e+00 3.2018065e+00 2.2177966e+00 2.5220687e+00 2.4265152e+00 2.6055197e+00 3.8016494e+00 3.2014773e+00 3.2019092e+00 3.4031881e+00 3.1122360e+00 2.8013347e+00 2.7110046e+00 3.1036553e+00 3.3009330e+00 2.7070770e+00 2.0855888e+00 2.9035486e+00 2.9008500e+00 2.9016034e+00 3.0016038e+00 1.7857124e+00 2.8028019e+00 4.7076061e+00 3.8037955e+00 4.6049801e+00 4.3013465e+00 4.5040960e+00 5.3068325e+00 3.2075036e+00 5.0037550e+00 4.5023523e+00 4.8096009e+00 3.8048551e+00 4.0031892e+00 4.2051335e+00 3.7071735e+00 3.8161632e+00 4.0093901e+00 4.2016368e+00 5.4081547e+00 5.6075434e+00 3.7075525e+00 4.4072835e+00 3.6062405e+00 5.4074634e+00 3.6038441e+00 4.4036959e+00 4.7038247e+00 3.5038075e+00 3.6028345e+00 4.3038299e+00 4.5042394e+00 4.8062731e+00 5.1150203e+00 4.3051629e+00 3.8011413e+00 4.3008955e+00 4.8153681e+00 4.3087925e+00 4.2014602e+00 3.5032125e+00 4.1063865e+00 4.3094598e+00 3.8146853e+00 3.8037955e+00 4.6054982e+00 4.4109814e+00 3.9115832e+00 3.7058197e+00 3.9043917e+00 4.1081838e+00 3.8021570e+00 6.0365948e-01 3.0008832e-01 3.3818226e-01 2.0121983e-01 5.2133802e-01 3.0915245e-01 5.0437695e-01 5.0043842e-01 2.0181667e-01 1.2085435e-01 1.2085435e-01 4.1317535e-01 4.1317535e-01 3.0026460e-01 6.0018299e-01 7.0462697e-01 4.0246123e-01 3.0490481e-01 4.0004442e-01 4.0246123e-01 7.1621884e-01 1.2085435e-01 1.1269424e-01 1.2036863e+00 7.0088627e-01 3.0482299e-01 5.0436965e-01 5.0436235e-01 3.0482299e-01 5.0436965e-01 2.2608083e-01 2.0121983e-01 3.3237063e+00 3.1056091e+00 3.5138377e+00 2.6067805e+00 3.2064817e+00 3.1008890e+00 3.3041599e+00 1.9144935e+00 3.2074507e+00 2.5042498e+00 2.1492024e+00 2.8038903e+00 2.6091437e+00 3.3015588e+00 2.2041706e+00 3.0148613e+00 3.1021975e+00 2.7007716e+00 3.1069083e+00 2.5027328e+00 3.4052051e+00 2.6037226e+00 3.5028446e+00 3.3009330e+00 2.9058292e+00 3.0107430e+00 3.4113341e+00 3.6081814e+00 3.1026177e+00 2.1035154e+00 2.4051766e+00 2.3058791e+00 2.5019964e+00 3.7017412e+00 3.1021847e+00 3.1038570e+00 3.3100818e+00 3.0059450e+00 2.7015162e+00 2.6035107e+00 3.0009631e+00 3.2017847e+00 2.6021247e+00 1.9231085e+00 2.8015882e+00 2.8007533e+00 2.8013565e+00 2.9028946e+00 1.6222582e+00 2.7017239e+00 4.6112605e+00 3.7050457e+00 4.5107898e+00 4.2023583e+00 4.4067851e+00 5.2146266e+00 3.1060428e+00 4.9089682e+00 4.4037570e+00 4.7173415e+00 3.7092301e+00 3.9050336e+00 4.1101936e+00 3.6083379e+00 3.7235997e+00 3.9149881e+00 4.1034584e+00 5.3169366e+00 5.5149065e+00 3.6029421e+00 4.3133953e+00 3.5091580e+00 5.3158283e+00 3.5057369e+00 4.3071174e+00 4.6095441e+00 3.4059695e+00 3.5048429e+00 4.2061215e+00 4.4109767e+00 4.7143113e+00 5.0310424e+00 4.2080636e+00 3.7018984e+00 4.2005765e+00 4.7313463e+00 4.2134002e+00 4.1029723e+00 3.4053426e+00 4.0133308e+00 4.2155438e+00 3.7272780e+00 3.7050457e+00 4.5097224e+00 4.3174320e+00 3.8199266e+00 3.6070223e+00 3.8081328e+00 4.0126677e+00 3.7034791e+00 6.0017665e-01 4.1210927e-01 6.0018299e-01 1.1133986e+00 6.3178534e-01 9.0142681e-01 8.5403486e-01 7.0462844e-01 5.0477564e-01 5.2491734e-01 1.0087252e+00 9.3306807e-01 4.1317535e-01 5.0517282e-01 4.1317535e-01 8.5409862e-01 7.5503094e-01 4.1317535e-01 8.5409862e-01 1.3133231e+00 6.0964891e-01 7.0548138e-01 1.5640758e+00 1.3027556e+00 7.0176271e-01 6.0017982e-01 9.6591433e-01 6.0000635e-01 1.1056693e+00 4.0127250e-01 7.1700909e-01 3.0056049e+00 2.8037508e+00 3.2038047e+00 2.3350905e+00 2.9043042e+00 2.8024566e+00 3.0040963e+00 1.7133143e+00 2.9021652e+00 2.2134864e+00 2.0299551e+00 2.5066443e+00 2.3464211e+00 3.0020171e+00 1.9120296e+00 2.7041827e+00 2.8038683e+00 2.4047867e+00 2.8219468e+00 2.2186306e+00 3.1079220e+00 2.3063026e+00 3.2048524e+00 3.0013665e+00 2.6029242e+00 2.7037323e+00 3.1033714e+00 3.3046348e+00 2.8041978e+00 1.8296471e+00 2.1344310e+00 2.0421601e+00 2.2088481e+00 3.4030563e+00 2.8038694e+00 2.8056176e+00 3.0035303e+00 2.7166861e+00 2.4032760e+00 2.3173405e+00 2.7049931e+00 2.9020943e+00 2.3107074e+00 1.7540491e+00 2.5057744e+00 2.5017294e+00 2.5032614e+00 2.6027348e+00 1.4738792e+00 2.4051328e+00 4.3150879e+00 3.4081972e+00 4.2065765e+00 3.9027794e+00 4.1082339e+00 4.9060122e+00 2.8144592e+00 4.6029848e+00 4.1031680e+00 4.4149701e+00 3.4105998e+00 3.6062867e+00 3.8091132e+00 3.3145497e+00 3.4354252e+00 3.6203140e+00 3.8031346e+00 5.0073650e+00 5.2071845e+00 3.3100796e+00 4.0129286e+00 3.2145637e+00 5.0059527e+00 3.2079238e+00 4.0069158e+00 4.3033003e+00 3.1086424e+00 3.2069551e+00 3.9078313e+00 4.1030253e+00 4.4053246e+00 4.7120702e+00 3.9105941e+00 3.4019027e+00 3.9011588e+00 4.4155733e+00 3.9183552e+00 3.8030509e+00 3.1080886e+00 3.7106642e+00 3.9186175e+00 3.4279064e+00 3.4081972e+00 4.2100505e+00 4.0214626e+00 3.5236480e+00 3.3110446e+00 3.5093262e+00 3.7177968e+00 3.4052047e+00 4.1317535e-01 1.1269424e-01 5.6371422e-01 5.0084481e-01 4.5784410e-01 8.0000239e-01 4.0006662e-01 3.0017653e-01 4.0006662e-01 6.0948800e-01 7.0088627e-01 4.1210927e-01 3.0482299e-01 4.5080200e-01 7.0016860e-01 6.0184934e-01 4.1317535e-01 7.0016860e-01 8.5406674e-01 4.0002221e-01 3.0482299e-01 1.5012719e+00 7.4269314e-01 3.3818226e-01 4.0002221e-01 8.0046685e-01 1.1269424e-01 6.3165225e-01 2.0121983e-01 5.0002283e-01 3.2274206e+00 3.0066036e+00 3.4159337e+00 2.5238518e+00 3.1081931e+00 3.0018108e+00 3.2048307e+00 1.8672243e+00 3.1090333e+00 2.4088880e+00 2.1557835e+00 2.7050009e+00 2.5327574e+00 3.2021240e+00 2.1075767e+00 2.9175658e+00 3.0027966e+00 2.6034860e+00 3.0173373e+00 2.4124132e+00 3.3060311e+00 2.5063233e+00 3.4049933e+00 3.2016467e+00 2.8074882e+00 2.9128790e+00 3.3135401e+00 3.5094636e+00 3.0034944e+00 2.0185049e+00 2.3226176e+00 2.2272636e+00 2.4061715e+00 3.6025233e+00 3.0027816e+00 3.0045159e+00 3.2117473e+00 2.9147768e+00 2.6022650e+00 2.5117111e+00 2.9035536e+00 3.1022707e+00 2.5074705e+00 1.8959538e+00 2.7040250e+00 2.7012715e+00 2.7023320e+00 2.8040244e+00 1.6015419e+00 2.6035923e+00 4.5125057e+00 3.6062867e+00 4.4120448e+00 4.1027436e+00 4.3076126e+00 5.1160601e+00 3.0101869e+00 4.8099407e+00 4.3047534e+00 4.6192050e+00 3.6105351e+00 3.8061121e+00 4.0115220e+00 3.5110245e+00 3.6271576e+00 3.8169672e+00 4.0039490e+00 5.2185416e+00 5.4163883e+00 3.5078417e+00 4.2149895e+00 3.4109302e+00 5.2173835e+00 3.4072913e+00 4.2079670e+00 4.5106052e+00 3.3073674e+00 3.4056857e+00 4.1070396e+00 4.3122866e+00 4.6159499e+00 4.9341410e+00 4.1092167e+00 3.6024856e+00 4.1011078e+00 4.6347105e+00 4.1150272e+00 4.0033723e+00 3.3063033e+00 3.9150644e+00 4.1174503e+00 3.6310621e+00 3.6062867e+00 4.4108290e+00 4.2194920e+00 3.7226812e+00 3.5095242e+00 3.7093173e+00 3.9142888e+00 3.6040604e+00 3.4342562e-01 8.5406616e-01 3.3813251e-01 6.0017665e-01 4.5078948e-01 4.0125062e-01 2.2573593e-01 3.0474106e-01 7.0008584e-01 6.0184622e-01 2.2538848e-01 7.0017011e-01 8.0046685e-01 5.0477564e-01 5.2167208e-01 4.0004442e-01 5.0477564e-01 1.0016896e+00 3.0474106e-01 4.5080200e-01 1.1531953e+00 1.0008617e+00 4.5080200e-01 4.1420960e-01 6.1119558e-01 4.1210927e-01 8.0051036e-01 3.0482299e-01 4.1210927e-01 3.0158412e+00 2.8068284e+00 3.2097099e+00 2.3108757e+00 2.9065890e+00 2.8022000e+00 3.0066661e+00 1.6225614e+00 2.9048017e+00 2.2116239e+00 1.8685354e+00 2.5096708e+00 2.3100354e+00 3.0026666e+00 1.9136652e+00 2.7108290e+00 2.8056165e+00 2.4010446e+00 2.8094419e+00 2.2042326e+00 3.1114445e+00 2.3060252e+00 3.2036636e+00 3.0010404e+00 2.6048201e+00 2.7083838e+00 3.1074856e+00 3.3083888e+00 2.8056953e+00 1.8055938e+00 2.1074903e+00 2.0078120e+00 2.2044098e+00 3.4034897e+00 2.8056164e+00 2.8086638e+00 3.0080453e+00 2.7058598e+00 2.4044765e+00 2.3071636e+00 2.7018643e+00 2.9031229e+00 2.3040302e+00 1.6345914e+00 2.5039390e+00 2.5021287e+00 2.5037126e+00 2.6035547e+00 1.3485963e+00 2.4045982e+00 4.3195471e+00 3.4105069e+00 4.2110205e+00 3.9039624e+00 4.1112641e+00 4.9115281e+00 2.8134622e+00 4.6064153e+00 4.1040152e+00 4.4216160e+00 3.4153329e+00 3.6083651e+00 3.8136432e+00 3.3170079e+00 3.4454804e+00 3.6271127e+00 3.8048208e+00 5.0136911e+00 5.2125102e+00 3.3041886e+00 4.0185527e+00 3.2193583e+00 5.0117789e+00 3.2102572e+00 4.0101485e+00 4.3071174e+00 3.1116727e+00 3.2099137e+00 3.9105756e+00 4.1073261e+00 4.4108290e+00 4.7236350e+00 3.9141183e+00 3.4025037e+00 3.9008223e+00 4.4275986e+00 3.9240716e+00 3.8046112e+00 3.1114731e+00 3.7165788e+00 3.9250546e+00 3.4397950e+00 3.4105069e+00 4.2141201e+00 4.0283725e+00 3.5323888e+00 3.3126331e+00 3.5133654e+00 3.7236064e+00 3.4073749e+00 5.6371422e-01 4.0125062e-01 4.2362917e-01 7.0008735e-01 3.0017653e-01 2.2573593e-01 3.0490481e-01 5.2167829e-01 6.0202028e-01 3.3808272e-01 4.1210927e-01 5.2167829e-01 6.0201716e-01 5.0477564e-01 4.0363334e-01 6.0201716e-01 7.8895472e-01 3.0474106e-01 2.2608083e-01 1.4017696e+00 7.1636719e-01 2.2608083e-01 4.0002221e-01 7.0088627e-01 2.0121983e-01 5.6371422e-01 2.2538848e-01 4.0127250e-01 3.2269400e+00 3.0055754e+00 3.4153574e+00 2.5158464e+00 3.1070003e+00 3.0010043e+00 3.2037264e+00 1.8447764e+00 3.1084925e+00 2.4051329e+00 2.1169795e+00 2.7031257e+00 2.5230194e+00 3.2014729e+00 2.1040690e+00 2.9167440e+00 3.0016616e+00 2.6020655e+00 3.0122358e+00 2.4077390e+00 3.3040889e+00 2.5044039e+00 3.4036241e+00 3.2011770e+00 2.8066054e+00 2.9119764e+00 3.3128842e+00 3.5083774e+00 3.0022542e+00 2.0112442e+00 2.3146813e+00 2.2178117e+00 2.4035997e+00 3.6016272e+00 3.0016466e+00 3.0030180e+00 3.2109724e+00 2.9107838e+00 2.6012056e+00 2.5072166e+00 2.9020943e+00 3.1016037e+00 2.5045154e+00 1.8665804e+00 2.7022828e+00 2.7006623e+00 2.7012715e+00 2.8031364e+00 1.5665127e+00 2.6019940e+00 4.5096473e+00 3.6042722e+00 4.4108394e+00 4.1020090e+00 4.3058539e+00 5.1154681e+00 3.0065585e+00 4.8095984e+00 4.3039464e+00 4.6166518e+00 3.6081814e+00 3.8045576e+00 4.0096177e+00 3.5076367e+00 3.6204901e+00 3.8129595e+00 4.0031500e+00 5.2178509e+00 5.4155855e+00 3.5053718e+00 4.2125027e+00 3.4076329e+00 5.2169557e+00 3.4052726e+00 4.2064771e+00 4.5101686e+00 3.3051940e+00 3.4039470e+00 4.1052782e+00 4.3120002e+00 4.6153660e+00 4.9336188e+00 4.1069501e+00 3.6018985e+00 4.1007374e+00 4.6331222e+00 4.1114855e+00 4.0025890e+00 3.3042986e+00 3.9129418e+00 4.1139050e+00 3.6259501e+00 3.6042722e+00 4.4088300e+00 4.2155438e+00 3.7181244e+00 3.5068261e+00 3.7072136e+00 3.9107458e+00 3.6027359e+00 7.1779518e-01 9.0005048e-01 6.8160885e-01 6.0980961e-01 6.3164977e-01 6.0964597e-01 6.0948506e-01 6.3178534e-01 8.0888055e-01 6.5712813e-01 9.1552331e-01 5.6595908e-01 4.5147187e-01 9.0026543e-01 5.6595908e-01 6.0201716e-01 5.6370994e-01 4.1212852e-01 1.3000455e+00 4.1315633e-01 6.1830764e-01 9.0511169e-01 6.0964891e-01 6.3178534e-01 4.5077696e-01 7.1621748e-01 4.5783248e-01 3.7510248e+00 3.5145413e+00 3.9319585e+00 3.0060350e+00 3.6168418e+00 3.5015800e+00 3.7092301e+00 2.3098782e+00 3.6209185e+00 2.9036019e+00 2.5319798e+00 3.2059465e+00 3.0125595e+00 3.7043511e+00 2.6050088e+00 3.4362995e+00 3.5023713e+00 3.1027850e+00 3.5112541e+00 2.9034027e+00 3.8056232e+00 3.0109656e+00 3.9070007e+00 3.7037948e+00 3.3177283e+00 3.4278716e+00 3.8279200e+00 4.0185639e+00 3.5049370e+00 2.5063489e+00 2.8048596e+00 2.7053910e+00 2.9045816e+00 4.1028806e+00 3.5020661e+00 3.5059137e+00 3.7249599e+00 3.4134555e+00 3.1021033e+00 3.0035422e+00 3.4012314e+00 3.6049329e+00 3.0042977e+00 2.3151346e+00 3.2021240e+00 3.2018065e+00 3.2023319e+00 3.3095196e+00 2.0139907e+00 3.1028259e+00 5.0111326e+00 4.1049446e+00 4.9203200e+00 4.6042055e+00 4.8089555e+00 5.6273643e+00 3.5051449e+00 5.3190012e+00 4.8083867e+00 5.1260178e+00 4.1140184e+00 4.3082037e+00 4.5172930e+00 4.0074572e+00 4.1195081e+00 4.3162103e+00 4.5071301e+00 5.7305902e+00 5.9266306e+00 4.0041352e+00 4.7202045e+00 3.9078680e+00 5.7295930e+00 3.9093593e+00 4.7117434e+00 5.0203874e+00 3.8087102e+00 3.9064537e+00 4.6081315e+00 4.8239967e+00 5.1282911e+00 5.4538016e+00 4.6097450e+00 4.1052255e+00 4.6016323e+00 5.1527860e+00 4.6133719e+00 4.5057296e+00 3.8063301e+00 4.4231469e+00 4.6192070e+00 4.1384491e+00 4.1049446e+00 4.9142249e+00 4.7202041e+00 4.2256252e+00 4.0099717e+00 4.2125085e+00 4.4124585e+00 4.1039188e+00 3.4085233e-01 3.3818226e-01 1.2699992e-01 3.0922892e-01 3.3818226e-01 4.1212852e-01 3.4085233e-01 3.0490481e-01 8.0250202e-01 9.0192695e-01 4.0363334e-01 5.0437695e-01 4.5847767e-01 4.0363334e-01 7.0633229e-01 3.0482299e-01 4.0246123e-01 1.0095513e+00 7.0548283e-01 2.0181667e-01 5.0043084e-01 3.6452132e-01 5.0436965e-01 5.0855778e-01 4.1420960e-01 3.3813251e-01 3.0360001e+00 2.8068283e+00 3.2199554e+00 2.3040302e+00 2.9083228e+00 2.8004229e+00 3.0040677e+00 1.6099792e+00 2.9111118e+00 2.2023225e+00 1.8444678e+00 2.5026969e+00 2.3072196e+00 3.0013665e+00 1.9023442e+00 2.7227152e+00 2.8012528e+00 2.4005053e+00 2.8054838e+00 2.2013444e+00 3.1036553e+00 2.3040711e+00 3.2026875e+00 3.0010106e+00 2.6084695e+00 2.7159628e+00 3.1166009e+00 3.3100796e+00 2.8019019e+00 1.8020058e+00 2.1029252e+00 2.0034861e+00 2.2011906e+00 3.4011297e+00 2.8012319e+00 2.8028007e+00 3.0142197e+00 2.7060544e+00 2.4007552e+00 2.3017471e+00 2.7003774e+00 2.9016034e+00 2.3011979e+00 1.6179000e+00 2.5007284e+00 2.5003793e+00 2.5007008e+00 2.6035320e+00 1.3154932e+00 2.4008859e+00 4.3091529e+00 3.4034897e+00 4.2123904e+00 3.9018704e+00 4.1056542e+00 4.9181670e+00 2.8038684e+00 4.6114520e+00 4.1039624e+00 4.4180514e+00 3.4084525e+00 3.6042874e+00 3.8104403e+00 3.3060311e+00 3.4198458e+00 3.6127194e+00 3.8032956e+00 5.0208687e+00 5.2178587e+00 3.3018328e+00 4.0133297e+00 3.2067991e+00 5.0200323e+00 3.2048524e+00 4.0067585e+00 4.3122441e+00 3.1047671e+00 3.2036090e+00 3.9049697e+00 4.1148052e+00 4.4184267e+00 4.7404155e+00 3.9065727e+00 3.4018864e+00 3.9004186e+00 4.4392802e+00 3.9110280e+00 3.8025990e+00 3.1038577e+00 3.7145622e+00 3.9140895e+00 3.4287259e+00 3.4034897e+00 4.2090841e+00 4.0156240e+00 3.5189468e+00 3.3056781e+00 3.5073617e+00 3.7102604e+00 3.4023494e+00 4.1315633e-01 3.0915245e-01 4.5078948e-01 5.2132556e-01 3.0482299e-01 3.3808272e-01 6.0964597e-01 7.0911112e-01 8.6051414e-01 4.1212852e-01 7.0016860e-01 7.4262964e-01 4.1212852e-01 6.1830489e-01 4.1209001e-01 6.0018299e-01 1.1056693e+00 6.0964597e-01 4.1317535e-01 4.1315633e-01 5.2133179e-01 4.2268438e-01 5.0084481e-01 5.2491131e-01 5.0043084e-01 2.9115264e+00 2.6338022e+00 3.0658361e+00 2.1172959e+00 2.7373419e+00 2.6040822e+00 2.8212040e+00 1.4407364e+00 2.7450517e+00 2.0182279e+00 1.7116683e+00 2.3196029e+00 2.1285888e+00 2.8091316e+00 1.7264084e+00 2.5863714e+00 2.6084695e+00 2.2054529e+00 2.6248910e+00 2.0083311e+00 2.9174382e+00 2.1301354e+00 3.0136614e+00 2.8068911e+00 2.4421128e+00 2.5659281e+00 2.9581275e+00 3.1380442e+00 2.6129786e+00 1.6191482e+00 1.9129988e+00 1.8141046e+00 2.0129571e+00 3.2064817e+00 2.6080847e+00 2.6171503e+00 2.8540078e+00 2.5288353e+00 2.2078337e+00 2.1116321e+00 2.5029614e+00 2.7108347e+00 2.1109969e+00 1.4620239e+00 2.3067198e+00 2.3048725e+00 2.3072196e+00 2.4221911e+00 1.1960519e+00 2.2090466e+00 4.1263920e+00 3.2146438e+00 4.0362393e+00 3.7082866e+00 3.9191966e+00 4.7434452e+00 2.6190662e+00 4.4302264e+00 3.9142233e+00 4.2488425e+00 3.2328627e+00 3.4177609e+00 3.6349468e+00 3.1232336e+00 3.2606481e+00 3.4419771e+00 3.6135028e+00 4.8484858e+00 5.0414126e+00 3.1077602e+00 3.8409517e+00 3.0264502e+00 4.8462395e+00 3.0224855e+00 3.8231767e+00 4.1339850e+00 2.9228238e+00 3.0173096e+00 3.7181009e+00 3.9409635e+00 4.2473796e+00 4.5888422e+00 3.7226114e+00 3.2097424e+00 3.7024938e+00 4.2924779e+00 3.7339169e+00 3.6111693e+00 2.9185950e+00 3.5470876e+00 3.7434043e+00 3.2896416e+00 3.2146438e+00 4.0283196e+00 3.8460162e+00 3.3616756e+00 3.1242731e+00 3.3284650e+00 3.5333785e+00 3.2109426e+00 4.0122873e-01 5.0043084e-01 4.0243965e-01 3.0474106e-01 2.0061436e-01 4.5148429e-01 1.1000100e+00 1.2012928e+00 1.2699992e-01 4.0122873e-01 5.6595488e-01 1.2699992e-01 6.0184309e-01 4.0004442e-01 5.0436965e-01 7.1700909e-01 6.0201716e-01 5.2132556e-01 8.0051115e-01 2.2573593e-01 8.0000080e-01 4.0243965e-01 7.0088477e-01 3.0474106e-01 3.1428043e+00 2.9119661e+00 3.3252402e+00 2.4048325e+00 3.0131919e+00 2.9019362e+00 3.1087162e+00 1.7043719e+00 3.0148571e+00 2.3090280e+00 1.9099608e+00 2.6089255e+00 2.4039780e+00 3.1034773e+00 2.0109328e+00 2.8295063e+00 2.9047982e+00 2.5011632e+00 2.9079901e+00 2.3019339e+00 3.2101766e+00 2.4088882e+00 3.3051149e+00 3.1020645e+00 2.7127201e+00 2.8219255e+00 3.2211370e+00 3.4154432e+00 2.9057760e+00 1.9031964e+00 2.2023924e+00 2.1016800e+00 2.3040177e+00 3.5033831e+00 2.9047500e+00 2.9083094e+00 3.1195526e+00 2.8078790e+00 2.5037817e+00 2.4045555e+00 2.8012577e+00 3.0040677e+00 2.4032886e+00 1.7053664e+00 2.6031367e+00 2.6019751e+00 2.6032655e+00 2.7067267e+00 1.4186217e+00 2.5039390e+00 4.4180854e+00 3.5092124e+00 4.3179254e+00 4.0043989e+00 4.2115634e+00 5.0223341e+00 2.9108451e+00 4.7142986e+00 4.2064794e+00 4.5276385e+00 3.5169841e+00 3.7092301e+00 3.9177719e+00 3.4145764e+00 3.5398518e+00 3.7257231e+00 3.9064409e+00 5.1255523e+00 5.3223081e+00 3.4028319e+00 4.1224590e+00 3.3167394e+00 5.1238108e+00 3.3110167e+00 4.1123595e+00 4.4156295e+00 3.2116669e+00 3.3094499e+00 4.0106882e+00 4.2180724e+00 4.5227110e+00 4.8462592e+00 4.0138270e+00 3.5038530e+00 4.0010263e+00 4.5481710e+00 4.0222346e+00 3.9055783e+00 3.2104685e+00 3.8231767e+00 4.0259306e+00 3.5470873e+00 3.5092124e+00 4.3162096e+00 4.1285334e+00 3.6344358e+00 3.4126369e+00 3.6148618e+00 3.8215373e+00 3.5066394e+00 2.2608083e-01 2.4170870e-01 3.0915245e-01 3.0915245e-01 4.0002221e-01 7.0096858e-01 8.0888055e-01 3.3818226e-01 4.0243965e-01 5.0477564e-01 3.3818226e-01 6.1135434e-01 2.0121983e-01 3.0017653e-01 1.1020506e+00 6.0219099e-01 2.0061436e-01 4.1210927e-01 4.0246123e-01 4.0125062e-01 4.0363334e-01 3.4085233e-01 2.2573593e-01 3.1414744e+00 2.9090612e+00 3.3237063e+00 2.4058952e+00 3.0107723e+00 2.9007492e+00 3.1056084e+00 1.7139238e+00 3.0138400e+00 2.3035512e+00 1.9525301e+00 2.6040007e+00 2.4100386e+00 3.1020779e+00 2.0037730e+00 2.8273039e+00 2.9018637e+00 2.5009579e+00 2.9077468e+00 2.3022754e+00 3.2048985e+00 2.4059812e+00 3.3038272e+00 3.1015567e+00 2.7110304e+00 2.8196992e+00 3.2199879e+00 3.4126307e+00 2.9028597e+00 1.9035634e+00 2.2044603e+00 2.1052067e+00 2.3021298e+00 3.5016873e+00 2.9018153e+00 2.9040211e+00 3.1174676e+00 2.8083845e+00 2.5012694e+00 2.4028385e+00 2.8006965e+00 3.0024198e+00 2.4021168e+00 1.7233814e+00 2.6012647e+00 2.6007117e+00 2.6012056e+00 2.7050190e+00 1.4220898e+00 2.5015263e+00 4.4109742e+00 3.5045842e+00 4.3148937e+00 4.0025815e+00 4.2071337e+00 5.0208677e+00 2.9053047e+00 4.7134688e+00 4.2051335e+00 4.5213131e+00 3.5107904e+00 3.7056862e+00 3.9129303e+00 3.4076849e+00 3.5232606e+00 3.7154827e+00 3.9043905e+00 5.1238111e+00 5.3204854e+00 3.4027174e+00 4.1161770e+00 3.3085473e+00 5.1228006e+00 3.3065392e+00 4.1085246e+00 4.4144908e+00 3.2064337e+00 3.3048953e+00 4.0063737e+00 4.2173565e+00 4.5213359e+00 4.8449108e+00 4.0082529e+00 3.5026815e+00 4.0006690e+00 4.5442582e+00 4.0132894e+00 3.9035247e+00 3.2051958e+00 3.8177289e+00 4.0170262e+00 3.5340950e+00 3.5045842e+00 4.3111747e+00 4.1186693e+00 3.6228903e+00 3.4075338e+00 3.6094379e+00 3.8124787e+00 3.5031928e+00 1.1269424e-01 5.0436965e-01 4.5078948e-01 2.2573593e-01 6.0000317e-01 7.0088477e-01 4.1210927e-01 3.4080442e-01 3.0474106e-01 4.1210927e-01 8.0883841e-01 1.1269424e-01 2.2573593e-01 1.2089253e+00 8.0051036e-01 4.0125062e-01 4.1317535e-01 5.2133802e-01 3.0017653e-01 6.0184622e-01 2.0061436e-01 2.2573593e-01 3.2211375e+00 3.0065592e+00 3.4126307e+00 2.5097024e+00 3.1069750e+00 3.0016616e+00 3.2056674e+00 1.8201133e+00 3.1066333e+00 2.4080686e+00 2.0619186e+00 2.7068820e+00 2.5107632e+00 3.2022485e+00 2.1087015e+00 2.9137660e+00 3.0040552e+00 2.6010528e+00 3.0089164e+00 2.4039766e+00 3.3085605e+00 2.5050799e+00 3.4035383e+00 3.2010814e+00 2.8057187e+00 2.9102474e+00 3.3101488e+00 3.5088135e+00 3.0043212e+00 2.0051350e+00 2.3071665e+00 2.2078183e+00 2.4034084e+00 3.6027901e+00 3.0040510e+00 3.0064311e+00 3.2097125e+00 2.9065741e+00 2.6030847e+00 2.5057763e+00 2.9016034e+00 3.1025924e+00 2.5033702e+00 1.8310475e+00 2.7029487e+00 2.7015162e+00 2.7026433e+00 2.8034238e+00 1.5358653e+00 2.6032968e+00 4.5159027e+00 3.6080734e+00 4.4115652e+00 4.1033603e+00 4.3094200e+00 5.1138780e+00 3.0100866e+00 4.8082318e+00 4.3041941e+00 4.6203464e+00 3.6127197e+00 3.8070338e+00 4.0124958e+00 3.5130651e+00 3.6349183e+00 3.8215362e+00 4.0044029e+00 5.2162094e+00 5.4145184e+00 3.5039680e+00 4.2166537e+00 3.4145702e+00 5.2146334e+00 3.4083285e+00 4.2090727e+00 4.5089181e+00 3.3091123e+00 3.4076329e+00 4.1087140e+00 4.3098021e+00 4.6133860e+00 4.9287684e+00 4.1115100e+00 3.6023704e+00 4.1007820e+00 4.6309835e+00 4.1192351e+00 4.0040240e+00 3.3086516e+00 3.9156759e+00 4.1209257e+00 3.6344375e+00 3.6080734e+00 4.4124586e+00 4.2235561e+00 3.7268101e+00 3.5102374e+00 3.7111714e+00 3.9185866e+00 3.6056580e+00 5.0084481e-01 4.1315633e-01 2.2573593e-01 7.0000303e-01 8.0046605e-01 3.3818226e-01 2.4170870e-01 3.0017653e-01 3.3818226e-01 8.0245824e-01 1.1269424e-01 2.0181667e-01 1.1133897e+00 8.0004523e-01 4.0246123e-01 5.2167829e-01 4.5078948e-01 4.0125062e-01 6.0017665e-01 3.0017653e-01 2.0061436e-01 3.3182813e+00 3.1056085e+00 3.5110034e+00 2.6060742e+00 3.2059465e+00 3.1013637e+00 3.3048926e+00 1.9099680e+00 3.2056789e+00 2.5063346e+00 2.1344310e+00 2.8057704e+00 2.6059875e+00 3.3019214e+00 2.2068463e+00 3.0117188e+00 3.1034568e+00 2.7006623e+00 3.1063566e+00 2.5023073e+00 3.4074246e+00 2.6040822e+00 3.5028878e+00 3.3008913e+00 2.9048017e+00 3.0087102e+00 3.4087684e+00 3.6077011e+00 3.1036688e+00 2.1027637e+00 2.4039664e+00 2.3040177e+00 2.5024922e+00 3.7023994e+00 3.1034532e+00 3.1054994e+00 3.3083865e+00 3.0045919e+00 2.7025560e+00 2.6039937e+00 3.0011260e+00 3.2022183e+00 2.6023240e+00 1.9156198e+00 2.8022964e+00 2.8012577e+00 2.8021795e+00 2.9028597e+00 1.6190551e+00 2.7026433e+00 4.6143249e+00 3.7070367e+00 4.5103890e+00 4.2029881e+00 4.4084395e+00 5.2126509e+00 3.1082889e+00 4.9074567e+00 4.4036930e+00 4.7183734e+00 3.7111657e+00 3.9061763e+00 4.1111077e+00 3.6112621e+00 3.7306950e+00 3.9190472e+00 4.1039096e+00 5.3148048e+00 5.5132902e+00 3.6028435e+00 4.3148929e+00 3.5126667e+00 5.3133599e+00 3.5071916e+00 4.3081091e+00 4.6080296e+00 3.4078683e+00 3.5066415e+00 4.2077543e+00 4.4087821e+00 4.7120754e+00 5.0261502e+00 4.2102487e+00 3.7020547e+00 4.2006494e+00 4.7279956e+00 4.2171591e+00 4.1035746e+00 3.4074978e+00 4.0138994e+00 4.2186688e+00 3.7302926e+00 3.7070367e+00 4.5111938e+00 4.3210760e+00 3.8236433e+00 3.6087856e+00 3.8098356e+00 4.0164852e+00 3.7049593e+00 1.1269424e-01 7.0017011e-01 9.0506343e-01 1.0426636e+00 2.0181667e-01 4.1209001e-01 8.0093081e-01 2.0181667e-01 3.4080442e-01 4.0125062e-01 3.6259865e-01 9.0029064e-01 3.3808272e-01 4.2268438e-01 6.1135434e-01 2.2608083e-01 6.0948212e-01 2.0061436e-01 6.3164977e-01 3.0482299e-01 3.1902650e+00 2.9267417e+00 3.3545239e+00 2.4065479e+00 3.0300492e+00 2.9028462e+00 3.1166330e+00 1.7073273e+00 3.0369978e+00 2.3091363e+00 1.9242178e+00 2.6129479e+00 2.4148785e+00 3.1074477e+00 2.0138888e+00 2.8680310e+00 2.9053048e+00 2.5042875e+00 2.9165009e+00 2.3038195e+00 3.2116668e+00 2.4221589e+00 3.3110857e+00 3.1060464e+00 2.7333589e+00 2.8520935e+00 3.2480481e+00 3.4313924e+00 2.9094538e+00 1.9103596e+00 2.2042535e+00 2.1040084e+00 2.3086427e+00 3.5048916e+00 2.9048754e+00 2.9119661e+00 3.1440058e+00 2.8212158e+00 2.5048147e+00 2.4054865e+00 2.8016296e+00 3.0087060e+00 2.4071454e+00 1.7108740e+00 2.6040234e+00 2.6035022e+00 2.6047905e+00 2.7176633e+00 1.4222462e+00 2.5057847e+00 4.4195581e+00 3.5098289e+00 4.3311360e+00 4.0067587e+00 4.2149806e+00 5.0390074e+00 2.9109559e+00 4.7273232e+00 4.2124122e+00 4.5405876e+00 3.5250718e+00 3.7139027e+00 3.9284285e+00 3.4150426e+00 3.5404383e+00 3.7302923e+00 3.9113385e+00 5.1434691e+00 5.3373009e+00 3.4049076e+00 4.1330547e+00 3.3170101e+00 5.1417717e+00 3.3168869e+00 4.1189487e+00 4.4302240e+00 3.2165105e+00 3.3123688e+00 4.0139003e+00 4.2362095e+00 4.5418862e+00 4.8784553e+00 4.0170271e+00 3.5083268e+00 4.0022121e+00 4.5797332e+00 4.0245435e+00 3.9092247e+00 3.2127499e+00 3.8383398e+00 4.0332236e+00 3.5687055e+00 3.5098289e+00 4.3229228e+00 4.1350002e+00 3.6463113e+00 3.4177609e+00 3.6219569e+00 3.8236419e+00 3.5076152e+00 6.0202028e-01 1.0008471e+00 1.1133984e+00 1.2085435e-01 4.0125062e-01 7.0548138e-01 1.2085435e-01 4.1210927e-01 3.3813251e-01 4.1317535e-01 8.0093160e-01 4.1210927e-01 4.5147187e-01 7.0184453e-01 2.0121983e-01 7.0088326e-01 2.2573593e-01 6.3164977e-01 2.4170870e-01 3.1712556e+00 2.9203033e+00 3.3425812e+00 2.4054865e+00 3.0228150e+00 2.9023686e+00 3.1131138e+00 1.7053664e+00 3.0276460e+00 2.3090554e+00 1.9156198e+00 2.6109872e+00 2.4094445e+00 3.1056085e+00 2.0122722e+00 2.8520934e+00 2.9050277e+00 2.5027053e+00 2.9125192e+00 2.3027405e+00 3.2109394e+00 2.4160415e+00 3.3084146e+00 3.1042008e+00 2.7243956e+00 2.8394100e+00 3.2369546e+00 3.4247119e+00 2.9077087e+00 1.9065546e+00 2.2031052e+00 2.1025721e+00 2.3063026e+00 3.5041732e+00 2.9047982e+00 2.9102300e+00 3.1338083e+00 2.8152056e+00 2.5042498e+00 2.4049187e+00 2.8014068e+00 3.0065584e+00 2.4051787e+00 1.7073273e+00 2.6035320e+00 2.6027034e+00 2.6039922e+00 2.7127202e+00 1.4197348e+00 2.5048165e+00 4.4189015e+00 3.5095163e+00 4.3257988e+00 4.0057069e+00 4.2135049e+00 5.0324949e+00 2.9108796e+00 4.7221364e+00 4.2099109e+00 4.5353940e+00 3.5215862e+00 3.7118544e+00 3.9240013e+00 3.4147901e+00 3.5401421e+00 3.7282909e+00 3.9092247e+00 5.1365094e+00 5.3314710e+00 3.4038679e+00 4.1286955e+00 3.3168613e+00 5.1347955e+00 3.3142720e+00 4.1161770e+00 4.4243750e+00 3.2143132e+00 3.3110162e+00 4.0124921e+00 4.2289511e+00 4.5343165e+00 4.8661278e+00 4.0156242e+00 3.5063341e+00 4.0016595e+00 4.5675358e+00 4.0235142e+00 3.9076269e+00 3.2116668e+00 3.8321137e+00 4.0301568e+00 3.5598554e+00 3.5095163e+00 4.3201293e+00 4.1322798e+00 3.6413274e+00 3.4154677e+00 3.6188977e+00 3.8226861e+00 3.5071388e+00 7.0096708e-01 8.0004602e-01 5.0855077e-01 4.1420960e-01 2.2608083e-01 5.0855077e-01 1.0008768e+00 3.0474106e-01 4.0127250e-01 1.1527746e+00 1.0000457e+00 4.0127250e-01 4.5783248e-01 6.0948800e-01 4.1317535e-01 8.0008964e-01 3.0482299e-01 4.0127250e-01 3.2104685e+00 3.0024155e+00 3.4059092e+00 2.5048145e+00 3.1026586e+00 3.0005260e+00 3.2022151e+00 1.8108200e+00 3.1025924e+00 2.4028974e+00 2.0417688e+00 2.7025751e+00 2.5062865e+00 3.2007416e+00 2.1027376e+00 2.9057769e+00 3.0015388e+00 2.6003213e+00 3.0043084e+00 2.4017233e+00 3.3039365e+00 2.5015263e+00 3.4013673e+00 3.2002931e+00 2.8019179e+00 2.9040262e+00 3.3045112e+00 3.5038551e+00 3.0015958e+00 2.0020172e+00 2.3035509e+00 2.2041009e+00 2.4010446e+00 3.6011254e+00 3.0015387e+00 3.0025850e+00 3.2040849e+00 2.9029297e+00 2.6009614e+00 2.5022969e+00 2.9005699e+00 3.1008537e+00 2.5011717e+00 1.8179820e+00 2.7009799e+00 2.7004102e+00 2.7008225e+00 2.8010266e+00 1.5160787e+00 2.6010449e+00 4.5093548e+00 3.6039076e+00 4.4060847e+00 4.1014985e+00 4.3050076e+00 5.1081747e+00 3.0045274e+00 4.8044751e+00 4.3019076e+00 4.6117611e+00 3.6062405e+00 3.8032982e+00 4.0063634e+00 3.5066398e+00 3.6202705e+00 3.8119529e+00 4.0019489e+00 5.2097659e+00 5.4087506e+00 3.5019664e+00 4.2090727e+00 3.4073888e+00 5.2088330e+00 3.4037266e+00 4.2046087e+00 4.5046939e+00 3.3041077e+00 3.4034672e+00 4.1044794e+00 4.3051857e+00 4.6074982e+00 4.9181673e+00 4.1061528e+00 3.6008588e+00 4.1002763e+00 4.6187512e+00 4.1110303e+00 4.0017844e+00 3.3039580e+00 3.9080413e+00 4.1118167e+00 3.6188744e+00 3.6039076e+00 4.4067826e+00 4.2136946e+00 3.7147052e+00 3.5048712e+00 3.7054764e+00 3.9103830e+00 3.6025973e+00 3.0026460e-01 1.0001598e+00 9.0029064e-01 6.0202028e-01 1.0001598e+00 1.1281352e+00 7.0000303e-01 6.0052920e-01 1.8012962e+00 9.6574369e-01 6.3178782e-01 4.2270142e-01 1.1005460e+00 3.0026460e-01 9.1422402e-01 4.0004442e-01 8.0004602e-01 3.2225450e+00 3.0091788e+00 3.4142737e+00 2.5659206e+00 3.1121190e+00 3.0065741e+00 3.2080663e+00 1.9795481e+00 3.1095927e+00 2.4291135e+00 2.3151880e+00 2.7129011e+00 2.5826416e+00 3.2051685e+00 2.1273517e+00 2.9165009e+00 3.0077149e+00 2.6132476e+00 3.0422268e+00 2.4403272e+00 3.3124044e+00 2.5166989e+00 3.4115621e+00 3.2044340e+00 2.8105357e+00 2.9137358e+00 3.3135329e+00 3.5115123e+00 3.0089448e+00 2.0634477e+00 2.3669955e+00 2.2798676e+00 2.4222743e+00 3.6065353e+00 3.0077107e+00 3.0095641e+00 3.2119165e+00 2.9352117e+00 2.6080595e+00 2.5371436e+00 2.9126008e+00 3.1051604e+00 2.5254396e+00 2.0316239e+00 2.7143597e+00 2.7050980e+00 2.7084026e+00 2.8082597e+00 1.7626307e+00 2.6129786e+00 4.5202811e+00 3.6136284e+00 4.4137920e+00 4.1051791e+00 4.3125133e+00 5.1149745e+00 3.0264326e+00 4.8090821e+00 4.3074243e+00 4.6242424e+00 3.6169385e+00 3.8113313e+00 4.0160029e+00 3.5235168e+00 3.6464145e+00 3.8279938e+00 4.0062032e+00 5.2173409e+00 5.4162239e+00 3.5202520e+00 4.2206877e+00 3.4219359e+00 5.2156030e+00 3.4146242e+00 4.2116109e+00 4.5097900e+00 3.3150972e+00 3.4115327e+00 4.1123767e+00 4.3106068e+00 4.6148396e+00 4.9296764e+00 4.1159139e+00 3.6049049e+00 4.1030781e+00 4.6336876e+00 4.1247374e+00 4.0056652e+00 3.3131419e+00 3.9194404e+00 4.1265834e+00 3.6428011e+00 3.6136284e+00 4.4157045e+00 4.2295866e+00 3.7344540e+00 3.5196603e+00 3.7152542e+00 3.9242137e+00 3.6086340e+00 1.1055707e+00 1.0030868e+00 7.0000151e-01 1.1055707e+00 1.3018102e+00 8.0245824e-01 7.1621884e-01 1.9078389e+00 1.1896594e+00 7.2044167e-01 5.3943256e-01 1.2089192e+00 4.5147187e-01 1.0776188e+00 5.0043084e-01 9.0506254e-01 3.3079985e+00 3.1046072e+00 3.5056118e+00 2.6709345e+00 3.2081329e+00 3.1065948e+00 3.3043807e+00 2.0901204e+00 3.2052035e+00 2.5276373e+00 2.4267777e+00 2.8091158e+00 2.6904888e+00 3.3041886e+00 2.2241050e+00 3.0065909e+00 3.1056084e+00 2.7155799e+00 3.1440950e+00 2.5451785e+00 3.4078458e+00 2.6152930e+00 3.5111169e+00 3.3045112e+00 2.9070941e+00 3.0065909e+00 3.4069929e+00 3.6059670e+00 3.1068940e+00 2.1702441e+00 2.4737523e+00 2.3880607e+00 2.5238437e+00 3.7056514e+00 3.1056084e+00 3.1055129e+00 3.3051256e+00 3.0372254e+00 2.7067267e+00 2.6397031e+00 3.0142197e+00 3.2037566e+00 2.6278605e+00 2.1424915e+00 2.8148768e+00 2.8047553e+00 2.8077256e+00 2.9066659e+00 1.8682644e+00 2.7127202e+00 4.6142218e+00 3.7103348e+00 4.5074842e+00 4.2035307e+00 4.4083412e+00 5.2074280e+00 3.1239158e+00 4.9041928e+00 4.4055872e+00 4.7149533e+00 3.7103439e+00 3.9081758e+00 4.1095835e+00 3.6188977e+00 3.7328455e+00 3.9187196e+00 4.1037709e+00 5.3087451e+00 5.5089283e+00 3.6218973e+00 4.3127798e+00 3.5155554e+00 5.3076917e+00 3.5109043e+00 4.3070065e+00 4.6043043e+00 3.4107931e+00 3.5076367e+00 4.2085644e+00 4.4044360e+00 4.7071579e+00 5.0144130e+00 4.2110565e+00 3.7038321e+00 4.2031939e+00 4.7176313e+00 4.2169539e+00 4.1034568e+00 3.4087523e+00 4.0110693e+00 4.2176552e+00 3.7262659e+00 3.7103348e+00 4.5099841e+00 4.3199893e+00 3.8223318e+00 3.6159248e+00 3.8096375e+00 4.0163546e+00 3.7058422e+00 3.0026460e-01 6.0964891e-01 0.0000000e+00 5.0043842e-01 3.0482299e-01 4.0246123e-01 8.0254500e-01 5.0043842e-01 5.2133802e-01 7.0556260e-01 2.0181667e-01 7.0008735e-01 3.0026460e-01 6.0948506e-01 2.0181667e-01 3.2490712e+00 3.0153168e+00 3.4297841e+00 2.5067523e+00 3.1166337e+00 3.0027816e+00 3.2112793e+00 1.8068048e+00 3.1183051e+00 2.4116924e+00 2.0138832e+00 2.7116615e+00 2.5059537e+00 3.2048192e+00 2.1144760e+00 2.9351753e+00 3.0063019e+00 2.6019122e+00 3.0106587e+00 2.4030297e+00 3.3125861e+00 2.5120719e+00 3.4068163e+00 3.2029877e+00 2.8162444e+00 2.9267417e+00 3.3252407e+00 3.5189464e+00 3.0077107e+00 2.0051350e+00 2.3037132e+00 2.2028146e+00 2.4058620e+00 3.6044981e+00 3.0062070e+00 3.0107283e+00 3.2237456e+00 2.9105093e+00 2.6052541e+00 2.5062865e+00 2.9018772e+00 3.1056084e+00 2.5048522e+00 1.8082911e+00 2.7043948e+00 2.7029415e+00 2.7046027e+00 2.8091099e+00 1.5248852e+00 2.6055127e+00 4.5209020e+00 3.6112573e+00 4.4212031e+00 4.1056541e+00 4.3138986e+00 5.1255338e+00 3.0133997e+00 4.8167235e+00 4.3081273e+00 4.6319211e+00 3.6205854e+00 3.8114965e+00 4.0212972e+00 3.5173798e+00 3.6449970e+00 3.8299342e+00 4.0081754e+00 5.2290121e+00 5.4254411e+00 3.5039202e+00 4.2264145e+00 3.4198378e+00 5.2270034e+00 3.4138008e+00 4.2149806e+00 4.5183778e+00 3.3145502e+00 3.4118179e+00 4.1129687e+00 4.3210760e+00 4.6261633e+00 4.9512603e+00 4.1165035e+00 3.6051692e+00 4.1014742e+00 4.6540056e+00 4.1257291e+00 4.0071257e+00 3.3129914e+00 3.9274863e+00 4.1301604e+00 3.6542046e+00 3.6112573e+00 4.4192311e+00 4.2328883e+00 3.7399948e+00 3.5155767e+00 3.7180846e+00 3.9250546e+00 3.6083191e+00 5.0436965e-01 3.0026460e-01 6.0017982e-01 3.0482299e-01 3.0017653e-01 9.0506343e-01 6.0000317e-01 4.5783248e-01 7.4269314e-01 2.4195741e-01 6.0948506e-01 4.0122873e-01 5.0855077e-01 2.0061436e-01 3.5243030e+00 3.3064692e+00 3.7147036e+00 2.8028227e+00 3.4072759e+00 3.3010449e+00 3.5048841e+00 2.1026764e+00 3.4081977e+00 2.7042302e+00 2.3098753e+00 3.0045117e+00 2.8027924e+00 3.5019450e+00 2.4045982e+00 3.2157547e+00 3.3025861e+00 2.9005886e+00 3.3047156e+00 2.7010554e+00 3.6058037e+00 2.8042692e+00 3.7029937e+00 3.5011559e+00 3.1065954e+00 3.2116669e+00 3.6121048e+00 3.8091015e+00 3.3031148e+00 2.3014285e+00 2.6014645e+00 2.5011992e+00 2.7018905e+00 3.9020189e+00 3.3025600e+00 3.3044825e+00 3.5110031e+00 3.2044340e+00 2.9018587e+00 2.8023124e+00 3.2006932e+00 3.4022345e+00 2.8016296e+00 2.1039819e+00 3.0015958e+00 3.0009948e+00 3.0016466e+00 3.1034780e+00 1.8068049e+00 2.9019412e+00 4.8119571e+00 3.9055005e+00 4.7117433e+00 4.4027872e+00 4.6074923e+00 5.4154953e+00 3.3059205e+00 5.1096877e+00 4.6042055e+00 4.9184662e+00 3.9101579e+00 4.1056576e+00 4.3111747e+00 3.8086187e+00 3.9240074e+00 4.1158326e+00 4.3040379e+00 5.5178488e+00 5.7157885e+00 3.8018678e+00 4.5144444e+00 3.7097243e+00 5.5166376e+00 3.7063915e+00 4.5079295e+00 4.8103281e+00 3.6066590e+00 3.7054748e+00 4.4067833e+00 4.6117275e+00 4.9151622e+00 5.2317566e+00 4.4087821e+00 3.9022961e+00 4.4006562e+00 4.9323259e+00 4.4141504e+00 4.3034963e+00 3.6059708e+00 4.2144276e+00 4.4165186e+00 3.9284285e+00 3.9055005e+00 4.7106152e+00 4.5183778e+00 4.0209837e+00 3.8074712e+00 4.0090032e+00 4.2134002e+00 3.9039579e+00 6.0964891e-01 1.1019501e+00 4.0125062e-01 5.0000761e-01 1.2632947e+00 1.1001012e+00 5.2491131e-01 6.1135434e-01 7.1621884e-01 4.2268438e-01 9.0026543e-01 2.4170870e-01 5.0043084e-01 3.4064574e+00 3.2033141e+00 3.6042703e+00 2.7067267e+00 3.3031847e+00 3.2012079e+00 3.4035361e+00 2.0125822e+00 3.3019706e+00 2.6055127e+00 2.2404570e+00 2.9047685e+00 2.7070958e+00 3.4014441e+00 2.3056303e+00 3.1043374e+00 3.2029748e+00 2.8006755e+00 3.2059945e+00 2.6027034e+00 3.5064150e+00 2.7028014e+00 3.6021536e+00 3.4005708e+00 3.0020583e+00 3.1034908e+00 3.5031921e+00 3.7043162e+00 3.2030081e+00 2.2031888e+00 2.5048145e+00 2.4051640e+00 2.6022353e+00 3.8020808e+00 3.2029748e+00 3.2045605e+00 3.4036086e+00 3.1036832e+00 2.8021575e+00 2.7039988e+00 3.1011640e+00 3.3016475e+00 2.7022579e+00 2.0191796e+00 2.9020892e+00 2.9010579e+00 2.9018587e+00 3.0016913e+00 1.7203066e+00 2.8022905e+00 4.7127831e+00 3.8062227e+00 4.6064153e+00 4.3024456e+00 4.5071341e+00 5.3066177e+00 3.2074507e+00 5.0034627e+00 4.5024143e+00 4.8135231e+00 3.8088290e+00 4.0049892e+00 4.2080447e+00 3.7100251e+00 3.8270894e+00 4.0163858e+00 4.2028588e+00 5.4079977e+00 5.6075453e+00 3.7029588e+00 4.4113160e+00 3.6111044e+00 5.4066727e+00 3.6058057e+00 4.4062018e+00 4.7037812e+00 3.5065182e+00 3.6056307e+00 4.3065776e+00 4.5036239e+00 4.8058364e+00 5.1131156e+00 4.3088094e+00 3.8014142e+00 4.3005452e+00 4.8156922e+00 4.3151195e+00 4.2027764e+00 3.5064276e+00 4.1095026e+00 4.3155223e+00 3.8226872e+00 3.8062227e+00 4.6088777e+00 4.4178507e+00 3.9190516e+00 3.7073875e+00 3.9078043e+00 4.1144923e+00 3.8043348e+00 5.0043842e-01 3.0482299e-01 4.0246123e-01 8.0254500e-01 5.0043842e-01 5.2133802e-01 7.0556260e-01 2.0181667e-01 7.0008735e-01 3.0026460e-01 6.0948506e-01 2.0181667e-01 3.2490712e+00 3.0153168e+00 3.4297841e+00 2.5067523e+00 3.1166337e+00 3.0027816e+00 3.2112793e+00 1.8068048e+00 3.1183051e+00 2.4116924e+00 2.0138832e+00 2.7116615e+00 2.5059537e+00 3.2048192e+00 2.1144760e+00 2.9351753e+00 3.0063019e+00 2.6019122e+00 3.0106587e+00 2.4030297e+00 3.3125861e+00 2.5120719e+00 3.4068163e+00 3.2029877e+00 2.8162444e+00 2.9267417e+00 3.3252407e+00 3.5189464e+00 3.0077107e+00 2.0051350e+00 2.3037132e+00 2.2028146e+00 2.4058620e+00 3.6044981e+00 3.0062070e+00 3.0107283e+00 3.2237456e+00 2.9105093e+00 2.6052541e+00 2.5062865e+00 2.9018772e+00 3.1056084e+00 2.5048522e+00 1.8082911e+00 2.7043948e+00 2.7029415e+00 2.7046027e+00 2.8091099e+00 1.5248852e+00 2.6055127e+00 4.5209020e+00 3.6112573e+00 4.4212031e+00 4.1056541e+00 4.3138986e+00 5.1255338e+00 3.0133997e+00 4.8167235e+00 4.3081273e+00 4.6319211e+00 3.6205854e+00 3.8114965e+00 4.0212972e+00 3.5173798e+00 3.6449970e+00 3.8299342e+00 4.0081754e+00 5.2290121e+00 5.4254411e+00 3.5039202e+00 4.2264145e+00 3.4198378e+00 5.2270034e+00 3.4138008e+00 4.2149806e+00 4.5183778e+00 3.3145502e+00 3.4118179e+00 4.1129687e+00 4.3210760e+00 4.6261633e+00 4.9512603e+00 4.1165035e+00 3.6051692e+00 4.1014742e+00 4.6540056e+00 4.1257291e+00 4.0071257e+00 3.3129914e+00 3.9274863e+00 4.1301604e+00 3.6542046e+00 3.6112573e+00 4.4192311e+00 4.2328883e+00 3.7399948e+00 3.5155767e+00 3.7180846e+00 3.9250546e+00 3.6083191e+00 7.0470720e-01 6.3164977e-01 7.0000303e-01 2.0000000e-01 6.4049114e-01 8.7212232e-01 4.0004442e-01 8.5437440e-01 2.2573593e-01 9.3308853e-01 6.0184622e-01 3.5152865e+00 3.2379971e+00 3.6729302e+00 2.7052554e+00 3.3425813e+00 3.2040843e+00 3.4230889e+00 2.0021220e+00 3.3530528e+00 2.6055127e+00 2.2051638e+00 2.9154879e+00 2.7227228e+00 3.4118179e+00 2.3143923e+00 3.1902650e+00 3.2048191e+00 2.8089346e+00 3.2223766e+00 2.6060092e+00 3.5107904e+00 2.7333577e+00 3.6167495e+00 3.4109217e+00 3.0488339e+00 3.1712556e+00 3.5658221e+00 3.7426726e+00 3.2127498e+00 2.2186491e+00 2.5049231e+00 2.4052960e+00 2.6139440e+00 3.8063158e+00 3.2036084e+00 3.2143157e+00 3.4603347e+00 3.1318587e+00 2.8056557e+00 2.7050980e+00 3.1020681e+00 3.3136174e+00 2.7116685e+00 2.0027889e+00 2.9047842e+00 2.9057760e+00 2.9065359e+00 3.0276459e+00 1.7091578e+00 2.8077256e+00 4.7169309e+00 3.8081280e+00 4.6399369e+00 4.3088507e+00 4.5162248e+00 5.3501952e+00 3.2067991e+00 5.0370912e+00 4.5175831e+00 4.8468186e+00 3.8290678e+00 4.0170262e+00 4.2347722e+00 3.7111714e+00 3.8289857e+00 4.0283196e+00 4.2155430e+00 5.4550926e+00 5.6472422e+00 3.7064735e+00 4.4381718e+00 3.6121030e+00 5.4538016e+00 3.6205857e+00 4.4231445e+00 4.7408825e+00 3.5189464e+00 3.6135011e+00 4.3151164e+00 4.5490925e+00 4.8546830e+00 5.1966534e+00 4.3173271e+00 3.8129545e+00 4.3038527e+00 4.8962803e+00 4.3214438e+00 4.2123903e+00 3.5127693e+00 4.1469662e+00 4.3342207e+00 3.8751227e+00 3.8081280e+00 4.6262568e+00 4.4345825e+00 3.9485180e+00 3.7201181e+00 3.9257254e+00 4.1203162e+00 3.8072915e+00 2.0181667e-01 1.1055799e+00 7.0016860e-01 4.0006662e-01 4.5147187e-01 4.1212852e-01 4.0002221e-01 5.0043084e-01 3.0474106e-01 1.2085435e-01 3.2280983e+00 3.0080445e+00 3.4166801e+00 2.5073304e+00 3.1087541e+00 3.0016255e+00 3.2064005e+00 1.8128544e+00 3.1091921e+00 2.4076934e+00 2.0429861e+00 2.7070770e+00 2.5077793e+00 3.2025221e+00 2.1086021e+00 2.9185909e+00 3.0040552e+00 2.6009247e+00 3.0080768e+00 2.4028385e+00 3.3086417e+00 2.5058827e+00 3.4038679e+00 3.2013290e+00 2.8077473e+00 2.9137660e+00 3.3136458e+00 3.5107924e+00 3.0045274e+00 2.0036964e+00 2.3048725e+00 2.2049827e+00 2.4032211e+00 3.6028345e+00 3.0040403e+00 3.0066661e+00 3.2127504e+00 2.9065741e+00 2.6030847e+00 2.5048249e+00 2.9013288e+00 3.1029264e+00 2.5029614e+00 1.8201043e+00 2.7027522e+00 2.7015465e+00 2.7026433e+00 2.8042851e+00 1.5256523e+00 2.6032253e+00 4.5160443e+00 3.6080467e+00 4.4135519e+00 4.1035779e+00 4.3098000e+00 5.1168009e+00 3.0096881e+00 4.8103297e+00 4.3048676e+00 4.6223708e+00 3.6136097e+00 3.8074712e+00 4.0139003e+00 3.5128896e+00 3.6349183e+00 3.8220063e+00 4.0049433e+00 5.2194303e+00 5.4171979e+00 3.5033669e+00 4.2181241e+00 3.4145410e+00 5.2178541e+00 3.4088042e+00 4.2099019e+00 4.5111938e+00 3.3094784e+00 3.4078458e+00 4.1090316e+00 4.3126257e+00 4.6165627e+00 4.9348334e+00 4.1118265e+00 3.6027619e+00 4.1008192e+00 4.6366757e+00 4.1194553e+00 4.0043991e+00 3.3087928e+00 3.9177721e+00 4.1218428e+00 3.6374332e+00 3.6080467e+00 4.4133507e+00 4.2243717e+00 3.7282925e+00 3.5105217e+00 3.7119499e+00 3.9187675e+00 3.6057072e+00 1.2012865e+00 6.0184622e-01 3.3808272e-01 6.0184934e-01 5.0043084e-01 3.3818226e-01 4.1212852e-01 3.0922892e-01 2.0121983e-01 3.4273160e+00 3.2064011e+00 3.6161317e+00 2.7056828e+00 3.3075153e+00 3.2008118e+00 3.4044261e+00 2.0113827e+00 3.3090710e+00 2.6035236e+00 2.2398619e+00 2.9035670e+00 2.7083020e+00 3.4017079e+00 2.3034787e+00 3.1174706e+00 3.2019092e+00 2.8008297e+00 3.2066700e+00 2.6023240e+00 3.5046442e+00 2.7041827e+00 3.6031099e+00 3.4011658e+00 3.0071110e+00 3.1127326e+00 3.5134157e+00 3.7092355e+00 3.2025439e+00 2.2031052e+00 2.5042875e+00 2.4048325e+00 2.6019131e+00 3.8016620e+00 3.2018790e+00 3.2036084e+00 3.4118203e+00 3.1063566e+00 2.8013151e+00 2.7029498e+00 3.1008327e+00 3.3019518e+00 2.7019892e+00 2.0181988e+00 2.9013773e+00 2.9007142e+00 2.9012240e+00 3.0034647e+00 1.7168003e+00 2.8015399e+00 4.7103355e+00 3.8044833e+00 4.6117631e+00 4.3023732e+00 4.5065283e+00 5.3163061e+00 3.2051927e+00 5.0102923e+00 4.5041827e+00 4.8177760e+00 3.8091017e+00 4.0050028e+00 4.2105704e+00 3.7073402e+00 3.8208501e+00 4.0138272e+00 4.2036880e+00 5.4187310e+00 5.6164039e+00 3.7027275e+00 4.4135513e+00 3.6080195e+00 5.4177192e+00 3.6056365e+00 4.4072751e+00 4.7109359e+00 3.5056751e+00 3.6045028e+00 4.3058539e+00 4.5127175e+00 4.8161488e+00 5.1342237e+00 4.3075896e+00 3.8021528e+00 4.3006308e+00 4.8339900e+00 4.3122441e+00 4.2030792e+00 3.5048429e+00 4.1140184e+00 4.3148937e+00 3.8271256e+00 3.8044833e+00 4.6097143e+00 4.4165186e+00 3.9191998e+00 3.7067060e+00 3.9080455e+00 4.1114854e+00 3.8031381e+00 9.0000091e-01 1.2014191e+00 1.5025345e+00 7.0088477e-01 1.5012926e+00 9.0000136e-01 1.4092540e+00 1.0030724e+00 3.4932678e+00 3.2284356e+00 3.6579694e+00 2.7029237e+00 3.3320310e+00 3.2025221e+00 3.4171529e+00 2.0008116e+00 3.3407229e+00 2.6032740e+00 2.2005685e+00 2.9103582e+00 2.7153679e+00 3.4082220e+00 2.3087475e+00 3.1706684e+00 3.2030687e+00 2.8057704e+00 3.2157547e+00 2.6035236e+00 3.5075879e+00 2.7233837e+00 3.6121030e+00 3.4076329e+00 3.0364247e+00 3.1548602e+00 3.5517240e+00 3.7328844e+00 3.2086545e+00 2.2116271e+00 2.5026949e+00 2.4028972e+00 2.6089340e+00 3.8042764e+00 3.2022967e+00 3.2108192e+00 3.4468872e+00 3.1231713e+00 2.8035152e+00 2.7029238e+00 3.1011647e+00 3.3095196e+00 2.7074599e+00 2.0008921e+00 2.9028462e+00 2.9036791e+00 2.9040745e+00 3.0197997e+00 1.7043730e+00 2.8047771e+00 4.7130344e+00 3.8056232e+00 4.6318991e+00 4.3063824e+00 4.5121922e+00 5.3416858e+00 3.2045522e+00 5.0302179e+00 4.5134527e+00 4.8380714e+00 3.8218532e+00 4.0124930e+00 4.2269486e+00 3.7079008e+00 3.8220112e+00 4.0214147e+00 4.2115853e+00 5.4465234e+00 5.6393868e+00 3.7043105e+00 4.4299700e+00 3.6085945e+00 5.4449998e+00 3.6148636e+00 4.4178341e+00 4.7331065e+00 3.5134671e+00 3.6094821e+00 4.3111775e+00 4.5398308e+00 4.8449119e+00 5.1826640e+00 4.3129030e+00 3.8093617e+00 4.3026669e+00 4.8806417e+00 4.3164776e+00 4.2091204e+00 3.5088587e+00 4.1368711e+00 4.3264627e+00 3.8592376e+00 3.8056232e+00 4.6204067e+00 4.4269727e+00 3.9374314e+00 3.7145622e+00 3.9192263e+00 4.1154804e+00 3.8050056e+00 6.1288055e-01 7.7603846e-01 4.0127250e-01 7.4329414e-01 2.0061436e-01 9.0508712e-01 6.0000635e-01 3.5152864e+00 3.2379970e+00 3.6729302e+00 2.7058598e+00 3.3425838e+00 3.2040874e+00 3.4230885e+00 2.0034894e+00 3.3530533e+00 2.6055423e+00 2.2123846e+00 2.9154880e+00 2.7237438e+00 3.4118184e+00 2.3143951e+00 3.1902650e+00 3.2048192e+00 2.8089552e+00 3.2228316e+00 2.6061975e+00 3.5107904e+00 2.7333644e+00 3.6167885e+00 3.4109240e+00 3.0488346e+00 3.1712557e+00 3.5658240e+00 3.7426726e+00 3.2127504e+00 2.2188249e+00 2.5053901e+00 2.4058634e+00 2.6139732e+00 3.8063206e+00 3.2036085e+00 3.2143126e+00 3.4603347e+00 3.1321581e+00 2.8056558e+00 2.7052554e+00 3.1021033e+00 3.3136175e+00 2.7117356e+00 2.0053411e+00 2.9048017e+00 2.9057761e+00 2.9065368e+00 3.0276467e+00 1.7105814e+00 2.8077315e+00 4.7169308e+00 3.8081328e+00 4.6399369e+00 4.3088509e+00 4.5162248e+00 5.3501952e+00 3.2068686e+00 5.0370912e+00 4.5175965e+00 4.8468145e+00 3.8290678e+00 4.0170299e+00 4.2347722e+00 3.7112059e+00 3.8289870e+00 4.0283196e+00 4.2155430e+00 5.4550814e+00 5.6472442e+00 3.7067060e+00 4.4381718e+00 3.6121048e+00 5.4538018e+00 3.6205918e+00 4.4231444e+00 4.7408825e+00 3.5189484e+00 3.6135011e+00 4.3151171e+00 4.5490925e+00 4.8546834e+00 5.1966394e+00 4.3173279e+00 3.8129558e+00 4.3038600e+00 4.8962803e+00 4.3214431e+00 4.2123903e+00 3.5127694e+00 4.1469662e+00 4.3342207e+00 3.8751227e+00 3.8081328e+00 4.6262568e+00 4.4345823e+00 3.9485180e+00 3.7201522e+00 3.9257254e+00 4.1203153e+00 3.8072915e+00 3.4085233e-01 5.0517282e-01 4.1210927e-01 4.5847767e-01 4.1317535e-01 4.0243965e-01 3.1409605e+00 2.9078360e+00 3.3230621e+00 2.4077390e+00 3.0097979e+00 2.9003941e+00 3.1042002e+00 1.7227897e+00 3.0135090e+00 2.3017319e+00 1.9755996e+00 2.6019350e+00 2.4142039e+00 3.1015567e+00 2.0014192e+00 2.8264551e+00 2.9006366e+00 2.5011717e+00 2.9082658e+00 2.3033727e+00 3.2022157e+00 2.4051094e+00 3.3034165e+00 3.1014454e+00 2.7104802e+00 2.8188502e+00 3.2195779e+00 3.4112824e+00 2.9016560e+00 1.9053006e+00 2.2068965e+00 2.1085395e+00 2.3018945e+00 3.5009585e+00 2.9005880e+00 2.9020766e+00 3.1165913e+00 2.8092629e+00 2.5004154e+00 2.4029432e+00 2.8007533e+00 3.0017918e+00 2.4022355e+00 1.7369589e+00 2.6007937e+00 2.6003442e+00 2.6005344e+00 2.7044628e+00 1.4329832e+00 2.5008032e+00 4.4064393e+00 3.5021596e+00 4.3131639e+00 4.0016670e+00 4.2045223e+00 5.0200323e+00 2.9028411e+00 4.7130517e+00 4.2044861e+00 4.5172866e+00 3.5073617e+00 3.7038321e+00 3.9101623e+00 3.4039470e+00 3.5128093e+00 3.7092301e+00 3.9033549e+00 5.1227972e+00 5.3193887e+00 3.4029615e+00 4.1123595e+00 3.3040255e+00 5.1222477e+00 3.3043123e+00 4.1063328e+00 4.4139149e+00 3.2038047e+00 3.3025879e+00 4.0039164e+00 4.2170349e+00 4.5206139e+00 4.8441812e+00 4.0049702e+00 3.5022104e+00 4.0005674e+00 4.5418878e+00 4.0077003e+00 3.9024858e+00 3.2025221e+00 3.8146102e+00 4.0114630e+00 3.5261349e+00 3.5021596e+00 4.3081194e+00 4.1123594e+00 3.6158324e+00 3.4049076e+00 3.6064417e+00 3.8069566e+00 3.5014492e+00 8.0923926e-01 3.0474106e-01 6.5724028e-01 4.0246123e-01 5.6371422e-01 2.8500310e+00 2.6110761e+00 3.0277528e+00 2.1510447e+00 2.7141512e+00 2.6027937e+00 2.8070667e+00 1.5787180e+00 2.7167342e+00 2.0166118e+00 1.9318287e+00 2.3071806e+00 2.1715812e+00 2.8031215e+00 1.7145956e+00 2.5336675e+00 2.6035547e+00 2.2074446e+00 2.6319765e+00 2.0282636e+00 2.9076123e+00 2.1122780e+00 3.0080768e+00 2.8027924e+00 2.4144060e+00 2.5243969e+00 2.9241685e+00 3.1150226e+00 2.6049377e+00 1.6499744e+00 1.9530826e+00 1.8666228e+00 2.0130304e+00 3.2033374e+00 2.6035250e+00 2.6059866e+00 2.8207213e+00 2.5287261e+00 2.2032583e+00 2.1244184e+00 2.5066544e+00 2.7033232e+00 2.1157724e+00 1.6395342e+00 2.3072196e+00 2.3018945e+00 2.3035850e+00 2.4072314e+00 1.3788456e+00 2.2062031e+00 4.1150297e+00 3.2079717e+00 4.0170857e+00 3.7033716e+00 3.9093672e+00 4.7228082e+00 2.6158579e+00 4.4145659e+00 3.9067187e+00 4.2256164e+00 3.2143454e+00 3.4081069e+00 3.6159248e+00 3.1148584e+00 3.2358776e+00 3.4219579e+00 3.6052692e+00 4.8260874e+00 5.0225486e+00 3.1131211e+00 3.8201108e+00 3.0142352e+00 4.8248264e+00 3.0102191e+00 3.8104451e+00 4.1158426e+00 2.9100849e+00 3.0073054e+00 3.7087638e+00 3.9191144e+00 4.2237272e+00 4.5500784e+00 3.7114840e+00 3.2036323e+00 3.7015743e+00 4.2506870e+00 3.7186993e+00 3.6043148e+00 2.9081165e+00 3.5216379e+00 3.7226348e+00 3.2449757e+00 3.2079717e+00 4.0139105e+00 3.8249612e+00 3.3311289e+00 3.1134242e+00 3.3125194e+00 3.5179632e+00 3.2049019e+00 8.0051115e-01 2.2573593e-01 7.1621884e-01 3.0482299e-01 3.3530529e+00 3.1135637e+00 3.5317001e+00 2.6021962e+00 3.2157548e+00 3.1011640e+00 3.3083865e+00 1.9014069e+00 3.2199554e+00 2.5036852e+00 2.1054816e+00 2.8056557e+00 2.6057308e+00 3.3035252e+00 2.2049636e+00 3.0369970e+00 3.1023768e+00 2.7016498e+00 3.1076516e+00 2.5011992e+00 3.4059088e+00 2.6097152e+00 3.5056297e+00 3.3028597e+00 2.9166917e+00 3.0276459e+00 3.4273156e+00 3.6176286e+00 3.1043337e+00 2.1032882e+00 2.4011650e+00 2.3009622e+00 2.5032633e+00 3.7024058e+00 3.1022094e+00 3.1056121e+00 3.3243222e+00 3.0101957e+00 2.7018643e+00 2.6020065e+00 3.0005955e+00 3.2040843e+00 2.6027120e+00 1.9019962e+00 2.8015673e+00 2.8013346e+00 2.8018959e+00 2.9083044e+00 1.6052507e+00 2.7022567e+00 4.6121162e+00 3.7052383e+00 4.5194334e+00 4.2036849e+00 4.4088275e+00 5.2263180e+00 3.1053076e+00 4.9177739e+00 4.4072684e+00 4.7260117e+00 3.7138970e+00 3.9076272e+00 4.1167962e+00 3.6081590e+00 3.7238338e+00 3.9176170e+00 4.1063328e+00 5.3296625e+00 5.5255577e+00 3.6022190e+00 4.3201293e+00 3.5092121e+00 5.3285444e+00 3.5088064e+00 4.3111749e+00 4.6192198e+00 3.4084525e+00 3.5063337e+00 4.2079639e+00 4.4229098e+00 4.7273231e+00 5.0541259e+00 4.2099019e+00 3.7043105e+00 4.2011108e+00 4.7534769e+00 4.2147199e+00 4.1050714e+00 3.4064570e+00 4.0228303e+00 4.2200398e+00 3.7407842e+00 3.7052383e+00 4.5139612e+00 4.3214432e+00 3.8271242e+00 3.6094426e+00 3.8122429e+00 4.0138280e+00 3.7039439e+00 6.3178534e-01 2.0121983e-01 5.0043084e-01 3.1326249e+00 2.9095058e+00 3.3192760e+00 2.4306373e+00 3.0110559e+00 2.9028946e+00 3.1074604e+00 1.7872757e+00 3.0111989e+00 2.3143923e+00 2.0898615e+00 2.6089349e+00 2.4398792e+00 3.1033306e+00 2.0139907e+00 2.8220753e+00 2.9050462e+00 2.5045154e+00 2.9220490e+00 2.3159976e+00 3.2100379e+00 2.4095513e+00 3.3067017e+00 3.1022615e+00 2.7099669e+00 2.8165723e+00 3.2163877e+00 3.4125151e+00 2.9058641e+00 1.9245956e+00 2.2287984e+00 2.1344529e+00 2.3089795e+00 3.5039202e+00 2.9050287e+00 2.9078401e+00 3.1149135e+00 2.8183214e+00 2.5042875e+00 2.4160514e+00 2.8047612e+00 3.0036601e+00 2.4102273e+00 1.8223604e+00 2.6061038e+00 2.6023240e+00 2.6040822e+00 2.7058598e+00 1.5384093e+00 2.5058827e+00 4.4178532e+00 3.5098740e+00 4.3151587e+00 4.0041429e+00 4.2110099e+00 5.0184788e+00 2.9154880e+00 4.7114737e+00 4.2061525e+00 4.5248210e+00 3.5155767e+00 3.7089995e+00 3.9157422e+00 3.4167041e+00 3.5401921e+00 3.7249704e+00 3.9056466e+00 5.1213055e+00 5.3189433e+00 3.4098171e+00 4.1203252e+00 3.3172667e+00 5.1196436e+00 3.3110366e+00 4.1111102e+00 4.4124656e+00 3.2115770e+00 3.3091938e+00 4.0103680e+00 4.2141675e+00 4.5185015e+00 4.8383751e+00 4.0135080e+00 3.5035589e+00 4.0015001e+00 4.5406852e+00 4.0218666e+00 3.9049967e+00 3.2103515e+00 3.8201314e+00 4.0245707e+00 3.5427188e+00 3.5098740e+00 4.3149009e+00 4.1273075e+00 3.6322643e+00 3.4139979e+00 3.6137088e+00 3.8212216e+00 3.5066417e+00 7.1621748e-01 4.0002221e-01 3.3858048e+00 3.1257747e+00 3.5528332e+00 2.6049377e+00 3.2291581e+00 3.1026235e+00 3.3158954e+00 1.9043238e+00 3.2362541e+00 2.5062158e+00 2.1151984e+00 2.8111676e+00 2.6144115e+00 3.3074459e+00 2.2106051e+00 3.0644792e+00 3.1042002e+00 2.7046286e+00 3.1155579e+00 2.5035275e+00 3.4095576e+00 2.6210983e+00 3.5110555e+00 3.3064076e+00 2.9323802e+00 3.0497665e+00 3.4467650e+00 3.6304824e+00 3.1087162e+00 2.1099919e+00 2.4034951e+00 2.3034398e+00 2.5081992e+00 3.7045399e+00 3.1036554e+00 3.1105454e+00 3.3425812e+00 3.0208515e+00 2.7039990e+00 2.6042124e+00 3.0014077e+00 3.2086215e+00 2.6068616e+00 1.9064532e+00 2.8033825e+00 2.8033607e+00 2.8042643e+00 2.9174390e+00 1.6121856e+00 2.7050791e+00 4.6165570e+00 3.7079065e+00 4.5303834e+00 4.2064764e+00 4.4135512e+00 5.2388103e+00 3.1079784e+00 4.9275471e+00 4.4124760e+00 4.7382279e+00 3.7227931e+00 3.9129335e+00 4.1268500e+00 3.6117351e+00 3.7315577e+00 3.9257254e+00 4.1111068e+00 5.3430927e+00 5.5370582e+00 3.6046347e+00 4.3307527e+00 3.5130597e+00 5.3416790e+00 3.5154388e+00 4.3179254e+00 4.6302391e+00 3.4146546e+00 3.5107904e+00 4.2125004e+00 4.4361489e+00 4.7415152e+00 5.0768435e+00 4.2149814e+00 3.7084460e+00 4.2023583e+00 4.7769945e+00 4.2205945e+00 4.1089343e+00 3.4107328e+00 4.0362383e+00 4.2295174e+00 3.7618281e+00 3.7079065e+00 4.5213131e+00 4.3307527e+00 3.8409517e+00 3.6158715e+00 3.8200965e+00 4.0195882e+00 3.7063858e+00 4.1210927e-01 3.2157661e+00 3.0055754e+00 3.4095823e+00 2.5182899e+00 3.1060146e+00 3.0020171e+00 3.2051958e+00 1.8468437e+00 3.1049591e+00 2.4099079e+00 2.1180305e+00 2.7069308e+00 2.5226256e+00 3.2022186e+00 2.1097489e+00 2.9102819e+00 3.0041469e+00 2.6022650e+00 3.0136614e+00 2.4087525e+00 3.3085287e+00 2.5053901e+00 3.4040883e+00 3.2011770e+00 2.8045980e+00 2.9078384e+00 3.3077457e+00 3.5074140e+00 3.0043867e+00 2.0123013e+00 2.3159429e+00 2.2186309e+00 2.4051787e+00 3.6030023e+00 3.0041461e+00 3.0063027e+00 3.2075252e+00 2.9100849e+00 2.6032671e+00 2.5097006e+00 2.9028412e+00 3.1024718e+00 2.5058120e+00 1.8685011e+00 2.7040002e+00 2.7016556e+00 2.7029487e+00 2.8031364e+00 1.5747356e+00 2.6040007e+00 4.5158117e+00 3.6083256e+00 4.4100325e+00 4.1032589e+00 4.3091726e+00 5.1114855e+00 3.0117223e+00 4.8065772e+00 4.3039464e+00 4.6187506e+00 3.6121095e+00 3.8069169e+00 4.0114753e+00 3.5138377e+00 3.6350529e+00 3.8212252e+00 4.0040508e+00 5.2135438e+00 5.4123528e+00 3.5063866e+00 4.2155461e+00 3.4147661e+00 5.2119900e+00 3.4083227e+00 4.2084707e+00 4.5071259e+00 3.3090897e+00 3.4075560e+00 4.1085724e+00 4.3075896e+00 4.6108642e+00 4.9236635e+00 4.1113689e+00 3.6022523e+00 4.1009647e+00 4.6262707e+00 4.1190929e+00 4.0037820e+00 3.3086298e+00 3.9141023e+00 4.1202674e+00 3.6321858e+00 3.6083256e+00 4.4117993e+00 4.2229640e+00 3.7257625e+00 3.5107118e+00 3.7106642e+00 3.9184747e+00 3.6056703e+00 3.3320214e+00 3.1087156e+00 3.5191298e+00 2.6048201e+00 3.2097208e+00 3.1014199e+00 3.3064692e+00 1.9064149e+00 3.2109426e+00 2.5061784e+00 2.1231492e+00 2.8062729e+00 2.6052659e+00 3.3025806e+00 2.2069764e+00 3.0213628e+00 3.1034889e+00 2.7008785e+00 3.1069083e+00 2.5018386e+00 3.4076243e+00 2.6061038e+00 3.5039680e+00 3.3015400e+00 2.9090661e+00 3.0158419e+00 3.4158824e+00 3.6117739e+00 3.1042038e+00 2.1025721e+00 2.4028385e+00 2.3026344e+00 2.5028039e+00 3.7026090e+00 3.1034538e+00 3.1060427e+00 3.3145497e+00 3.0064351e+00 2.7026184e+00 2.6035547e+00 3.0010106e+00 3.2029877e+00 2.6024546e+00 1.9099608e+00 2.8022622e+00 2.8013859e+00 2.8022964e+00 2.9047883e+00 1.6144390e+00 2.7027522e+00 4.6146429e+00 3.7070840e+00 4.5144445e+00 4.2034836e+00 4.4092638e+00 5.2185417e+00 3.1080879e+00 4.9117250e+00 4.4052231e+00 4.7224998e+00 3.7130492e+00 3.9071930e+00 4.1140176e+00 3.6112039e+00 3.7307535e+00 3.9200662e+00 4.1050716e+00 5.3212806e+00 5.5187164e+00 3.6026912e+00 4.3179254e+00 3.5126721e+00 5.3198415e+00 3.5083463e+00 4.3098506e+00 4.6126508e+00 3.4087523e+00 3.5071392e+00 4.2084730e+00 4.4144909e+00 4.7184838e+00 5.0381916e+00 4.2109654e+00 3.7029588e+00 4.2008334e+00 4.7393168e+00 4.2176488e+00 4.1043916e+00 3.4078439e+00 4.0181863e+00 4.2205945e+00 3.7363783e+00 3.7070840e+00 4.5130589e+00 4.3227927e+00 3.8267268e+00 3.6097220e+00 3.8114954e+00 4.0168944e+00 3.7050916e+00 6.0017982e-01 2.0181667e-01 1.5160570e+00 5.2133802e-01 1.3002451e+00 7.0008584e-01 2.1344529e+00 4.1212852e-01 1.8029854e+00 2.0342311e+00 1.1019599e+00 1.1393620e+00 9.0026497e-01 1.4543172e+00 3.3813251e-01 1.4000061e+00 1.2053003e+00 1.0426638e+00 1.4134492e+00 1.1005364e+00 9.3424697e-01 7.8890806e-01 9.0142636e-01 6.1119558e-01 4.1315633e-01 4.0125062e-01 3.6452132e-01 1.0001753e+00 1.4158897e+00 1.5195166e+00 1.5300146e+00 1.2201636e+00 1.0039209e+00 1.6000032e+00 1.0000457e+00 3.0017653e-01 9.3329055e-01 1.4017696e+00 1.5061610e+00 1.5012947e+00 9.0002570e-01 1.2124837e+00 2.0445123e+00 1.4012283e+00 1.3008855e+00 1.3009222e+00 8.0291749e-01 2.0440118e+00 1.3027556e+00 1.3788457e+00 1.2029161e+00 1.2089253e+00 9.3446811e-01 1.1298636e+00 1.9014076e+00 2.1006232e+00 1.6001224e+00 1.1139906e+00 1.4544336e+00 6.3912709e-01 7.1183012e-01 8.5409862e-01 1.3086191e+00 1.2638465e+00 9.2745734e-01 8.1117067e-01 2.0027889e+00 2.2028146e+00 1.1270327e+00 1.0776190e+00 1.4019372e+00 2.0011307e+00 7.2044167e-01 1.0208709e+00 1.3002450e+00 8.0488008e-01 9.0145141e-01 9.4622126e-01 1.1000289e+00 1.4009513e+00 1.7086186e+00 9.7694377e-01 7.0911112e-01 1.0224133e+00 1.4220925e+00 1.0923537e+00 8.2631334e-01 1.0008620e+00 7.8886139e-01 1.0777307e+00 9.0140221e-01 1.2029161e+00 1.2362755e+00 1.1897289e+00 9.0534502e-01 7.9871893e-01 6.5724028e-01 9.8998705e-01 1.1010807e+00 5.2133179e-01 1.0171340e+00 4.0004442e-01 7.0470720e-01 2.0181667e-01 1.5698091e+00 3.0922892e-01 1.2049541e+00 1.5104875e+00 5.0476836e-01 1.0069214e+00 3.4085233e-01 9.6593231e-01 3.0026460e-01 8.0004443e-01 6.6334810e-01 1.0000152e+00 8.7372177e-01 5.0855077e-01 5.2524663e-01 7.0462697e-01 4.2362917e-01 3.0915245e-01 2.2608083e-01 4.5784410e-01 5.0517282e-01 4.1209001e-01 1.0313359e+00 9.9085945e-01 1.0179856e+00 6.9600743e-01 6.3912943e-01 1.0000152e+00 4.0125062e-01 3.0482299e-01 9.0002615e-01 8.0254500e-01 9.3735629e-01 9.1446938e-01 3.0490481e-01 6.9600743e-01 1.4994060e+00 8.0928056e-01 7.0184453e-01 7.0184453e-01 3.1328089e-01 1.5989637e+00 7.0918894e-01 1.5237054e+00 6.9987517e-01 1.4060443e+00 1.1002025e+00 1.3061181e+00 2.1141220e+00 1.5030978e+00 1.8055480e+00 1.3062025e+00 1.6223413e+00 6.3164977e-01 8.1112909e-01 1.0095513e+00 8.0713433e-01 9.2867113e-01 9.0155393e-01 1.0001753e+00 2.2182690e+00 2.4124980e+00 1.0039060e+00 1.2201577e+00 8.1343016e-01 2.2176846e+00 5.2491734e-01 1.2037520e+00 1.5066999e+00 4.2362917e-01 4.2362917e-01 1.1060937e+00 1.3130978e+00 1.6177611e+00 1.9760242e+00 1.1138953e+00 6.0948506e-01 1.1056693e+00 1.6779798e+00 1.1527746e+00 1.0001601e+00 4.2362917e-01 9.1892454e-01 1.1528477e+00 8.3183672e-01 6.9987517e-01 1.4094144e+00 1.2633467e+00 8.5440680e-01 7.2036951e-01 7.1629303e-01 9.6576136e-01 6.3322667e-01 1.4267554e+00 4.2268438e-01 1.2004262e+00 6.0035621e-01 2.0860325e+00 3.4342562e-01 1.7133162e+00 1.9641993e+00 1.0207260e+00 1.0897469e+00 8.0008964e-01 1.4650300e+00 5.0043084e-01 1.3002407e+00 1.1303267e+00 9.3424659e-01 1.3473688e+00 1.0001604e+00 9.6593231e-01 6.7616545e-01 8.0097499e-01 6.3192325e-01 5.0437695e-01 3.0026460e-01 2.2608083e-01 9.0142636e-01 1.4861824e+00 1.4580174e+00 1.4889602e+00 1.1900969e+00 9.0142681e-01 1.5001212e+00 9.0166476e-01 2.2538848e-01 8.3187290e-01 1.3130978e+00 1.4197078e+00 1.4012600e+00 8.0046764e-01 1.1544060e+00 2.0075255e+00 1.3063533e+00 1.2089835e+00 1.2089313e+00 7.4275547e-01 2.0887699e+00 1.2190319e+00 1.1935069e+00 1.1010807e+00 1.0087396e+00 7.4335736e-01 9.3424697e-01 1.7023957e+00 2.0003507e+00 1.4002035e+00 9.1449234e-01 1.2643523e+00 5.2167829e-01 5.5450500e-01 6.7616902e-01 1.2049541e+00 1.1528553e+00 8.1112984e-01 6.1119558e-01 1.8053679e+00 2.0034894e+00 1.0142484e+00 9.0155438e-01 1.3009222e+00 1.8029948e+00 6.1119267e-01 8.2425704e-01 1.1002025e+00 7.0176271e-01 8.0046685e-01 7.5564478e-01 9.0026588e-01 1.2017042e+00 1.5269837e+00 7.9871893e-01 6.0201716e-01 8.6051471e-01 1.2366099e+00 9.4532171e-01 6.3309012e-01 9.0026588e-01 6.3164729e-01 9.3308853e-01 8.0004443e-01 1.1010807e+00 1.0426516e+00 1.0426760e+00 8.0051115e-01 6.8161057e-01 5.2491734e-01 8.6084272e-01 1.0001753e+00 1.0116865e+00 5.6370994e-01 1.0599087e+00 7.4329527e-01 1.1110092e+00 4.1212852e-01 5.6838732e-01 7.0478886e-01 5.0436965e-01 7.7598796e-01 6.0948506e-01 1.2192920e+00 7.1629303e-01 4.2270142e-01 7.1629303e-01 2.2608083e-01 9.7033357e-01 6.3164729e-01 9.6576136e-01 7.5503094e-01 9.1446896e-01 1.1138955e+00 1.3139296e+00 1.2705641e+00 6.5724028e-01 5.0894102e-01 2.2573593e-01 3.3813251e-01 4.1212852e-01 1.1025819e+00 7.1629303e-01 1.1039833e+00 1.2272550e+00 8.0245746e-01 7.0000303e-01 2.0000000e-01 4.1210927e-01 7.7598796e-01 3.3813251e-01 7.1700774e-01 4.0125062e-01 7.0017011e-01 6.0035305e-01 7.4329414e-01 1.0008768e+00 5.0043084e-01 2.0249458e+00 1.1061923e+00 2.0081838e+00 1.6061519e+00 1.8167511e+00 2.7171724e+00 6.3925756e-01 2.3875202e+00 1.8286180e+00 2.2239101e+00 1.2353587e+00 1.3278587e+00 1.6038059e+00 1.0207533e+00 1.2407946e+00 1.3868868e+00 1.5269837e+00 2.8396169e+00 2.9941208e+00 1.0030871e+00 1.8005082e+00 9.3733589e-01 2.8269381e+00 9.7033357e-01 1.7520952e+00 2.1193712e+00 8.6676847e-01 9.4912864e-01 1.6147493e+00 1.9768316e+00 2.2674825e+00 2.7199050e+00 1.6193612e+00 1.1298636e+00 1.6009488e+00 2.4288142e+00 1.6617386e+00 1.5199103e+00 8.6676847e-01 1.5881447e+00 1.6785116e+00 1.4886759e+00 1.1061923e+00 1.9457481e+00 1.7813291e+00 1.3946348e+00 1.0498347e+00 1.2771155e+00 1.4848797e+00 1.1157320e+00 8.0004523e-01 5.0043842e-01 1.6743483e+00 2.0121983e-01 1.3061139e+00 1.5464046e+00 6.0964597e-01 7.1183012e-01 4.0006662e-01 1.0776296e+00 3.0922892e-01 9.0002570e-01 7.3084171e-01 6.0184622e-01 9.3446811e-01 6.1135434e-01 6.0964597e-01 3.4080442e-01 4.1210927e-01 3.0490481e-01 2.2608083e-01 3.0482299e-01 4.0363334e-01 5.0001522e-01 1.1298636e+00 1.0440350e+00 1.0803561e+00 7.8935898e-01 5.6347978e-01 1.1000098e+00 6.3165225e-01 3.0482299e-01 5.0126466e-01 9.0511169e-01 1.0088926e+00 1.0001903e+00 4.0125062e-01 7.4335736e-01 1.5972311e+00 9.0142681e-01 8.0296037e-01 8.0250202e-01 3.4085233e-01 1.7081446e+00 8.0883841e-01 1.4329858e+00 7.2036951e-01 1.3050153e+00 1.0001753e+00 1.2089252e+00 2.0109333e+00 1.6000184e+00 1.7036944e+00 1.2001396e+00 1.5327217e+00 5.7608844e-01 7.0462844e-01 9.1449234e-01 8.1156529e-01 9.3733552e-01 8.5583415e-01 9.0029018e-01 2.1191883e+00 2.3098756e+00 6.3912709e-01 1.1290757e+00 9.0532049e-01 2.1139617e+00 3.4085233e-01 1.1074834e+00 1.4044980e+00 3.4080442e-01 4.2362917e-01 1.0087250e+00 1.2089253e+00 1.5132032e+00 1.8748226e+00 1.0207260e+00 5.0042326e-01 1.0008620e+00 1.5694554e+00 1.0837679e+00 9.0053003e-01 5.0517282e-01 8.2671175e-01 1.0777411e+00 8.1156529e-01 7.2036951e-01 1.3133662e+00 1.1910068e+00 8.2425704e-01 4.5847767e-01 6.3178534e-01 9.1590889e-01 6.3322667e-01 6.3322667e-01 1.2193537e+00 9.0000091e-01 6.3165225e-01 1.0599087e+00 3.1328089e-01 6.3451734e-01 4.0127250e-01 9.0000091e-01 1.0001604e+00 2.2573593e-01 4.1212852e-01 6.3178534e-01 6.0202028e-01 5.2524663e-01 5.2132556e-01 6.1135434e-01 4.0125062e-01 7.0008584e-01 9.0002615e-01 1.1001014e+00 1.0039209e+00 3.0482299e-01 1.0001751e+00 7.0478886e-01 8.0296037e-01 6.0000952e-01 6.0366256e-01 3.0915245e-01 6.0365948e-01 1.0001903e+00 6.3164977e-01 4.0125062e-01 5.0476836e-01 2.2608083e-01 4.0127250e-01 5.0043842e-01 1.2102248e+00 3.0017653e-01 3.0482299e-01 3.0008832e-01 5.0043084e-01 1.5012947e+00 4.0000000e-01 1.5653766e+00 6.7616902e-01 1.5829749e+00 1.1074742e+00 1.3373141e+00 2.2681751e+00 8.0291671e-01 1.9315820e+00 1.3458100e+00 1.7862938e+00 8.7372177e-01 8.7209348e-01 1.2093969e+00 7.1700774e-01 1.1055705e+00 1.0604287e+00 1.0451812e+00 2.3834499e+00 2.5286011e+00 6.3322667e-01 1.3903623e+00 7.0462697e-01 2.3796582e+00 6.3912943e-01 1.2792049e+00 1.6907308e+00 5.6595488e-01 5.3943256e-01 1.1400339e+00 1.5965952e+00 1.8639835e+00 2.3424496e+00 1.1635325e+00 6.7626502e-01 1.1005460e+00 2.0903382e+00 1.2459141e+00 1.0236548e+00 5.0894102e-01 1.2528590e+00 1.2949162e+00 1.2662318e+00 6.7616902e-01 1.4817248e+00 1.3908238e+00 1.1389163e+00 6.9600743e-01 8.9540816e-01 1.0858512e+00 6.3192325e-01 1.5890088e+00 4.2270142e-01 1.1330776e+00 1.5368468e+00 5.2491734e-01 1.1187430e+00 4.0243965e-01 1.1139906e+00 4.1420960e-01 7.0096858e-01 7.3895268e-01 1.1000100e+00 9.3861512e-01 4.0127250e-01 7.1708289e-01 8.0004523e-01 5.2167208e-01 4.5784410e-01 3.6452132e-01 5.6371422e-01 4.2270142e-01 4.1317535e-01 1.2159868e+00 1.0567817e+00 1.1138092e+00 8.3387677e-01 6.1119267e-01 9.0029064e-01 3.0482299e-01 4.0125062e-01 1.0003196e+00 7.4395693e-01 9.3459651e-01 8.5617086e-01 3.0922892e-01 8.0073117e-01 1.5493206e+00 7.5564478e-01 6.4049114e-01 6.4049114e-01 4.5784410e-01 1.7404389e+00 6.9600743e-01 1.3253457e+00 6.4049114e-01 1.2202193e+00 9.0142636e-01 1.1056785e+00 1.9348400e+00 1.4092540e+00 1.6176783e+00 1.1286101e+00 1.4350761e+00 4.5148429e-01 6.7720957e-01 8.1757693e-01 8.2671175e-01 8.1937731e-01 7.4263078e-01 8.0055465e-01 2.0418418e+00 2.2277117e+00 1.1002025e+00 1.0286508e+00 7.2044167e-01 2.0415798e+00 6.0035305e-01 1.0039060e+00 1.3253497e+00 5.0043842e-01 3.1328089e-01 9.0999313e-01 1.1528476e+00 1.4548293e+00 1.8637334e+00 9.1892454e-01 5.2133179e-01 9.3310976e-01 1.5801693e+00 9.6572569e-01 8.0008964e-01 3.4085233e-01 7.5508853e-01 9.6674360e-01 7.4618926e-01 6.4049114e-01 1.2101609e+00 1.0782105e+00 7.2113820e-01 8.0093081e-01 5.2524663e-01 7.8886139e-01 4.5847767e-01 1.7572657e+00 6.1288055e-01 4.0125062e-01 1.0858512e+00 1.1133984e+00 1.4858469e+00 7.1779518e-01 1.8187119e+00 1.2137020e+00 9.6591433e-01 1.4146346e+00 7.4263078e-01 1.5359852e+00 1.2093243e+00 1.7083042e+00 1.4853863e+00 1.5241361e+00 1.7234436e+00 1.9756319e+00 1.9771636e+00 1.3035495e+00 8.0008884e-01 6.3164977e-01 6.0948212e-01 9.1449234e-01 1.8179429e+00 1.2062153e+00 1.3486924e+00 1.8673780e+00 1.4543172e+00 8.7240114e-01 7.4329527e-01 1.1055892e+00 1.4158897e+00 9.3310976e-01 1.1269424e-01 9.3351278e-01 9.7600992e-01 9.6953662e-01 1.3458100e+00 3.0490481e-01 9.0320459e-01 2.7259033e+00 1.8109877e+00 2.7506971e+00 2.3226569e+00 2.5372438e+00 3.4590995e+00 1.2089192e+00 3.1281646e+00 2.5610212e+00 2.9500632e+00 1.9406671e+00 2.0633570e+00 2.3443688e+00 1.7168003e+00 1.8708330e+00 2.0857354e+00 2.2573821e+00 3.5725062e+00 3.7336869e+00 1.7229558e+00 2.5362836e+00 1.6198349e+00 3.5690915e+00 1.7116793e+00 2.4776152e+00 2.8599555e+00 1.6016303e+00 1.6534235e+00 2.3372717e+00 2.7159844e+00 3.0094888e+00 3.4430661e+00 2.3406025e+00 1.8663319e+00 2.3090404e+00 3.1586433e+00 2.3454995e+00 2.2408459e+00 1.5471213e+00 2.3192230e+00 2.4059451e+00 2.1751377e+00 1.8109877e+00 2.6757243e+00 2.4966678e+00 2.1111734e+00 1.7901165e+00 2.0121175e+00 2.1471399e+00 1.8133657e+00 1.4043036e+00 1.6388784e+00 7.0470867e-01 7.7652636e-01 5.0001522e-01 1.1269424e+00 2.2608083e-01 1.0000158e+00 8.0928056e-01 7.0470867e-01 1.0215068e+00 7.1708289e-01 6.3164977e-01 4.2362917e-01 5.0002283e-01 3.0474106e-01 2.0121983e-01 2.2608083e-01 4.5080200e-01 6.0017982e-01 1.1529284e+00 1.1298636e+00 1.1544060e+00 8.5406674e-01 6.3322667e-01 1.2000066e+00 6.3309258e-01 2.2608083e-01 6.0201716e-01 1.0030721e+00 1.1060937e+00 1.1001110e+00 5.0001522e-01 8.2458478e-01 1.6747799e+00 1.0008617e+00 9.0140221e-01 9.0140131e-01 4.1209001e-01 1.7511598e+00 9.0506299e-01 1.4854079e+00 8.3187290e-01 1.3139296e+00 1.0032293e+00 1.2362702e+00 2.0078120e+00 1.7001329e+00 1.7019430e+00 1.2016381e+00 1.5675442e+00 7.1700909e-01 7.4275547e-01 9.6574369e-01 9.3541878e-01 1.1298552e+00 1.0208844e+00 9.0506343e-01 2.1136134e+00 2.3085898e+00 7.4618926e-01 1.1897982e+00 1.0208709e+00 2.1090362e+00 5.0894102e-01 1.1286018e+00 1.4024091e+00 5.2167829e-01 5.6595908e-01 1.0426638e+00 1.2037520e+00 1.5079206e+00 1.8503663e+00 1.0776296e+00 5.0477564e-01 1.0032296e+00 1.5611241e+00 1.1910693e+00 9.0511169e-01 6.3178782e-01 9.0184172e-01 1.1896660e+00 1.0032443e+00 8.3187290e-01 1.3450688e+00 1.3020492e+00 1.0087252e+00 6.1990228e-01 7.4263078e-01 1.0458540e+00 7.3084171e-01 7.0918894e-01 7.0176271e-01 8.1112984e-01 9.6574336e-01 4.1317535e-01 1.5005626e+00 6.1119558e-01 6.0964597e-01 1.0116724e+00 4.1315633e-01 9.3848935e-01 9.0000136e-01 1.1896660e+00 9.6574369e-01 1.2003597e+00 1.4006465e+00 1.6096629e+00 1.5401713e+00 8.2421923e-01 5.3914287e-01 3.6259865e-01 4.2362917e-01 6.0017665e-01 1.2189701e+00 6.0202028e-01 8.7212232e-01 1.5067961e+00 1.1024820e+00 4.1317535e-01 3.0490481e-01 5.0477564e-01 9.3329017e-01 6.0018299e-01 6.1845783e-01 4.1210927e-01 5.0894102e-01 5.0477564e-01 1.0008620e+00 9.0029064e-01 5.0043842e-01 2.1169442e+00 1.2049539e+00 2.2014913e+00 1.7227908e+00 1.9366943e+00 2.8973091e+00 6.0383105e-01 2.5621105e+00 1.9756002e+00 2.3854144e+00 1.4163126e+00 1.4857201e+00 1.8044011e+00 1.1074834e+00 1.2661803e+00 1.4994060e+00 1.6741010e+00 3.0107625e+00 3.1586112e+00 1.1298552e+00 1.9796588e+00 1.0095370e+00 3.0090568e+00 1.1900276e+00 1.8963668e+00 2.3135911e+00 1.0782107e+00 1.0783219e+00 1.7384347e+00 2.2009981e+00 2.4793129e+00 2.9421182e+00 1.7402224e+00 1.3018103e+00 1.7072540e+00 2.6745468e+00 1.7367211e+00 1.6485141e+00 9.6691372e-01 1.8209763e+00 1.8293641e+00 1.7435092e+00 1.2049539e+00 2.0881329e+00 1.9090398e+00 1.6063540e+00 1.2407432e+00 1.4664722e+00 1.5386307e+00 1.2093243e+00 1.0943600e+00 1.0030868e+00 1.3272142e+00 9.1446938e-01 1.7295996e+00 1.1336109e+00 8.7209296e-01 1.2643054e+00 6.3912943e-01 1.4396100e+00 1.1299441e+00 1.5271597e+00 1.3148232e+00 1.4267817e+00 1.6268514e+00 1.8468437e+00 1.8305154e+00 1.1759988e+00 7.4262850e-01 5.2491734e-01 5.2167208e-01 8.5586571e-01 1.6206300e+00 1.1291536e+00 1.4631182e+00 1.7576822e+00 1.3254284e+00 1.0172489e+00 6.0605366e-01 9.1894698e-01 1.2951152e+00 8.3187290e-01 3.0474106e-01 8.1500329e-01 1.0396215e+00 9.6150595e-01 1.2528590e+00 5.6347978e-01 8.7240114e-01 2.5401214e+00 1.6166178e+00 2.5672376e+00 2.1256636e+00 2.3434890e+00 3.2706021e+00 1.0235120e+00 2.9379053e+00 2.3650373e+00 2.7819820e+00 1.7939428e+00 1.8718670e+00 2.1669217e+00 1.5269837e+00 1.7152309e+00 1.9257519e+00 2.0672316e+00 3.3962101e+00 3.5413320e+00 1.5241169e+00 2.3604685e+00 1.4422764e+00 3.3805191e+00 1.5352907e+00 2.2985560e+00 2.6785349e+00 1.4314424e+00 1.4886759e+00 2.1422340e+00 2.5406863e+00 2.8290490e+00 3.2861997e+00 2.1472832e+00 1.6782365e+00 2.1087015e+00 2.9939447e+00 2.1830772e+00 2.0525906e+00 1.3935744e+00 2.1564350e+00 2.2287876e+00 2.0426476e+00 1.6166178e+00 2.4889554e+00 2.3256006e+00 1.9561612e+00 1.6066555e+00 1.8386981e+00 2.0009986e+00 1.6313110e+00 8.0883916e-01 5.0043842e-01 6.0202028e-01 8.0004602e-01 3.3808272e-01 5.0437695e-01 8.0093081e-01 5.2838320e-01 6.0201716e-01 2.5399984e-01 7.2036819e-01 5.0517282e-01 5.0043842e-01 7.0008584e-01 9.1424701e-01 9.0157896e-01 3.0017653e-01 7.2044167e-01 6.2656178e-01 6.6334810e-01 3.6259865e-01 9.0026588e-01 5.0436235e-01 4.1212852e-01 8.0879701e-01 7.0478886e-01 3.0482299e-01 5.2201750e-01 4.5847767e-01 4.0125062e-01 4.1317535e-01 1.0363096e+00 3.4080442e-01 3.0474106e-01 2.2573593e-01 3.0490481e-01 1.2204839e+00 2.4195741e-01 1.8101835e+00 9.0166476e-01 1.7375279e+00 1.4002005e+00 1.6032003e+00 2.4532171e+00 1.0032443e+00 2.1331916e+00 1.6052507e+00 1.9422649e+00 9.1894698e-01 1.1025819e+00 1.3276411e+00 8.1719606e-01 1.0142626e+00 1.1298636e+00 1.3025621e+00 2.5612597e+00 2.7430487e+00 9.0155438e-01 1.5299064e+00 7.1708289e-01 2.5605373e+00 7.0633229e-01 1.5079428e+00 1.8443132e+00 6.0383105e-01 7.0096708e-01 1.4023806e+00 1.6740160e+00 1.9756002e+00 2.3801033e+00 1.4049093e+00 9.0142636e-01 1.4001717e+00 2.0898615e+00 1.4183606e+00 1.3009222e+00 6.0184622e-01 1.2661803e+00 1.4267527e+00 1.1084368e+00 9.0166476e-01 1.7108631e+00 1.5299252e+00 1.0782751e+00 8.1343016e-01 1.0116721e+00 1.2193537e+00 9.0026497e-01 7.9148746e-01 7.0993998e-01 9.3541878e-01 8.1937731e-01 5.0043084e-01 5.6370994e-01 4.1212852e-01 1.0782753e+00 6.0184622e-01 9.0557807e-01 7.4269314e-01 7.0633229e-01 8.2841920e-01 9.1695534e-01 1.0756891e+00 7.3084048e-01 5.2491131e-01 5.0085236e-01 5.0476836e-01 5.0085236e-01 1.1074740e+00 8.3916809e-01 1.2049539e+00 9.6501813e-01 4.2270142e-01 8.0291749e-01 5.0855077e-01 5.3943256e-01 8.2631334e-01 4.0243965e-01 1.0207260e+00 5.2524663e-01 8.0055465e-01 7.0184453e-01 7.0184453e-01 1.0777307e+00 6.0366256e-01 2.0696799e+00 1.1543334e+00 1.9286352e+00 1.6071727e+00 1.8312163e+00 2.6295459e+00 1.1153247e+00 2.3155068e+00 1.8040969e+00 2.1901871e+00 1.2562955e+00 1.3263639e+00 1.5518083e+00 1.1271226e+00 1.4557657e+00 1.4915559e+00 1.5136393e+00 2.7555974e+00 2.9267466e+00 1.0030718e+00 1.7744103e+00 1.0843333e+00 2.7324083e+00 9.6953662e-01 1.7456060e+00 2.0249458e+00 9.1568820e-01 1.0151258e+00 1.6309461e+00 1.8315348e+00 2.1358791e+00 2.5304748e+00 1.6492450e+00 1.1075720e+00 1.6001777e+00 2.2141198e+00 1.7441970e+00 1.5196090e+00 9.6683480e-01 1.4838225e+00 1.7167914e+00 1.4122282e+00 1.1543334e+00 1.9438463e+00 1.8374400e+00 1.4268530e+00 1.0778421e+00 1.2792049e+00 1.5857302e+00 1.1532421e+00 1.1019503e+00 6.0201716e-01 5.0043842e-01 6.1135434e-01 7.0008735e-01 8.1156529e-01 4.1317535e-01 7.0000303e-01 4.0246123e-01 2.0061436e-01 4.1210927e-01 5.0436965e-01 7.0000303e-01 6.0366256e-01 2.0121983e-01 1.2007726e+00 9.1916394e-01 1.0124729e+00 8.0055465e-01 4.0246123e-01 7.0008735e-01 5.0085236e-01 6.0017982e-01 6.0202028e-01 6.3165225e-01 7.4612830e-01 6.0383105e-01 1.1269424e-01 7.0184453e-01 1.4559030e+00 5.6371422e-01 5.2167829e-01 5.2133179e-01 4.0004442e-01 1.7133283e+00 6.0948800e-01 1.3743342e+00 5.2524663e-01 1.2702954e+00 9.0142636e-01 1.1286018e+00 1.9763960e+00 1.2004262e+00 1.6484371e+00 1.1066159e+00 1.5033966e+00 6.1990228e-01 6.3322667e-01 8.9538275e-01 6.1990228e-01 1.0010060e+00 9.1471442e-01 8.0488008e-01 2.0894199e+00 2.2581358e+00 7.0088627e-01 1.1085342e+00 6.3178782e-01 2.0855639e+00 4.0363334e-01 1.0293900e+00 1.3743657e+00 4.0006662e-01 4.0125062e-01 9.3329055e-01 1.2396422e+00 1.5267540e+00 1.9798779e+00 9.6591465e-01 4.0127250e-01 9.0026497e-01 1.7151603e+00 1.0797805e+00 8.0296037e-01 4.0006662e-01 8.9540816e-01 1.0837679e+00 9.6674360e-01 5.2524663e-01 1.2440789e+00 1.1938630e+00 9.1892454e-01 5.2524663e-01 6.3912943e-01 9.3733589e-01 4.5148429e-01 1.1281352e+00 9.0002570e-01 5.0517282e-01 9.4513210e-01 4.1315633e-01 1.2014191e+00 5.2133179e-01 1.3063533e+00 1.1019505e+00 8.5403370e-01 1.0426516e+00 1.3523310e+00 1.4544312e+00 9.0142636e-01 3.3818226e-01 5.0085236e-01 5.0437695e-01 3.0922892e-01 1.5001461e+00 9.0005094e-01 9.0668287e-01 1.2396475e+00 8.7209296e-01 5.0000761e-01 4.5078948e-01 8.0046764e-01 1.0030724e+00 4.1317535e-01 6.7824250e-01 6.0017665e-01 6.0000952e-01 6.0000317e-01 7.4262850e-01 6.3925756e-01 5.0001522e-01 2.4077059e+00 1.5012741e+00 2.3329496e+00 2.0008921e+00 2.2042323e+00 3.0476353e+00 9.3541878e-01 2.7309758e+00 2.2068463e+00 2.5373913e+00 1.5160787e+00 1.7043730e+00 1.9242109e+00 1.4044668e+00 1.5401330e+00 1.7168122e+00 1.9044144e+00 3.1543192e+00 3.3406961e+00 1.4044697e+00 2.1265131e+00 1.3061138e+00 3.1536525e+00 1.3069754e+00 2.1097680e+00 2.4379736e+00 1.2049541e+00 1.3017511e+00 2.0033792e+00 2.2562563e+00 2.5606009e+00 2.9377608e+00 2.0050253e+00 1.5030978e+00 2.0001168e+00 2.6390071e+00 2.0114908e+00 1.9023062e+00 1.2016381e+00 1.8467998e+00 2.0209800e+00 1.6143467e+00 1.5012741e+00 2.3121231e+00 2.1220697e+00 1.6461460e+00 1.4062065e+00 1.6118728e+00 1.8108200e+00 1.5004645e+00 1.1000005e+00 9.0305330e-01 9.0506343e-01 1.1075720e+00 8.0488008e-01 6.1119558e-01 6.3912943e-01 6.0383105e-01 3.0490481e-01 1.1269424e-01 4.1210927e-01 6.0184622e-01 7.0008735e-01 1.0803561e+00 1.2125410e+00 1.2178626e+00 9.0645118e-01 7.9153339e-01 1.3000002e+00 7.0096858e-01 3.0008832e-01 8.0245824e-01 1.1001015e+00 1.2040344e+00 1.2012928e+00 6.0017982e-01 9.0645118e-01 1.7262450e+00 1.1005460e+00 1.0000307e+00 1.0000307e+00 5.0043842e-01 1.7087610e+00 1.0003198e+00 1.6300950e+00 9.3848935e-01 1.5032156e+00 1.2007124e+00 1.4092540e+00 2.2026134e+00 1.8005395e+00 1.9004485e+00 1.4019342e+00 1.7231818e+00 7.4269314e-01 9.0668287e-01 1.1133897e+00 1.0251597e+00 1.0924484e+00 1.0143978e+00 1.1005460e+00 2.3044111e+00 2.5032992e+00 9.4511250e-01 1.3253497e+00 1.1075720e+00 2.3033192e+00 5.5450500e-01 1.3061180e+00 1.6004128e+00 5.4219811e-01 6.3912943e-01 1.2090477e+00 1.4006179e+00 1.7019555e+00 2.0185049e+00 1.2190878e+00 7.0548283e-01 1.2049539e+00 1.7202439e+00 1.2636227e+00 1.1006371e+00 7.0911112e-01 1.0207396e+00 1.2632946e+00 9.3308853e-01 9.3848935e-01 1.5130871e+00 1.3741498e+00 9.6572569e-01 6.9987517e-01 8.2421923e-01 1.0798806e+00 8.5583415e-01 5.2524663e-01 8.2418002e-01 6.3912709e-01 3.6452132e-01 5.6394820e-01 7.2036819e-01 5.0517282e-01 8.0008964e-01 1.0000005e+00 1.2000731e+00 1.1019597e+00 4.0002221e-01 1.0039063e+00 7.4612830e-01 8.3183672e-01 6.0383105e-01 6.1119558e-01 2.0000000e-01 4.5078948e-01 1.1000098e+00 7.8890806e-01 4.0122873e-01 5.6371422e-01 4.1212852e-01 5.0001522e-01 5.2524663e-01 1.2137020e+00 3.4080442e-01 3.3813251e-01 3.0490481e-01 6.0035621e-01 1.5010034e+00 4.0246123e-01 1.5265987e+00 6.1135434e-01 1.6395342e+00 1.1134850e+00 1.3309249e+00 2.3136797e+00 7.1629168e-01 1.9760038e+00 1.3748534e+00 1.8136626e+00 9.1894698e-01 9.0320459e-01 1.2661802e+00 6.0427481e-01 9.1427000e-01 9.6685270e-01 1.0777305e+00 2.4270428e+00 2.5626268e+00 8.1112909e-01 1.4228744e+00 5.2167208e-01 2.4261071e+00 7.0633229e-01 1.3043552e+00 1.7511131e+00 6.0383105e-01 5.2491131e-01 1.1330776e+00 1.6740160e+00 1.9314874e+00 2.4166999e+00 1.1400420e+00 7.4269200e-01 1.1024820e+00 2.1702438e+00 1.1639421e+00 1.0427822e+00 4.2268438e-01 1.3276412e+00 1.2710363e+00 1.3154933e+00 6.1135434e-01 1.4922566e+00 1.3466030e+00 1.1400339e+00 7.3461436e-01 9.3733552e-01 9.7694377e-01 6.0365948e-01 5.8750389e-01 2.4195741e-01 8.6051471e-01 3.3818226e-01 8.1719606e-01 6.0202028e-01 6.0219099e-01 8.0337471e-01 1.0214933e+00 1.0338224e+00 5.2201750e-01 6.0000635e-01 3.6259865e-01 4.2268438e-01 2.2538848e-01 1.0087393e+00 5.4219811e-01 7.4618926e-01 9.2019277e-01 5.2838320e-01 3.4080442e-01 3.4085233e-01 3.4085233e-01 5.2838320e-01 2.0121983e-01 9.0294373e-01 3.0482299e-01 3.0490481e-01 3.0490481e-01 4.1420960e-01 1.1133986e+00 3.0017653e-01 1.9760242e+00 1.0776188e+00 1.8598666e+00 1.5071120e+00 1.7384459e+00 2.5637810e+00 9.3426769e-01 2.2403929e+00 1.7108631e+00 2.0993246e+00 1.1405598e+00 1.2394690e+00 1.4816205e+00 1.0776296e+00 1.4324323e+00 1.4163126e+00 1.4134492e+00 2.6753615e+00 2.8540068e+00 9.1001664e-01 1.6986597e+00 1.0426638e+00 2.6697938e+00 9.0657539e-01 1.6396943e+00 1.9541963e+00 8.5583415e-01 9.0207914e-01 1.5412500e+00 1.7849153e+00 2.0880425e+00 2.4973149e+00 1.5650163e+00 1.0060994e+00 1.5001440e+00 2.2185588e+00 1.6410190e+00 1.4111252e+00 8.5440680e-01 1.4330979e+00 1.6474117e+00 1.4095656e+00 1.0776188e+00 1.8534896e+00 1.7579984e+00 1.3938438e+00 1.0171340e+00 1.1990152e+00 1.4686236e+00 1.0427822e+00 6.8261201e-01 1.0004792e+00 6.3178782e-01 4.1210927e-01 6.0202028e-01 7.0025283e-01 8.0245903e-01 6.7720957e-01 8.1719606e-01 7.0008432e-01 1.0069214e+00 7.9153339e-01 8.6054545e-01 6.4049114e-01 6.3178782e-01 9.0155393e-01 1.2000065e+00 9.0508712e-01 2.0181667e-01 8.2635069e-01 7.1708289e-01 7.0548283e-01 8.0000239e-01 5.4219811e-01 1.3530568e+00 6.3322667e-01 8.0967961e-01 7.1708289e-01 7.0016860e-01 1.5402579e+00 6.3925756e-01 1.5611241e+00 6.4620889e-01 1.4283663e+00 1.1134850e+00 1.3189663e+00 2.1346646e+00 1.3000497e+00 1.8186729e+00 1.3009674e+00 1.7335369e+00 1.0118233e+00 8.1117067e-01 1.0567664e+00 6.0605366e-01 9.2867113e-01 1.0782857e+00 1.0429127e+00 2.2917679e+00 2.4270713e+00 5.0042326e-01 1.2848760e+00 6.9987517e-01 2.2396581e+00 5.2491734e-01 1.3051737e+00 1.5457820e+00 6.0365948e-01 8.0291749e-01 1.1110184e+00 1.3561934e+00 1.6492450e+00 2.1212048e+00 1.1186586e+00 6.7616723e-01 1.1005365e+00 1.7574668e+00 1.3269962e+00 1.0777411e+00 8.0097499e-01 1.0411548e+00 1.1972915e+00 9.9911696e-01 6.4620889e-01 1.4422764e+00 1.3473056e+00 9.3861512e-01 5.2491734e-01 8.6084272e-01 1.2528048e+00 8.2498722e-01 9.6150595e-01 5.0477564e-01 1.0214931e+00 8.0923926e-01 8.0492246e-01 1.0062544e+00 1.2363856e+00 1.2438823e+00 6.2656178e-01 4.0006662e-01 1.2085435e-01 2.0181667e-01 2.2573593e-01 1.2016443e+00 6.3925756e-01 9.2019277e-01 1.1335345e+00 7.1636719e-01 5.0084481e-01 2.0121983e-01 5.0002283e-01 7.3155911e-01 2.0181667e-01 6.7626681e-01 3.0915245e-01 5.0437695e-01 4.1317535e-01 6.1845783e-01 9.0506254e-01 3.0922892e-01 2.1350025e+00 1.2189760e+00 2.0658767e+00 1.7034615e+00 1.9177947e+00 2.7775988e+00 7.7598704e-01 2.4534018e+00 1.9144928e+00 2.2857680e+00 1.2749306e+00 1.4182222e+00 1.6639408e+00 1.1527669e+00 1.4140789e+00 1.4954274e+00 1.6121856e+00 2.8913337e+00 3.0644792e+00 1.1011719e+00 1.8708183e+00 1.0777305e+00 2.8852099e+00 1.0396215e+00 1.8297117e+00 2.1701542e+00 9.4532171e-01 1.0262619e+00 1.7168122e+00 2.0059655e+00 2.3063931e+00 2.7230908e+00 1.7261949e+00 1.2093243e+00 1.7002548e+00 2.4331092e+00 1.7646791e+00 1.6080687e+00 9.3848935e-01 1.6152383e+00 1.7771159e+00 1.4971922e+00 1.2189760e+00 2.0349233e+00 1.8831259e+00 1.4665397e+00 1.1400339e+00 1.3492939e+00 1.5757399e+00 1.2102248e+00 8.1117067e-01 7.0548283e-01 6.0964891e-01 6.0605366e-01 7.0918894e-01 9.0279223e-01 8.0008964e-01 3.6259865e-01 1.3154973e+00 1.0604287e+00 1.1536694e+00 9.1892454e-01 5.0477564e-01 5.0894102e-01 3.0922892e-01 8.0046764e-01 9.0778124e-01 7.1708289e-01 8.6225026e-01 6.8685125e-01 4.0363334e-01 8.4536936e-01 1.5318139e+00 6.5832080e-01 6.7636452e-01 6.3322667e-01 5.6838732e-01 1.8053679e+00 7.2044167e-01 1.2092602e+00 5.0437695e-01 1.3018595e+00 8.0291671e-01 1.0095513e+00 1.9760044e+00 1.0208709e+00 1.6387179e+00 1.0597877e+00 1.4686236e+00 6.0201716e-01 6.0427481e-01 9.3331138e-01 7.0025283e-01 6.1119558e-01 6.0427175e-01 7.4269200e-01 2.0887699e+00 2.2281421e+00 1.0001753e+00 1.0797700e+00 4.1317535e-01 2.0885107e+00 5.2133179e-01 9.6591465e-01 1.4140457e+00 4.1209001e-01 2.2573593e-01 8.1156529e-01 1.3450340e+00 1.5966664e+00 2.0855643e+00 8.1343016e-01 4.6440171e-01 8.2635069e-01 1.8444686e+00 8.2635069e-01 7.1621748e-01 2.0061436e-01 1.0088783e+00 9.1566538e-01 1.0032296e+00 5.0437695e-01 1.1543257e+00 9.8997136e-01 8.1117067e-01 7.0470867e-01 6.0980961e-01 6.3322667e-01 3.0474106e-01 9.0031539e-01 7.0000151e-01 3.3813251e-01 5.2167829e-01 8.5403428e-01 1.0095513e+00 5.0043842e-01 5.2524663e-01 6.0980961e-01 6.1288055e-01 3.0026460e-01 1.1001015e+00 7.1636719e-01 6.3309258e-01 7.4335736e-01 5.2167208e-01 5.0043084e-01 6.0184309e-01 6.0964891e-01 6.0017982e-01 3.0482299e-01 1.1153247e+00 5.0043084e-01 4.0246123e-01 4.0125062e-01 3.0017653e-01 1.1270411e+00 4.0002221e-01 2.0175565e+00 1.1056693e+00 1.9099615e+00 1.6003257e+00 1.8055799e+00 2.6186105e+00 1.2017042e+00 2.3090806e+00 1.8007233e+00 2.1233216e+00 1.1144002e+00 1.3025622e+00 1.5097103e+00 1.0216374e+00 1.2396937e+00 1.3452695e+00 1.5005647e+00 2.7241212e+00 2.9166918e+00 1.0087396e+00 1.7168636e+00 9.3733552e-01 2.7221286e+00 9.0508756e-01 1.7046111e+00 2.0107590e+00 8.0879701e-01 9.0508712e-01 1.6049314e+00 1.8174378e+00 2.1221146e+00 2.4750525e+00 1.6096791e+00 1.1000193e+00 1.6000016e+00 2.1732693e+00 1.6308665e+00 1.5004872e+00 8.0883916e-01 1.4182493e+00 1.6308803e+00 1.2094550e+00 1.1056693e+00 1.9088565e+00 1.7377460e+00 1.2661852e+00 1.0088926e+00 1.2092662e+00 1.4340155e+00 1.1019692e+00 3.4342562e-01 6.0964891e-01 5.6595908e-01 5.0437695e-01 5.2167829e-01 4.5783248e-01 1.4023777e+00 1.1286018e+00 1.2201578e+00 1.0032443e+00 3.0922892e-01 9.0642679e-01 9.0166476e-01 6.0964597e-01 5.0084481e-01 8.6054545e-01 9.6574336e-01 8.0923926e-01 5.0477564e-01 9.0532093e-01 1.6742781e+00 7.8895472e-01 7.5564478e-01 7.4618926e-01 6.0964891e-01 1.9222003e+00 8.2462252e-01 1.2093908e+00 5.2201750e-01 1.0522594e+00 7.0548138e-01 9.3735629e-01 1.7578497e+00 1.4001717e+00 1.4326118e+00 9.0166431e-01 1.3681502e+00 7.1636719e-01 4.5148429e-01 7.1183012e-01 6.3164977e-01 9.0534502e-01 8.5583415e-01 6.3322667e-01 1.9047821e+00 2.0429861e+00 3.3813251e-01 9.4634218e-01 7.1700774e-01 1.8662975e+00 3.0474106e-01 9.1695534e-01 1.1636098e+00 3.3818226e-01 5.0476836e-01 7.4329527e-01 1.0171202e+00 1.3020942e+00 1.8013674e+00 7.8935898e-01 3.0474106e-01 7.0008735e-01 1.4927071e+00 1.0336860e+00 6.7720957e-01 5.0855778e-01 7.3895268e-01 9.4622126e-01 8.4540285e-01 5.2201750e-01 1.0621172e+00 1.0788651e+00 8.1156529e-01 4.0002221e-01 5.6618864e-01 9.6935134e-01 5.2524663e-01 4.1212852e-01 5.0517282e-01 7.0008584e-01 6.3322667e-01 3.0490481e-01 1.2003660e+00 9.1552373e-01 1.0095513e+00 8.0046685e-01 4.5080200e-01 7.0105084e-01 6.0964891e-01 6.0365948e-01 5.0477564e-01 6.3178782e-01 7.4329527e-01 6.0201716e-01 2.2573593e-01 7.0096708e-01 1.4548054e+00 5.6347978e-01 5.2167208e-01 5.2133802e-01 4.0006662e-01 1.7132643e+00 6.0948506e-01 1.4655221e+00 7.0548283e-01 1.2921474e+00 9.1424701e-01 1.1900342e+00 1.9791159e+00 1.2013591e+00 1.6491682e+00 1.1111057e+00 1.5689626e+00 8.0726668e-01 7.4329527e-01 9.8998705e-01 8.0337471e-01 1.2004198e+00 1.1061923e+00 8.2635069e-01 2.0953157e+00 2.2622460e+00 6.0366256e-01 1.2097311e+00 8.0883841e-01 2.0866883e+00 6.0035621e-01 1.0858512e+00 1.3762609e+00 6.0000635e-01 6.0035305e-01 1.0143975e+00 1.2399444e+00 1.5291965e+00 1.9842703e+00 1.0777305e+00 4.1315633e-01 9.0005048e-01 1.7303039e+00 1.2394744e+00 8.2498722e-01 6.0018299e-01 9.9013884e-01 1.2395260e+00 1.1286911e+00 7.0548283e-01 1.3081175e+00 1.3479052e+00 1.1074834e+00 7.0184453e-01 8.1117067e-01 1.1186499e+00 6.0980961e-01 2.0181667e-01 5.2133802e-01 7.0548283e-01 4.0243965e-01 8.5471446e-01 9.1001664e-01 9.1916394e-01 6.0964891e-01 8.0296037e-01 1.0000307e+00 5.2524663e-01 4.1420960e-01 6.0000635e-01 8.0004523e-01 9.0166431e-01 9.0026588e-01 3.3818226e-01 6.0366256e-01 1.4340438e+00 8.0004523e-01 7.0000454e-01 7.0000151e-01 2.0000000e-01 1.4651632e+00 7.0008584e-01 1.7369589e+00 8.4540285e-01 1.6071563e+00 1.3008770e+00 1.5130871e+00 2.3098753e+00 1.5002444e+00 2.0034559e+00 1.5005854e+00 1.8322392e+00 8.5437498e-01 1.0087393e+00 1.2192920e+00 8.4786353e-01 1.1330694e+00 1.1270325e+00 1.2012867e+00 2.4144060e+00 2.6097166e+00 7.9153339e-01 1.4330116e+00 8.7209348e-01 2.4119960e+00 6.3178782e-01 1.4094452e+00 1.7039341e+00 5.6371422e-01 6.3309258e-01 1.3130937e+00 1.5066999e+00 1.8106410e+00 2.1515742e+00 1.3253458e+00 8.0004602e-01 1.3000908e+00 1.8533295e+00 1.3748188e+00 1.2012928e+00 5.7609230e-01 1.1298636e+00 1.3741846e+00 1.0451812e+00 8.4540285e-01 1.6176927e+00 1.4854079e+00 1.0777307e+00 7.4612830e-01 9.3306807e-01 1.1910068e+00 8.1715665e-01 4.0243965e-01 6.0184622e-01 6.0000952e-01 1.0158274e+00 1.1111057e+00 1.1191444e+00 8.0928056e-01 7.4335736e-01 1.2000002e+00 6.0964891e-01 3.0026460e-01 7.0088477e-01 1.0001601e+00 1.1024820e+00 1.1005458e+00 5.0042326e-01 8.0492246e-01 1.6321742e+00 1.0001753e+00 9.0005048e-01 9.0002615e-01 4.0006662e-01 1.6390068e+00 9.0029064e-01 1.6300430e+00 8.6084272e-01 1.5035329e+00 1.2004200e+00 1.4092511e+00 2.2043907e+00 1.7002548e+00 1.9010379e+00 1.4007831e+00 1.7240342e+00 7.4269314e-01 9.0534502e-01 1.1133984e+00 9.3184922e-01 1.0597992e+00 1.0142766e+00 1.1005364e+00 2.3071806e+00 2.5048249e+00 8.4536936e-01 1.3253910e+00 1.0116865e+00 2.3056305e+00 5.2838320e-01 1.3061582e+00 1.6010223e+00 4.8391482e-01 5.7608844e-01 1.2089313e+00 1.4017695e+00 1.7039229e+00 2.0293124e+00 1.2189760e+00 7.0096858e-01 1.2016380e+00 1.7295384e+00 1.2636227e+00 1.1005460e+00 6.1830489e-01 1.0208709e+00 1.2632948e+00 9.3329055e-01 8.6084272e-01 1.5130912e+00 1.3741813e+00 9.6572569e-01 6.5832080e-01 8.2418071e-01 1.0788007e+00 7.9148662e-01 3.0922892e-01 8.0046764e-01 1.3743342e+00 1.3452695e+00 1.3745152e+00 1.0776296e+00 8.0051115e-01 1.4000349e+00 8.2462252e-01 3.0026460e-01 5.7609230e-01 1.2089253e+00 1.3131370e+00 1.3002493e+00 7.0016860e-01 1.0426760e+00 1.8951252e+00 1.2036864e+00 1.1055892e+00 1.1055707e+00 6.3165225e-01 1.9760099e+00 1.1133895e+00 1.3035495e+00 1.0032296e+00 1.1134939e+00 8.1112984e-01 1.0427944e+00 1.8040883e+00 1.9000220e+00 1.5005626e+00 1.0010060e+00 1.3844234e+00 6.1288055e-01 5.7609230e-01 7.8890721e-01 1.1056785e+00 1.1270325e+00 9.0778124e-01 7.0556260e-01 1.9141294e+00 2.1052841e+00 8.2421923e-01 1.0150395e+00 1.2036863e+00 1.9046783e+00 5.2133802e-01 9.3733589e-01 1.2010584e+00 6.0948212e-01 7.0470867e-01 8.5583357e-01 1.0008768e+00 1.3033860e+00 1.6469593e+00 9.0294373e-01 5.0436965e-01 8.5406616e-01 1.3485619e+00 1.0522594e+00 7.0993998e-01 8.0250123e-01 7.4329527e-01 1.0427822e+00 9.0053003e-01 1.0032296e+00 1.1531951e+00 1.1543259e+00 9.0142681e-01 5.6618864e-01 6.1135434e-01 9.3984267e-01 9.0168933e-01 7.1629303e-01 1.5266891e+00 1.3564850e+00 1.4198077e+00 1.1544060e+00 7.0088627e-01 1.3008812e+00 7.2036951e-01 3.0482299e-01 7.4954884e-01 1.1531951e+00 1.2645755e+00 1.2053003e+00 6.1119267e-01 1.0803561e+00 1.9177201e+00 1.1286911e+00 1.0451689e+00 1.0433444e+00 7.2036951e-01 2.0856547e+00 1.0782211e+00 1.0434746e+00 9.0029064e-01 9.0279223e-01 6.0948800e-01 8.0883841e-01 1.6097492e+00 1.8003682e+00 1.3025173e+00 8.0879701e-01 1.1347620e+00 3.0922892e-01 3.6452132e-01 5.2133179e-01 1.0032293e+00 9.3308891e-01 6.0383105e-01 5.0043084e-01 1.7170314e+00 1.9082779e+00 8.5406616e-01 7.4275547e-01 1.1001110e+00 1.7132654e+00 4.1212852e-01 7.0548138e-01 1.0030871e+00 5.0085236e-01 6.0000635e-01 6.1135434e-01 8.0879701e-01 1.1134075e+00 1.4922778e+00 6.3322667e-01 4.0246123e-01 6.8261201e-01 1.1935004e+00 7.4954884e-01 5.0437695e-01 7.0008584e-01 4.5148429e-01 7.4262964e-01 6.0018299e-01 9.0029064e-01 9.1424701e-01 8.5437440e-01 6.0017665e-01 5.2167208e-01 3.0915245e-01 6.4620889e-01 8.0000160e-01 1.0033867e+00 7.3461436e-01 8.2512420e-01 6.0219099e-01 6.0017982e-01 6.0000317e-01 5.0000761e-01 7.0016860e-01 6.0202028e-01 4.5148429e-01 5.7630313e-01 5.0855778e-01 1.2699992e-01 5.0894102e-01 1.2671752e+00 4.1420960e-01 3.6259865e-01 3.4080442e-01 2.4170870e-01 1.5133193e+00 4.1317535e-01 1.5238388e+00 6.0980961e-01 1.4557632e+00 1.1002023e+00 1.3069713e+00 2.1693127e+00 1.1005458e+00 1.8443124e+00 1.3063934e+00 1.6655594e+00 6.5832080e-01 8.0492246e-01 1.0498228e+00 5.7832449e-01 9.1424701e-01 9.0320459e-01 1.0032296e+00 2.2802814e+00 2.4537354e+00 7.1621613e-01 1.2528590e+00 5.3914287e-01 2.2781292e+00 4.2362917e-01 1.2128138e+00 1.5640141e+00 3.4085233e-01 4.1212852e-01 1.1060939e+00 1.4140458e+00 1.7081323e+00 2.1436849e+00 1.1138955e+00 6.0184622e-01 1.1001015e+00 1.8659091e+00 1.1544060e+00 1.0010209e+00 3.3813251e-01 1.0224270e+00 1.1635398e+00 9.7600992e-01 6.0980961e-01 1.4182493e+00 1.2705641e+00 8.9538275e-01 5.4219811e-01 7.3084171e-01 9.6936870e-01 6.0184934e-01 3.0922892e-01 2.4170870e-01 4.0127250e-01 1.6009488e+00 1.0040629e+00 1.0499492e+00 1.2653025e+00 9.1471442e-01 6.1119558e-01 5.0477564e-01 9.0005048e-01 1.1016049e+00 5.0043084e-01 7.0096708e-01 7.0088627e-01 7.0470720e-01 7.0176121e-01 8.0967961e-01 6.3165225e-01 6.0201716e-01 2.5221737e+00 1.6096629e+00 2.4221589e+00 2.1015969e+00 2.3098905e+00 3.1317714e+00 1.0597879e+00 2.8188299e+00 2.3040148e+00 2.6373482e+00 1.6231306e+00 1.8068049e+00 2.0210084e+00 1.5237053e+00 1.7080686e+00 1.8459262e+00 2.0034094e+00 3.2387184e+00 3.4286399e+00 1.5005854e+00 2.2285172e+00 1.4324350e+00 3.2358000e+00 1.4109628e+00 2.2110849e+00 2.5224740e+00 1.3139336e+00 1.4095777e+00 2.1090366e+00 2.3323064e+00 2.6377472e+00 2.9966835e+00 2.1144760e+00 1.6012568e+00 2.1000482e+00 2.6968519e+00 2.1346646e+00 2.0025815e+00 1.3133662e+00 1.9351024e+00 2.1377869e+00 1.7137965e+00 1.6096629e+00 2.4161682e+00 2.2434416e+00 1.7684500e+00 1.5143051e+00 1.7168636e+00 1.9368172e+00 1.6050040e+00 1.1269424e-01 3.3818226e-01 1.3017961e+00 7.4612830e-01 1.0262619e+00 1.2443200e+00 8.2421923e-01 6.0202028e-01 2.2573593e-01 6.0017982e-01 8.4572653e-01 3.0922892e-01 5.6347978e-01 4.1317535e-01 6.0964891e-01 5.2201750e-01 7.3090905e-01 8.0245824e-01 4.1420960e-01 2.2297880e+00 1.3131802e+00 2.1734835e+00 1.8042696e+00 2.0169191e+00 2.8857511e+00 7.7598796e-01 2.5607759e+00 2.0181988e+00 2.3909895e+00 1.3770846e+00 1.5195166e+00 1.7689720e+00 1.2362756e+00 1.4651863e+00 1.5800353e+00 1.7155605e+00 3.0010211e+00 3.1712557e+00 1.2016443e+00 1.9735224e+00 1.1531953e+00 2.9937162e+00 1.1401191e+00 1.9335528e+00 2.2793947e+00 1.0403116e+00 1.1237940e+00 1.8155572e+00 2.1170640e+00 2.4166673e+00 2.8369211e+00 1.8227568e+00 1.3135522e+00 1.8005404e+00 2.5443612e+00 1.8557670e+00 1.7105814e+00 1.0313359e+00 1.7226330e+00 1.8708183e+00 1.5881025e+00 1.3131802e+00 2.1363271e+00 1.9752912e+00 1.5530527e+00 1.2366099e+00 1.4501583e+00 1.6655594e+00 1.3088083e+00 3.4342562e-01 1.4024091e+00 8.3183672e-01 1.0522594e+00 1.2712749e+00 8.5437498e-01 6.1119558e-01 3.3813251e-01 7.0016860e-01 9.2867113e-01 3.4342562e-01 5.2133179e-01 5.0855778e-01 6.3192325e-01 5.6618864e-01 7.5564478e-01 7.0462844e-01 4.5847767e-01 2.3345511e+00 1.4181033e+00 2.2624227e+00 1.9044571e+00 2.1188381e+00 2.9740725e+00 8.7209348e-01 2.6511588e+00 2.1151751e+00 2.4832720e+00 1.4692287e+00 1.6190709e+00 1.8603115e+00 1.3450304e+00 1.5778323e+00 1.6856949e+00 1.8133657e+00 3.0879393e+00 3.2627356e+00 1.3017553e+00 2.0678448e+00 1.2635708e+00 3.0810441e+00 1.2366675e+00 2.0307764e+00 2.3657459e+00 1.1404856e+00 1.2257611e+00 1.9176961e+00 2.1957105e+00 2.4980314e+00 2.9055191e+00 1.9262438e+00 1.4100098e+00 1.9004485e+00 2.6116431e+00 1.9609333e+00 1.8095574e+00 1.1347620e+00 1.8037909e+00 1.9725464e+00 1.6581521e+00 1.4181033e+00 2.2355461e+00 2.0784269e+00 1.6462102e+00 1.3373104e+00 1.5468618e+00 1.7698041e+00 1.4111252e+00 1.2003596e+00 6.1288055e-01 7.4618926e-01 9.6691372e-01 5.7609230e-01 3.0922892e-01 3.0490481e-01 5.0436965e-01 7.0184453e-01 1.1269424e-01 8.2635069e-01 3.0482299e-01 3.3813251e-01 3.0490481e-01 4.5148429e-01 9.3308891e-01 2.0181667e-01 2.1221982e+00 1.2089191e+00 2.0305682e+00 1.7009400e+00 1.9088256e+00 2.7434081e+00 9.1894698e-01 2.4265154e+00 1.9046790e+00 2.2453370e+00 1.2284047e+00 1.4060413e+00 1.6267848e+00 1.1281352e+00 1.3523310e+00 1.4562730e+00 1.6032169e+00 2.8519346e+00 3.0369970e+00 1.1020600e+00 1.8342569e+00 1.0426638e+00 2.8491513e+00 1.0116721e+00 1.8114932e+00 2.1335035e+00 9.1552373e-01 1.0090312e+00 1.7079369e+00 1.9522117e+00 2.2566913e+00 2.6406601e+00 1.7139238e+00 1.2013529e+00 1.7000137e+00 2.3442222e+00 1.7386523e+00 1.6019500e+00 9.1449234e-01 1.5517970e+00 1.7435092e+00 1.3757183e+00 1.2089191e+00 2.0167186e+00 1.8496945e+00 1.3938438e+00 1.1152390e+00 1.3189663e+00 1.5429659e+00 1.2037520e+00 6.7720957e-01 7.4262850e-01 7.0911112e-01 7.0633229e-01 1.0011648e+00 1.1020600e+00 7.2036951e-01 5.0477564e-01 1.1005460e+00 1.8106900e+00 9.0166431e-01 9.0192695e-01 9.0055475e-01 8.0055465e-01 2.1027376e+00 1.0003198e+00 1.0225570e+00 3.0474106e-01 1.1299441e+00 5.0517282e-01 7.5564478e-01 1.7513222e+00 1.1055799e+00 1.4140515e+00 7.8895472e-01 1.3181953e+00 5.7608844e-01 4.1315633e-01 8.1156529e-01 4.1317535e-01 8.0004523e-01 7.2044167e-01 5.2524663e-01 1.8787830e+00 1.9768256e+00 5.0001522e-01 9.4912864e-01 4.5148429e-01 1.8635775e+00 3.0915245e-01 7.8611860e-01 1.2373911e+00 3.0922892e-01 3.0922892e-01 5.7609230e-01 1.2089834e+00 1.4324608e+00 1.9471600e+00 6.3912943e-01 3.0017653e-01 5.0043842e-01 1.7149040e+00 8.6084272e-01 4.8391482e-01 3.4080442e-01 9.0668287e-01 8.6225026e-01 9.3424659e-01 3.0474106e-01 9.3861512e-01 9.5646231e-01 7.8935898e-01 3.4085233e-01 5.2491734e-01 7.8940551e-01 3.0482299e-01 6.0948506e-01 1.3000044e+00 9.3308891e-01 4.0243965e-01 5.6371422e-01 4.1212852e-01 7.0000303e-01 5.4219811e-01 1.2105001e+00 3.4342562e-01 3.6256305e-01 3.4085233e-01 8.0008964e-01 1.5005854e+00 4.1420960e-01 1.5358856e+00 6.1990228e-01 1.7849054e+00 1.1528477e+00 1.3788456e+00 2.4261894e+00 5.6370994e-01 2.0884901e+00 1.4655452e+00 1.9390732e+00 1.1074834e+00 1.0434746e+00 1.4340155e+00 6.0605366e-01 9.1554656e-01 1.0782857e+00 1.1897288e+00 2.5394068e+00 2.6516318e+00 8.3183606e-01 1.5694554e+00 5.2201750e-01 2.5386539e+00 9.0192695e-01 1.4157600e+00 1.8949500e+00 8.0097499e-01 7.0548138e-01 1.1935069e+00 1.8443040e+00 2.0853276e+00 2.5816887e+00 1.1989547e+00 9.1424659e-01 1.1138955e+00 2.3468430e+00 1.1963432e+00 1.1270327e+00 6.0365948e-01 1.5143051e+00 1.3938114e+00 1.5079206e+00 6.1990228e-01 1.5829749e+00 1.4450801e+00 1.3189240e+00 9.1132198e-01 1.1152300e+00 1.0159134e+00 6.3309012e-01 7.0096858e-01 1.1002025e+00 4.8852375e-01 9.1024401e-01 8.1112984e-01 4.0127250e-01 8.1117067e-01 1.3486924e+00 7.0633229e-01 4.6440171e-01 5.1257987e-01 5.0517282e-01 1.5260594e+00 6.1288055e-01 1.5131090e+00 7.4335736e-01 1.4549432e+00 1.1020600e+00 1.3036236e+00 2.1691920e+00 1.1527669e+00 1.8444686e+00 1.3309288e+00 1.6567564e+00 6.3925756e-01 8.5617086e-01 1.0458540e+00 9.0668287e-01 8.4540285e-01 8.5586571e-01 1.0039209e+00 2.2782572e+00 2.4540263e+00 1.2012866e+00 1.2440282e+00 6.2656178e-01 2.2782572e+00 7.0556260e-01 1.2101609e+00 1.5639802e+00 6.0219099e-01 4.5148429e-01 1.1079931e+00 1.4142064e+00 1.7087610e+00 2.1412345e+00 1.1115204e+00 6.7720957e-01 1.1281352e+00 1.8646736e+00 1.1282162e+00 1.0010209e+00 4.1315633e-01 1.0172673e+00 1.1401191e+00 9.4532171e-01 7.4335736e-01 1.4134218e+00 1.2440229e+00 8.4786353e-01 9.0557807e-01 7.2440846e-01 9.3308853e-01 6.0964891e-01 8.0296037e-01 1.1055799e+00 1.2124837e+00 1.2014191e+00 6.0000952e-01 9.3755356e-01 1.7874653e+00 1.1024913e+00 1.0032296e+00 1.0031018e+00 5.2201750e-01 1.8640262e+00 1.0088926e+00 1.3452347e+00 9.0417295e-01 1.2040344e+00 9.0168933e-01 1.1133986e+00 1.9046783e+00 1.8005318e+00 1.6009504e+00 1.1056691e+00 1.4335330e+00 5.2167829e-01 6.1990228e-01 8.2418141e-01 1.0118233e+00 1.0151880e+00 8.2458478e-01 8.0051115e-01 2.0076819e+00 2.2050331e+00 9.3329017e-01 1.0426638e+00 1.1020600e+00 2.0062587e+00 4.5847767e-01 1.0087393e+00 1.3009222e+00 5.0855778e-01 6.0202028e-01 9.1471442e-01 1.1019505e+00 1.4044980e+00 1.7386523e+00 9.3351278e-01 4.5783248e-01 9.1892454e-01 1.4407364e+00 1.0151880e+00 8.0093081e-01 7.0088627e-01 7.4269200e-01 1.0142482e+00 8.0250123e-01 9.0417295e-01 1.2189645e+00 1.1269510e+00 8.0879701e-01 6.1990228e-01 5.6371422e-01 8.6084272e-01 8.0291749e-01 7.8935813e-01 8.0250123e-01 8.0046685e-01 7.0017011e-01 5.2491734e-01 1.3741813e+00 7.0470720e-01 7.4269314e-01 6.7626502e-01 6.0000635e-01 1.4852616e+00 6.3309012e-01 1.6636721e+00 7.5826453e-01 1.5161847e+00 1.2049539e+00 1.4220925e+00 2.2191056e+00 1.4001717e+00 1.9083789e+00 1.4007861e+00 1.7945122e+00 9.6133119e-01 9.1552373e-01 1.1416778e+00 7.7603846e-01 1.1170561e+00 1.1351073e+00 1.1152390e+00 2.3540839e+00 2.5167781e+00 6.0202028e-01 1.3687074e+00 8.0713433e-01 2.3222107e+00 5.7608844e-01 1.3563898e+00 1.6193612e+00 5.7609230e-01 7.3090905e-01 1.2201578e+00 1.4221192e+00 1.7236083e+00 2.1360791e+00 1.2373857e+00 7.1629168e-01 1.2000731e+00 1.7962160e+00 1.3755348e+00 1.1298552e+00 7.2113820e-01 1.0843962e+00 1.3150470e+00 1.0664292e+00 7.5826453e-01 1.5362595e+00 1.4451976e+00 1.0604287e+00 6.7626502e-01 8.9540816e-01 1.2552585e+00 8.0073117e-01 5.0001522e-01 4.1212852e-01 5.6347549e-01 4.0127250e-01 8.7240114e-01 3.0008832e-01 1.2085435e-01 1.2085435e-01 6.0017982e-01 1.1038933e+00 2.0061436e-01 1.9231154e+00 1.0088926e+00 1.8971338e+00 1.5035330e+00 1.7143629e+00 2.6071033e+00 7.2440846e-01 2.2781292e+00 1.7231818e+00 2.0998984e+00 1.0923537e+00 1.2224463e+00 1.4922544e+00 9.3733589e-01 1.1896725e+00 1.2782589e+00 1.4186216e+00 2.7177641e+00 2.8857013e+00 9.6674360e-01 1.6882618e+00 8.5406616e-01 2.7167827e+00 8.6084272e-01 1.6345263e+00 2.0058565e+00 7.5508853e-01 8.1715593e-01 1.5132180e+00 1.8635428e+00 2.1554613e+00 2.5926811e+00 1.5194972e+00 1.0207533e+00 1.5005626e+00 2.3165875e+00 1.5429659e+00 1.4098467e+00 7.2036819e-01 1.4724918e+00 1.5757929e+00 1.3838027e+00 1.0088926e+00 1.8378491e+00 1.6745686e+00 1.2948699e+00 9.4912864e-01 1.1635325e+00 1.3473688e+00 1.0032293e+00 4.0004442e-01 6.9509552e-01 3.0017653e-01 7.1708289e-01 2.2573593e-01 5.0085236e-01 4.0243965e-01 7.0548138e-01 1.0008617e+00 3.0482299e-01 2.0206913e+00 1.1056785e+00 2.0075255e+00 1.6053217e+00 1.8156855e+00 2.7170183e+00 6.3912709e-01 2.3873965e+00 1.8286172e+00 2.2132187e+00 1.2079042e+00 1.3276450e+00 1.6018644e+00 1.0207396e+00 1.2397507e+00 1.3715471e+00 1.5245240e+00 2.8327619e+00 2.9941199e+00 1.0032443e+00 1.7962160e+00 9.3329055e-01 2.8269181e+00 9.6936870e-01 1.7435156e+00 2.1174156e+00 8.6084272e-01 9.2351241e-01 1.6144550e+00 1.9761215e+00 2.2674248e+00 2.7114616e+00 1.6190709e+00 1.1282247e+00 1.6009322e+00 2.4285500e+00 1.6432478e+00 1.5147271e+00 8.2512420e-01 1.5839544e+00 1.6753044e+00 1.4829434e+00 1.1056785e+00 1.9427965e+00 1.7734131e+00 1.3908238e+00 1.0498226e+00 1.2712749e+00 1.4523130e+00 1.1044111e+00 6.0980961e-01 4.1209001e-01 1.1020600e+00 2.0181667e-01 4.0243965e-01 3.0922892e-01 7.0088627e-01 1.4001688e+00 3.0922892e-01 1.6797901e+00 7.8935898e-01 1.7574606e+00 1.2224463e+00 1.4618181e+00 2.4274025e+00 6.3165225e-01 2.0887499e+00 1.4865883e+00 1.9561612e+00 1.0664292e+00 1.0336863e+00 1.3939836e+00 8.2421923e-01 1.2089895e+00 1.1997296e+00 1.1938630e+00 2.5462062e+00 2.6763758e+00 6.4049114e-01 1.5645185e+00 8.0883916e-01 2.5391583e+00 8.3183672e-01 1.4351453e+00 1.8644317e+00 7.4618926e-01 6.9987517e-01 1.2680580e+00 1.7844580e+00 2.0440071e+00 2.5329067e+00 1.2921474e+00 8.5440680e-01 1.2036924e+00 2.2838099e+00 1.3737025e+00 1.1587585e+00 6.4620889e-01 1.4491800e+00 1.4507713e+00 1.4583848e+00 7.8935898e-01 1.6277433e+00 1.5384791e+00 1.3150470e+00 8.7209348e-01 1.0788651e+00 1.2179890e+00 7.4954884e-01 6.1135434e-01 1.3790270e+00 5.2491734e-01 4.5147187e-01 4.5080200e-01 3.0026460e-01 1.6179159e+00 5.2167829e-01 1.4543196e+00 5.6838732e-01 1.3502290e+00 1.0008620e+00 1.2192919e+00 2.0611274e+00 1.2013529e+00 1.7369589e+00 1.2053003e+00 1.5767956e+00 6.3925756e-01 7.1779518e-01 9.6131279e-01 6.4620889e-01 1.0032443e+00 9.3331138e-01 9.0279223e-01 2.1713885e+00 2.3476282e+00 8.0245903e-01 1.1755517e+00 6.3322667e-01 2.1693131e+00 4.2362917e-01 1.1187430e+00 1.4544336e+00 4.0246123e-01 4.1209001e-01 1.0208844e+00 1.3018144e+00 1.5969056e+00 2.0303761e+00 1.0427944e+00 5.0085236e-01 1.0008465e+00 1.7574039e+00 1.1274284e+00 9.0166476e-01 4.0125062e-01 9.3437551e-01 1.1319099e+00 9.6935134e-01 5.6838732e-01 1.3309288e+00 1.2428507e+00 9.2745734e-01 5.7630313e-01 6.8160885e-01 9.6672602e-01 5.2167208e-01 8.5440680e-01 2.2608083e-01 4.0125062e-01 3.0490481e-01 4.2270142e-01 1.0207262e+00 2.0181667e-01 2.0282636e+00 1.1133895e+00 1.9386586e+00 1.6012719e+00 1.8114342e+00 2.6515677e+00 9.0999313e-01 2.3322945e+00 1.8060515e+00 2.1578375e+00 1.1447365e+00 1.3085752e+00 1.5359734e+00 1.0426516e+00 1.3018144e+00 1.3779960e+00 1.5044724e+00 2.7627283e+00 2.9432651e+00 1.0010209e+00 1.7447170e+00 9.6576136e-01 2.7579768e+00 9.1892454e-01 1.7159977e+00 2.0420308e+00 8.2635069e-01 9.1576742e-01 1.6105700e+00 1.8662195e+00 2.1696258e+00 2.5680120e+00 1.6184785e+00 1.1020600e+00 1.6000183e+00 2.2731185e+00 1.6529028e+00 1.5029725e+00 8.2635069e-01 1.4699000e+00 1.6570292e+00 1.3301857e+00 1.1133895e+00 1.9214944e+00 1.7646791e+00 1.3272142e+00 1.0235120e+00 1.2275665e+00 1.4621584e+00 1.1060939e+00 9.1576742e-01 9.6133119e-01 9.4532171e-01 1.2662318e+00 3.0490481e-01 8.6084272e-01 2.7230933e+00 1.8083405e+00 2.7192500e+00 2.3152780e+00 2.5278895e+00 3.4307167e+00 1.2089253e+00 3.1023107e+00 2.5446557e+00 2.9238544e+00 1.9071235e+00 2.0445123e+00 2.3113306e+00 1.7148932e+00 1.8686471e+00 2.0692591e+00 2.2408459e+00 3.5448121e+00 3.7102716e+00 1.7134856e+00 2.5076804e+00 1.6187837e+00 3.5398901e+00 1.6780493e+00 2.4594169e+00 2.8277283e+00 1.5698091e+00 1.6365650e+00 2.3270565e+00 2.6739856e+00 2.9710335e+00 3.3954286e+00 2.3304578e+00 1.8446316e+00 2.3054869e+00 3.1050823e+00 2.3405162e+00 2.2288004e+00 1.5327217e+00 2.2740189e+00 2.3840998e+00 2.1122339e+00 1.8083405e+00 2.6588338e+00 2.4791402e+00 2.0688078e+00 1.7632513e+00 1.9828965e+00 2.1428811e+00 1.8095574e+00 3.0017653e-01 2.0061436e-01 6.0017982e-01 1.2012991e+00 1.2085435e-01 1.8301371e+00 9.1424659e-01 1.8223693e+00 1.4049093e+00 1.6190709e+00 2.5271432e+00 7.0556260e-01 2.1953731e+00 1.6303102e+00 2.0261311e+00 1.0363096e+00 1.1330692e+00 1.4229011e+00 8.5406674e-01 1.1527746e+00 1.2106302e+00 1.3261864e+00 2.6410980e+00 2.8004332e+00 8.1117067e-01 1.6146557e+00 7.8886054e-01 2.6375763e+00 7.9824795e-01 1.5471213e+00 1.9317133e+00 6.9509552e-01 7.3155911e-01 1.4182194e+00 1.8031267e+00 2.0887452e+00 2.5422790e+00 1.4267527e+00 9.3308891e-01 1.4006149e+00 2.2706274e+00 1.4614246e+00 1.3141581e+00 6.4049114e-01 1.4230277e+00 1.5004249e+00 1.3669148e+00 9.1424659e-01 1.7490906e+00 1.5981930e+00 1.2553121e+00 8.7212232e-01 1.0924484e+00 1.2731059e+00 9.0557807e-01 1.1269424e-01 5.0002283e-01 1.2049541e+00 2.0121983e-01 1.8447840e+00 9.3329055e-01 1.7901165e+00 1.4035225e+00 1.6222582e+00 2.4980210e+00 8.1757693e-01 2.1693127e+00 1.6187837e+00 2.0049100e+00 1.0151397e+00 1.1261381e+00 1.3938113e+00 9.0657539e-01 1.2362756e+00 1.2472959e+00 1.3154932e+00 2.6088344e+00 2.7785257e+00 9.0207914e-01 1.5972548e+00 8.5406674e-01 2.6071034e+00 7.7652636e-01 1.5358856e+00 1.8953567e+00 6.9518117e-01 7.4612718e-01 1.4220925e+00 1.7511588e+00 2.0440071e+00 2.4804818e+00 1.4362913e+00 9.1449234e-01 1.4003402e+00 2.2077377e+00 1.4867147e+00 1.3085752e+00 6.7720780e-01 1.3734975e+00 1.5100598e+00 1.3269962e+00 9.3329055e-01 1.7441015e+00 1.6143613e+00 1.2552584e+00 8.7796615e-01 1.0782751e+00 1.3029195e+00 9.1424659e-01 5.0000761e-01 1.2040406e+00 1.1269424e-01 1.8289847e+00 9.1424701e-01 1.7872748e+00 1.4023776e+00 1.6144390e+00 2.4974488e+00 8.0533198e-01 2.1691714e+00 1.6179842e+00 1.9948417e+00 9.9013884e-01 1.1186586e+00 1.3842454e+00 8.5583357e-01 1.1527671e+00 1.1990152e+00 1.3139296e+00 2.6085083e+00 2.7775771e+00 8.5440680e-01 1.5835478e+00 7.8886139e-01 2.6068470e+00 7.5508853e-01 1.5300146e+00 1.8950932e+00 6.5712813e-01 7.2036951e-01 1.4134189e+00 1.7511120e+00 2.0435901e+00 2.4807480e+00 1.4220898e+00 9.1424701e-01 1.4002005e+00 2.2048860e+00 1.4562730e+00 1.3069754e+00 6.3309258e-01 1.3632211e+00 1.4815986e+00 1.2921474e+00 9.1424701e-01 1.7351894e+00 1.5836236e+00 1.2085436e+00 8.4725834e-01 1.0597879e+00 1.2653025e+00 9.0508756e-01 1.3743342e+00 5.0043084e-01 1.7369589e+00 8.2635069e-01 1.6144390e+00 1.3008770e+00 1.5131090e+00 2.3226028e+00 1.3004854e+00 2.0107294e+00 1.5010034e+00 1.8390199e+00 8.5471446e-01 1.0087539e+00 1.2223855e+00 8.0073117e-01 1.1286018e+00 1.1270411e+00 1.2013529e+00 2.4290388e+00 2.6198428e+00 7.8895472e-01 1.4363167e+00 7.7598796e-01 2.4266979e+00 6.3178782e-01 1.4100098e+00 1.7134977e+00 5.6347549e-01 6.3165225e-01 1.3130978e+00 1.5237265e+00 1.8289379e+00 2.1979419e+00 1.3253497e+00 8.0004602e-01 1.3000455e+00 1.9028805e+00 1.3748188e+00 1.2012991e+00 5.6371422e-01 1.1400420e+00 1.3748220e+00 1.0597992e+00 8.2635069e-01 1.6184929e+00 1.4858469e+00 1.0797702e+00 7.4612830e-01 9.3329055e-01 1.1910002e+00 8.0923926e-01 1.1056785e+00 3.0089448e+00 2.1019570e+00 2.9563162e+00 2.6052626e+00 2.8107271e+00 3.6717374e+00 1.5012719e+00 3.3522198e+00 2.8186527e+00 3.1596417e+00 2.1362161e+00 2.3151198e+00 2.5461024e+00 2.0036629e+00 2.1224665e+00 2.3234228e+00 2.5150159e+00 3.7801779e+00 3.9623034e+00 2.0033816e+00 2.7467405e+00 1.9044216e+00 3.7784933e+00 1.9231092e+00 2.7237438e+00 3.0623796e+00 1.8186729e+00 1.9089573e+00 2.6097166e+00 2.8846684e+00 3.1885494e+00 3.5706709e+00 2.6109888e+00 2.1139043e+00 2.6017555e+00 3.2706949e+00 2.6138780e+00 2.5099937e+00 1.8069857e+00 2.4748863e+00 2.6338874e+00 2.2385678e+00 2.1019570e+00 2.9251726e+00 2.7321685e+00 2.2661994e+00 2.0190735e+00 2.2288464e+00 2.4131370e+00 2.1020441e+00 1.9226845e+00 1.0087252e+00 1.8684939e+00 1.5017097e+00 1.7108631e+00 2.5816562e+00 8.0533198e-01 2.2563154e+00 1.7134977e+00 2.0770423e+00 1.0604287e+00 1.2124777e+00 1.4620239e+00 9.3329017e-01 1.1896594e+00 1.2705641e+00 1.4098496e+00 2.6923501e+00 2.8659663e+00 9.1449234e-01 1.6637458e+00 8.5403428e-01 2.6902417e+00 8.3183672e-01 1.6225614e+00 1.9757175e+00 7.3084048e-01 8.1117067e-01 1.5097082e+00 1.8197097e+00 2.1169795e+00 2.5408329e+00 1.5160570e+00 1.0087393e+00 1.5001233e+00 2.2573596e+00 1.5423651e+00 1.4049376e+00 7.1708289e-01 1.4229011e+00 1.5611429e+00 1.3142952e+00 1.0087252e+00 1.8271493e+00 1.6639408e+00 1.2552635e+00 9.2768675e-01 1.1400420e+00 1.3479052e+00 1.0031018e+00 9.3184922e-01 8.0291749e-01 7.0910969e-01 3.4342562e-01 1.3028005e+00 1.6474201e+00 1.0216374e+00 8.5586571e-01 9.0026543e-01 9.0508756e-01 7.7598796e-01 5.7832449e-01 1.0522594e+00 9.0999313e-01 7.0008735e-01 7.1708289e-01 1.4049376e+00 1.4220925e+00 1.2553121e+00 6.0202028e-01 1.1170561e+00 1.4055109e+00 1.1186497e+00 4.5783248e-01 9.3306769e-01 1.2101609e+00 1.1134939e+00 5.3914287e-01 1.0144117e+00 1.1074742e+00 1.6007365e+00 5.2491734e-01 1.0797700e+00 1.1139044e+00 1.4000349e+00 4.0004442e-01 7.1629303e-01 1.2090477e+00 6.8170466e-01 4.5148429e-01 9.1427000e-01 9.3184922e-01 5.0043842e-01 4.1209001e-01 8.0296037e-01 1.0498226e+00 8.0928056e-01 6.0018299e-01 9.3446811e-01 1.3131410e+00 5.6371422e-01 7.8985507e-01 1.8949500e+00 9.1427000e-01 1.5639785e+00 9.3308891e-01 1.4501583e+00 7.1621748e-01 6.0017665e-01 1.0010209e+00 2.0181667e-01 5.0000761e-01 6.3925756e-01 7.0548283e-01 2.0162299e+00 2.0885102e+00 5.2167829e-01 1.1079931e+00 2.2608083e-01 2.0057464e+00 5.0043084e-01 9.2747919e-01 1.4186217e+00 4.1212852e-01 3.4085233e-01 6.3178782e-01 1.4043632e+00 1.6175925e+00 2.1298991e+00 6.3309258e-01 5.2133179e-01 5.6595908e-01 1.9078843e+00 7.4418186e-01 6.1830764e-01 3.4085233e-01 1.1006468e+00 9.1132198e-01 1.1010711e+00 0.0000000e+00 1.0458540e+00 9.3984267e-01 9.0166476e-01 5.0043084e-01 7.0088627e-01 7.0993998e-01 3.0017653e-01 8.0093160e-01 6.0000635e-01 7.1621613e-01 2.2268632e+00 4.1317535e-01 5.2491734e-01 6.0964891e-01 8.2421923e-01 7.4335736e-01 4.1209001e-01 1.4186217e+00 1.3131410e+00 7.4275547e-01 6.1119267e-01 9.1566538e-01 1.0095513e+00 1.1796101e+00 2.5399984e-01 1.5237074e+00 8.2421923e-01 1.0429127e+00 4.1315633e-01 3.0490481e-01 1.1528553e+00 1.1270325e+00 7.0096708e-01 5.0001522e-01 3.1328089e-01 9.0657583e-01 7.0096858e-01 9.1568820e-01 1.0216374e+00 6.0035305e-01 8.0337471e-01 7.0548283e-01 1.2396937e+00 5.0043084e-01 4.2270142e-01 8.0008964e-01 1.3131410e+00 3.0915245e-01 4.5847767e-01 7.0470720e-01 9.6936870e-01 7.4262964e-01 9.0645118e-01 1.2190260e+00 4.0246123e-01 1.3450652e+00 1.4544312e+00 1.0207258e+00 4.5147187e-01 9.6501813e-01 5.0517282e-01 3.0490481e-01 5.0437695e-01 6.8170466e-01 6.5712813e-01 5.0855778e-01 2.0121983e-01 1.4695463e+00 1.5267750e+00 7.4395693e-01 6.3309258e-01 7.8890806e-01 1.4542932e+00 7.0008432e-01 4.5784410e-01 9.0166431e-01 8.0000160e-01 7.0008584e-01 3.0017653e-01 9.0005094e-01 1.1019505e+00 1.6144405e+00 4.0004442e-01 5.0436965e-01 4.1315633e-01 1.4012283e+00 6.3164729e-01 2.0121983e-01 8.0046685e-01 6.0219099e-01 6.0964597e-01 6.5724028e-01 5.6371422e-01 5.6838732e-01 7.0911112e-01 5.3914287e-01 6.0948506e-01 4.0246123e-01 5.6371422e-01 5.2133179e-01 1.1281267e+00 1.6745375e+00 8.1112984e-01 5.2167208e-01 7.4395693e-01 7.0016860e-01 5.0855778e-01 3.3813251e-01 9.0659977e-01 7.8895472e-01 5.0043842e-01 4.1209001e-01 1.2528048e+00 1.3020492e+00 9.3861512e-01 4.0127250e-01 1.0142766e+00 1.2362810e+00 9.0168933e-01 3.0490481e-01 7.0478886e-01 1.0010209e+00 9.0279223e-01 2.2608083e-01 7.4262850e-01 9.0055475e-01 1.4109657e+00 2.2573593e-01 7.8895472e-01 8.0492246e-01 1.2000668e+00 4.0363334e-01 4.1212852e-01 1.0039060e+00 4.5080200e-01 2.4195741e-01 7.0462844e-01 7.8985507e-01 3.0490481e-01 3.4085233e-01 6.0017982e-01 8.0928056e-01 6.0017665e-01 4.5784410e-01 7.4612718e-01 2.7992301e+00 3.6259865e-01 9.6953662e-01 6.4620889e-01 1.5401330e+00 1.4140789e+00 1.1281265e+00 2.0058560e+00 1.8949500e+00 1.4140515e+00 1.2396937e+00 8.0000239e-01 4.1317535e-01 1.8064092e+00 9.3310976e-01 2.1167364e+00 2.0181667e-01 1.7570696e+00 1.0143975e+00 6.1135434e-01 1.8661434e+00 1.8197089e+00 1.2632995e+00 8.1112909e-01 5.0126466e-01 8.0051115e-01 1.2632996e+00 1.5975200e+00 1.5266891e+00 5.0043084e-01 1.3452695e+00 1.3018553e+00 1.9314575e+00 1.2089192e+00 1.0777307e+00 1.5030978e+00 1.8949500e+00 8.5409862e-01 1.0151880e+00 1.4180463e+00 1.6742781e+00 1.4542907e+00 1.4853863e+00 1.8197089e+00 2.4725511e+00 1.8443040e+00 2.3518103e+00 1.6032169e+00 1.5066818e+00 1.9080163e+00 8.0923851e-01 9.4532171e-01 1.5109394e+00 1.6179000e+00 2.9132779e+00 2.9705619e+00 1.1020600e+00 2.0185049e+00 7.0633229e-01 2.9085831e+00 1.4001717e+00 1.8310931e+00 2.3325127e+00 1.3000908e+00 1.2016381e+00 1.5402579e+00 2.3143334e+00 2.5314248e+00 3.0393618e+00 1.5405402e+00 1.4018011e+00 1.3018553e+00 2.8185850e+00 1.4728279e+00 1.5248833e+00 1.1020506e+00 2.0036931e+00 1.8191683e+00 2.0009584e+00 9.1427000e-01 1.9534067e+00 1.8336293e+00 1.8020058e+00 1.4006178e+00 1.6026130e+00 1.3506710e+00 1.0116724e+00 6.3912709e-01 7.8890806e-01 1.2190319e+00 1.0776296e+00 8.0923926e-01 1.6740888e+00 1.5650163e+00 1.0798806e+00 9.0155438e-01 9.0417295e-01 6.4049114e-01 1.4685147e+00 6.4049114e-01 1.7843537e+00 4.5148429e-01 1.4324350e+00 6.8261201e-01 3.3813251e-01 1.5401311e+00 1.4852570e+00 9.3329055e-01 5.0043842e-01 2.0181667e-01 9.1424701e-01 9.3424697e-01 1.2633467e+00 1.2093243e+00 5.2167829e-01 1.0313359e+00 9.6574336e-01 1.5965767e+00 9.0168933e-01 7.7603846e-01 1.2016443e+00 1.5639785e+00 5.7832449e-01 7.7882758e-01 1.1074742e+00 1.3452311e+00 1.1281352e+00 1.1558746e+00 1.4852570e+00 1.1153247e+00 7.8895472e-01 5.0477564e-01 5.0855778e-01 1.0426636e+00 9.4532171e-01 7.3155911e-01 5.0476836e-01 1.3669148e+00 1.1910003e+00 8.5471446e-01 7.1629303e-01 1.1528553e+00 1.0777411e+00 9.0142636e-01 8.0046685e-01 7.1629168e-01 1.0032293e+00 9.1892413e-01 3.6452132e-01 5.6370994e-01 7.0176271e-01 1.4157327e+00 4.2362917e-01 7.0633229e-01 6.0964891e-01 1.0062544e+00 9.1554656e-01 6.0365948e-01 1.0235118e+00 6.1135434e-01 6.7626502e-01 7.5508853e-01 9.3308891e-01 7.1621884e-01 8.5403428e-01 6.5712608e-01 8.0245824e-01 6.3192325e-01 9.1132198e-01 8.6051414e-01 1.0242692e+00 1.0232576e+00 6.8685125e-01 1.5761415e+00 1.4407364e+00 9.0296858e-01 8.3689956e-01 6.3322667e-01 1.0451812e+00 1.5490134e+00 4.5847767e-01 1.6529028e+00 8.3916809e-01 1.2749306e+00 5.4219811e-01 7.0462697e-01 1.3611955e+00 1.3103292e+00 9.0792879e-01 9.1446896e-01 8.2421853e-01 7.1708289e-01 9.0683128e-01 1.1954899e+00 1.2957636e+00 6.3178534e-01 9.0508756e-01 8.7796615e-01 1.4198077e+00 7.2113820e-01 6.0427481e-01 1.0032443e+00 1.4501583e+00 4.5216167e-01 5.2491131e-01 9.1894698e-01 1.2738390e+00 9.4912864e-01 1.0207533e+00 1.3523292e+00 5.0043842e-01 4.1317535e-01 8.5403428e-01 7.0910969e-01 3.0482299e-01 4.0243965e-01 1.6491696e+00 1.8289467e+00 1.0060994e+00 6.1119267e-01 9.0142636e-01 1.6484371e+00 5.0126466e-01 6.0018299e-01 9.3308853e-01 4.2362917e-01 4.0363334e-01 5.2133802e-01 7.9153339e-01 1.0782107e+00 1.5275160e+00 5.2167829e-01 5.2167208e-01 6.9987517e-01 1.2633516e+00 5.2201750e-01 4.0127250e-01 5.0517282e-01 4.1212852e-01 5.2167829e-01 4.1210927e-01 7.1621748e-01 8.0093081e-01 6.3178782e-01 3.0922892e-01 7.0008735e-01 2.0061436e-01 3.6452132e-01 6.0035305e-01 4.1420960e-01 7.0096858e-01 6.3178782e-01 5.2132556e-01 3.0490481e-01 1.5634961e+00 1.6740875e+00 5.4219811e-01 5.8750389e-01 8.0245903e-01 1.5263478e+00 4.0004442e-01 6.1135434e-01 8.6051471e-01 5.0043842e-01 4.2270142e-01 3.0482299e-01 8.0967961e-01 1.0426513e+00 1.5757929e+00 3.3813251e-01 4.0127250e-01 5.0855778e-01 1.3133662e+00 7.1700909e-01 4.0125062e-01 5.2491734e-01 5.2167829e-01 5.2838320e-01 5.3943256e-01 6.0017665e-01 6.4620889e-01 6.8261201e-01 4.2270142e-01 3.0482299e-01 3.0026460e-01 7.0470867e-01 5.0477564e-01 1.1038840e+00 1.0010209e+00 4.0363334e-01 3.3808272e-01 1.2528049e+00 1.4182049e+00 9.2033101e-01 2.4195741e-01 1.2036925e+00 1.2362756e+00 6.3451734e-01 3.0482299e-01 5.2524663e-01 7.4335736e-01 7.4329414e-01 4.0125062e-01 5.2491131e-01 6.7636452e-01 1.1755449e+00 4.0127250e-01 6.3925756e-01 7.9148746e-01 9.1424659e-01 5.2491734e-01 4.1210927e-01 8.5437440e-01 1.2085435e-01 3.0026460e-01 4.0127250e-01 1.0010209e+00 4.0243965e-01 4.1317535e-01 3.0482299e-01 6.0444249e-01 3.3813251e-01 6.0964891e-01 9.0166431e-01 4.1212852e-01 7.8985507e-01 8.1719606e-01 2.1378157e+00 2.2009978e+00 5.0855077e-01 1.2175952e+00 3.0017653e-01 2.1167404e+00 6.0035621e-01 1.0597879e+00 1.5265797e+00 5.0517282e-01 5.2167829e-01 7.4329527e-01 1.5072282e+00 1.7227391e+00 2.2434054e+00 7.4335736e-01 6.3309258e-01 6.8161057e-01 2.0107350e+00 9.2867113e-01 7.5508853e-01 5.0517282e-01 1.2040344e+00 1.0178820e+00 1.2037520e+00 2.0181667e-01 1.1636098e+00 1.0621172e+00 1.0032443e+00 6.0000317e-01 8.0883841e-01 9.0668287e-01 5.0085236e-01 6.0964891e-01 7.4618926e-01 2.0118073e+00 2.0884859e+00 9.1424701e-01 1.1060939e+00 4.0243965e-01 2.0057764e+00 6.3178782e-01 9.1916394e-01 1.4198627e+00 6.1119267e-01 6.0219099e-01 6.3309012e-01 1.4134218e+00 1.6179000e+00 2.1265315e+00 6.3178534e-01 9.0506254e-01 1.0032443e+00 1.9078396e+00 6.5712608e-01 6.8261201e-01 6.0219099e-01 1.1003034e+00 9.0532049e-01 1.1001014e+00 5.0000761e-01 1.0433444e+00 9.1892454e-01 9.0002615e-01 5.6595908e-01 7.0470867e-01 6.1119558e-01 6.0017982e-01 5.0085236e-01 1.5275160e+00 1.6747664e+00 1.0434746e+00 5.2132556e-01 8.0533198e-01 1.5264802e+00 5.7609230e-01 4.1317535e-01 8.6051414e-01 5.7630313e-01 5.2524663e-01 4.1315633e-01 8.6054545e-01 1.0440350e+00 1.5412701e+00 4.1210927e-01 8.0250202e-01 9.1471442e-01 1.3130978e+00 3.0490481e-01 5.0043084e-01 5.7630313e-01 5.0043842e-01 3.3818226e-01 5.0043084e-01 6.3925756e-01 6.0948212e-01 4.1317535e-01 3.0482299e-01 7.0548283e-01 3.0490481e-01 2.2573593e-01 5.6394820e-01 1.3634093e+00 1.4858469e+00 8.1757693e-01 5.2201750e-01 9.1427000e-01 1.3523380e+00 6.0201716e-01 3.4342562e-01 7.1629168e-01 7.0096708e-01 6.0948212e-01 3.0490481e-01 7.0096708e-01 9.1424701e-01 1.4267554e+00 4.0127250e-01 4.1420960e-01 4.8342635e-01 1.2049539e+00 6.0964891e-01 1.1269424e-01 7.1621613e-01 4.1212852e-01 6.0018299e-01 5.3914287e-01 7.0548283e-01 5.2524663e-01 7.0105084e-01 5.0476836e-01 5.6371422e-01 3.0474106e-01 5.2491734e-01 6.0948212e-01 1.2000065e+00 2.0187441e+00 1.0498228e+00 2.2315584e+00 1.0000152e+00 1.8808952e+00 1.1286798e+00 7.5826453e-01 1.9821126e+00 1.9334872e+00 1.4094023e+00 9.7944085e-01 1.0090312e+00 3.0915245e-01 1.4094022e+00 1.7226330e+00 1.6785116e+00 8.2418071e-01 1.4544336e+00 1.4183053e+00 2.0448570e+00 1.3189240e+00 1.1989547e+00 1.6071563e+00 2.0162299e+00 9.7599312e-01 1.1287691e+00 1.5299044e+00 1.8304280e+00 1.5694554e+00 1.5966664e+00 1.9334872e+00 2.0448570e+00 1.2223853e+00 2.3135239e+00 3.0915245e-01 2.0415522e+00 1.2703001e+00 9.2351241e-01 2.1487275e+00 2.0854181e+00 1.4650300e+00 1.1157320e+00 8.0296037e-01 1.2013591e+00 1.4650276e+00 1.8684939e+00 1.6818191e+00 8.0245746e-01 1.5324961e+00 1.5271597e+00 2.1953922e+00 1.5071120e+00 1.3457716e+00 1.8029854e+00 2.0885102e+00 1.0837575e+00 1.2703001e+00 1.7133162e+00 1.9522053e+00 1.7369702e+00 1.6941963e+00 2.0286286e+00 1.1213597e+00 6.3912943e-01 1.9163315e+00 5.0855778e-01 1.1310337e+00 1.3142952e+00 6.0219099e-01 8.0046764e-01 7.2904264e-01 1.2366099e+00 1.4559030e+00 2.0467625e+00 7.7882758e-01 6.0184622e-01 6.0948800e-01 1.7296063e+00 1.2395260e+00 9.0668287e-01 8.0051036e-01 1.0231745e+00 1.0411548e+00 1.0543951e+00 5.2167829e-01 1.1356187e+00 1.2079042e+00 9.3439622e-01 4.2268438e-01 8.1719606e-01 1.2192978e+00 8.0046764e-01 1.3133662e+00 1.0434746e+00 8.3916809e-01 2.2573593e-01 5.0855077e-01 9.3848935e-01 9.0659977e-01 5.2167829e-01 7.0096858e-01 5.5450500e-01 1.0287902e+00 5.2133802e-01 8.4725834e-01 9.7599312e-01 8.0250123e-01 6.0018299e-01 5.6371422e-01 1.0171340e+00 3.0482299e-01 2.0181667e-01 6.0000317e-01 1.1079931e+00 2.0061436e-01 2.2573593e-01 5.0084481e-01 8.1683095e-01 5.2524663e-01 7.0096708e-01 1.0116865e+00 2.2278855e+00 7.0008584e-01 1.1298552e+00 1.6300950e+00 6.0017982e-01 5.0084481e-01 8.5403428e-01 1.6097507e+00 1.8284464e+00 2.3350903e+00 8.5406616e-01 7.1629168e-01 7.5508853e-01 2.1138813e+00 8.1683095e-01 8.2462252e-01 4.0246123e-01 1.3009222e+00 1.1139906e+00 1.3000951e+00 2.2608083e-01 1.2636227e+00 1.1315710e+00 1.1002119e+00 7.0088627e-01 9.0029018e-01 6.9600743e-01 3.1328089e-01 1.8661354e+00 1.1286798e+00 7.2044167e-01 1.9755679e+00 1.9314520e+00 1.3741466e+00 9.0645118e-01 6.0184622e-01 1.0001751e+00 1.3741498e+00 1.7083042e+00 1.6308665e+00 6.0201716e-01 1.4559030e+00 1.4140789e+00 2.0433026e+00 1.3131370e+00 1.1900969e+00 1.6049479e+00 2.0057464e+00 9.6691372e-01 1.1304042e+00 1.5237285e+00 1.7843627e+00 1.5639785e+00 1.5975352e+00 1.9314520e+00 8.2671175e-01 1.1543257e+00 1.2085435e-01 3.0474106e-01 7.0088627e-01 1.0144117e+00 1.3018103e+00 1.7709153e+00 7.0462844e-01 3.0482299e-01 7.0470867e-01 1.4857440e+00 8.1457587e-01 6.0948506e-01 3.3813251e-01 6.4049114e-01 7.4954884e-01 6.3925756e-01 5.0043084e-01 1.0090834e+00 8.7372177e-01 5.2838320e-01 2.0121983e-01 3.4342562e-01 7.3084171e-01 4.1315633e-01 5.0855778e-01 9.1024401e-01 8.2498722e-01 5.0436965e-01 5.6595908e-01 7.2044167e-01 1.2101609e+00 5.0437695e-01 6.9987517e-01 8.1457660e-01 1.0010209e+00 4.1212852e-01 3.4342562e-01 9.3351278e-01 3.0915245e-01 3.0482299e-01 6.0052920e-01 9.2747919e-01 2.2608083e-01 4.0000000e-01 5.0476836e-01 8.5586571e-01 5.0477564e-01 5.0477564e-01 8.2498722e-01 1.2635707e+00 1.2396421e+00 8.0533198e-01 2.4170870e-01 4.0127250e-01 7.4618926e-01 8.0726668e-01 1.0151880e+00 1.1066159e+00 5.6371422e-01 9.1554656e-01 8.0879701e-01 1.3523345e+00 6.0366256e-01 6.3912943e-01 9.0532093e-01 1.4186217e+00 5.2133179e-01 7.1700909e-01 8.1719606e-01 1.0923439e+00 8.5409862e-01 1.0116865e+00 1.3253496e+00 2.0121983e-01 8.0051036e-01 1.1269596e+00 1.4140457e+00 1.8721285e+00 8.0250123e-01 3.3813251e-01 8.0250202e-01 1.5969056e+00 8.4536936e-01 7.0096708e-01 2.2538848e-01 7.4395693e-01 8.3222261e-01 7.1779518e-01 4.1212852e-01 1.1079931e+00 9.4151244e-01 5.7630313e-01 3.0490481e-01 4.1420960e-01 6.9509395e-01 3.4080442e-01 7.0184453e-01 1.1527745e+00 1.4140486e+00 1.8971345e+00 7.0556260e-01 3.1328089e-01 7.0910969e-01 1.6486410e+00 7.4618926e-01 6.0184622e-01 1.1269424e-01 8.0923926e-01 7.7598796e-01 8.0883916e-01 3.4085233e-01 1.0235254e+00 8.7240114e-01 6.3309012e-01 5.0043842e-01 4.1315633e-01 5.7609230e-01 2.2538848e-01 8.0888055e-01 1.0030868e+00 1.5299044e+00 1.0000000e-01 6.3164977e-01 7.0096708e-01 1.3008855e+00 6.0184622e-01 3.3813251e-01 8.0296037e-01 5.0476836e-01 3.6256305e-01 5.6618864e-01 6.3178782e-01 4.5847767e-01 5.2491734e-01 4.1420960e-01 6.0202028e-01 4.0127250e-01 6.0052920e-01 5.6618864e-01 3.4342562e-01 8.7372177e-01 8.2425704e-01 9.3308891e-01 1.1005554e+00 7.1700774e-01 9.6674360e-01 8.0051115e-01 1.2632995e+00 5.2491734e-01 8.0883916e-01 7.8935898e-01 1.4043632e+00 7.0470867e-01 9.0532093e-01 7.5502989e-01 9.6953662e-01 7.4612718e-01 1.0222576e+00 1.3061180e+00 1.0032296e+00 1.0032293e+00 1.1900276e+00 1.3017553e+00 4.1315633e-01 1.1093621e+00 1.0088783e+00 1.5263498e+00 7.1708289e-01 7.3155911e-01 1.0040629e+00 1.6175925e+00 6.1845783e-01 7.5826453e-01 9.3426769e-01 1.2396937e+00 1.0142626e+00 1.2128138e+00 1.5237074e+00 1.5299064e+00 1.6885111e+00 1.8315348e+00 8.0097499e-01 1.6050900e+00 1.5160591e+00 2.0074169e+00 1.1389082e+00 1.2275665e+00 1.3502668e+00 2.1298991e+00 1.1075720e+00 1.2113964e+00 1.3632538e+00 1.7639471e+00 1.4922544e+00 1.7133283e+00 2.0290146e+00 7.1621748e-01 8.0051036e-01 1.3008813e+00 6.0017982e-01 4.1210927e-01 8.0492246e-01 5.0477564e-01 3.4080442e-01 5.6595908e-01 6.3309258e-01 4.5784410e-01 5.0855778e-01 4.1317535e-01 6.0366256e-01 4.0246123e-01 6.0035621e-01 5.7630313e-01 5.0085236e-01 1.4407390e+00 9.1892413e-01 4.2270142e-01 3.6452132e-01 6.7824250e-01 9.0668287e-01 8.2458409e-01 5.2133179e-01 9.0792879e-01 1.0124729e+00 8.0250202e-01 4.1210927e-01 5.0085236e-01 8.2458478e-01 4.1315633e-01 1.6100639e+00 1.0426636e+00 5.2491734e-01 8.0488008e-01 8.6054545e-01 1.0116721e+00 9.7291273e-01 5.6595908e-01 9.4532171e-01 1.1186499e+00 9.1681464e-01 6.3178782e-01 6.2656178e-01 9.6574369e-01 5.3943256e-01 1.4007831e+00 1.3033860e+00 1.7572550e+00 8.5406674e-01 1.0030724e+00 1.0426513e+00 1.9078843e+00 9.0005048e-01 1.0010209e+00 1.0776188e+00 1.4549432e+00 1.2363278e+00 1.5032156e+00 1.8103044e+00 6.0184934e-01 8.2671175e-01 6.0383105e-01 4.1209001e-01 6.3309258e-01 7.4418186e-01 5.0477564e-01 4.0006662e-01 4.8342635e-01 9.1892413e-01 4.8391482e-01 2.0121983e-01 6.4620889e-01 7.0462697e-01 5.0436965e-01 6.0184622e-01 5.7608844e-01 6.1830764e-01 5.3914287e-01 7.0105084e-01 5.0855778e-01 6.3165225e-01 3.0490481e-01 5.0477564e-01 5.2133179e-01 9.1446938e-01 8.7209348e-01 9.0532093e-01 3.4085233e-01 1.1298636e+00 9.6150595e-01 7.2036819e-01 5.0477564e-01 5.2167208e-01 6.3925756e-01 3.0008832e-01 3.0915245e-01 3.0474106e-01 1.1006468e+00 5.0043842e-01 4.1420960e-01 2.4195741e-01 6.8170466e-01 4.0127250e-01 7.0096708e-01 1.0003198e+00 5.0043084e-01 9.1132198e-01 3.0026460e-01 2.0121983e-01 4.0004442e-01 6.9987517e-01 4.5148429e-01 5.0477564e-01 8.3183672e-01 1.1010711e+00 8.0000160e-01 6.0052920e-01 2.0121983e-01 6.8161057e-01 4.1212852e-01 7.0176121e-01 1.0030721e+00 1.0458540e+00 9.3984267e-01 9.0166476e-01 5.0043084e-01 7.0088627e-01 7.0993998e-01 3.0017653e-01 2.2608083e-01 7.0008584e-01 9.3848935e-01 7.0184453e-01 6.3178534e-01 9.6936870e-01 5.0476836e-01 8.7372177e-01 5.6618864e-01 5.0477564e-01 8.7240114e-01 5.3943256e-01 3.0474106e-01 5.2167208e-01 8.0879701e-01 5.0085236e-01 9.0279268e-01 5.2133802e-01 4.2362917e-01 6.0017982e-01 5.2838320e-01 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-seuclidean-ml-iris.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-seuclidean-ml-iris.txt new file mode 100644 index 0000000000000000000000000000000000000000..3e2759df30c14c1503818cc6a400a370e8fd8e89 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-seuclidean-ml-iris.txt @@ -0,0 +1 @@ + 1.1781739e+00 8.4573383e-01 1.1040164e+00 2.6033464e-01 1.0391769e+00 6.5951091e-01 2.6643250e-01 1.6215602e+00 9.6424206e-01 5.8926015e-01 4.4417668e-01 1.2158053e+00 1.5196051e+00 1.4342986e+00 2.2147971e+00 1.0267382e+00 1.3103399e-01 1.0246015e+00 7.0646671e-01 4.6190224e-01 5.3352899e-01 6.8496652e-01 6.2944414e-01 5.1453676e-01 1.1649855e+00 3.8639663e-01 1.3340137e-01 2.6033464e-01 8.5141186e-01 9.9757114e-01 5.0629646e-01 1.3963590e+00 1.6851313e+00 9.6424206e-01 7.1143905e-01 4.8636669e-01 9.6424206e-01 1.4309353e+00 2.3749211e-01 1.8699153e-01 2.8644037e+00 1.0938603e+00 5.4968254e-01 7.9227302e-01 1.2158053e+00 7.0111465e-01 9.1831777e-01 5.2374483e-01 4.7680727e-01 3.4225655e+00 2.9886388e+00 3.5231786e+00 3.4844976e+00 3.4140450e+00 2.8802393e+00 3.0292175e+00 2.9585178e+00 3.2500773e+00 2.8104851e+00 3.8076036e+00 2.7718515e+00 3.6661618e+00 3.0567513e+00 2.4313960e+00 3.1540282e+00 2.7718124e+00 2.7494216e+00 4.0917474e+00 3.0136333e+00 3.0855821e+00 2.8833448e+00 3.7756717e+00 3.0462644e+00 3.0262994e+00 3.1582448e+00 3.6064873e+00 3.6179250e+00 3.0140884e+00 2.7108793e+00 3.1480683e+00 3.0769261e+00 2.8006021e+00 3.5140011e+00 2.7293962e+00 2.7724816e+00 3.3142477e+00 3.8377035e+00 2.4725633e+00 3.1307104e+00 3.0248446e+00 2.9240118e+00 2.9852014e+00 3.1515797e+00 2.8921724e+00 2.4678110e+00 2.6524994e+00 2.9083443e+00 2.7444686e+00 2.7478281e+00 4.2652803e+00 3.6712837e+00 4.4571526e+00 3.7518856e+00 4.1563042e+00 5.0327536e+00 3.5110505e+00 4.5914343e+00 4.4347154e+00 4.7605836e+00 3.6465897e+00 3.9644198e+00 4.1403419e+00 3.9458900e+00 4.0035735e+00 3.9244083e+00 3.7394250e+00 5.1213512e+00 5.6085412e+00 4.1515197e+00 4.3260896e+00 3.5311267e+00 5.2010517e+00 3.7194928e+00 4.0104626e+00 4.2547108e+00 3.5326627e+00 3.3344440e+00 4.1152831e+00 4.1647603e+00 4.7306329e+00 5.0503286e+00 4.1958529e+00 3.4649010e+00 3.7290073e+00 5.0848756e+00 4.0161825e+00 3.6208873e+00 3.2588014e+00 4.1126592e+00 4.3082433e+00 4.1887411e+00 3.6712837e+00 4.3324309e+00 4.3552675e+00 4.1561376e+00 4.0674499e+00 3.7933592e+00 3.8117183e+00 3.3250640e+00 5.2374483e-01 4.3319335e-01 1.3890415e+00 2.1841707e+00 9.9973471e-01 9.3211669e-01 6.4636269e-01 2.7124234e-01 1.7245677e+00 9.3727156e-01 1.7819563e-01 7.5570839e-01 2.5520912e+00 3.3809114e+00 2.1782802e+00 1.1854382e+00 2.0937104e+00 1.8662528e+00 1.1155937e+00 1.6542533e+00 1.4482752e+00 8.4881492e-01 9.7259094e-01 1.6562722e-01 9.7322023e-01 1.2100516e+00 9.9111027e-01 5.3286499e-01 2.8394141e-01 1.1346946e+00 2.5666454e+00 2.8608436e+00 2.7124234e-01 4.9009568e-01 1.3630799e+00 2.7124234e-01 6.0647055e-01 9.5529726e-01 1.1682143e+00 1.6911681e+00 7.6195008e-01 1.2774622e+00 1.9003949e+00 1.7819563e-01 1.8642334e+00 5.8652824e-01 1.6860841e+00 7.0235100e-01 3.5517185e+00 3.0793995e+00 3.5669733e+00 2.7166736e+00 3.1838913e+00 2.5120824e+00 3.1938169e+00 2.0428688e+00 3.1039816e+00 2.2561090e+00 2.8016158e+00 2.6226738e+00 2.9050141e+00 2.8502197e+00 2.0976260e+00 3.1846091e+00 2.5890531e+00 2.2584354e+00 3.4434621e+00 2.3329638e+00 3.1272801e+00 2.5616006e+00 3.3203580e+00 2.7436923e+00 2.8484236e+00 3.0948526e+00 3.4151452e+00 3.5708989e+00 2.7939968e+00 2.0736054e+00 2.3834491e+00 2.2886612e+00 2.3204706e+00 3.1632397e+00 2.5205525e+00 3.0112889e+00 3.3433635e+00 3.2300528e+00 2.2657938e+00 2.4705763e+00 2.4462190e+00 2.8038852e+00 2.4332562e+00 2.2089299e+00 2.4060762e+00 2.2734727e+00 2.3627180e+00 2.7012637e+00 1.8976741e+00 2.3590971e+00 4.3837112e+00 3.3195686e+00 4.4453895e+00 3.6018522e+00 4.1012355e+00 5.0512932e+00 2.8774753e+00 4.5344585e+00 4.0827835e+00 5.0801762e+00 3.7291677e+00 3.6888814e+00 4.1064223e+00 3.4625304e+00 3.7552252e+00 3.9939605e+00 3.6781201e+00 5.5433523e+00 5.4381439e+00 3.4976392e+00 4.4223824e+00 3.2288234e+00 5.1217596e+00 3.4157742e+00 4.1643077e+00 4.3726405e+00 3.2842292e+00 3.2296198e+00 3.9190152e+00 4.1591876e+00 4.6244312e+00 5.4884429e+00 4.0035368e+00 3.2202996e+00 3.3301365e+00 5.1089381e+00 4.2054648e+00 3.6234874e+00 3.1421933e+00 4.1502382e+00 4.3306814e+00 4.2256435e+00 3.3195686e+00 4.4219948e+00 4.4973329e+00 4.1152664e+00 3.6487297e+00 3.7329401e+00 4.0033827e+00 3.2017663e+00 2.8394141e-01 9.9272943e-01 1.8549949e+00 4.9772204e-01 5.9738093e-01 7.8305765e-01 3.7622328e-01 1.4342986e+00 5.0621589e-01 4.9772204e-01 6.9001472e-01 2.2742100e+00 3.0330374e+00 1.8410898e+00 8.5582452e-01 1.8552074e+00 1.4758765e+00 9.8932340e-01 1.2824303e+00 9.4580058e-01 7.0175090e-01 5.8564715e-01 6.1067563e-01 6.6453319e-01 9.2528705e-01 7.6195008e-01 1.7002750e-01 3.1093967e-01 1.0044375e+00 2.1686473e+00 2.5011215e+00 3.7622328e-01 3.6669623e-01 1.1883075e+00 3.7622328e-01 5.8652824e-01 6.7745878e-01 7.9191984e-01 2.0937821e+00 3.6228991e-01 9.5582164e-01 1.5272557e+00 4.9772204e-01 1.4755007e+00 1.3340137e-01 1.3666101e+00 4.3319335e-01 3.7283414e+00 3.2257816e+00 3.7651559e+00 3.1082143e+00 3.4606263e+00 2.7705999e+00 3.2962379e+00 2.4179023e+00 3.3643791e+00 2.5175848e+00 3.2317517e+00 2.8135312e+00 3.3502574e+00 3.0859108e+00 2.3316915e+00 3.3832002e+00 2.7540885e+00 2.5906747e+00 3.8459512e+00 2.7110494e+00 3.2296198e+00 2.8510843e+00 3.6612067e+00 3.0231940e+00 3.1083626e+00 3.3221751e+00 3.6999785e+00 3.7824508e+00 3.0223050e+00 2.4549511e+00 2.7813487e+00 2.6993734e+00 2.6424988e+00 3.4348309e+00 2.6680185e+00 3.0548262e+00 3.5357687e+00 3.6340473e+00 2.4474337e+00 2.8211532e+00 2.7662396e+00 3.0069386e+00 2.7817508e+00 2.6121651e+00 2.7000040e+00 2.4677010e+00 2.5915377e+00 2.9544131e+00 2.2712863e+00 2.6277952e+00 4.4682388e+00 3.5629824e+00 4.6484688e+00 3.8140427e+00 4.2790737e+00 5.2629823e+00 3.1332305e+00 4.7710813e+00 4.3977196e+00 5.1429155e+00 3.8634878e+00 3.9555042e+00 4.3021827e+00 3.7450218e+00 3.9451569e+00 4.1141318e+00 3.8729361e+00 5.5923916e+00 5.7171219e+00 3.8836634e+00 4.5660923e+00 3.4290419e+00 5.3764415e+00 3.6907517e+00 4.2782894e+00 4.5393827e+00 3.5302656e+00 3.4102235e+00 4.1476932e+00 4.3814983e+00 4.8831870e+00 5.5467550e+00 4.2276454e+00 3.4820326e+00 3.6311162e+00 5.3207972e+00 4.2656428e+00 3.7854499e+00 3.3178004e+00 4.3254709e+00 4.4873379e+00 4.3956810e+00 3.5629824e+00 4.5607328e+00 4.6030755e+00 4.3016138e+00 3.9622355e+00 3.9225802e+00 4.0577906e+00 3.3684813e+00 1.2515236e+00 2.1021589e+00 7.0646671e-01 8.4383266e-01 5.2374483e-01 3.8525820e-01 1.6876653e+00 7.3502408e-01 3.6319073e-01 5.0299964e-01 2.5372015e+00 3.2897546e+00 2.1021589e+00 1.1117653e+00 2.0978519e+00 1.7286097e+00 1.1937015e+00 1.5323598e+00 1.1874605e+00 8.6297946e-01 7.6710016e-01 5.3827772e-01 8.8540687e-01 1.1730565e+00 1.0034646e+00 2.6643250e-01 2.4808718e-01 1.2168625e+00 2.4209958e+00 2.7605308e+00 3.8525820e-01 5.6164055e-01 1.4300979e+00 3.8525820e-01 3.5266705e-01 9.1831777e-01 1.0556536e+00 1.8570904e+00 3.5266705e-01 1.1671832e+00 1.7581227e+00 3.6319073e-01 1.7245677e+00 2.3749211e-01 1.6215602e+00 6.7030885e-01 3.7702988e+00 3.2513048e+00 3.7854692e+00 2.9445918e+00 3.4252075e+00 2.6854877e+00 3.3289662e+00 2.2084365e+00 3.3482393e+00 2.3872006e+00 3.0088381e+00 2.7858967e+00 3.2051999e+00 3.0423378e+00 2.2727200e+00 3.4066596e+00 2.7026316e+00 2.4942728e+00 3.7194777e+00 2.5718070e+00 3.2266664e+00 2.8009311e+00 3.5699473e+00 2.9607930e+00 3.0876835e+00 3.3257458e+00 3.6752903e+00 3.7792524e+00 2.9772187e+00 2.3405405e+00 2.6225184e+00 2.5379456e+00 2.5530959e+00 3.3522700e+00 2.6036900e+00 3.0973166e+00 3.5528019e+00 3.5210610e+00 2.4001125e+00 2.6797931e+00 2.6323855e+00 2.9822614e+00 2.6747723e+00 2.4035668e+00 2.5939621e+00 2.4241443e+00 2.5291529e+00 2.9226858e+00 2.0959349e+00 2.5480036e+00 4.4738080e+00 3.4750769e+00 4.6459778e+00 3.7712854e+00 4.2573656e+00 5.2660922e+00 2.9665251e+00 4.7582165e+00 4.3221591e+00 5.2027091e+00 3.8786505e+00 3.8957203e+00 4.2952898e+00 3.6300721e+00 3.8796854e+00 4.1217239e+00 3.8539421e+00 5.6722969e+00 5.6818418e+00 3.7421166e+00 4.5832488e+00 3.3486395e+00 5.3611963e+00 3.6296692e+00 4.3021827e+00 4.5620086e+00 3.4793229e+00 3.3827920e+00 4.0990020e+00 4.3836503e+00 4.8653269e+00 5.6359100e+00 4.1798856e+00 3.4290065e+00 3.5331571e+00 5.3326389e+00 4.2899049e+00 3.7762521e+00 3.2871170e+00 4.3357622e+00 4.4879065e+00 4.4101806e+00 3.4750769e+00 4.5719131e+00 4.6252914e+00 4.2958117e+00 3.8764095e+00 3.9087616e+00 4.0828629e+00 3.3281063e+00 8.9980139e-01 6.8064066e-01 4.6472955e-01 1.7695601e+00 1.1682143e+00 5.3827772e-01 5.3286499e-01 1.4108003e+00 1.6357068e+00 1.3406177e+00 2.0471148e+00 8.8540687e-01 2.9145160e-01 9.8663349e-01 4.9772204e-01 6.8921053e-01 3.7371902e-01 5.3360548e-01 8.2263932e-01 5.9279023e-01 1.3884168e+00 5.4248468e-01 3.3872939e-01 5.2066928e-01 9.9757114e-01 1.1836141e+00 7.1971771e-01 1.1867923e+00 1.5097838e+00 1.1682143e+00 9.2945909e-01 6.4884272e-01 1.1682143e+00 1.5630357e+00 4.8016385e-01 2.7124234e-01 3.0617227e+00 1.1744248e+00 5.8374436e-01 6.1345624e-01 1.4108003e+00 4.9009568e-01 1.0413386e+00 4.3319335e-01 6.9189100e-01 3.5573943e+00 3.1141702e+00 3.6648465e+00 3.6881887e+00 3.5883824e+00 3.0468381e+00 3.1315658e+00 3.1515797e+00 3.4214871e+00 2.9743594e+00 4.0164863e+00 2.9182492e+00 3.8928105e+00 3.2158144e+00 2.6006889e+00 3.3027067e+00 2.9031809e+00 2.9465762e+00 4.3027855e+00 3.2186029e+00 3.1845052e+00 3.0688421e+00 3.9670252e+00 3.2223969e+00 3.2005819e+00 3.3183883e+00 3.7835219e+00 3.7624114e+00 3.1706932e+00 2.9238797e+00 3.3563322e+00 3.2896970e+00 2.9943889e+00 3.6782511e+00 2.8525048e+00 2.8501434e+00 3.4560405e+00 4.0524463e+00 2.6189855e+00 3.3240937e+00 3.2080454e+00 3.0726532e+00 3.1844624e+00 3.3537486e+00 3.0707196e+00 2.6200714e+00 2.8136838e+00 3.0798325e+00 2.9434145e+00 2.9219863e+00 4.3385668e+00 3.8211670e+00 4.5879449e+00 3.8900790e+00 4.2758494e+00 5.1630878e+00 3.6606996e+00 4.7359279e+00 4.6113949e+00 4.8204842e+00 3.7540483e+00 4.1248784e+00 4.2705921e+00 4.1081181e+00 4.1285849e+00 4.0208302e+00 3.8718630e+00 5.1706118e+00 5.7653526e+00 4.3529699e+00 4.4302351e+00 3.6643052e+00 5.3499285e+00 3.8863166e+00 4.1025634e+00 4.3705834e+00 3.6895783e+00 3.4655259e+00 4.2576017e+00 4.3078329e+00 4.8848930e+00 5.1059908e+00 4.3355275e+00 3.6287723e+00 3.9015858e+00 5.2167033e+00 4.0809175e+00 3.7394250e+00 3.3885059e+00 4.2346521e+00 4.4182506e+00 4.3085803e+00 3.8211670e+00 4.4331391e+00 4.4402220e+00 4.2825037e+00 4.2456731e+00 3.9239772e+00 3.8761056e+00 3.4480528e+00 1.5196051e+00 1.2824303e+00 2.6220224e+00 1.9839744e+00 5.4248468e-01 1.3880441e+00 2.2398377e+00 2.5185753e+00 6.5993495e-01 1.2140269e+00 2.2670334e-01 1.0140902e+00 4.4901474e-01 4.6310132e-01 1.1825559e+00 5.9738093e-01 1.2799022e+00 1.4364110e+00 1.3915110e+00 2.1479410e+00 1.2515236e+00 9.9544409e-01 1.2188859e+00 1.8419620e+00 2.0002725e+00 1.1587093e+00 6.6217390e-01 7.6869104e-01 1.9839744e+00 1.7287715e+00 9.9282597e-01 1.9839744e+00 2.4262873e+00 1.2419907e+00 1.0737552e+00 3.8557204e+00 2.0456732e+00 1.0753036e+00 4.4417668e-01 2.2089621e+00 5.0629646e-01 1.9071648e+00 5.5576380e-01 1.4985933e+00 3.3087308e+00 2.9428879e+00 3.4716469e+00 4.0891690e+00 3.6027276e+00 3.2367228e+00 2.9085289e+00 3.7111791e+00 3.3928277e+00 3.3150290e+00 4.5928107e+00 2.9594198e+00 4.2678298e+00 3.2621413e+00 2.8156205e+00 3.1507918e+00 2.9937665e+00 3.2188610e+00 4.5717893e+00 3.5888229e+00 3.0697068e+00 3.2000980e+00 4.1198780e+00 3.3377308e+00 3.2155231e+00 3.2352945e+00 3.7547729e+00 3.6294383e+00 3.2310889e+00 3.2831808e+00 3.7736317e+00 3.7263104e+00 3.2475076e+00 3.7907966e+00 2.9840079e+00 2.6164035e+00 3.2920107e+00 4.3046992e+00 2.7582086e+00 3.6782988e+00 3.5276458e+00 3.0726914e+00 3.4670753e+00 3.9103065e+00 3.3340819e+00 2.7470239e+00 2.9746673e+00 3.1328218e+00 3.4555378e+00 3.1318122e+00 4.0752096e+00 3.9330937e+00 4.3762388e+00 3.8407425e+00 4.1274362e+00 4.9032073e+00 4.0261574e+00 4.5547766e+00 4.6534818e+00 4.3582690e+00 3.5326627e+00 4.1405270e+00 4.0947877e+00 4.2953569e+00 4.1533819e+00 3.7981559e+00 3.7518931e+00 4.6218430e+00 5.6203182e+00 4.6338556e+00 4.1503558e+00 3.7655153e+00 5.1552615e+00 3.9363994e+00 3.8053980e+00 4.0787299e+00 3.7177375e+00 3.4172455e+00 4.2121483e+00 4.1116484e+00 4.7277367e+00 4.5452377e+00 4.2828893e+00 3.6617103e+00 4.0381240e+00 4.9437127e+00 3.7768622e+00 3.5869495e+00 3.3594066e+00 4.0056296e+00 4.1979142e+00 4.0739556e+00 3.9330937e+00 4.1628496e+00 4.1341118e+00 4.1117268e+00 4.3552101e+00 3.7951858e+00 3.5859295e+00 3.4280549e+00 5.0370871e-01 1.1854382e+00 8.2574748e-01 1.1968529e+00 2.9724335e-01 9.8896933e-01 1.0391769e+00 2.0112023e+00 2.6653431e+00 1.5111262e+00 6.4636269e-01 1.6262201e+00 1.1040164e+00 9.8966705e-01 9.2934901e-01 5.3040146e-01 7.1789533e-01 3.9472619e-01 1.0556536e+00 5.1318506e-01 7.7368489e-01 7.3633268e-01 5.0731024e-01 7.5303835e-01 9.7659801e-01 1.7897583e+00 2.1453760e+00 8.2574748e-01 6.9001472e-01 1.1202045e+00 8.2574748e-01 9.6424206e-01 6.2046469e-01 5.3827772e-01 2.5404386e+00 5.3988754e-01 6.7372733e-01 1.1459117e+00 9.5361455e-01 1.1160907e+00 4.7951153e-01 1.1016806e+00 5.5109043e-01 3.7667766e+00 3.2399456e+00 3.8211099e+00 3.3920086e+00 3.5974024e+00 2.9126202e+00 3.2661365e+00 2.7296888e+00 3.4884812e+00 2.6863536e+00 3.5939578e+00 2.8820992e+00 3.6783922e+00 3.1916608e+00 2.4616677e+00 3.4465420e+00 2.8051321e+00 2.8088029e+00 4.1173049e+00 2.9788024e+00 3.2021702e+00 3.0140681e+00 3.8639979e+00 3.1756883e+00 3.2362495e+00 3.4136564e+00 3.8424217e+00 3.8484723e+00 3.1221021e+00 2.7251978e+00 3.0739866e+00 3.0068046e+00 2.8468838e+00 3.5726594e+00 2.7099355e+00 2.9743925e+00 3.5889631e+00 3.9062347e+00 2.5235038e+00 3.0623697e+00 2.9777787e+00 3.0820765e+00 3.0110500e+00 2.9445347e+00 2.8809757e+00 2.5543631e+00 2.7073441e+00 3.0792230e+00 2.5679169e+00 2.7817508e+00 4.4017095e+00 3.6741422e+00 4.6939918e+00 3.8825162e+00 4.3049794e+00 5.3127345e+00 3.3002804e+00 4.8514877e+00 4.5630927e+00 5.0475012e+00 3.8518880e+00 4.0758615e+00 4.3442223e+00 3.8984747e+00 3.9980344e+00 4.0855291e+00 3.9215612e+00 5.4851910e+00 5.8312870e+00 4.1416475e+00 4.5535489e+00 3.5028870e+00 5.4694510e+00 3.8234999e+00 4.2411026e+00 4.5531893e+00 3.6365882e+00 3.4540568e+00 4.2272070e+00 4.4531017e+00 4.9839411e+00 5.4520873e+00 4.3016933e+00 3.6054769e+00 3.7985950e+00 5.3693255e+00 4.1776636e+00 3.8035129e+00 3.3594554e+00 4.3469553e+00 4.4886880e+00 4.4112274e+00 3.6741422e+00 4.5435532e+00 4.5534752e+00 4.3346048e+00 4.1329859e+00 3.9643709e+00 3.9674740e+00 3.4024060e+00 1.3630799e+00 7.1446962e-01 8.4383266e-01 2.4808718e-01 9.6424206e-01 1.2783641e+00 1.6962086e+00 2.4702874e+00 1.2824303e+00 2.9691107e-01 1.2631980e+00 9.3957399e-01 4.9617437e-01 7.4965096e-01 7.2553812e-01 4.8492463e-01 3.3125444e-01 9.2426065e-01 2.6812643e-01 3.3395426e-01 2.4808718e-01 5.8926015e-01 7.3502408e-01 5.4956349e-01 1.6376300e+00 1.9421609e+00 7.1446962e-01 4.9160020e-01 6.5622658e-01 7.1446962e-01 1.1785203e+00 1.2076330e-01 2.8845946e-01 2.6135503e+00 8.6638670e-01 5.7543116e-01 9.9282597e-01 9.6424206e-01 9.3211669e-01 6.7030885e-01 7.8100392e-01 2.3749211e-01 3.4362741e+00 2.9772187e+00 3.5154539e+00 3.2993605e+00 3.3443673e+00 2.7564382e+00 3.0285957e+00 2.7337208e+00 3.1980682e+00 2.6433553e+00 3.5789723e+00 2.6973512e+00 3.4963203e+00 2.9759207e+00 2.3127671e+00 3.1412273e+00 2.6774449e+00 2.6095931e+00 3.9436181e+00 2.8415480e+00 3.0475523e+00 2.7865107e+00 3.6589666e+00 2.9471549e+00 2.9637920e+00 3.1238401e+00 3.5511257e+00 3.5866237e+00 2.9292978e+00 2.5500042e+00 2.9620296e+00 2.8874183e+00 2.6658729e+00 3.4048426e+00 2.6224103e+00 2.7775195e+00 3.2991484e+00 3.6986035e+00 2.3717154e+00 2.9594198e+00 2.8613259e+00 2.8592001e+00 2.8393888e+00 2.9284199e+00 2.7478281e+00 2.3715604e+00 2.5423572e+00 2.8329679e+00 2.5370255e+00 2.6226761e+00 4.2550363e+00 3.5587552e+00 4.4384175e+00 3.6863990e+00 4.1157774e+00 5.0262130e+00 3.3282378e+00 4.5651798e+00 4.3425674e+00 4.8115590e+00 3.6359466e+00 3.8813909e+00 4.1126592e+00 3.8106374e+00 3.9142555e+00 3.9091502e+00 3.6969354e+00 5.1996380e+00 5.5654572e+00 3.9942942e+00 4.3261607e+00 3.4228883e+00 5.1764012e+00 3.6303894e+00 4.0165247e+00 4.2627936e+00 3.4508614e+00 3.2748167e+00 4.0461381e+00 4.1489951e+00 4.6983104e+00 5.1372583e+00 4.1280577e+00 3.3829235e+00 3.6112201e+00 5.0844328e+00 4.0217556e+00 3.5877667e+00 3.1942059e+00 4.1021303e+00 4.2899049e+00 4.1807095e+00 3.5587552e+00 4.3276502e+00 4.3608503e+00 4.1273623e+00 3.9585431e+00 3.7540483e+00 3.8154519e+00 3.2543470e+00 7.7313507e-01 2.2058495e+00 1.2553676e+00 5.5109043e-01 3.3742167e-01 3.0507869e+00 3.8084614e+00 2.6171176e+00 1.6268459e+00 2.6113513e+00 2.2457527e+00 1.6784057e+00 2.0471148e+00 1.6480463e+00 1.3225313e+00 1.2819528e+00 7.6880092e-01 1.3915110e+00 1.6886167e+00 1.5043671e+00 7.8918675e-01 6.7745878e-01 1.6911617e+00 2.9348176e+00 3.2792996e+00 7.7313507e-01 1.0082548e+00 1.9190366e+00 7.7313507e-01 2.3749211e-01 1.4309353e+00 1.5685186e+00 1.3963590e+00 6.9420840e-01 1.6514950e+00 2.2742046e+00 5.5109043e-01 2.2440749e+00 7.3283576e-01 2.1421205e+00 1.1730565e+00 4.0382971e+00 3.5072516e+00 4.0204750e+00 2.8157524e+00 3.5602797e+00 2.7716933e+00 3.6026548e+00 1.9881684e+00 3.5249607e+00 2.3719578e+00 2.7108793e+00 2.9588139e+00 3.1000099e+00 3.1914275e+00 2.3942229e+00 3.6456797e+00 2.8533918e+00 2.5518058e+00 3.6496659e+00 2.5198146e+00 3.4451131e+00 2.9183683e+00 3.5989425e+00 3.0794356e+00 3.2576813e+00 3.5320163e+00 3.8261152e+00 3.9741896e+00 3.1180182e+00 2.3364082e+00 2.5170134e+00 2.4274466e+00 2.6068690e+00 3.4218333e+00 2.7386417e+00 3.3934324e+00 3.7851452e+00 3.4854109e+00 2.5636830e+00 2.6200486e+00 2.6174942e+00 3.1669559e+00 2.6880360e+00 2.1675629e+00 2.6284424e+00 2.5986852e+00 2.6571682e+00 3.0828753e+00 1.9438939e+00 2.6338308e+00 4.6899445e+00 3.5257224e+00 4.8360835e+00 3.9149039e+00 4.4239486e+00 5.4654338e+00 2.8575769e+00 4.9368840e+00 4.3795070e+00 5.4971381e+00 4.1073887e+00 3.9867349e+00 4.4778796e+00 3.6113294e+00 3.9521234e+00 4.3324165e+00 4.0348180e+00 6.0067497e+00 5.8007868e+00 3.6612067e+00 4.8067419e+00 3.4133837e+00 5.5245725e+00 3.7158962e+00 4.5501061e+00 4.8067452e+00 3.5898573e+00 3.5494058e+00 4.2132256e+00 4.5903044e+00 5.0235775e+00 5.9805492e+00 4.2919572e+00 3.5520531e+00 3.5821954e+00 5.5319518e+00 4.5355231e+00 3.9801247e+00 3.4489678e+00 4.5459210e+00 4.6801759e+00 4.6148655e+00 3.5257224e+00 4.7911899e+00 4.8567489e+00 4.4697071e+00 3.9039516e+00 4.0848538e+00 4.3320055e+00 3.4824517e+00 1.5154593e+00 7.1671402e-01 2.6643250e-01 7.9347379e-01 2.3528246e+00 3.1744385e+00 1.9839744e+00 9.9059199e-01 1.9029496e+00 1.6532822e+00 9.3451915e-01 1.4586696e+00 1.2483935e+00 7.4743804e-01 7.4957404e-01 2.9691107e-01 8.0686941e-01 9.9973471e-01 7.9394533e-01 3.6319073e-01 1.8699153e-01 9.9891776e-01 2.3345854e+00 2.6422396e+00 0.0000000e+00 3.3742167e-01 1.1857824e+00 0.0000000e+00 6.6918102e-01 7.4445830e-01 9.7322023e-01 1.9284841e+00 6.6918102e-01 1.1393372e+00 1.6942803e+00 3.7371902e-01 1.6386105e+00 4.5257749e-01 1.4715172e+00 4.9772204e-01 3.5602797e+00 3.0968979e+00 3.5933352e+00 2.8998722e+00 3.2656298e+00 2.6029746e+00 3.1974447e+00 2.2445103e+00 3.1601923e+00 2.3946216e+00 3.0209665e+00 2.6867317e+00 3.0775658e+00 2.9161244e+00 2.1946278e+00 3.2137635e+00 2.6502891e+00 2.3652711e+00 3.6096140e+00 2.4893065e+00 3.1578003e+00 2.6568473e+00 3.4426472e+00 2.8187901e+00 2.9128857e+00 3.1418202e+00 3.4847097e+00 3.6205958e+00 2.8694312e+00 2.2223283e+00 2.5588203e+00 2.4651138e+00 2.4413293e+00 3.2621861e+00 2.5834128e+00 2.9995857e+00 3.3733791e+00 3.3817876e+00 2.3263008e+00 2.6305758e+00 2.5756071e+00 2.8533918e+00 2.5683063e+00 2.4187322e+00 2.5258216e+00 2.3250308e+00 2.4413618e+00 2.7691536e+00 2.1006933e+00 2.4608850e+00 4.4119896e+00 3.4290419e+00 4.4942656e+00 3.6650933e+00 4.1590662e+00 5.0899438e+00 3.0333619e+00 4.5799469e+00 4.1882413e+00 5.0726081e+00 3.7613721e+00 3.7859992e+00 4.1623715e+00 3.6029758e+00 3.8608065e+00 4.0352348e+00 3.7266849e+00 5.5043247e+00 5.5172732e+00 3.6569442e+00 4.4568115e+00 3.3324016e+00 5.1765224e+00 3.5192065e+00 4.1799642e+00 4.3857400e+00 3.3769078e+00 3.2906843e+00 4.0034548e+00 4.1917183e+00 4.6854597e+00 5.4444866e+00 4.0904298e+00 3.2962678e+00 3.4250783e+00 5.1569386e+00 4.2213314e+00 3.6582637e+00 3.2059261e+00 4.1937040e+00 4.3826532e+00 4.2786320e+00 3.4290419e+00 4.4549850e+00 4.5270304e+00 4.1816268e+00 3.7777251e+00 3.7924144e+00 4.0173731e+00 3.2613828e+00 1.0034646e+00 1.7753099e+00 2.1070188e+00 8.6079202e-01 1.6751898e+00 5.4248468e-01 6.0365341e-01 4.6310132e-01 4.4901474e-01 7.0111465e-01 4.4713936e-01 1.0328871e+00 1.0722301e+00 1.0271920e+00 1.6860841e+00 8.8540687e-01 5.2066928e-01 7.3502408e-01 1.4309353e+00 1.5630357e+00 7.3985997e-01 9.6257499e-01 1.1608422e+00 1.5154593e+00 1.2617482e+00 4.9009568e-01 1.5154593e+00 2.0192952e+00 7.8100392e-01 6.9001472e-01 3.4112480e+00 1.6736143e+00 8.5090098e-01 5.5183182e-01 1.7753099e+00 4.3319335e-01 1.5054343e+00 1.2076330e-01 1.0428797e+00 3.2901237e+00 2.9292978e+00 3.4367371e+00 3.8111737e+00 3.4729880e+00 3.0672734e+00 2.9473505e+00 3.3901879e+00 3.2662947e+00 3.1144880e+00 4.2413542e+00 2.8660589e+00 3.9495965e+00 3.1433256e+00 2.6375433e+00 3.0908568e+00 2.9081458e+00 2.9702968e+00 4.3236374e+00 3.3103937e+00 3.0964304e+00 3.0179755e+00 3.9313682e+00 3.1669001e+00 3.0754584e+00 3.1432906e+00 3.6245464e+00 3.5873526e+00 3.1179878e+00 2.9918256e+00 3.4776059e+00 3.4142800e+00 3.0198617e+00 3.6568155e+00 2.8980988e+00 2.6944324e+00 3.2512254e+00 4.0479095e+00 2.6293791e+00 3.4291613e+00 3.2968205e+00 2.9799791e+00 3.2239661e+00 3.5774656e+00 3.1299499e+00 2.6069579e+00 2.8203994e+00 2.9888842e+00 3.1470877e+00 2.9476507e+00 4.1975965e+00 3.8311128e+00 4.3861256e+00 3.7921747e+00 4.1446583e+00 4.9211801e+00 3.8442384e+00 4.5238497e+00 4.5231439e+00 4.5451210e+00 3.5805575e+00 4.0469570e+00 4.0990882e+00 4.1579560e+00 4.1249171e+00 3.8727781e+00 3.7290616e+00 4.8292468e+00 5.5757877e+00 4.3965263e+00 4.2248397e+00 3.6936498e+00 5.1256160e+00 3.8221804e+00 3.8961870e+00 4.1176453e+00 3.6242665e+00 3.3807801e+00 4.1671042e+00 4.0787299e+00 4.6798442e+00 4.7374542e+00 4.2466909e+00 3.5432140e+00 3.8759165e+00 4.9689016e+00 3.9204411e+00 3.5927937e+00 3.3203721e+00 4.0348754e+00 4.2531600e+00 4.1147391e+00 3.8311128e+00 4.2401451e+00 4.2502727e+00 4.1279956e+00 4.2116129e+00 3.7856899e+00 3.7242025e+00 3.3954918e+00 9.3865015e-01 1.1459117e+00 1.8505741e+00 2.5636327e+00 1.3972701e+00 4.6310132e-01 1.4327294e+00 1.0013399e+00 7.2679299e-01 8.2574748e-01 6.2187934e-01 5.8496636e-01 1.7002750e-01 9.5361455e-01 3.5639126e-01 5.3827772e-01 4.9617437e-01 4.7680727e-01 6.9189100e-01 7.7259801e-01 1.6911681e+00 2.0326426e+00 7.1671402e-01 5.6788283e-01 8.9258315e-01 7.1671402e-01 1.0551281e+00 3.6669623e-01 3.9699460e-01 2.5716465e+00 6.8921053e-01 6.2148529e-01 1.0391769e+00 9.3865015e-01 9.9111027e-01 5.3286499e-01 9.2006504e-01 3.5266705e-01 3.5819899e+00 3.0902007e+00 3.6482741e+00 3.3284223e+00 3.4528558e+00 2.8062636e+00 3.1283731e+00 2.7130802e+00 3.3201500e+00 2.6478976e+00 3.5696084e+00 2.7728704e+00 3.5649049e+00 3.0583917e+00 2.3718219e+00 3.2763163e+00 2.7180029e+00 2.6779045e+00 4.0150919e+00 2.8864805e+00 3.1083977e+00 2.8822332e+00 3.7402558e+00 3.0304088e+00 3.0793541e+00 3.2506893e+00 3.6756049e+00 3.7003058e+00 3.0054875e+00 2.6160903e+00 2.9965118e+00 2.9238797e+00 2.7351276e+00 3.4650507e+00 2.6418165e+00 2.8577585e+00 3.4252075e+00 3.7832878e+00 2.4227175e+00 2.9917855e+00 2.8903467e+00 2.9460322e+00 2.9034030e+00 2.9191699e+00 2.7908173e+00 2.4332562e+00 2.6000033e+00 2.9338362e+00 2.5416562e+00 2.6797931e+00 4.3169600e+00 3.6002350e+00 4.5501061e+00 3.7611228e+00 4.1952298e+00 5.1491201e+00 3.2996439e+00 4.6835622e+00 4.4311275e+00 4.9194005e+00 3.7316761e+00 3.9622355e+00 4.2152785e+00 3.8426553e+00 3.9520057e+00 3.9894324e+00 3.7877346e+00 5.3234168e+00 5.6801405e+00 4.0465336e+00 4.4289683e+00 3.4509848e+00 5.3007226e+00 3.7123045e+00 4.1128937e+00 4.3848871e+00 3.5295907e+00 3.3480190e+00 4.1214168e+00 4.2758432e+00 4.8208082e+00 5.2754050e+00 4.2018689e+00 3.4688327e+00 3.6716137e+00 5.2146461e+00 4.0903576e+00 3.6733277e+00 3.2612647e+00 4.2126998e+00 4.3809966e+00 4.2914999e+00 3.6002350e+00 4.4223824e+00 4.4497684e+00 4.2250047e+00 4.0330034e+00 3.8460049e+00 3.8818416e+00 3.3084835e+00 6.2729876e-01 2.6091054e+00 3.4299177e+00 2.2340939e+00 1.2368073e+00 2.1640372e+00 1.8992968e+00 1.1925354e+00 1.7015647e+00 1.4288989e+00 9.5582164e-01 9.7391954e-01 2.9724335e-01 1.0376697e+00 1.2583645e+00 1.0495503e+00 5.0731024e-01 2.8845946e-01 1.2384679e+00 2.5831347e+00 2.8967543e+00 2.6643250e-01 5.4873947e-01 1.4369223e+00 2.6643250e-01 5.0370871e-01 1.0013399e+00 1.2082987e+00 1.6761482e+00 6.8299624e-01 1.3528452e+00 1.9417181e+00 2.6206799e-01 1.8882412e+00 5.3690447e-01 1.7295385e+00 7.4445830e-01 3.6974389e+00 3.2246529e+00 3.7127916e+00 2.8221999e+00 3.3289662e+00 2.6369282e+00 3.3348648e+00 2.1165503e+00 3.2465431e+00 2.3709411e+00 2.8608899e+00 2.7655496e+00 3.0110500e+00 2.9862341e+00 2.2391292e+00 3.3332541e+00 2.7176350e+00 2.3810734e+00 3.5657791e+00 2.4469788e+00 3.2638546e+00 2.7057900e+00 3.4512743e+00 2.8728052e+00 2.9934131e+00 3.2431147e+00 3.5582624e+00 3.7179545e+00 2.9335017e+00 2.1999209e+00 2.4893065e+00 2.3915367e+00 2.4540260e+00 3.2923304e+00 2.6414379e+00 3.1466196e+00 3.4901671e+00 3.3542627e+00 2.3973915e+00 2.5861640e+00 2.5561973e+00 2.9420425e+00 2.5609364e+00 2.2836399e+00 2.5303888e+00 2.4035745e+00 2.4950488e+00 2.8435005e+00 2.0000785e+00 2.4916202e+00 4.5218181e+00 3.4492861e+00 4.5921002e+00 3.7366932e+00 4.2432727e+00 5.1949299e+00 2.9709788e+00 4.6735988e+00 4.2160797e+00 5.2249989e+00 3.8759828e+00 3.8289542e+00 4.2545385e+00 3.5878027e+00 3.8924868e+00 4.1403048e+00 3.8179103e+00 5.6801405e+00 5.5805905e+00 3.6100547e+00 4.5709635e+00 3.3584734e+00 5.2629823e+00 3.5576748e+00 4.3070506e+00 4.5135384e+00 3.4273212e+00 3.3707040e+00 4.0596064e+00 4.2990937e+00 4.7676077e+00 5.6256469e+00 4.1454035e+00 3.3551224e+00 3.4472672e+00 5.2603070e+00 4.3452859e+00 3.7614312e+00 3.2825924e+00 4.3002370e+00 4.4796258e+00 4.3809022e+00 3.4492861e+00 4.5673965e+00 4.6446301e+00 4.2677070e+00 3.7864370e+00 3.8796124e+00 4.1423594e+00 3.3352922e+00 2.9361142e+00 3.6728262e+00 2.4980859e+00 1.5364600e+00 2.5390784e+00 2.1113072e+00 1.6578570e+00 1.9353585e+00 1.4375287e+00 1.3425463e+00 1.1993279e+00 9.0115406e-01 1.3418210e+00 1.6061161e+00 1.4416694e+00 7.3727571e-01 7.1781501e-01 1.6797637e+00 2.7692440e+00 3.1313820e+00 7.9347379e-01 9.7352372e-01 1.8600648e+00 7.9347379e-01 2.1119253e-01 1.3612390e+00 1.4580439e+00 1.6571634e+00 5.0731024e-01 1.5980974e+00 2.1674065e+00 6.7984069e-01 2.1059482e+00 6.2457556e-01 2.0330443e+00 1.1132823e+00 4.2319020e+00 3.7044235e+00 4.2326669e+00 3.1432906e+00 3.8172627e+00 3.0425144e+00 3.7866079e+00 2.3206274e+00 3.7650177e+00 2.6608343e+00 3.0454230e+00 3.1914925e+00 3.4221447e+00 3.4413652e+00 2.6453561e+00 3.8539838e+00 3.0892079e+00 2.8357998e+00 3.9683086e+00 2.8336784e+00 3.6477040e+00 3.1799040e+00 3.8944724e+00 3.3434129e+00 3.4994776e+00 3.7569353e+00 4.0775935e+00 4.2049294e+00 3.3684490e+00 2.6363662e+00 2.8414019e+00 2.7526519e+00 2.8906655e+00 3.7008234e+00 2.9737492e+00 3.5555916e+00 3.9977110e+00 3.7960948e+00 2.7978670e+00 2.9332077e+00 2.9200513e+00 3.4002561e+00 2.9851921e+00 2.5032729e+00 2.9159414e+00 2.8324645e+00 2.9104902e+00 3.3286096e+00 2.2670901e+00 2.9042354e+00 4.8902416e+00 3.8029663e+00 5.0697571e+00 4.1657422e+00 4.6611282e+00 5.6979337e+00 3.1565039e+00 5.1794156e+00 4.6677357e+00 5.6656906e+00 4.3138249e+00 4.2590423e+00 4.7118516e+00 3.9079657e+00 4.2090892e+00 4.5409993e+00 4.2707579e+00 6.1569683e+00 6.0684263e+00 3.9837013e+00 5.0178221e+00 3.6761530e+00 5.7743610e+00 3.9890690e+00 4.7480354e+00 5.0151961e+00 3.8518880e+00 3.7849163e+00 4.4740109e+00 4.8191103e+00 5.2745801e+00 6.1258486e+00 4.5520039e+00 3.8145791e+00 3.8707244e+00 5.7618968e+00 4.7193263e+00 4.2030300e+00 3.6843246e+00 4.7664506e+00 4.9031551e+00 4.8333734e+00 3.8029663e+00 5.0038635e+00 5.0562579e+00 4.7021393e+00 4.1966653e+00 4.3193180e+00 4.5127918e+00 3.7195417e+00 9.8143688e-01 5.9868400e-01 1.4402716e+00 5.6992880e-01 9.8663349e-01 1.4928150e+00 1.1361809e+00 1.7216149e+00 1.8856736e+00 1.8789959e+00 2.5107352e+00 1.7228721e+00 1.3724737e+00 1.5661153e+00 2.2847787e+00 2.4120925e+00 1.4985933e+00 7.9011741e-01 5.9738093e-01 2.3528246e+00 2.0826771e+00 1.2100516e+00 2.3528246e+00 2.8601865e+00 1.6304499e+00 1.5111262e+00 4.2257604e+00 2.5031609e+00 1.6091095e+00 1.0739839e+00 2.6091054e+00 9.8932340e-01 2.3488496e+00 9.3392552e-01 1.8848176e+00 3.4513181e+00 3.2138675e+00 3.6568023e+00 4.4832075e+00 3.8715598e+00 3.6399979e+00 3.2048569e+00 4.1609431e+00 3.6276988e+00 3.7852753e+00 5.0007603e+00 3.3356061e+00 4.5726588e+00 3.6020324e+00 3.2283316e+00 3.3543125e+00 3.4317803e+00 3.5762357e+00 4.8853618e+00 3.9697083e+00 3.4608105e+00 3.5194529e+00 4.4307529e+00 3.6664068e+00 3.4821665e+00 3.4661369e+00 3.9690303e+00 3.8732280e+00 3.5908374e+00 3.6384054e+00 4.1605480e+00 4.1054173e+00 3.6121763e+00 4.1591449e+00 3.4571840e+00 2.9726287e+00 3.5108834e+00 4.5938444e+00 3.1869025e+00 4.0859475e+00 3.9449709e+00 3.4111584e+00 3.8289196e+00 4.3382952e+00 3.7437946e+00 3.1530215e+00 3.3792174e+00 3.4400302e+00 3.8876642e+00 3.5288768e+00 4.4107365e+00 4.3401559e+00 4.5910423e+00 4.1731099e+00 4.4383007e+00 5.0605479e+00 4.5288382e+00 4.7400085e+00 4.9337127e+00 4.5282137e+00 3.8167418e+00 4.4582410e+00 4.3491396e+00 4.7099690e+00 4.5667632e+00 4.1110524e+00 4.0457882e+00 4.6970439e+00 5.8050200e+00 4.9831785e+00 4.3869525e+00 4.2045486e+00 5.3107398e+00 4.2598936e+00 4.0608563e+00 4.2495756e+00 4.0560071e+00 3.7740189e+00 4.5388860e+00 4.2824837e+00 4.9058468e+00 4.5708763e+00 4.6120616e+00 3.9763551e+00 4.3872260e+00 5.0860672e+00 4.0998055e+00 3.8946369e+00 3.7330702e+00 4.2352833e+00 4.4742220e+00 4.3047259e+00 4.3401559e+00 4.4192906e+00 4.4017154e+00 4.3831142e+00 4.6832544e+00 4.0909816e+00 3.9225445e+00 3.8229302e+00 1.2140269e+00 2.2031378e+00 1.3945864e+00 1.5674943e+00 2.3519816e+00 1.7695601e+00 2.3060361e+00 2.6440626e+00 2.5730128e+00 3.3484034e+00 2.4570006e+00 2.1775427e+00 2.3990667e+00 3.0314484e+00 3.2003667e+00 2.3345854e+00 9.9891776e-01 5.8565201e-01 3.1744385e+00 2.9106021e+00 2.1090950e+00 3.1744385e+00 3.6015962e+00 2.4316107e+00 2.2478972e+00 5.0583620e+00 3.1946200e+00 2.2571919e+00 1.5783735e+00 3.4098353e+00 1.5848534e+00 3.0815481e+00 1.7053877e+00 2.6874763e+00 3.8897688e+00 3.6527400e+00 4.1085323e+00 5.1878354e+00 4.4401043e+00 4.2306533e+00 3.5668974e+00 4.8855250e+00 4.1984227e+00 4.3936084e+00 5.7667342e+00 3.8604223e+00 5.3386416e+00 4.1481805e+00 3.8457422e+00 3.8556395e+00 3.9253518e+00 4.2633467e+00 5.5746944e+00 4.6805795e+00 3.8185179e+00 4.1531225e+00 5.0514886e+00 4.2706189e+00 4.0732692e+00 4.0031242e+00 4.5383244e+00 4.3266944e+00 4.1312924e+00 4.3745457e+00 4.8862079e+00 4.8484299e+00 4.2820168e+00 4.7051757e+00 3.9401848e+00 3.2884177e+00 3.9767257e+00 5.2985037e+00 3.7419338e+00 4.7600849e+00 4.5926355e+00 3.9322406e+00 4.5116211e+00 5.0823619e+00 4.3725296e+00 3.7236864e+00 3.9623539e+00 4.0300759e+00 4.6141946e+00 4.1447443e+00 4.5866744e+00 4.8386745e+00 4.9461657e+00 4.6106150e+00 4.7813164e+00 5.3858108e+00 5.0919277e+00 5.1446449e+00 5.4739987e+00 4.5885042e+00 4.1414025e+00 4.9586480e+00 4.7213864e+00 5.2471037e+00 4.9661074e+00 4.3830009e+00 4.4568388e+00 4.6901031e+00 6.2154767e+00 5.6469307e+00 4.6501660e+00 4.6626232e+00 5.7036296e+00 4.7932843e+00 4.3038060e+00 4.5618709e+00 4.5655950e+00 4.2115551e+00 4.9692114e+00 4.7030193e+00 5.3377504e+00 4.5914343e+00 5.0293150e+00 4.5146706e+00 4.9581881e+00 5.4087027e+00 4.2557771e+00 4.2671438e+00 4.1737149e+00 4.5756985e+00 4.7660397e+00 4.6314702e+00 4.8386745e+00 4.6734470e+00 4.5970177e+00 4.7412505e+00 5.2464126e+00 4.4890534e+00 4.0948317e+00 4.2440420e+00 1.0013399e+00 5.0299964e-01 4.6310132e-01 1.2040900e+00 5.9738093e-01 1.2286837e+00 1.4541908e+00 1.4279677e+00 2.1539145e+00 1.2617482e+00 9.9544409e-01 1.2082987e+00 1.8489243e+00 2.0066856e+00 1.1587093e+00 6.6217390e-01 7.5179033e-01 1.9839744e+00 1.7063292e+00 9.6659661e-01 1.9839744e+00 2.4156729e+00 1.2419907e+00 1.0495503e+00 3.8490499e+00 2.0330726e+00 1.0871867e+00 5.4779717e-01 2.2031378e+00 5.3106808e-01 1.9004159e+00 5.5576380e-01 1.4899949e+00 3.4307448e+00 3.0710756e+00 3.5952799e+00 4.1669813e+00 3.7116384e+00 3.3536981e+00 3.0466130e+00 3.7729829e+00 3.5082606e+00 3.4067800e+00 4.6484249e+00 3.0744089e+00 4.3424419e+00 3.3858347e+00 2.9098729e+00 3.2669110e+00 3.1198644e+00 3.3210229e+00 4.6553382e+00 3.6737423e+00 3.2048569e+00 3.2989479e+00 4.2245828e+00 3.4587219e+00 3.3255241e+00 3.3484846e+00 3.8660480e+00 3.7512964e+00 3.3482610e+00 3.3605387e+00 3.8511468e+00 3.8014113e+00 3.3411134e+00 3.9109127e+00 3.1105014e+00 2.7597977e+00 3.4146222e+00 4.3904048e+00 2.8767763e+00 3.7646132e+00 3.6317356e+00 3.1996946e+00 3.5585167e+00 3.9690108e+00 3.4365573e+00 2.8705339e+00 3.0890888e+00 3.2456270e+00 3.5108688e+00 3.2367228e+00 4.2147014e+00 4.0489906e+00 4.5035700e+00 3.9755362e+00 4.2591912e+00 5.0350768e+00 4.1207838e+00 4.6882252e+00 4.7707308e+00 4.4918348e+00 3.6612573e+00 4.2568131e+00 4.2184327e+00 4.3988058e+00 4.2632946e+00 3.9245996e+00 3.8864624e+00 4.7642090e+00 5.7424408e+00 4.7299069e+00 4.2784034e+00 3.8797952e+00 5.2832732e+00 4.0458553e+00 3.9446593e+00 4.2181053e+00 3.8300888e+00 3.5427774e+00 4.3354099e+00 4.2438935e+00 4.8511407e+00 4.6817036e+00 4.4041714e+00 3.7859242e+00 4.1665370e+00 5.0618540e+00 3.9138566e+00 3.7274783e+00 3.4833346e+00 4.1288327e+00 4.3215818e+00 4.1859543e+00 4.0489906e+00 4.2965095e+00 4.2626474e+00 4.2257654e+00 4.4572702e+00 3.9184477e+00 3.7230473e+00 3.5604297e+00 1.0161882e+00 6.9420840e-01 4.8012872e-01 4.8284931e-01 6.9738730e-01 5.5709100e-01 5.3095950e-01 1.1723315e+00 3.1271814e-01 1.8699153e-01 2.9145160e-01 8.6143605e-01 1.0061402e+00 4.5257749e-01 1.4146831e+00 1.6902182e+00 9.9059199e-01 7.2340544e-01 5.0370871e-01 9.9059199e-01 1.4369223e+00 2.7124234e-01 1.3340137e-01 2.8614050e+00 1.1016806e+00 4.2656951e-01 7.5906970e-01 1.2087236e+00 7.1325427e-01 9.2761923e-01 5.3988754e-01 4.9448466e-01 3.3643791e+00 2.9159414e+00 3.4617249e+00 3.4323687e+00 3.3505903e+00 2.8169505e+00 2.9517065e+00 2.9146662e+00 3.1941250e+00 2.7393282e+00 3.7736317e+00 2.6933089e+00 3.6308668e+00 2.9914579e+00 2.3560812e+00 3.0907905e+00 2.6932687e+00 2.7021788e+00 4.0389540e+00 2.9648098e+00 2.9980910e+00 2.8201257e+00 3.7183934e+00 2.9922398e+00 2.9661287e+00 3.0950932e+00 3.5513156e+00 3.5484439e+00 2.9420200e+00 2.6629529e+00 3.1013619e+00 3.0347859e+00 2.7417410e+00 3.4474072e+00 2.6495954e+00 2.6875764e+00 3.2488445e+00 3.7904353e+00 2.3985415e+00 3.0725852e+00 2.9704304e+00 2.8556850e+00 2.9300511e+00 3.1104511e+00 2.8291506e+00 2.4008046e+00 2.5836379e+00 2.8456807e+00 2.6907656e+00 2.6814159e+00 4.1737238e+00 3.5932878e+00 4.3853076e+00 3.6802688e+00 4.0749525e+00 4.9692376e+00 3.4394110e+00 4.5331007e+00 4.3742923e+00 4.6787296e+00 3.5632387e+00 3.8923023e+00 4.0628985e+00 3.8689922e+00 3.9102807e+00 3.8336686e+00 3.6675649e+00 5.0555526e+00 5.5454277e+00 4.0994961e+00 4.2439469e+00 3.4449831e+00 5.1429556e+00 3.6472400e+00 3.9304610e+00 4.1916938e+00 3.4565067e+00 3.2536517e+00 4.0373591e+00 4.1087274e+00 4.6703619e+00 4.9904781e+00 4.1152831e+00 3.4023949e+00 3.6756751e+00 5.0151763e+00 3.9231895e+00 3.5466262e+00 3.1760855e+00 4.0346845e+00 4.2216886e+00 4.1038501e+00 3.5932878e+00 4.2504107e+00 4.2656428e+00 4.0705667e+00 3.9971917e+00 3.7133040e+00 3.7182295e+00 3.2440381e+00 7.3339246e-01 9.9973471e-01 7.7988766e-01 1.4669572e+00 1.3868865e+00 1.4360884e+00 2.0344949e+00 1.2593779e+00 9.3451915e-01 1.1232628e+00 1.8421759e+00 1.9514085e+00 1.0061402e+00 9.6168382e-01 9.7747632e-01 1.9029496e+00 1.6513423e+00 7.7821113e-01 1.9029496e+00 2.4366790e+00 1.1857824e+00 1.1156669e+00 3.7575639e+00 2.1090460e+00 1.1623508e+00 7.4500632e-01 2.1481102e+00 7.3851064e-01 1.9301732e+00 5.6262711e-01 1.4458364e+00 3.0574507e+00 2.7604800e+00 3.2354442e+00 3.9296796e+00 3.3802783e+00 3.0910114e+00 2.7653977e+00 3.6086433e+00 3.1477156e+00 3.2299948e+00 4.4531271e+00 2.8182580e+00 4.0359059e+00 3.0838698e+00 2.6832031e+00 2.9127171e+00 2.8999239e+00 3.0235972e+00 4.3556993e+00 3.4142800e+00 2.9871882e+00 2.9947610e+00 3.9084388e+00 3.1359326e+00 2.9852014e+00 3.0007807e+00 3.4997296e+00 3.4243092e+00 3.0709062e+00 3.0889274e+00 3.6054231e+00 3.5510321e+00 3.0652992e+00 3.6307363e+00 2.9199707e+00 2.5302845e+00 3.0705222e+00 4.0683526e+00 2.6430958e+00 3.5303998e+00 3.3838093e+00 2.9011205e+00 3.2808511e+00 3.7876206e+00 3.1898591e+00 2.6081677e+00 2.8342553e+00 2.9259899e+00 3.3400468e+00 2.9809771e+00 4.0130133e+00 3.8156727e+00 4.1823301e+00 3.6854232e+00 3.9919300e+00 4.6844795e+00 3.9756960e+00 4.3245814e+00 4.4396397e+00 4.2453585e+00 3.3946374e+00 3.9634682e+00 3.9204865e+00 4.1772364e+00 4.0766155e+00 3.6959934e+00 3.5831715e+00 4.4790872e+00 5.3894840e+00 4.4405497e+00 4.0027890e+00 3.6857786e+00 4.9137586e+00 3.7567964e+00 3.6729588e+00 3.8728151e+00 3.5543966e+00 3.2848126e+00 4.0598486e+00 3.8712880e+00 4.4886485e+00 4.3722180e+00 4.1373490e+00 3.4683949e+00 3.8543469e+00 4.7248681e+00 3.7193644e+00 3.4383872e+00 3.2381387e+00 3.8297356e+00 4.0647650e+00 3.9099360e+00 3.8156727e+00 4.0266221e+00 4.0296168e+00 3.9579549e+00 4.1722551e+00 3.6379295e+00 3.5328511e+00 3.3224979e+00 1.0061402e+00 2.6525508e-01 8.2148003e-01 1.1879760e+00 1.0251165e+00 1.8544941e+00 9.4128180e-01 7.1446962e-01 9.4128180e-01 1.4726083e+00 1.6607117e+00 9.9973471e-01 7.4965096e-01 1.0510795e+00 1.6532822e+00 1.4055304e+00 8.6143605e-01 1.6532822e+00 2.0368618e+00 9.3178083e-01 7.1143905e-01 3.5363390e+00 1.6307900e+00 8.0686941e-01 2.6184788e-01 1.8811296e+00 1.4276574e-01 1.5165187e+00 3.5874135e-01 1.1682143e+00 3.5420892e+00 3.1213639e+00 3.6765721e+00 3.9907084e+00 3.7063187e+00 3.2329517e+00 3.1017380e+00 3.5164906e+00 3.5204595e+00 3.2215483e+00 4.4016409e+00 3.0251724e+00 4.2008255e+00 3.3367044e+00 2.7940225e+00 3.3344791e+00 3.0219495e+00 3.1880051e+00 4.5546425e+00 3.5075399e+00 3.1952269e+00 3.2406785e+00 4.1563139e+00 3.3848806e+00 3.3178898e+00 3.3859281e+00 3.8870730e+00 3.7997125e+00 3.2944053e+00 3.2110142e+00 3.6683444e+00 3.6131226e+00 3.2236002e+00 3.8317071e+00 2.9830921e+00 2.7973167e+00 3.4787185e+00 4.2995699e+00 2.7671612e+00 3.5982071e+00 3.4619260e+00 3.1665431e+00 3.4310890e+00 3.7235030e+00 3.2953414e+00 2.7679629e+00 2.9819595e+00 3.2106653e+00 3.2879746e+00 3.1196883e+00 4.2713770e+00 3.9634682e+00 4.5846990e+00 3.9587038e+00 4.2895460e+00 5.1416821e+00 3.9119997e+00 4.7572039e+00 4.7460626e+00 4.6638344e+00 3.7280454e+00 4.2349181e+00 4.2803486e+00 4.2908242e+00 4.2152718e+00 3.9857018e+00 3.9070797e+00 4.9741957e+00 5.8097018e+00 4.6049285e+00 4.3788345e+00 3.7893243e+00 5.3689314e+00 4.0140467e+00 4.0363955e+00 4.3259832e+00 3.8006490e+00 3.5269016e+00 4.3297076e+00 4.3216441e+00 4.9220177e+00 4.9100057e+00 4.4024600e+00 3.7489348e+00 4.0736926e+00 5.1891895e+00 3.9903212e+00 3.7514870e+00 3.4564041e+00 4.2166575e+00 4.3944655e+00 4.2851348e+00 3.9634682e+00 4.3836343e+00 4.3634474e+00 4.2898748e+00 4.4067690e+00 3.9524852e+00 3.7906894e+00 3.5162082e+00 8.3156200e-01 1.1417173e+00 5.8221430e-01 7.3339246e-01 1.0428797e+00 5.5247822e-01 3.5266705e-01 2.9537172e-01 9.6466498e-01 1.0034646e+00 2.8553149e-01 1.6415483e+00 1.8567917e+00 9.3451915e-01 7.2553812e-01 3.4520795e-01 9.3451915e-01 1.5364952e+00 3.7960845e-01 5.9589853e-01 2.7723424e+00 1.3124532e+00 7.5130648e-01 1.0314203e+00 1.1925354e+00 9.9272943e-01 1.0839891e+00 7.1143905e-01 5.6164055e-01 3.0511653e+00 2.6629268e+00 3.1545235e+00 3.1980310e+00 3.0467396e+00 2.5772061e+00 2.7369167e+00 2.7576827e+00 2.8651003e+00 2.5868532e+00 3.5774656e+00 2.4748633e+00 3.3139897e+00 2.7217211e+00 2.1506369e+00 2.7852281e+00 2.5158340e+00 2.4059801e+00 3.7433691e+00 2.7041074e+00 2.8389661e+00 2.5310559e+00 3.4176981e+00 2.6902386e+00 2.6527549e+00 2.7866168e+00 3.2144386e+00 3.2675625e+00 2.6971865e+00 2.3822357e+00 2.8532332e+00 2.7780124e+00 2.4721123e+00 3.1952919e+00 2.5042136e+00 2.5315299e+00 2.9556760e+00 3.4693709e+00 2.1993495e+00 2.8460127e+00 2.7344861e+00 2.5960616e+00 2.6558880e+00 2.9309653e+00 2.5980406e+00 2.1695355e+00 2.3550298e+00 2.5518802e+00 2.5245372e+00 2.4441489e+00 4.0319503e+00 3.3933783e+00 4.1146478e+00 3.4339804e+00 3.8578841e+00 4.6712206e+00 3.3248410e+00 4.2174528e+00 4.0704050e+00 4.4988341e+00 3.3546526e+00 3.6317702e+00 3.8139412e+00 3.6743372e+00 3.7645284e+00 3.6614225e+00 3.4131399e+00 4.8439861e+00 5.2322637e+00 3.8189229e+00 4.0256031e+00 3.2902097e+00 4.8190347e+00 3.3870859e+00 3.7223145e+00 3.9080259e+00 3.2141230e+00 3.0414452e+00 3.8022687e+00 3.7869665e+00 4.3507688e+00 4.7565318e+00 3.8893282e+00 3.1162635e+00 3.3877625e+00 4.7282676e+00 3.7917280e+00 3.3122397e+00 2.9763122e+00 3.7889092e+00 4.0173731e+00 3.8788191e+00 3.3933783e+00 4.0384828e+00 4.0914753e+00 3.8500022e+00 3.7349483e+00 3.4804621e+00 3.5920363e+00 3.0535851e+00 7.5284003e-01 9.3865015e-01 8.5442446e-01 1.6409761e+00 7.0463400e-01 5.4408162e-01 7.5179033e-01 1.2786676e+00 1.4553344e+00 7.8100392e-01 1.0100290e+00 1.2786676e+00 1.4586696e+00 1.2008045e+00 7.2638147e-01 1.4586696e+00 1.8445759e+00 7.3985997e-01 5.0731024e-01 3.3136601e+00 1.4580439e+00 5.4702555e-01 3.2339566e-01 1.6607117e+00 3.5366952e-01 1.3290015e+00 3.5639126e-01 9.6825676e-01 3.4059851e+00 2.9602214e+00 3.5257340e+00 3.7492673e+00 3.5115913e+00 3.0191277e+00 2.9517483e+00 3.2720571e+00 3.3411331e+00 2.9834222e+00 4.1580731e+00 2.8211532e+00 3.9717534e+00 3.1414634e+00 2.5643903e+00 3.1728076e+00 2.8176969e+00 2.9703822e+00 4.3244606e+00 3.2734582e+00 3.0210021e+00 3.0274003e+00 3.9433841e+00 3.1866772e+00 3.1269680e+00 3.2103093e+00 3.7065013e+00 3.6299273e+00 3.0909484e+00 2.9772513e+00 3.4297321e+00 3.3756936e+00 2.9971174e+00 3.6243253e+00 2.7759818e+00 2.6501700e+00 3.3189004e+00 4.0764633e+00 2.5559925e+00 3.3602243e+00 3.2356862e+00 2.9780147e+00 3.2026716e+00 3.4783251e+00 3.0685582e+00 2.5635668e+00 2.7679629e+00 3.0129566e+00 3.0370166e+00 2.8975180e+00 4.1264564e+00 3.7496421e+00 4.4295218e+00 3.7774558e+00 4.1191095e+00 5.0038078e+00 3.6756489e+00 4.6074750e+00 4.5494422e+00 4.5665604e+00 3.5702411e+00 4.0355009e+00 4.1137066e+00 4.0638414e+00 4.0067360e+00 3.8250619e+00 3.7375780e+00 4.9153359e+00 5.6444336e+00 4.3773916e+00 4.2331397e+00 3.5751580e+00 5.2199809e+00 3.8075775e+00 3.9003626e+00 4.1989415e+00 3.5967191e+00 3.3381510e+00 4.1394208e+00 4.1772604e+00 4.7627066e+00 4.8574416e+00 4.2113835e+00 3.5565415e+00 3.8744064e+00 5.0458107e+00 3.8530980e+00 3.5894641e+00 3.2635788e+00 4.0605147e+00 4.2327162e+00 4.1232607e+00 3.7496421e+00 4.2381044e+00 4.2216886e+00 4.1152818e+00 4.1901775e+00 3.7759339e+00 3.6506667e+00 3.3268510e+00 1.0748172e+00 7.2889003e-01 1.5046031e+00 7.9398919e-01 8.1148630e-01 8.8835337e-01 9.9058911e-01 1.2262672e+00 1.1380274e+00 1.3972288e+00 1.7741287e+00 1.2483935e+00 1.0474897e+00 1.1240042e+00 1.2483935e+00 1.4149548e+00 8.1096210e-01 5.7672351e-01 3.0082939e+00 9.6865373e-01 8.2273123e-01 9.5195566e-01 1.4288989e+00 8.3246212e-01 9.4996842e-01 9.2092295e-01 8.7375509e-01 4.0151215e+00 3.5231786e+00 4.1026785e+00 3.8908802e+00 3.9665585e+00 3.3438394e+00 3.5293285e+00 3.2540384e+00 3.8314935e+00 3.1634347e+00 4.1178317e+00 3.2512254e+00 4.1561446e+00 3.5717750e+00 2.8833448e+00 3.7345570e+00 3.1952822e+00 3.2548783e+00 4.5820687e+00 3.4621656e+00 3.5141919e+00 3.4137993e+00 4.2939653e+00 3.5777026e+00 3.5926398e+00 3.7328374e+00 4.1920808e+00 4.1652091e+00 3.5073274e+00 3.1921998e+00 3.5706840e+00 3.5044583e+00 3.2904241e+00 3.9914615e+00 3.1120432e+00 3.2204607e+00 3.8807669e+00 4.3582892e+00 2.9219284e+00 3.5476488e+00 3.4540639e+00 3.4397115e+00 3.4680001e+00 3.4670753e+00 3.3367044e+00 2.9471549e+00 3.1205392e+00 3.4518638e+00 3.0783517e+00 3.2145380e+00 4.6697624e+00 4.0951447e+00 4.9940386e+00 4.2442248e+00 4.6312366e+00 5.5957028e+00 3.7901714e+00 5.1629764e+00 4.9662629e+00 5.2245876e+00 4.1326097e+00 4.4648550e+00 4.6557857e+00 4.3477764e+00 4.3833898e+00 4.3689111e+00 4.2520226e+00 5.6153369e+00 6.1715044e+00 4.6178873e+00 4.8201070e+00 3.9129644e+00 5.7808751e+00 4.2195149e+00 4.4949009e+00 4.8099428e+00 4.0213766e+00 3.8049151e+00 4.5961475e+00 4.7475868e+00 5.3061067e+00 5.5699347e+00 4.6684257e+00 3.9900166e+00 4.2272640e+00 5.6441645e+00 4.4197984e+00 4.1176453e+00 3.7157925e+00 4.6326704e+00 4.7820862e+00 4.6921349e+00 4.0951447e+00 4.8160040e+00 4.8050680e+00 4.6459078e+00 4.5554678e+00 4.2905569e+00 4.2115152e+00 3.7649212e+00 5.9314593e-01 8.0686941e-01 2.9691107e-01 6.2826980e-01 5.0121118e-01 6.6653737e-01 7.0834786e-01 4.6310132e-01 1.9251840e+00 2.1737519e+00 7.4743804e-01 5.5009731e-01 8.0748088e-01 7.4743804e-01 1.1828955e+00 4.6964680e-01 5.8942278e-01 2.4421558e+00 9.8677196e-01 4.9772204e-01 1.1660949e+00 8.4116354e-01 1.2196311e+00 7.7538587e-01 1.0376697e+00 4.4499696e-01 3.0983271e+00 2.5986852e+00 3.1534326e+00 2.8897192e+00 2.9336987e+00 2.3392252e+00 2.6586759e+00 2.3702978e+00 2.8165027e+00 2.2079130e+00 3.2363154e+00 2.2664200e+00 3.1218253e+00 2.5673178e+00 1.8638939e+00 2.7710337e+00 2.2535803e+00 2.2156046e+00 3.5264693e+00 2.4375344e+00 2.6410495e+00 2.3635223e+00 3.2419868e+00 2.5535068e+00 2.5663186e+00 2.7372400e+00 3.1657714e+00 3.1910277e+00 2.5035271e+00 2.1450705e+00 2.5644558e+00 2.5011730e+00 2.2417546e+00 2.9810976e+00 2.2012005e+00 2.4146140e+00 2.9247451e+00 3.2953953e+00 1.9474034e+00 2.5368532e+00 2.4541089e+00 2.4554575e+00 2.4210504e+00 2.5661600e+00 2.3207574e+00 1.9628165e+00 2.1171985e+00 2.4261018e+00 2.1366217e+00 2.1917681e+00 3.8609963e+00 3.1157672e+00 4.0464741e+00 3.2769657e+00 3.7011972e+00 4.6584806e+00 2.9074576e+00 4.1962146e+00 3.9292452e+00 4.4717831e+00 3.2385313e+00 3.4507621e+00 3.7050324e+00 3.3601278e+00 3.4577371e+00 3.4991206e+00 3.2980589e+00 4.9174048e+00 5.1685262e+00 3.5822256e+00 3.9345678e+00 2.9743611e+00 4.8043725e+00 3.1946631e+00 3.6425792e+00 3.9147944e+00 3.0137993e+00 2.8509730e+00 3.6160190e+00 3.7930649e+00 4.3160863e+00 4.8705552e+00 3.6935350e+00 2.9765851e+00 3.2157655e+00 4.7030966e+00 3.6383061e+00 3.1964791e+00 2.7656084e+00 3.7055141e+00 3.8768834e+00 3.7701724e+00 3.1157672e+00 3.9366463e+00 3.9674740e+00 3.7027144e+00 3.5167570e+00 3.3369517e+00 3.4319544e+00 2.8332022e+00 9.6865373e-01 3.9487224e-01 5.8131330e-01 5.6003943e-01 5.0621589e-01 7.1247632e-01 8.0317491e-01 1.7053539e+00 2.0491684e+00 7.4957404e-01 6.5459290e-01 9.3991103e-01 7.4957404e-01 1.0954558e+00 4.2737382e-01 4.9430028e-01 2.5884539e+00 7.4949264e-01 6.4432393e-01 1.0251728e+00 9.7391954e-01 1.0055888e+00 5.9279023e-01 9.4588685e-01 4.3798311e-01 3.5017283e+00 3.0032209e+00 3.5640998e+00 3.2626300e+00 3.3723783e+00 2.7101865e+00 3.0361435e+00 2.6574564e+00 3.2363742e+00 2.5684615e+00 3.5220489e+00 2.6863775e+00 3.5035562e+00 2.9639854e+00 2.2954282e+00 3.1974234e+00 2.6186896e+00 2.5919605e+00 3.9485388e+00 2.8137879e+00 3.0123600e+00 2.8059985e+00 3.6581986e+00 2.9351026e+00 2.9984934e+00 3.1711590e+00 3.5947528e+00 3.6146776e+00 2.9159819e+00 2.5508141e+00 2.9298445e+00 2.8588898e+00 2.6582994e+00 3.3705985e+00 2.5395254e+00 2.7634723e+00 3.3411818e+00 3.7151762e+00 2.3273691e+00 2.9184140e+00 2.8006021e+00 2.8512853e+00 2.8277392e+00 2.8675465e+00 2.7048983e+00 2.3342128e+00 2.5075548e+00 2.8488482e+00 2.4938133e+00 2.5939117e+00 4.2210242e+00 3.5094230e+00 4.4613495e+00 3.6611526e+00 4.1011462e+00 5.0575391e+00 3.2183295e+00 4.5889909e+00 4.3421582e+00 4.8334387e+00 3.6441411e+00 3.8749352e+00 4.1286607e+00 3.7602700e+00 3.8694583e+00 3.9027404e+00 3.6910974e+00 5.2330448e+00 5.5920875e+00 3.9683831e+00 4.3421746e+00 3.3618744e+00 5.2099570e+00 3.6296154e+00 4.0192804e+00 4.2904705e+00 3.4453138e+00 3.2560920e+00 4.0303932e+00 4.1835729e+00 4.7330562e+00 5.1897695e+00 4.1126264e+00 3.3744864e+00 3.5691373e+00 5.1336306e+00 3.9986271e+00 3.5735980e+00 3.1698618e+00 4.1283627e+00 4.2954773e+00 4.2156054e+00 3.5094230e+00 4.3310092e+00 4.3633885e+00 4.1455698e+00 3.9545856e+00 3.7585686e+00 3.7901495e+00 3.2094268e+00 9.5902306e-01 1.1795364e+00 9.6032771e-01 5.8652824e-01 3.3395426e-01 1.0753036e+00 2.5524007e+00 2.8349345e+00 2.9691107e-01 5.1396090e-01 1.3127309e+00 2.9691107e-01 7.4426155e-01 9.3211669e-01 1.1729612e+00 1.7369516e+00 8.7560645e-01 1.2666796e+00 1.8751947e+00 2.9724335e-01 1.8489906e+00 6.7745878e-01 1.6555341e+00 7.0111465e-01 3.4067014e+00 2.9452188e+00 3.4231096e+00 2.6265336e+00 3.0474186e+00 2.3887954e+00 3.0652160e+00 1.9891259e+00 2.9589070e+00 2.1699637e+00 2.7527251e+00 2.5008826e+00 2.7949298e+00 2.7160947e+00 1.9851008e+00 3.0428102e+00 2.4755098e+00 2.1256864e+00 3.3327734e+00 2.2236827e+00 3.0131023e+00 2.4300526e+00 3.1928299e+00 2.6040863e+00 2.7075499e+00 2.9536823e+00 3.2710263e+00 3.4338296e+00 2.6673396e+00 1.9555334e+00 2.2858019e+00 2.1897213e+00 2.1973377e+00 3.0392888e+00 2.4158794e+00 2.8941568e+00 3.2025759e+00 3.1091590e+00 2.1471303e+00 2.3710990e+00 2.3347284e+00 2.6698387e+00 2.3133518e+00 2.1525596e+00 2.2918773e+00 2.1454625e+00 2.2398142e+00 2.5636830e+00 1.8343082e+00 2.2388656e+00 4.2714137e+00 3.2107728e+00 4.3091817e+00 3.4717121e+00 3.9768763e+00 4.9078859e+00 2.8122927e+00 4.3885241e+00 3.9504682e+00 4.9558940e+00 3.6044479e+00 3.5632387e+00 3.9760735e+00 3.3646188e+00 3.6594046e+00 3.8782141e+00 3.5443654e+00 5.4091146e+00 5.2988184e+00 3.3878489e+00 4.2952367e+00 3.1303129e+00 4.9761618e+00 3.2919446e+00 4.0362588e+00 4.2291285e+00 3.1618923e+00 3.1077588e+00 3.7959134e+00 4.0112445e+00 4.4810404e+00 5.3509795e+00 3.8831153e+00 3.0844802e+00 3.1980603e+00 4.9707249e+00 4.0945548e+00 3.4918172e+00 3.0237585e+00 4.0192804e+00 4.2092252e+00 4.1017980e+00 3.2107728e+00 4.2952415e+00 4.3790330e+00 3.9936934e+00 3.5312555e+00 3.6065699e+00 3.8937621e+00 3.0840989e+00 4.2827238e-01 3.7398306e-01 6.4241342e-01 7.7828522e-01 4.8636669e-01 1.6800011e+00 1.9622194e+00 8.0686941e-01 5.7691891e-01 7.1789533e-01 8.0686941e-01 1.2139401e+00 2.9406726e-01 3.1507080e-01 2.6166211e+00 9.1398375e-01 3.4909881e-01 9.4580058e-01 9.6922609e-01 9.6659661e-01 7.2638147e-01 8.2574748e-01 3.6704030e-01 3.2939549e+00 2.8018134e+00 3.3643791e+00 3.1688464e+00 3.1882120e+00 2.5926123e+00 2.8420400e+00 2.6229843e+00 3.0569434e+00 2.4659441e+00 3.4932809e+00 2.5062529e+00 3.4038365e+00 2.8103848e+00 2.1284730e+00 2.9880998e+00 2.4809350e+00 2.4830222e+00 3.8129321e+00 2.7155086e+00 2.8370039e+00 2.6306749e+00 3.5140670e+00 2.8045035e+00 2.8143558e+00 2.9698163e+00 3.4126571e+00 3.4177063e+00 2.7508387e+00 2.4282690e+00 2.8424700e+00 2.7781836e+00 2.5174968e+00 3.2360555e+00 2.4214382e+00 2.5753180e+00 3.1397228e+00 3.5790751e+00 2.1850441e+00 2.8131786e+00 2.7177153e+00 2.6876771e+00 2.6993734e+00 2.8253248e+00 2.5871836e+00 2.1990767e+00 2.3678133e+00 2.6762366e+00 2.4070540e+00 2.4551607e+00 4.0383784e+00 3.3671653e+00 4.2642537e+00 3.5070157e+00 3.9193977e+00 4.8684861e+00 3.1505769e+00 4.4165051e+00 4.1898287e+00 4.6203725e+00 3.4386758e+00 3.7047820e+00 3.9273366e+00 3.6237778e+00 3.6947343e+00 3.6968840e+00 3.5190023e+00 5.0398879e+00 5.4089760e+00 3.8611646e+00 4.1322470e+00 3.2145601e+00 5.0295849e+00 3.4546083e+00 3.8248698e+00 4.1055247e+00 3.2664139e+00 3.0788010e+00 3.8567883e+00 4.0060320e+00 4.5478501e+00 4.9912214e+00 3.9339246e+00 3.2236553e+00 3.4677443e+00 4.9178815e+00 3.8042163e+00 3.4041321e+00 2.9939885e+00 3.9171296e+00 4.0866646e+00 3.9845548e+00 3.3671653e+00 4.1322520e+00 4.1520423e+00 3.9277271e+00 3.7880802e+00 3.5624203e+00 3.5967687e+00 3.0549169e+00 2.3749211e-01 9.2006504e-01 1.0428797e+00 4.2450569e-01 1.3899721e+00 1.6555341e+00 9.9973471e-01 7.5230154e-01 3.7960845e-01 9.9973471e-01 1.5086315e+00 2.6033464e-01 2.9724335e-01 2.8989712e+00 1.1937015e+00 5.7988427e-01 7.8318003e-01 1.2583645e+00 7.0463400e-01 1.0034646e+00 4.7680727e-01 5.2374483e-01 3.3114294e+00 2.8933417e+00 3.4177063e+00 3.4461307e+00 3.3255941e+00 2.8176969e+00 2.9380167e+00 2.9507452e+00 3.1524130e+00 2.7797208e+00 3.7960371e+00 2.6995806e+00 3.6095704e+00 2.9762135e+00 2.3753547e+00 3.0506196e+00 2.7121484e+00 2.6831858e+00 4.0299127e+00 2.9653560e+00 3.0144396e+00 2.8058449e+00 3.7011663e+00 2.9654419e+00 2.9344166e+00 3.0597490e+00 3.5085997e+00 3.5226725e+00 2.9395346e+00 2.6564538e+00 3.1076159e+00 3.0365838e+00 2.7379532e+00 3.4446760e+00 2.6796909e+00 2.6912430e+00 3.2129972e+00 3.7686900e+00 2.4108238e+00 3.0879511e+00 2.9762529e+00 2.8408428e+00 2.9254092e+00 3.1396427e+00 2.8384396e+00 2.3985415e+00 2.5881776e+00 2.8229620e+00 2.7289403e+00 2.6869860e+00 4.1910480e+00 3.6130663e+00 4.3602249e+00 3.6707779e+00 4.0745117e+00 4.9277939e+00 3.4934873e+00 4.4880495e+00 4.3514534e+00 4.6654573e+00 3.5594056e+00 3.8864758e+00 4.0498126e+00 3.8963526e+00 3.9502563e+00 3.8456535e+00 3.6509387e+00 5.0146974e+00 5.5101576e+00 4.0937915e+00 4.2345704e+00 3.4807992e+00 5.0960662e+00 3.6438388e+00 3.9190152e+00 4.1487738e+00 3.4580678e+00 3.2588014e+00 4.0378648e+00 4.0580582e+00 4.6285945e+00 4.9381887e+00 4.1199488e+00 3.3816601e+00 3.6553790e+00 4.9813108e+00 3.9405186e+00 3.5335600e+00 3.1869497e+00 4.0186781e+00 4.2240093e+00 4.0988575e+00 3.6130663e+00 4.2429720e+00 4.2712088e+00 4.0719125e+00 3.9975817e+00 3.7087600e+00 3.7375363e+00 3.2561951e+00 7.6824760e-01 8.5141186e-01 3.6086962e-01 1.6207126e+00 1.8802756e+00 7.9394533e-01 5.3286499e-01 4.3319335e-01 7.9394533e-01 1.3370188e+00 1.3340137e-01 3.6319073e-01 2.6778759e+00 1.0720705e+00 6.3173774e-01 1.0072799e+00 1.0495503e+00 9.3727156e-01 8.5893964e-01 7.0463400e-01 3.3395426e-01 3.3027871e+00 2.8812178e+00 3.3955887e+00 3.2888081e+00 3.2512254e+00 2.7283479e+00 2.9463809e+00 2.7764635e+00 3.0911130e+00 2.6620270e+00 3.6054231e+00 2.6430457e+00 3.4442793e+00 2.9123088e+00 2.2793286e+00 3.0205073e+00 2.6595069e+00 2.5635668e+00 3.8866925e+00 2.8178210e+00 3.0060120e+00 2.7101865e+00 3.5930006e+00 2.8829084e+00 2.8651003e+00 3.0121201e+00 3.4400598e+00 3.4869142e+00 2.8725792e+00 2.5068325e+00 2.9480926e+00 2.8720011e+00 2.6183827e+00 3.3619078e+00 2.6263990e+00 2.7176350e+00 3.1874455e+00 3.6289342e+00 2.3459758e+00 2.9476507e+00 2.8536577e+00 2.7917808e+00 2.7959976e+00 2.9585178e+00 2.7268209e+00 2.3347284e+00 2.5080346e+00 2.7508387e+00 2.5565749e+00 2.5881776e+00 4.2068537e+00 3.5342439e+00 4.3380559e+00 3.6271373e+00 4.0499864e+00 4.9127682e+00 3.3748745e+00 4.4574738e+00 4.2666131e+00 4.7143178e+00 3.5549829e+00 3.8149934e+00 4.0227420e+00 3.7946027e+00 3.8919837e+00 3.8432323e+00 3.6208873e+00 5.0849580e+00 5.4596452e+00 3.9569474e+00 4.2354064e+00 3.4126422e+00 5.0611947e+00 3.5638945e+00 3.9334644e+00 4.1519487e+00 3.3885059e+00 3.2191166e+00 3.9849073e+00 4.0334328e+00 4.5859724e+00 5.0075986e+00 4.0680600e+00 3.3134027e+00 3.5670952e+00 4.9632121e+00 3.9675062e+00 3.5176551e+00 3.1453377e+00 4.0038982e+00 4.2114761e+00 4.0820077e+00 3.5342439e+00 4.2453199e+00 4.2844704e+00 4.0426067e+00 3.8984747e+00 3.6765607e+00 3.7642725e+00 3.2184749e+00 2.6033464e-01 9.9962901e-01 2.1664244e+00 2.5030472e+00 3.6319073e-01 4.2737382e-01 1.2004100e+00 3.6319073e-01 6.1067563e-01 6.7030885e-01 8.0996690e-01 2.1006743e+00 4.0020411e-01 9.4057729e-01 1.4985933e+00 5.0731024e-01 1.4656715e+00 1.6562722e-01 1.3630799e+00 4.4417668e-01 3.6433721e+00 3.1333439e+00 3.6757970e+00 3.0281244e+00 3.3717708e+00 2.6624050e+00 3.1998148e+00 2.3430115e+00 3.2729115e+00 2.4219924e+00 3.1700354e+00 2.7177110e+00 3.2760900e+00 2.9826961e+00 2.2410752e+00 3.2981044e+00 2.6452183e+00 2.4901533e+00 3.7687554e+00 2.6225184e+00 3.1280668e+00 2.7635526e+00 3.5692464e+00 2.9177616e+00 3.0187150e+00 3.2354747e+00 3.6116754e+00 3.6909005e+00 2.9234404e+00 2.3731183e+00 2.6987010e+00 2.6178190e+00 2.5515904e+00 3.3308561e+00 2.5554841e+00 2.9570491e+00 3.4460544e+00 3.5549612e+00 2.3407691e+00 2.7326628e+00 2.6614903e+00 2.9042354e+00 2.6919656e+00 2.5430017e+00 2.6000033e+00 2.3578684e+00 2.4871797e+00 2.8599439e+00 2.2045434e+00 2.5287499e+00 4.3690091e+00 3.4628576e+00 4.5552847e+00 3.7077077e+00 4.1799642e+00 5.1678263e+00 3.0379779e+00 4.6720960e+00 4.3013447e+00 5.0550361e+00 3.7713495e+00 3.8605708e+00 4.2104897e+00 3.6525334e+00 3.8549710e+00 4.0229434e+00 3.7708197e+00 5.5011831e+00 5.6245097e+00 3.7945557e+00 4.4755001e+00 3.3306776e+00 5.2815051e+00 3.5995462e+00 4.1814664e+00 4.4417427e+00 3.4376057e+00 3.3113002e+00 4.0501276e+00 4.2847585e+00 4.7905454e+00 5.4600808e+00 4.1319681e+00 3.3795104e+00 3.5192584e+00 5.2359042e+00 4.1708373e+00 3.6809073e+00 3.2190305e+00 4.2365575e+00 4.3973146e+00 4.3149219e+00 3.4628576e+00 4.4657183e+00 4.5132257e+00 4.2167698e+00 3.8749352e+00 3.8293474e+00 3.9628758e+00 3.2623926e+00 1.0371214e+00 2.3606689e+00 2.6764689e+00 1.8699153e-01 4.0363332e-01 1.2627589e+00 1.8699153e-01 5.6164055e-01 7.8305765e-01 9.7747632e-01 1.8924893e+00 5.6164055e-01 1.0881632e+00 1.6837963e+00 2.8845946e-01 1.6545637e+00 3.5266705e-01 1.5108472e+00 5.3286499e-01 3.5596461e+00 3.0642731e+00 3.5820652e+00 2.8366432e+00 3.2382208e+00 2.5375138e+00 3.1537738e+00 2.1559444e+00 3.1474432e+00 2.2926143e+00 2.9585178e+00 2.6250629e+00 3.0590120e+00 2.8699760e+00 2.1233327e+00 3.2024265e+00 2.5670381e+00 2.3272067e+00 3.5735096e+00 2.4368431e+00 3.0826231e+00 2.6212838e+00 3.4052824e+00 2.7833861e+00 2.8923043e+00 3.1255601e+00 3.4747564e+00 3.5908785e+00 2.8135312e+00 2.1839196e+00 2.5032729e+00 2.4158569e+00 2.3928312e+00 3.2017644e+00 2.4862299e+00 2.9403226e+00 3.3545989e+00 3.3587820e+00 2.2520446e+00 2.5607059e+00 2.5059290e+00 2.8073565e+00 2.5209771e+00 2.3430115e+00 2.4562939e+00 2.2633781e+00 2.3755041e+00 2.7368591e+00 2.0165442e+00 2.3969046e+00 4.3354025e+00 3.3475977e+00 4.4615703e+00 3.6095772e+00 4.0990362e+00 5.0710534e+00 2.9144612e+00 4.5627576e+00 4.1522674e+00 5.0316497e+00 3.7102339e+00 3.7341705e+00 4.1195531e+00 3.5174471e+00 3.7659275e+00 3.9693828e+00 3.6809073e+00 5.4858042e+00 5.4945039e+00 3.6088006e+00 4.4109170e+00 3.2362256e+00 5.1634795e+00 3.4678413e+00 4.1322470e+00 4.3666536e+00 3.3199204e+00 3.2266664e+00 3.9433408e+00 4.1815045e+00 4.6694810e+00 5.4392260e+00 4.0273519e+00 3.2552513e+00 3.3773249e+00 5.1375752e+00 4.1484621e+00 3.6075786e+00 3.1365574e+00 4.1554935e+00 4.3260165e+00 4.2353581e+00 3.3475977e+00 4.4043042e+00 4.4676627e+00 4.1295047e+00 3.7244531e+00 3.7408419e+00 3.9430201e+00 3.1856251e+00 1.6790448e+00 1.8683303e+00 9.9891776e-01 7.3735391e-01 3.8639663e-01 9.9891776e-01 1.5462701e+00 4.4713936e-01 5.6262711e-01 2.7653818e+00 1.3238834e+00 5.9868400e-01 1.0167074e+00 1.1817121e+00 1.0267382e+00 1.1036371e+00 7.4965096e-01 5.9868400e-01 2.9920629e+00 2.5767485e+00 3.0904477e+00 3.1383073e+00 2.9738737e+00 2.5155127e+00 2.6450302e+00 2.7097016e+00 2.8120208e+00 2.4963677e+00 3.5442384e+00 2.3737852e+00 3.2878773e+00 2.6552959e+00 2.0482711e+00 2.7132601e+00 2.4244329e+00 2.3725931e+00 3.6825624e+00 2.6567419e+00 2.7277627e+00 2.4551607e+00 3.3586468e+00 2.6490703e+00 2.5878996e+00 2.7146857e+00 3.1604264e+00 3.1862677e+00 2.6121387e+00 2.3320406e+00 2.8060955e+00 2.7397840e+00 2.4059801e+00 3.1251810e+00 2.4123722e+00 2.4266062e+00 2.8827369e+00 3.4219145e+00 2.1146056e+00 2.7787333e+00 2.6868306e+00 2.5237903e+00 2.5969195e+00 2.8858666e+00 2.5292454e+00 2.1030528e+00 2.2789104e+00 2.4843930e+00 2.4502513e+00 2.3681813e+00 3.9129285e+00 3.2963379e+00 4.0307050e+00 3.3579713e+00 3.7573925e+00 4.6072225e+00 3.2350676e+00 4.1666050e+00 4.0096938e+00 4.3939440e+00 3.2458961e+00 3.5448948e+00 3.7163166e+00 3.5735211e+00 3.6303034e+00 3.5366397e+00 3.3347301e+00 4.7764597e+00 5.1656525e+00 3.7678733e+00 3.9190152e+00 3.1752055e+00 4.7655871e+00 3.2963860e+00 3.6257668e+00 3.8480918e+00 3.1163356e+00 2.9401017e+00 3.7060704e+00 3.7400429e+00 4.2905130e+00 4.6982735e+00 3.7862785e+00 3.0555922e+00 3.3519252e+00 4.6433941e+00 3.6672706e+00 3.2313825e+00 2.8704346e+00 3.6888814e+00 3.9001229e+00 3.7578379e+00 3.2963379e+00 3.9355102e+00 3.9693842e+00 3.7298088e+00 3.6452459e+00 3.3776637e+00 3.4666091e+00 2.9570067e+00 4.5257749e-01 2.3345854e+00 2.1006743e+00 1.4408765e+00 2.3345854e+00 2.7201861e+00 1.6242170e+00 1.4334280e+00 4.2461520e+00 2.2960397e+00 1.5510150e+00 8.3619405e-01 2.5963945e+00 7.1671402e-01 2.2031378e+00 9.3957399e-01 1.8662528e+00 3.9018608e+00 3.5587525e+00 4.0758181e+00 4.6738622e+00 4.2315488e+00 3.8362958e+00 3.5101695e+00 4.2349456e+00 4.0096351e+00 3.8957954e+00 5.1177048e+00 3.5857491e+00 4.8511271e+00 3.8770675e+00 3.4324591e+00 3.7687554e+00 3.5952204e+00 3.8095276e+00 5.1880951e+00 4.1733990e+00 3.6719420e+00 3.8275992e+00 4.7391892e+00 3.9417326e+00 3.8406076e+00 3.8597390e+00 4.3729123e+00 4.2482658e+00 3.8534412e+00 3.8740219e+00 4.3496532e+00 4.2951960e+00 3.8572117e+00 4.4028225e+00 3.5707989e+00 3.2084035e+00 3.9057558e+00 4.9165227e+00 3.3635180e+00 4.2694314e+00 4.1082916e+00 3.6886188e+00 4.0716087e+00 4.4411156e+00 3.9335446e+00 3.3496034e+00 3.5830335e+00 3.7561390e+00 4.0088699e+00 3.7413425e+00 4.6436290e+00 4.5471223e+00 4.9787007e+00 4.4481204e+00 4.7341193e+00 5.4826137e+00 4.5863292e+00 5.1433212e+00 5.2725182e+00 4.8836508e+00 4.1393671e+00 4.7672599e+00 4.7092337e+00 4.9106562e+00 4.7707455e+00 4.3996661e+00 4.3591552e+00 5.0844032e+00 6.2257171e+00 5.2378683e+00 4.7433741e+00 4.3742533e+00 5.7435198e+00 4.5678545e+00 4.3840310e+00 4.6485090e+00 4.3482964e+00 4.0364176e+00 4.8328894e+00 4.6980887e+00 5.3298852e+00 5.0020990e+00 4.9051796e+00 4.2757519e+00 4.6314634e+00 5.5369700e+00 4.3420582e+00 4.1857666e+00 3.9786340e+00 4.6138259e+00 4.8044656e+00 4.6911542e+00 4.5471223e+00 4.7508760e+00 4.7161034e+00 4.7355095e+00 4.9879154e+00 4.4154797e+00 4.1545903e+00 4.0343137e+00 2.6422396e+00 2.3867296e+00 1.6154069e+00 2.6422396e+00 3.0703842e+00 1.9080710e+00 1.7295385e+00 4.5475791e+00 2.6621202e+00 1.8051284e+00 1.1105716e+00 2.8967543e+00 1.0474897e+00 2.5495727e+00 1.1795364e+00 2.1617152e+00 3.8171826e+00 3.5339654e+00 4.0163479e+00 4.8425911e+00 4.2514283e+00 3.9557653e+00 3.4792404e+00 4.4740529e+00 4.0150475e+00 4.0717494e+00 5.3501548e+00 3.6486698e+00 4.9910943e+00 3.9350582e+00 3.5547141e+00 3.7282030e+00 3.6962934e+00 3.9420318e+00 5.2895497e+00 4.3341610e+00 3.6960949e+00 3.8986276e+00 4.8106103e+00 4.0206152e+00 3.8664495e+00 3.8454452e+00 4.3675713e+00 4.2173036e+00 3.9169317e+00 4.0237417e+00 4.5248905e+00 4.4756871e+00 3.9778974e+00 4.4827624e+00 3.6962934e+00 3.1970228e+00 3.8646917e+00 5.0103465e+00 3.4775294e+00 4.4295579e+00 4.2690345e+00 3.7344524e+00 4.1995700e+00 4.6716989e+00 4.0716455e+00 3.4573201e+00 3.6936958e+00 3.8056210e+00 4.2211876e+00 3.8604223e+00 4.5958210e+00 4.6323449e+00 4.9087471e+00 4.4703758e+00 4.7121623e+00 5.3828288e+00 4.7798674e+00 5.0815530e+00 5.2996504e+00 4.7231435e+00 4.0911974e+00 4.7955081e+00 4.6606898e+00 5.0156099e+00 4.8233009e+00 4.3540706e+00 4.3488974e+00 4.8785742e+00 6.1614901e+00 5.3577416e+00 4.6571075e+00 4.4651793e+00 5.6630236e+00 4.6077729e+00 4.3065165e+00 4.5525984e+00 4.3873290e+00 4.0638414e+00 4.8447047e+00 4.6322938e+00 5.2676175e+00 4.7796156e+00 4.9133278e+00 4.3194697e+00 4.7202167e+00 5.4208419e+00 4.2794874e+00 4.1728215e+00 4.0165591e+00 4.5422714e+00 4.7447407e+00 4.6112705e+00 4.6323449e+00 4.6754921e+00 4.6293227e+00 4.6871898e+00 5.0428586e+00 4.3953592e+00 4.1024574e+00 4.0848110e+00 3.3742167e-01 1.1857824e+00 0.0000000e+00 6.6918102e-01 7.4445830e-01 9.7322023e-01 1.9284841e+00 6.6918102e-01 1.1393372e+00 1.6942803e+00 3.7371902e-01 1.6386105e+00 4.5257749e-01 1.4715172e+00 4.9772204e-01 3.5602797e+00 3.0968979e+00 3.5933352e+00 2.8998722e+00 3.2656298e+00 2.6029746e+00 3.1974447e+00 2.2445103e+00 3.1601923e+00 2.3946216e+00 3.0209665e+00 2.6867317e+00 3.0775658e+00 2.9161244e+00 2.1946278e+00 3.2137635e+00 2.6502891e+00 2.3652711e+00 3.6096140e+00 2.4893065e+00 3.1578003e+00 2.6568473e+00 3.4426472e+00 2.8187901e+00 2.9128857e+00 3.1418202e+00 3.4847097e+00 3.6205958e+00 2.8694312e+00 2.2223283e+00 2.5588203e+00 2.4651138e+00 2.4413293e+00 3.2621861e+00 2.5834128e+00 2.9995857e+00 3.3733791e+00 3.3817876e+00 2.3263008e+00 2.6305758e+00 2.5756071e+00 2.8533918e+00 2.5683063e+00 2.4187322e+00 2.5258216e+00 2.3250308e+00 2.4413618e+00 2.7691536e+00 2.1006933e+00 2.4608850e+00 4.4119896e+00 3.4290419e+00 4.4942656e+00 3.6650933e+00 4.1590662e+00 5.0899438e+00 3.0333619e+00 4.5799469e+00 4.1882413e+00 5.0726081e+00 3.7613721e+00 3.7859992e+00 4.1623715e+00 3.6029758e+00 3.8608065e+00 4.0352348e+00 3.7266849e+00 5.5043247e+00 5.5172732e+00 3.6569442e+00 4.4568115e+00 3.3324016e+00 5.1765224e+00 3.5192065e+00 4.1799642e+00 4.3857400e+00 3.3769078e+00 3.2906843e+00 4.0034548e+00 4.1917183e+00 4.6854597e+00 5.4444866e+00 4.0904298e+00 3.2962678e+00 3.4250783e+00 5.1569386e+00 4.2213314e+00 3.6582637e+00 3.2059261e+00 4.1937040e+00 4.3826532e+00 4.2786320e+00 3.4290419e+00 4.4549850e+00 4.5270304e+00 4.1816268e+00 3.7777251e+00 3.7924144e+00 4.0173731e+00 3.2613828e+00 9.2006504e-01 3.3742167e-01 8.6080744e-01 5.0621589e-01 7.0646671e-01 2.1664244e+00 7.2679299e-01 8.9712099e-01 1.4681660e+00 5.4873947e-01 1.4074199e+00 4.9617437e-01 1.2206236e+00 2.5698045e-01 3.4986942e+00 3.0427234e+00 3.5520531e+00 3.0444864e+00 3.2783159e+00 2.6723101e+00 3.1333743e+00 2.4360210e+00 3.1627463e+00 2.4904253e+00 3.2338077e+00 2.6808015e+00 3.2240677e+00 2.9412073e+00 2.2206950e+00 3.1669559e+00 2.6716144e+00 2.4623998e+00 3.7173707e+00 2.6198784e+00 3.1208539e+00 2.6854361e+00 3.5171200e+00 2.8753360e+00 2.9157449e+00 3.1157529e+00 3.4945103e+00 3.5956983e+00 2.8873581e+00 2.3297122e+00 2.7075732e+00 2.6220688e+00 2.5143128e+00 3.3225169e+00 2.6164571e+00 2.9213819e+00 3.3323415e+00 3.4842326e+00 2.3487772e+00 2.7507828e+00 2.6991998e+00 2.8571158e+00 2.6614903e+00 2.6122501e+00 2.6121387e+00 2.3527202e+00 2.4822998e+00 2.7826627e+00 2.2477567e+00 2.5188545e+00 4.3590737e+00 3.4800724e+00 4.4652192e+00 3.6820633e+00 4.1423404e+00 5.0632361e+00 3.1594575e+00 4.5764429e+00 4.2442248e+00 4.9703970e+00 3.7054123e+00 3.8144340e+00 4.1322520e+00 3.6772717e+00 3.8704422e+00 3.9786899e+00 3.7187193e+00 5.3973273e+00 5.5276243e+00 3.7838435e+00 4.3978718e+00 3.3669786e+00 5.1732410e+00 3.5478651e+00 4.1195682e+00 4.3422158e+00 3.3925731e+00 3.2818178e+00 4.0157845e+00 4.1753467e+00 4.6824968e+00 5.3318394e+00 4.0983108e+00 3.3321312e+00 3.5171976e+00 5.1116177e+00 4.1480571e+00 3.6395566e+00 3.1983718e+00 4.1451783e+00 4.3355345e+00 4.2161052e+00 3.4800724e+00 4.4037157e+00 4.4559384e+00 4.1399085e+00 3.8303307e+00 3.7678377e+00 3.9434740e+00 3.2672961e+00 1.1857824e+00 1.7590894e+00 5.4715569e-01 6.1787077e-01 3.0224093e+00 1.4977817e+00 8.1744862e-01 9.4676850e-01 1.4369223e+00 8.6079202e-01 1.2896554e+00 5.3286499e-01 7.6195008e-01 3.1536923e+00 2.8019556e+00 3.2823965e+00 3.4754319e+00 3.2348803e+00 2.8339836e+00 2.8678686e+00 3.0569237e+00 3.0422163e+00 2.8599505e+00 3.8711727e+00 2.6769819e+00 3.5769114e+00 2.9369339e+00 2.3887701e+00 2.9172679e+00 2.7450499e+00 2.6744413e+00 3.9868196e+00 2.9825819e+00 3.0070640e+00 2.7478281e+00 3.6492544e+00 2.9260177e+00 2.8398296e+00 2.9417237e+00 3.3879693e+00 3.4191352e+00 2.9103957e+00 2.6495864e+00 3.1359829e+00 3.0635119e+00 2.7246726e+00 3.4310966e+00 2.7450499e+00 2.6593850e+00 3.0929063e+00 3.7090709e+00 2.4372581e+00 3.1206171e+00 3.0186562e+00 2.7973689e+00 2.9151879e+00 3.2261028e+00 2.8631702e+00 2.4096686e+00 2.5984928e+00 2.7564382e+00 2.8056103e+00 2.6945402e+00 4.1622883e+00 3.6243461e+00 4.2495237e+00 3.6308369e+00 4.0200378e+00 4.7940036e+00 3.6050689e+00 4.3664479e+00 4.2800934e+00 4.5553898e+00 3.4840330e+00 3.8323637e+00 3.9571437e+00 3.9163572e+00 3.9605759e+00 3.7909588e+00 3.5846709e+00 4.8756388e+00 5.3862972e+00 4.0807979e+00 4.1385728e+00 3.5138167e+00 4.9592897e+00 3.5910983e+00 3.8379532e+00 4.0230039e+00 3.4134019e+00 3.2269518e+00 3.9906410e+00 3.9261146e+00 4.4982182e+00 4.7746016e+00 4.0736767e+00 3.3286256e+00 3.6393910e+00 4.8333249e+00 3.9033387e+00 3.4776516e+00 3.1661860e+00 3.9124707e+00 4.1473618e+00 3.9899548e+00 3.6243461e+00 4.1607944e+00 4.1969547e+00 3.9859042e+00 3.9511939e+00 3.6382505e+00 3.7066628e+00 3.2552942e+00 6.6918102e-01 7.4445830e-01 9.7322023e-01 1.9284841e+00 6.6918102e-01 1.1393372e+00 1.6942803e+00 3.7371902e-01 1.6386105e+00 4.5257749e-01 1.4715172e+00 4.9772204e-01 3.5602797e+00 3.0968979e+00 3.5933352e+00 2.8998722e+00 3.2656298e+00 2.6029746e+00 3.1974447e+00 2.2445103e+00 3.1601923e+00 2.3946216e+00 3.0209665e+00 2.6867317e+00 3.0775658e+00 2.9161244e+00 2.1946278e+00 3.2137635e+00 2.6502891e+00 2.3652711e+00 3.6096140e+00 2.4893065e+00 3.1578003e+00 2.6568473e+00 3.4426472e+00 2.8187901e+00 2.9128857e+00 3.1418202e+00 3.4847097e+00 3.6205958e+00 2.8694312e+00 2.2223283e+00 2.5588203e+00 2.4651138e+00 2.4413293e+00 3.2621861e+00 2.5834128e+00 2.9995857e+00 3.3733791e+00 3.3817876e+00 2.3263008e+00 2.6305758e+00 2.5756071e+00 2.8533918e+00 2.5683063e+00 2.4187322e+00 2.5258216e+00 2.3250308e+00 2.4413618e+00 2.7691536e+00 2.1006933e+00 2.4608850e+00 4.4119896e+00 3.4290419e+00 4.4942656e+00 3.6650933e+00 4.1590662e+00 5.0899438e+00 3.0333619e+00 4.5799469e+00 4.1882413e+00 5.0726081e+00 3.7613721e+00 3.7859992e+00 4.1623715e+00 3.6029758e+00 3.8608065e+00 4.0352348e+00 3.7266849e+00 5.5043247e+00 5.5172732e+00 3.6569442e+00 4.4568115e+00 3.3324016e+00 5.1765224e+00 3.5192065e+00 4.1799642e+00 4.3857400e+00 3.3769078e+00 3.2906843e+00 4.0034548e+00 4.1917183e+00 4.6854597e+00 5.4444866e+00 4.0904298e+00 3.2962678e+00 3.4250783e+00 5.1569386e+00 4.2213314e+00 3.6582637e+00 3.2059261e+00 4.1937040e+00 4.3826532e+00 4.2786320e+00 3.4290419e+00 4.4549850e+00 4.5270304e+00 4.1816268e+00 3.7777251e+00 3.7924144e+00 4.0173731e+00 3.2613828e+00 1.2563834e+00 1.3681903e+00 1.6242170e+00 4.6126066e-01 1.4691503e+00 2.0743925e+00 5.0370871e-01 2.0365895e+00 5.2374483e-01 1.9494772e+00 1.0034646e+00 4.0320101e+00 3.4981749e+00 4.0289839e+00 2.9648238e+00 3.6116412e+00 2.8362334e+00 3.5807825e+00 2.1594400e+00 3.5619276e+00 2.4608850e+00 2.9150653e+00 2.9806848e+00 3.2524084e+00 3.2332049e+00 2.4351674e+00 3.6506644e+00 2.8794131e+00 2.6371069e+00 3.7842148e+00 2.6442387e+00 3.4386758e+00 2.9743384e+00 3.6958304e+00 3.1396988e+00 3.2947222e+00 3.5521670e+00 3.8756118e+00 3.9969338e+00 3.1587328e+00 2.4432066e+00 2.6604221e+00 2.5745994e+00 2.6880360e+00 3.4951118e+00 2.7657429e+00 3.3524671e+00 3.7924883e+00 3.6104716e+00 2.5876530e+00 2.7410968e+00 2.7238850e+00 3.1914275e+00 2.7871336e+00 2.3484202e+00 2.7125180e+00 2.6235600e+00 2.7012637e+00 3.1219910e+00 2.0888843e+00 2.6969064e+00 4.6820911e+00 3.5968849e+00 4.8607426e+00 3.9563487e+00 4.4501699e+00 5.4913616e+00 2.9743611e+00 4.9743359e+00 4.4659463e+00 5.4618868e+00 4.1043393e+00 4.0513907e+00 4.5016468e+00 3.7087600e+00 4.0024694e+00 4.3310092e+00 4.0611789e+00 5.9599083e+00 5.8632763e+00 3.7995759e+00 4.8081465e+00 3.4697005e+00 5.5699347e+00 3.7817852e+00 4.5398887e+00 4.8101536e+00 3.6425657e+00 3.5739550e+00 4.2642554e+00 4.6155808e+00 5.0696209e+00 5.9318766e+00 4.3420618e+00 3.6079861e+00 3.6711700e+00 5.5546786e+00 4.5127918e+00 3.9935485e+00 3.4733020e+00 4.5569739e+00 4.6922818e+00 4.6236700e+00 3.5968849e+00 4.7939394e+00 4.8471780e+00 4.4913725e+00 3.9942507e+00 4.1085491e+00 4.3067090e+00 3.5093006e+00 3.1271814e-01 2.6440626e+00 9.6964683e-01 5.8796666e-01 9.8545402e-01 1.0013399e+00 9.2426065e-01 7.6195008e-01 7.3283576e-01 2.6643250e-01 3.3524935e+00 2.9103383e+00 3.4378505e+00 3.2794093e+00 3.2805279e+00 2.7218307e+00 2.9677934e+00 2.7417113e+00 3.1265865e+00 2.6350666e+00 3.5810092e+00 2.6509959e+00 3.4564670e+00 2.9240118e+00 2.2778214e+00 3.0636652e+00 2.6473174e+00 2.5673371e+00 3.9008585e+00 2.8131786e+00 3.0066012e+00 2.7310040e+00 3.6088006e+00 2.8947302e+00 2.8966017e+00 3.0506196e+00 3.4785143e+00 3.5188926e+00 2.8816131e+00 2.5125550e+00 2.9397900e+00 2.8645995e+00 2.6245231e+00 3.3639057e+00 2.6028733e+00 2.7271822e+00 3.2253861e+00 3.6489825e+00 2.3376510e+00 2.9371604e+00 2.8382974e+00 2.8051321e+00 2.8006021e+00 2.9309089e+00 2.7184808e+00 2.3312464e+00 2.5047936e+00 2.7731354e+00 2.5341497e+00 2.5862794e+00 4.2119757e+00 3.5278864e+00 4.3705395e+00 3.6366115e+00 4.0640736e+00 4.9516709e+00 3.3348040e+00 4.4927271e+00 4.2867968e+00 4.7459453e+00 3.5773144e+00 3.8303307e+00 4.0501276e+00 3.7856794e+00 3.8862115e+00 3.8584574e+00 3.6392860e+00 5.1247727e+00 5.4955777e+00 3.9594564e+00 4.2633399e+00 3.3993739e+00 5.1011948e+00 3.5798230e+00 3.9561606e+00 4.1885925e+00 3.4019138e+00 3.2277183e+00 3.9971830e+00 4.0727212e+00 4.6247900e+00 5.0557045e+00 4.0800856e+00 3.3285999e+00 3.5685643e+00 5.0078455e+00 3.9761694e+00 3.5324648e+00 3.1505332e+00 4.0358238e+00 4.2334406e+00 4.1156691e+00 3.5278864e+00 4.2682695e+00 4.3053166e+00 4.0686429e+00 3.9122205e+00 3.6972894e+00 3.7712394e+00 3.2160302e+00 2.8326674e+00 1.0103954e+00 4.2829723e-01 7.9126749e-01 1.1795364e+00 7.3442235e-01 8.5582452e-01 6.1158310e-01 4.8284931e-01 3.4789406e+00 3.0164286e+00 3.5708825e+00 3.4760111e+00 3.4435701e+00 2.8856827e+00 3.0483404e+00 2.9286177e+00 3.2959553e+00 2.7769569e+00 3.7899650e+00 2.7721706e+00 3.6919547e+00 3.0773843e+00 2.4199353e+00 3.1984671e+00 2.7597977e+00 2.7743820e+00 4.1049898e+00 3.0189963e+00 3.0754044e+00 2.9033794e+00 3.7972498e+00 3.0781443e+00 3.0628742e+00 3.1980682e+00 3.6529321e+00 3.6479042e+00 3.0224061e+00 2.7237896e+00 3.1475538e+00 3.0809334e+00 2.8106441e+00 3.5217353e+00 2.7064382e+00 2.7753422e+00 3.3543209e+00 3.8636687e+00 2.4678110e+00 3.1212622e+00 3.0250044e+00 2.9444840e+00 2.9956969e+00 3.1281937e+00 2.8892226e+00 2.4772050e+00 2.6547819e+00 2.9364676e+00 2.7130802e+00 2.7488632e+00 4.2524457e+00 3.6566905e+00 4.4856620e+00 3.7659004e+00 4.1610154e+00 5.0768465e+00 3.4623926e+00 4.6393183e+00 4.4611186e+00 4.7773180e+00 3.6552032e+00 3.9746118e+00 4.1574253e+00 3.9234139e+00 3.9686223e+00 3.9172103e+00 3.7603950e+00 5.1648090e+00 5.6463490e+00 4.1614237e+00 4.3393711e+00 3.5009132e+00 5.2503936e+00 3.7276020e+00 4.0260707e+00 4.3007127e+00 3.5361708e+00 3.3347521e+00 4.1191095e+00 4.2183675e+00 4.7752353e+00 5.1049558e+00 4.1955154e+00 3.4902431e+00 3.7536489e+00 5.1215318e+00 4.0036288e+00 3.6385337e+00 3.2536517e+00 4.1326097e+00 4.3100988e+00 4.1978681e+00 3.6566905e+00 4.3438151e+00 4.3538983e+00 4.1591001e+00 4.0714399e+00 3.8024850e+00 3.7974783e+00 3.3185266e+00 2.0833080e+00 2.8648636e+00 3.5532593e+00 1.6555341e+00 3.5410343e+00 2.0840787e+00 3.3747131e+00 2.3883072e+00 4.3833871e+00 3.9159762e+00 4.2941647e+00 2.3488350e+00 3.6240540e+00 2.9044888e+00 4.0815608e+00 1.5532921e+00 3.6825697e+00 2.4113529e+00 1.7998094e+00 3.2616916e+00 2.5529439e+00 3.3821744e+00 2.6637769e+00 3.9531209e+00 3.1831859e+00 2.5836708e+00 3.1669559e+00 2.2907828e+00 3.8684560e+00 3.0202406e+00 3.4019580e+00 3.1886068e+00 3.4332960e+00 3.7685816e+00 3.8803374e+00 4.1746389e+00 3.3102735e+00 2.2304221e+00 2.1489616e+00 2.0501444e+00 2.6225712e+00 3.4164974e+00 3.0901976e+00 3.9885258e+00 4.0802502e+00 3.0869095e+00 2.9336463e+00 2.3936974e+00 2.5327316e+00 3.4518638e+00 2.5837552e+00 1.5782205e+00 2.6521862e+00 2.9662386e+00 2.9040188e+00 3.2768109e+00 1.6628177e+00 2.7685987e+00 5.0448046e+00 3.5141919e+00 4.9824611e+00 4.0549341e+00 4.5981277e+00 5.5863508e+00 2.6647036e+00 5.0241554e+00 4.1998979e+00 5.9440534e+00 4.4432394e+00 3.9560997e+00 4.6422438e+00 3.4164839e+00 4.0005863e+00 4.6454886e+00 4.2390210e+00 6.5166388e+00 5.6880370e+00 3.1944389e+00 5.0789131e+00 3.4956324e+00 5.5310286e+00 3.6881384e+00 4.9152167e+00 5.0890922e+00 3.6527501e+00 3.7902440e+00 4.2540354e+00 4.7585941e+00 5.0389487e+00 6.4918086e+00 4.3280601e+00 3.6284588e+00 3.4969965e+00 5.6399353e+00 4.9671290e+00 4.2659568e+00 3.6994310e+00 4.7714894e+00 4.8963175e+00 4.8281202e+00 3.5141919e+00 5.0683437e+00 5.1871515e+00 4.6280145e+00 3.7055141e+00 4.2764028e+00 4.7873094e+00 3.7371542e+00 1.1433971e+00 1.6774310e+00 6.8299624e-01 1.6304499e+00 2.4808718e-01 1.5886765e+00 7.6250797e-01 4.0055392e+00 3.4676312e+00 4.0289839e+00 3.2391776e+00 3.6989507e+00 2.9466089e+00 3.5208636e+00 2.4804256e+00 3.6211670e+00 2.6281173e+00 3.2921089e+00 3.0161637e+00 3.5345457e+00 3.2983536e+00 2.5210242e+00 3.6506644e+00 2.9161244e+00 2.7938108e+00 4.0292846e+00 2.8755116e+00 3.4075988e+00 3.0797683e+00 3.8646774e+00 3.2397520e+00 3.3586779e+00 3.5819899e+00 3.9571013e+00 4.0234614e+00 3.2253861e+00 2.6519927e+00 2.9269738e+00 2.8491914e+00 2.8419330e+00 3.6148101e+00 2.8039428e+00 3.2558795e+00 3.7924883e+00 3.8389577e+00 2.6284424e+00 2.9648238e+00 2.9126202e+00 3.2245885e+00 2.9718548e+00 2.6864788e+00 2.8651003e+00 2.6637996e+00 2.7789114e+00 3.1894122e+00 2.3748697e+00 2.8127546e+00 4.6364269e+00 3.7133040e+00 4.8825792e+00 4.0097653e+00 4.4740109e+00 5.5106999e+00 3.1817279e+00 5.0169254e+00 4.6066522e+00 5.3636182e+00 4.0783379e+00 4.1550948e+00 4.5252166e+00 3.8770438e+00 4.0814269e+00 4.3063766e+00 4.0872895e+00 5.8336247e+00 5.9533030e+00 4.0437148e+00 4.7859703e+00 3.5604924e+00 5.6269403e+00 3.8926783e+00 4.4927794e+00 4.7879866e+00 3.7291513e+00 3.6035976e+00 4.3384511e+00 4.6385717e+00 5.1321867e+00 5.8049832e+00 4.4149501e+00 3.6953819e+00 3.8133051e+00 5.5737973e+00 4.4415093e+00 3.9935485e+00 3.5037963e+00 4.5569739e+00 4.6922818e+00 4.6236700e+00 3.7133040e+00 4.7716971e+00 4.8030835e+00 4.5149959e+00 4.1509766e+00 4.1343605e+00 4.2319568e+00 3.5394847e+00 7.6869104e-01 1.2471855e+00 8.7636491e-01 9.9981032e-01 7.8863556e-01 7.0733904e-01 3.2400577e+00 2.7256768e+00 3.3173156e+00 3.2734582e+00 3.1889456e+00 2.6198618e+00 2.7351941e+00 2.7665224e+00 3.0627699e+00 2.5021229e+00 3.6608924e+00 2.4643905e+00 3.5457670e+00 2.8045035e+00 2.1368327e+00 2.9466857e+00 2.4386380e+00 2.5729082e+00 3.8963334e+00 2.8235662e+00 2.7242811e+00 2.6575342e+00 3.5598437e+00 2.8418228e+00 2.8206835e+00 2.9462527e+00 3.4233881e+00 3.3667899e+00 2.7322904e+00 2.5411273e+00 2.9638750e+00 2.9140871e+00 2.5797070e+00 3.2425969e+00 2.3780833e+00 2.4351544e+00 3.0892387e+00 3.6720185e+00 2.1688001e+00 2.8939857e+00 2.7945402e+00 2.6616170e+00 2.7767058e+00 2.9769851e+00 2.6347557e+00 2.1986118e+00 2.3753308e+00 2.6828901e+00 2.5283291e+00 2.4839186e+00 3.8851614e+00 3.3427747e+00 4.1909067e+00 3.4628626e+00 3.8305140e+00 4.8043725e+00 3.1800308e+00 4.3815267e+00 4.2038608e+00 4.4513681e+00 3.3256952e+00 3.6826282e+00 3.8475722e+00 3.6210755e+00 3.6107649e+00 3.5632387e+00 3.4596612e+00 4.8847297e+00 5.3781989e+00 3.9435460e+00 4.0131264e+00 3.1614358e+00 4.9957986e+00 3.4408340e+00 3.7000441e+00 4.0284550e+00 3.2354442e+00 3.0107962e+00 3.8036057e+00 3.9713385e+00 4.5180638e+00 4.8486868e+00 3.8729425e+00 3.2243808e+00 3.5087561e+00 4.8402519e+00 3.6359784e+00 3.3268022e+00 2.9240118e+00 3.8232660e+00 3.9709252e+00 3.8746323e+00 3.3427747e+00 4.0131316e+00 4.0031779e+00 3.8300809e+00 3.7945557e+00 3.4841580e+00 3.4283673e+00 2.9863682e+00 1.9060194e+00 3.1239235e-01 1.5583422e+00 4.8124784e-01 1.2220171e+00 3.3785962e+00 2.9374280e+00 3.5071305e+00 3.8740792e+00 3.5491790e+00 3.0669573e+00 2.9018296e+00 3.4251046e+00 3.3648459e+00 3.0744865e+00 4.3230411e+00 2.8485664e+00 4.1027662e+00 3.1626116e+00 2.6442554e+00 3.1724373e+00 2.8315630e+00 3.0534300e+00 4.4306138e+00 3.3882074e+00 2.9857887e+00 3.0959220e+00 4.0072094e+00 3.2240677e+00 3.1644964e+00 3.2264712e+00 3.7352584e+00 3.6230125e+00 3.1206853e+00 3.1023948e+00 3.5580276e+00 3.5096299e+00 3.0877778e+00 3.6577352e+00 2.7900553e+00 2.5838366e+00 3.3069107e+00 4.1792641e+00 2.5911812e+00 3.4684046e+00 3.3165070e+00 2.9868392e+00 3.2999163e+00 3.6373219e+00 3.1449351e+00 2.5937039e+00 2.8148578e+00 3.0518873e+00 3.1967428e+00 2.9647081e+00 4.0498613e+00 3.7819451e+00 4.3976398e+00 3.7644678e+00 4.0879497e+00 4.9574979e+00 3.7577430e+00 4.5772252e+00 4.5796941e+00 4.4589650e+00 3.5295907e+00 4.0592075e+00 4.0919364e+00 4.1226882e+00 4.0237849e+00 3.7803562e+00 3.7136035e+00 4.7772875e+00 5.6344258e+00 4.4679358e+00 4.1805116e+00 3.6013971e+00 5.1936459e+00 3.8460802e+00 3.8293150e+00 4.1365715e+00 3.6263469e+00 3.3344860e+00 4.1404384e+00 4.1465376e+00 4.7500857e+00 4.7258629e+00 4.2123837e+00 3.5757376e+00 3.9028467e+00 5.0127222e+00 3.7704782e+00 3.5495399e+00 3.2637691e+00 4.0284560e+00 4.1958516e+00 4.1011034e+00 3.7819451e+00 4.1793948e+00 4.1561376e+00 4.1029254e+00 4.2472742e+00 3.7624633e+00 3.5705606e+00 3.3154318e+00 1.8882412e+00 5.3690447e-01 1.7295385e+00 7.4445830e-01 3.5842571e+00 3.0831073e+00 3.5905412e+00 2.6850208e+00 3.1920496e+00 2.4895611e+00 3.1874455e+00 1.9825106e+00 3.1280291e+00 2.1902526e+00 2.7631963e+00 2.5991209e+00 2.9183874e+00 2.8448970e+00 2.0635463e+00 3.2072460e+00 2.5480786e+00 2.2627580e+00 3.4383056e+00 2.3172372e+00 3.0909340e+00 2.5623863e+00 3.3194064e+00 2.7506751e+00 2.8644451e+00 3.1134606e+00 3.4405052e+00 3.5767292e+00 2.7771563e+00 2.0712834e+00 2.3618912e+00 2.2737657e+00 2.3098587e+00 3.1429166e+00 2.4666493e+00 2.9899331e+00 3.3598261e+00 3.2396917e+00 2.2342806e+00 2.4357274e+00 2.4181291e+00 2.7984743e+00 2.4231383e+00 2.1599940e+00 2.3764241e+00 2.2561857e+00 2.3387588e+00 2.7074009e+00 1.8390751e+00 2.3351007e+00 4.3436399e+00 3.2756710e+00 4.4477490e+00 3.5866422e+00 4.0782068e+00 5.0677790e+00 2.7922251e+00 4.5545199e+00 4.0836814e+00 5.0715858e+00 3.7130862e+00 3.6733277e+00 4.0983149e+00 3.4111720e+00 3.6933050e+00 3.9623038e+00 3.6711803e+00 5.5579136e+00 5.4498365e+00 3.4842014e+00 4.4103781e+00 3.1690867e+00 5.1441957e+00 3.3997317e+00 4.1528029e+00 4.3901202e+00 3.2630747e+00 3.2035560e+00 3.8955732e+00 4.1857725e+00 4.6435471e+00 5.5146776e+00 3.9762768e+00 3.2193184e+00 3.3255820e+00 5.1213824e+00 4.1678001e+00 3.6124079e+00 3.1107135e+00 4.1457358e+00 4.3076787e+00 4.2130787e+00 3.2756710e+00 4.4066811e+00 4.4713485e+00 4.0952473e+00 3.6289876e+00 3.7168749e+00 3.9644506e+00 3.1662754e+00 1.5140329e+00 3.3872939e-01 1.1649855e+00 3.5691650e+00 3.1595321e+00 3.7055656e+00 4.0160835e+00 3.7376603e+00 3.2592987e+00 3.1435650e+00 3.5370651e+00 3.5437638e+00 3.2591886e+00 4.4166410e+00 3.0676819e+00 4.2127293e+00 3.3654329e+00 2.8346837e+00 3.3660906e+00 3.0613575e+00 3.2026716e+00 4.5808841e+00 3.5275705e+00 3.2454510e+00 3.2718756e+00 4.1819826e+00 3.4031279e+00 3.3454884e+00 3.4170637e+00 3.9109404e+00 3.8358967e+00 3.3305911e+00 3.2315455e+00 3.6883726e+00 3.6296117e+00 3.2506700e+00 3.8623185e+00 3.0230066e+00 2.8458833e+00 3.5111771e+00 4.3201594e+00 2.8024863e+00 3.6263297e+00 3.4825375e+00 3.1978058e+00 3.4556048e+00 3.7429398e+00 3.3240937e+00 2.7959976e+00 3.0137031e+00 3.2391776e+00 3.3180586e+00 3.1510639e+00 4.3279818e+00 4.0059487e+00 4.6233424e+00 3.9929211e+00 4.3355275e+00 5.1718231e+00 3.9512216e+00 4.7810147e+00 4.7732950e+00 4.7150495e+00 3.7777251e+00 4.2731987e+00 4.3246862e+00 4.3347988e+00 4.2753666e+00 4.0433740e+00 3.9425600e+00 5.0081332e+00 5.8406251e+00 4.6274156e+00 4.4284929e+00 3.8398842e+00 5.3940263e+00 4.0533472e+00 4.0818092e+00 4.3543675e+00 3.8429689e+00 3.5715666e+00 4.3728103e+00 4.3436347e+00 4.9498040e+00 4.9393850e+00 4.4487185e+00 3.7756717e+00 4.0901950e+00 5.2287042e+00 4.0497882e+00 3.7884247e+00 3.5028854e+00 4.2624115e+00 4.4485334e+00 4.3403092e+00 4.0059487e+00 4.4317896e+00 4.4210531e+00 4.3442496e+00 4.4457375e+00 3.9985746e+00 3.8504489e+00 3.5592028e+00 1.4309353e+00 5.3528567e-01 3.7908776e+00 3.2731841e+00 3.8215973e+00 3.1206853e+00 3.5080970e+00 2.7892862e+00 3.3363505e+00 2.4070515e+00 3.4174587e+00 2.5169099e+00 3.2261716e+00 2.8456035e+00 3.3834513e+00 3.1193847e+00 2.3599428e+00 3.4420978e+00 2.7676217e+00 2.6211360e+00 3.8782821e+00 2.7318604e+00 3.2516765e+00 2.8950591e+00 3.6956240e+00 3.0573546e+00 3.1595622e+00 3.3778208e+00 3.7543715e+00 3.8301935e+00 3.0538048e+00 2.4889600e+00 2.7975756e+00 2.7172725e+00 2.6747723e+00 3.4570094e+00 2.6710885e+00 3.0859941e+00 3.5894820e+00 3.6730945e+00 2.4678645e+00 2.8348872e+00 2.7756196e+00 3.0423378e+00 2.8112845e+00 2.6077230e+00 2.7173555e+00 2.4925318e+00 2.6151930e+00 2.9985224e+00 2.2768387e+00 2.6523384e+00 4.4886181e+00 3.5762214e+00 4.6936725e+00 3.8412437e+00 4.3086181e+00 5.3124523e+00 3.1125049e+00 4.8185220e+00 4.4330566e+00 5.1853832e+00 3.9019516e+00 3.9878172e+00 4.3438773e+00 3.7545919e+00 3.9571174e+00 4.1452084e+00 3.9080206e+00 5.6409887e+00 5.7635531e+00 3.9041153e+00 4.6071696e+00 3.4361835e+00 5.4269728e+00 3.7248960e+00 4.3153491e+00 4.5881410e+00 3.5627565e+00 3.4386758e+00 4.1762134e+00 4.4334431e+00 4.9338087e+00 5.6026788e+00 4.2556298e+00 3.5163766e+00 3.6516985e+00 5.3754384e+00 4.2899814e+00 3.8175194e+00 3.3436392e+00 4.3710164e+00 4.5233951e+00 4.4426760e+00 3.5762214e+00 4.5972906e+00 4.6375405e+00 4.3421746e+00 3.9932553e+00 3.9596590e+00 4.0813696e+00 3.3867904e+00 9.9272943e-01 3.3624661e+00 2.9811147e+00 3.5018936e+00 3.8169093e+00 3.5209477e+00 3.0838698e+00 2.9939885e+00 3.3707744e+00 3.3216375e+00 3.1074562e+00 4.2293025e+00 2.8939100e+00 3.9735251e+00 3.1779321e+00 2.6513305e+00 3.1539115e+00 2.9206559e+00 2.9923096e+00 4.3522137e+00 3.3213891e+00 3.1222272e+00 3.0540027e+00 3.9664528e+00 3.2012517e+00 3.1248526e+00 3.2007609e+00 3.6824267e+00 3.6418210e+00 3.1482435e+00 3.0088381e+00 3.4838907e+00 3.4206811e+00 3.0415159e+00 3.6826470e+00 2.9006138e+00 2.7293873e+00 3.3112277e+00 4.0819926e+00 2.6432089e+00 3.4355346e+00 3.3034492e+00 3.0164601e+00 3.2442582e+00 3.5631690e+00 3.1415769e+00 2.6264645e+00 2.8384396e+00 3.0300747e+00 3.1354811e+00 2.9649167e+00 4.2304738e+00 3.8482047e+00 4.4439318e+00 3.8285351e+00 4.1849277e+00 4.9874125e+00 3.8271288e+00 4.5862820e+00 4.5664639e+00 4.6040986e+00 3.6270951e+00 4.0846199e+00 4.1503558e+00 4.1702140e+00 4.1407964e+00 3.9121183e+00 3.7737683e+00 4.8997002e+00 5.6369181e+00 4.4180349e+00 4.2780098e+00 3.7035075e+00 5.1920494e+00 3.8582580e+00 3.9463952e+00 4.1826549e+00 3.6583100e+00 3.4129797e+00 4.2036908e+00 4.1443501e+00 4.7432980e+00 4.8153136e+00 4.2825977e+00 3.5821023e+00 3.9040345e+00 5.0374022e+00 3.9556226e+00 3.6351652e+00 3.3487998e+00 4.0905154e+00 4.2992014e+00 4.1693135e+00 3.8482047e+00 4.2897273e+00 4.2963449e+00 4.1754173e+00 4.2443816e+00 3.8297356e+00 3.7573406e+00 3.4190329e+00 3.4434283e+00 2.9833205e+00 3.5091456e+00 3.1516030e+00 3.2866494e+00 2.6849207e+00 3.0541761e+00 2.5654361e+00 3.1545670e+00 2.5403244e+00 3.3918434e+00 2.6608343e+00 3.3413616e+00 2.9302185e+00 2.2379234e+00 3.1290373e+00 2.6442995e+00 2.5077372e+00 3.8111267e+00 2.7069456e+00 3.0566678e+00 2.7098649e+00 3.5644689e+00 2.8826061e+00 2.9134932e+00 3.0944404e+00 3.4986589e+00 3.5664548e+00 2.8806273e+00 2.4158569e+00 2.8131786e+00 2.7333339e+00 2.5637470e+00 3.3370594e+00 2.5885603e+00 2.8220110e+00 3.2904739e+00 3.5710204e+00 2.3287218e+00 2.8315630e+00 2.7529707e+00 2.8293212e+00 2.7254528e+00 2.7527251e+00 2.6524994e+00 2.3299431e+00 2.4822440e+00 2.7803033e+00 2.3731496e+00 2.5423572e+00 4.2830420e+00 3.4939592e+00 4.4286678e+00 3.6575173e+00 4.1044791e+00 5.0220848e+00 3.2200733e+00 4.5468375e+00 4.2700249e+00 4.8698851e+00 3.6462342e+00 3.8237490e+00 4.0990020e+00 3.7208580e+00 3.8692104e+00 3.9203597e+00 3.6817365e+00 5.2775206e+00 5.5250867e+00 3.8676958e+00 4.3392543e+00 3.3693781e+00 5.1524083e+00 3.5650934e+00 4.0437994e+00 4.2783342e+00 3.3968462e+00 3.2517273e+00 4.0065881e+00 4.1377875e+00 4.6677357e+00 5.2142247e+00 4.0893000e+00 3.3307003e+00 3.5369003e+00 5.0771896e+00 4.0613196e+00 3.5869628e+00 3.1695162e+00 4.1006440e+00 4.2899814e+00 4.1769447e+00 3.4939592e+00 4.3422191e+00 4.3859843e+00 4.1114107e+00 3.8721945e+00 3.7365034e+00 3.8554667e+00 3.2330990e+00 7.4500632e-01 3.1271814e-01 2.7864553e+00 1.1117653e+00 1.8291315e+00 9.1459005e-01 3.2771828e+00 8.5582452e-01 2.5020950e+00 3.7722922e+00 1.4404415e+00 2.6850561e+00 1.2884095e+00 1.9346765e+00 4.6190224e-01 1.7610224e+00 1.9545276e+00 2.5064746e+00 2.4134734e+00 1.4291842e+00 1.4855627e+00 1.8305602e+00 1.4494865e+00 1.0355160e+00 6.8921053e-01 9.5529726e-01 7.2626021e-01 1.4025367e+00 2.2620298e+00 2.6646285e+00 2.6984190e+00 1.9245986e+00 1.7053476e+00 1.9940477e+00 1.3238834e+00 4.4901474e-01 2.2514668e+00 1.7899689e+00 2.4621620e+00 2.3008240e+00 1.1820572e+00 2.0593667e+00 3.3235867e+00 2.0701817e+00 1.6811909e+00 1.7438018e+00 1.2168151e+00 2.9923086e+00 1.8570167e+00 1.8407084e+00 1.9774894e+00 1.2374249e+00 1.3146181e+00 1.4369760e+00 1.6548985e+00 3.0339990e+00 1.3065206e+00 1.8441719e+00 1.9017153e+00 1.0169098e+00 1.5490835e+00 1.1480416e+00 2.3912363e+00 2.1724397e+00 1.4252775e+00 1.0284221e+00 2.2390158e+00 2.3611228e+00 2.6121814e+00 1.3139868e+00 2.0833701e+00 1.8624251e+00 1.5270661e+00 1.1605968e+00 9.3589904e-01 1.4360842e+00 1.2967707e+00 1.5740302e+00 8.5349066e-01 1.4639724e+00 2.1546616e+00 1.6538197e+00 1.2783641e+00 1.8320269e+00 1.7168897e+00 1.7042715e+00 1.0288355e+00 1.3960908e+00 1.0327124e+00 1.4702446e+00 1.2287925e+00 1.9774894e+00 1.3826233e+00 1.6072393e+00 1.3472497e+00 1.9439880e+00 1.1295026e+00 1.6414265e+00 1.5177322e+00 6.8496652e-01 2.3745921e+00 9.3211669e-01 1.2784093e+00 3.1271814e-01 2.7526949e+00 7.8034610e-01 1.8874930e+00 3.3568278e+00 7.7863029e-01 2.4620981e+00 7.9999102e-01 1.3194463e+00 4.5257749e-01 1.0705713e+00 1.5282070e+00 2.3189157e+00 1.9824340e+00 7.4029244e-01 1.0636179e+00 1.6347187e+00 1.0722301e+00 7.4849274e-01 5.3988754e-01 1.0632334e+00 7.0213871e-01 8.4383266e-01 1.8384560e+00 2.2399960e+00 2.2847962e+00 1.4577178e+00 1.3022697e+00 1.2927254e+00 6.8064066e-01 4.4417668e-01 2.0964002e+00 1.1252542e+00 1.9840858e+00 1.8038514e+00 6.0365341e-01 1.6354514e+00 2.8387736e+00 1.5364600e+00 1.0539473e+00 1.1361809e+00 7.8649633e-01 2.4634199e+00 1.2983546e+00 1.5835083e+00 1.4983760e+00 1.4748100e+00 1.0180846e+00 1.2694582e+00 2.0850659e+00 2.4405647e+00 1.6897529e+00 1.8533655e+00 2.0793529e+00 7.4797652e-01 1.3453828e+00 1.1770444e+00 1.9571621e+00 1.6977813e+00 1.1421260e+00 8.3850424e-01 2.6029823e+00 2.7071356e+00 2.3733266e+00 1.3878105e+00 1.5050081e+00 2.3020930e+00 1.2450968e+00 1.1247714e+00 1.3455945e+00 1.0453799e+00 7.4157869e-01 1.3630233e+00 1.3061954e+00 1.8456576e+00 2.6048102e+00 1.4425815e+00 9.9058911e-01 1.5658693e+00 2.1444356e+00 1.4166079e+00 7.2727886e-01 7.9343577e-01 1.1384575e+00 1.4013840e+00 1.2776135e+00 1.4983760e+00 1.4006413e+00 1.5375255e+00 1.2650236e+00 1.7250893e+00 9.0221296e-01 1.2767751e+00 9.2060977e-01 2.5673851e+00 8.6079202e-01 1.6428179e+00 8.7623959e-01 3.1131006e+00 6.6453319e-01 2.3246810e+00 3.5720588e+00 1.2918836e+00 2.4857868e+00 1.0845006e+00 1.8135469e+00 3.9472619e-01 1.6028858e+00 1.8029164e+00 2.2526468e+00 2.2305704e+00 1.2920175e+00 1.3194463e+00 1.5620078e+00 1.2567627e+00 8.7273869e-01 5.3095950e-01 7.1671402e-01 4.2827238e-01 1.2022652e+00 2.1186438e+00 2.4755072e+00 2.5212188e+00 1.7582453e+00 1.4360884e+00 1.8400908e+00 1.3147484e+00 2.6680274e-01 2.0194508e+00 1.6709595e+00 2.2587909e+00 2.1030957e+00 1.0161846e+00 1.8732616e+00 3.1496799e+00 1.8819614e+00 1.5700887e+00 1.5933926e+00 1.0543640e+00 2.8415314e+00 1.6890927e+00 1.6862498e+00 1.7038925e+00 1.0251132e+00 1.0245496e+00 1.1781513e+00 1.5212572e+00 2.8050734e+00 1.1091494e+00 1.5452835e+00 1.9080234e+00 8.5359653e-01 1.2416734e+00 8.9528108e-01 2.1088803e+00 1.9097018e+00 1.2522193e+00 7.4612152e-01 2.3284654e+00 2.1556564e+00 2.3436971e+00 1.1651790e+00 1.8364691e+00 1.6976628e+00 1.2371704e+00 1.0463225e+00 8.5302032e-01 1.1623508e+00 1.0682140e+00 1.2723284e+00 6.7955751e-01 1.2572095e+00 2.2840066e+00 1.3572135e+00 1.0082548e+00 1.5613089e+00 1.5962380e+00 1.5974627e+00 7.9671887e-01 1.1799226e+00 8.3571552e-01 1.2674750e+00 1.0543826e+00 1.7038925e+00 1.2197800e+00 1.4811026e+00 1.1132425e+00 1.6485749e+00 8.6295295e-01 1.5402909e+00 1.2957413e+00 1.7240804e+00 1.2117746e+00 2.5620931e+00 9.4346743e-01 1.9481085e+00 1.0013399e+00 1.0383354e+00 1.7091506e+00 7.5651431e-01 1.6169211e+00 1.4074199e+00 2.3606801e+00 1.6642999e+00 1.0677270e+00 9.5748562e-01 5.4702555e-01 2.2752108e+00 1.3619011e+00 1.2144903e+00 1.4245490e+00 1.7677805e+00 2.1070188e+00 2.0042865e+00 2.3026776e+00 1.5583422e+00 8.7856768e-01 3.6704030e-01 4.8644514e-01 1.0013399e+00 1.3262124e+00 1.6642999e+00 2.6524441e+00 2.3938089e+00 9.9234874e-01 1.6199145e+00 4.6126066e-01 7.3978204e-01 1.8066960e+00 7.9191984e-01 8.2250769e-01 9.3727156e-01 1.6415483e+00 1.4092680e+00 1.6304499e+00 9.1432842e-01 1.1795364e+00 3.1638147e+00 1.4103498e+00 2.9322745e+00 2.0247895e+00 2.5487652e+00 3.5082844e+00 1.0453705e+00 2.9611604e+00 1.9449446e+00 4.1343567e+00 2.6451449e+00 1.7869811e+00 2.6253748e+00 1.1973458e+00 1.9817270e+00 2.7838011e+00 2.2840066e+00 4.7706180e+00 3.4576971e+00 8.9870984e-01 3.1324336e+00 1.5639220e+00 3.4016597e+00 1.5728443e+00 3.0734808e+00 3.1995683e+00 1.6368228e+00 1.9546803e+00 2.1052860e+00 2.8313078e+00 2.9375460e+00 4.8020420e+00 2.1735035e+00 1.6493848e+00 1.3576485e+00 3.5774884e+00 3.2045691e+00 2.3952974e+00 1.8988804e+00 2.8268459e+00 2.8989852e+00 2.8927951e+00 1.4103498e+00 3.1063891e+00 3.2893581e+00 2.6241058e+00 1.4441104e+00 2.3170196e+00 3.0817543e+00 1.9124815e+00 1.0026233e+00 1.1867923e+00 2.3572427e+00 3.6939647e-01 1.6408576e+00 2.7392425e+00 8.8835337e-01 1.6805749e+00 5.5399712e-01 1.2745081e+00 7.5303835e-01 1.1820572e+00 1.1301977e+00 1.4315442e+00 1.4464138e+00 1.2423523e+00 6.4626422e-01 7.5230154e-01 6.2536527e-01 4.0664863e-01 5.0731024e-01 4.0158746e-01 6.2543628e-01 6.4884272e-01 1.4014424e+00 1.6702453e+00 1.7317202e+00 1.0390957e+00 7.1781501e-01 1.4073416e+00 1.5165187e+00 7.3502408e-01 1.2122797e+00 1.2421878e+00 1.4565053e+00 1.3559191e+00 6.8064066e-01 1.0943185e+00 2.3628816e+00 1.1638514e+00 1.1627754e+00 1.0519629e+00 5.3106808e-01 2.1057450e+00 1.0403581e+00 1.9325284e+00 1.0596309e+00 1.3779504e+00 7.6633520e-01 1.2315180e+00 1.9698667e+00 2.0697950e+00 1.4385383e+00 1.0743031e+00 2.5609592e+00 1.1664463e+00 7.0702759e-01 1.1055841e+00 1.3757605e+00 1.4784016e+00 1.4566739e+00 7.9213303e-01 3.1107848e+00 2.2607358e+00 1.5267093e+00 1.6037239e+00 1.2804073e+00 1.9864213e+00 5.4310586e-01 1.5475402e+00 1.5328931e+00 5.4647209e-01 7.9343577e-01 9.7668596e-01 1.1862065e+00 1.4760549e+00 3.1060327e+00 1.0849536e+00 3.7234239e-01 8.8571256e-01 2.0333305e+00 1.9196784e+00 9.5289573e-01 8.6297946e-01 1.2392529e+00 1.4996752e+00 1.3752205e+00 1.0596309e+00 1.6198849e+00 1.8691588e+00 1.2188552e+00 9.2906468e-01 8.7042892e-01 1.8304530e+00 9.8621003e-01 1.4220241e+00 1.5496729e+00 1.1125144e+00 7.4201890e-01 2.1434858e+00 6.0719477e-01 1.5102780e+00 5.6262711e-01 5.7267643e-01 1.3990971e+00 5.4408162e-01 5.2316125e-01 1.5323598e+00 8.2317311e-01 1.1694177e+00 5.6003943e-01 1.0600958e+00 5.1318506e-01 8.8354057e-01 1.1892978e+00 1.3456285e+00 1.4234329e+00 5.0311426e-01 8.2976237e-01 1.0655776e+00 1.1267154e+00 4.4786319e-01 6.7424840e-01 6.4241342e-01 1.4834540e+00 1.4207811e+00 1.3630799e+00 5.2795793e-01 7.8571751e-01 5.3988754e-01 6.8299624e-01 5.6992880e-01 1.6313928e+00 3.1093967e-01 5.0876385e-01 2.8653046e-01 6.5622658e-01 1.3398293e+00 2.2670334e-01 2.2472150e+00 8.9528108e-01 2.1908074e+00 1.1815770e+00 1.7549185e+00 2.8271782e+00 1.2987661e+00 2.2927322e+00 1.7056353e+00 3.1591627e+00 1.6557083e+00 1.2615426e+00 1.8432274e+00 1.1833606e+00 1.4858600e+00 1.8676774e+00 1.3771658e+00 3.7547288e+00 3.1005581e+00 1.4815836e+00 2.2650937e+00 9.5252488e-01 2.8687133e+00 1.0290036e+00 2.0855599e+00 2.2987772e+00 9.0705646e-01 9.6267538e-01 1.4839640e+00 2.0473137e+00 2.3780534e+00 3.7918985e+00 1.5792523e+00 8.4221906e-01 9.2300698e-01 2.9301148e+00 2.2149712e+00 1.3941954e+00 8.9564079e-01 1.9843979e+00 2.0984088e+00 2.1003345e+00 8.9528108e-01 2.2276119e+00 2.3923111e+00 1.8829565e+00 1.3046645e+00 1.4645285e+00 2.0631582e+00 9.0331700e-01 2.9007820e+00 1.0677270e+00 1.9884030e+00 3.5404087e+00 8.9973730e-01 2.7097598e+00 9.8896933e-01 1.4521880e+00 7.3735391e-01 1.1060455e+00 1.7358574e+00 2.5457091e+00 2.1802781e+00 5.9868400e-01 1.3038475e+00 1.8531597e+00 1.2895008e+00 1.0351584e+00 8.4116354e-01 1.3290015e+00 8.7070822e-01 1.0061402e+00 2.0523180e+00 2.4354079e+00 2.4861842e+00 1.6612475e+00 1.4482752e+00 1.3000067e+00 4.4417668e-01 6.8064066e-01 2.3457352e+00 1.2097457e+00 2.1562626e+00 1.9604379e+00 7.8034610e-01 1.8447318e+00 3.0052273e+00 1.6924215e+00 1.1656549e+00 1.2692102e+00 1.0351584e+00 2.6195047e+00 1.4577178e+00 1.3905452e+00 1.5765058e+00 1.5178511e+00 1.0862363e+00 1.2425116e+00 2.1288976e+00 2.5085097e+00 1.7889699e+00 2.0235792e+00 1.9184220e+00 6.6154242e-01 1.4831058e+00 1.2157849e+00 2.0573833e+00 1.6866006e+00 1.0122929e+00 9.0072498e-01 2.4680266e+00 2.8037035e+00 2.5716465e+00 1.3193736e+00 1.5270661e+00 2.3974481e+00 1.4129334e+00 9.9186850e-01 1.3586792e+00 1.1900564e+00 7.8649633e-01 1.4261046e+00 1.4313173e+00 1.9693923e+00 2.5032449e+00 1.4908532e+00 1.1825071e+00 1.7301809e+00 2.1927243e+00 1.1883807e+00 7.0823896e-01 8.2574748e-01 1.1508346e+00 1.3435624e+00 1.2769092e+00 1.5765058e+00 1.3121204e+00 1.3947465e+00 1.2781560e+00 1.8941016e+00 9.4449485e-01 1.0327124e+00 9.1221028e-01 2.4983699e+00 1.0001615e+00 9.3727156e-01 2.0156046e+00 1.4610933e+00 2.0818555e+00 1.4925824e+00 2.8275182e+00 1.8765007e+00 1.3658611e+00 1.8892371e+00 9.4900087e-01 2.5853758e+00 1.8063869e+00 2.0403844e+00 1.9103325e+00 2.2554051e+00 2.6063293e+00 2.6670659e+00 2.8999367e+00 1.9965452e+00 1.0765554e+00 7.8898008e-01 7.5921691e-01 1.3580560e+00 1.9753995e+00 1.7807988e+00 2.8573306e+00 2.8966014e+00 1.8587118e+00 1.7290357e+00 9.4346743e-01 1.0932187e+00 2.1982921e+00 1.2728402e+00 2.6033464e-01 1.2680818e+00 1.7824360e+00 1.6364088e+00 2.0664368e+00 3.9699460e-01 1.4644159e+00 3.6567369e+00 2.0227452e+00 3.6362580e+00 2.6431572e+00 3.1825084e+00 4.2569960e+00 1.1649315e+00 3.7040279e+00 2.8079889e+00 4.6643094e+00 3.1456885e+00 2.5368652e+00 3.2881355e+00 1.9057424e+00 2.5373943e+00 3.2972877e+00 2.8812938e+00 5.2957248e+00 4.3256332e+00 1.8261865e+00 3.7402681e+00 2.0260681e+00 4.2089146e+00 2.2931022e+00 3.6001832e+00 3.8156954e+00 2.2665638e+00 2.4364115e+00 2.8123267e+00 3.5007685e+00 3.7249152e+00 5.3249013e+00 2.8816817e+00 2.2758405e+00 2.0704519e+00 4.3322711e+00 3.6389537e+00 2.9225385e+00 2.3454418e+00 3.4545556e+00 3.5207953e+00 3.5188476e+00 2.0227452e+00 3.7070275e+00 3.8401809e+00 3.2712836e+00 2.2870689e+00 2.9197390e+00 3.4787880e+00 2.3479440e+00 1.8015956e+00 2.9300280e+00 9.4226820e-01 1.8443182e+00 6.2046469e-01 1.3340137e+00 5.0731024e-01 1.2583559e+00 1.1751408e+00 1.7063292e+00 1.5923247e+00 1.2788332e+00 7.3035754e-01 1.0391769e+00 6.6194168e-01 2.9537172e-01 2.8845946e-01 3.7622328e-01 6.2760421e-01 7.7259801e-01 1.4843174e+00 1.8353890e+00 1.8732616e+00 1.1492120e+00 9.8621003e-01 1.4916922e+00 1.4186317e+00 5.4702555e-01 1.4349060e+00 1.2616939e+00 1.6526705e+00 1.5077694e+00 6.5951091e-01 1.2429329e+00 2.5190636e+00 1.3124532e+00 1.1415080e+00 1.1102613e+00 5.1210327e-01 2.2412909e+00 1.1466385e+00 2.0209769e+00 1.3581397e+00 1.4351001e+00 9.3899770e-01 1.3860326e+00 1.9736520e+00 2.3116417e+00 1.4395013e+00 1.3256797e+00 2.5152621e+00 1.1895067e+00 1.0230389e+00 1.2126763e+00 1.7102781e+00 1.7732497e+00 1.5528794e+00 8.7017583e-01 2.9799960e+00 2.3789847e+00 1.8031686e+00 1.6479163e+00 1.5433090e+00 2.0188390e+00 8.9564079e-01 1.5340057e+00 1.4361609e+00 8.5359653e-01 9.3591761e-01 1.2375842e+00 1.0932909e+00 1.5255827e+00 2.9419617e+00 1.3503714e+00 5.7743200e-01 1.0870568e+00 2.0633836e+00 1.9646340e+00 9.8006549e-01 1.0101003e+00 1.2839264e+00 1.6205305e+00 1.4633215e+00 1.3581397e+00 1.6723912e+00 1.9304834e+00 1.3785508e+00 1.2852279e+00 1.0122929e+00 1.8669942e+00 1.1301977e+00 1.7293858e+00 1.1132823e+00 1.5940674e+00 1.2647627e+00 7.0155617e-01 2.0524860e+00 9.1916314e-01 9.0143387e-01 1.7090768e+00 7.7500385e-01 1.6060095e+00 1.1202045e+00 1.5217697e+00 1.2283051e+00 1.5431751e+00 1.8486311e+00 2.0116712e+00 2.0744305e+00 1.1308980e+00 8.6249502e-01 8.7618973e-01 9.4738284e-01 7.7051641e-01 1.2102028e+00 8.1844705e-01 1.9297683e+00 2.0868978e+00 1.6471661e+00 8.6143605e-01 6.0365341e-01 5.7743200e-01 1.3481077e+00 8.0628657e-01 1.1400599e+00 5.2860161e-01 9.6999820e-01 7.8957903e-01 1.3189781e+00 8.0128554e-01 6.6918102e-01 2.6783589e+00 1.1902996e+00 2.8052881e+00 1.7833755e+00 2.2807524e+00 3.4730319e+00 7.8369762e-01 2.9612706e+00 2.2200035e+00 3.7113566e+00 2.2079590e+00 1.7773274e+00 2.4240040e+00 1.2586273e+00 1.6606465e+00 2.3345591e+00 2.0100747e+00 4.3781379e+00 3.6673897e+00 1.6336953e+00 2.8241758e+00 1.1071867e+00 3.5077760e+00 1.5364148e+00 2.6605007e+00 2.9756588e+00 1.4305490e+00 1.5019762e+00 1.9806289e+00 2.7459951e+00 3.0159022e+00 4.4377151e+00 2.0446123e+00 1.5157660e+00 1.4706419e+00 3.5410473e+00 2.6488235e+00 2.0119986e+00 1.3953413e+00 2.5748429e+00 2.6034011e+00 2.6304123e+00 1.1902996e+00 2.7818749e+00 2.8834870e+00 2.3861430e+00 1.6719199e+00 2.0259174e+00 2.4855987e+00 1.3894554e+00 2.6621352e+00 1.3234208e+00 2.6096596e+00 2.2340939e+00 3.3444949e+00 2.5679785e+00 1.9118907e+00 1.7502251e+00 1.3868450e+00 3.2376571e+00 2.3245757e+00 2.2030084e+00 2.3874774e+00 2.7435279e+00 3.0963501e+00 2.9911365e+00 3.3313369e+00 2.5528922e+00 1.6215602e+00 1.1232628e+00 1.1083720e+00 1.9130507e+00 2.3463017e+00 2.5105454e+00 3.5809242e+00 3.3974315e+00 1.8325077e+00 2.4726944e+00 1.3889514e+00 1.6150266e+00 2.7833542e+00 1.7312416e+00 7.0111465e-01 1.8556044e+00 2.5019422e+00 2.3097506e+00 2.6016512e+00 1.2007565e+00 2.0949830e+00 4.1622891e+00 2.3984916e+00 3.9595754e+00 3.0477055e+00 3.5738045e+00 4.5102220e+00 1.5833139e+00 3.9547990e+00 2.8883510e+00 5.1681640e+00 3.6715203e+00 2.8100260e+00 3.6615020e+00 2.1175666e+00 2.9197870e+00 3.8026677e+00 3.3142297e+00 5.7988752e+00 4.3773719e+00 1.6802144e+00 4.1689985e+00 2.5051488e+00 4.3637125e+00 2.6075737e+00 4.1031841e+00 4.2218983e+00 2.6731954e+00 2.9685228e+00 3.1235748e+00 3.8333962e+00 3.9200272e+00 5.8238336e+00 3.1861618e+00 2.6684075e+00 2.3174914e+00 4.5851647e+00 4.2037872e+00 3.4173362e+00 2.9015754e+00 3.8649606e+00 3.9284352e+00 3.9274419e+00 2.3984916e+00 4.1396215e+00 4.3152972e+00 3.6556493e+00 2.4306199e+00 3.3534589e+00 4.0726739e+00 2.9019830e+00 1.9649078e+00 4.5716421e-01 6.0725725e-01 1.0082512e+00 4.0020411e-01 9.6216255e-01 1.8879475e+00 1.3283978e+00 6.9493020e-01 5.9382214e-01 1.3116762e+00 7.1128716e-01 6.9976890e-01 8.6291569e-01 1.2356595e+00 1.0989171e+00 3.1093967e-01 1.2231205e+00 1.5729927e+00 1.6302590e+00 8.2263932e-01 8.7786730e-01 6.2729876e-01 9.5483435e-01 1.0328871e+00 1.7091506e+00 4.5071694e-01 1.2824303e+00 1.1188225e+00 3.5622944e-01 1.0163696e+00 2.1159028e+00 8.2380019e-01 4.6137216e-01 4.2450569e-01 5.0629646e-01 1.7321630e+00 5.8565201e-01 1.8627348e+00 1.0140018e+00 1.9095789e+00 1.0347180e+00 1.4794093e+00 2.5851550e+00 1.6987423e+00 2.1172382e+00 1.7999889e+00 2.6937126e+00 1.1946586e+00 1.2274756e+00 1.5304430e+00 1.4222936e+00 1.3705079e+00 1.4369760e+00 1.1056213e+00 3.3133435e+00 3.0027854e+00 1.9037709e+00 1.8688892e+00 9.6470639e-01 2.7156484e+00 1.0119180e+00 1.6591942e+00 1.9679139e+00 7.8369762e-01 6.0848963e-01 1.3509456e+00 1.8177289e+00 2.2200035e+00 3.3498688e+00 1.4311753e+00 8.4040822e-01 1.2474502e+00 2.6426508e+00 1.7620244e+00 1.0560148e+00 5.3362004e-01 1.6100417e+00 1.7340403e+00 1.6942922e+00 1.0140018e+00 1.8496575e+00 1.9626001e+00 1.5340961e+00 1.4294738e+00 1.1293709e+00 1.5949054e+00 6.4398240e-01 1.7472907e+00 1.7451622e+00 2.3128200e+00 2.0364367e+00 1.1795364e+00 7.5358247e-01 8.5582452e-01 2.5764453e+00 1.4435947e+00 1.1399118e+00 1.4681660e+00 1.7387082e+00 2.0628406e+00 1.8244206e+00 2.2981140e+00 1.7651851e+00 1.0308265e+00 7.7934221e-01 7.7863029e-01 1.2082987e+00 1.5285763e+00 2.1068341e+00 2.8909913e+00 2.3684734e+00 6.2479428e-01 1.9481438e+00 9.9891776e-01 1.1557309e+00 1.9516972e+00 9.8896933e-01 1.2918836e+00 1.3154759e+00 1.9018319e+00 1.7043940e+00 1.6876317e+00 1.4136421e+00 1.4845363e+00 3.4227731e+00 1.7797546e+00 2.8993041e+00 2.1584174e+00 2.6985144e+00 3.3744038e+00 1.7790388e+00 2.8051892e+00 1.8256311e+00 4.2196161e+00 2.7909300e+00 1.8699505e+00 2.6716730e+00 1.6273208e+00 2.3931485e+00 2.9994905e+00 2.3643994e+00 4.7587356e+00 3.2663266e+00 8.6629251e-01 3.2140857e+00 2.0311002e+00 3.1918979e+00 1.6793067e+00 3.1869276e+00 3.1309476e+00 1.8104252e+00 2.1858235e+00 2.2467893e+00 2.6763967e+00 2.7532877e+00 4.7380019e+00 2.3330174e+00 1.6923429e+00 1.4009491e+00 3.4550204e+00 3.4609647e+00 2.5225714e+00 2.1699387e+00 2.8630132e+00 3.0349029e+00 2.9631214e+00 1.7797546e+00 3.2114945e+00 3.4557456e+00 2.7355167e+00 1.5237929e+00 2.4389172e+00 3.3539591e+00 2.2150193e+00 8.7774396e-01 8.7560645e-01 6.6918102e-01 8.5695467e-01 1.6281675e+00 1.2552875e+00 9.0276183e-01 4.7723749e-01 9.6922609e-01 3.4909881e-01 4.4701039e-01 6.6835176e-01 8.7807032e-01 8.7272262e-01 2.1119253e-01 1.2038778e+00 1.5064820e+00 1.5654738e+00 7.8630314e-01 5.8942278e-01 8.9320425e-01 1.1940983e+00 8.6887698e-01 1.4210091e+00 7.4201890e-01 1.2452417e+00 1.0494370e+00 2.3749211e-01 9.1435339e-01 2.1409786e+00 8.2148003e-01 6.5993495e-01 5.7516438e-01 2.8835410e-01 1.8418099e+00 6.4756318e-01 1.8787743e+00 9.0810653e-01 1.6779282e+00 7.7021931e-01 1.3319441e+00 2.3098596e+00 1.7659238e+00 1.7880416e+00 1.4280932e+00 2.6604707e+00 1.1753998e+00 9.4281519e-01 1.3471074e+00 1.3158313e+00 1.3974368e+00 1.4547739e+00 8.7568652e-01 3.2288696e+00 2.6753697e+00 1.6330922e+00 1.7674989e+00 1.0240850e+00 2.3852911e+00 7.4743804e-01 1.5932991e+00 1.7495490e+00 5.8796666e-01 5.8374436e-01 1.1339991e+00 1.5083690e+00 1.8912106e+00 3.2526896e+00 1.2423778e+00 4.2436984e-01 8.5959137e-01 2.4097678e+00 1.8344669e+00 9.0791603e-01 5.8796666e-01 1.4645285e+00 1.6477112e+00 1.6088132e+00 9.0810653e-01 1.7454599e+00 1.9428935e+00 1.4315280e+00 1.1694177e+00 9.9244707e-01 1.7007353e+00 6.6154242e-01 1.4832888e+00 6.1810529e-01 7.1128716e-01 1.8601631e+00 9.7397874e-01 1.2254650e+00 6.8496652e-01 1.4755282e+00 9.0753778e-01 1.0443931e+00 1.3169341e+00 1.6226440e+00 1.6498870e+00 7.4980278e-01 8.0686941e-01 1.1940983e+00 1.2255953e+00 5.6318359e-01 1.1503759e+00 6.6361830e-01 1.4063472e+00 1.5603679e+00 1.6837563e+00 3.6536845e-01 9.5761359e-01 8.4619410e-01 8.6958016e-01 7.7821113e-01 1.6196626e+00 5.7306091e-01 4.4786319e-01 3.6086172e-01 8.2608188e-01 1.1831978e+00 3.8480889e-01 2.4265852e+00 1.2696247e+00 2.4764170e+00 1.5584328e+00 2.0444851e+00 3.1426915e+00 1.4493286e+00 2.6430316e+00 2.1446703e+00 3.2893516e+00 1.7955663e+00 1.6408995e+00 2.1004081e+00 1.5285733e+00 1.7064050e+00 2.0142932e+00 1.6802708e+00 3.9009617e+00 3.4821230e+00 1.8809382e+00 2.4651410e+00 1.1989033e+00 3.2268928e+00 1.3782117e+00 2.2651964e+00 2.5478630e+00 1.2124370e+00 1.1789342e+00 1.8358339e+00 2.3443222e+00 2.7210373e+00 3.9221023e+00 1.9136809e+00 1.2486828e+00 1.4646971e+00 3.1951870e+00 2.3252489e+00 1.6537705e+00 1.0855082e+00 2.1947734e+00 2.3108044e+00 2.2621105e+00 1.2696247e+00 2.4484679e+00 2.5504328e+00 2.0873736e+00 1.6773040e+00 1.7023842e+00 2.1476736e+00 1.1560388e+00 1.3558057e+00 1.5283845e+00 2.1664244e+00 1.9784646e+00 1.1457159e+00 1.0355160e+00 1.4985549e+00 1.0494370e+00 6.0365341e-01 2.6033464e-01 7.3803207e-01 5.6864482e-01 9.7352372e-01 1.8229204e+00 2.2308199e+00 2.2668270e+00 1.4769275e+00 1.3385535e+00 1.5931825e+00 1.1248155e+00 2.1466080e-01 1.9117251e+00 1.3652496e+00 2.0207624e+00 1.8704283e+00 7.6880092e-01 1.6220723e+00 2.8778954e+00 1.6265611e+00 1.2621791e+00 1.3042843e+00 7.7313507e-01 2.5362196e+00 1.4082507e+00 1.8291996e+00 1.6183246e+00 1.3603639e+00 1.0878281e+00 1.3564590e+00 1.9053825e+00 2.6072470e+00 1.4737985e+00 1.6790332e+00 2.1679999e+00 9.4182667e-01 1.2929545e+00 1.1391970e+00 2.0265696e+00 1.8799960e+00 1.3547660e+00 8.8029208e-01 2.6196958e+00 2.4872661e+00 2.2706454e+00 1.4300844e+00 1.7151590e+00 2.0626281e+00 1.1997534e+00 1.2637010e+00 1.2307777e+00 1.0813975e+00 9.6603754e-01 1.3834169e+00 1.0564307e+00 1.5971466e+00 2.5708690e+00 1.4735640e+00 9.4160439e-01 1.5222760e+00 1.9572025e+00 1.7004687e+00 8.9142733e-01 1.0459007e+00 1.1049324e+00 1.4763267e+00 1.2674750e+00 1.6183246e+00 1.4769125e+00 1.6832034e+00 1.2843405e+00 1.6410601e+00 9.6706760e-01 1.5985259e+00 1.1910776e+00 1.0088064e+00 1.9822205e+00 1.3115314e+00 7.2626021e-01 8.5225534e-01 1.4476734e+00 8.6297946e-01 1.0334797e+00 1.2160426e+00 1.5358725e+00 1.3833366e+00 5.3528567e-01 1.2712561e+00 1.5367336e+00 1.6013312e+00 8.9845135e-01 9.1916314e-01 2.4152660e-01 1.0495503e+00 1.3530247e+00 1.8419620e+00 3.4651700e-01 1.2220171e+00 1.0116179e+00 6.2046469e-01 1.0696792e+00 2.0057768e+00 7.5914566e-01 4.4499696e-01 4.0664863e-01 8.1224041e-01 1.6406723e+00 5.8942278e-01 1.9060542e+00 9.6301827e-01 2.1281559e+00 1.1449868e+00 1.6017068e+00 2.8050285e+00 1.4536311e+00 2.3373419e+00 1.9472489e+00 2.8613983e+00 1.3924555e+00 1.3756347e+00 1.7433862e+00 1.3615778e+00 1.3332278e+00 1.5654312e+00 1.2872568e+00 3.4973752e+00 3.1986815e+00 1.9281666e+00 2.0588451e+00 8.3270853e-01 2.9373687e+00 1.1828955e+00 1.8231885e+00 2.1962402e+00 9.5979989e-01 7.5532639e-01 1.4672797e+00 2.0720690e+00 2.4566102e+00 3.5648048e+00 1.5414664e+00 1.0212756e+00 1.2733735e+00 2.8900916e+00 1.8289569e+00 1.2092544e+00 6.4558417e-01 1.8428644e+00 1.8966444e+00 1.9319316e+00 9.6301827e-01 2.0102936e+00 2.1030669e+00 1.7380754e+00 1.5489952e+00 1.3296349e+00 1.6538197e+00 6.3357758e-01 1.4295948e+00 5.4873947e-01 1.6126413e+00 5.8496636e-01 1.1009910e+00 6.0725725e-01 9.5139638e-01 1.3098483e+00 1.3941599e+00 1.6617787e+00 8.6702860e-01 4.2826573e-01 8.0996690e-01 8.1324137e-01 2.8553149e-01 9.9883272e-01 1.0921061e+00 1.8259719e+00 1.6053711e+00 1.1828265e+00 8.3161134e-01 7.0834786e-01 5.3106808e-01 9.8233874e-01 3.5366952e-01 1.4106682e+00 4.6484021e-01 7.5179033e-01 6.2055338e-01 7.8324937e-01 1.1546456e+00 4.7149050e-01 2.7022699e+00 1.3084256e+00 2.4620452e+00 1.5488588e+00 2.1433843e+00 3.0477876e+00 1.5122060e+00 2.4794486e+00 1.8496575e+00 3.5092631e+00 2.0205369e+00 1.5421829e+00 2.1550478e+00 1.4847626e+00 1.9338323e+00 2.2845215e+00 1.7093196e+00 4.0428524e+00 3.2768847e+00 1.4413624e+00 2.6112105e+00 1.4262166e+00 3.0341947e+00 1.2919157e+00 2.4486747e+00 2.5390232e+00 1.2420951e+00 1.3836252e+00 1.8380693e+00 2.2098781e+00 2.5420974e+00 4.0353061e+00 1.9425259e+00 1.0808550e+00 1.0871507e+00 3.1511951e+00 2.6568698e+00 1.7619640e+00 1.3391481e+00 2.2882514e+00 2.4739376e+00 2.4163220e+00 1.3084256e+00 2.5943375e+00 2.7895659e+00 2.2249457e+00 1.4927500e+00 1.8163092e+00 2.5068377e+00 1.3832520e+00 1.1807138e+00 2.3735475e+00 1.4416726e+00 7.3803207e-01 1.4480380e+00 1.6571634e+00 1.9125650e+00 1.5766889e+00 1.9793333e+00 1.6323793e+00 1.4021778e+00 1.1659675e+00 1.2498767e+00 1.3539814e+00 1.2332482e+00 2.0826771e+00 2.7811716e+00 2.1646850e+00 3.7371902e-01 2.0122804e+00 1.1585774e+00 1.3127802e+00 1.8544941e+00 1.1485726e+00 1.7450075e+00 1.3972701e+00 1.9880179e+00 1.7517164e+00 1.6394680e+00 1.8002228e+00 1.5490387e+00 2.9816674e+00 1.3976606e+00 2.4151949e+00 1.7787946e+00 2.2180206e+00 2.8804995e+00 1.7355261e+00 2.3592859e+00 1.2412454e+00 3.7977608e+00 2.4485045e+00 1.3668906e+00 2.2064746e+00 1.1631247e+00 1.9116990e+00 2.5849220e+00 2.0027932e+00 4.3925033e+00 2.6611027e+00 3.7234239e-01 2.7559143e+00 1.7089501e+00 2.6795765e+00 1.2450968e+00 2.8073641e+00 2.7667084e+00 1.4485479e+00 1.9038618e+00 1.7262603e+00 2.3286441e+00 2.2609611e+00 4.4068441e+00 1.7897439e+00 1.4300608e+00 1.1275945e+00 2.9337206e+00 3.0746426e+00 2.2005676e+00 1.9094387e+00 2.4292641e+00 2.5401664e+00 2.4975057e+00 1.3976606e+00 2.7518188e+00 2.9966927e+00 2.2416615e+00 9.2104245e-01 2.0302905e+00 3.0030765e+00 1.9507955e+00 1.9593598e+00 9.5666050e-01 1.1447875e+00 1.0324994e+00 1.3800294e+00 1.7386688e+00 1.7301705e+00 2.0251376e+00 1.2143895e+00 3.6924035e-01 2.6643250e-01 3.1271814e-01 5.3690447e-01 1.1566759e+00 1.3335853e+00 2.2553589e+00 2.0395552e+00 1.0374728e+00 1.1879760e+00 2.9406726e-01 4.0650681e-01 1.4164313e+00 3.6319073e-01 9.3305124e-01 5.5709100e-01 1.1791615e+00 9.8143688e-01 1.2231662e+00 7.9042934e-01 7.5817225e-01 2.9833953e+00 1.3537061e+00 2.7591591e+00 1.8262769e+00 2.3975382e+00 3.3499130e+00 1.2034779e+00 2.7851895e+00 1.9405021e+00 3.8845156e+00 2.3750632e+00 1.6954582e+00 2.4431790e+00 1.3394090e+00 1.9751740e+00 2.5771567e+00 2.0432035e+00 4.4739802e+00 3.4420978e+00 1.1727925e+00 2.9298786e+00 1.4800982e+00 3.2892623e+00 1.4456510e+00 2.8154123e+00 2.9321762e+00 1.4509441e+00 1.6902348e+00 2.0142932e+00 2.5791547e+00 2.8031074e+00 4.4835636e+00 2.1018908e+00 1.3894554e+00 1.2250001e+00 3.4334168e+00 2.9754074e+00 2.1241116e+00 1.6323629e+00 2.6113665e+00 2.7403495e+00 2.7045382e+00 1.3537061e+00 2.9092469e+00 3.0943267e+00 2.4717839e+00 1.4839640e+00 2.1082363e+00 2.8334846e+00 1.6627952e+00 1.2426609e+00 1.7313027e+00 1.2372185e+00 1.1631247e+00 1.1195889e+00 1.5188976e+00 1.0845006e+00 8.2263932e-01 1.9012930e+00 2.1909047e+00 2.2638611e+00 1.4908532e+00 1.2008045e+00 8.7223523e-01 5.7002996e-01 1.0697164e+00 2.2410714e+00 9.6470639e-01 1.8639992e+00 1.6786018e+00 7.4743804e-01 1.6592561e+00 2.7039438e+00 1.4162972e+00 1.0024224e+00 1.0401603e+00 1.0580730e+00 2.3284654e+00 1.2231205e+00 1.2611129e+00 1.1791615e+00 1.6899776e+00 9.5793067e-01 1.1548640e+00 2.3712314e+00 2.0275068e+00 2.0149111e+00 1.9649183e+00 2.1679212e+00 7.8905316e-01 1.3385913e+00 1.3061285e+00 1.6571634e+00 1.2299006e+00 9.3495766e-01 9.4613565e-01 2.8415314e+00 2.9130399e+00 2.3454203e+00 1.4655406e+00 1.0267382e+00 2.6085350e+00 1.2515236e+00 1.1837505e+00 1.7109084e+00 9.9111027e-01 5.2374483e-01 1.2552875e+00 1.7513749e+00 2.1661990e+00 2.9392776e+00 1.3022811e+00 1.1259771e+00 1.5663601e+00 2.4310503e+00 1.1268523e+00 7.5840628e-01 4.7680727e-01 1.3348163e+00 1.3454539e+00 1.4034689e+00 1.1791615e+00 1.4139320e+00 1.4450127e+00 1.2754470e+00 1.6940148e+00 9.2620264e-01 9.4281519e-01 4.9160020e-01 9.3054395e-01 4.1781009e-01 4.6190224e-01 8.0369154e-01 9.6816967e-01 1.1548640e+00 4.6557224e-01 8.2518769e-01 1.2073068e+00 1.2487994e+00 4.5257749e-01 7.8164792e-01 1.0374728e+00 1.4711456e+00 1.1089653e+00 1.1997868e+00 7.6195008e-01 1.0018628e+00 8.9796526e-01 5.8785093e-01 6.0098693e-01 1.8456219e+00 6.5622658e-01 6.9001472e-01 5.4715569e-01 3.1093967e-01 1.5254459e+00 4.8636669e-01 2.2683520e+00 1.0914354e+00 1.9823217e+00 1.1675117e+00 1.6963493e+00 2.6008457e+00 1.7128336e+00 2.0692339e+00 1.5728043e+00 3.0096252e+00 1.5213092e+00 1.1599200e+00 1.6580031e+00 1.3691582e+00 1.6116709e+00 1.8005954e+00 1.2641532e+00 3.5755981e+00 2.8921647e+00 1.5229350e+00 2.1046875e+00 1.2108278e+00 2.6299105e+00 8.9496218e-01 1.9702691e+00 2.0808148e+00 8.0585922e-01 9.4983854e-01 1.4326334e+00 1.7811974e+00 2.1211631e+00 3.5687116e+00 1.5311195e+00 7.1811205e-01 1.0257884e+00 2.6607812e+00 2.2075002e+00 1.3273841e+00 9.2853136e-01 1.7721541e+00 1.9757526e+00 1.8755628e+00 1.0914354e+00 2.1076593e+00 2.2924992e+00 1.7080157e+00 1.2150638e+00 1.3228669e+00 2.0678512e+00 1.0435585e+00 8.3930091e-01 1.0246689e+00 1.2483935e+00 9.2934901e-01 1.2786676e+00 1.0167074e+00 1.2794668e+00 1.2845002e+00 1.3705288e+00 1.0262066e+00 6.1158310e-01 1.6007620e+00 2.1232609e+00 1.4700482e+00 6.0145223e-01 1.5227019e+00 1.1234881e+00 1.1051628e+00 1.1975697e+00 9.1241332e-01 1.9821649e+00 1.0739839e+00 1.4719712e+00 1.2657553e+00 1.0246689e+00 1.8799916e+00 1.1304806e+00 2.3473055e+00 9.3001231e-01 1.7895396e+00 1.0784109e+00 1.5778477e+00 2.3110268e+00 1.7258314e+00 1.7588444e+00 8.0501785e-01 3.1299934e+00 1.7625999e+00 7.4394765e-01 1.5582385e+00 9.7850690e-01 1.4989725e+00 1.9419525e+00 1.2877346e+00 3.7053544e+00 2.3011615e+00 7.8305765e-01 2.1061327e+00 1.2737998e+00 2.1925140e+00 6.0604502e-01 2.1121593e+00 2.0810604e+00 8.0686941e-01 1.2420238e+00 1.1264142e+00 1.6698499e+00 1.7264467e+00 3.7248620e+00 1.2214818e+00 7.0111465e-01 5.3487449e-01 2.3978329e+00 2.4200364e+00 1.4831058e+00 1.2723027e+00 1.7715216e+00 1.9225896e+00 1.8845666e+00 9.3001231e-01 2.0954738e+00 2.3579846e+00 1.6403910e+00 5.2719130e-01 1.3587682e+00 2.3456726e+00 1.3154759e+00 5.0299964e-01 8.2155022e-01 8.8684653e-01 1.0935878e+00 4.8492463e-01 9.8860056e-01 1.2858521e+00 1.3288928e+00 6.2451737e-01 6.2760421e-01 1.0463002e+00 1.4889605e+00 1.0762241e+00 1.1975697e+00 8.4271175e-01 1.0854927e+00 8.7560645e-01 5.3352899e-01 7.0810362e-01 1.9474744e+00 7.1781501e-01 7.2553812e-01 6.1968090e-01 3.6924035e-01 1.6978139e+00 6.0510141e-01 2.1983316e+00 1.0378652e+00 1.8773521e+00 9.9490014e-01 1.5974238e+00 2.4585483e+00 1.7380659e+00 1.8957007e+00 1.4179266e+00 2.9495957e+00 1.4948761e+00 1.0683666e+00 1.5886178e+00 1.3564059e+00 1.6294524e+00 1.7819921e+00 1.1268523e+00 3.4719349e+00 2.7528980e+00 1.4535731e+00 2.0452826e+00 1.2150379e+00 2.4732935e+00 8.6167901e-01 1.8885847e+00 1.9433611e+00 7.9744128e-01 9.1854596e-01 1.3349909e+00 1.6250498e+00 1.9838258e+00 3.4743868e+00 1.4520430e+00 5.1406096e-01 7.3595190e-01 2.5794085e+00 2.1692945e+00 1.1973560e+00 9.2123504e-01 1.7205327e+00 1.9329718e+00 1.8817619e+00 1.0378652e+00 2.0262673e+00 2.2533761e+00 1.7016580e+00 1.1862896e+00 1.2748646e+00 2.0406838e+00 9.6984925e-01 3.6319073e-01 6.1968090e-01 7.8521221e-01 5.6113157e-01 1.2463647e+00 1.6309592e+00 1.6676963e+00 8.9796526e-01 8.9789119e-01 1.2621791e+00 1.3154759e+00 6.8124108e-01 1.3901973e+00 9.9970024e-01 1.4357022e+00 1.2962951e+00 4.8012872e-01 1.0246015e+00 2.2910733e+00 1.0720705e+00 8.8779355e-01 8.4724089e-01 2.4152660e-01 1.9817257e+00 8.8354057e-01 2.0655284e+00 1.2495886e+00 1.6398109e+00 9.9332012e-01 1.4769125e+00 2.2251642e+00 2.1023706e+00 1.7015856e+00 1.4609179e+00 2.6557282e+00 1.2410479e+00 1.0733560e+00 1.3593949e+00 1.6013655e+00 1.6915504e+00 1.5864800e+00 9.7957718e-01 3.1644964e+00 2.6137665e+00 1.7509262e+00 1.7860234e+00 1.3941000e+00 2.2824049e+00 8.7876634e-01 1.6464371e+00 1.6642217e+00 7.8808432e-01 8.5400786e-01 1.3018901e+00 1.3652161e+00 1.7805677e+00 3.1380968e+00 1.4095411e+00 5.8483448e-01 1.0816610e+00 2.2968622e+00 1.9911692e+00 1.0509799e+00 8.9223438e-01 1.4369760e+00 1.7217513e+00 1.5811148e+00 1.2495886e+00 1.8031513e+00 2.0209769e+00 1.4702446e+00 1.2810704e+00 1.0813343e+00 1.8691588e+00 1.0259679e+00 5.6788283e-01 5.3362004e-01 7.7368489e-01 1.6022591e+00 1.9873741e+00 2.0277089e+00 1.2494231e+00 1.1089653e+00 1.4561750e+00 1.2033093e+00 3.3742167e-01 1.6597443e+00 1.2265630e+00 1.7784712e+00 1.6384023e+00 6.1436388e-01 1.3800294e+00 2.6463489e+00 1.4025367e+00 1.1237500e+00 1.1244975e+00 5.5399712e-01 2.3227610e+00 1.2000527e+00 1.8734557e+00 1.4137602e+00 1.3887598e+00 9.6005858e-01 1.3202421e+00 1.9632584e+00 2.3879303e+00 1.4839475e+00 1.4995474e+00 2.3336107e+00 1.0014276e+00 1.1074656e+00 1.1350466e+00 1.8013325e+00 1.7379612e+00 1.3863777e+00 8.2339084e-01 2.8225734e+00 2.4523537e+00 2.0154418e+00 1.5091823e+00 1.5393373e+00 2.0723760e+00 9.8233874e-01 1.3702101e+00 1.3545502e+00 8.7875749e-01 8.4830222e-01 1.2549787e+00 1.1060185e+00 1.5823028e+00 2.7877979e+00 1.3537061e+00 7.2012544e-01 1.2954496e+00 2.0208193e+00 1.7781563e+00 8.8029208e-01 9.2256644e-01 1.1605968e+00 1.4991046e+00 1.3162835e+00 1.4137602e+00 1.5442127e+00 1.7645705e+00 1.2692218e+00 1.4162972e+00 9.1557526e-01 1.6722331e+00 1.0708496e+00 6.2826980e-01 1.0161846e+00 1.6718164e+00 1.9471640e+00 1.9947662e+00 1.3566251e+00 1.0412209e+00 1.7655766e+00 1.7163342e+00 7.1671402e-01 1.3277490e+00 1.5771462e+00 1.7793591e+00 1.6725709e+00 9.6964683e-01 1.3947746e+00 2.6556269e+00 1.5119726e+00 1.4702773e+00 1.3966512e+00 8.2199752e-01 2.4266623e+00 1.3925524e+00 2.0577807e+00 1.4034689e+00 1.2545960e+00 9.4767129e-01 1.3281960e+00 1.7401681e+00 2.4345214e+00 1.1896374e+00 1.0436620e+00 2.5015865e+00 1.2764504e+00 8.9223438e-01 1.1006735e+00 1.6953806e+00 1.7900496e+00 1.5985782e+00 8.8098199e-01 2.9595238e+00 2.0497239e+00 1.6965355e+00 1.5863720e+00 1.6496643e+00 1.7201711e+00 8.3409556e-01 1.5639220e+00 1.3496867e+00 8.9427872e-01 1.0978602e+00 1.1314785e+00 9.1432842e-01 1.2235673e+00 2.9196060e+00 1.2400775e+00 6.4083823e-01 1.0643984e+00 1.8241883e+00 2.0498818e+00 1.0696576e+00 1.1919906e+00 1.2042673e+00 1.5543054e+00 1.3831011e+00 1.4034689e+00 1.6218749e+00 1.9188761e+00 1.2920921e+00 1.1337565e+00 1.0067405e+00 1.9865217e+00 1.3029486e+00 9.5748562e-01 1.9681165e+00 2.2573397e+00 2.3235953e+00 1.5741400e+00 1.1016806e+00 1.6166760e+00 1.2896217e+00 3.8830315e-01 1.7972266e+00 1.5164233e+00 2.0064286e+00 1.8697578e+00 8.5494999e-01 1.6681709e+00 2.9309853e+00 1.6503473e+00 1.4467905e+00 1.4113341e+00 9.2189946e-01 2.6393526e+00 1.4852749e+00 1.4601858e+00 1.3160132e+00 8.7649478e-01 6.4756318e-01 8.3256255e-01 1.5094087e+00 2.4769347e+00 1.0668784e+00 1.2459961e+00 1.9408738e+00 6.5485710e-01 8.4116354e-01 6.0795234e-01 1.7154199e+00 1.4961901e+00 9.9551062e-01 3.9472619e-01 2.4940166e+00 2.0216642e+00 2.0463301e+00 1.0230389e+00 1.4612117e+00 1.6595118e+00 8.5582452e-01 9.5437259e-01 9.5694342e-01 7.7934221e-01 7.3851064e-01 8.5695467e-01 7.6638235e-01 1.1767396e+00 2.5076596e+00 9.4281519e-01 7.1971771e-01 1.2830542e+00 1.5700842e+00 1.4287578e+00 5.3095950e-01 8.6291569e-01 6.6154242e-01 1.0050638e+00 8.5606908e-01 1.3160132e+00 1.0514970e+00 1.3171874e+00 7.9433323e-01 1.2774110e+00 4.7509249e-01 1.3730080e+00 9.7659801e-01 1.1663747e+00 1.4582411e+00 1.5261646e+00 7.3570584e-01 5.8785093e-01 7.6039875e-01 1.1605726e+00 9.6964683e-01 1.4553344e+00 6.3765570e-01 1.1681709e+00 1.0005243e+00 2.9691107e-01 8.7856768e-01 2.0651943e+00 7.3735391e-01 6.0653347e-01 4.7837533e-01 3.7398306e-01 1.7406274e+00 5.5183182e-01 1.8498714e+00 8.1329726e-01 1.7508641e+00 8.2125107e-01 1.3423724e+00 2.4127395e+00 1.6384023e+00 1.9130927e+00 1.5043381e+00 2.6917823e+00 1.1782159e+00 9.6249568e-01 1.3877621e+00 1.2214135e+00 1.2719770e+00 1.4200371e+00 9.4526659e-01 3.3044115e+00 2.7645066e+00 1.6390945e+00 1.7948322e+00 8.7588404e-01 2.5003659e+00 7.4157869e-01 1.6267504e+00 1.8590427e+00 5.4310586e-01 5.2316125e-01 1.1372412e+00 1.6472029e+00 2.0021586e+00 3.3409572e+00 1.2314733e+00 5.4779717e-01 9.4822835e-01 2.4877874e+00 1.8001237e+00 9.6012811e-01 4.8644514e-01 1.5074309e+00 1.6452353e+00 1.6151033e+00 8.1329726e-01 1.7721541e+00 1.9352496e+00 1.4226963e+00 1.1564263e+00 1.0022114e+00 1.6574535e+00 5.8132667e-01 5.6318359e-01 5.3286499e-01 4.3341454e-01 1.2747045e+00 1.3163443e+00 2.1153648e+00 1.9183153e+00 1.1909838e+00 1.0657373e+00 5.8852220e-01 6.2225308e-01 1.3220343e+00 4.0443437e-01 1.0982562e+00 6.1619693e-01 1.0378442e+00 8.8917809e-01 1.0970024e+00 8.2199752e-01 6.9493020e-01 3.0003610e+00 1.5102474e+00 2.7635526e+00 1.8759428e+00 2.4405125e+00 3.3586044e+00 1.4659783e+00 2.7980993e+00 2.0759743e+00 3.8255754e+00 2.3211022e+00 1.7886572e+00 2.4450156e+00 1.5788967e+00 2.1011800e+00 2.5635734e+00 2.0416027e+00 4.3880097e+00 3.5282390e+00 1.4609179e+00 2.9105517e+00 1.6043433e+00 3.3245307e+00 1.5187698e+00 2.7743367e+00 2.8814354e+00 1.4896588e+00 1.6771528e+00 2.1027324e+00 2.5396337e+00 2.8265966e+00 4.3745133e+00 2.1946278e+00 1.4104380e+00 1.3873057e+00 3.4289479e+00 2.9514502e+00 2.1043046e+00 1.6198849e+00 2.5820471e+00 2.7513626e+00 2.6746677e+00 1.5102474e+00 2.9036877e+00 3.0793854e+00 2.4777911e+00 1.6406409e+00 2.1046875e+00 2.7982275e+00 1.6824284e+00 1.4276574e-01 7.9394533e-01 1.3473710e+00 1.5367336e+00 2.5040512e+00 2.2893871e+00 1.0820670e+00 1.4237364e+00 3.6704030e-01 5.8785093e-01 1.6733127e+00 6.1158310e-01 7.1781501e-01 7.8318003e-01 1.4288989e+00 1.2280749e+00 1.4809953e+00 7.0150436e-01 1.0034788e+00 3.1877520e+00 1.5005648e+00 2.9634183e+00 2.0359721e+00 2.5953129e+00 3.5470571e+00 1.1634940e+00 2.9839272e+00 2.0686806e+00 4.1156592e+00 2.6069476e+00 1.8659064e+00 2.6504363e+00 1.4017266e+00 2.1040122e+00 2.7893850e+00 2.2677890e+00 4.7183507e+00 3.5819899e+00 1.1465705e+00 3.1455771e+00 1.6263647e+00 3.4643576e+00 1.6254447e+00 3.0471395e+00 3.1646326e+00 1.6517237e+00 1.9156890e+00 2.1886203e+00 2.8006555e+00 2.9856138e+00 4.7315684e+00 2.2694993e+00 1.6130651e+00 1.3903392e+00 3.6256164e+00 3.1929372e+00 2.3573820e+00 1.8552594e+00 2.8291427e+00 2.9408913e+00 2.9120555e+00 1.5005648e+00 3.1237582e+00 3.3065647e+00 2.6677639e+00 1.5962380e+00 2.3224070e+00 3.0542458e+00 1.8794605e+00 8.3156200e-01 1.4460310e+00 1.6013312e+00 2.5509456e+00 2.3359909e+00 1.1395071e+00 1.4612871e+00 4.8644514e-01 6.6244727e-01 1.7247525e+00 6.6453319e-01 6.8496652e-01 8.5330525e-01 1.4567673e+00 1.2739414e+00 1.5213580e+00 6.7904052e-01 1.0560797e+00 3.2869799e+00 1.6218234e+00 3.0463976e+00 2.1264009e+00 2.6948572e+00 3.6228821e+00 1.2747978e+00 3.0537173e+00 2.1607143e+00 4.1937512e+00 2.6849827e+00 1.9680122e+00 2.7382122e+00 1.5399252e+00 2.2309601e+00 2.8826191e+00 2.3479440e+00 4.7798805e+00 3.6690959e+00 1.2447718e+00 3.2325186e+00 1.7450415e+00 3.5380106e+00 1.7243835e+00 3.1258440e+00 3.2275370e+00 1.7473394e+00 2.0003230e+00 2.2955340e+00 2.8573132e+00 3.0588804e+00 4.7837445e+00 2.3799967e+00 1.6861899e+00 1.4737985e+00 3.7047689e+00 3.2828775e+00 2.4345890e+00 1.9408738e+00 2.9104325e+00 3.0383020e+00 2.9993404e+00 1.6218234e+00 3.2132904e+00 3.3994957e+00 2.7639400e+00 1.7088499e+00 2.4110070e+00 3.1406474e+00 1.9689207e+00 8.9196595e-01 9.9107019e-01 1.7478610e+00 1.5467508e+00 1.1459117e+00 7.5303835e-01 6.0365341e-01 5.1453676e-01 9.1435339e-01 2.3749211e-01 1.4031123e+00 3.2313211e-01 7.2263841e-01 5.2290002e-01 7.1740234e-01 1.0975976e+00 3.1271814e-01 2.5686027e+00 1.1418735e+00 2.3704417e+00 1.4573208e+00 2.0173981e+00 2.9893605e+00 1.3924555e+00 2.4418079e+00 1.7809408e+00 3.4092863e+00 1.8988911e+00 1.4127713e+00 2.0371950e+00 1.3095379e+00 1.7286430e+00 2.1358640e+00 1.6228818e+00 3.9920035e+00 3.2072460e+00 1.3897098e+00 2.4925270e+00 1.2375842e+00 2.9891693e+00 1.1418958e+00 2.3510928e+00 2.4945648e+00 1.0792736e+00 1.2447083e+00 1.7021399e+00 2.1843621e+00 2.4864921e+00 3.9967418e+00 1.7954132e+00 1.0172824e+00 1.0869385e+00 3.0619758e+00 2.5242226e+00 1.6782397e+00 1.1896845e+00 2.1746675e+00 2.3309032e+00 2.2706367e+00 1.1418735e+00 2.4800313e+00 2.6530340e+00 2.0689155e+00 1.3443777e+00 1.6837594e+00 2.3748600e+00 1.2545769e+00 1.0660846e+00 1.6498377e+00 1.2783641e+00 1.1376397e+00 1.0898613e+00 1.0585628e+00 9.2189946e-01 8.0142393e-01 8.8029208e-01 1.9920533e+00 8.0501785e-01 1.0699859e+00 8.7105035e-01 7.9448303e-01 1.7999592e+00 8.1251986e-01 1.9227723e+00 4.6137216e-01 1.6965186e+00 7.0213871e-01 1.2723284e+00 2.3160615e+00 1.4526546e+00 1.7912701e+00 1.0739839e+00 2.8496420e+00 1.4032361e+00 6.3302304e-01 1.3757605e+00 7.8863556e-01 1.1001816e+00 1.5547583e+00 9.8152003e-01 3.4772360e+00 2.4799120e+00 1.1619556e+00 1.8622587e+00 7.5769247e-01 2.3162319e+00 4.6128322e-01 1.7816685e+00 1.9387331e+00 4.5729032e-01 7.5817225e-01 8.9223438e-01 1.6541379e+00 1.8404767e+00 3.5381276e+00 9.9244707e-01 4.4901474e-01 4.6557224e-01 2.4199101e+00 1.9790803e+00 1.0974789e+00 7.5914566e-01 1.5781281e+00 1.6567524e+00 1.6951864e+00 4.6137216e-01 1.8193470e+00 2.0336808e+00 1.4275349e+00 7.0834786e-01 1.0588854e+00 1.8801322e+00 7.4965096e-01 1.1803522e+00 1.5908164e+00 1.9645622e+00 4.2238505e-01 1.2220171e+00 1.0116179e+00 8.5731385e-01 1.1485726e+00 1.9317000e+00 7.9664122e-01 5.6097460e-01 5.3106808e-01 1.0334797e+00 1.5679493e+00 6.8124108e-01 2.0247774e+00 1.0499569e+00 2.3371797e+00 1.3332950e+00 1.7744903e+00 3.0154970e+00 1.3277924e+00 2.5520970e+00 2.1193865e+00 3.0297355e+00 1.5881698e+00 1.5547948e+00 1.9487821e+00 1.4037678e+00 1.3973195e+00 1.7249900e+00 1.4967902e+00 3.6762761e+00 3.3933664e+00 2.0023741e+00 2.2484516e+00 8.6702860e-01 3.1482546e+00 1.3659877e+00 2.0060004e+00 2.4114658e+00 1.1530661e+00 9.5944179e-01 1.6364369e+00 2.2989490e+00 2.6726954e+00 3.7560452e+00 1.7032717e+00 1.2286922e+00 1.4040978e+00 3.1041910e+00 1.9523740e+00 1.4097206e+00 8.4169735e-01 2.0525205e+00 2.0729884e+00 2.1328505e+00 1.0499569e+00 2.1908074e+00 2.2633850e+00 1.9289706e+00 1.6929462e+00 1.5333884e+00 1.7729821e+00 7.9671887e-01 1.1060455e+00 2.5932658e+00 1.1359179e+00 2.2153658e+00 2.0116430e+00 9.6825676e-01 1.9538525e+00 2.9958431e+00 1.7387082e+00 1.1339874e+00 1.2823616e+00 1.2471855e+00 2.5771468e+00 1.5006766e+00 1.5158960e+00 1.7131342e+00 1.9169015e+00 1.3850497e+00 1.5416258e+00 2.5358032e+00 2.4678381e+00 2.2144600e+00 2.3737220e+00 2.1274158e+00 9.8372339e-01 1.7887913e+00 1.5921275e+00 2.1896791e+00 1.7854129e+00 1.2218858e+00 1.2670969e+00 2.6904561e+00 3.2109839e+00 2.7851183e+00 1.6425353e+00 1.5729927e+00 2.8211634e+00 1.6904600e+00 1.2882518e+00 1.7618849e+00 1.4390193e+00 9.9282597e-01 1.7222401e+00 1.8692144e+00 2.3979391e+00 2.7477433e+00 1.7762263e+00 1.4761145e+00 1.9687854e+00 2.5941073e+00 1.2723200e+00 1.0497372e+00 9.7397874e-01 1.5327853e+00 1.6373339e+00 1.6177026e+00 1.7131342e+00 1.6177237e+00 1.6189835e+00 1.6013655e+00 2.1620604e+00 1.2836487e+00 1.0769609e+00 1.0246689e+00 1.9326437e+00 1.4149714e+00 2.0593667e+00 1.9008579e+00 7.7368489e-01 1.6801694e+00 2.9457974e+00 1.6627284e+00 1.3215146e+00 1.3491191e+00 8.3512263e-01 2.6175043e+00 1.4565053e+00 1.6449760e+00 1.5357227e+00 1.1692720e+00 9.2780124e-01 1.1582405e+00 1.7355630e+00 2.5925902e+00 1.3094338e+00 1.5678176e+00 2.0102053e+00 7.6952423e-01 1.1716038e+00 9.4417605e-01 1.9573929e+00 1.7612938e+00 1.1827746e+00 6.8675486e-01 2.4881500e+00 2.3327432e+00 2.2476505e+00 1.2375842e+00 1.6387331e+00 1.9108109e+00 1.1188225e+00 1.0733560e+00 1.0560148e+00 1.0005243e+00 8.6347207e-01 1.2199459e+00 9.0753778e-01 1.4483156e+00 2.4625089e+00 1.3082342e+00 8.7375509e-01 1.4601811e+00 1.8000065e+00 1.5372053e+00 7.0097130e-01 9.6204815e-01 9.1315231e-01 1.2848917e+00 1.0993651e+00 1.5357227e+00 1.2764003e+00 1.5003224e+00 1.1101208e+00 1.5658291e+00 7.8808432e-01 1.4489917e+00 1.0920053e+00 1.8302572e+00 1.0943114e+00 1.1955102e+00 1.6415483e+00 9.5491981e-01 1.7343175e+00 1.2563834e+00 1.7780218e+00 1.5661153e+00 1.3901973e+00 1.7352481e+00 1.3724737e+00 2.9349297e+00 1.4110819e+00 2.3154474e+00 1.6753059e+00 2.1644875e+00 2.7793057e+00 1.8300579e+00 2.2275691e+00 1.2267563e+00 3.6839155e+00 2.3163493e+00 1.3205795e+00 2.1115079e+00 1.3018219e+00 1.9822480e+00 2.5100153e+00 1.8661672e+00 4.2327578e+00 2.6573893e+00 6.0725725e-01 2.6633209e+00 1.7222058e+00 2.5939799e+00 1.1664463e+00 2.6821825e+00 2.5963941e+00 1.3509199e+00 1.7816323e+00 1.7046308e+00 2.1381589e+00 2.1542571e+00 4.2222578e+00 1.7881987e+00 1.2473306e+00 1.0083490e+00 2.8478148e+00 2.9960208e+00 2.0583207e+00 1.7939407e+00 2.3128527e+00 2.4854841e+00 2.4090630e+00 1.4110819e+00 2.6669716e+00 2.9270626e+00 2.1822548e+00 9.7289027e-01 1.9265423e+00 2.9135583e+00 1.8510296e+00 1.1608422e+00 9.5483435e-01 6.7975587e-01 9.6424206e-01 1.8685422e+00 6.9420840e-01 1.8699153e-01 2.6643250e-01 7.6880092e-01 1.4668684e+00 4.7680727e-01 2.1966727e+00 1.2150638e+00 2.3282955e+00 1.3855601e+00 1.8709248e+00 2.9899796e+00 1.5396352e+00 2.5003659e+00 2.1099656e+00 3.0668593e+00 1.5989333e+00 1.5788417e+00 1.9566602e+00 1.5639220e+00 1.6339738e+00 1.8236402e+00 1.4967013e+00 3.6603010e+00 3.3937895e+00 1.9915789e+00 2.2840141e+00 1.1223478e+00 3.1075626e+00 1.3520885e+00 2.0407191e+00 2.3526669e+00 1.1508346e+00 9.9970980e-01 1.7227103e+00 2.1946041e+00 2.6155078e+00 3.6958832e+00 1.8054416e+00 1.1477199e+00 1.3984076e+00 3.0713671e+00 2.0894840e+00 1.4301682e+00 9.0552938e-01 2.0395038e+00 2.1489811e+00 2.1344915e+00 1.2150638e+00 2.2517887e+00 2.3533226e+00 1.9673072e+00 1.7095802e+00 1.5528301e+00 1.9068051e+00 9.3899770e-01 3.4893361e-01 1.4098163e+00 4.4901474e-01 9.4301660e-01 4.9009568e-01 1.1908452e+00 9.6032771e-01 1.2627589e+00 7.8945238e-01 7.3502408e-01 2.8451486e+00 1.1622402e+00 2.7058576e+00 1.7424022e+00 2.2846522e+00 3.3213689e+00 9.3810350e-01 2.7757276e+00 1.8894571e+00 3.8131048e+00 2.3010216e+00 1.5984421e+00 2.3698153e+00 1.1049324e+00 1.7539088e+00 2.4591578e+00 1.9849730e+00 4.4474865e+00 3.3956070e+00 1.1104964e+00 2.8478148e+00 1.2628565e+00 3.2741783e+00 1.3548265e+00 2.7443454e+00 2.9214972e+00 1.3520885e+00 1.5950569e+00 1.8924015e+00 2.5961001e+00 2.7889301e+00 4.4811770e+00 1.9680122e+00 1.3672690e+00 1.1906665e+00 3.3943858e+00 2.8533575e+00 2.0610968e+00 1.5261646e+00 2.5498486e+00 2.6295980e+00 2.6227721e+00 1.1622402e+00 2.8191421e+00 2.9841287e+00 2.3684093e+00 1.3684638e+00 2.0228721e+00 2.7146999e+00 1.5430544e+00 1.2073068e+00 4.2737382e-01 1.1404637e+00 3.1271814e-01 9.6032771e-01 7.5303835e-01 1.1016806e+00 9.6606527e-01 5.6318359e-01 2.6951278e+00 1.0877340e+00 2.5880472e+00 1.5788417e+00 2.1577755e+00 3.1981141e+00 1.0053189e+00 2.6422640e+00 1.8441670e+00 3.6556493e+00 2.1516272e+00 1.5283932e+00 2.2572409e+00 1.1515368e+00 1.7244934e+00 2.3310687e+00 1.8210464e+00 4.2584241e+00 3.3382181e+00 1.2189366e+00 2.7191331e+00 1.1859692e+00 3.1732334e+00 1.2980649e+00 2.5768210e+00 2.7513616e+00 1.2636762e+00 1.4403062e+00 1.8020431e+00 2.4433699e+00 2.6920515e+00 4.2945779e+00 1.8903935e+00 1.2074964e+00 1.0277379e+00 3.3038558e+00 2.6967685e+00 1.8755883e+00 1.3730080e+00 2.4290237e+00 2.5228632e+00 2.5343900e+00 1.0877340e+00 2.6795155e+00 2.8549884e+00 2.2878474e+00 1.3941000e+00 1.9010194e+00 2.5529515e+00 1.3637808e+00 1.0801003e+00 2.2778358e+00 9.5491981e-01 5.9448670e-01 5.9589853e-01 3.3742167e-01 1.9403546e+00 7.3727571e-01 1.8011631e+00 1.0580730e+00 1.6859882e+00 8.4110582e-01 1.3396881e+00 2.3254107e+00 1.8940865e+00 1.8320164e+00 1.6099822e+00 2.5455416e+00 1.0698235e+00 1.0938968e+00 1.3476330e+00 1.4941922e+00 1.4633215e+00 1.3755629e+00 8.7649478e-01 3.1069376e+00 2.7702855e+00 1.8674396e+00 1.7104256e+00 1.1065179e+00 2.4455843e+00 9.1688392e-01 1.4945651e+00 1.6975565e+00 7.1757390e-01 5.5102439e-01 1.2274184e+00 1.5152116e+00 1.9568855e+00 3.1286065e+00 1.3281960e+00 6.0709980e-01 1.0827099e+00 2.4180452e+00 1.7168537e+00 8.4814328e-01 5.4968254e-01 1.4259927e+00 1.6175327e+00 1.5676792e+00 1.0580730e+00 1.6914438e+00 1.8627823e+00 1.4252775e+00 1.3670172e+00 9.8340962e-01 1.5690664e+00 6.4292875e-01 1.2799022e+00 3.7622328e-01 9.3727156e-01 7.2340544e-01 8.7070822e-01 1.0517510e+00 4.9772204e-01 2.6753497e+00 1.1327780e+00 2.4219935e+00 1.5112031e+00 2.0792734e+00 3.0229728e+00 1.3206164e+00 2.4652397e+00 1.7009790e+00 3.5349296e+00 2.0290396e+00 1.4008516e+00 2.1030738e+00 1.2197800e+00 1.7532536e+00 2.2495068e+00 1.7048463e+00 4.1210195e+00 3.1691829e+00 1.1769133e+00 2.5856062e+00 1.2767751e+00 2.9863081e+00 1.1384575e+00 2.4711712e+00 2.5838439e+00 1.1268523e+00 1.3640383e+00 1.7178039e+00 2.2416335e+00 2.4908014e+00 4.1279448e+00 1.8102703e+00 1.0585628e+00 1.0110609e+00 3.0999848e+00 2.6577347e+00 1.7876312e+00 1.3164631e+00 2.2615790e+00 2.4095273e+00 2.3580977e+00 1.1327780e+00 2.5710650e+00 2.7600070e+00 2.1383264e+00 1.2571099e+00 1.7683536e+00 2.5188615e+00 1.3683626e+00 1.3381984e+00 1.9104439e+00 1.7447553e+00 2.1191178e+00 5.2290002e-01 1.5506355e+00 3.7401310e+00 2.0532672e+00 3.6450987e+00 2.6791066e+00 3.2198971e+00 4.2474168e+00 1.2374249e+00 3.6904578e+00 2.7448024e+00 4.7359552e+00 3.2167523e+00 2.5268732e+00 3.3111493e+00 1.8901504e+00 2.5824715e+00 3.3694826e+00 2.9225385e+00 5.3651760e+00 4.2632085e+00 1.6938497e+00 3.7848480e+00 2.0962051e+00 4.1703198e+00 2.2884248e+00 3.6689921e+00 3.8480511e+00 2.2915999e+00 2.5084155e+00 2.8222270e+00 3.5057930e+00 3.6931154e+00 5.3885667e+00 2.8913445e+00 2.2944283e+00 2.0536056e+00 4.3194837e+00 3.7370068e+00 2.9859935e+00 2.4261724e+00 3.4875553e+00 3.5613793e+00 3.5512500e+00 2.0532672e+00 3.7558873e+00 3.9047630e+00 3.2988390e+00 2.2352837e+00 2.9604482e+00 3.5852990e+00 2.4345890e+00 7.1446962e-01 4.7680727e-01 8.6080744e-01 1.0528937e+00 2.6643250e-01 2.4784392e+00 9.6779954e-01 2.4056700e+00 1.4093245e+00 1.9680122e+00 3.0432377e+00 1.1095018e+00 2.5046513e+00 1.7969297e+00 3.4167115e+00 1.9006720e+00 1.3928921e+00 2.0543866e+00 1.1288261e+00 1.5650139e+00 2.0901630e+00 1.6223748e+00 4.0330923e+00 3.2470423e+00 1.3554912e+00 2.4968262e+00 1.0256272e+00 3.0550867e+00 1.1407226e+00 2.3454418e+00 2.5560105e+00 1.0597600e+00 1.1958054e+00 1.6477280e+00 2.2779375e+00 2.5604758e+00 4.0677826e+00 1.7340403e+00 1.0472149e+00 1.0317636e+00 3.1283758e+00 2.4552133e+00 1.6602736e+00 1.1211328e+00 2.2084219e+00 2.3071243e+00 2.3006257e+00 9.6779954e-01 2.4647768e+00 2.6219630e+00 2.0691920e+00 1.3232765e+00 1.6800415e+00 2.3045354e+00 1.1399118e+00 2.6525508e-01 6.6194168e-01 1.5279052e+00 4.8284931e-01 2.2240009e+00 1.2628565e+00 2.2754107e+00 1.3512603e+00 1.8635082e+00 2.9164540e+00 1.6496295e+00 2.4127395e+00 2.0563471e+00 3.0426144e+00 1.5827764e+00 1.5566996e+00 1.9230842e+00 1.6230251e+00 1.7204639e+00 1.8421714e+00 1.4471806e+00 3.6003163e+00 3.3322323e+00 1.9737130e+00 2.2612204e+00 1.2180372e+00 3.0253495e+00 1.3338820e+00 2.0126070e+00 2.2700141e+00 1.1450371e+00 1.0044165e+00 1.7168897e+00 2.0924575e+00 2.5354258e+00 3.6216411e+00 1.8094028e+00 1.0735412e+00 1.3351581e+00 3.0117528e+00 2.1161544e+00 1.3888000e+00 9.3005809e-01 2.0016409e+00 2.1479330e+00 2.1191972e+00 1.2628565e+00 2.2323235e+00 2.3582915e+00 1.9639632e+00 1.7034312e+00 1.5340961e+00 1.9379753e+00 9.6779954e-01 6.0647055e-01 1.3810470e+00 2.3749211e-01 2.2111682e+00 1.0514970e+00 2.2223402e+00 1.2585091e+00 1.7887495e+00 2.8752401e+00 1.4450035e+00 2.3620441e+00 1.8870562e+00 3.0854059e+00 1.5854288e+00 1.3907384e+00 1.8599878e+00 1.3776606e+00 1.5509730e+00 1.8163092e+00 1.3995189e+00 3.6797126e+00 3.2203837e+00 1.7354649e+00 2.2402012e+00 1.0327124e+00 2.9556082e+00 1.1508346e+00 2.0324938e+00 2.2869296e+00 9.8115739e-01 9.3443769e-01 1.5799528e+00 2.0763861e+00 2.4587811e+00 3.7098479e+00 1.6697722e+00 9.5240225e-01 1.1656779e+00 2.9602833e+00 2.1358640e+00 1.3782117e+00 8.5400786e-01 1.9683111e+00 2.0924338e+00 2.0712315e+00 1.0514970e+00 2.2110297e+00 2.3461934e+00 1.8840843e+00 1.4831574e+00 1.4659783e+00 1.9682209e+00 8.9496218e-01 1.7964452e+00 6.5622658e-01 2.0655284e+00 1.1268523e+00 1.7764179e+00 9.9332012e-01 1.5158960e+00 2.3895003e+00 1.8982283e+00 1.8651393e+00 1.5387077e+00 2.7528000e+00 1.2871947e+00 1.1001946e+00 1.4627474e+00 1.4880729e+00 1.6030181e+00 1.6047598e+00 1.0374207e+00 3.2910073e+00 2.7655862e+00 1.7002168e+00 1.8814596e+00 1.2390194e+00 2.4548042e+00 8.7876634e-01 1.7158367e+00 1.8151170e+00 7.5016118e-01 7.8272551e-01 1.3241046e+00 1.5455843e+00 1.9524619e+00 3.2834453e+00 1.4300844e+00 5.8483448e-01 1.0263139e+00 2.4682518e+00 1.9911692e+00 1.0783755e+00 7.8808432e-01 1.5539983e+00 1.7882304e+00 1.6881750e+00 1.1268523e+00 1.8822939e+00 2.0779047e+00 1.5475657e+00 1.2810704e+00 1.1339991e+00 1.8534885e+00 9.0513514e-01 1.2087510e+00 3.4293561e+00 1.8554780e+00 3.4031864e+00 2.4420991e+00 2.9637920e+00 4.0403658e+00 1.1828717e+00 3.4998500e+00 2.6632870e+00 4.3954130e+00 2.8761203e+00 2.3399831e+00 3.0445122e+00 1.7890328e+00 2.3476777e+00 3.0401775e+00 2.6527529e+00 5.0321758e+00 4.1557153e+00 1.7943181e+00 3.4850530e+00 1.8421879e+00 4.0156620e+00 2.0769537e+00 3.3460838e+00 3.5735182e+00 2.0311110e+00 2.1883894e+00 2.6137665e+00 3.2724268e+00 3.5184202e+00 5.0524110e+00 2.6818545e+00 2.0664108e+00 1.9589565e+00 4.0923995e+00 3.3884524e+00 2.6885740e+00 2.0959739e+00 3.1948685e+00 3.2743590e+00 3.2448452e+00 1.8554780e+00 3.4633688e+00 3.5839347e+00 3.0150212e+00 2.1174980e+00 2.6708841e+00 3.2242395e+00 2.1262653e+00 2.3423978e+00 1.0035466e+00 2.2827159e+00 1.3153660e+00 1.8615039e+00 2.9298417e+00 1.3184035e+00 2.4022001e+00 1.8151170e+00 3.2315412e+00 1.7166676e+00 1.3595814e+00 1.9250594e+00 1.2570691e+00 1.5534985e+00 1.9352496e+00 1.4849081e+00 3.8359772e+00 3.2064915e+00 1.5410939e+00 2.3431625e+00 1.0302848e+00 2.9742645e+00 1.1013771e+00 2.1700970e+00 2.3919091e+00 9.7531402e-01 1.0396764e+00 1.5925492e+00 2.1393811e+00 2.4733960e+00 3.8624002e+00 1.6816960e+00 9.5650957e-01 1.0890388e+00 3.0080097e+00 2.2891398e+00 1.5007156e+00 9.6470639e-01 2.0543866e+00 2.1765531e+00 2.1487165e+00 1.0035466e+00 2.3180617e+00 2.4663563e+00 1.9433990e+00 1.3718709e+00 1.5414664e+00 2.1305612e+00 1.0107221e+00 1.7770053e+00 1.3000021e+00 1.3205171e+00 8.3930091e-01 1.8258497e+00 2.8432746e+00 1.7831595e+00 2.1193624e+00 1.2896554e+00 8.9496218e-01 1.6446727e+00 1.0946825e+00 2.1632524e+00 1.4041749e+00 5.4207852e-01 1.2077572e+00 2.1213447e+00 2.4069921e+00 2.9335119e+00 8.2206766e-01 1.6918279e+00 2.1851365e+00 1.7733720e+00 7.3278119e-01 1.4407642e+00 1.6273345e+00 1.3293020e+00 1.2924610e+00 1.7503171e+00 1.9276214e+00 2.3545376e+00 1.2450968e+00 1.8184976e+00 2.1894327e+00 1.8463545e+00 3.4893361e-01 1.0719022e+00 1.3834169e+00 1.0621362e+00 7.1740234e-01 1.0327832e+00 1.7770053e+00 6.9976890e-01 5.1210327e-01 9.9313181e-01 2.0841099e+00 1.0825311e+00 5.0208681e-01 1.3466860e+00 1.7937749e+00 8.2148003e-01 1.2268833e+00 2.4485240e+00 1.2563297e+00 1.9934469e+00 1.2524426e+00 2.8471336e+00 1.4358042e+00 7.3339246e-01 1.4342819e+00 4.9772204e-01 6.9457760e-01 1.4636741e+00 1.1233354e+00 3.5605638e+00 2.5755365e+00 1.2907457e+00 1.8667489e+00 3.7622328e-01 2.4814136e+00 6.2818221e-01 1.8112028e+00 2.1131807e+00 5.7672351e-01 7.9999102e-01 8.5275415e-01 1.9102507e+00 2.0267836e+00 3.6643554e+00 9.0168685e-01 8.3216780e-01 8.3306409e-01 2.5178144e+00 1.8656026e+00 1.2019259e+00 7.6362786e-01 1.6472011e+00 1.5943283e+00 1.7001179e+00 0.0000000e+00 1.8078806e+00 1.9570111e+00 1.3920954e+00 7.6195008e-01 1.1016806e+00 1.7729341e+00 7.1446962e-01 1.0816610e+00 7.3851064e-01 7.2248857e-01 3.0483776e+00 5.6342615e-01 1.3118081e+00 1.4889605e+00 9.8006369e-01 1.1737270e+00 4.2737382e-01 2.1131807e+00 1.7428500e+00 1.0543640e+00 8.5494999e-01 2.0376324e+00 1.3288928e+00 2.4590893e+00 5.9382214e-01 1.9576761e+00 9.8006369e-01 1.3739792e+00 8.5141186e-01 6.2055338e-01 1.3918500e+00 1.3907270e+00 9.7789352e-01 6.6861320e-01 6.5233704e-01 2.1059482e+00 9.8663349e-01 1.4035018e+00 1.7831595e+00 7.7880944e-01 1.4027992e+00 9.8677196e-01 1.5191564e+00 4.3798311e-01 6.8554305e-01 6.2111408e-01 1.7937749e+00 6.4241342e-01 9.9981032e-01 6.7780188e-01 1.6099640e+00 8.3640969e-01 1.4769275e+00 1.5684930e+00 6.3173774e-01 1.7302001e+00 2.0286216e+00 1.2711306e+00 1.0474897e+00 2.1700788e+00 8.2827027e-01 5.2290002e-01 7.5863433e-01 1.2491511e+00 1.0565061e+00 9.7542502e-01 3.3872939e-01 2.7982543e+00 2.0758695e+00 1.7342859e+00 1.1984110e+00 9.9693045e-01 1.8354727e+00 6.0840510e-01 1.1145077e+00 1.3082023e+00 5.2283051e-01 5.1857575e-01 4.7149050e-01 1.1471723e+00 1.3839439e+00 2.8837687e+00 5.8522871e-01 5.3667800e-01 9.0098101e-01 1.8496383e+00 1.3956631e+00 4.8016385e-01 6.2451737e-01 9.5139638e-01 1.0316097e+00 1.1168387e+00 8.2148003e-01 1.1408175e+00 1.3888569e+00 8.7588404e-01 9.9189360e-01 4.8124784e-01 1.3365773e+00 6.0566865e-01 1.4097462e+00 2.4566860e+00 1.1582635e+00 1.2895008e+00 1.6771691e+00 6.6244727e-01 8.5330525e-01 4.2110953e-01 1.5929148e+00 1.0739839e+00 5.6992880e-01 5.5102439e-01 2.4009228e+00 1.8321979e+00 2.1944657e+00 6.8299624e-01 1.3125970e+00 1.6253273e+00 1.0353506e+00 7.4661256e-01 1.1022402e+00 9.6950963e-01 8.7649478e-01 5.0731024e-01 1.1544356e+00 1.2559800e+00 2.5390784e+00 4.9009568e-01 1.1268617e+00 1.4819274e+00 1.4649720e+00 9.9544409e-01 6.0942760e-01 9.8006526e-01 5.9589853e-01 4.3937875e-01 6.7904052e-01 1.2268833e+00 6.0365341e-01 8.3354038e-01 4.3719837e-01 1.3221954e+00 4.2932160e-01 1.0251165e+00 9.7833010e-01 3.6949435e+00 6.0653347e-01 1.6944472e+00 1.5821553e+00 1.6484241e+00 1.7861438e+00 1.1497964e+00 2.7265330e+00 2.4114658e+00 1.7100754e+00 1.5191564e+00 1.8544941e+00 9.8143688e-01 2.9288318e+00 1.1208167e+00 2.6441923e+00 4.9772204e-01 2.0065422e+00 1.3857067e+00 8.4632640e-01 2.0655380e+00 2.0890644e+00 1.6229726e+00 9.3175410e-01 6.4813570e-01 1.8882412e+00 1.6282537e+00 2.0045623e+00 2.3010727e+00 4.0443437e-01 1.9471640e+00 1.6420881e+00 2.2200703e+00 1.1092092e+00 1.3077539e+00 1.2486828e+00 2.4485240e+00 1.1714086e+00 1.4815200e+00 1.3709657e+00 2.1645801e+00 1.5528645e+00 2.0592947e+00 2.2565403e+00 3.2107953e+00 2.2989490e+00 4.0089941e+00 2.5709804e+00 1.9412285e+00 2.6814987e+00 1.0808305e+00 1.6177026e+00 2.5906314e+00 2.3241321e+00 4.7335798e+00 3.7356640e+00 1.5467170e+00 3.0855313e+00 1.1828955e+00 3.6907456e+00 1.7719327e+00 2.9776826e+00 3.3258154e+00 1.7290027e+00 1.8703975e+00 2.1032002e+00 3.0991288e+00 3.2379874e+00 4.8403184e+00 2.1396216e+00 1.8765527e+00 1.6420881e+00 3.7688016e+00 2.8977291e+00 2.3525703e+00 1.7721385e+00 2.8780663e+00 2.8053505e+00 2.9124074e+00 1.2563297e+00 3.0197298e+00 3.1129968e+00 2.6135061e+00 1.7341866e+00 2.3184326e+00 2.7661123e+00 1.7090768e+00 1.2067996e+00 1.8641580e+00 1.3940244e+00 1.3162189e+00 8.8198158e-01 2.2794791e+00 2.1012392e+00 1.5525661e+00 1.0918469e+00 2.2063254e+00 1.1211328e+00 2.4017426e+00 1.1211328e+00 2.2284888e+00 6.3765570e-01 1.5168126e+00 1.2830542e+00 7.2263841e-01 1.5939137e+00 1.6681833e+00 1.2435436e+00 4.6557224e-01 3.1271814e-01 2.2147971e+00 1.2909648e+00 1.4589882e+00 1.7351918e+00 8.5359653e-01 1.8877628e+00 1.2647627e+00 1.8001617e+00 9.2780124e-01 1.2301583e+00 1.1566759e+00 1.9934469e+00 1.1506301e+00 1.5274241e+00 1.1815770e+00 1.6939440e+00 1.2016246e+00 1.9452063e+00 1.8368886e+00 2.7696320e+00 1.7002168e+00 6.6444642e-01 1.2360344e+00 1.3162958e+00 1.5606124e+00 1.8019802e+00 1.1903794e+00 3.3139779e+00 1.5262653e+00 1.2463647e+00 1.7598642e+00 1.6038123e+00 1.5053088e+00 8.4040822e-01 1.8873059e+00 1.7273593e+00 1.0791305e+00 1.4542898e+00 8.8167165e-01 1.3277924e+00 1.1132823e+00 3.3576107e+00 9.4738284e-01 1.0119180e+00 9.3046944e-01 1.8017473e+00 2.2743623e+00 1.4404916e+00 1.5380438e+00 1.4761813e+00 1.5955619e+00 1.5999471e+00 1.2524426e+00 1.7473897e+00 2.0612423e+00 1.3691763e+00 6.7534282e-01 1.2539581e+00 2.2701663e+00 1.5558007e+00 1.5218782e+00 2.4628184e+00 1.5932824e+00 3.2458126e+00 2.5692387e+00 1.4348047e+00 1.8937847e+00 9.2060977e-01 2.4408782e+00 3.8250534e+00 1.0499398e+00 2.8336242e+00 2.0769357e+00 2.6064495e+00 1.0813975e+00 1.3021456e+00 2.4993477e+00 2.2323451e+00 2.1662332e+00 1.8260680e+00 2.0200580e+00 1.1770826e+00 2.1383117e+00 2.5736499e+00 3.0399892e+00 1.5323598e+00 1.2212784e+00 1.7944590e+00 2.3235953e+00 1.3759094e+00 1.3385913e+00 1.3604806e+00 2.8471336e+00 1.0797751e+00 9.4588685e-01 1.6150266e+00 2.9366827e+00 1.8217819e+00 1.3773939e+00 2.3541561e+00 1.1723315e+00 6.4232366e-01 1.8822595e+00 1.3566020e+00 4.2656951e-01 5.7691891e-01 2.2149281e+00 2.2825823e+00 2.4730728e+00 7.0958226e-01 1.4300979e+00 1.9425292e+00 1.2122797e+00 4.9430028e-01 1.0215032e+00 1.0391769e+00 7.2638147e-01 9.8137813e-01 1.1659675e+00 1.5397131e+00 2.3056726e+00 1.0072799e+00 1.1569911e+00 1.6871910e+00 1.6699010e+00 7.9127668e-01 4.3341454e-01 8.2155022e-01 5.7672351e-01 6.8304299e-01 6.6412342e-01 1.4358042e+00 7.0097130e-01 8.1019167e-01 6.5485710e-01 1.6386105e+00 4.6472955e-01 7.2626021e-01 8.9802947e-01 8.9083207e-01 9.8663349e-01 1.0101003e+00 1.2666796e+00 7.2340544e-01 3.1120413e+00 1.9012831e+00 1.3662822e+00 1.4214310e+00 1.0271885e+00 1.7789322e+00 2.8835410e-01 1.4717950e+00 1.5613089e+00 4.5716421e-01 8.2373020e-01 3.8830315e-01 1.2833190e+00 1.3103990e+00 3.1817011e+00 4.8644514e-01 5.9610506e-01 8.0162421e-01 1.8503155e+00 1.7547273e+00 9.3865015e-01 8.9973730e-01 1.1346946e+00 1.2001902e+00 1.2260535e+00 7.3339246e-01 1.3976606e+00 1.6479131e+00 9.4228329e-01 5.0621589e-01 7.1671402e-01 1.7153988e+00 9.3451915e-01 1.7865803e+00 1.3700593e+00 7.2638147e-01 5.3458689e-01 2.2505972e+00 1.6524504e+00 2.2440955e+00 5.5576380e-01 1.5638518e+00 1.3688560e+00 1.0552128e+00 7.1143905e-01 8.2518769e-01 1.0245496e+00 9.9235657e-01 6.7030885e-01 8.3156325e-01 9.6025744e-01 2.3337038e+00 6.8299624e-01 1.1166319e+00 1.5524781e+00 1.1685901e+00 1.1719135e+00 6.6412342e-01 1.1159239e+00 2.6643250e-01 4.7488466e-01 4.3341454e-01 1.4342819e+00 5.7691891e-01 8.8366512e-01 3.3492202e-01 1.3576953e+00 4.2110953e-01 1.2033093e+00 1.1777985e+00 8.7819565e-01 1.8719964e+00 1.5530949e+00 3.9773949e+00 2.6834336e+00 1.0194189e+00 2.2401597e+00 7.0463400e-01 2.6908242e+00 8.9981614e-01 2.2443541e+00 2.5055082e+00 9.6168382e-01 1.2786676e+00 1.1515752e+00 2.2564140e+00 2.2581551e+00 4.0837847e+00 1.1737270e+00 1.1984110e+00 1.0100915e+00 2.7760526e+00 2.2855612e+00 1.6668656e+00 1.2419907e+00 2.0207624e+00 1.9399964e+00 2.0427084e+00 4.9772204e-01 2.1876191e+00 2.3343528e+00 1.7191609e+00 7.3633268e-01 1.5086315e+00 2.2088314e+00 1.2082987e+00 1.1857824e+00 1.2636762e+00 3.3874427e+00 2.5564450e+00 1.8349829e+00 1.6578570e+00 5.8813453e-01 2.5222553e+00 1.0240850e+00 1.6676963e+00 2.1419072e+00 9.3827844e-01 9.8741108e-01 8.7169308e-01 2.0802526e+00 2.1175243e+00 3.5451448e+00 8.2097460e-01 1.3248988e+00 1.4633215e+00 2.4116155e+00 1.5361480e+00 1.2935378e+00 9.5818710e-01 1.5578153e+00 1.3192053e+00 1.5035025e+00 6.9457760e-01 1.5912796e+00 1.6259926e+00 1.1892978e+00 1.1294987e+00 1.0978602e+00 1.4813076e+00 9.1948999e-01 8.1819403e-01 2.2419326e+00 2.2807501e+00 2.5846003e+00 6.4497192e-01 1.4107908e+00 2.0247998e+00 1.3509199e+00 5.5183182e-01 1.2328847e+00 1.1911894e+00 9.0810653e-01 9.7397874e-01 1.4379681e+00 1.6702453e+00 2.3957048e+00 9.4716675e-01 1.4061835e+00 1.8616601e+00 1.6979390e+00 5.2290002e-01 7.0376604e-01 9.7757519e-01 6.9976890e-01 4.8012872e-01 6.5622658e-01 1.4636741e+00 5.9074344e-01 5.5183182e-01 5.8926015e-01 1.7101283e+00 6.2055338e-01 5.2374483e-01 1.0096792e+00 2.4983023e+00 2.0024830e+00 2.0009022e+00 9.4244262e-01 1.2563297e+00 1.6864324e+00 8.0788963e-01 8.3930091e-01 1.0038277e+00 7.0810362e-01 5.9074344e-01 6.2055338e-01 9.0121804e-01 1.2356595e+00 2.5673851e+00 7.1082758e-01 6.9066640e-01 1.1671832e+00 1.6263298e+00 1.2372185e+00 2.6033464e-01 7.2248857e-01 6.6653737e-01 8.5606908e-01 8.7588404e-01 1.1233354e+00 9.0810653e-01 1.1795009e+00 7.1867388e-01 1.2188386e+00 3.1239235e-01 1.1894366e+00 7.5921691e-01 2.7729820e+00 4.4273104e+00 1.7851048e+00 3.5860697e+00 2.3211451e+00 3.2572853e+00 1.7681972e+00 1.6466818e+00 3.1677578e+00 2.9074188e+00 2.8617360e+00 2.1557081e+00 2.3917474e+00 3.9487224e-01 2.8587345e+00 3.1370513e+00 3.5889276e+00 1.8806886e+00 2.0412779e+00 2.4100318e+00 3.0088533e+00 2.0247746e+00 2.1265123e+00 2.0926464e+00 3.5605638e+00 1.8217810e+00 1.8066213e+00 2.3669524e+00 3.5958907e+00 2.5091153e+00 2.1661990e+00 3.0374915e+00 2.7063291e+00 1.8195505e+00 2.8431665e+00 6.1655427e-01 2.1507483e+00 2.1438129e+00 1.7230435e+00 2.3108260e+00 2.5097011e+00 1.8135469e+00 1.5638528e+00 9.0791603e-01 2.8200316e+00 1.7992895e+00 2.2827159e+00 2.3805592e+00 1.0279218e+00 2.6120156e+00 2.2030084e+00 2.6289851e+00 1.7477225e+00 1.8297977e+00 1.8176515e+00 2.5755365e+00 1.8486085e+00 2.1438129e+00 1.7993706e+00 2.0846858e+00 2.0084695e+00 2.7218129e+00 2.6544629e+00 2.7850656e+00 1.6064410e+00 2.7362607e+00 1.2723027e+00 2.8153418e+00 2.8097763e+00 1.4630671e+00 1.8911656e+00 1.6976298e+00 2.3931138e+00 2.3316649e+00 4.4654565e+00 1.7621453e+00 1.4315442e+00 9.9921804e-01 3.0176875e+00 3.0491088e+00 2.1855415e+00 1.8898572e+00 2.4817766e+00 2.5552736e+00 2.5674482e+00 1.2907457e+00 2.7588865e+00 3.0041677e+00 2.2870308e+00 9.4057729e-01 2.0520412e+00 2.9779211e+00 1.8911656e+00 1.9172403e+00 1.5033800e+00 1.5778466e+00 4.2450569e-01 7.6773108e-01 1.5016932e+00 1.3345218e+00 1.1346946e+00 1.0902078e+00 1.2416734e+00 1.9196757e+00 1.1117653e+00 1.6095257e+00 2.0596575e+00 1.0943114e+00 8.7072347e-01 9.2729770e-01 1.4434261e+00 3.8830315e-01 3.6319073e-01 4.1088655e-01 1.8667489e+00 1.6562722e-01 4.2450569e-01 5.9279023e-01 1.8877121e+00 8.2518769e-01 9.7789352e-01 1.4886316e+00 2.7335291e+00 9.1459005e-01 1.8213026e+00 2.2454046e+00 7.7259801e-01 8.0376328e-01 1.0525811e+00 2.1168634e+00 2.2814168e+00 3.7089872e+00 1.0767714e+00 1.0755005e+00 1.1631285e+00 2.6946772e+00 1.7497347e+00 1.2634840e+00 7.1971771e-01 1.7438018e+00 1.6356845e+00 1.7637315e+00 3.7622328e-01 1.8511762e+00 1.9311191e+00 1.4699785e+00 1.1016806e+00 1.1928774e+00 1.6354514e+00 6.5233704e-01 2.0052498e+00 1.7681972e+00 1.2007144e+00 2.1235855e+00 2.2484715e+00 1.6942544e+00 1.0546367e+00 5.1386894e-01 2.3251407e+00 1.7093881e+00 2.0273081e+00 2.2255325e+00 6.9493020e-01 2.3316649e+00 1.8640280e+00 2.3781796e+00 1.4043141e+00 1.6126002e+00 1.5456113e+00 2.4814136e+00 1.5467508e+00 1.8811164e+00 1.5963715e+00 2.0694478e+00 1.7422855e+00 2.4276706e+00 2.4143104e+00 1.5837613e+00 1.7028549e+00 2.6643250e-01 7.3283576e-01 6.1619693e-01 1.4102704e+00 1.5157660e+00 3.3107238e+00 7.0702759e-01 4.6964680e-01 7.3731902e-01 2.0564363e+00 1.8389778e+00 9.9058911e-01 7.8305765e-01 1.2692102e+00 1.3637808e+00 1.3483908e+00 6.2818221e-01 1.5635907e+00 1.7874832e+00 1.0817627e+00 4.8284931e-01 7.9664122e-01 1.7693113e+00 8.5141186e-01 7.7538587e-01 1.4522625e+00 1.1678338e+00 1.2100516e+00 1.1294987e+00 1.4712028e+00 1.8985225e+00 1.2171256e+00 1.5155373e+00 1.9939611e+00 1.4342819e+00 6.6653737e-01 7.1511757e-01 1.2680818e+00 5.4772790e-01 6.0868934e-01 6.7484334e-01 1.8112028e+00 3.8639663e-01 5.2413598e-01 7.9227302e-01 1.9656037e+00 7.9656884e-01 7.1789533e-01 1.2970125e+00 1.6649242e+00 1.5382030e+00 1.4107908e+00 5.4248468e-01 9.6424206e-01 1.6581712e+00 1.4527629e+00 1.5643033e+00 2.0014001e+00 1.0048958e+00 1.4365091e+00 1.0328871e+00 1.6659456e+00 6.7424840e-01 1.0427348e+00 9.3481345e-01 2.1131807e+00 8.1596583e-01 1.1349095e+00 1.1009910e+00 2.0312552e+00 1.0961859e+00 1.4886316e+00 1.7139439e+00 4.8016385e-01 6.4687084e-01 1.4356300e+00 1.6309773e+00 3.2287360e+00 7.3391501e-01 4.4499696e-01 8.4121419e-01 2.1133414e+00 1.6592561e+00 8.3333283e-01 5.2066928e-01 1.2097457e+00 1.2911242e+00 1.2850973e+00 5.7672351e-01 1.4812088e+00 1.6720834e+00 1.0285902e+00 7.2340544e-01 6.8124108e-01 1.5683551e+00 6.1067563e-01 8.0990117e-01 1.4468934e+00 1.7768340e+00 2.9867606e+00 8.8098199e-01 6.6217390e-01 1.1327663e+00 2.1506380e+00 1.2980342e+00 5.4779717e-01 1.3340137e-01 1.1051628e+00 1.1634940e+00 1.1952607e+00 7.9999102e-01 1.2953104e+00 1.4320028e+00 9.9155078e-01 1.1867923e+00 5.7526462e-01 1.1726810e+00 2.6680274e-01 1.2602457e+00 1.2678174e+00 2.9703757e+00 1.3103399e-01 8.4439576e-01 1.0887336e+00 1.6811909e+00 1.4435947e+00 7.9778097e-01 8.9789119e-01 9.2528705e-01 8.7435479e-01 9.9613800e-01 8.5275415e-01 1.0871867e+00 1.3186900e+00 6.8124108e-01 8.2317311e-01 5.4397563e-01 1.4334280e+00 9.0121513e-01 6.7419212e-01 2.1234744e+00 1.3330747e+00 1.2524426e+00 1.6423187e+00 1.1112287e+00 1.7731481e+00 1.0412209e+00 1.5779602e+00 8.1552831e-01 1.2367326e+00 1.0877340e+00 1.9102507e+00 1.1360631e+00 1.4957547e+00 1.1495900e+00 1.6944472e+00 1.0511712e+00 1.7894533e+00 1.6403454e+00 2.3936810e+00 1.3012342e+00 1.5364148e+00 1.7852089e+00 7.8659640e-01 2.0467146e+00 1.4387140e+00 1.9055720e+00 1.0341095e+00 1.3049404e+00 1.1996837e+00 2.0267836e+00 1.2898173e+00 1.6473842e+00 1.2092432e+00 1.6223502e+00 1.2928268e+00 2.1087983e+00 1.9576761e+00 2.9790337e+00 3.1661621e+00 3.6343153e+00 1.9094387e+00 2.2505084e+00 2.4932991e+00 3.0919113e+00 2.0983540e+00 2.2774299e+00 2.1822207e+00 3.6643554e+00 1.9784646e+00 2.0041121e+00 2.4741311e+00 3.6564145e+00 2.5932898e+00 2.3540393e+00 3.1383476e+00 9.6758101e-01 1.2012033e+00 1.6658010e+00 1.4135473e+00 8.6985276e-01 9.6249568e-01 9.3451915e-01 8.2380019e-01 9.6993876e-01 9.0168685e-01 1.0632334e+00 1.2723027e+00 6.4232366e-01 8.7376399e-01 5.8942278e-01 1.4153467e+00 9.6559725e-01 6.0709980e-01 2.1192618e+00 1.8400866e+00 8.3619405e-01 7.2626021e-01 1.2848171e+00 1.4775384e+00 1.4500356e+00 8.3216780e-01 1.5874797e+00 1.8427499e+00 1.2442620e+00 8.6985276e-01 8.3878265e-01 1.7484907e+00 7.7500385e-01 2.4608044e+00 2.2758533e+00 1.3186900e+00 1.1601403e+00 1.7655861e+00 1.8899115e+00 1.9324044e+00 8.3306409e-01 2.0122449e+00 2.2830055e+00 1.6787550e+00 8.1019167e-01 1.3243478e+00 2.1959912e+00 1.1244567e+00 1.9511379e+00 1.7500667e+00 2.2774574e+00 1.1011934e+00 1.2684800e+00 1.1435764e+00 2.5178144e+00 1.1861264e+00 1.4342819e+00 1.3109392e+00 2.2026274e+00 1.5858048e+00 2.0711809e+00 2.3400013e+00 1.0557584e+00 1.3438727e+00 1.0821769e+00 8.4383266e-01 1.0493821e+00 1.8656026e+00 7.8957903e-01 5.5399712e-01 1.0737552e+00 2.2030214e+00 1.1115276e+00 2.1119253e-01 1.3352177e+00 6.6627781e-01 7.2272795e-01 8.6751530e-01 9.1936743e-01 1.2019259e+00 8.7588404e-01 1.0946184e+00 8.0162421e-01 1.4236959e+00 4.0664863e-01 9.8463602e-01 6.8496652e-01 1.2266388e+00 1.2615426e+00 1.3010124e+00 7.6362786e-01 1.4014424e+00 1.5148689e+00 1.0932736e+00 1.2210779e+00 6.9618131e-01 1.2059294e+00 2.0855006e-01 4.7509249e-01 3.1239235e-01 1.6472011e+00 4.6557224e-01 7.5810578e-01 4.3937875e-01 1.5999820e+00 5.6262711e-01 1.1233867e+00 1.3019241e+00 3.9472619e-01 1.5943283e+00 3.3742167e-01 4.8284931e-01 3.4893361e-01 1.6410601e+00 6.6154242e-01 9.3451915e-01 1.2980649e+00 1.7001179e+00 5.2283051e-01 6.7484334e-01 3.3872939e-01 1.6485749e+00 6.6653737e-01 1.1055440e+00 1.3931316e+00 1.8078806e+00 1.9570111e+00 1.3920954e+00 7.6195008e-01 1.1016806e+00 1.7729341e+00 7.1446962e-01 3.8639663e-01 6.2027457e-01 1.8723846e+00 8.0990117e-01 9.0447834e-01 1.4243850e+00 7.9227302e-01 2.1007225e+00 1.0230346e+00 7.1789533e-01 1.5391678e+00 1.3603920e+00 4.6137216e-01 1.1083720e+00 1.1686836e+00 1.1908452e+00 2.1561807e+00 1.2583645e+00 1.0722301e+00 7.7259801e-01 1.2001902e+00 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-seuclidean-ml.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-seuclidean-ml.txt new file mode 100644 index 0000000000000000000000000000000000000000..ce80cb1ead3f88bec0fbaf6d48cb4fc584e52168 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-seuclidean-ml.txt @@ -0,0 +1 @@ + 1.4330520e+01 1.4635426e+01 1.3450855e+01 1.4761140e+01 1.3508642e+01 1.5434417e+01 1.3887693e+01 1.5166776e+01 1.3966038e+01 1.4950451e+01 1.4564587e+01 1.3834201e+01 1.4347008e+01 1.5641962e+01 1.4689053e+01 1.4418720e+01 1.4545856e+01 1.4151822e+01 1.4669017e+01 1.5150750e+01 1.3770166e+01 1.3288969e+01 1.4048191e+01 1.4049959e+01 1.4164158e+01 1.3727834e+01 1.4074687e+01 1.4321303e+01 1.2497330e+01 1.3820273e+01 1.4441030e+01 1.4780222e+01 1.2504339e+01 1.5022245e+01 1.4263650e+01 1.3704507e+01 1.3694385e+01 1.3667517e+01 1.3177468e+01 1.4391931e+01 1.4893903e+01 1.4475753e+01 1.4440707e+01 1.3603096e+01 1.6889651e+01 1.4731174e+01 1.3337775e+01 1.5187532e+01 1.5667271e+01 1.4226037e+01 1.4203554e+01 1.5272898e+01 1.6031460e+01 1.5991549e+01 1.1855060e+01 1.4844776e+01 1.2475182e+01 1.4408126e+01 1.4836870e+01 1.3472986e+01 1.4089281e+01 1.1018298e+01 1.3183296e+01 1.4590802e+01 1.4404230e+01 1.2717623e+01 1.3983283e+01 1.4017133e+01 1.4608005e+01 1.4402553e+01 1.3977803e+01 1.4091040e+01 1.3977459e+01 1.2630449e+01 1.4160109e+01 1.3029417e+01 1.2654432e+01 1.2794946e+01 1.3194978e+01 1.4378745e+01 1.2431908e+01 1.3852651e+01 1.3748358e+01 1.4003568e+01 1.5066681e+01 1.5192826e+01 1.4370013e+01 1.5792545e+01 1.3547546e+01 1.4411543e+01 1.4794215e+01 1.4924312e+01 1.4789153e+01 1.4875055e+01 1.4208537e+01 1.2786148e+01 1.4882476e+01 1.3302010e+01 1.4354774e+01 1.4542129e+01 1.5889633e+01 1.2928185e+01 1.4877868e+01 1.2890902e+01 1.4406165e+01 1.4498123e+01 1.4303273e+01 1.3207002e+01 1.3954732e+01 1.4841248e+01 1.5427799e+01 1.4363463e+01 1.3976277e+01 1.4284878e+01 1.4457991e+01 1.3369469e+01 1.5246610e+01 1.4487573e+01 1.4525176e+01 1.4505865e+01 1.5037347e+01 1.3834927e+01 1.3758988e+01 1.3424987e+01 1.4914766e+01 1.3783923e+01 1.3434291e+01 1.2895927e+01 1.3870360e+01 1.3342977e+01 1.3094322e+01 1.3057847e+01 1.3322375e+01 1.4940650e+01 1.4476829e+01 1.4197503e+01 1.4597035e+01 1.2963234e+01 1.4011414e+01 1.3181409e+01 1.3339615e+01 1.3928735e+01 1.3508015e+01 1.3170749e+01 1.3529133e+01 1.3454724e+01 1.4883437e+01 1.4564565e+01 1.2474313e+01 1.4435790e+01 1.5285703e+01 1.3701736e+01 1.3578312e+01 1.4807311e+01 1.4281072e+01 1.2920213e+01 1.4427803e+01 1.1408611e+01 1.4097334e+01 1.2868115e+01 1.3903683e+01 1.3800332e+01 1.3439339e+01 1.4062651e+01 1.3242107e+01 1.4400424e+01 1.3826132e+01 1.5991146e+01 1.3118258e+01 1.5377390e+01 1.2858378e+01 1.5249567e+01 1.4081585e+01 1.4458052e+01 1.4175623e+01 1.4850069e+01 1.5506668e+01 1.5014770e+01 1.4337030e+01 1.5214705e+01 1.4803729e+01 1.3188675e+01 1.3437739e+01 1.3409394e+01 1.4607386e+01 1.5394271e+01 1.5946451e+01 1.3769364e+01 1.4181208e+01 1.2551765e+01 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-spearman-ml.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-spearman-ml.txt new file mode 100644 index 0000000000000000000000000000000000000000..b50fe3af1912d20aaa737eedc1b6e096a7005876 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/pdist-spearman-ml.txt @@ -0,0 +1 @@ + 9.3540954e-01 9.7904590e-01 8.6703870e-01 1.1569997e+00 8.7174317e-01 1.0627183e+00 9.1272727e-01 1.1593999e+00 9.7573357e-01 1.0072127e+00 1.0536814e+00 9.6276028e-01 9.7700570e-01 1.1513951e+00 1.0719592e+00 9.2178818e-01 1.0004680e+00 9.3689769e-01 9.8205821e-01 1.0332673e+00 9.4517852e-01 8.9437744e-01 9.7556556e-01 9.0460246e-01 9.7210921e-01 9.2230423e-01 9.9605161e-01 9.6852085e-01 8.4162016e-01 9.6667267e-01 9.7759376e-01 9.9757576e-01 7.6992499e-01 1.0151695e+00 9.8691869e-01 9.0325833e-01 8.6665467e-01 8.8844884e-01 8.4553255e-01 9.7700570e-01 9.5159916e-01 9.8906691e-01 1.0551935e+00 9.1973597e-01 1.3266247e+00 1.0982778e+00 8.4531653e-01 1.0887369e+00 1.0984938e+00 9.9851185e-01 9.0701470e-01 1.0639304e+00 1.2392919e+00 1.1422502e+00 8.1725773e-01 1.1844944e+00 7.8219022e-01 1.0817162e+00 1.2196100e+00 1.0003120e+00 1.0164536e+00 7.0724272e-01 9.7981398e-01 1.1134953e+00 1.0671107e+00 9.3600960e-01 9.9984398e-01 1.0356916e+00 1.1248005e+00 1.0696310e+00 1.0634263e+00 9.6472847e-01 9.9365137e-01 8.5724572e-01 1.1257846e+00 8.9930993e-01 9.4903090e-01 9.0667867e-01 9.1231923e-01 1.0573777e+00 9.0105011e-01 9.5255926e-01 1.0177978e+00 1.0606901e+00 1.1966997e+00 1.0891929e+00 1.0085089e+00 1.2640264e+00 9.3246925e-01 1.0198020e+00 1.2055806e+00 1.1237924e+00 1.1060666e+00 1.0517252e+00 1.0684668e+00 7.6844884e-01 1.0572697e+00 8.7373537e-01 9.6283228e-01 9.9350735e-01 1.2412601e+00 7.6322832e-01 1.0298950e+00 8.6148215e-01 1.0042724e+00 9.7012901e-01 9.3712571e-01 8.5845785e-01 8.5862586e-01 1.0336634e+00 1.0955536e+00 9.5302730e-01 9.8696670e-01 1.0633063e+00 1.0026643e+00 9.6380438e-01 1.1711251e+00 9.9273927e-01 1.0260906e+00 1.0863966e+00 1.0482808e+00 9.0361836e-01 9.2358836e-01 8.7794779e-01 1.2461206e+00 9.2985299e-01 1.0418962e+00 9.4660666e-01 9.5636364e-01 9.0646265e-01 9.9113111e-01 8.3027903e-01 9.3341734e-01 1.1378938e+00 1.0548215e+00 1.0086889e+00 1.1998920e+00 8.6063006e-01 1.0255506e+00 8.4786079e-01 1.0090729e+00 9.2542454e-01 9.5176718e-01 9.3477348e-01 9.0091809e-01 9.6404440e-01 1.1158716e+00 9.9614761e-01 7.7682568e-01 1.0605461e+00 1.0895650e+00 9.0065407e-01 8.7173117e-01 9.9821182e-01 1.2165617e+00 8.6127813e-01 1.1111071e+00 7.9015902e-01 1.0433843e+00 8.6510651e-01 1.0019202e+00 1.0154815e+00 9.4381038e-01 9.8646265e-01 1.0062526e+00 9.7426943e-01 9.8191419e-01 1.3038944e+00 8.6277828e-01 1.0830243e+00 8.6851485e-01 1.1192559e+00 9.9120312e-01 9.6540054e-01 9.1072307e-01 1.1775698e+00 1.1139154e+00 1.1083468e+00 9.9593159e-01 1.0825923e+00 1.1115032e+00 9.7430543e-01 9.5605161e-01 9.2800480e-01 9.4369037e-01 1.1136034e+00 1.1382898e+00 9.5937594e-01 9.8843084e-01 7.4563456e-01 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/random-bool-data.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/random-bool-data.txt new file mode 100644 index 0000000000000000000000000000000000000000..df0d838f517f6c0afd8954ad87bc83886e0e3de4 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/random-bool-data.txt @@ -0,0 +1,100 @@ +0 1 1 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 1 1 0 0 1 1 +1 1 1 1 1 1 1 0 0 1 1 1 0 0 0 0 1 0 1 0 1 1 1 0 1 0 1 1 1 1 +0 1 0 1 1 0 0 1 1 1 1 0 1 0 0 1 1 0 1 1 1 0 1 1 0 1 1 1 0 1 +1 1 1 0 0 1 1 0 0 1 1 1 0 0 1 1 0 1 1 1 0 1 1 0 0 0 0 1 0 0 +1 0 0 0 0 1 1 0 1 1 0 1 0 0 0 0 1 0 0 1 0 1 0 0 1 1 1 1 0 0 +1 0 1 1 0 0 0 1 1 1 1 1 0 1 1 0 1 0 1 0 1 0 0 0 0 0 0 0 1 1 +0 1 0 0 1 0 0 0 1 0 0 1 1 0 0 0 0 1 1 0 0 1 0 1 1 1 1 0 1 0 +1 0 1 1 1 0 0 0 0 1 1 0 0 0 0 1 0 1 0 0 0 1 1 1 0 1 0 0 1 0 +1 1 1 0 0 1 1 0 0 1 0 0 1 0 0 1 0 1 1 0 1 1 0 1 1 1 0 0 1 1 +1 1 0 1 0 0 1 1 1 1 1 1 1 0 1 0 1 1 1 1 0 0 0 0 0 0 1 1 0 0 +1 0 1 0 1 1 0 1 1 0 1 1 0 1 1 1 1 0 0 1 1 0 0 0 0 1 0 0 0 0 +1 1 1 1 0 1 0 0 0 0 0 1 0 1 1 1 1 0 1 1 1 1 1 1 0 1 0 1 1 1 +1 1 1 1 1 1 1 1 1 0 1 1 0 0 1 0 1 0 1 0 1 0 0 0 1 0 0 1 0 1 +0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 0 1 0 1 0 1 1 0 1 0 0 1 1 1 1 +1 0 0 1 0 0 1 0 1 0 0 1 0 0 0 1 1 0 0 0 1 0 1 0 0 1 1 0 1 1 +1 0 0 1 1 0 0 1 1 0 0 1 1 1 1 1 1 1 1 0 1 1 1 1 0 1 1 1 0 0 +1 1 0 0 1 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 0 0 0 1 1 1 1 1 +0 0 0 1 1 1 1 1 0 1 0 1 1 1 1 0 0 1 1 1 1 1 0 0 1 0 1 0 0 0 +1 0 1 1 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 1 1 0 1 1 0 1 1 +0 0 0 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1 1 1 +0 1 0 0 1 1 0 0 1 1 1 0 0 0 1 0 0 0 0 1 1 0 0 1 0 1 1 0 1 0 +1 0 1 0 1 1 1 0 0 0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 1 1 1 0 1 1 +0 0 1 0 0 0 0 0 1 1 0 0 1 1 1 1 1 1 1 1 0 1 0 0 0 0 0 0 1 0 +0 1 0 1 1 1 0 1 1 1 0 1 0 1 1 1 0 0 0 0 1 1 1 0 0 1 1 0 0 1 +0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 1 1 0 1 1 0 0 +1 0 0 0 1 0 1 0 0 1 0 1 1 0 1 0 1 0 1 0 1 1 1 0 0 0 1 1 1 0 +1 0 0 0 1 1 1 0 0 1 0 1 1 1 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 1 +0 1 0 0 0 1 1 1 0 1 1 1 0 1 0 0 1 1 1 1 0 1 0 1 0 1 1 0 1 1 +0 0 1 0 0 0 0 0 0 0 0 1 1 0 1 0 0 1 0 0 0 1 0 1 0 1 0 1 0 1 +0 0 1 0 1 0 1 1 1 1 0 0 1 1 1 1 0 0 1 1 1 1 0 0 1 0 1 0 1 0 +1 1 0 1 1 1 1 1 0 1 0 0 0 1 1 1 0 1 0 0 0 1 1 0 1 0 0 0 0 1 +0 1 0 0 0 1 0 1 1 0 0 1 0 0 0 1 1 1 0 0 1 1 0 1 1 0 0 1 0 1 +1 1 0 0 0 0 0 1 1 0 1 1 0 0 1 0 1 1 0 0 0 1 0 1 0 1 0 1 0 1 +1 1 1 0 1 0 0 1 1 0 1 1 1 0 1 0 1 1 0 0 0 1 1 0 0 1 1 1 1 1 +0 1 0 0 1 1 0 0 1 1 1 1 0 1 0 1 0 1 1 1 0 1 1 0 1 1 0 0 1 0 +1 1 1 1 0 1 0 1 0 1 1 1 1 0 1 0 1 0 1 0 1 1 0 0 1 0 1 0 0 0 +0 0 0 0 1 1 1 0 1 1 0 0 1 1 1 1 0 1 0 1 1 1 1 1 1 0 0 0 0 0 +0 1 1 1 0 0 0 1 1 1 0 1 0 0 1 1 1 1 1 0 1 0 0 1 0 0 0 0 1 1 +0 1 0 0 1 1 1 1 0 0 1 0 1 0 1 1 0 0 1 0 0 1 1 0 0 0 0 1 0 0 +1 1 0 1 0 0 1 1 0 0 1 1 1 0 0 1 1 1 0 0 0 0 1 1 1 0 1 0 0 1 +0 1 1 0 1 0 1 1 0 0 0 1 1 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0 1 1 +0 0 1 1 1 0 1 0 0 1 1 0 0 0 1 1 1 0 1 0 0 0 0 1 1 0 1 1 0 0 +1 0 1 1 1 1 1 1 1 1 0 1 0 0 0 1 0 1 0 0 0 1 1 0 0 1 0 0 0 0 +1 0 1 1 1 0 1 1 1 1 0 0 1 0 1 1 1 0 0 0 0 1 1 1 1 1 0 1 0 0 +1 0 0 0 1 1 1 0 1 1 0 0 1 1 1 0 1 0 0 1 0 1 0 1 1 1 0 0 0 1 +1 0 1 0 1 0 0 0 1 0 0 1 1 0 1 1 0 0 0 1 0 1 1 0 1 0 0 1 0 0 +0 1 1 0 1 0 1 1 1 1 1 0 0 0 0 1 0 1 0 0 1 1 1 1 0 1 0 1 1 1 +0 1 0 1 1 0 1 0 0 1 0 0 1 0 0 1 1 0 1 0 0 0 1 1 1 0 0 1 0 1 +1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 1 +1 1 1 1 1 1 1 1 1 1 0 0 1 0 0 1 0 0 1 1 0 0 1 1 1 1 0 1 0 1 +1 1 1 1 0 0 0 1 0 1 1 0 0 0 1 1 0 0 1 1 1 1 0 0 0 1 0 1 0 0 +1 0 1 0 0 1 1 1 1 0 1 1 0 0 1 0 0 1 1 0 1 1 1 1 1 1 0 0 0 0 +0 1 1 0 0 1 0 0 0 0 0 1 0 1 0 0 1 1 0 1 0 1 0 0 0 1 0 0 1 0 +0 0 0 1 0 0 0 1 1 1 1 1 0 0 0 1 1 0 0 0 1 1 1 0 1 0 1 1 1 0 +1 1 0 0 0 0 1 1 1 0 1 0 1 1 1 0 0 1 0 0 0 0 0 0 1 1 1 0 0 0 +1 0 1 1 1 0 1 0 1 0 0 1 1 1 1 1 0 0 1 1 0 1 1 1 1 0 0 0 0 1 +0 0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 1 1 1 0 0 1 0 0 +0 0 1 1 1 1 1 0 1 0 1 0 0 1 1 1 1 0 0 0 1 0 1 1 0 1 1 1 0 0 +0 0 0 0 0 1 0 0 1 1 0 1 1 0 0 0 0 1 0 1 1 0 0 1 0 0 1 0 1 0 +1 0 0 1 0 1 1 1 0 1 0 1 1 0 0 1 1 0 1 1 1 0 1 0 0 0 1 1 1 1 +0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 1 1 0 0 1 1 0 0 0 +1 0 0 1 1 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 0 1 1 0 0 1 0 1 0 +0 1 0 1 1 1 1 1 0 1 0 1 1 0 0 1 1 0 1 1 0 1 1 0 1 1 0 0 0 1 +1 0 1 1 1 0 0 0 1 0 0 1 0 0 0 1 0 1 1 1 0 0 1 1 1 1 0 0 0 1 +0 1 0 0 1 1 1 1 1 1 0 0 1 0 0 1 1 0 1 0 1 0 1 1 1 0 1 1 0 1 +0 0 1 0 1 1 1 0 0 0 1 0 1 0 1 1 0 0 1 1 0 1 0 1 1 0 0 1 0 1 +0 1 1 1 1 1 0 0 0 0 0 1 0 1 1 1 1 1 0 1 1 1 0 0 1 0 0 1 1 1 +1 1 1 1 0 1 1 1 1 1 1 0 0 1 1 0 1 1 0 1 0 1 0 1 0 1 1 0 0 0 +1 0 0 0 1 0 1 0 0 0 1 0 1 0 0 1 0 1 1 1 1 1 0 0 1 1 1 1 1 0 +0 0 0 0 1 1 1 0 1 0 0 1 1 0 0 1 1 1 1 0 0 1 0 1 0 0 0 1 0 0 +1 1 1 1 1 0 0 0 1 1 0 0 1 1 1 1 0 1 0 1 0 0 0 0 1 1 0 1 1 0 +1 0 1 1 0 1 0 1 0 1 1 0 1 1 1 0 0 1 0 0 1 1 0 0 1 1 0 1 0 1 +1 1 1 1 1 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 1 1 +0 1 1 0 0 1 0 0 0 0 0 0 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 1 1 +1 1 1 0 1 1 1 1 1 0 0 0 0 1 0 0 1 0 1 0 1 1 1 0 0 1 0 0 1 1 +1 1 0 1 0 1 0 1 0 0 1 0 0 0 1 0 1 1 0 1 1 0 1 0 0 1 0 0 1 0 +1 0 1 1 0 0 1 1 0 0 1 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1 0 1 1 0 +1 1 1 1 1 0 0 1 0 0 1 1 1 0 1 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1 +1 0 1 1 0 0 1 1 0 1 1 1 0 0 0 1 0 1 0 0 0 1 1 1 1 1 0 0 1 0 +0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 1 0 0 1 1 0 0 1 0 0 1 0 0 +1 1 1 0 0 0 0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 1 1 0 1 1 1 0 1 0 +1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 1 0 1 0 1 1 0 0 1 0 1 0 1 +1 0 0 0 1 0 1 1 0 1 0 0 0 1 0 1 0 0 0 0 1 1 1 0 1 0 1 1 0 1 +0 1 0 0 0 0 1 0 1 1 1 0 1 1 0 1 0 1 0 1 1 0 0 0 0 0 0 1 1 1 +0 1 0 0 1 0 1 1 0 0 0 0 1 1 0 1 1 1 0 0 1 1 0 0 1 0 1 0 0 0 +0 1 0 1 1 1 1 1 1 1 0 0 1 0 1 0 0 0 0 0 0 1 0 0 1 0 0 1 1 0 +0 0 0 1 0 0 1 0 0 1 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 1 0 0 +1 0 0 0 1 0 1 1 1 1 1 1 1 0 1 0 1 1 1 0 0 1 0 1 0 1 0 1 0 0 +1 0 0 0 1 0 1 0 0 0 1 1 0 0 0 1 1 0 0 1 1 1 1 1 1 0 1 1 1 0 +0 0 0 1 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 1 1 1 0 1 0 0 0 1 1 0 +1 0 0 0 0 0 1 0 1 0 1 0 0 1 1 1 0 1 1 1 0 0 1 0 1 1 1 0 1 0 +0 1 0 0 1 1 1 0 0 1 0 0 0 1 0 1 0 0 0 1 0 0 1 0 0 1 1 1 0 1 +0 0 0 1 1 0 1 0 1 0 1 0 0 0 1 1 1 0 1 1 0 0 0 1 1 0 0 1 0 1 +1 1 1 1 1 1 1 1 0 0 1 1 0 0 0 1 0 1 0 1 0 0 0 1 1 0 1 0 1 0 +0 1 1 0 0 0 1 1 0 0 1 1 0 1 1 1 1 1 0 1 0 0 0 0 1 0 1 0 0 0 +1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 1 1 0 0 1 +0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 1 1 1 1 1 1 0 1 0 0 0 1 1 0 +1 1 1 0 1 1 0 1 1 0 1 1 0 1 0 0 1 0 0 0 1 1 1 1 0 1 1 0 1 1 +0 0 1 1 1 0 0 0 0 1 1 0 0 1 1 0 1 0 1 0 0 1 0 0 0 1 1 0 0 1 +0 0 0 1 0 0 1 1 1 1 1 1 0 0 1 0 0 1 0 0 0 0 1 1 1 1 1 1 0 0 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/random-double-data.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/random-double-data.txt new file mode 100644 index 0000000000000000000000000000000000000000..039ac506f5590f953ffc6598c11197d3fade2bbd --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/random-double-data.txt @@ -0,0 +1,100 @@ +1.172993630434470589e+02 1.905532343119886605e+02 2.613653823499444115e+02 1.570270816248337269e+02 2.373767637129340642e+02 2.175366144750510671e+02 2.609909144757107242e+02 2.086671686166440622e+02 2.674986450118991002e+02 1.395992762090408235e+02 1.115453060949917159e+02 1.531034842395609701e+02 2.621042034264289668e+02 2.958729454449504033e+02 2.137960368830719062e+02 2.606436280968571282e+02 2.492136530687155869e+02 2.770806237064748530e+02 2.667325121892417883e+02 2.909243437665674037e+02 1.570328417294508085e+02 1.738762543815240917e+02 1.514157955792608163e+02 2.264748814818163396e+02 1.911869834397498380e+02 2.083706054660671043e+02 2.778115921852293013e+02 1.330374814391803397e+02 2.988697222234711717e+02 2.534167825404447001e+02 +2.090964891529778242e+02 1.322006104643973003e+02 1.443415945355371832e+02 2.991388772264980389e+02 1.649302344777914868e+02 2.839528641910463875e+02 1.677159709681393736e+02 2.597553832458208944e+02 2.861055547321268477e+02 1.866431671806918189e+02 2.131812134614140177e+02 1.881465139477683124e+02 1.271865139985419262e+02 1.821608865941132649e+02 2.793653846657656459e+02 1.745982981552271838e+02 2.440893905635109888e+02 1.926469151980868446e+02 2.752453852984189098e+02 1.333479229516146347e+02 1.756311805755703404e+02 2.039367615619088383e+02 2.441861159155101575e+02 2.136111324500645594e+02 2.893808960992043922e+02 2.723220466017930335e+02 2.367879096909125565e+02 2.831541206793258425e+02 2.017643187924728068e+02 1.293072046241175030e+02 +2.311242818257193221e+02 2.180694109009666306e+02 2.728791416531455525e+02 1.239345918565636993e+02 2.885729762050686418e+02 2.082619393005260804e+02 2.331416004257805525e+02 1.003112528445347778e+02 2.796331120515330895e+02 2.804679740148056339e+02 2.466936828597247597e+02 1.422398585800914361e+02 1.312115029632765015e+02 1.324417143647877708e+02 2.161716508991076466e+02 1.791489656100356171e+02 2.239038785146145472e+02 2.456511993086799919e+02 2.885023077068626662e+02 2.127338775308419940e+02 2.468090724782538246e+02 2.704135008577740109e+02 1.144148504575758665e+02 1.641571759150080538e+02 2.473349551308716343e+02 2.366620528761779667e+02 1.208143167141831498e+02 1.403705034199327599e+02 2.061073908129479548e+02 1.482034962693051057e+02 +1.938319500339997035e+02 2.000523826243218650e+02 1.356134735235139317e+02 1.224357428573656250e+02 1.262840705282213918e+02 1.112797762573139977e+02 1.727826315738305993e+02 2.199559683100150664e+02 1.817290208723558180e+02 2.185579898773881951e+02 1.772844462934412491e+02 1.589145011846130728e+02 1.017520743541414703e+02 2.836990856171782980e+02 1.265544072638776640e+02 2.503473341476423855e+02 2.178539278172635534e+02 2.063574432066289432e+02 1.473169457524925861e+02 1.112719632489760784e+02 1.195996070145015722e+02 1.345099678548529312e+02 2.992645259487585463e+02 2.692242364540683752e+02 2.139649193607747861e+02 2.313659165106297451e+02 2.524185025119667785e+02 2.678714004815313388e+02 1.111457754393238702e+02 1.296443575800298902e+02 +1.183944097426736306e+02 2.750477277868330930e+02 1.688558971333346790e+02 1.432283295687057034e+02 2.226043174503911359e+02 1.825124733235978169e+02 1.806485153578007612e+02 2.270256019866706936e+02 2.852913053786990076e+02 2.867562520175486043e+02 2.795056496733417362e+02 1.142488895870292822e+02 1.502985045661773427e+02 2.246907359526948937e+02 2.051158858061974115e+02 2.663351441156772808e+02 2.864853431806749882e+02 2.276548949573071070e+02 2.678087640355958001e+02 2.266463576941352187e+02 1.886763304826383774e+02 1.150603609957262563e+02 1.596187994714221929e+02 1.844565420383776484e+02 1.730173420200940768e+02 1.427940137102308995e+02 1.774757620992130001e+02 2.563086691508434001e+02 1.666317348809653822e+02 1.878143419608473437e+02 +1.642344698640436036e+02 1.591648429561690818e+02 1.561851029939521140e+02 1.854367091922420059e+02 1.494951311500319093e+02 2.443780767043579942e+02 2.741090240793212160e+02 1.519200656263381006e+02 1.391711947382712538e+02 1.482414334940778815e+02 2.574425018646875287e+02 1.455120022089010945e+02 1.620904376421240727e+02 2.098493186451893848e+02 2.377904829227144887e+02 2.881187570801528750e+02 1.785609418793050054e+02 1.500483139796714340e+02 1.697371065898091729e+02 1.824143324642365087e+02 2.329862749140337712e+02 1.372006180078979298e+02 2.250666134242961789e+02 1.760894707637434067e+02 1.874161150869196035e+02 2.860410495381969440e+02 1.539271628213176086e+02 1.051658254213322152e+02 1.501619097950496666e+02 1.205717364486104515e+02 +1.275638286377957371e+02 2.620802183565458563e+02 2.290828196339760723e+02 2.591630015014513333e+02 2.102568650793322149e+02 2.385080320420775593e+02 2.683788150825365619e+02 1.808700201925492763e+02 1.972184450648797451e+02 2.382313686117472287e+02 1.733526990293641177e+02 2.369802981553972074e+02 1.835652530901061823e+02 1.274084560526275141e+02 2.403488205519001326e+02 2.713515297463850402e+02 1.455311801633137065e+02 1.889430214806582171e+02 1.676324321357484735e+02 2.327799977696781184e+02 2.846419393176552148e+02 1.510702433968490936e+02 1.361559014852734606e+02 1.732199851325496525e+02 2.451323003571785364e+02 1.833444866660036894e+02 2.451280287301300405e+02 1.669088211440060832e+02 2.768492228383354359e+02 2.445882168033535038e+02 +2.905092787520428601e+02 2.948076984760371033e+02 1.731080208454208673e+02 2.825532355845657548e+02 1.108820315678514845e+02 2.862013985457700755e+02 2.111453776876104769e+02 2.614428154999528147e+02 1.461523265575596042e+02 2.304914832379158156e+02 2.502987607420118934e+02 2.474276046141548875e+02 1.739607960146905725e+02 2.098700376203710789e+02 2.373226438948917121e+02 1.258493219462072119e+02 2.692932028872633055e+02 2.819145908444669999e+02 1.941653933285864468e+02 1.666395497972145847e+02 2.371919109091950588e+02 1.978302896313488191e+02 1.951483674191611613e+02 2.694357972099330141e+02 2.387068160427941450e+02 2.826084316255729618e+02 1.350954172043159929e+02 1.414479610501084039e+02 1.407657276334374501e+02 2.725513503737778365e+02 +2.055761393809777360e+02 1.070553196069381556e+02 1.045726024365074096e+02 1.611577217417760153e+02 1.258091705742062629e+02 1.038769334534844120e+02 2.956016304760584035e+02 1.586570076132481972e+02 1.636816353299032585e+02 2.375674325770941095e+02 2.085436646116971531e+02 2.088922128397473443e+02 2.316234644183506930e+02 2.623581653234684268e+02 1.714245300492981698e+02 2.844387943099641234e+02 1.469270259610659650e+02 1.157700922187784727e+02 2.367694595159086361e+02 1.548671738744121740e+02 2.013687686570863207e+02 1.860374943080277887e+02 1.733446602950305930e+02 2.488507085609763010e+02 2.929099979257852056e+02 1.825615338506695480e+02 1.338575452835397925e+02 1.491478381149757979e+02 1.116052925520655066e+02 2.341983606431906537e+02 +1.014445800974648222e+02 2.539987638010908597e+02 1.871788778457793399e+02 1.454231386314719998e+02 2.284640297096368045e+02 1.174773591296971915e+02 1.395683165851895637e+02 1.137193571402578414e+02 2.370662356797280950e+02 1.767292649815032064e+02 2.688513591587910696e+02 2.913902923086397436e+02 1.122392290694582897e+02 1.366157623619356229e+02 2.667409125457835444e+02 1.834435599491967537e+02 1.437174343391732236e+02 1.130622879516462120e+02 2.898543289046954214e+02 1.559795378531963479e+02 1.765577834073310157e+02 2.422955620302867885e+02 2.384835032255701321e+02 1.708163174135501094e+02 2.012159081107001839e+02 2.825663186839160517e+02 2.627299211659199045e+02 2.173916205317264883e+02 1.878835852278120910e+02 2.578733373077019451e+02 +2.843897417914848802e+02 2.685865547709703378e+02 2.810255710736182664e+02 2.572690897085278152e+02 2.416998564827035523e+02 1.770932574976374099e+02 2.021652319180342943e+02 1.414744641219446351e+02 1.464677002516696405e+02 1.831165552459343644e+02 1.157177632931430651e+02 2.625289386264841482e+02 2.972225480003540952e+02 1.024156386789293265e+02 2.305099741095138768e+02 2.241903749843916671e+02 1.157222019118702292e+02 1.533205318359311775e+02 1.179505454242311799e+02 2.666741766563739020e+02 2.792728900733587238e+02 1.222170248460037811e+02 2.573772727215269924e+02 1.535874607134987286e+02 1.231830862844115728e+02 2.584552954023608891e+02 2.541883057030129862e+02 1.001259630352790566e+02 2.332879439260797767e+02 2.240027888381033563e+02 +1.537092645679641123e+02 1.737278083620151392e+02 1.736358049797527201e+02 2.251608985235982630e+02 1.812387130195175473e+02 1.605621432944637377e+02 1.880655312831545700e+02 2.234500385148787700e+02 1.156918728696038272e+02 2.243685096423413654e+02 1.934342626327970720e+02 1.850952349553267027e+02 2.629944548485545965e+02 1.410418270562070973e+02 1.442479234012843960e+02 2.244518961458842909e+02 1.350755563946989923e+02 1.207094763037939913e+02 1.849900977633715797e+02 1.712315707730903398e+02 1.136025349108833495e+02 2.266901327137990734e+02 2.049289406654929735e+02 2.168279721613268407e+02 2.802488024880154285e+02 2.288593244920211873e+02 2.512942787545493957e+02 1.605416563468323261e+02 1.449848598254574483e+02 1.444073785399158396e+02 +1.576600406756634243e+02 1.316580100950168912e+02 2.530050469343043460e+02 1.319013133578224028e+02 2.708693079386434306e+02 1.256852413190491689e+02 1.471714019119002046e+02 1.119112141125198576e+02 1.482405279774543772e+02 2.151504825709631064e+02 1.449998801809978488e+02 2.163638771503673581e+02 1.272949254250747657e+02 2.476027791419436141e+02 2.891208457332292028e+02 2.642744540427622724e+02 1.972643066216432999e+02 2.480891057982425423e+02 1.265454595896786003e+02 2.957735252703171227e+02 1.831389323451852533e+02 2.674516147697771657e+02 1.404389674972707667e+02 1.350952754772052913e+02 2.169062951790871807e+02 2.445227715623778408e+02 1.771545655819627427e+02 2.729961759152714649e+02 2.655105689521545855e+02 1.887977700062222084e+02 +1.336462666694000632e+02 1.333709897858500995e+02 2.263366393511863350e+02 1.847175439991091821e+02 1.121699721143812383e+02 1.985314153845103533e+02 2.097626398761568396e+02 1.994292542548276970e+02 2.119822099620050722e+02 1.121578896112172430e+02 2.285640262135607372e+02 1.530452060058861719e+02 2.280757825791220625e+02 1.002584314437652893e+02 1.549763597162410349e+02 1.962603185897801836e+02 1.520023734031539107e+02 2.188357004065238129e+02 2.078620274892635678e+02 2.253215106546470281e+02 1.707542413836397373e+02 2.818584030117174279e+02 2.256862624833151472e+02 1.123882683852972377e+02 2.188298604829752776e+02 1.623779544769217296e+02 2.272253780943444212e+02 1.236449568833132560e+02 1.456708971140968174e+02 2.173334506159979753e+02 +1.355111076933105210e+02 2.882277378633141325e+02 1.458332953325788139e+02 2.038461345794760007e+02 2.077052275373579278e+02 2.430957456359013804e+02 2.398926697516154150e+02 1.861334604823129553e+02 1.056851094080089695e+02 1.250491536199931772e+02 1.475324860190441427e+02 2.446126161547439324e+02 2.283994822545897705e+02 1.411463500178549850e+02 1.017206978570942510e+02 2.805514386584911790e+02 1.128847993259780083e+02 2.326583828053989862e+02 1.968387029218569069e+02 2.013375618903088480e+02 2.981010702857409456e+02 1.018614681114941902e+02 1.799507821883679526e+02 1.133741465580100396e+02 1.235533581072856038e+02 1.980629645203880500e+02 2.289642287691829097e+02 1.596082722591768288e+02 1.905110471998515322e+02 1.789448781159623820e+02 +2.588286452268601465e+02 1.978130463173739599e+02 1.052689337312009599e+02 1.316763830509305251e+02 2.659236586726388509e+02 1.637014132384438767e+02 1.416031833329826668e+02 2.638665530652568236e+02 1.007257384115875425e+02 1.143900271701907769e+02 2.977834670475828602e+02 1.589765734727692745e+02 1.903975572290986520e+02 2.371635535037608804e+02 1.840341975670916668e+02 2.047003785265828242e+02 2.798969769773281655e+02 2.731706896262927557e+02 1.266878907904394254e+02 1.882415083052244427e+02 2.273996647906652129e+02 1.051754139634791869e+02 1.949647447346334843e+02 2.153583447980240919e+02 2.763468452623635585e+02 1.126493843527773322e+02 1.566047572050934491e+02 1.655928523150526246e+02 1.733528322945315949e+02 1.292815908595541146e+02 +1.453195062153936874e+02 1.443849872704900008e+02 2.393030362110915519e+02 2.203850914291498668e+02 2.628192548589183275e+02 1.142161203389242132e+02 2.954875947743198594e+02 1.914138981839176950e+02 1.956478457154231023e+02 1.282875398486639824e+02 2.801001077571227142e+02 2.478095646281364566e+02 2.467477848581343949e+02 2.819656424464902784e+02 2.951823714077539194e+02 1.777239847229775478e+02 1.197979896746704185e+02 1.481181033052623661e+02 1.906710229153984528e+02 2.142395628283543658e+02 2.300980272040501973e+02 2.228884003748859186e+02 2.473330601440014220e+02 1.391193242835927322e+02 2.836257563055140736e+02 1.510096324299383923e+02 2.202302141125946946e+02 1.931468179284185851e+02 1.332427495686727639e+02 2.591048546650930575e+02 +1.878681542531208208e+02 1.576240359584147654e+02 2.653849736815447500e+02 2.963544993865212973e+02 2.044592436730770828e+02 2.022626486161902903e+02 2.692262675681025144e+02 2.660999355751699227e+02 2.275843495473382347e+02 1.090849337992742818e+02 2.095602584555617227e+02 1.896271059113536808e+02 1.103822849104477513e+02 2.916911739044173260e+02 1.131212278363718582e+02 2.998892666268029643e+02 2.476782245756396605e+02 2.259689579913920738e+02 1.853942231198421950e+02 1.358270117521841200e+02 1.538630682720535674e+02 1.002148317174243601e+02 2.538393939061405433e+02 1.631649956267838206e+02 2.086654853664906000e+02 2.065167771482954322e+02 2.184161808630845485e+02 2.204789814939956045e+02 2.876785893506615821e+02 2.415299687386639675e+02 +2.578989465605797591e+02 2.309888943086805853e+02 2.139372792253111584e+02 1.438019921733897775e+02 2.686852572045135616e+02 1.347038004304963579e+02 2.662658866335509060e+02 2.378358170108797367e+02 2.901455078003721155e+02 2.653867524737770509e+02 1.011162296015096302e+02 1.236447329941733528e+02 2.440241295351771669e+02 1.285889645706482725e+02 1.234088480316093808e+02 2.765916670935633874e+02 1.132915304101479421e+02 2.967043774237617413e+02 2.960414394814537786e+02 1.923965028192617410e+02 2.177448618307050765e+02 2.328047369831131732e+02 1.702256773965170282e+02 2.320080409490440729e+02 2.962065584958517093e+02 1.421971909775941185e+02 1.416181340866144183e+02 2.318260414882616374e+02 1.990521696869427046e+02 1.291045564046920333e+02 +1.562042774178686386e+02 1.004265446278790392e+02 2.987714610921041185e+02 1.843637355858842284e+02 1.975513718825063165e+02 2.869996482942455032e+02 1.598134132589713943e+02 1.814921031876193638e+02 2.433389905907341983e+02 2.220363745053336970e+02 1.548306942100590504e+02 2.274512269554506361e+02 2.173006200058655963e+02 2.139515436667214772e+02 1.820439741095771353e+02 2.954110718222074183e+02 2.706126458816278273e+02 2.546812106115172583e+02 1.499899738326257363e+02 1.498010641912065921e+02 1.897725780579399668e+02 2.531561160917130167e+02 2.568891780637028432e+02 2.223136077092870551e+02 1.518604819103856585e+02 1.610422120589223027e+02 1.090455809489133259e+02 1.950503873748027388e+02 1.235704160644129388e+02 2.711492093024702967e+02 +2.039597038432034424e+02 2.026680584622021684e+02 1.365818873512059213e+02 2.909476552420245525e+02 1.721994194158640425e+02 1.854386667051114443e+02 2.287109571295530372e+02 1.912591665763447963e+02 1.607322994166321450e+02 2.949516230628389053e+02 2.522065912002103403e+02 1.869433122585654701e+02 1.235797649248940644e+02 1.522422059501078024e+02 2.738245135411146975e+02 1.059681837441489307e+02 1.013027238331489173e+02 1.660100598156148237e+02 2.454471731623151243e+02 2.467503196183328100e+02 2.584564749953993896e+02 2.079587352810677316e+02 1.650926041957846451e+02 2.269719270682073784e+02 2.376254891983122093e+02 1.510146656008620596e+02 2.672848371954185041e+02 2.692845974117340688e+02 2.180714754246087921e+02 2.186797802447831884e+02 +1.704231257711912519e+02 1.993416036368699906e+02 2.293703655438095268e+02 1.494582642918422266e+02 1.988970317734676030e+02 2.329763291241497711e+02 2.594871448385057420e+02 2.168089936885102134e+02 1.825320854593447280e+02 1.816754553181755796e+02 2.164740515812325725e+02 2.676208645391697019e+02 1.298365075936954725e+02 1.802664596093496243e+02 1.015344620621038132e+02 1.955048336384612639e+02 1.938953913674110083e+02 2.716932071347151805e+02 2.391085978949223829e+02 1.852300387899809380e+02 2.933293185307651356e+02 2.502753353909542966e+02 1.326128348575908262e+02 1.132638325194699433e+02 1.382024010322260494e+02 1.899310337488860796e+02 2.577639546186944699e+02 2.130234590296898887e+02 2.056292296528304746e+02 2.070746044453983927e+02 +2.712524956603344890e+02 1.103212761114690750e+02 1.501201791543782917e+02 1.588084859702673555e+02 1.780379814134324192e+02 1.938691258391782810e+02 1.322057441019641146e+02 1.105823874551086590e+02 2.879365916037821194e+02 2.457617763012990224e+02 1.036189749330240488e+02 1.682919366264929124e+02 2.271749409116763161e+02 2.468308259697249127e+02 2.530034131464132088e+02 2.481420904342841709e+02 1.546080547019561209e+02 1.278414739842506265e+02 2.234886960240669111e+02 2.535365186455997843e+02 1.599130733896959669e+02 1.151371295028686035e+02 2.378656188176093451e+02 2.901072209563180877e+02 2.524076257924749882e+02 2.849501171254129304e+02 1.802791659856764568e+02 1.527418387706650833e+02 2.578820596338672431e+02 1.208856989199291263e+02 +1.884906470590645711e+02 2.304295185581007672e+02 1.035923344330140736e+02 1.647061655195892627e+02 1.910201770870304472e+02 1.752788518438422614e+02 2.763014227316762117e+02 2.545709641405486252e+02 1.642694881393259152e+02 1.850698110761380804e+02 2.423689469305483328e+02 2.821007056776016384e+02 1.440765548977453250e+02 1.082195827231368952e+02 1.292487205530619008e+02 2.136496853657876613e+02 2.268509220579896635e+02 2.999629735037570981e+02 2.135306905316524535e+02 2.807718279523737692e+02 1.079256111018183759e+02 2.233050677333321801e+02 1.960571416898615951e+02 2.930642308139058514e+02 1.350490077967585307e+02 2.626074042719769750e+02 2.812196827814445328e+02 2.812753678081913336e+02 1.893738913514469004e+02 1.237248675858835725e+02 +2.024005284879252144e+02 2.663611407988397559e+02 2.687079844301063076e+02 1.583164038086077312e+02 1.451019436850150441e+02 1.100558451420041450e+02 2.083655450975085159e+02 2.034012033819327598e+02 2.745375932717230398e+02 1.454718097055225599e+02 1.519068131933423729e+02 2.522666952972969625e+02 2.409340029943109300e+02 1.697386944425205115e+02 1.092659514648129289e+02 2.785598218078254149e+02 1.404092026094307357e+02 2.152301424167146990e+02 1.170396027347833723e+02 2.495323893679063474e+02 2.070836095469416591e+02 2.187978925167305135e+02 1.478606128149070855e+02 1.189323178954538207e+02 2.012925160284665651e+02 2.080878545398990127e+02 1.510128433840351647e+02 1.657302151838663065e+02 2.177026636795220043e+02 1.221198981216710422e+02 +1.411258561955272341e+02 1.419717097672817374e+02 2.247481951315160984e+02 2.805973971111802712e+02 2.755562061324142178e+02 2.039769327420251557e+02 2.994080883760036045e+02 2.417843309736466040e+02 1.023751441731232319e+02 1.491356884971497152e+02 2.542464200475323821e+02 1.496044144381669128e+02 2.829129207809560285e+02 2.479316882407134699e+02 2.441205876677642550e+02 2.045492313770996020e+02 2.855582203360229414e+02 2.884005586284110336e+02 2.039668453101600676e+02 1.690279206477617890e+02 2.136822090795746760e+02 1.254275901194574772e+02 1.084851042192170922e+02 1.656011685190305229e+02 1.415195951026897774e+02 1.578115814760412263e+02 2.619737257057257693e+02 1.492347147839753347e+02 1.627213988646173561e+02 1.343297485726322691e+02 +2.544675070683062756e+02 1.367461330002975899e+02 2.928364121110963652e+02 2.024865028281971036e+02 2.758937379397792142e+02 1.293527538914390220e+02 1.003170531204512059e+02 1.514803620238746760e+02 2.603616046431354789e+02 1.790387290949859960e+02 1.954717187769221027e+02 1.325226280128280223e+02 1.522166198122710625e+02 1.162911821325583048e+02 2.798489406348742250e+02 2.521718932296424498e+02 2.622327475379161115e+02 1.027798265388270949e+02 2.437256510683693023e+02 1.911771820917219884e+02 2.722604457055863350e+02 2.850557929858495640e+02 1.953760157441756746e+02 2.473572905253965644e+02 1.891404804097296051e+02 1.514672503279451803e+02 2.213565012031598940e+02 2.253356064978207769e+02 2.044629345029305227e+02 2.805872739342098612e+02 +2.859142434488251183e+02 1.016009480575973356e+02 1.779351649172412522e+02 2.205171340775500539e+02 2.104472905774927369e+02 1.755755724600441567e+02 2.751836189782782185e+02 2.820692049982218350e+02 1.337557428916256015e+02 1.569761138230965969e+02 1.991757527032745543e+02 2.615974376894962461e+02 1.944849272958306017e+02 1.868411694165790777e+02 2.994394032068257729e+02 2.802783326794233290e+02 2.693871918204162625e+02 1.750293298802730249e+02 1.468161278725061720e+02 1.272003326865558108e+02 2.233103517167062932e+02 2.103066399402185027e+02 2.720825853079193735e+02 2.728915492341989193e+02 2.160004538807991992e+02 1.325145501710478015e+02 2.549827549782140466e+02 2.921469675413995901e+02 1.846231529604695822e+02 1.391152989663993651e+02 +2.538717579982014456e+02 1.450483481068324352e+02 2.720200816305956550e+02 1.120834821105324011e+02 1.703801876168104741e+02 1.091293661435919233e+02 1.410263490040598526e+02 1.910022197757120352e+02 2.505223413771657022e+02 2.069613533172621374e+02 1.367200764291426935e+02 1.269156762039037574e+02 1.459486945063737267e+02 1.585863332989725905e+02 1.433846106215619329e+02 2.893202513225785424e+02 1.754070497414596730e+02 1.678900237854272746e+02 2.363821059303507752e+02 1.088858921730617908e+02 1.962435837543239927e+02 2.151311182954276831e+02 1.943029551670006754e+02 1.670799798236046172e+02 1.348235227224938910e+02 2.005836112104490212e+02 2.601588534628079969e+02 1.194827586439497935e+02 2.131891535893303740e+02 1.835674362703964277e+02 +2.872207377280434457e+02 1.680389491751975299e+02 2.268072198735419533e+02 1.324343035526375729e+02 2.746241572770433095e+02 2.142161570690199710e+02 1.852290440736100550e+02 1.772431485621305285e+02 1.144750125154023266e+02 2.162070901557998468e+02 1.490690769171257557e+02 2.904041493178549445e+02 2.673617561413327621e+02 2.904362235840736730e+02 1.438791831406123833e+02 2.596893065528289526e+02 2.617155941751458386e+02 2.388486986717779246e+02 2.718819501315180105e+02 1.265484539827731680e+02 2.508989305854047700e+02 1.677208481362706323e+02 1.527665277518251230e+02 2.069026506407369084e+02 2.223100964495413336e+02 2.859845330217733022e+02 1.430291068893224349e+02 1.186508486537613436e+02 2.043257492072551713e+02 2.909823892985461953e+02 +2.385945641230763670e+02 2.011887933217761031e+02 1.622448188725907983e+02 1.738874847453056987e+02 1.669498482708885376e+02 1.853462372214463016e+02 1.514500885098960907e+02 1.569159134451362547e+02 2.521399095730983504e+02 1.246878140446721659e+02 1.758330561641313352e+02 2.722601647479554003e+02 1.679012078705679869e+02 1.710944469563905272e+02 2.012619557548435978e+02 2.130692925302264200e+02 2.489118511754019778e+02 1.553758318484749452e+02 2.531318516516165857e+02 1.895498740333992487e+02 2.010265603399928409e+02 1.805605111948569856e+02 2.471772127430102159e+02 2.822665908577009759e+02 1.256656757093761314e+02 1.218957078832023626e+02 2.851942693987446660e+02 2.434079459678487751e+02 2.183256665756584312e+02 1.881473862468819220e+02 +2.878274557836845133e+02 1.654481949983921254e+02 1.215681808546938214e+02 2.567820905945674781e+02 2.104106688330284101e+02 2.960796083414018085e+02 2.020680111052573693e+02 2.328934707961639106e+02 1.081575190462602336e+02 1.003340046261853189e+02 2.009697278729638299e+02 2.231963192062537757e+02 1.203849639323555323e+02 1.187994179134823156e+02 2.211937485225296030e+02 1.667300587261732119e+02 1.727379541915926211e+02 2.085029285798690353e+02 2.440827389167183981e+02 2.864522928573259151e+02 2.974890568790378893e+02 2.102945085846974393e+02 1.972598274048171447e+02 1.762889209976547136e+02 1.346946323322499666e+02 1.554434255958064170e+02 2.915634104756007901e+02 1.434053307556222876e+02 1.055800565037633163e+02 2.043924431141962259e+02 +1.494596010135965116e+02 1.369114048625681335e+02 1.414146701131132886e+02 1.383970135097982848e+02 1.734304788623498155e+02 1.594301265610334610e+02 1.040146208229407137e+02 2.208381597698417806e+02 2.904998286250861383e+02 1.300157615397056929e+02 2.667076669416877621e+02 1.062418844419948556e+02 2.717657999079561364e+02 1.054097765488278640e+02 2.401074677516734823e+02 1.045408432466875297e+02 1.330046749931937882e+02 2.297648034226271534e+02 1.488059718063634307e+02 1.725671935994615183e+02 1.330818497812682608e+02 2.341687919103425770e+02 2.983144736799429211e+02 2.798846823197050071e+02 2.218705077010061473e+02 2.681931695329894865e+02 2.339384973461015420e+02 2.893058480095726281e+02 1.539801301873031321e+02 2.746688360458649640e+02 +1.330701439354522222e+02 1.727884450558678395e+02 2.309082669627648272e+02 2.027633892073664299e+02 2.725503026364725656e+02 1.999882667367585896e+02 1.904108867169430255e+02 2.952458047945178805e+02 2.903769421220866320e+02 1.593020200554085477e+02 1.236139458806368623e+02 2.670862420061573062e+02 2.910830183895285472e+02 1.860711175093342149e+02 2.161724988935532963e+02 2.564488756979296795e+02 1.231566645138573648e+02 1.554206254375235403e+02 1.148558104746345521e+02 1.512714227454516163e+02 1.953024826710307025e+02 1.296022137194406127e+02 1.500450396815122076e+02 2.611742573447975246e+02 1.601671705158374550e+02 2.391666762859087214e+02 2.566415095930981352e+02 1.923304801412870404e+02 1.194174883996373353e+02 1.970722090829630986e+02 +1.912113734453868688e+02 1.498407015577022605e+02 2.038188614169363007e+02 1.315017316695561647e+02 2.564290419741012101e+02 1.890015309531812022e+02 2.451565642315005960e+02 2.794356592632736920e+02 2.286941218755985972e+02 1.959549984609147941e+02 1.183834182035568716e+02 2.102820643179567242e+02 1.748108698585573393e+02 1.534379248653211221e+02 1.919662859034699522e+02 1.273611408042816464e+02 1.848163823983119585e+02 1.719445827292381637e+02 1.098466009889928898e+02 2.781108902268393877e+02 2.089286134506138524e+02 2.324518337977864348e+02 1.983840049195213169e+02 1.897881971862217370e+02 1.057077761008814605e+02 2.693629461665184408e+02 1.359710117509105487e+02 2.191184409971657487e+02 1.295811391257115304e+02 1.272165218667991553e+02 +1.987244486959793903e+02 1.516360617950651317e+02 2.198509518241761498e+02 2.494181713303175911e+02 2.903223989223247372e+02 2.847249789220907132e+02 1.747037051964282171e+02 1.610307305098726829e+02 1.866621867053561061e+02 1.016530888490581503e+02 2.606194448419089440e+02 1.820037020201941402e+02 2.650669443765450524e+02 1.137210849453726098e+02 1.329244106101075715e+02 1.741312140090854257e+02 2.301425980066611885e+02 1.051708772384664030e+02 1.994040172335078864e+02 1.874773290907829733e+02 2.745616984783777070e+02 2.354781865911449756e+02 1.598287033335407159e+02 2.650689470710170212e+02 1.643692352330562017e+02 2.991199217036622713e+02 2.713535332162406348e+02 2.516280148665988463e+02 1.124367393830256532e+02 1.725070309959049837e+02 +1.637875882282461077e+02 1.407642428016634426e+02 2.759741260511348173e+02 1.982469453863400304e+02 2.966736241669494802e+02 2.756530253528777052e+02 1.426661371226006167e+02 1.585144634205103102e+02 2.836415355000413001e+02 2.468213340046699784e+02 2.898204535963063790e+02 1.711408259966125343e+02 1.900542569026269177e+02 1.112151031999617032e+02 2.679918109779015936e+02 2.737346364036235400e+02 2.597479311885246602e+02 1.719445390286030886e+02 2.361360157374418236e+02 1.123330408578339785e+02 1.214203690485689719e+02 2.552722899309185891e+02 2.436705678248840456e+02 1.596697357728296254e+02 2.533254006866929444e+02 2.066863222258713790e+02 1.194370826184286329e+02 2.943584774485435673e+02 1.636272134478143130e+02 1.191267138602315185e+02 +2.350924626651462006e+02 2.263138093076711357e+02 2.206572605284771385e+02 1.704171521239532296e+02 2.000250897638135257e+02 2.966317084215347109e+02 1.350543763227695138e+02 1.248113195978286285e+02 1.480602782771696297e+02 2.391913401309390679e+02 1.908758915801345779e+02 2.476074601271855045e+02 2.408834383325319095e+02 1.009169451940341560e+02 2.567526834523320645e+02 1.791854948779896688e+02 1.412277552146151152e+02 2.660711025781407670e+02 2.073940326990519054e+02 2.509760072499196610e+02 1.358593750308925223e+02 2.127422683140523532e+02 1.874643773621423293e+02 2.844455725631112273e+02 2.197223292953194118e+02 2.049519862750077266e+02 1.674367936692717365e+02 2.806316262053937294e+02 2.040091003350897836e+02 2.675290975004411962e+02 +1.483513543637005796e+02 2.384008274111940011e+02 2.834409911154408519e+02 1.344593118283445392e+02 2.346883831968173979e+02 1.381882879805813218e+02 1.241165074750676638e+02 2.186327911062819567e+02 2.466602279029802673e+02 1.573094529523951906e+02 1.568918412618390903e+02 2.289205163045023710e+02 1.170165333644822283e+02 1.742406104080407658e+02 2.082974381484526702e+02 1.600869123712819260e+02 2.399160913983472199e+02 2.877189278027444743e+02 2.845252294036096146e+02 2.342337907657317544e+02 1.496264758341107779e+02 2.905797831387872066e+02 2.824703799011629144e+02 1.047015685176013307e+02 1.056531628249932169e+02 2.778559625738202499e+02 1.693549799118289343e+02 1.654193764711911570e+02 1.062077606699500762e+02 1.159643419206647792e+02 +2.694780377267857716e+02 2.229138360502907403e+02 2.407432883969363218e+02 1.240072643521201741e+02 2.128611568148922970e+02 2.114050669978733481e+02 1.042337934877265297e+02 1.044783539591350490e+02 2.706611056394938259e+02 1.972285130309975898e+02 1.959046941044780681e+02 2.915493579522836853e+02 1.131994346897827342e+02 1.197362406389762839e+02 2.877593780027675621e+02 1.089470964294721824e+02 1.996015695685267417e+02 2.185569019121031999e+02 2.102686704320404374e+02 2.955299037924150980e+02 2.987478446256551479e+02 2.517129931888254646e+02 1.552463625479420557e+02 2.295020326441428153e+02 2.886454895961533111e+02 1.869792800456660871e+02 2.703426621835664037e+02 1.873514421416134326e+02 2.714620374401066556e+02 1.623625260081516331e+02 +1.457420078291350194e+02 1.926195242081234369e+02 1.841639049563959247e+02 1.397830290030836125e+02 1.287503203163068406e+02 1.684614546803193775e+02 2.820658047345126533e+02 2.986548244924653090e+02 2.631399932039782925e+02 2.870930868530864473e+02 1.141938207690214426e+02 2.868552010662050407e+02 2.019110175402121286e+02 2.840219745246005232e+02 2.848478851173646262e+02 1.902287203163165259e+02 2.696968940302964484e+02 1.690355482825476656e+02 2.171695948786692725e+02 1.960363641465239652e+02 2.930566891688549731e+02 1.380341365242818483e+02 1.769912313914243214e+02 1.164985277343077996e+02 2.079184380436491324e+02 2.871364788135472850e+02 1.796231479741346391e+02 1.115892945700443875e+02 1.922852518794877028e+02 1.851500906627327083e+02 +2.894943401361737187e+02 1.972990286414578804e+02 2.801948561309920933e+02 1.993490085147259947e+02 2.539099743775018112e+02 2.972486389690005240e+02 1.162404922698449354e+02 1.801898545246462504e+02 1.283416456049016858e+02 2.289248555429664407e+02 2.419505668531598985e+02 2.755101537543703216e+02 2.786083442131507013e+02 2.461931811431258552e+02 2.699066237266536064e+02 1.088542193903703179e+02 2.302113104476973149e+02 2.158136503417114227e+02 2.797451432348925096e+02 2.832754349673875822e+02 2.207567008139471909e+02 2.920947868166995249e+02 1.300092217647513735e+02 2.953259288980694350e+02 2.539624465668687492e+02 1.304833679125420645e+02 1.051395153781939484e+02 1.855592224876973830e+02 2.160289702497469477e+02 1.227895712666205981e+02 +1.029685235386965587e+02 1.410297052380113882e+02 1.832105986621241982e+02 1.016727951098498579e+02 2.130361696974732126e+02 1.817578553203918830e+02 2.644724203174304193e+02 1.713346250427240420e+02 1.297164370175517547e+02 1.072810924841072193e+02 1.083932811014470161e+02 2.860684171745337494e+02 2.893854146138399983e+02 1.677808320623732925e+02 2.343535290724524600e+02 1.209564642240636090e+02 1.329537830609780542e+02 2.924542956964438645e+02 2.733376468658280487e+02 1.397146179999238598e+02 1.103570089598620285e+02 2.231457082965310690e+02 1.056672424832338635e+02 2.887779644840117612e+02 1.127167878193751704e+02 1.387640376146708263e+02 1.791595456124304633e+02 2.709107895779202408e+02 2.238624693992912569e+02 1.773395240564728397e+02 +2.317578772498348769e+02 1.294950944138938667e+02 1.126253428029936572e+02 1.371351849575549693e+02 1.785990678455200964e+02 1.021081186758702444e+02 1.471984209931611360e+02 2.907355141803875540e+02 1.881128962816476644e+02 2.776434621780599628e+02 2.231668573818950279e+02 1.905362514139340817e+02 1.921875823712000226e+02 1.027725913116546792e+02 2.939602582690168902e+02 1.776540079128602656e+02 2.761214484196684111e+02 1.042033722248946646e+02 1.812858538041361385e+02 1.739774673118114663e+02 2.626640185867897799e+02 1.702975408841979288e+02 2.558138050153142729e+02 1.733257751657050392e+02 2.918973111180089859e+02 2.499103812623473857e+02 1.210050998380505973e+02 2.819910650801346605e+02 1.887952629909842699e+02 1.910084514453274380e+02 +2.212539479167726029e+02 2.774434360961662378e+02 2.337566454731646104e+02 2.345785537275947661e+02 2.365459264006348405e+02 1.983982238092833086e+02 2.030822332599765332e+02 1.995891111618029186e+02 2.834365683300363798e+02 1.036872616932399609e+02 2.192093181482490252e+02 2.601252995545215754e+02 2.498786393235831724e+02 2.102914196276636858e+02 1.344974807588668000e+02 2.319076536245909210e+02 2.769341510052834110e+02 2.705990780330756138e+02 1.679097240924248240e+02 2.394521666103182724e+02 2.042111123157340842e+02 1.679545908808316028e+02 1.638112120198904051e+02 2.498667640522866407e+02 1.298749690282424183e+02 2.953546510122243944e+02 2.420377599473625025e+02 1.972281420856064642e+02 1.511153679243939223e+02 1.785899871179086063e+02 +2.568297621323404201e+02 2.469847896802298237e+02 2.766623631158322496e+02 2.476135901735717937e+02 1.788596740963971570e+02 1.849716544556056874e+02 2.568516536462929594e+02 1.692762419184084877e+02 1.468834240718183537e+02 2.716053370235183593e+02 1.674083895790932957e+02 2.340636951853666687e+02 1.637725360284847227e+02 1.316562872243186177e+02 2.850086566701365882e+02 2.066513343106022944e+02 2.990778363456342390e+02 1.780020440519503495e+02 2.906711993591478631e+02 2.149926413975278479e+02 2.151504627144789765e+02 1.458362697904619836e+02 2.339644011324822657e+02 1.740513991402896181e+02 1.804876886135730842e+02 1.706585538790989176e+02 1.113370339871644603e+02 2.032819788543359039e+02 1.225434838619497526e+02 1.558188197132453183e+02 +2.752385657001058803e+02 1.704994416021052643e+02 1.607090409105587696e+02 2.031247490318933444e+02 1.333383797740430339e+02 1.922643047184382112e+02 2.665685682619526915e+02 2.611043497447243453e+02 2.444450591022788615e+02 1.012899678037660181e+02 2.236752860048796947e+02 1.164606756896235993e+02 1.768812782093617955e+02 2.532808672341815850e+02 1.308823477633827395e+02 1.683394957344131626e+02 1.787390150786144716e+02 1.962681762314343530e+02 1.178176219749694980e+02 2.151624908275416885e+02 2.951256579216935734e+02 2.058583926262361388e+02 2.348769662163374790e+02 2.500118096543036472e+02 2.065978549387351109e+02 1.732426267043477139e+02 2.575950640438621804e+02 1.826939497339359946e+02 1.586062531006688801e+02 1.141086110094916819e+02 +2.107478059550890066e+02 1.212326460542207940e+02 2.154852140069355073e+02 2.624147598788578648e+02 1.169795422214265699e+02 1.682202484364929660e+02 2.987700686247625299e+02 2.259973608163532504e+02 1.912690930240648015e+02 1.896338093439390775e+02 2.747727757049322008e+02 2.388804299971102978e+02 2.538821160842531128e+02 1.839990833334872491e+02 2.839611350159472067e+02 2.953225980324958755e+02 1.674336071760058076e+02 1.609172697163818953e+02 2.902596210806400450e+02 1.513824951234124114e+02 1.873458283487339600e+02 1.695960935104061491e+02 2.116215526550050470e+02 1.849422962892989233e+02 1.434256749723924713e+02 1.304784783123307079e+02 2.632948417544853328e+02 1.656472047377057777e+02 2.303125851744007377e+02 1.681993961373014486e+02 +1.104191565760665128e+02 1.750924257030650040e+02 1.242494131306669090e+02 1.541741282893887899e+02 2.585460716706878657e+02 2.286423505464783261e+02 1.890990979891397501e+02 2.707781238779197679e+02 2.619171833457787670e+02 2.695823002806438353e+02 1.941989480397771786e+02 1.389058748786196134e+02 1.283479072532797431e+02 2.347481590897206729e+02 1.518985431591505630e+02 1.757095590143896402e+02 2.225334593093496096e+02 2.231309387578290568e+02 1.039310896134069395e+02 2.614149485334186238e+02 2.212890027388380076e+02 1.425609106790709859e+02 1.376620423520403733e+02 2.403640719649376933e+02 1.152284694789922526e+02 2.108068210397188409e+02 2.526640691383259991e+02 2.323633859683563969e+02 2.720522122905912283e+02 2.498034621012949685e+02 +2.223449436042899947e+02 2.823923482876032267e+02 1.728419664392092727e+02 1.542710015610415724e+02 2.699062389875002737e+02 1.776741825057288793e+02 1.800001384193664080e+02 1.819433000632012636e+02 1.436484983468620840e+02 2.344086094824976954e+02 2.824459866922626361e+02 1.860318500101035681e+02 1.749968777772715498e+02 2.792448396035428004e+02 2.134719239619671498e+02 2.649346822194891047e+02 2.535109715864082602e+02 1.651109960016319178e+02 2.407385671793928736e+02 2.276937454871455770e+02 2.965404491761371446e+02 1.771850291606413634e+02 2.317902380753697855e+02 2.233400563607936817e+02 2.471010629200553694e+02 2.999085009765063319e+02 1.263611681933084725e+02 2.954593528043474180e+02 2.279026703099021915e+02 2.630592311905735414e+02 +1.662671322607742752e+02 1.600442354914371208e+02 2.476541290397616137e+02 1.471310870365195740e+02 2.302232198157895198e+02 2.833854716762933776e+02 1.464787719165046553e+02 1.913553080525503560e+02 1.014594285276723156e+02 2.182963956218923158e+02 1.629807715448000636e+02 2.692152036144454428e+02 2.287521686048013976e+02 2.982465613581407524e+02 1.646080094271899839e+02 1.685350412843276899e+02 2.638506951547767585e+02 2.931520510309920837e+02 1.395453733045734168e+02 2.192750645467382355e+02 1.118562057344099543e+02 2.210439168983162972e+02 1.977199388190010438e+02 2.248771354041466566e+02 2.967583759675493411e+02 1.144799677712354793e+02 2.877369511761256149e+02 2.831237961244747225e+02 2.909105411130262269e+02 2.550977837950437390e+02 +1.519738194711488006e+02 1.042788193386050608e+02 1.298121344332743377e+02 1.827398187867084971e+02 2.371985543371917800e+02 1.647119082252074236e+02 2.792046599520904238e+02 1.737333830141970452e+02 2.019611337599129968e+02 2.402390448779260623e+02 2.107045415433176174e+02 2.447101973248666411e+02 1.584507446746840174e+02 2.877533155913679366e+02 1.209142860803932251e+02 1.903846717728129931e+02 1.485923447895592631e+02 1.040627746119376695e+02 2.329784390325348795e+02 1.136264746597146882e+02 1.019818146651219024e+02 2.395077159260278847e+02 2.571474008697522322e+02 2.507839876514990465e+02 2.649762964978717719e+02 1.398370322453145889e+02 1.116668292809188614e+02 1.262068209877756289e+02 2.561228606182183967e+02 1.019925993853918413e+02 +2.525550526067758881e+02 2.649927164229666232e+02 1.457764901336312846e+02 1.519121804298574148e+02 1.112983565335166247e+02 2.979018464293943680e+02 2.517559946611144142e+02 1.257251989750113239e+02 2.377842966816966737e+02 2.692916709774201536e+02 1.558791612193160745e+02 2.988101508442036334e+02 1.264682305510686575e+02 2.586186621657187743e+02 2.397705732393993969e+02 1.799773948514575750e+02 2.289212202830902072e+02 2.551439950194432242e+02 2.270410183155361210e+02 2.624250216967006395e+02 2.894508375480465361e+02 1.106681053253299183e+02 1.696755343387707171e+02 2.302155275158106917e+02 1.445113211107399138e+02 1.886794441144848236e+02 2.129906512422033131e+02 2.340704769023953986e+02 1.082933010325512981e+02 1.977265970892881626e+02 +2.874406426475449052e+02 1.913451373833616742e+02 2.647704607931181044e+02 1.881279366057496532e+02 2.840067538093052804e+02 2.179159896935567247e+02 1.839859875309309132e+02 1.189702187115672132e+02 2.794517441847542614e+02 2.815599370853284427e+02 1.258259904677427699e+02 1.428483537633051412e+02 2.541426109645265967e+02 1.338781623221585164e+02 2.877181693280556374e+02 2.041742222547631513e+02 2.429167887622087392e+02 1.861891141000048435e+02 2.815058357304060337e+02 2.932279451804108703e+02 1.428092602118218792e+02 1.129541128601477595e+02 1.104970415865426503e+02 1.361068733124779726e+02 1.702082770497633533e+02 1.583852379729134157e+02 1.614070717213254511e+02 1.054529192214523476e+02 1.116913943762218366e+02 1.806474879921846366e+02 +1.904583320230821926e+02 1.477903225290235980e+02 2.926623631581093150e+02 2.267002240281469199e+02 1.643763662729302268e+02 2.199235242233247902e+02 1.853923849032223359e+02 2.941726936508506469e+02 2.665966841434134835e+02 1.199566433868006357e+02 2.951991052054676175e+02 1.594510101065885124e+02 1.458298791153635534e+02 1.532145001211049475e+02 1.411023254500616133e+02 2.140513226665028128e+02 1.678784758049908419e+02 1.708308530430679184e+02 2.099440033407245778e+02 2.664570659333852518e+02 2.959905162222905801e+02 2.829445582187913715e+02 2.588706049990775000e+02 1.722199615074994483e+02 2.869184560072056343e+02 1.681559218785307053e+02 1.503240659973911306e+02 2.588597461006905291e+02 2.678295026364270939e+02 2.154561503934444886e+02 +2.071927904539387839e+02 2.171736003654224305e+02 1.593735315924418785e+02 2.947356579175152547e+02 1.742775794491871011e+02 2.184611101357660914e+02 2.225198306238390842e+02 2.168369296352294668e+02 1.755672175076374231e+02 2.252214925755263835e+02 1.563369877784152209e+02 2.085332604119019209e+02 2.572482649031854862e+02 2.951800051631508950e+02 1.079183556031880329e+02 1.218838648771928774e+02 2.685371616407055626e+02 2.419162624723466877e+02 1.022244855205179022e+02 1.101224552326326602e+02 2.597819405832950679e+02 1.134555412120959517e+02 2.870491931154815575e+02 1.374365654160442318e+02 2.645641258978021142e+02 2.531141673781916666e+02 2.361747183362105886e+02 1.893108861581111171e+02 1.539026912190118139e+02 2.501170032332128415e+02 +2.547888423116186232e+02 1.853670755857669974e+02 1.389074705955763420e+02 2.709929622842061008e+02 1.228800068832790515e+02 2.778321736112652616e+02 1.309641642706778555e+02 1.156980811627219055e+02 1.431313378740429982e+02 1.646591400066212714e+02 1.920182917083556049e+02 2.178001706163468043e+02 2.235489712948179886e+02 1.079088316874027242e+02 2.447091545393394370e+02 2.320303973549428065e+02 2.359105911115680101e+02 2.382951907588607128e+02 1.062067779247245483e+02 2.905379355334102911e+02 2.023335418134440715e+02 2.128348219019524095e+02 2.865957710750057004e+02 1.782427960783044796e+02 2.856139874187100531e+02 1.139905905655008098e+02 2.264676166669663360e+02 2.479179013019825675e+02 1.746165350218777803e+02 2.255842464851874070e+02 +1.883869033800616819e+02 1.965817072065136699e+02 1.890868666652849015e+02 1.898737766004000491e+02 2.779218373710688184e+02 2.134628932560298722e+02 1.100835458783813436e+02 2.768750976313177148e+02 2.547073561014202880e+02 2.728160162818061281e+02 1.733645011505617504e+02 1.625036971255624394e+02 2.977754324167240156e+02 1.632372616873928450e+02 2.174045665187836107e+02 2.606964806055048030e+02 1.625508452643421720e+02 1.715067940576683441e+02 1.218481476549646629e+02 2.842560845538128547e+02 1.928678337146606623e+02 2.708765321293922739e+02 2.077020047066411621e+02 2.923591890868326004e+02 2.230876482822842206e+02 2.689925468225608256e+02 1.036588336737814586e+02 2.052618530546818363e+02 2.648220111560104897e+02 1.868396012623422280e+02 +1.785937212608853315e+02 2.973454718025594161e+02 2.368986004504845084e+02 1.146953890760472348e+02 1.265905165006724644e+02 2.255973396401841455e+02 2.163675674740596264e+02 1.527913853500098185e+02 2.283358642424602465e+02 2.759303134283557597e+02 2.876072117803540777e+02 2.029362495845153944e+02 1.212425121544320490e+02 1.100001317370093830e+02 2.335268996183764330e+02 2.375268130741384027e+02 2.336339660612213436e+02 2.462747325703657282e+02 2.841981652294566061e+02 1.081959034831858446e+02 1.291296469376330833e+02 2.602425849072438950e+02 2.575669438145553727e+02 2.135342654708205714e+02 2.294373105308322067e+02 2.706502840281193016e+02 2.928412927772634475e+02 1.330151104176747765e+02 1.533759962548247131e+02 2.744006234275867655e+02 +2.257735103076358882e+02 2.728385269717355186e+02 2.290872800510813363e+02 2.330934692803050154e+02 1.037274604992595215e+02 2.674079561164307961e+02 1.195755645916240866e+02 1.402804464035359047e+02 2.170516922702277611e+02 2.744725918691634661e+02 2.930458735600458908e+02 1.496408395971007224e+02 1.595562419103408729e+02 2.835538666488008630e+02 1.780163567793609332e+02 2.906408145890961237e+02 1.133853019218590248e+02 1.494630592331960770e+02 1.214592101712915451e+02 2.263015460193574881e+02 2.598100406717117608e+02 1.963383361449393192e+02 2.235083985338561376e+02 2.946475410923074492e+02 1.758055989844200724e+02 2.637780439251395137e+02 2.875400021086666698e+02 1.577781508415756662e+02 2.146553072676672684e+02 1.798181279868336446e+02 +2.620574340171276617e+02 2.153711882285265915e+02 2.245961661539886904e+02 2.054509343172356921e+02 2.926008719008261210e+02 2.432564531143420652e+02 2.303655720936658611e+02 1.615953803481287991e+02 2.918921003884012748e+02 2.760746977013722017e+02 1.909442200188182710e+02 1.596536528765051060e+02 2.491411570718119037e+02 2.924629085319008936e+02 2.587604848561293807e+02 1.524605619386706792e+02 2.737599884275671798e+02 2.090365453766356723e+02 1.610548024559351461e+02 1.018774121963877803e+02 2.410901898572944049e+02 1.875862586601133444e+02 2.588626077539996686e+02 2.579873618626863845e+02 2.838744453525392828e+02 2.580071516854936817e+02 2.114887112935771256e+02 2.675506009048368696e+02 1.260391751775616029e+02 1.858866479221875920e+02 +1.963224789638335892e+02 2.444908535968891954e+02 1.962779352478895589e+02 1.553096436749702889e+02 2.483662294276224429e+02 1.067992874414757978e+02 2.633849667942634483e+02 2.454321751613854588e+02 1.854433418739394028e+02 2.562889653665436072e+02 2.506342746416453622e+02 1.900819942764665598e+02 1.704565979131312474e+02 2.916979173024495822e+02 1.898592592817412310e+02 2.687872145548625440e+02 1.525347862509104004e+02 2.786582104923993484e+02 2.310813531087783872e+02 1.166208530157265386e+02 2.602471623613457723e+02 2.102772607982462034e+02 2.183751071150112466e+02 1.065011561509572999e+02 2.813176394708128782e+02 1.792292558016025623e+02 2.804083600455996361e+02 1.557890480883644102e+02 2.439522159916458861e+02 2.652201783594097719e+02 +1.425266334964659904e+02 2.075049705342416928e+02 1.704914602333145126e+02 1.886474594627911756e+02 1.252313163849750595e+02 2.836097447326676502e+02 1.406399617929505439e+02 2.414245225193989768e+02 2.576349788827002385e+02 1.486724691707949262e+02 1.092388214497626961e+02 1.685935770192617724e+02 2.033388664740227227e+02 1.390809359458484948e+02 1.056188661648174758e+02 2.350581131530574055e+02 1.964295662906907012e+02 2.578831766420791496e+02 1.109952979966328144e+02 2.027546721440710940e+02 2.501377690830167637e+02 2.111868593440530617e+02 2.324728205186171692e+02 2.453971856382445935e+02 1.723822394524685819e+02 2.872924628066301693e+02 1.140766727214026446e+02 2.221345013854892159e+02 1.728173248741775296e+02 2.676400838220500873e+02 +1.711571121866394947e+02 1.085759247733173396e+02 2.001753766691515750e+02 2.760446855018309407e+02 2.056587091496190567e+02 1.121827347031253197e+02 2.274644480946081444e+02 2.571858980756533128e+02 2.945439217283808375e+02 1.913312305877045674e+02 1.500446430731354894e+02 1.650397772114545489e+02 2.581660073502400792e+02 2.094009769144933273e+02 1.731816092302842094e+02 2.727903589313663133e+02 2.606648610353666982e+02 1.460656197586831695e+02 2.016951883706858268e+02 1.247477859691891240e+02 1.732157361502286221e+02 1.195560196858487245e+02 1.253893910664414904e+02 2.455457677441618216e+02 1.778732818035962850e+02 2.490436815297808266e+02 1.487573988963908960e+02 1.937302250034929898e+02 1.502426775501600389e+02 1.110841009912817583e+02 +2.382535443835092508e+02 1.972031918916456732e+02 2.576267295349729807e+02 1.730194312205534288e+02 1.301593684828995094e+02 1.624008376323430127e+02 2.060036399923972681e+02 1.233366573394677630e+02 2.194763391620297739e+02 1.701495187616251314e+02 1.223397596968992218e+02 1.987622577877627350e+02 2.511738650001373117e+02 2.130204435763062634e+02 1.993899817227978133e+02 1.597764561560970265e+02 1.205224890815559604e+02 2.184250491898233690e+02 1.755709834516516139e+02 2.741081010321077542e+02 2.104755291992826187e+02 2.698148014221883386e+02 1.299106544858947814e+02 2.008369880697999292e+02 2.938716155581552130e+02 2.671516623028076083e+02 1.332347035771324215e+02 1.291435420390463378e+02 1.835021202063177554e+02 2.002866194329941720e+02 +2.554906544300547182e+02 2.365682876454178540e+02 2.924004211094360244e+02 1.662852505275750730e+02 1.123350814405425808e+02 1.910015128879867632e+02 1.341551373493250594e+02 1.313122940860927770e+02 2.397311819484906152e+02 1.559268654058377024e+02 1.407120959783594003e+02 2.371419051640040152e+02 2.217591327496910480e+02 1.881187811266301537e+02 1.632462641154496907e+02 2.970940639140721373e+02 2.422917505999918433e+02 1.356966040631749593e+02 1.702398486895437486e+02 2.608644720933497183e+02 2.783751927848827563e+02 2.951746624002826138e+02 1.720706565846523688e+02 1.275268866601749096e+02 1.880990845238362681e+02 1.129502795714700625e+02 2.919985401845127626e+02 2.747497807112307555e+02 2.667734033775608395e+02 1.373740617490475699e+02 +2.115416415080857746e+02 1.431719947715498336e+02 1.718744824503889674e+02 1.075365968452523902e+02 2.220100335193473029e+02 1.965127222891928795e+02 1.062726056237197838e+02 2.631794488147562561e+02 1.658640190278337627e+02 1.169182569761068464e+02 1.645780782039788619e+02 2.940728738870184316e+02 2.979920277570993790e+02 2.125849825405138631e+02 1.533327700316632161e+02 2.655551337415409421e+02 1.329075684859120088e+02 2.686536376777100941e+02 2.299223677315555676e+02 2.123135030200585334e+02 1.474417961566917654e+02 2.899688778344954017e+02 1.439992490259426461e+02 1.606165457016644780e+02 2.854253601360321682e+02 2.837928223954166924e+02 1.868865943198568402e+02 1.809928275876523571e+02 1.583918020284682484e+02 2.384217495701244331e+02 +1.181670050605631417e+02 1.525653020190297582e+02 2.615084872177121724e+02 1.755024420886775829e+02 2.989795566898581001e+02 1.573585789513378188e+02 1.903575226478752711e+02 1.641861715477102166e+02 2.943146494922903003e+02 2.038802368327418719e+02 2.581560000437879694e+02 1.504995935930718076e+02 1.095655891680627008e+02 2.628623226127134558e+02 1.069018430130149255e+02 2.750818506761686422e+02 1.121786007219489818e+02 1.106710601660877415e+02 1.217291564359016149e+02 2.915199334459504144e+02 1.325859381653097557e+02 1.737237090326784141e+02 1.036075961875061751e+02 2.392327113385031510e+02 2.486092083099548233e+02 1.259492139939950306e+02 2.665249241620523435e+02 2.103119814995928039e+02 2.718465347096271216e+02 2.018653364759854298e+02 +2.085808638159350608e+02 2.977621083099649582e+02 1.394173606621695285e+02 2.232898484647512873e+02 1.347812725162832521e+02 1.574683348766579627e+02 1.827258429860655724e+02 2.827887224427595356e+02 2.608349632236463549e+02 2.370910079389979046e+02 2.033290260845359398e+02 1.566531500677691042e+02 2.982287288081304837e+02 2.998057140577807900e+02 1.906108269451214596e+02 2.023344526730545851e+02 1.717672594576409040e+02 2.093320563180507747e+02 2.649028095061802333e+02 2.840422446800275793e+02 2.111868958418739908e+02 1.803076798272542760e+02 2.311954915496957312e+02 1.563425451766251513e+02 2.610066662710300989e+02 1.855286443040786537e+02 1.478912573842241045e+02 2.544380211258828410e+02 2.799416317427427430e+02 2.238937193404353252e+02 +1.269470316997365131e+02 1.895539822645488357e+02 2.443421824114378467e+02 2.632321641240823737e+02 2.164919638664115951e+02 1.042697198382110884e+02 2.896061632271033659e+02 2.068164163046922681e+02 2.059671371408958294e+02 2.352532326493898722e+02 1.046233655847859296e+02 2.755187319279126541e+02 2.344641322699609987e+02 1.434858288567621969e+02 1.255438908126368176e+02 2.548141480364848803e+02 1.466719626681152704e+02 2.020892715394597872e+02 1.195107046056347713e+02 2.012968701954913797e+02 1.996902768982717191e+02 1.560547951636197013e+02 2.162555170020900164e+02 1.483278604161245084e+02 2.615607136845001151e+02 2.424344777210258997e+02 2.524090919470299070e+02 1.726167614603126026e+02 2.199373130240069258e+02 2.318614758097714912e+02 +1.590143031424979370e+02 1.933970326403360502e+02 1.227042846200323112e+02 2.107086401017011781e+02 2.844049872407889552e+02 1.420899421875644464e+02 1.736571760246831673e+02 1.130876049831349661e+02 1.470306210908964317e+02 2.959723384067232246e+02 1.438030965279091049e+02 1.685928342779160403e+02 1.351720793691902713e+02 1.909711091249450590e+02 1.477005416416634205e+02 1.010528808923594681e+02 2.205493627613245167e+02 2.367352422049318079e+02 1.224997665062844305e+02 1.620949451166091251e+02 1.270634404764108467e+02 2.673321646154778932e+02 1.618882934467209225e+02 1.208967331765591524e+02 2.073956586593529607e+02 1.223277950209799059e+02 2.625820210851194361e+02 2.262632377752408672e+02 2.222881433937307349e+02 1.716205611551696961e+02 +2.376094214038359667e+02 2.287867757784330820e+02 2.035778067022395703e+02 2.546588007138803391e+02 1.514832565507949198e+02 1.736683542684334327e+02 1.991020520349750598e+02 1.873563480883249213e+02 1.589186331386689801e+02 1.042563150975229149e+02 2.019924784676414902e+02 1.136537158101241971e+02 1.091264020137841158e+02 1.352770409719844054e+02 2.178414513482917414e+02 1.831380105899948489e+02 1.114225947990316570e+02 1.736029819106907439e+02 1.354612112967272424e+02 1.996055424300992627e+02 2.905125217944571432e+02 2.980326934372309893e+02 1.560898949881966473e+02 1.943286005606112212e+02 2.429797193518882636e+02 2.652714760000731076e+02 2.863852813340179182e+02 1.838252831614893239e+02 1.814799327205894315e+02 2.338290144642930954e+02 +2.526381992552952340e+02 2.089745531365245483e+02 1.869938021147821701e+02 2.864405091884094645e+02 1.736924996547539877e+02 1.479914815134324613e+02 2.132537252074255321e+02 1.830098172980584934e+02 2.476607236946428827e+02 1.066503395377639265e+02 1.405219898965278276e+02 2.743866427972425299e+02 2.269305408710248173e+02 2.791638036143738191e+02 1.824422387811073634e+02 1.852994662516045423e+02 2.777032940597408128e+02 2.109153407914434126e+02 2.214759900082639490e+02 1.857033490029854761e+02 1.302118293337227328e+02 1.889562709124264188e+02 1.844813915245081546e+02 2.875482403705134402e+02 2.022892465111445404e+02 2.230217175841083872e+02 2.843056043891419904e+02 2.350834055358549222e+02 2.080929758762673032e+02 2.770814576487081240e+02 +2.389430507965955428e+02 2.463651891862864147e+02 2.369578462650186452e+02 1.902366989508459199e+02 2.003468797600664004e+02 2.681735461841141728e+02 2.362787745532336601e+02 2.323782975776413480e+02 2.525302892415198812e+02 2.828059530799229151e+02 2.840327053185673662e+02 1.223941816187275435e+02 1.056255174412387134e+02 1.386503050117574105e+02 1.384325506562210535e+02 1.176641636239777426e+02 1.670688688422628161e+02 2.506322552784647826e+02 1.181229702988334083e+02 2.607048520072489737e+02 1.667476448166365515e+02 1.310085831735554223e+02 1.553111545647699927e+02 2.907454039462255651e+02 2.844644695877585718e+02 1.989933906493695019e+02 2.662036190025202131e+02 1.792754658114438371e+02 1.073664330563030944e+02 2.793141822468826376e+02 +2.640306978448612654e+02 2.458161373226257069e+02 1.015510894380497575e+02 1.527048938693112916e+02 2.893334394723561900e+02 2.994916089563248534e+02 1.054055716033572452e+02 2.278819528330843127e+02 1.890909183007994443e+02 2.134436011261824433e+02 2.654189934957544210e+02 1.780852604264427725e+02 2.222277079756825628e+02 2.689688042831336361e+02 2.232046857529678050e+02 1.778434593737022169e+02 1.336418515516146783e+02 2.739064893378349552e+02 2.065065746675076355e+02 1.329712924393647313e+02 2.176938186185978736e+02 1.918043587714230114e+02 2.280421349429639122e+02 1.182282112372680842e+02 1.370131137248831692e+02 1.716251366233928195e+02 2.412427837766657888e+02 2.738208811966829899e+02 1.471415247536169488e+02 1.638288393831292353e+02 +2.669085627842696908e+02 2.477147782526785136e+02 1.718200513884793565e+02 2.299346472745743597e+02 2.016242169414389309e+02 1.631378839470685307e+02 1.859938403107781255e+02 1.609729169019194330e+02 1.536303039404505171e+02 2.234728543554556950e+02 1.953401084257108096e+02 2.920381588589057174e+02 2.034966688752892310e+02 1.019427894404581139e+02 2.980736970140829953e+02 1.738263823108001418e+02 1.531314323312329293e+02 1.400030133312995702e+02 1.802287961283190043e+02 1.719909696301723443e+02 1.974918793689569725e+02 1.666882741246514001e+02 2.879569025675030502e+02 1.334044307903087088e+02 1.016937569869423896e+02 1.660343944328368764e+02 2.214967229035601974e+02 2.539424882366704992e+02 1.211914878013190133e+02 2.835892388637473687e+02 +1.704109091340931741e+02 1.337843054639438378e+02 1.570106251098002588e+02 2.123587857442842335e+02 2.788290802167920219e+02 2.795601449888932848e+02 1.220747715539721696e+02 1.179984498565524405e+02 1.552783750686872963e+02 1.257256444039083192e+02 2.312614004137946893e+02 1.971625968209403084e+02 1.208837070227885135e+02 2.231693789143681386e+02 2.332576722664892941e+02 1.659208209363902711e+02 1.979623049620595907e+02 2.497459328714609512e+02 2.540243570817084446e+02 1.309045902221261599e+02 2.376613837929333499e+02 2.140333351750954023e+02 2.231625169053620539e+02 2.869160136215916737e+02 1.282002159167354023e+02 1.029173927424986488e+02 2.432034421383394545e+02 1.495648010251883306e+02 1.971910657968611247e+02 1.358409247687675361e+02 +1.833826243837603442e+02 2.960483510370855811e+02 2.343723986770386318e+02 1.560358896543934293e+02 2.499669478251469172e+02 1.762005778153444169e+02 1.918050503412152921e+02 2.089352602085182866e+02 2.770127170480132008e+02 1.268157216157417224e+02 2.670673189640755822e+02 1.547628252866769287e+02 2.602514896343354849e+02 1.557532905756793866e+02 2.574076233589491949e+02 2.646855654359934533e+02 1.749681240869035719e+02 2.465698370051858035e+02 1.076897610845538082e+02 2.337637497458482301e+02 1.791847918196868932e+02 1.967068388721293104e+02 2.340964493346380095e+02 2.762770912600988140e+02 1.174465260954359564e+02 2.950490567997024982e+02 1.354710376622284116e+02 2.342233227246520642e+02 1.617966271393036379e+02 2.107879984327653915e+02 +2.493754578342164336e+02 2.275093847135933061e+02 1.466148442335522191e+02 2.261697123059220189e+02 1.213252451599347950e+02 1.628949300801819504e+02 2.100466501082228206e+02 1.508908296808102989e+02 1.488199564735201079e+02 1.727131563468088302e+02 2.306747713688439205e+02 2.570279850661015644e+02 2.309125192178541113e+02 2.422081718543400370e+02 1.769407234272878782e+02 2.688532243604371956e+02 2.276780878660686085e+02 1.065345319601523641e+02 1.535069430280279050e+02 1.717902253122074967e+02 2.876755354986605084e+02 1.683056100689713332e+02 1.120105413679224569e+02 1.755508096146901664e+02 2.095863991316655870e+02 1.523590730880595174e+02 2.944635547123552897e+02 1.444697311944634066e+02 2.165062978405008494e+02 1.410128743297030098e+02 +1.434402193906418006e+02 2.368914090178307106e+02 1.963465933374949941e+02 1.914557752364961516e+02 2.870767419320768568e+02 2.044699144835463187e+02 1.223520556576680036e+02 2.352284247043744472e+02 2.917945011866975165e+02 2.225925999946875322e+02 2.240309397680480288e+02 2.048455962243571093e+02 1.188048963943729035e+02 2.200553599997707579e+02 1.885605934416515765e+02 2.863412817843446874e+02 2.913876692311304737e+02 2.446563674684449552e+02 2.981153955140326843e+02 1.111775924383378253e+02 2.239868361016714857e+02 2.540473271011064469e+02 1.343930974769885438e+02 2.368686732696482409e+02 1.175691554116390591e+02 1.014879352562223715e+02 1.330784448687188046e+02 2.045426156006566885e+02 1.168174380391246245e+02 1.704438548713551995e+02 +2.696784010384477597e+02 2.991318545155386346e+02 2.120364825583467336e+02 1.950895785161033018e+02 1.216112431291165592e+02 2.438998438799096391e+02 1.588292735755803733e+02 2.347670069791354024e+02 1.862846309471772770e+02 2.258642611266068343e+02 1.423367506635381119e+02 2.692888471853933083e+02 2.950212092401994255e+02 2.331327670110776467e+02 1.542291422318579635e+02 2.809064569107727038e+02 2.358857646534314654e+02 2.378124255062788563e+02 2.664164586086786812e+02 1.387157904298663880e+02 2.297158046581682243e+02 2.386372312695162634e+02 1.246509391338716171e+02 2.338956320284196408e+02 1.820257170558419944e+02 1.957425768708682767e+02 1.680974560138464540e+02 1.288235048549348676e+02 1.483029350020115089e+02 1.744880718659300669e+02 +2.512494238114035738e+02 1.112846425403449615e+02 2.472643304237797395e+02 1.241745840646870818e+02 1.808849124644312099e+02 2.524760780760417731e+02 1.836118621524309447e+02 1.408362492891266982e+02 1.099623406752946693e+02 2.383967522197594064e+02 2.436606913384966049e+02 2.770699525768120566e+02 2.597573569531676867e+02 2.935649366424795517e+02 2.702790297508025219e+02 2.563597369995835606e+02 2.279477293752616447e+02 2.477470305460766440e+02 1.962131167814513333e+02 2.859744526791636190e+02 2.703401534622389590e+02 2.763052603711840902e+02 2.934416645125817809e+02 2.193475948646207030e+02 2.822891098008749395e+02 1.085391177109117820e+02 1.782208012387337703e+02 2.335496863699061976e+02 1.715066387390946829e+02 1.948062204233656303e+02 +2.879262290016004613e+02 1.676743911135137068e+02 1.403503828589753937e+02 2.744454339345198832e+02 2.935124358491533485e+02 2.920282649929100671e+02 1.390240222956847447e+02 2.426642861805074745e+02 1.217336684570653489e+02 1.311823750440439085e+02 1.647679902066092836e+02 2.962811279981685288e+02 2.945746172932865647e+02 2.005257587949587332e+02 2.072045953580022228e+02 2.893049469033056766e+02 1.913962360581630833e+02 1.823675529874825543e+02 1.830342103129283373e+02 1.222396004373517400e+02 2.248239872372262482e+02 1.170253438297526429e+02 2.853825568202013301e+02 2.214973458763422514e+02 2.563932510909227176e+02 2.144837192650675206e+02 1.793062298958048473e+02 2.920176466690815005e+02 1.515607839109829627e+02 1.981203765908239802e+02 +1.733053660232129403e+02 1.312183264386245583e+02 1.276233157677672807e+02 2.020942572504836789e+02 2.314817368496994732e+02 2.242589617101967008e+02 2.160504620978007893e+02 2.360595788588375399e+02 2.952977074031120992e+02 2.334652590044975682e+02 1.243453875174208747e+02 1.916144242306085630e+02 1.092365115042800596e+02 1.478765005471206280e+02 2.191946613400726278e+02 2.879274886834762697e+02 2.733443652356662597e+02 1.858481832262083344e+02 2.193747651131673706e+02 2.695165737089945424e+02 2.960753121523491700e+02 1.890691006834304631e+02 2.638343907584013550e+02 1.510492177865631334e+02 1.878288206285384661e+02 2.726561149875388992e+02 1.704246795027074199e+02 1.006381753343381718e+02 2.153734239260733148e+02 2.551451126036402854e+02 +1.591849792872858984e+02 1.304671215023752779e+02 1.427456440770346831e+02 2.882324895344759170e+02 1.680635293254793510e+02 1.205800311663507642e+02 2.861305963205076637e+02 1.219224106654408928e+02 2.467003871618023538e+02 2.830287806498602095e+02 1.445950870572595193e+02 2.496562286252286640e+02 1.464987579205844099e+02 2.848280464142704318e+02 2.785616857190397013e+02 1.837468579783306950e+02 1.246964377230690673e+02 1.251791080124520050e+02 1.496399061799681363e+02 1.375936265087168522e+02 2.547928467777094852e+02 2.554856419260690927e+02 1.285559318166884850e+02 2.092144446410586909e+02 2.868951534942014518e+02 1.178319347908447270e+02 1.347784205269015274e+02 2.851299399919766984e+02 1.754694686670390809e+02 1.016886128619324694e+02 +2.606618423405234353e+02 2.125366732076933545e+02 2.822772640751277322e+02 1.096405633955119185e+02 2.437561663288932721e+02 2.129146561548243994e+02 1.148823764090175530e+02 1.516868774610028368e+02 2.090025176018670265e+02 1.817684320186263562e+02 1.584667226055155709e+02 1.501973711988126468e+02 2.530199923706828713e+02 1.847948752811591930e+02 1.778871618489498303e+02 1.664551902511519188e+02 1.100020157933824265e+02 1.352000835393275509e+02 1.710981737682794801e+02 1.530513645967782566e+02 2.588476693974693035e+02 1.775587245068043956e+02 2.006331886716666588e+02 1.389709403689849694e+02 2.489553638298030194e+02 1.673604491791948021e+02 1.991154502489720812e+02 2.423848982654565418e+02 2.882603768001737308e+02 1.620650086718309240e+02 +2.723642490909132903e+02 1.680927290528325670e+02 1.005734627393615455e+02 1.598916606218045047e+02 1.672547346703738071e+02 2.361420151042074451e+02 2.741857058408131707e+02 2.533004150866734392e+02 2.036092771261417340e+02 1.091915011443997230e+02 1.145604210422382323e+02 1.209982156413156247e+02 2.749595368914399387e+02 2.177794513808643160e+02 2.054163746311436967e+02 2.185860861470465579e+02 1.504022045473846845e+02 1.713704456854883347e+02 2.175221629008602804e+02 1.230663148243889253e+02 2.419648244223723168e+02 1.383010418990747326e+02 2.040260833828849059e+02 2.966316994044250919e+02 1.630596872908637351e+02 2.562534082821714492e+02 2.549425872735235998e+02 1.983522705781282127e+02 1.524860865223137694e+02 2.736848821358530586e+02 +1.277021385004174192e+02 2.448445434866889343e+02 1.296687360965440803e+02 1.874271582575348702e+02 1.145742775945452792e+02 1.884744688522491742e+02 1.336298647132909423e+02 1.523816963142488419e+02 2.658270705367647224e+02 1.781637174983711134e+02 1.154610011723892171e+02 2.005342781476718415e+02 1.303166615041172918e+02 2.397284110571510496e+02 1.612912854182502542e+02 2.821645080329541315e+02 2.544831471501324813e+02 2.622237400581972224e+02 1.417212269902922230e+02 2.054005404298748658e+02 1.092142219674599062e+02 1.652051184306486107e+02 2.825679563619778492e+02 2.056286073102957630e+02 1.772062144904277545e+02 1.163520479257007310e+02 1.006186351926139366e+02 1.734025793931427586e+02 1.446958902579306709e+02 2.025820689614877779e+02 +1.798382687901162740e+02 1.604629760861514001e+02 2.668981169240885265e+02 2.763242846779806996e+02 1.318105471716862098e+02 2.191362245125996537e+02 2.770758446308884686e+02 2.308910816293108326e+02 2.956895796828827656e+02 1.566426856848869988e+02 2.326210561246332418e+02 1.206555816723871715e+02 2.603144096756907970e+02 1.172571782204154829e+02 2.219493974369055991e+02 2.385109304229506790e+02 2.599678734377965839e+02 2.850516346518521686e+02 1.472948582444382168e+02 2.234296740595885922e+02 1.427895312415343199e+02 2.848238578369252423e+02 2.260232767550441508e+02 1.544648385858973541e+02 1.163971462755376791e+02 1.762731012775239492e+02 1.089523563056807660e+02 1.663966154222005116e+02 1.342495772836978745e+02 2.922401077696804350e+02 +2.806557294060240224e+02 1.077657131130299604e+02 1.622983596366119059e+02 1.723469481204717795e+02 2.678046848873893850e+02 1.442059922525422451e+02 2.629931208031973711e+02 2.741083495447689415e+02 1.194142462414748707e+02 1.688961325073638022e+02 2.967954354880449728e+02 1.822107331135221671e+02 1.292333403080546645e+02 1.856814508383810391e+02 2.103923137448445573e+02 2.517859299913771451e+02 2.551152596962431574e+02 2.077883190793959898e+02 2.986930461834413677e+02 1.196764061335889551e+02 2.378823960447958257e+02 1.692017967083341432e+02 1.471250494556689432e+02 2.608355254883699672e+02 1.757172426071724942e+02 2.629426236813185369e+02 1.040244734248400533e+02 1.533558690719498827e+02 2.011860465194789072e+02 1.720545334339216765e+02 +2.966488050331527688e+02 1.809989340563203086e+02 1.871527370563514978e+02 2.315558973515319394e+02 2.657682292004950000e+02 2.237816732699509998e+02 2.282045922056215090e+02 1.846236325909775928e+02 1.644827554373339353e+02 2.760250360653360531e+02 2.492622345937652995e+02 1.483432536002697191e+02 1.527550390024584601e+02 1.573429964258168070e+02 2.090721206423400247e+02 2.535819867756219708e+02 2.420536340362719159e+02 1.691914404667937788e+02 2.388696721384086459e+02 2.593840245957078423e+02 1.331872961625781500e+02 1.116342264469163581e+02 1.680964276125217793e+02 1.555020753508222526e+02 2.422052215908822177e+02 2.626184375196450560e+02 2.674230788003709449e+02 1.948146659156083729e+02 2.663681889818526543e+02 2.795342087705012659e+02 +1.674728956867265310e+02 2.635505920196726493e+02 1.395353777027027604e+02 1.883233466008314565e+02 1.249441512057495913e+02 2.512189370435067417e+02 2.719913755602378842e+02 1.237326636617429614e+02 2.939951219495833357e+02 1.686366002602222807e+02 1.800181056076297068e+02 2.288525977776352818e+02 2.717306800175948638e+02 1.565292507387619594e+02 1.445460932655216766e+02 2.092313282690445249e+02 2.370375511382032698e+02 2.880525812713749474e+02 1.172567175017127141e+02 1.112412797274302250e+02 2.246954385922853135e+02 2.812359340959551446e+02 1.004168603505609241e+02 1.005387863078678805e+02 1.815971195408835683e+02 2.811251817522295937e+02 2.605765849402707772e+02 2.298114360271968621e+02 2.557293814584297706e+02 2.542416589790913122e+02 +2.943583269632734414e+02 1.442274778682184717e+02 2.700917391987959491e+02 2.527420049761408904e+02 1.527279900348522688e+02 1.841979337126335281e+02 2.902442440856567600e+02 2.889101481258517765e+02 1.828125218264408716e+02 1.133179379993730862e+02 1.484787634874768116e+02 2.676352293304336740e+02 1.452118425579454311e+02 2.636966617786087568e+02 1.313546620759107100e+02 1.834019443937838787e+02 2.892465421328221282e+02 2.575015388377624959e+02 1.970702343003932242e+02 2.507528167727347181e+02 1.724897096143170074e+02 2.664268628760375464e+02 1.365257050051324370e+02 1.198011035974838308e+02 1.176831988053894520e+02 1.070946883963453899e+02 1.964638491125322446e+02 2.570844982939356100e+02 1.593905150913052466e+02 1.202569936867807598e+02 +2.734271498156417692e+02 2.352133531486530842e+02 2.590835237087205769e+02 2.260994493040042528e+02 1.805421354394846105e+02 2.728408805160995598e+02 2.367263522625478913e+02 2.580210451062748689e+02 1.204524877415260562e+02 2.946465680607327613e+02 1.547220269335912803e+02 1.186203172746691337e+02 1.923878728892914864e+02 1.094127410697402354e+02 2.222837240826847278e+02 1.529333599077602628e+02 1.861450256630199647e+02 2.125583079944122176e+02 1.527591657960447264e+02 2.694001797345342766e+02 1.986063989766776388e+02 2.192493126389772442e+02 2.986827335637019587e+02 2.790660387254000625e+02 2.781487003899754313e+02 2.564198676846006606e+02 2.597551240338123648e+02 2.358970425952163907e+02 1.951628676328612357e+02 1.078208269500064347e+02 +1.190762776130697205e+02 2.951075493308472346e+02 1.091043363430719069e+02 2.824365312299846664e+02 2.445811468414383398e+02 2.538090805786315514e+02 1.230092364266577363e+02 2.633887649939744051e+02 1.865216093980499181e+02 1.540388898662323243e+02 2.047343894245035756e+02 1.431412534309083640e+02 2.857794001060171922e+02 1.492366175285521592e+02 1.380934567887849198e+02 1.331831467466375898e+02 1.149412013934811796e+02 2.205070844660474734e+02 2.939252657951740844e+02 2.049464694042562769e+02 2.047902832862141054e+02 1.810793422252176015e+02 2.005356992447976836e+02 1.381400138775680375e+02 2.582445444487385657e+02 1.698212931623984616e+02 2.252085951830697468e+02 1.808378144669676999e+02 1.307311344108444473e+02 1.050024101356033697e+02 +1.722314120162143354e+02 2.530014253763471856e+02 1.298340795948372772e+02 2.948664870226410812e+02 2.383106068289312702e+02 1.822969205106659558e+02 2.285226769051377005e+02 2.759417691711663565e+02 2.120970517474504220e+02 2.831046044310812704e+02 2.320579821788242612e+02 1.286125039667014960e+02 1.609837368065715282e+02 2.931112965353385107e+02 1.441758663366052531e+02 2.810263276191118962e+02 1.239857273771131077e+02 2.399447548605567988e+02 1.460208836055017514e+02 1.205325462037979491e+02 2.112513935912650993e+02 1.036793750016967692e+02 1.113202625217208777e+02 1.646612561683649574e+02 1.018350908838390581e+02 1.263835026124204859e+02 2.766683711501553944e+02 1.682407929561517506e+02 2.677103056024840271e+02 2.147294480454548307e+02 +2.763536852866382105e+02 1.511976958084401872e+02 1.026794659371155944e+02 1.805990415690671398e+02 2.442493962549426385e+02 1.881796213041043018e+02 1.028768312506858535e+02 2.787706953534510603e+02 2.589640601731795755e+02 1.730107396932538677e+02 2.218419822849910190e+02 2.651646152747807719e+02 1.476149140151474342e+02 1.986450675254654072e+02 1.050693447352362853e+02 1.819666738706916931e+02 2.873544952103893593e+02 1.472060704631180954e+02 1.297023844405691761e+02 2.824778443572924971e+02 2.918073394139615289e+02 2.128134400148996974e+02 2.223096450508596149e+02 2.761940547406351811e+02 1.348708672340777639e+02 1.857009592938832441e+02 1.062906640064134649e+02 2.104442283262811202e+02 2.812954268214299418e+02 2.739038950945439979e+02 +1.837264129055918147e+02 2.399207190527903322e+02 2.843910623120511900e+02 1.773207161532972975e+02 2.056581469496123873e+02 1.558029517788254168e+02 1.458438122541016924e+02 1.893030782939712253e+02 1.139027557376393673e+02 2.228775749423569437e+02 1.367670384452707140e+02 2.854480456674787092e+02 2.424985140340279202e+02 2.940521113211518696e+02 1.330693282221190259e+02 1.212599008475133076e+02 2.754747741586869552e+02 1.062856492128348549e+02 1.212724485003486166e+02 2.100514698158626743e+02 2.547262582240854272e+02 1.999488755181088777e+02 2.578561029518564283e+02 2.784200494851090752e+02 2.728829168298310606e+02 2.071711407548560544e+02 1.708729380756020362e+02 2.726254883308487251e+02 1.104364015278258364e+02 1.175773277008901090e+02 +2.554381337818412305e+02 1.634513906120204183e+02 2.309962436793083214e+02 2.460443770945291249e+02 1.618890365991254896e+02 1.046310291743186980e+02 2.772116654811295575e+02 2.098555252827713957e+02 2.309383801112169863e+02 2.845300950466865402e+02 1.268119123926061320e+02 1.697885006171669602e+02 1.901887742560337529e+02 2.605757830463372215e+02 2.755463791239279772e+02 1.771647294768940810e+02 2.403902735905423356e+02 1.774352552408031443e+02 1.796883744424403631e+02 2.736192366006921475e+02 2.118505050785533967e+02 1.873353967662169453e+02 1.802980863638028950e+02 1.869858546159753132e+02 1.200946851663063342e+02 2.350811068219035178e+02 2.018941614745772313e+02 1.010158706413519525e+02 1.661546933057649937e+02 2.570882207683835077e+02 +2.856134023048114159e+02 1.356279054667102741e+02 1.225310201562991494e+02 1.529777144242077327e+02 2.936506440162480658e+02 2.589580133771784176e+02 1.864782805190425279e+02 1.931182124516369640e+02 2.913608028278327993e+02 1.555662042949096531e+02 1.173676742008071301e+02 2.242990267171766732e+02 2.651338851871976203e+02 1.128980005738893482e+02 1.283582653966309408e+02 2.071495534530326097e+02 1.241509031508031740e+02 2.393403040292282640e+02 2.829812266966206380e+02 2.294799861563923287e+02 2.129576840814710295e+02 2.165539860914115877e+02 1.357366103660294243e+02 2.396252028023287153e+02 1.395106368224716107e+02 1.700689743264745744e+02 1.253435651632085950e+02 1.508112259783626428e+02 2.310267786371028933e+02 2.311667616985857876e+02 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/random-int-data.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/random-int-data.txt new file mode 100644 index 0000000000000000000000000000000000000000..4fd11b7509e65b01393a6af6125d1b304d524bd7 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/random-int-data.txt @@ -0,0 +1,100 @@ +-67 65 82 64 51 1 -12 2 -84 -52 12 82 -45 -84 -41 31 -49 36 -70 40 -74 -99 32 64 -6 43 -53 -43 43 96 +-58 20 25 99 -25 78 -6 59 -23 30 36 25 -8 83 -43 -7 -8 42 -90 96 46 88 31 12 68 -21 -6 7 78 -19 +-66 -51 0 13 42 -43 -30 -29 20 10 -24 -5 -42 38 -56 6 1 -80 -65 -91 89 64 -21 49 -84 41 6 -78 71 -2 +-50 -84 -50 -66 46 -88 -10 -28 -25 6 -7 10 -35 86 41 -17 72 -67 13 -67 -76 -84 -15 35 67 40 90 38 -1 -47 +-51 27 -48 26 -73 -46 -68 -56 -38 -4 49 -64 57 -86 -80 70 50 34 84 97 -76 3 -54 -89 -7 -53 15 36 -28 85 +2 -59 4 30 70 -42 -26 -1 27 -90 -18 95 -10 -36 43 24 86 -8 -100 92 80 -40 17 -93 -81 54 -8 84 -53 38 +-80 0 -71 -41 -33 9 -61 0 26 80 64 67 74 68 -72 78 -72 -52 -19 37 -33 -24 -11 -71 -53 -16 25 56 -74 0 +71 -23 49 -36 -43 -70 82 69 -100 -27 50 20 30 84 -33 90 49 39 -52 -51 -86 -76 -72 -88 12 91 -96 -61 -87 -47 +21 39 1 78 68 -80 -54 71 17 -94 34 -20 14 -5 -24 55 -84 -50 -90 -24 -79 -81 53 -50 22 -13 -92 78 -22 -50 +-47 -73 77 -93 -20 51 -37 -14 -37 -18 -8 -14 -71 29 -27 -5 54 77 -7 -2 15 -23 98 -34 -65 -78 -77 -90 -5 -35 +92 -33 71 24 43 -19 50 -40 -48 -33 -51 -14 23 40 -78 -14 -76 1 52 69 93 5 -13 30 -60 -20 -54 49 -52 93 +32 -86 21 -41 -86 -38 97 -35 -37 -89 -15 -18 -46 -37 8 63 -63 -61 57 50 43 -27 -45 98 -56 -81 16 -38 -25 -28 +-18 19 -52 -86 92 -72 23 35 20 57 69 -22 52 -66 -74 -29 -1 -10 -97 22 -97 -93 -70 87 85 -31 42 -29 -10 -36 +78 80 -93 68 41 84 -37 -62 38 -9 99 -60 90 47 -33 -40 -59 97 -28 9 35 -6 -60 -83 -39 -97 -25 -78 95 40 +79 -35 -45 -46 69 10 29 -88 98 -44 66 11 45 -58 -11 -25 51 -44 54 30 59 98 35 -28 93 86 99 19 -27 -83 +80 77 -72 57 -35 -27 86 -67 11 77 -28 -89 -30 -31 -72 64 -95 -75 92 -32 -96 -14 6 -83 -66 -58 71 -17 58 -53 +-1 17 -72 82 -57 -48 -7 -44 -80 85 -99 -9 27 -11 24 13 86 18 67 -9 12 77 98 49 49 12 -82 45 31 -68 +-13 -75 -26 17 91 12 -95 -62 -54 -60 22 50 86 58 -11 -11 -21 31 16 -15 67 90 1 80 -57 -98 35 -54 51 91 +28 -75 -31 49 0 73 75 -66 50 -77 -20 82 -40 -90 -28 32 -44 89 -75 -33 -11 -19 -55 79 18 2 -39 -49 78 -72 +14 56 78 69 -40 -20 -39 71 99 -89 60 -82 -1 -77 -42 94 -41 35 72 11 -13 89 -52 -41 -93 43 -39 -61 68 -4 +88 18 -90 -75 -49 46 -28 -48 -69 -64 77 -8 91 -65 62 -27 -19 34 10 78 82 49 -34 63 78 -88 -17 -37 -85 91 +4 36 -77 -75 -12 70 42 8 7 -31 -69 -74 -65 18 85 -92 91 16 -15 24 -74 -56 71 -70 -90 20 13 73 -68 -65 +92 22 -31 -73 -59 -78 -20 -11 -61 36 -40 34 -96 -12 51 -45 -12 12 -3 -42 -71 68 -8 -91 50 -73 -96 -46 -38 -4 +-87 44 -58 -83 70 -81 32 29 -79 45 -64 -52 57 73 -80 69 7 -22 31 -71 -34 -33 47 79 -17 6 -77 -89 3 50 +85 2 73 -88 -99 -13 -76 1 -90 51 30 -52 75 -2 -8 10 -83 -40 -5 -79 82 19 79 94 49 4 66 -76 6 -48 +29 -34 66 -93 45 -1 -98 92 -92 29 -10 64 -23 -81 -73 -62 -18 37 -29 -50 -52 90 -28 24 -4 -67 -33 25 -78 93 +57 -46 36 -16 34 -59 -96 -86 64 2 28 42 -32 6 -17 37 38 -40 -92 55 -22 -42 11 -77 12 81 -89 -39 -30 -39 +-72 -68 -41 -5 93 55 24 -6 84 77 30 33 -51 -62 6 -5 -83 60 -1 -64 7 -7 -92 31 5 -21 -34 -14 21 -33 +26 -75 -36 -54 -21 -38 -49 -20 82 73 -84 -5 -69 84 -87 12 7 -67 -40 -50 -35 -65 80 -83 -2 1 34 -16 91 82 +61 -21 1 -64 -56 -61 74 16 0 38 51 34 -35 37 -28 -52 -14 61 14 58 50 27 -43 -27 14 56 -16 -78 50 -89 +45 -47 -61 68 -41 -70 14 -51 49 -84 64 -65 88 -39 -88 28 -55 -18 81 -2 -1 -45 65 -6 62 16 71 71 -1 47 +47 60 22 -42 -5 -74 12 66 89 -82 -85 65 74 0 -18 56 -39 84 -65 -42 -33 -60 23 33 -8 -72 3 -64 -3 -25 +-70 11 -19 -12 -1 -50 -89 -61 78 28 55 92 -17 86 -17 -45 -31 68 -24 -99 -59 27 79 -2 21 -80 54 9 14 -70 +-38 52 -99 50 -46 -63 -74 -41 -43 -62 -81 38 -99 17 -94 -6 44 -20 -13 -30 71 -43 43 -28 -8 57 -93 98 4 42 +-17 -27 -60 -22 86 -49 39 -83 72 -16 82 74 73 -29 16 -59 81 -60 -96 51 -62 -55 -79 -31 -15 -67 -18 -83 -61 -86 +28 37 -44 7 -17 -10 -65 8 -78 -17 -46 -5 -35 -86 13 -16 27 24 60 -12 -48 -45 16 -33 70 -45 -63 -60 21 70 +-75 -89 -93 -93 62 -44 -39 46 31 57 72 30 -65 29 66 -53 2 -2 71 -90 -73 -40 -63 32 68 30 25 98 38 92 +88 3 5 73 -2 -61 -94 79 99 94 71 -83 -40 80 -79 -14 -34 -99 -52 27 23 13 13 -35 -74 13 43 -19 2 -62 +92 -47 -27 9 -68 -86 -57 43 9 -81 -9 69 52 -28 80 -13 -6 -44 -81 -89 -10 30 -64 86 -76 -11 -100 15 12 -62 +76 -42 39 70 74 79 84 -52 18 -58 78 53 89 58 -32 20 -51 35 12 37 -70 -21 5 97 67 -25 -25 -10 2 30 +-84 26 -60 -34 11 -27 47 85 -89 29 54 -53 66 -9 12 4 92 70 2 -12 -55 72 -62 -79 -8 68 -19 12 -8 -100 +78 -97 -76 86 -47 42 99 -3 9 49 -84 86 26 43 -26 90 23 -66 -37 -35 25 -12 -42 -12 96 -15 48 87 -95 -12 +-60 57 -30 -4 -84 24 -82 -5 34 56 76 81 -64 23 32 34 -41 -48 -6 77 -42 64 87 92 82 59 9 -71 -56 -45 +-74 -90 -27 93 33 15 -35 -73 78 23 17 -28 9 63 9 35 15 32 0 -4 -32 54 -76 14 -14 -8 16 -43 -81 57 +-2 22 85 -33 -48 74 64 -59 -27 17 -65 27 -50 -81 41 -69 -26 -29 -83 48 -81 51 58 -62 -63 -55 -63 39 32 -34 +98 -99 13 25 -10 43 -62 50 82 -90 -51 40 -71 82 27 -73 19 -62 37 10 -21 45 -94 -45 -41 -3 44 86 -2 27 +-80 -89 -57 87 -42 19 32 -49 37 -4 -30 54 46 -3 -92 89 60 37 -86 38 61 93 45 -45 -86 54 21 45 50 -53 +7 -68 71 -6 41 -72 67 45 15 46 85 59 82 19 65 75 -62 -35 47 -51 23 41 -54 27 -99 14 9 69 60 62 +99 -51 83 -47 -19 -57 -22 51 -52 52 92 80 69 1 -31 0 -19 -54 73 -5 3 82 -86 -84 -95 -83 -92 -52 -90 -79 +43 -75 62 99 66 -43 -38 -21 23 35 -63 -61 -46 5 3 -90 -28 55 87 89 -29 -46 23 -61 -5 10 -70 -63 50 -14 +39 38 10 66 -24 -45 55 -33 31 29 44 31 73 44 6 69 -21 -58 -3 93 -51 86 -16 -88 88 -30 75 78 -20 -12 +-11 11 -19 40 82 6 10 22 90 -78 -88 -49 72 69 -62 42 -23 22 -38 -98 0 -3 -43 20 9 18 -67 -7 22 21 +99 80 -55 74 43 -31 60 -26 -29 -6 75 60 92 -42 85 18 1 1 -74 -44 -12 72 -57 -98 99 62 45 -40 -39 -75 +50 30 -18 -29 -80 -59 -96 46 -99 -76 -13 -75 -93 -95 -45 62 -37 53 -96 57 -40 3 14 -45 -84 58 75 16 37 -6 +1 -47 87 -99 -22 -22 -20 71 -91 13 35 -80 75 65 -87 16 -37 99 -60 49 52 18 55 -11 18 24 -65 -80 8 -79 +-8 -87 86 -9 -64 -76 59 -52 -89 18 13 70 44 93 99 62 39 49 83 28 72 -71 -13 -71 -22 44 -87 73 -68 80 +41 -26 44 -63 -26 -83 -44 63 -51 -48 52 -8 55 73 -45 84 40 45 32 -34 -78 -46 -79 57 -40 11 34 -75 -20 91 +94 9 -35 -5 3 59 -63 2 -7 -72 -34 -70 78 99 -29 37 11 91 61 29 85 -15 59 79 47 41 19 -18 -92 47 +-59 -89 57 -72 -79 88 -85 18 -35 -96 -57 33 83 70 -55 -16 -21 72 -53 89 -44 -86 9 -44 -26 78 2 -93 -75 6 +55 73 89 80 -69 -93 -39 -88 62 49 91 -68 87 -26 40 16 -49 -53 -57 23 -97 39 -78 44 -15 1 60 -87 43 -42 +-2 -23 -74 -80 -59 52 -58 68 64 97 -86 -41 -88 35 49 3 -40 90 34 -2 3 13 -95 8 -1 6 75 92 19 -31 +57 76 65 3 37 -72 -43 57 64 -23 41 87 26 76 -18 -32 28 47 11 47 -33 -12 4 81 -92 -47 -81 43 -2 5 +68 74 66 -89 -95 -40 -78 -58 -54 -20 2 20 94 -35 58 -20 41 77 0 95 39 14 36 -40 -85 -60 -63 82 0 58 +-61 -99 61 10 -2 -31 -70 37 -77 -10 85 95 -28 70 -81 -78 -68 -33 -77 77 -6 42 -100 -68 -59 -86 -42 -74 35 -32 +64 -1 -1 -64 51 11 -65 47 -87 -8 5 58 22 -80 68 -25 24 59 -25 -75 95 -22 -73 27 86 -39 -98 -1 -17 -32 +94 -50 -53 -62 -53 46 50 38 -95 -77 40 -38 -23 -14 -68 -20 -47 23 -8 -12 -92 -69 -97 30 94 -45 47 -81 82 -60 +28 67 -48 4 74 27 -30 12 -32 35 91 -83 30 -55 -7 79 97 11 93 -45 -79 31 78 65 84 -23 -26 17 -61 43 +44 60 -88 72 31 98 55 -4 66 -14 10 -81 -40 66 -15 21 69 -98 34 3 75 18 98 -6 47 -39 31 -19 30 -51 +-6 18 -93 31 51 -20 -16 -33 -38 -19 71 4 -53 23 97 1 -28 -72 -44 -48 45 33 -76 86 64 49 -45 -34 -9 -76 +-19 8 28 -27 -51 -58 -36 63 -92 -95 70 41 -38 -49 -95 -100 43 97 -60 -5 -56 45 -13 -3 20 -10 -21 -85 -5 63 +-74 -74 -74 -39 -57 -12 51 11 -11 -22 -26 -54 71 24 -37 77 -90 77 75 86 -53 3 69 -99 -82 -59 30 81 -21 -86 +67 63 87 -15 60 -82 87 51 -39 -49 -16 74 51 17 6 47 98 89 -20 -98 97 -61 18 34 37 -36 37 -96 90 44 +53 -8 37 -76 -61 70 -77 -11 98 -80 12 -80 6 -89 8 -59 -69 -100 -52 -30 95 -58 61 29 52 -64 -51 10 16 -58 +54 -10 49 62 76 -25 80 36 13 5 59 -65 14 41 26 -78 23 -45 -51 -85 91 -43 -61 -37 94 27 -11 49 98 48 +53 -51 27 34 28 -53 18 17 31 -31 59 71 -34 25 54 -84 -34 -24 76 38 -36 15 -1 56 2 -12 0 26 -38 -62 +4 -94 -63 -21 -95 -42 -12 86 14 -86 -1 80 -48 62 -47 -52 3 91 -86 11 79 32 -24 -33 -54 19 -17 28 -33 -97 +-18 41 84 1 -83 48 -99 -64 26 -52 3 -64 68 -98 93 -79 -97 11 88 74 41 -31 -42 -35 -66 18 97 -30 19 -93 +-19 42 61 -91 -20 59 -11 -64 -60 85 -6 -71 33 -52 46 51 -86 -77 74 -4 74 -81 1 -39 -30 12 -12 20 66 60 +86 1 -67 -91 -92 -22 91 -90 -45 26 53 -6 99 46 -29 -40 -99 57 -45 -47 -3 -86 90 -78 -33 73 90 -51 -75 2 +88 -34 -2 30 -18 35 -23 90 99 -49 90 -79 94 -38 48 67 -35 -58 81 -24 18 -54 83 65 -58 -12 13 89 -59 57 +92 -99 94 -73 97 -78 -93 98 -78 95 -21 -17 -11 -92 69 -60 86 9 -36 -18 -33 -39 -65 74 -65 37 -49 87 -28 -81 +-95 2 -18 20 93 54 86 -63 -5 -89 17 -9 75 -66 -64 -82 -46 -48 82 5 -89 19 -32 -45 53 -47 21 -9 40 34 +86 87 55 -41 49 -10 -6 -7 -99 23 90 -50 -9 -81 77 65 29 -21 22 -82 19 48 -24 -72 75 -66 -69 -17 72 6 +13 37 96 31 -65 -54 -91 -27 84 52 -9 -28 85 96 14 63 -34 -29 -85 78 -75 -44 -30 -5 4 72 -45 6 13 71 +96 -69 67 59 69 46 80 42 81 30 89 -45 -10 -44 25 31 89 16 -36 86 31 92 1 5 -2 92 -11 77 20 40 +-48 98 -100 30 54 9 84 -88 5 48 93 56 -94 -89 81 33 44 -30 -95 -98 29 -33 13 -26 -59 -80 -68 -40 12 11 +82 -63 -30 -67 54 -68 50 -63 -91 -68 -45 -66 -58 16 -25 9 -50 -59 -55 4 -2 0 -63 67 30 -21 -8 55 21 -68 +9 -8 56 -6 84 81 -63 -35 81 56 -50 -54 96 -51 86 0 66 -4 -18 65 -26 -57 8 78 -54 17 18 86 21 68 +9 38 33 16 3 86 -57 28 -6 -44 -42 -2 3 -71 -86 23 34 -29 33 -30 67 63 -11 76 -65 92 30 -66 61 1 +-72 -85 -1 64 -79 -78 -1 15 -35 -32 80 33 -36 -82 24 -65 -23 29 38 -31 87 55 -18 -52 -77 -22 -11 54 62 -48 +65 -77 50 16 41 -94 -21 16 85 24 60 86 -78 -13 69 46 55 5 -27 -18 -6 -1 59 -62 -58 -99 -49 -84 89 18 +-21 -15 -55 60 78 98 67 94 58 -5 -36 42 36 73 13 72 -78 -68 41 -37 -33 -46 -80 40 13 -44 -71 -8 15 -77 +16 -93 -42 -10 14 57 -54 -3 -44 -21 30 -93 71 25 -60 -94 93 5 -94 -84 -72 1 -50 -34 23 -15 15 18 72 -29 +-22 -82 -30 -87 -88 -25 46 32 -30 -55 -79 -85 71 -89 -57 -88 21 53 -100 -64 -92 -97 56 -51 -17 -34 -31 6 -68 84 +-53 -51 90 -38 -61 57 -63 67 22 22 70 44 43 97 20 -62 -74 72 83 -32 35 -66 -29 5 -88 55 -94 94 -19 55 +57 51 29 -42 -21 63 -57 7 -48 -87 -60 -55 -77 -53 -1 -85 64 60 53 71 41 59 -61 -73 -12 86 90 10 -60 -38 +2 -9 14 67 -2 70 11 -78 26 -55 -86 -25 99 66 63 64 46 59 66 -37 -78 -70 63 1 -20 2 46 50 34 19 +-87 -40 75 -11 -88 -80 -95 -20 -92 -28 83 24 88 -39 83 -36 -61 56 99 -73 -59 -85 -49 -10 91 12 -79 -18 -15 6 +35 -74 -4 -15 40 -87 81 -22 -12 -46 14 9 98 -35 -2 -12 57 -74 -52 71 70 -70 -61 -47 89 44 33 -100 54 42 +-4 -34 80 -12 -15 -9 -8 -29 89 -55 -33 89 16 -33 -73 -82 98 27 88 59 48 20 -67 -21 -86 11 -50 46 64 -8 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/random-uint-data.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/random-uint-data.txt new file mode 100644 index 0000000000000000000000000000000000000000..c1ec7a5d64e540428507ee5a3358743b6c034ebc --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/random-uint-data.txt @@ -0,0 +1,100 @@ +52 34 59 34 64 20 89 69 26 93 95 32 17 93 77 49 51 60 51 27 60 10 61 2 16 30 41 68 65 0 +43 74 11 37 32 61 72 29 47 21 7 47 68 58 22 33 29 37 14 45 71 1 67 79 69 9 6 6 95 78 +86 20 68 67 43 5 77 70 96 37 79 71 35 30 22 4 56 28 33 50 97 17 85 52 21 5 57 19 35 97 +15 21 99 4 54 39 15 29 68 21 50 76 64 51 79 0 24 5 65 95 90 51 99 82 9 80 61 32 2 38 +46 97 53 96 51 84 18 42 30 52 82 77 72 59 1 67 72 16 14 63 70 94 20 27 38 70 86 95 41 75 +2 35 45 63 92 76 81 60 62 72 90 46 47 33 1 30 54 22 50 85 63 61 22 79 45 53 45 33 8 28 +43 41 14 79 2 77 95 16 74 19 17 78 47 12 68 55 3 2 77 10 35 86 52 33 47 26 98 42 48 86 +18 32 85 4 91 10 69 68 15 42 58 77 88 64 91 43 56 30 92 11 52 23 43 92 65 50 68 8 80 81 +20 57 38 44 62 10 80 25 32 11 70 32 13 50 41 55 44 0 28 83 5 1 34 94 55 52 56 24 76 21 +36 43 59 28 10 59 4 41 64 98 54 66 44 3 37 41 67 10 85 23 58 35 58 34 35 79 46 18 1 51 +72 63 85 51 23 91 3 56 35 72 38 26 91 0 68 98 27 10 12 71 30 1 14 47 47 88 17 68 78 46 +53 47 1 89 95 53 11 45 46 6 91 20 57 35 58 79 60 3 21 45 4 18 59 96 36 12 13 83 52 46 +33 91 82 24 97 28 50 43 65 22 14 44 32 57 33 10 34 77 58 6 27 90 26 77 62 81 87 96 0 32 +96 44 59 3 47 18 0 91 83 68 48 26 67 82 39 18 88 47 80 0 57 40 30 7 57 74 49 37 57 65 +18 44 0 46 47 30 65 79 53 8 26 42 80 76 30 61 82 93 78 25 89 49 55 15 86 63 35 74 41 11 +18 14 40 90 91 79 80 36 33 72 25 56 73 28 65 27 62 17 60 84 23 70 32 26 77 97 47 94 72 1 +82 36 68 10 83 83 40 42 51 55 82 6 37 69 93 82 64 13 54 30 45 36 87 59 1 80 39 93 11 61 +78 34 53 39 64 52 52 22 33 69 71 82 57 37 78 52 62 31 87 68 70 5 85 94 41 75 38 45 84 22 +36 23 51 15 61 76 88 85 36 96 21 60 34 61 72 60 69 81 5 17 16 82 30 61 39 96 40 70 42 71 +45 30 60 50 78 90 36 40 11 85 42 14 61 3 66 53 68 14 41 30 97 74 79 91 64 8 1 53 52 33 +55 24 35 4 49 51 44 70 93 78 25 65 1 29 96 12 93 94 13 65 4 47 84 10 90 12 36 48 21 36 +17 74 61 54 21 83 35 97 47 90 57 11 16 39 95 78 23 40 23 55 17 51 20 73 98 93 50 32 58 4 +84 76 78 33 50 29 11 20 5 93 63 22 91 92 44 85 62 25 63 92 36 26 57 33 8 74 69 64 78 91 +58 34 91 71 37 84 28 90 28 37 97 7 26 44 59 18 58 64 31 83 16 17 50 36 65 81 19 63 66 64 +20 71 1 35 87 5 47 27 6 95 86 75 74 9 94 93 26 5 61 3 97 88 0 57 21 64 46 24 86 12 +23 53 31 39 37 77 29 51 85 10 41 91 67 82 50 91 53 72 75 81 50 63 52 92 83 49 92 50 26 9 +38 43 13 87 11 45 28 16 27 61 70 52 77 9 57 42 73 22 32 95 23 91 93 63 16 44 26 9 93 83 +77 68 21 96 44 45 9 2 14 2 67 90 55 82 67 21 18 64 31 16 2 27 86 42 34 72 22 98 91 33 +89 66 87 76 0 32 81 39 55 76 23 56 51 53 75 79 30 86 1 66 64 14 46 84 92 19 95 47 77 97 +88 79 61 26 66 92 54 22 15 25 26 0 76 27 17 59 48 4 42 61 65 91 0 62 55 79 29 88 10 11 +24 89 91 39 56 36 16 86 41 31 14 35 7 71 77 74 33 11 49 7 96 83 31 63 90 49 96 22 58 86 +45 7 93 44 50 54 83 80 3 36 11 38 14 17 10 84 96 94 26 34 26 75 72 0 41 89 96 47 39 88 +0 95 2 22 68 38 0 3 51 6 13 10 14 49 75 69 25 39 63 67 12 80 37 77 10 90 60 35 84 37 +98 56 99 75 49 66 3 33 65 86 1 79 91 23 69 98 91 73 95 45 64 26 99 75 49 77 71 55 42 18 +80 39 26 94 85 42 91 27 14 57 36 34 10 44 38 77 23 39 54 25 32 5 17 9 66 3 67 94 20 11 +88 80 30 77 72 67 16 75 84 87 60 89 21 94 24 11 63 8 79 89 37 18 6 82 76 70 81 95 67 95 +92 36 55 55 43 18 76 94 30 74 95 38 45 95 54 87 22 57 4 65 15 90 90 38 73 24 67 24 36 25 +98 30 34 68 11 48 42 38 80 23 12 91 77 22 65 2 88 31 70 12 46 63 17 63 27 76 21 71 70 7 +76 29 56 12 41 66 22 96 8 6 7 13 27 10 77 90 2 76 30 24 81 88 19 16 93 13 30 24 98 96 +45 94 89 41 52 14 71 88 80 74 7 85 44 69 65 88 4 15 84 97 86 5 53 15 39 34 9 10 45 20 +95 47 45 96 71 10 36 10 90 49 7 68 14 46 97 89 82 58 69 34 93 77 90 9 27 91 29 27 22 17 +80 6 29 26 34 59 10 55 32 53 18 72 39 40 29 35 52 64 2 64 38 83 16 46 53 20 19 8 10 67 +47 44 79 32 58 82 26 69 0 26 4 73 95 98 61 96 20 38 3 92 6 5 25 24 42 49 15 92 80 16 +74 37 86 84 47 15 56 36 43 59 72 72 74 73 49 54 26 5 40 80 78 48 4 65 31 70 14 91 88 72 +91 45 73 62 83 40 49 3 27 79 80 90 3 3 58 44 7 66 77 42 37 25 20 91 47 63 71 7 72 22 +51 3 36 90 45 84 18 55 75 78 42 62 86 63 65 67 46 75 1 79 2 85 85 60 36 92 34 89 66 99 +36 99 0 63 89 65 54 58 52 28 98 27 67 1 45 71 35 52 55 55 44 23 46 89 83 37 8 2 92 75 +51 13 71 2 9 95 23 60 24 98 86 43 32 16 75 70 92 78 26 84 29 14 35 55 61 89 73 59 76 44 +59 57 28 92 33 50 70 94 89 67 70 38 53 16 35 70 35 92 39 78 88 80 71 1 93 21 87 64 49 84 +29 6 17 45 38 65 41 48 81 69 34 12 2 14 41 71 16 92 69 27 61 74 58 20 75 19 39 66 57 82 +12 8 14 85 97 31 58 31 20 76 6 42 29 95 60 94 15 84 86 69 73 52 73 57 12 66 89 65 60 84 +20 74 96 34 83 41 8 37 22 36 30 25 20 8 58 73 9 75 76 73 84 38 16 24 95 95 68 66 43 19 +33 15 25 80 48 69 63 39 16 45 6 77 14 46 38 15 64 85 49 5 59 28 9 4 23 68 59 26 1 75 +35 45 3 6 34 59 55 51 81 59 59 93 18 41 8 44 88 7 86 4 88 90 24 54 73 62 89 13 44 92 +72 60 68 83 39 32 30 15 98 92 69 94 51 48 9 0 4 1 30 92 40 1 61 82 66 4 39 10 93 87 +12 20 34 72 33 31 67 71 67 47 98 76 53 29 17 17 13 31 43 76 25 37 8 39 9 5 96 41 87 66 +96 30 2 57 57 10 14 17 86 76 35 94 42 54 18 24 19 34 12 42 18 11 83 65 86 38 45 17 60 70 +19 62 71 99 35 60 96 30 44 80 78 15 14 5 32 43 10 26 81 72 41 98 30 87 75 8 53 33 25 95 +22 0 38 57 88 7 47 83 49 41 52 1 14 93 41 3 18 42 15 57 28 74 97 2 18 48 64 25 77 69 +36 95 65 81 44 41 6 74 62 16 72 81 15 72 31 5 22 17 19 6 7 15 82 10 31 93 11 45 41 11 +22 76 14 62 34 65 82 5 57 51 51 5 1 6 17 43 28 31 90 99 48 14 96 49 95 40 87 85 40 51 +95 13 99 46 52 80 4 18 95 94 0 46 10 80 3 34 60 15 86 10 28 59 6 35 14 93 18 8 3 65 +57 37 6 31 45 85 42 34 47 92 48 40 7 17 5 74 67 62 0 74 58 21 23 3 5 24 50 54 99 19 +24 14 10 4 36 33 88 51 40 66 40 56 65 23 43 13 82 62 27 88 89 91 36 37 19 11 50 39 96 68 +82 7 39 80 52 90 57 17 61 15 51 71 82 15 21 44 4 46 75 50 78 18 63 75 98 45 6 16 57 25 +0 26 56 74 62 84 71 42 25 86 68 10 73 0 71 6 15 99 1 51 45 42 5 49 3 35 84 29 15 36 +60 78 76 3 95 73 36 57 35 44 50 42 85 57 18 69 37 42 75 79 15 12 74 72 51 36 79 3 58 71 +69 24 16 96 17 25 21 94 71 78 74 39 7 96 3 12 13 16 7 99 65 72 12 28 75 44 55 8 75 67 +3 13 92 9 92 83 69 91 65 92 29 63 46 1 4 62 29 85 47 93 81 3 15 23 63 50 17 9 13 13 +9 18 46 53 0 86 10 41 87 89 24 25 70 73 8 23 27 76 66 46 58 39 28 1 99 64 59 13 7 68 +72 57 90 50 47 57 34 27 94 39 23 31 74 77 45 74 18 49 96 8 95 50 20 81 73 55 72 2 32 15 +87 77 74 5 99 86 5 65 97 39 17 74 48 87 20 66 28 2 18 58 49 22 79 23 36 30 64 20 71 32 +35 43 66 96 63 77 18 90 47 86 94 19 88 79 23 12 38 4 56 42 36 2 77 1 3 17 64 52 31 24 +80 2 4 39 61 60 74 83 28 28 61 10 71 82 44 29 55 30 1 58 81 79 34 41 85 82 84 55 22 12 +76 77 58 92 90 0 54 28 77 68 58 12 1 81 37 28 19 60 71 59 25 83 8 49 52 11 28 65 59 70 +14 1 92 90 5 48 28 78 1 42 54 43 60 83 72 19 28 33 12 52 18 15 56 95 39 33 37 70 53 23 +53 76 26 31 18 81 83 79 25 1 82 43 50 24 63 49 5 23 66 37 80 41 63 77 2 28 15 21 32 93 +80 41 81 7 37 95 19 42 57 30 12 25 29 34 41 45 87 8 20 95 63 16 99 55 16 61 16 36 81 25 +32 30 2 81 23 25 88 30 37 76 52 77 79 58 21 58 10 0 13 32 72 80 3 75 75 25 21 9 79 18 +26 13 36 63 43 2 50 41 65 18 88 44 82 75 73 24 1 30 54 68 15 18 22 50 41 99 27 96 51 53 +22 4 76 11 85 88 28 75 1 2 92 66 63 3 58 43 53 5 1 24 99 90 87 87 41 1 85 37 98 92 +16 39 13 88 60 55 35 11 34 23 23 85 79 41 79 87 65 78 47 83 88 78 35 84 30 61 37 58 25 55 +27 33 15 76 82 79 73 92 93 78 18 38 22 96 63 92 41 9 50 96 14 55 8 60 15 61 97 56 43 22 +42 34 94 11 35 70 50 49 36 34 59 14 87 84 88 83 4 69 29 99 35 24 2 18 97 97 74 88 91 49 +33 25 71 12 60 2 48 22 81 33 27 95 54 25 53 14 20 43 26 96 98 37 64 27 72 33 78 45 22 61 +61 21 91 38 92 47 26 90 78 96 58 41 21 72 81 61 55 9 55 60 28 25 25 74 73 81 64 16 49 39 +90 89 12 93 91 23 82 36 63 58 73 81 49 32 60 39 4 84 73 16 18 26 58 85 46 28 82 91 72 7 +79 41 28 76 33 70 47 6 18 64 40 54 45 61 28 63 87 83 38 9 65 68 62 45 80 63 89 29 20 40 +20 59 58 23 61 79 35 19 78 2 26 48 90 34 69 31 31 42 92 33 18 74 28 47 45 52 36 89 19 40 +58 13 72 24 31 26 73 72 84 29 85 99 20 32 54 92 8 80 86 58 23 80 59 21 76 75 90 76 92 57 +74 53 80 51 8 88 84 63 82 99 97 77 38 9 51 61 37 20 68 47 65 21 53 82 85 96 62 65 35 4 +71 82 14 18 88 79 38 76 66 27 10 10 62 54 80 21 6 57 83 33 52 10 97 37 6 38 12 51 0 84 +95 30 75 92 84 30 55 57 32 44 53 24 77 81 34 84 69 85 91 33 50 72 62 79 62 12 59 75 99 81 +38 42 47 1 11 34 27 77 70 85 89 84 79 15 14 54 78 93 72 68 63 39 98 72 55 32 93 0 13 21 +3 15 10 15 3 31 84 89 53 5 60 41 66 77 45 12 68 68 50 68 99 64 46 54 30 56 2 90 99 78 +66 10 27 89 42 16 9 98 16 2 68 51 0 22 73 60 69 96 37 69 30 36 20 21 51 26 65 13 74 86 +94 58 34 97 77 88 90 75 47 30 6 36 89 66 48 9 20 6 52 45 0 37 99 46 11 53 53 72 94 40 +5 71 50 96 89 71 80 43 27 95 49 9 74 28 62 65 64 97 2 55 58 11 69 0 31 22 73 20 66 11 +63 39 84 62 64 5 56 92 26 86 19 20 56 85 42 48 56 51 54 29 26 95 72 38 70 61 16 54 57 19 +76 97 40 99 73 68 98 92 97 62 73 1 29 72 18 70 90 4 98 95 70 36 65 45 86 36 88 38 64 54 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/selfdual-4d-polytope.txt b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/selfdual-4d-polytope.txt new file mode 100644 index 0000000000000000000000000000000000000000..47ce4a7ae522fc2a2bbaa9d8ca285913b8ef0712 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/data/selfdual-4d-polytope.txt @@ -0,0 +1,27 @@ +# The facets of a self-dual 4-dim regular polytope +# with 24 octahedron facets. Taken from cddlib. +# Format b + Ax >= 0 + 1 1 1 1 1 + 1 1 1 1 -1 + 1 1 1 -1 1 + 1 1 1 -1 -1 + 1 1 -1 1 1 + 1 1 -1 1 -1 + 1 1 -1 -1 1 + 1 1 -1 -1 -1 + 1 -1 1 1 1 + 1 -1 1 1 -1 + 1 -1 1 -1 1 + 1 -1 1 -1 -1 + 1 -1 -1 1 1 + 1 -1 -1 1 -1 + 1 -1 -1 -1 1 + 1 -1 -1 -1 -1 + 1 2 0 0 0 + 1 0 2 0 0 + 1 0 0 2 0 + 1 0 0 0 2 + 1 -2 0 0 0 + 1 0 -2 0 0 + 1 0 0 -2 0 + 1 0 0 0 -2 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test__plotutils.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test__plotutils.py new file mode 100644 index 0000000000000000000000000000000000000000..0e2553bf7ad56e97b567e5b334ccf17921f7f7f3 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test__plotutils.py @@ -0,0 +1,91 @@ +import pytest +import numpy as np +from numpy.testing import assert_, assert_array_equal, assert_allclose + +try: + import matplotlib + matplotlib.rcParams['backend'] = 'Agg' + import matplotlib.pyplot as plt + has_matplotlib = True +except Exception: + has_matplotlib = False + +from scipy.spatial import \ + delaunay_plot_2d, voronoi_plot_2d, convex_hull_plot_2d, \ + Delaunay, Voronoi, ConvexHull + + +@pytest.mark.skipif(not has_matplotlib, reason="Matplotlib not available") +class TestPlotting: + points = [(0,0), (0,1), (1,0), (1,1)] + + def test_delaunay(self): + # Smoke test + fig = plt.figure() + obj = Delaunay(self.points) + s_before = obj.simplices.copy() + r = delaunay_plot_2d(obj, ax=fig.gca()) + assert_array_equal(obj.simplices, s_before) # shouldn't modify + assert_(r is fig) + delaunay_plot_2d(obj, ax=fig.gca()) + + def test_voronoi(self): + # Smoke test + fig = plt.figure() + obj = Voronoi(self.points) + r = voronoi_plot_2d(obj, ax=fig.gca()) + assert_(r is fig) + voronoi_plot_2d(obj) + voronoi_plot_2d(obj, show_vertices=False) + + def test_convex_hull(self): + # Smoke test + fig = plt.figure() + tri = ConvexHull(self.points) + r = convex_hull_plot_2d(tri, ax=fig.gca()) + assert_(r is fig) + convex_hull_plot_2d(tri) + + def test_gh_19653(self): + # aspect ratio sensitivity of voronoi_plot_2d + # infinite Voronoi edges + points = np.array([[245.059986986012, 10.971011721360075], + [320.49044143557785, 10.970258360366753], + [239.79023081978914, 13.108487516946218], + [263.38325791238833, 12.93241352743668], + [219.53334398353175, 13.346107628161008]]) + vor = Voronoi(points) + fig = voronoi_plot_2d(vor) + ax = fig.gca() + infinite_segments = ax.collections[1].get_segments() + expected_segments = np.array([[[282.77256, -254.76904], + [282.729714, -4544.744698]], + [[282.77256014, -254.76904029], + [430.08561382, 4032.67658742]], + [[229.26733285, -20.39957514], + [-168.17167404, -4291.92545966]], + [[289.93433364, 5151.40412217], + [330.40553385, 9441.18887532]]]) + assert_allclose(infinite_segments, expected_segments) + + def test_gh_19653_smaller_aspect(self): + # reasonable behavior for less extreme aspect + # ratio + points = np.array([[24.059986986012, 10.971011721360075], + [32.49044143557785, 10.970258360366753], + [23.79023081978914, 13.108487516946218], + [26.38325791238833, 12.93241352743668], + [21.53334398353175, 13.346107628161008]]) + vor = Voronoi(points) + fig = voronoi_plot_2d(vor) + ax = fig.gca() + infinite_segments = ax.collections[1].get_segments() + expected_segments = np.array([[[28.274979, 8.335027], + [28.270463, -42.19763338]], + [[28.27497869, 8.33502697], + [43.73223829, 56.44555501]], + [[22.51805823, 11.8621754], + [-12.09266506, -24.95694485]], + [[29.53092448, 78.46952378], + [33.82572726, 128.81934455]]]) + assert_allclose(infinite_segments, expected_segments) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test__procrustes.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test__procrustes.py new file mode 100644 index 0000000000000000000000000000000000000000..42a3c4d35bd55e2ffecefb691c805f517c56d6ca --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test__procrustes.py @@ -0,0 +1,116 @@ +import numpy as np +from numpy.testing import assert_allclose, assert_equal, assert_almost_equal +from pytest import raises as assert_raises + +from scipy.spatial import procrustes + + +class TestProcrustes: + def setup_method(self): + """creates inputs""" + # an L + self.data1 = np.array([[1, 3], [1, 2], [1, 1], [2, 1]], 'd') + + # a larger, shifted, mirrored L + self.data2 = np.array([[4, -2], [4, -4], [4, -6], [2, -6]], 'd') + + # an L shifted up 1, right 1, and with point 4 shifted an extra .5 + # to the right + # pointwise distance disparity with data1: 3*(2) + (1 + 1.5^2) + self.data3 = np.array([[2, 4], [2, 3], [2, 2], [3, 2.5]], 'd') + + # data4, data5 are standardized (trace(A*A') = 1). + # procrustes should return an identical copy if they are used + # as the first matrix argument. + shiftangle = np.pi / 8 + self.data4 = np.array([[1, 0], [0, 1], [-1, 0], + [0, -1]], 'd') / np.sqrt(4) + self.data5 = np.array([[np.cos(shiftangle), np.sin(shiftangle)], + [np.cos(np.pi / 2 - shiftangle), + np.sin(np.pi / 2 - shiftangle)], + [-np.cos(shiftangle), + -np.sin(shiftangle)], + [-np.cos(np.pi / 2 - shiftangle), + -np.sin(np.pi / 2 - shiftangle)]], + 'd') / np.sqrt(4) + + def test_procrustes(self): + # tests procrustes' ability to match two matrices. + # + # the second matrix is a rotated, shifted, scaled, and mirrored version + # of the first, in two dimensions only + # + # can shift, mirror, and scale an 'L'? + a, b, disparity = procrustes(self.data1, self.data2) + assert_allclose(b, a) + assert_almost_equal(disparity, 0.) + + # if first mtx is standardized, leaves first mtx unchanged? + m4, m5, disp45 = procrustes(self.data4, self.data5) + assert_equal(m4, self.data4) + + # at worst, data3 is an 'L' with one point off by .5 + m1, m3, disp13 = procrustes(self.data1, self.data3) + #assert_(disp13 < 0.5 ** 2) + + def test_procrustes2(self): + # procrustes disparity should not depend on order of matrices + m1, m3, disp13 = procrustes(self.data1, self.data3) + m3_2, m1_2, disp31 = procrustes(self.data3, self.data1) + assert_almost_equal(disp13, disp31) + + # try with 3d, 8 pts per + rand1 = np.array([[2.61955202, 0.30522265, 0.55515826], + [0.41124708, -0.03966978, -0.31854548], + [0.91910318, 1.39451809, -0.15295084], + [2.00452023, 0.50150048, 0.29485268], + [0.09453595, 0.67528885, 0.03283872], + [0.07015232, 2.18892599, -1.67266852], + [0.65029688, 1.60551637, 0.80013549], + [-0.6607528, 0.53644208, 0.17033891]]) + + rand3 = np.array([[0.0809969, 0.09731461, -0.173442], + [-1.84888465, -0.92589646, -1.29335743], + [0.67031855, -1.35957463, 0.41938621], + [0.73967209, -0.20230757, 0.52418027], + [0.17752796, 0.09065607, 0.29827466], + [0.47999368, -0.88455717, -0.57547934], + [-0.11486344, -0.12608506, -0.3395779], + [-0.86106154, -0.28687488, 0.9644429]]) + res1, res3, disp13 = procrustes(rand1, rand3) + res3_2, res1_2, disp31 = procrustes(rand3, rand1) + assert_almost_equal(disp13, disp31) + + def test_procrustes_shape_mismatch(self): + assert_raises(ValueError, procrustes, + np.array([[1, 2], [3, 4]]), + np.array([[5, 6, 7], [8, 9, 10]])) + + def test_procrustes_empty_rows_or_cols(self): + empty = np.array([[]]) + assert_raises(ValueError, procrustes, empty, empty) + + def test_procrustes_no_variation(self): + assert_raises(ValueError, procrustes, + np.array([[42, 42], [42, 42]]), + np.array([[45, 45], [45, 45]])) + + def test_procrustes_bad_number_of_dimensions(self): + # fewer dimensions in one dataset + assert_raises(ValueError, procrustes, + np.array([1, 1, 2, 3, 5, 8]), + np.array([[1, 2], [3, 4]])) + + # fewer dimensions in both datasets + assert_raises(ValueError, procrustes, + np.array([1, 1, 2, 3, 5, 8]), + np.array([1, 1, 2, 3, 5, 8])) + + # zero dimensions + assert_raises(ValueError, procrustes, np.array(7), np.array(11)) + + # extra dimensions + assert_raises(ValueError, procrustes, + np.array([[[11], [7]]]), + np.array([[[5, 13]]])) + diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_distance.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_distance.py new file mode 100644 index 0000000000000000000000000000000000000000..7317603e6d30fccc4b5c3c7837898498faf56b9f --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_distance.py @@ -0,0 +1,2287 @@ +# +# Author: Damian Eads +# Date: April 17, 2008 +# +# Copyright (C) 2008 Damian Eads +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# +# 3. The name of the author may not be used to endorse or promote +# products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from functools import wraps, partial +import os.path +import sys +import sysconfig +import warnings +import weakref + +import numpy as np +from numpy.linalg import norm +from numpy.testing import (verbose, assert_, + assert_array_equal, assert_equal, + assert_almost_equal, assert_allclose, + break_cycles, IS_PYPY) +import pytest + +import scipy.spatial.distance + +from scipy.spatial.distance import ( + squareform, pdist, cdist, num_obs_y, num_obs_dm, is_valid_dm, is_valid_y, + _validate_vector, _METRICS_NAMES) + +# these were missing: chebyshev cityblock +# jensenshannon and seuclidean are referenced by string name. +from scipy.spatial.distance import (braycurtis, canberra, chebyshev, cityblock, + correlation, cosine, dice, euclidean, + hamming, jaccard, jensenshannon, mahalanobis, + minkowski, rogerstanimoto, + russellrao, seuclidean, # noqa: F401 + sokalsneath, sqeuclidean, yule) +from scipy._lib._util import np_long, np_ulong +from scipy.conftest import skip_xp_invalid_arg + + +@pytest.fixture(params=_METRICS_NAMES, scope="session") +def metric(request): + """ + Fixture for all metrics in scipy.spatial.distance + """ + return request.param + + +_filenames = [ + "cdist-X1.txt", + "cdist-X2.txt", + "iris.txt", + "pdist-boolean-inp.txt", + "pdist-chebyshev-ml-iris.txt", + "pdist-chebyshev-ml.txt", + "pdist-cityblock-ml-iris.txt", + "pdist-cityblock-ml.txt", + "pdist-correlation-ml-iris.txt", + "pdist-correlation-ml.txt", + "pdist-cosine-ml-iris.txt", + "pdist-cosine-ml.txt", + "pdist-double-inp.txt", + "pdist-euclidean-ml-iris.txt", + "pdist-euclidean-ml.txt", + "pdist-hamming-ml.txt", + "pdist-jaccard-ml.txt", + "pdist-jensenshannon-ml-iris.txt", + "pdist-jensenshannon-ml.txt", + "pdist-minkowski-3.2-ml-iris.txt", + "pdist-minkowski-3.2-ml.txt", + "pdist-minkowski-5.8-ml-iris.txt", + "pdist-seuclidean-ml-iris.txt", + "pdist-seuclidean-ml.txt", + "pdist-spearman-ml.txt", + "random-bool-data.txt", + "random-double-data.txt", + "random-int-data.txt", + "random-uint-data.txt", + ] + +_tdist = np.array([[0, 662, 877, 255, 412, 996], + [662, 0, 295, 468, 268, 400], + [877, 295, 0, 754, 564, 138], + [255, 468, 754, 0, 219, 869], + [412, 268, 564, 219, 0, 669], + [996, 400, 138, 869, 669, 0]], dtype='double') + +_ytdist = squareform(_tdist) + +# A hashmap of expected output arrays for the tests. These arrays +# come from a list of text files, which are read prior to testing. +# Each test loads inputs and outputs from this dictionary. +eo = {} + + +def load_testing_files(): + for fn in _filenames: + name = fn.replace(".txt", "").replace("-ml", "") + fqfn = os.path.join(os.path.dirname(__file__), 'data', fn) + fp = open(fqfn) + eo[name] = np.loadtxt(fp) + fp.close() + eo['pdist-boolean-inp'] = np.bool_(eo['pdist-boolean-inp']) + eo['random-bool-data'] = np.bool_(eo['random-bool-data']) + eo['random-float32-data'] = np.float32(eo['random-double-data']) + eo['random-int-data'] = np_long(eo['random-int-data']) + eo['random-uint-data'] = np_ulong(eo['random-uint-data']) + + +load_testing_files() + + +def _is_32bit(): + return np.intp(0).itemsize < 8 + + +def _chk_asarrays(arrays, axis=None): + arrays = [np.asanyarray(a) for a in arrays] + if axis is None: + # np < 1.10 ravel removes subclass from arrays + arrays = [np.ravel(a) if a.ndim != 1 else a + for a in arrays] + axis = 0 + arrays = tuple(np.atleast_1d(a) for a in arrays) + if axis < 0: + if not all(a.ndim == arrays[0].ndim for a in arrays): + raise ValueError("array ndim must be the same for neg axis") + axis = range(arrays[0].ndim)[axis] + return arrays + (axis,) + + +def _chk_weights(arrays, weights=None, axis=None, + force_weights=False, simplify_weights=True, + pos_only=False, neg_check=False, + nan_screen=False, mask_screen=False, + ddof=None): + chked = _chk_asarrays(arrays, axis=axis) + arrays, axis = chked[:-1], chked[-1] + + simplify_weights = simplify_weights and not force_weights + if not force_weights and mask_screen: + force_weights = any(np.ma.getmask(a) is not np.ma.nomask for a in arrays) + + if nan_screen: + has_nans = [np.isnan(np.sum(a)) for a in arrays] + if any(has_nans): + mask_screen = True + force_weights = True + arrays = tuple(np.ma.masked_invalid(a) if has_nan else a + for a, has_nan in zip(arrays, has_nans)) + + if weights is not None: + weights = np.asanyarray(weights) + elif force_weights: + weights = np.ones(arrays[0].shape[axis]) + else: + return arrays + (weights, axis) + + if ddof: + weights = _freq_weights(weights) + + if mask_screen: + weights = _weight_masked(arrays, weights, axis) + + if not all(weights.shape == (a.shape[axis],) for a in arrays): + raise ValueError("weights shape must match arrays along axis") + if neg_check and (weights < 0).any(): + raise ValueError("weights cannot be negative") + + if pos_only: + pos_weights = np.nonzero(weights > 0)[0] + if pos_weights.size < weights.size: + arrays = tuple(np.take(a, pos_weights, axis=axis) for a in arrays) + weights = weights[pos_weights] + if simplify_weights and (weights == 1).all(): + weights = None + return arrays + (weights, axis) + + +def _freq_weights(weights): + if weights is None: + return weights + int_weights = weights.astype(int) + if (weights != int_weights).any(): + raise ValueError(f"frequency (integer count-type) weights required {weights}") + return int_weights + + +def _weight_masked(arrays, weights, axis): + if axis is None: + axis = 0 + weights = np.asanyarray(weights) + for a in arrays: + axis_mask = np.ma.getmask(a) + if axis_mask is np.ma.nomask: + continue + if a.ndim > 1: + not_axes = tuple(i for i in range(a.ndim) if i != axis) + axis_mask = axis_mask.any(axis=not_axes) + weights *= 1 - axis_mask.astype(int) + return weights + + +def _rand_split(arrays, weights, axis, split_per, seed=None): + # Coerce `arrays` to float64 if integer, to avoid nan-to-integer issues + arrays = [arr.astype(np.float64) if np.issubdtype(arr.dtype, np.integer) + else arr for arr in arrays] + + # inverse operation for stats.collapse_weights + weights = np.array(weights, dtype=np.float64) # modified inplace; need a copy + seeded_rand = np.random.RandomState(seed) + + def mytake(a, ix, axis): + record = np.asanyarray(np.take(a, ix, axis=axis)) + return record.reshape([a.shape[i] if i != axis else 1 + for i in range(a.ndim)]) + + n_obs = arrays[0].shape[axis] + assert all(a.shape[axis] == n_obs for a in arrays), \ + "data must be aligned on sample axis" + for i in range(int(split_per) * n_obs): + split_ix = seeded_rand.randint(n_obs + i) + prev_w = weights[split_ix] + q = seeded_rand.rand() + weights[split_ix] = q * prev_w + weights = np.append(weights, (1. - q) * prev_w) + arrays = [np.append(a, mytake(a, split_ix, axis=axis), + axis=axis) for a in arrays] + return arrays, weights + + +assert_allclose_forgiving = partial(assert_allclose, atol=1e-5) + + +def _rough_check(a, b, compare_assert=assert_allclose_forgiving, + key=lambda x: x, w=None): + check_a = key(a) + check_b = key(b) + try: + if np.array(check_a != check_b).any(): # try strict equality for string types + compare_assert(check_a, check_b) + except AttributeError: # masked array + compare_assert(check_a, check_b) + except (TypeError, ValueError): # nested data structure + for a_i, b_i in zip(check_a, check_b): + _rough_check(a_i, b_i, compare_assert=compare_assert) + +# diff from test_stats: +# n_args=2, weight_arg='w', default_axis=None +# ma_safe = False, nan_safe = False +def _weight_checked(fn, n_args=2, default_axis=None, key=lambda x: x, weight_arg='w', + squeeze=True, silent=False, + ones_test=True, const_test=True, dup_test=True, + split_test=True, dud_test=True, ma_safe=False, ma_very_safe=False, + nan_safe=False, split_per=1.0, seed=0, + compare_assert=assert_allclose_forgiving): + """runs fn on its arguments 2 or 3 ways, checks that the results are the same, + then returns the same thing it would have returned before""" + @wraps(fn) + def wrapped(*args, **kwargs): + result = fn(*args, **kwargs) + + arrays = args[:n_args] + rest = args[n_args:] + weights = kwargs.get(weight_arg, None) + axis = kwargs.get('axis', default_axis) + + chked = _chk_weights(arrays, weights=weights, axis=axis, + force_weights=True, mask_screen=True) + arrays, weights, axis = chked[:-2], chked[-2], chked[-1] + if squeeze: + arrays = [np.atleast_1d(a.squeeze()) for a in arrays] + + try: + # WEIGHTS CHECK 1: EQUAL WEIGHTED OBSERVATIONS + args = tuple(arrays) + rest + if ones_test: + kwargs[weight_arg] = weights + _rough_check(result, fn(*args, **kwargs), key=key) + if const_test: + kwargs[weight_arg] = weights * 101.0 + _rough_check(result, fn(*args, **kwargs), key=key) + kwargs[weight_arg] = weights * 0.101 + try: + _rough_check(result, fn(*args, **kwargs), key=key) + except Exception as e: + raise type(e)((e, arrays, weights)) from e + + # WEIGHTS CHECK 2: ADDL 0-WEIGHTED OBS + if dud_test: + # add randomly resampled rows, weighted at 0 + dud_arrays, dud_weights = _rand_split(arrays, weights, axis, + split_per=split_per, seed=seed) + dud_weights[:weights.size] = weights # not exactly 1 because of masked arrays # noqa: E501 + dud_weights[weights.size:] = 0 + dud_args = tuple(dud_arrays) + rest + kwargs[weight_arg] = dud_weights + _rough_check(result, fn(*dud_args, **kwargs), key=key) + # increase the value of those 0-weighted rows + for a in dud_arrays: + indexer = [slice(None)] * a.ndim + indexer[axis] = slice(weights.size, None) + indexer = tuple(indexer) + a[indexer] = a[indexer] * 101 + dud_args = tuple(dud_arrays) + rest + _rough_check(result, fn(*dud_args, **kwargs), key=key) + # set those 0-weighted rows to NaNs + for a in dud_arrays: + indexer = [slice(None)] * a.ndim + indexer[axis] = slice(weights.size, None) + indexer = tuple(indexer) + a[indexer] = a[indexer] * np.nan + if kwargs.get("nan_policy", None) == "omit" and nan_safe: + dud_args = tuple(dud_arrays) + rest + _rough_check(result, fn(*dud_args, **kwargs), key=key) + # mask out those nan values + if ma_safe: + dud_arrays = [np.ma.masked_invalid(a) for a in dud_arrays] + dud_args = tuple(dud_arrays) + rest + _rough_check(result, fn(*dud_args, **kwargs), key=key) + if ma_very_safe: + kwargs[weight_arg] = None + _rough_check(result, fn(*dud_args, **kwargs), key=key) + del dud_arrays, dud_args, dud_weights + + # WEIGHTS CHECK 3: DUPLICATE DATA (DUMB SPLITTING) + if dup_test: + dup_arrays = [np.append(a, a, axis=axis) for a in arrays] + dup_weights = np.append(weights, weights) / 2.0 + dup_args = tuple(dup_arrays) + rest + kwargs[weight_arg] = dup_weights + _rough_check(result, fn(*dup_args, **kwargs), key=key) + del dup_args, dup_arrays, dup_weights + + # WEIGHT CHECK 3: RANDOM SPLITTING + if split_test and split_per > 0: + split = _rand_split(arrays, weights, axis, + split_per=split_per, seed=seed) + split_arrays, split_weights = split + split_args = tuple(split_arrays) + rest + kwargs[weight_arg] = split_weights + _rough_check(result, fn(*split_args, **kwargs), key=key) + except NotImplementedError as e: + # when some combination of arguments makes weighting impossible, + # this is the desired response + if not silent: + warnings.warn(f"{fn.__name__} NotImplemented weights: {e}", + stacklevel=3) + return result + return wrapped + + +wcdist = _weight_checked(cdist, default_axis=1, squeeze=False) +wcdist_no_const = _weight_checked(cdist, default_axis=1, + squeeze=False, const_test=False) +wpdist = _weight_checked(pdist, default_axis=1, squeeze=False, n_args=1) +wpdist_no_const = _weight_checked(pdist, default_axis=1, squeeze=False, + const_test=False, n_args=1) +wrogerstanimoto = _weight_checked(rogerstanimoto) +wmatching = whamming = _weight_checked(hamming, dud_test=False) +wyule = _weight_checked(yule) +wdice = _weight_checked(dice) +wcityblock = _weight_checked(cityblock) +wchebyshev = _weight_checked(chebyshev) +wcosine = _weight_checked(cosine) +wcorrelation = _weight_checked(correlation) +wjaccard = _weight_checked(jaccard) +weuclidean = _weight_checked(euclidean, const_test=False) +wsqeuclidean = _weight_checked(sqeuclidean, const_test=False) +wbraycurtis = _weight_checked(braycurtis) +wcanberra = _weight_checked(canberra, const_test=False) +wsokalsneath = _weight_checked(sokalsneath) +wrussellrao = _weight_checked(russellrao) + + +class TestCdist: + + def setup_method(self): + self.rnd_eo_names = ['random-float32-data', 'random-int-data', + 'random-uint-data', 'random-double-data', + 'random-bool-data'] + self.valid_upcasts = {'bool': [np_ulong, np_long, np.float32, np.float64], + 'uint': [np_long, np.float32, np.float64], + 'int': [np.float32, np.float64], + 'float32': [np.float64]} + + def test_cdist_extra_args(self, metric): + # Tests that args and kwargs are correctly handled + + X1 = [[1., 2., 3.], [1.2, 2.3, 3.4], [2.2, 2.3, 4.4]] + X2 = [[7., 5., 8.], [7.5, 5.8, 8.4], [5.5, 5.8, 4.4]] + kwargs = {"N0tV4l1D_p4raM": 3.14, "w": np.arange(3)} + args = [3.14] * 200 + + with pytest.raises(TypeError): + cdist(X1, X2, metric=metric, **kwargs) + with pytest.raises(TypeError): + cdist(X1, X2, metric=eval(metric), **kwargs) + with pytest.raises(TypeError): + cdist(X1, X2, metric="test_" + metric, **kwargs) + with pytest.raises(TypeError): + cdist(X1, X2, metric=metric, *args) + with pytest.raises(TypeError): + cdist(X1, X2, metric=eval(metric), *args) + with pytest.raises(TypeError): + cdist(X1, X2, metric="test_" + metric, *args) + + def test_cdist_extra_args_custom(self): + # Tests that args and kwargs are correctly handled + # also for custom metric + def _my_metric(x, y, arg, kwarg=1, kwarg2=2): + return arg + kwarg + kwarg2 + + X1 = [[1., 2., 3.], [1.2, 2.3, 3.4], [2.2, 2.3, 4.4]] + X2 = [[7., 5., 8.], [7.5, 5.8, 8.4], [5.5, 5.8, 4.4]] + kwargs = {"N0tV4l1D_p4raM": 3.14, "w": np.arange(3)} + args = [3.14] * 200 + + with pytest.raises(TypeError): + cdist(X1, X2, _my_metric) + with pytest.raises(TypeError): + cdist(X1, X2, _my_metric, *args) + with pytest.raises(TypeError): + cdist(X1, X2, _my_metric, **kwargs) + with pytest.raises(TypeError): + cdist(X1, X2, _my_metric, kwarg=2.2, kwarg2=3.3) + with pytest.raises(TypeError): + cdist(X1, X2, _my_metric, 1, 2, kwarg=2.2) + with pytest.raises(TypeError): + cdist(X1, X2, _my_metric, 1, 2, kwarg=2.2) + with pytest.raises(TypeError): + cdist(X1, X2, _my_metric, 1.1, 2.2, 3.3) + with pytest.raises(TypeError): + cdist(X1, X2, _my_metric, 1.1, 2.2) + with pytest.raises(TypeError): + cdist(X1, X2, _my_metric, 1.1) + with pytest.raises(TypeError): + cdist(X1, X2, _my_metric, 1.1, kwarg=2.2, kwarg2=3.3) + + # this should work + assert_allclose(cdist(X1, X2, metric=_my_metric, + arg=1.1, kwarg2=3.3), 5.4) + + def test_cdist_euclidean_random_unicode(self): + eps = 1e-15 + X1 = eo['cdist-X1'] + X2 = eo['cdist-X2'] + Y1 = wcdist_no_const(X1, X2, 'euclidean') + Y2 = wcdist_no_const(X1, X2, 'test_euclidean') + assert_allclose(Y1, Y2, rtol=eps, verbose=verbose > 2) + + @pytest.mark.parametrize("p", [0.1, 0.25, 1.0, 1.23, + 2.0, 3.8, 4.6, np.inf]) + def test_cdist_minkowski_random(self, p): + eps = 1e-13 + X1 = eo['cdist-X1'] + X2 = eo['cdist-X2'] + Y1 = wcdist_no_const(X1, X2, 'minkowski', p=p) + Y2 = wcdist_no_const(X1, X2, 'test_minkowski', p=p) + assert_allclose(Y1, Y2, atol=0, rtol=eps, verbose=verbose > 2) + + def test_cdist_cosine_random(self): + eps = 1e-14 + X1 = eo['cdist-X1'] + X2 = eo['cdist-X2'] + Y1 = wcdist(X1, X2, 'cosine') + + # Naive implementation + def norms(X): + return np.linalg.norm(X, axis=1).reshape(-1, 1) + + Y2 = 1 - np.dot((X1 / norms(X1)), (X2 / norms(X2)).T) + + assert_allclose(Y1, Y2, rtol=eps, verbose=verbose > 2) + + def test_cdist_mahalanobis(self): + # 1-dimensional observations + x1 = np.array([[2], [3]]) + x2 = np.array([[2], [5]]) + dist = cdist(x1, x2, metric='mahalanobis') + assert_allclose(dist, [[0.0, np.sqrt(4.5)], [np.sqrt(0.5), np.sqrt(2)]]) + + # 2-dimensional observations + x1 = np.array([[0, 0], [-1, 0]]) + x2 = np.array([[0, 2], [1, 0], [0, -2]]) + dist = cdist(x1, x2, metric='mahalanobis') + rt2 = np.sqrt(2) + assert_allclose(dist, [[rt2, rt2, rt2], [2, 2 * rt2, 2]]) + + # Too few observations + with pytest.raises(ValueError): + cdist([[0, 1]], [[2, 3]], metric='mahalanobis') + + def test_cdist_custom_notdouble(self): + class myclass: + pass + + def _my_metric(x, y): + if not isinstance(x[0], myclass) or not isinstance(y[0], myclass): + raise ValueError("Type has been changed") + return 1.123 + data = np.array([[myclass()]], dtype=object) + cdist_y = cdist(data, data, metric=_my_metric) + right_y = 1.123 + assert_equal(cdist_y, right_y, verbose=verbose > 2) + + def _check_calling_conventions(self, X1, X2, metric, eps=1e-07, **kwargs): + # helper function for test_cdist_calling_conventions + try: + y1 = cdist(X1, X2, metric=metric, **kwargs) + y2 = cdist(X1, X2, metric=eval(metric), **kwargs) + y3 = cdist(X1, X2, metric="test_" + metric, **kwargs) + except Exception as e: + e_cls = e.__class__ + if verbose > 2: + print(e_cls.__name__) + print(e) + with pytest.raises(e_cls): + cdist(X1, X2, metric=metric, **kwargs) + with pytest.raises(e_cls): + cdist(X1, X2, metric=eval(metric), **kwargs) + with pytest.raises(e_cls): + cdist(X1, X2, metric="test_" + metric, **kwargs) + else: + assert_allclose(y1, y2, rtol=eps, verbose=verbose > 2) + assert_allclose(y1, y3, rtol=eps, verbose=verbose > 2) + + def test_cdist_calling_conventions(self, metric): + # Ensures that specifying the metric with a str or scipy function + # gives the same behaviour (i.e. same result or same exception). + # NOTE: The correctness should be checked within each metric tests. + for eo_name in self.rnd_eo_names: + # subsampling input data to speed-up tests + # NOTE: num samples needs to be > than dimensions for mahalanobis + X1 = eo[eo_name][::5, ::-2] + X2 = eo[eo_name][1::5, ::2] + if verbose > 2: + print("testing: ", metric, " with: ", eo_name) + if (metric in {'dice', 'yule', 'rogerstanimoto', 'russellrao', + 'sokalsneath'} + and 'bool' not in eo_name): + # python version permits non-bools e.g. for fuzzy logic + continue + self._check_calling_conventions(X1, X2, metric) + + # Testing built-in metrics with extra args + if metric == "seuclidean": + X12 = np.vstack([X1, X2]).astype(np.float64) + V = np.var(X12, axis=0, ddof=1) + self._check_calling_conventions(X1, X2, metric, V=V) + elif metric == "mahalanobis": + X12 = np.vstack([X1, X2]).astype(np.float64) + V = np.atleast_2d(np.cov(X12.T)) + VI = np.array(np.linalg.inv(V).T) + self._check_calling_conventions(X1, X2, metric, VI=VI) + + def test_cdist_dtype_equivalence(self, metric): + # Tests that the result is not affected by type up-casting + eps = 1e-07 + tests = [(eo['random-bool-data'], self.valid_upcasts['bool']), + (eo['random-uint-data'], self.valid_upcasts['uint']), + (eo['random-int-data'], self.valid_upcasts['int']), + (eo['random-float32-data'], self.valid_upcasts['float32'])] + for test in tests: + X1 = test[0][::5, ::-2] + X2 = test[0][1::5, ::2] + try: + y1 = cdist(X1, X2, metric=metric) + except Exception as e: + e_cls = e.__class__ + if verbose > 2: + print(e_cls.__name__) + print(e) + for new_type in test[1]: + X1new = new_type(X1) + X2new = new_type(X2) + with pytest.raises(e_cls): + cdist(X1new, X2new, metric=metric) + else: + for new_type in test[1]: + y2 = cdist(new_type(X1), new_type(X2), metric=metric) + assert_allclose(y1, y2, rtol=eps, verbose=verbose > 2) + + @pytest.mark.skipif(sysconfig.get_platform() == 'win-arm64', reason="numpy#29442") + def test_cdist_out(self, metric): + # Test that out parameter works properly + eps = 1e-15 + X1 = eo['cdist-X1'] + X2 = eo['cdist-X2'] + out_r, out_c = X1.shape[0], X2.shape[0] + + kwargs = dict() + if metric == 'minkowski': + kwargs['p'] = 1.23 + out1 = np.empty((out_r, out_c), dtype=np.float64) + Y1 = cdist(X1, X2, metric, **kwargs) + Y2 = cdist(X1, X2, metric, out=out1, **kwargs) + + # test that output is numerically equivalent + assert_allclose(Y1, Y2, rtol=eps, verbose=verbose > 2) + + # test that Y_test1 and out1 are the same object + assert_(Y2 is out1) + + # test for incorrect shape + out2 = np.empty((out_r-1, out_c+1), dtype=np.float64) + with pytest.raises(ValueError): + cdist(X1, X2, metric, out=out2, **kwargs) + + # test for C-contiguous order + out3 = np.empty( + (2 * out_r, 2 * out_c), dtype=np.float64)[::2, ::2] + out4 = np.empty((out_r, out_c), dtype=np.float64, order='F') + with pytest.raises(ValueError): + cdist(X1, X2, metric, out=out3, **kwargs) + with pytest.raises(ValueError): + cdist(X1, X2, metric, out=out4, **kwargs) + + # test for incorrect dtype + out5 = np.empty((out_r, out_c), dtype=np.int64) + with pytest.raises(ValueError): + cdist(X1, X2, metric, out=out5, **kwargs) + + def test_striding(self, metric): + # test that striding is handled correct with calls to + # _copy_array_if_base_present + eps = 1e-15 + X1 = eo['cdist-X1'][::2, ::2] + X2 = eo['cdist-X2'][::2, ::2] + X1_copy = X1.copy() + X2_copy = X2.copy() + + # confirm equivalence + assert_equal(X1, X1_copy) + assert_equal(X2, X2_copy) + # confirm contiguity + assert_(not X1.flags.c_contiguous) + assert_(not X2.flags.c_contiguous) + assert_(X1_copy.flags.c_contiguous) + assert_(X2_copy.flags.c_contiguous) + + kwargs = dict() + if metric == 'minkowski': + kwargs['p'] = 1.23 + Y1 = cdist(X1, X2, metric, **kwargs) + Y2 = cdist(X1_copy, X2_copy, metric, **kwargs) + # test that output is numerically equivalent + assert_allclose(Y1, Y2, rtol=eps, verbose=verbose > 2) + + def test_cdist_refcount(self, metric): + x1 = np.random.rand(10, 10) + x2 = np.random.rand(10, 10) + + kwargs = dict() + if metric == 'minkowski': + kwargs['p'] = 1.23 + + out = cdist(x1, x2, metric=metric, **kwargs) + + # Check reference counts aren't messed up. If we only hold weak + # references, the arrays should be deallocated. + weak_refs = [weakref.ref(v) for v in (x1, x2, out)] + del x1, x2, out + + if IS_PYPY: + break_cycles() + assert all(weak_ref() is None for weak_ref in weak_refs) + + +class TestPdist: + + def setup_method(self): + self.rnd_eo_names = ['random-float32-data', 'random-int-data', + 'random-uint-data', 'random-double-data', + 'random-bool-data'] + self.valid_upcasts = {'bool': [np_ulong, np_long, np.float32, np.float64], + 'uint': [np_long, np.float32, np.float64], + 'int': [np.float32, np.float64], + 'float32': [np.float64]} + + def test_pdist_extra_args(self, metric): + # Tests that args and kwargs are correctly handled + X1 = [[1., 2.], [1.2, 2.3], [2.2, 2.3]] + kwargs = {"N0tV4l1D_p4raM": 3.14, "w": np.arange(2)} + args = [3.14] * 200 + + with pytest.raises(TypeError): + pdist(X1, metric=metric, **kwargs) + with pytest.raises(TypeError): + pdist(X1, metric=eval(metric), **kwargs) + with pytest.raises(TypeError): + pdist(X1, metric="test_" + metric, **kwargs) + with pytest.raises(TypeError): + pdist(X1, metric=metric, *args) + with pytest.raises(TypeError): + pdist(X1, metric=eval(metric), *args) + with pytest.raises(TypeError): + pdist(X1, metric="test_" + metric, *args) + + def test_pdist_extra_args_custom(self): + # Tests that args and kwargs are correctly handled + # also for custom metric + def _my_metric(x, y, arg, kwarg=1, kwarg2=2): + return arg + kwarg + kwarg2 + + X1 = [[1., 2.], [1.2, 2.3], [2.2, 2.3]] + kwargs = {"N0tV4l1D_p4raM": 3.14, "w": np.arange(2)} + args = [3.14] * 200 + + with pytest.raises(TypeError): + pdist(X1, _my_metric) + with pytest.raises(TypeError): + pdist(X1, _my_metric, *args) + with pytest.raises(TypeError): + pdist(X1, _my_metric, **kwargs) + with pytest.raises(TypeError): + pdist(X1, _my_metric, kwarg=2.2, kwarg2=3.3) + with pytest.raises(TypeError): + pdist(X1, _my_metric, 1, 2, kwarg=2.2) + with pytest.raises(TypeError): + pdist(X1, _my_metric, 1, 2, kwarg=2.2) + with pytest.raises(TypeError): + pdist(X1, _my_metric, 1.1, 2.2, 3.3) + with pytest.raises(TypeError): + pdist(X1, _my_metric, 1.1, 2.2) + with pytest.raises(TypeError): + pdist(X1, _my_metric, 1.1) + with pytest.raises(TypeError): + pdist(X1, _my_metric, 1.1, kwarg=2.2, kwarg2=3.3) + + # these should work + assert_allclose(pdist(X1, metric=_my_metric, + arg=1.1, kwarg2=3.3), 5.4) + + def test_pdist_euclidean_random(self): + eps = 1e-07 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-euclidean'] + Y_test1 = wpdist_no_const(X, 'euclidean') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_euclidean_random_u(self): + eps = 1e-07 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-euclidean'] + Y_test1 = wpdist_no_const(X, 'euclidean') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_euclidean_random_float32(self): + eps = 1e-07 + X = np.float32(eo['pdist-double-inp']) + Y_right = eo['pdist-euclidean'] + Y_test1 = wpdist_no_const(X, 'euclidean') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_euclidean_random_nonC(self): + eps = 1e-07 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-euclidean'] + Y_test2 = wpdist_no_const(X, 'test_euclidean') + assert_allclose(Y_test2, Y_right, rtol=eps) + + @pytest.mark.slow + def test_pdist_euclidean_iris_double(self): + eps = 1e-7 + X = eo['iris'] + Y_right = eo['pdist-euclidean-iris'] + Y_test1 = wpdist_no_const(X, 'euclidean') + assert_allclose(Y_test1, Y_right, rtol=eps) + + @pytest.mark.slow + def test_pdist_euclidean_iris_float32(self): + eps = 1e-5 + X = np.float32(eo['iris']) + Y_right = eo['pdist-euclidean-iris'] + Y_test1 = wpdist_no_const(X, 'euclidean') + assert_allclose(Y_test1, Y_right, rtol=eps, verbose=verbose > 2) + + @pytest.mark.slow + def test_pdist_euclidean_iris_nonC(self): + # Test pdist(X, 'test_euclidean') [the non-C implementation] on the + # Iris data set. + eps = 1e-7 + X = eo['iris'] + Y_right = eo['pdist-euclidean-iris'] + Y_test2 = wpdist_no_const(X, 'test_euclidean') + assert_allclose(Y_test2, Y_right, rtol=eps) + + def test_pdist_seuclidean_random(self): + eps = 1e-7 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-seuclidean'] + Y_test1 = pdist(X, 'seuclidean') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_seuclidean_random_float32(self): + eps = 1e-7 + X = np.float32(eo['pdist-double-inp']) + Y_right = eo['pdist-seuclidean'] + Y_test1 = pdist(X, 'seuclidean') + assert_allclose(Y_test1, Y_right, rtol=eps) + + # Check no error is raise when V has float32 dtype (#11171). + V = np.var(X, axis=0, ddof=1) + Y_test2 = pdist(X, 'seuclidean', V=V) + assert_allclose(Y_test2, Y_right, rtol=eps) + + def test_pdist_seuclidean_random_nonC(self): + # Test pdist(X, 'test_sqeuclidean') [the non-C implementation] + eps = 1e-07 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-seuclidean'] + Y_test2 = pdist(X, 'test_seuclidean') + assert_allclose(Y_test2, Y_right, rtol=eps) + + def test_pdist_seuclidean_iris(self): + eps = 1e-7 + X = eo['iris'] + Y_right = eo['pdist-seuclidean-iris'] + Y_test1 = pdist(X, 'seuclidean') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_seuclidean_iris_float32(self): + # Tests pdist(X, 'seuclidean') on the Iris data set (float32). + eps = 1e-5 + X = np.float32(eo['iris']) + Y_right = eo['pdist-seuclidean-iris'] + Y_test1 = pdist(X, 'seuclidean') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_seuclidean_iris_nonC(self): + # Test pdist(X, 'test_seuclidean') [the non-C implementation] on the + # Iris data set. + eps = 1e-7 + X = eo['iris'] + Y_right = eo['pdist-seuclidean-iris'] + Y_test2 = pdist(X, 'test_seuclidean') + assert_allclose(Y_test2, Y_right, rtol=eps) + + def test_pdist_cosine_random(self): + eps = 1e-7 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-cosine'] + Y_test1 = wpdist(X, 'cosine') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_cosine_random_float32(self): + eps = 1e-7 + X = np.float32(eo['pdist-double-inp']) + Y_right = eo['pdist-cosine'] + Y_test1 = wpdist(X, 'cosine') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_cosine_random_nonC(self): + # Test pdist(X, 'test_cosine') [the non-C implementation] + eps = 1e-7 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-cosine'] + Y_test2 = wpdist(X, 'test_cosine') + assert_allclose(Y_test2, Y_right, rtol=eps) + + @pytest.mark.slow + def test_pdist_cosine_iris(self): + eps = 1e-05 + X = eo['iris'] + Y_right = eo['pdist-cosine-iris'] + Y_test1 = wpdist(X, 'cosine') + assert_allclose(Y_test1, Y_right, atol=eps) + + @pytest.mark.slow + def test_pdist_cosine_iris_float32(self): + eps = 1e-05 + X = np.float32(eo['iris']) + Y_right = eo['pdist-cosine-iris'] + Y_test1 = wpdist(X, 'cosine') + assert_allclose(Y_test1, Y_right, atol=eps, verbose=verbose > 2) + + @pytest.mark.slow + def test_pdist_cosine_iris_nonC(self): + eps = 1e-05 + X = eo['iris'] + Y_right = eo['pdist-cosine-iris'] + Y_test2 = wpdist(X, 'test_cosine') + assert_allclose(Y_test2, Y_right, atol=eps) + + def test_pdist_cosine_bounds(self): + # Test adapted from @joernhees's example at gh-5208: case where + # cosine distance used to be negative. XXX: very sensitive to the + # specific norm computation. + x = np.abs(np.random.RandomState(1337).rand(91)) + X = np.vstack([x, x]) + assert_(wpdist(X, 'cosine')[0] >= 0, + msg='cosine distance should be non-negative') + + def test_pdist_cityblock_random(self): + eps = 1e-7 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-cityblock'] + Y_test1 = wpdist_no_const(X, 'cityblock') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_cityblock_random_float32(self): + eps = 1e-7 + X = np.float32(eo['pdist-double-inp']) + Y_right = eo['pdist-cityblock'] + Y_test1 = wpdist_no_const(X, 'cityblock') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_cityblock_random_nonC(self): + eps = 1e-7 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-cityblock'] + Y_test2 = wpdist_no_const(X, 'test_cityblock') + assert_allclose(Y_test2, Y_right, rtol=eps) + + @pytest.mark.slow + def test_pdist_cityblock_iris(self): + eps = 1e-14 + X = eo['iris'] + Y_right = eo['pdist-cityblock-iris'] + Y_test1 = wpdist_no_const(X, 'cityblock') + assert_allclose(Y_test1, Y_right, rtol=eps) + + @pytest.mark.slow + def test_pdist_cityblock_iris_float32(self): + eps = 1e-5 + X = np.float32(eo['iris']) + Y_right = eo['pdist-cityblock-iris'] + Y_test1 = wpdist_no_const(X, 'cityblock') + assert_allclose(Y_test1, Y_right, rtol=eps, verbose=verbose > 2) + + @pytest.mark.slow + def test_pdist_cityblock_iris_nonC(self): + # Test pdist(X, 'test_cityblock') [the non-C implementation] on the + # Iris data set. + eps = 1e-14 + X = eo['iris'] + Y_right = eo['pdist-cityblock-iris'] + Y_test2 = wpdist_no_const(X, 'test_cityblock') + assert_allclose(Y_test2, Y_right, rtol=eps) + + def test_pdist_correlation_random(self): + eps = 1e-7 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-correlation'] + Y_test1 = wpdist(X, 'correlation') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_correlation_random_float32(self): + eps = 1e-7 + X = np.float32(eo['pdist-double-inp']) + Y_right = eo['pdist-correlation'] + Y_test1 = wpdist(X, 'correlation') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_correlation_random_nonC(self): + eps = 1e-7 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-correlation'] + Y_test2 = wpdist(X, 'test_correlation') + assert_allclose(Y_test2, Y_right, rtol=eps) + + @pytest.mark.slow + def test_pdist_correlation_iris(self): + eps = 1e-7 + X = eo['iris'] + Y_right = eo['pdist-correlation-iris'] + Y_test1 = wpdist(X, 'correlation') + assert_allclose(Y_test1, Y_right, rtol=eps) + + @pytest.mark.slow + def test_pdist_correlation_iris_float32(self): + eps = 1e-7 + X = eo['iris'] + Y_right = np.float32(eo['pdist-correlation-iris']) + Y_test1 = wpdist(X, 'correlation') + assert_allclose(Y_test1, Y_right, rtol=eps, verbose=verbose > 2) + + @pytest.mark.slow + def test_pdist_correlation_iris_nonC(self): + if sys.maxsize > 2**32: + eps = 1e-7 + else: + pytest.skip("see gh-16456") + X = eo['iris'] + Y_right = eo['pdist-correlation-iris'] + Y_test2 = wpdist(X, 'test_correlation') + assert_allclose(Y_test2, Y_right, rtol=eps) + + @pytest.mark.parametrize("p", [0.1, 0.25, 1.0, 2.0, 3.2, np.inf]) + def test_pdist_minkowski_random_p(self, p): + eps = 1e-13 + X = eo['pdist-double-inp'] + Y1 = wpdist_no_const(X, 'minkowski', p=p) + Y2 = wpdist_no_const(X, 'test_minkowski', p=p) + assert_allclose(Y1, Y2, atol=0, rtol=eps) + + def test_pdist_minkowski_random(self): + eps = 1e-7 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-minkowski-3.2'] + Y_test1 = wpdist_no_const(X, 'minkowski', p=3.2) + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_minkowski_random_float32(self): + eps = 1e-7 + X = np.float32(eo['pdist-double-inp']) + Y_right = eo['pdist-minkowski-3.2'] + Y_test1 = wpdist_no_const(X, 'minkowski', p=3.2) + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_minkowski_random_nonC(self): + eps = 1e-7 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-minkowski-3.2'] + Y_test2 = wpdist_no_const(X, 'test_minkowski', p=3.2) + assert_allclose(Y_test2, Y_right, rtol=eps) + + @pytest.mark.slow + def test_pdist_minkowski_3_2_iris(self): + eps = 1e-7 + X = eo['iris'] + Y_right = eo['pdist-minkowski-3.2-iris'] + Y_test1 = wpdist_no_const(X, 'minkowski', p=3.2) + assert_allclose(Y_test1, Y_right, rtol=eps) + + @pytest.mark.slow + def test_pdist_minkowski_3_2_iris_float32(self): + eps = 1e-5 + X = np.float32(eo['iris']) + Y_right = eo['pdist-minkowski-3.2-iris'] + Y_test1 = wpdist_no_const(X, 'minkowski', p=3.2) + assert_allclose(Y_test1, Y_right, rtol=eps) + + @pytest.mark.slow + def test_pdist_minkowski_3_2_iris_nonC(self): + eps = 1e-7 + X = eo['iris'] + Y_right = eo['pdist-minkowski-3.2-iris'] + Y_test2 = wpdist_no_const(X, 'test_minkowski', p=3.2) + assert_allclose(Y_test2, Y_right, rtol=eps) + + @pytest.mark.slow + def test_pdist_minkowski_5_8_iris(self): + eps = 1e-7 + X = eo['iris'] + Y_right = eo['pdist-minkowski-5.8-iris'] + Y_test1 = wpdist_no_const(X, 'minkowski', p=5.8) + assert_allclose(Y_test1, Y_right, rtol=eps) + + @pytest.mark.slow + def test_pdist_minkowski_5_8_iris_float32(self): + eps = 1e-5 + X = np.float32(eo['iris']) + Y_right = eo['pdist-minkowski-5.8-iris'] + Y_test1 = wpdist_no_const(X, 'minkowski', p=5.8) + assert_allclose(Y_test1, Y_right, rtol=eps, verbose=verbose > 2) + + @pytest.mark.slow + def test_pdist_minkowski_5_8_iris_nonC(self): + eps = 1e-7 + X = eo['iris'] + Y_right = eo['pdist-minkowski-5.8-iris'] + Y_test2 = wpdist_no_const(X, 'test_minkowski', p=5.8) + assert_allclose(Y_test2, Y_right, rtol=eps) + + def test_pdist_mahalanobis(self): + # 1-dimensional observations + x = np.array([2.0, 2.0, 3.0, 5.0]).reshape(-1, 1) + dist = pdist(x, metric='mahalanobis') + assert_allclose(dist, [0.0, np.sqrt(0.5), np.sqrt(4.5), + np.sqrt(0.5), np.sqrt(4.5), np.sqrt(2.0)]) + + # 2-dimensional observations + x = np.array([[0, 0], [-1, 0], [0, 2], [1, 0], [0, -2]]) + dist = pdist(x, metric='mahalanobis') + rt2 = np.sqrt(2) + assert_allclose(dist, [rt2, rt2, rt2, rt2, 2, 2 * rt2, 2, 2, 2 * rt2, 2]) + + # Too few observations + with pytest.raises(ValueError): + wpdist([[0, 1], [2, 3]], metric='mahalanobis') + + def test_pdist_hamming_random(self): + eps = 1e-15 + X = eo['pdist-boolean-inp'] + Y_right = eo['pdist-hamming'] + Y_test1 = wpdist(X, 'hamming') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_hamming_random_float32(self): + eps = 1e-15 + X = np.float32(eo['pdist-boolean-inp']) + Y_right = eo['pdist-hamming'] + Y_test1 = wpdist(X, 'hamming') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_hamming_random_nonC(self): + eps = 1e-15 + X = eo['pdist-boolean-inp'] + Y_right = eo['pdist-hamming'] + Y_test2 = wpdist(X, 'test_hamming') + assert_allclose(Y_test2, Y_right, rtol=eps) + + def test_pdist_dhamming_random(self): + eps = 1e-15 + X = np.float64(eo['pdist-boolean-inp']) + Y_right = eo['pdist-hamming'] + Y_test1 = wpdist(X, 'hamming') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_dhamming_random_float32(self): + eps = 1e-15 + X = np.float32(eo['pdist-boolean-inp']) + Y_right = eo['pdist-hamming'] + Y_test1 = wpdist(X, 'hamming') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_dhamming_random_nonC(self): + eps = 1e-15 + X = np.float64(eo['pdist-boolean-inp']) + Y_right = eo['pdist-hamming'] + Y_test2 = wpdist(X, 'test_hamming') + assert_allclose(Y_test2, Y_right, rtol=eps) + + def test_pdist_jensenshannon_random(self): + eps = 1e-11 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-jensenshannon'] + Y_test1 = pdist(X, 'jensenshannon') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_jensenshannon_random_float32(self): + eps = 1e-8 + X = np.float32(eo['pdist-double-inp']) + Y_right = eo['pdist-jensenshannon'] + Y_test1 = pdist(X, 'jensenshannon') + assert_allclose(Y_test1, Y_right, rtol=eps, verbose=verbose > 2) + + def test_pdist_jensenshannon_random_nonC(self): + eps = 1e-11 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-jensenshannon'] + Y_test2 = pdist(X, 'test_jensenshannon') + assert_allclose(Y_test2, Y_right, rtol=eps) + + def test_pdist_jensenshannon_iris(self): + if _is_32bit(): + # Test failing on 32-bit Linux on Azure otherwise, see gh-12810 + eps = 2.5e-10 + else: + eps = 1e-12 + + X = eo['iris'] + Y_right = eo['pdist-jensenshannon-iris'] + Y_test1 = pdist(X, 'jensenshannon') + assert_allclose(Y_test1, Y_right, atol=eps) + + def test_pdist_jensenshannon_iris_float32(self): + eps = 1e-06 + X = np.float32(eo['iris']) + Y_right = eo['pdist-jensenshannon-iris'] + Y_test1 = pdist(X, 'jensenshannon') + assert_allclose(Y_test1, Y_right, atol=eps, verbose=verbose > 2) + + def test_pdist_jensenshannon_iris_nonC(self): + eps = 5e-5 + X = eo['iris'] + Y_right = eo['pdist-jensenshannon-iris'] + Y_test2 = pdist(X, 'test_jensenshannon') + assert_allclose(Y_test2, Y_right, rtol=eps) + + def test_pdist_matching_mtica1(self): + # Test matching(*,*) with mtica example #1 (nums). + m = wmatching(np.array([1, 0, 1, 1, 0]), + np.array([1, 1, 0, 1, 1])) + m2 = wmatching(np.array([1, 0, 1, 1, 0], dtype=bool), + np.array([1, 1, 0, 1, 1], dtype=bool)) + assert_allclose(m, 0.6, rtol=0, atol=1e-10) + assert_allclose(m2, 0.6, rtol=0, atol=1e-10) + + def test_pdist_matching_mtica2(self): + # Test matching(*,*) with mtica example #2. + m = wmatching(np.array([1, 0, 1]), + np.array([1, 1, 0])) + m2 = wmatching(np.array([1, 0, 1], dtype=bool), + np.array([1, 1, 0], dtype=bool)) + assert_allclose(m, 2 / 3, rtol=0, atol=1e-10) + assert_allclose(m2, 2 / 3, rtol=0, atol=1e-10) + + def test_pdist_yule_mtica1(self): + m = wyule(np.array([1, 0, 1, 1, 0]), + np.array([1, 1, 0, 1, 1])) + m2 = wyule(np.array([1, 0, 1, 1, 0], dtype=bool), + np.array([1, 1, 0, 1, 1], dtype=bool)) + if verbose > 2: + print(m) + assert_allclose(m, 2, rtol=0, atol=1e-10) + assert_allclose(m2, 2, rtol=0, atol=1e-10) + + def test_pdist_yule_mtica2(self): + m = wyule(np.array([1, 0, 1]), + np.array([1, 1, 0])) + m2 = wyule(np.array([1, 0, 1], dtype=bool), + np.array([1, 1, 0], dtype=bool)) + if verbose > 2: + print(m) + assert_allclose(m, 2, rtol=0, atol=1e-10) + assert_allclose(m2, 2, rtol=0, atol=1e-10) + + def test_pdist_dice_mtica1(self): + m = wdice(np.array([1, 0, 1, 1, 0]), + np.array([1, 1, 0, 1, 1])) + m2 = wdice(np.array([1, 0, 1, 1, 0], dtype=bool), + np.array([1, 1, 0, 1, 1], dtype=bool)) + if verbose > 2: + print(m) + assert_allclose(m, 3 / 7, rtol=0, atol=1e-10) + assert_allclose(m2, 3 / 7, rtol=0, atol=1e-10) + + def test_pdist_dice_mtica2(self): + m = wdice(np.array([1, 0, 1]), + np.array([1, 1, 0])) + m2 = wdice(np.array([1, 0, 1], dtype=bool), + np.array([1, 1, 0], dtype=bool)) + if verbose > 2: + print(m) + assert_allclose(m, 0.5, rtol=0, atol=1e-10) + assert_allclose(m2, 0.5, rtol=0, atol=1e-10) + + def test_pdist_sokalsneath_mtica1(self): + m = sokalsneath(np.array([1, 0, 1, 1, 0]), + np.array([1, 1, 0, 1, 1])) + m2 = sokalsneath(np.array([1, 0, 1, 1, 0], dtype=bool), + np.array([1, 1, 0, 1, 1], dtype=bool)) + if verbose > 2: + print(m) + assert_allclose(m, 3 / 4, rtol=0, atol=1e-10) + assert_allclose(m2, 3 / 4, rtol=0, atol=1e-10) + + def test_pdist_sokalsneath_mtica2(self): + m = wsokalsneath(np.array([1, 0, 1]), + np.array([1, 1, 0])) + m2 = wsokalsneath(np.array([1, 0, 1], dtype=bool), + np.array([1, 1, 0], dtype=bool)) + if verbose > 2: + print(m) + assert_allclose(m, 4 / 5, rtol=0, atol=1e-10) + assert_allclose(m2, 4 / 5, rtol=0, atol=1e-10) + + def test_pdist_rogerstanimoto_mtica1(self): + m = wrogerstanimoto(np.array([1, 0, 1, 1, 0]), + np.array([1, 1, 0, 1, 1])) + m2 = wrogerstanimoto(np.array([1, 0, 1, 1, 0], dtype=bool), + np.array([1, 1, 0, 1, 1], dtype=bool)) + if verbose > 2: + print(m) + assert_allclose(m, 3 / 4, rtol=0, atol=1e-10) + assert_allclose(m2, 3 / 4, rtol=0, atol=1e-10) + + def test_pdist_rogerstanimoto_mtica2(self): + m = wrogerstanimoto(np.array([1, 0, 1]), + np.array([1, 1, 0])) + m2 = wrogerstanimoto(np.array([1, 0, 1], dtype=bool), + np.array([1, 1, 0], dtype=bool)) + if verbose > 2: + print(m) + assert_allclose(m, 4 / 5, rtol=0, atol=1e-10) + assert_allclose(m2, 4 / 5, rtol=0, atol=1e-10) + + def test_pdist_russellrao_mtica1(self): + m = wrussellrao(np.array([1, 0, 1, 1, 0]), + np.array([1, 1, 0, 1, 1])) + m2 = wrussellrao(np.array([1, 0, 1, 1, 0], dtype=bool), + np.array([1, 1, 0, 1, 1], dtype=bool)) + if verbose > 2: + print(m) + assert_allclose(m, 3 / 5, rtol=0, atol=1e-10) + assert_allclose(m2, 3 / 5, rtol=0, atol=1e-10) + + def test_pdist_russellrao_mtica2(self): + m = wrussellrao(np.array([1, 0, 1]), + np.array([1, 1, 0])) + m2 = wrussellrao(np.array([1, 0, 1], dtype=bool), + np.array([1, 1, 0], dtype=bool)) + if verbose > 2: + print(m) + assert_allclose(m, 2 / 3, rtol=0, atol=1e-10) + assert_allclose(m2, 2 / 3, rtol=0, atol=1e-10) + + @pytest.mark.slow + def test_pdist_canberra_match(self): + D = eo['iris'] + if verbose > 2: + print(D.shape, D.dtype) + eps = 1e-15 + y1 = wpdist_no_const(D, "canberra") + y2 = wpdist_no_const(D, "test_canberra") + assert_allclose(y1, y2, rtol=eps, verbose=verbose > 2) + + def test_pdist_canberra_ticket_711(self): + # Test pdist(X, 'canberra') to see if Canberra gives the right result + # as reported on gh-1238. + eps = 1e-8 + pdist_y = wpdist_no_const(([3.3], [3.4]), "canberra") + right_y = 0.01492537 + assert_allclose(pdist_y, right_y, atol=eps, verbose=verbose > 2) + + @skip_xp_invalid_arg + def test_pdist_custom_notdouble(self): + # tests that when using a custom metric the data type is not altered + class myclass: + pass + + def _my_metric(x, y): + if not isinstance(x[0], myclass) or not isinstance(y[0], myclass): + raise ValueError("Type has been changed") + return 1.123 + data = np.array([[myclass()], [myclass()]], dtype=object) + pdist_y = pdist(data, metric=_my_metric) + right_y = 1.123 + assert_equal(pdist_y, right_y, verbose=verbose > 2) + + def _check_calling_conventions(self, X, metric, eps=1e-07, **kwargs): + # helper function for test_pdist_calling_conventions + try: + y1 = pdist(X, metric=metric, **kwargs) + y2 = pdist(X, metric=eval(metric), **kwargs) + y3 = pdist(X, metric="test_" + metric, **kwargs) + except Exception as e: + e_cls = e.__class__ + if verbose > 2: + print(e_cls.__name__) + print(e) + with pytest.raises(e_cls): + pdist(X, metric=metric, **kwargs) + with pytest.raises(e_cls): + pdist(X, metric=eval(metric), **kwargs) + with pytest.raises(e_cls): + pdist(X, metric="test_" + metric, **kwargs) + else: + assert_allclose(y1, y2, rtol=eps, verbose=verbose > 2) + assert_allclose(y1, y3, rtol=eps, verbose=verbose > 2) + + def test_pdist_calling_conventions(self, metric): + # Ensures that specifying the metric with a str or scipy function + # gives the same behaviour (i.e. same result or same exception). + # NOTE: The correctness should be checked within each metric tests. + # NOTE: Extra args should be checked with a dedicated test + for eo_name in self.rnd_eo_names: + # subsampling input data to speed-up tests + # NOTE: num samples needs to be > than dimensions for mahalanobis + X = eo[eo_name][::5, ::2] + if verbose > 2: + print("testing: ", metric, " with: ", eo_name) + if metric in {'dice', 'yule', 'matching', 'rogerstanimoto', 'russellrao', + 'sokalsneath'} and 'bool' not in eo_name: + # python version permits non-bools e.g. for fuzzy logic + continue + self._check_calling_conventions(X, metric) + + # Testing built-in metrics with extra args + if metric == "seuclidean": + V = np.var(X.astype(np.float64), axis=0, ddof=1) + self._check_calling_conventions(X, metric, V=V) + elif metric == "mahalanobis": + V = np.atleast_2d(np.cov(X.astype(np.float64).T)) + VI = np.array(np.linalg.inv(V).T) + self._check_calling_conventions(X, metric, VI=VI) + + def test_pdist_dtype_equivalence(self, metric): + # Tests that the result is not affected by type up-casting + eps = 1e-07 + tests = [(eo['random-bool-data'], self.valid_upcasts['bool']), + (eo['random-uint-data'], self.valid_upcasts['uint']), + (eo['random-int-data'], self.valid_upcasts['int']), + (eo['random-float32-data'], self.valid_upcasts['float32'])] + for test in tests: + X1 = test[0][::5, ::2] + try: + y1 = pdist(X1, metric=metric) + except Exception as e: + e_cls = e.__class__ + if verbose > 2: + print(e_cls.__name__) + print(e) + for new_type in test[1]: + X2 = new_type(X1) + with pytest.raises(e_cls): + pdist(X2, metric=metric) + else: + for new_type in test[1]: + y2 = pdist(new_type(X1), metric=metric) + assert_allclose(y1, y2, rtol=eps, verbose=verbose > 2) + + def test_pdist_out(self, metric): + # Test that out parameter works properly + eps = 1e-15 + X = eo['random-float32-data'][::5, ::2] + out_size = int((X.shape[0] * (X.shape[0] - 1)) / 2) + + kwargs = dict() + if metric == 'minkowski': + kwargs['p'] = 1.23 + out1 = np.empty(out_size, dtype=np.float64) + Y_right = pdist(X, metric, **kwargs) + Y_test1 = pdist(X, metric, out=out1, **kwargs) + + # test that output is numerically equivalent + assert_allclose(Y_test1, Y_right, rtol=eps) + + # test that Y_test1 and out1 are the same object + assert_(Y_test1 is out1) + + # test for incorrect shape + out2 = np.empty(out_size + 3, dtype=np.float64) + with pytest.raises(ValueError): + pdist(X, metric, out=out2, **kwargs) + + # test for (C-)contiguous output + out3 = np.empty(2 * out_size, dtype=np.float64)[::2] + with pytest.raises(ValueError): + pdist(X, metric, out=out3, **kwargs) + + # test for incorrect dtype + out5 = np.empty(out_size, dtype=np.int64) + with pytest.raises(ValueError): + pdist(X, metric, out=out5, **kwargs) + + def test_striding(self, metric): + # test that striding is handled correct with calls to + # _copy_array_if_base_present + eps = 1e-15 + X = eo['random-float32-data'][::5, ::2] + X_copy = X.copy() + + # confirm contiguity + assert_(not X.flags.c_contiguous) + assert_(X_copy.flags.c_contiguous) + + kwargs = dict() + if metric == 'minkowski': + kwargs['p'] = 1.23 + Y1 = pdist(X, metric, **kwargs) + Y2 = pdist(X_copy, metric, **kwargs) + # test that output is numerically equivalent + assert_allclose(Y1, Y2, rtol=eps, verbose=verbose > 2) + +class TestSomeDistanceFunctions: + + def setup_method(self): + # 1D arrays + x = np.array([1.0, 2.0, 3.0]) + y = np.array([1.0, 1.0, 5.0]) + + self.cases = [(x, y)] + + def test_minkowski(self): + for x, y in self.cases: + dist1 = minkowski(x, y, p=1) + assert_almost_equal(dist1, 3.0) + dist1p5 = minkowski(x, y, p=1.5) + assert_almost_equal(dist1p5, (1.0 + 2.0**1.5)**(2. / 3)) + dist2 = minkowski(x, y, p=2) + assert_almost_equal(dist2, 5.0 ** 0.5) + dist0p25 = minkowski(x, y, p=0.25) + assert_almost_equal(dist0p25, (1.0 + 2.0 ** 0.25) ** 4) + + # Check that casting input to minimum scalar type doesn't affect result + # (issue #10262). This could be extended to more test inputs with + # np.min_scalar_type(np.max(input_matrix)). + a = np.array([352, 916]) + b = np.array([350, 660]) + assert_equal(minkowski(a, b), + minkowski(a.astype('uint16'), b.astype('uint16'))) + + def test_euclidean(self): + for x, y in self.cases: + dist = weuclidean(x, y) + assert_almost_equal(dist, np.sqrt(5)) + + def test_sqeuclidean(self): + for x, y in self.cases: + dist = wsqeuclidean(x, y) + assert_almost_equal(dist, 5.0) + + def test_cosine(self): + for x, y in self.cases: + dist = wcosine(x, y) + assert_almost_equal(dist, 1.0 - 18.0 / (np.sqrt(14) * np.sqrt(27))) + + def test_cosine_output_dtype(self): + # Regression test for gh-19541 + assert isinstance(wcorrelation([1, 1], [1, 1], centered=False), float) + assert isinstance(wcosine([1, 1], [1, 1]), float) + + def test_correlation(self): + xm = np.array([-1.0, 0, 1.0]) + ym = np.array([-4.0 / 3, -4.0 / 3, 5.0 - 7.0 / 3]) + for x, y in self.cases: + dist = wcorrelation(x, y) + assert_almost_equal(dist, 1.0 - np.dot(xm, ym) / (norm(xm) * norm(ym))) + + def test_correlation_positive(self): + # Regression test for gh-12320 (negative return value due to rounding + x = np.array([0., 0., 0., 0., 0., 0., -2., 0., 0., 0., -2., -2., -2., + 0., -2., 0., -2., 0., 0., -1., -2., 0., 1., 0., 0., -2., + 0., 0., -2., 0., -2., -2., -2., -2., -2., -2., 0.]) + y = np.array([1., 1., 1., 1., 1., 1., -1., 1., 1., 1., -1., -1., -1., + 1., -1., 1., -1., 1., 1., 0., -1., 1., 2., 1., 1., -1., + 1., 1., -1., 1., -1., -1., -1., -1., -1., -1., 1.]) + dist = correlation(x, y) + assert 0 <= dist <= 10 * np.finfo(np.float64).eps + + @pytest.mark.filterwarnings('ignore:Casting complex') + @pytest.mark.parametrize("func", [correlation, cosine]) + def test_corr_dep_complex(self, func): + x = [1+0j, 2+0j] + y = [3+0j, 4+0j] + with pytest.raises(TypeError, match="real"): + func(x, y) + + def test_mahalanobis(self): + x = np.array([1.0, 2.0, 3.0]) + y = np.array([1.0, 1.0, 5.0]) + vi = np.array([[2.0, 1.0, 0.0], [1.0, 2.0, 1.0], [0.0, 1.0, 2.0]]) + for x, y in self.cases: + dist = mahalanobis(x, y, vi) + assert_almost_equal(dist, np.sqrt(6.0)) + + +class TestSquareForm: + checked_dtypes = [np.float64, np.float32, np.int32, np.int8, bool] + + def test_squareform_matrix(self): + for dtype in self.checked_dtypes: + self.check_squareform_matrix(dtype) + + def test_squareform_vector(self): + for dtype in self.checked_dtypes: + self.check_squareform_vector(dtype) + + def check_squareform_matrix(self, dtype): + A = np.zeros((0, 0), dtype=dtype) + rA = squareform(A) + assert_equal(rA.shape, (0,)) + assert_equal(rA.dtype, dtype) + + A = np.zeros((1, 1), dtype=dtype) + rA = squareform(A) + assert_equal(rA.shape, (0,)) + assert_equal(rA.dtype, dtype) + + A = np.array([[0, 4.2], [4.2, 0]], dtype=dtype) + rA = squareform(A) + assert_equal(rA.shape, (1,)) + assert_equal(rA.dtype, dtype) + assert_array_equal(rA, np.array([4.2], dtype=dtype)) + + def check_squareform_vector(self, dtype): + v = np.zeros((0,), dtype=dtype) + rv = squareform(v) + assert_equal(rv.shape, (1, 1)) + assert_equal(rv.dtype, dtype) + assert_array_equal(rv, [[0]]) + + v = np.array([8.3], dtype=dtype) + rv = squareform(v) + assert_equal(rv.shape, (2, 2)) + assert_equal(rv.dtype, dtype) + assert_array_equal(rv, np.array([[0, 8.3], [8.3, 0]], dtype=dtype)) + + def test_squareform_multi_matrix(self): + for n in range(2, 5): + self.check_squareform_multi_matrix(n) + + def check_squareform_multi_matrix(self, n): + X = np.random.rand(n, 4) + Y = wpdist_no_const(X) + assert_equal(len(Y.shape), 1) + A = squareform(Y) + Yr = squareform(A) + s = A.shape + k = 0 + if verbose >= 3: + print(A.shape, Y.shape, Yr.shape) + assert_equal(len(s), 2) + assert_equal(len(Yr.shape), 1) + assert_equal(s[0], s[1]) + for i in range(0, s[0]): + for j in range(i + 1, s[1]): + if i != j: + assert_equal(A[i, j], Y[k]) + k += 1 + else: + assert_equal(A[i, j], 0) + + +class TestNumObsY: + + def test_num_obs_y_multi_matrix(self): + for n in range(2, 10): + X = np.random.rand(n, 4) + Y = wpdist_no_const(X) + assert_equal(num_obs_y(Y), n) + + def test_num_obs_y_1(self): + # Tests num_obs_y(y) on a condensed distance matrix over 1 + # observations. Expecting exception. + with pytest.raises(ValueError): + self.check_y(1) + + def test_num_obs_y_2(self): + # Tests num_obs_y(y) on a condensed distance matrix over 2 + # observations. + assert_(self.check_y(2)) + + def test_num_obs_y_3(self): + assert_(self.check_y(3)) + + def test_num_obs_y_4(self): + assert_(self.check_y(4)) + + def test_num_obs_y_5_10(self): + for i in range(5, 16): + self.minit(i) + + def test_num_obs_y_2_100(self): + # Tests num_obs_y(y) on 100 improper condensed distance matrices. + # Expecting exception. + a = set() + for n in range(2, 16): + a.add(n * (n - 1) / 2) + for i in range(5, 105): + if i not in a: + with pytest.raises(ValueError): + self.bad_y(i) + + def minit(self, n): + assert_(self.check_y(n)) + + def bad_y(self, n): + y = np.random.rand(n) + return num_obs_y(y) + + def check_y(self, n): + return num_obs_y(self.make_y(n)) == n + + def make_y(self, n): + return np.random.rand((n * (n - 1)) // 2) + + +class TestNumObsDM: + + def test_num_obs_dm_multi_matrix(self): + for n in range(1, 10): + X = np.random.rand(n, 4) + Y = wpdist_no_const(X) + A = squareform(Y) + if verbose >= 3: + print(A.shape, Y.shape) + assert_equal(num_obs_dm(A), n) + + def test_num_obs_dm_0(self): + # Tests num_obs_dm(D) on a 0x0 distance matrix. Expecting exception. + assert_(self.check_D(0)) + + def test_num_obs_dm_1(self): + # Tests num_obs_dm(D) on a 1x1 distance matrix. + assert_(self.check_D(1)) + + def test_num_obs_dm_2(self): + assert_(self.check_D(2)) + + def test_num_obs_dm_3(self): + assert_(self.check_D(2)) + + def test_num_obs_dm_4(self): + assert_(self.check_D(4)) + + def check_D(self, n): + return num_obs_dm(self.make_D(n)) == n + + def make_D(self, n): + return np.random.rand(n, n) + + +def is_valid_dm_throw(D): + return is_valid_dm(D, throw=True) + + +class TestIsValidDM: + + def test_is_valid_dm_improper_shape_1D_E(self): + D = np.zeros((5,), dtype=np.float64) + with pytest.raises(ValueError): + is_valid_dm_throw(D) + + def test_is_valid_dm_improper_shape_1D_F(self): + D = np.zeros((5,), dtype=np.float64) + assert_equal(is_valid_dm(D), False) + + def test_is_valid_dm_improper_shape_3D_E(self): + D = np.zeros((3, 3, 3), dtype=np.float64) + with pytest.raises(ValueError): + is_valid_dm_throw(D) + + def test_is_valid_dm_improper_shape_3D_F(self): + D = np.zeros((3, 3, 3), dtype=np.float64) + assert_equal(is_valid_dm(D), False) + + def test_is_valid_dm_nonzero_diagonal_E(self): + y = np.random.rand(10) + D = squareform(y) + for i in range(0, 5): + D[i, i] = 2.0 + with pytest.raises(ValueError): + is_valid_dm_throw(D) + + def test_is_valid_dm_nonzero_diagonal_F(self): + y = np.random.rand(10) + D = squareform(y) + for i in range(0, 5): + D[i, i] = 2.0 + assert_equal(is_valid_dm(D), False) + + def test_is_valid_dm_asymmetric_E(self): + y = np.random.rand(10) + D = squareform(y) + D[1, 3] = D[3, 1] + 1 + with pytest.raises(ValueError): + is_valid_dm_throw(D) + + def test_is_valid_dm_asymmetric_F(self): + y = np.random.rand(10) + D = squareform(y) + D[1, 3] = D[3, 1] + 1 + assert_equal(is_valid_dm(D), False) + + def test_is_valid_dm_correct_1_by_1(self): + D = np.zeros((1, 1), dtype=np.float64) + assert_equal(is_valid_dm(D), True) + + def test_is_valid_dm_correct_2_by_2(self): + y = np.random.rand(1) + D = squareform(y) + assert_equal(is_valid_dm(D), True) + + def test_is_valid_dm_correct_3_by_3(self): + y = np.random.rand(3) + D = squareform(y) + assert_equal(is_valid_dm(D), True) + + def test_is_valid_dm_correct_4_by_4(self): + y = np.random.rand(6) + D = squareform(y) + assert_equal(is_valid_dm(D), True) + + def test_is_valid_dm_correct_5_by_5(self): + y = np.random.rand(10) + D = squareform(y) + assert_equal(is_valid_dm(D), True) + + +def is_valid_y_throw(y): + return is_valid_y(y, throw=True) + + +class TestIsValidY: + # If test case name ends on "_E" then an exception is expected for the + # given input, if it ends in "_F" then False is expected for the is_valid_y + # check. Otherwise the input is expected to be valid. + + def test_is_valid_y_improper_shape_2D_E(self): + y = np.zeros((3, 3,), dtype=np.float64) + with pytest.raises(ValueError): + is_valid_y_throw(y) + + def test_is_valid_y_improper_shape_2D_F(self): + y = np.zeros((3, 3,), dtype=np.float64) + assert_equal(is_valid_y(y), False) + + def test_is_valid_y_improper_shape_3D_E(self): + y = np.zeros((3, 3, 3), dtype=np.float64) + with pytest.raises(ValueError): + is_valid_y_throw(y) + + def test_is_valid_y_improper_shape_3D_F(self): + y = np.zeros((3, 3, 3), dtype=np.float64) + assert_equal(is_valid_y(y), False) + + def test_is_valid_y_correct_2_by_2(self): + y = self.correct_n_by_n(2) + assert_equal(is_valid_y(y), True) + + def test_is_valid_y_correct_3_by_3(self): + y = self.correct_n_by_n(3) + assert_equal(is_valid_y(y), True) + + def test_is_valid_y_correct_4_by_4(self): + y = self.correct_n_by_n(4) + assert_equal(is_valid_y(y), True) + + def test_is_valid_y_correct_5_by_5(self): + y = self.correct_n_by_n(5) + assert_equal(is_valid_y(y), True) + + def test_is_valid_y_2_100(self): + a = set() + for n in range(2, 16): + a.add(n * (n - 1) / 2) + for i in range(5, 105): + if i not in a: + with pytest.raises(ValueError): + self.bad_y(i) + + def bad_y(self, n): + y = np.random.rand(n) + return is_valid_y(y, throw=True) + + def correct_n_by_n(self, n): + y = np.random.rand((n * (n - 1)) // 2) + return y + + +@pytest.mark.parametrize("p", [-10.0, -0.5, 0.0]) +def test_bad_p(p): + # Raise ValueError if p <=0. + with pytest.raises(ValueError): + minkowski([1, 2], [3, 4], p) + with pytest.raises(ValueError): + minkowski([1, 2], [3, 4], p, [1, 1]) + + +def test_sokalsneath_all_false(): + # Regression test for ticket #876 + with pytest.raises(ValueError): + sokalsneath([False, False, False], [False, False, False]) + + +def test_canberra(): + # Regression test for ticket #1430. + assert_equal(wcanberra([1, 2, 3], [2, 4, 6]), 1) + assert_equal(wcanberra([1, 1, 0, 0], [1, 0, 1, 0]), 2) + + +def test_braycurtis(): + # Regression test for ticket #1430. + assert_almost_equal(wbraycurtis([1, 2, 3], [2, 4, 6]), 1. / 3, decimal=15) + assert_almost_equal(wbraycurtis([1, 1, 0, 0], [1, 0, 1, 0]), 0.5, decimal=15) + + +def test_euclideans(): + # Regression test for ticket #1328. + x1 = np.array([1, 1, 1]) + x2 = np.array([0, 0, 0]) + + # Basic test of the calculation. + assert_almost_equal(wsqeuclidean(x1, x2), 3.0, decimal=14) + assert_almost_equal(weuclidean(x1, x2), np.sqrt(3), decimal=14) + + # Check flattening for (1, N) or (N, 1) inputs + with pytest.raises(ValueError, match="Input vector should be 1-D"): + weuclidean(x1[np.newaxis, :], x2[np.newaxis, :]), np.sqrt(3) + with pytest.raises(ValueError, match="Input vector should be 1-D"): + wsqeuclidean(x1[np.newaxis, :], x2[np.newaxis, :]) + with pytest.raises(ValueError, match="Input vector should be 1-D"): + wsqeuclidean(x1[:, np.newaxis], x2[:, np.newaxis]) + + # Distance metrics only defined for vectors (= 1-D) + x = np.arange(4).reshape(2, 2) + with pytest.raises(ValueError): + weuclidean(x, x) + with pytest.raises(ValueError): + wsqeuclidean(x, x) + + # Another check, with random data. + rs = np.random.RandomState(1234567890) + x = rs.rand(10) + y = rs.rand(10) + d1 = weuclidean(x, y) + d2 = wsqeuclidean(x, y) + assert_almost_equal(d1**2, d2, decimal=14) + + +def test_hamming_unequal_length(): + # Regression test for gh-4290. + x = [0, 0, 1] + y = [1, 0, 1, 0] + # Used to give an AttributeError from ndarray.mean called on bool + with pytest.raises(ValueError): + whamming(x, y) + + +def test_hamming_unequal_length_with_w(): + u = [0, 0, 1] + v = [0, 0, 1] + w = [1, 0, 1, 0] + msg = "'w' should have the same length as 'u' and 'v'." + with pytest.raises(ValueError, match=msg): + whamming(u, v, w) + + +def test_hamming_string_array(): + # https://github.com/scikit-learn/scikit-learn/issues/4014 + a = np.array(['eggs', 'spam', 'spam', 'eggs', 'spam', 'spam', 'spam', + 'spam', 'spam', 'spam', 'spam', 'eggs', 'eggs', 'spam', + 'eggs', 'eggs', 'eggs', 'eggs', 'eggs', 'spam'], + dtype='|S4') + b = np.array(['eggs', 'spam', 'spam', 'eggs', 'eggs', 'spam', 'spam', + 'spam', 'spam', 'eggs', 'spam', 'eggs', 'spam', 'eggs', + 'spam', 'spam', 'eggs', 'spam', 'spam', 'eggs'], + dtype='|S4') + desired = 0.45 + assert_allclose(whamming(a, b), desired) + + +def test_minkowski_w(): + # Regression test for gh-8142. + arr_in = np.array([[83.33333333, 100., 83.33333333, 100., 36., + 60., 90., 150., 24., 48.], + [83.33333333, 100., 83.33333333, 100., 36., + 60., 90., 150., 24., 48.]]) + p0 = pdist(arr_in, metric='minkowski', p=1, w=None) + c0 = cdist(arr_in, arr_in, metric='minkowski', p=1, w=None) + p1 = pdist(arr_in, metric='minkowski', p=1) + c1 = cdist(arr_in, arr_in, metric='minkowski', p=1) + + assert_allclose(p0, p1, rtol=1e-15) + assert_allclose(c0, c1, rtol=1e-15) + + +def test_sqeuclidean_dtypes(): + # Assert that sqeuclidean returns the right types of values. + # Integer types should be converted to floating for stability. + # Floating point types should be the same as the input. + x = [1, 2, 3] + y = [4, 5, 6] + + for dtype in [np.int8, np.int16, np.int32, np.int64]: + d = wsqeuclidean(np.asarray(x, dtype=dtype), np.asarray(y, dtype=dtype)) + assert_(np.issubdtype(d.dtype, np.floating)) + + for dtype in [np.uint8, np.uint16, np.uint32, np.uint64]: + umax = np.iinfo(dtype).max + d1 = wsqeuclidean([0], np.asarray([umax], dtype=dtype)) + d2 = wsqeuclidean(np.asarray([umax], dtype=dtype), [0]) + + assert_equal(d1, d2) + assert_equal(d1, np.float64(umax)**2) + + dtypes = [np.float32, np.float64, np.complex64, np.complex128] + for dtype in ['float16', 'float128']: + # These aren't present in older numpy versions; float128 may also not + # be present on all platforms. + if hasattr(np, dtype): + dtypes.append(getattr(np, dtype)) + + for dtype in dtypes: + d = wsqeuclidean(np.asarray(x, dtype=dtype), np.asarray(y, dtype=dtype)) + assert_equal(d.dtype, dtype) + + +def test_modifies_input(metric): + # test whether cdist or pdist modifies input arrays + X1 = np.asarray([[1., 2., 3.], + [1.2, 2.3, 3.4], + [2.2, 2.3, 4.4], + [22.2, 23.3, 44.4]]) + X1_copy = X1.copy() + cdist(X1, X1, metric) + pdist(X1, metric) + assert_array_equal(X1, X1_copy) + + +def test_Xdist_deprecated_args(metric): + # testing both cdist and pdist deprecated warnings + X1 = np.asarray([[1., 2., 3.], + [1.2, 2.3, 3.4], + [2.2, 2.3, 4.4], + [22.2, 23.3, 44.4]]) + + with pytest.raises(TypeError): + cdist(X1, X1, metric, 2.) + + with pytest.raises(TypeError): + pdist(X1, metric, 2.) + + for arg in ["p", "V", "VI"]: + kwargs = {arg: np.asarray(1.)} + + if ((arg == "V" and metric == "seuclidean") + or (arg == "VI" and metric == "mahalanobis") + or (arg == "p" and metric == "minkowski")): + continue + + with pytest.raises(TypeError): + cdist(X1, X1, metric, **kwargs) + + with pytest.raises(TypeError): + pdist(X1, metric, **kwargs) + + +def test_Xdist_non_negative_weights(metric): + X = eo['random-float32-data'][::5, ::2] + w = np.ones(X.shape[1]) + w[::5] = -w[::5] + + if metric in ['seuclidean', 'mahalanobis', 'jensenshannon']: + pytest.skip("not applicable") + + for m in [metric, eval(metric), "test_" + metric]: + with pytest.raises(ValueError): + pdist(X, m, w=w) + with pytest.raises(ValueError): + cdist(X, X, m, w=w) + + +def test__validate_vector(): + x = [1, 2, 3] + y = _validate_vector(x) + assert_array_equal(y, x) + + y = _validate_vector(x, dtype=np.float64) + assert_array_equal(y, x) + assert_equal(y.dtype, np.float64) + + x = [1] + y = _validate_vector(x) + assert_equal(y.ndim, 1) + assert_equal(y, x) + + x = 1 + with pytest.raises(ValueError, match="Input vector should be 1-D"): + _validate_vector(x) + + x = np.arange(5).reshape(1, -1, 1) + with pytest.raises(ValueError, match="Input vector should be 1-D"): + _validate_vector(x) + + x = [[1, 2], [3, 4]] + with pytest.raises(ValueError, match="Input vector should be 1-D"): + _validate_vector(x) + +def test_yule_all_same(): + # Test yule avoids a divide by zero when exactly equal + x = np.ones((2, 6), dtype=bool) + d = wyule(x[0], x[0]) + assert d == 0.0 + + d = pdist(x, 'yule') + assert_equal(d, [0.0]) + + d = cdist(x[:1], x[:1], 'yule') + assert_equal(d, [[0.0]]) + + +def test_jensenshannon(): + assert_almost_equal(jensenshannon([1.0, 0.0, 0.0], [0.0, 1.0, 0.0], 2.0), + 1.0) + assert_almost_equal(jensenshannon([1.0, 0.0], [0.5, 0.5]), + 0.46450140402245893) + assert_almost_equal(jensenshannon([1.0, 0.0, 0.0], [1.0, 0.0, 0.0]), 0.0) + + assert_almost_equal(jensenshannon([[1.0, 2.0]], [[0.5, 1.5]], axis=0), + [0.0, 0.0]) + assert_almost_equal(jensenshannon([[1.0, 2.0]], [[0.5, 1.5]], axis=1), + [0.0649045]) + assert_almost_equal(jensenshannon([[1.0, 2.0]], [[0.5, 1.5]], axis=0, + keepdims=True), [[0.0, 0.0]]) + assert_almost_equal(jensenshannon([[1.0, 2.0]], [[0.5, 1.5]], axis=1, + keepdims=True), [[0.0649045]]) + + a = np.array([[1, 2, 3, 4], + [5, 6, 7, 8], + [9, 10, 11, 12]]) + b = np.array([[13, 14, 15, 16], + [17, 18, 19, 20], + [21, 22, 23, 24]]) + + assert_almost_equal(jensenshannon(a, b, axis=0), + [0.1954288, 0.1447697, 0.1138377, 0.0927636]) + assert_almost_equal(jensenshannon(a, b, axis=1), + [0.1402339, 0.0399106, 0.0201815]) + + +def test_gh_17703(): + arr_1 = np.array([1, 0, 0]) + arr_2 = np.array([2, 0, 0]) + expected = dice(arr_1, arr_2) + actual = pdist([arr_1, arr_2], metric='dice') + assert_allclose(actual, expected) + actual = cdist(np.atleast_2d(arr_1), + np.atleast_2d(arr_2), metric='dice') + assert_allclose(actual, expected) + + +def test_immutable_input(metric): + if metric in ("jensenshannon", "mahalanobis", "seuclidean"): + pytest.skip("not applicable") + x = np.arange(10, dtype=np.float64) + x.setflags(write=False) + getattr(scipy.spatial.distance, metric)(x, x, w=x) + + +def test_gh_23109(): + a = np.array([0, 0, 1, 1]) + b = np.array([0, 1, 1, 0]) + w = np.asarray([1.5, 1.2, 0.7, 1.3]) + expected = yule(a, b, w=w) + assert_allclose(expected, 1.1954022988505748) + actual = cdist(np.atleast_2d(a), + np.atleast_2d(b), + metric='yule', w=w) + assert_allclose(actual, expected) + + +class TestJaccard: + + def test_pdist_jaccard_random(self): + eps = 1e-8 + X = eo['pdist-boolean-inp'] + Y_right = eo['pdist-jaccard'] + Y_test1 = wpdist(X, 'jaccard') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_jaccard_random_float32(self): + eps = 1e-8 + X = np.float32(eo['pdist-boolean-inp']) + Y_right = eo['pdist-jaccard'] + Y_test1 = wpdist(X, 'jaccard') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_jaccard_random_nonC(self): + eps = 1e-8 + X = eo['pdist-boolean-inp'] + Y_right = eo['pdist-jaccard'] + Y_test2 = wpdist(X, 'test_jaccard') + assert_allclose(Y_test2, Y_right, rtol=eps) + + def test_pdist_djaccard_random(self): + eps = 1e-8 + X = np.float64(eo['pdist-boolean-inp']) + Y_right = eo['pdist-jaccard'] + Y_test1 = wpdist(X, 'jaccard') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_djaccard_random_float32(self): + eps = 1e-8 + X = np.float32(eo['pdist-boolean-inp']) + Y_right = eo['pdist-jaccard'] + Y_test1 = wpdist(X, 'jaccard') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_djaccard_allzeros(self): + eps = 1e-15 + Y = pdist(np.zeros((5, 3)), 'jaccard') + assert_allclose(np.zeros(10), Y, rtol=eps) + + def test_pdist_djaccard_random_nonC(self): + eps = 1e-8 + X = np.float64(eo['pdist-boolean-inp']) + Y_right = eo['pdist-jaccard'] + Y_test2 = wpdist(X, 'test_jaccard') + assert_allclose(Y_test2, Y_right, rtol=eps) + + def test_pdist_djaccard_allzeros_nonC(self): + eps = 1e-15 + Y = pdist(np.zeros((5, 3)), 'test_jaccard') + assert_allclose(np.zeros(10), Y, rtol=eps) + + def test_pdist_jaccard_mtica1(self): + m = wjaccard(np.array([1, 0, 1, 1, 0]), + np.array([1, 1, 0, 1, 1])) + m2 = wjaccard(np.array([1, 0, 1, 1, 0], dtype=bool), + np.array([1, 1, 0, 1, 1], dtype=bool)) + assert_allclose(m, 0.6, rtol=0, atol=1e-10) + assert_allclose(m2, 0.6, rtol=0, atol=1e-10) + + def test_pdist_jaccard_mtica2(self): + m = wjaccard(np.array([1, 0, 1]), + np.array([1, 1, 0])) + m2 = wjaccard(np.array([1, 0, 1], dtype=bool), + np.array([1, 1, 0], dtype=bool)) + assert_allclose(m, 2 / 3, rtol=0, atol=1e-10) + assert_allclose(m2, 2 / 3, rtol=0, atol=1e-10) + + def test_non_01_input(self): + # Non-0/1 numeric input should be cast to bool before computation. + # See gh-21176. + x = np.array([-10, 2.5, 0]) # [True, True, False] + y = np.array([ 2, -5, 2]) # [True, True, True] + eps = np.finfo(float).eps + assert_allclose(jaccard(x, y), 1/3, rtol=eps) + assert_allclose(cdist([x], [y], 'jaccard'), [[1/3]]) + assert_allclose(pdist([x, y], 'jaccard'), [1/3]) + + +class TestChebyshev: + + def test_pdist_chebyshev_random(self): + eps = 1e-8 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-chebyshev'] + Y_test1 = pdist(X, 'chebyshev') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_chebyshev_random_float32(self): + eps = 1e-7 + X = np.float32(eo['pdist-double-inp']) + Y_right = eo['pdist-chebyshev'] + Y_test1 = pdist(X, 'chebyshev') + assert_allclose(Y_test1, Y_right, rtol=eps, verbose=verbose > 2) + + def test_pdist_chebyshev_random_nonC(self): + eps = 1e-8 + X = eo['pdist-double-inp'] + Y_right = eo['pdist-chebyshev'] + Y_test2 = pdist(X, 'test_chebyshev') + assert_allclose(Y_test2, Y_right, rtol=eps) + + def test_pdist_chebyshev_iris(self): + eps = 1e-14 + X = eo['iris'] + Y_right = eo['pdist-chebyshev-iris'] + Y_test1 = pdist(X, 'chebyshev') + assert_allclose(Y_test1, Y_right, rtol=eps) + + def test_pdist_chebyshev_iris_float32(self): + eps = 1e-5 + X = np.float32(eo['iris']) + Y_right = eo['pdist-chebyshev-iris'] + Y_test1 = pdist(X, 'chebyshev') + assert_allclose(Y_test1, Y_right, rtol=eps, verbose=verbose > 2) + + def test_pdist_chebyshev_iris_nonC(self): + eps = 1e-14 + X = eo['iris'] + Y_right = eo['pdist-chebyshev-iris'] + Y_test2 = pdist(X, 'test_chebyshev') + assert_allclose(Y_test2, Y_right, rtol=eps) + + def test_weighted(self): + # Basic test for weighted Chebyshev. Only components with non-zero + # weight participate in the 'max'. + x = [1, 2, 3] + y = [6, 5, 4] + w = [0, 1, 5] + assert_equal(chebyshev(x, y, w), 3) + assert_equal(pdist([x, y], 'chebyshev', w=w), [3]) + assert_equal(cdist([x], [y], 'chebyshev', w=w), [[3]]) + + def test_zero_weight(self): + # If the weight is identically zero, the distance should be zero. + x = [1, 2, 3] + y = [6, 5, 4] + w = [0, 0, 0] + assert_equal(chebyshev(x, y, w), 0) + assert_equal(pdist([x, y], 'chebyshev', w=w), [0]) + assert_equal(cdist([x], [y], 'chebyshev', w=w), [[0]]) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_hausdorff.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_hausdorff.py new file mode 100644 index 0000000000000000000000000000000000000000..45d89e868c8c2daca6e9c30973399fbbfc5d52fd --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_hausdorff.py @@ -0,0 +1,199 @@ +import numpy as np +from numpy.testing import (assert_allclose, + assert_array_equal, + assert_equal) +import pytest +from scipy.spatial.distance import directed_hausdorff +from scipy.spatial import distance +from scipy._lib._util import check_random_state + + +class TestHausdorff: + # Test various properties of the directed Hausdorff code. + + def setup_method(self): + np.random.seed(1234) + random_angles = np.random.random(100) * np.pi * 2 + random_columns = np.column_stack( + (random_angles, random_angles, np.zeros(100))) + random_columns[..., 0] = np.cos(random_columns[..., 0]) + random_columns[..., 1] = np.sin(random_columns[..., 1]) + random_columns_2 = np.column_stack( + (random_angles, random_angles, np.zeros(100))) + random_columns_2[1:, 0] = np.cos(random_columns_2[1:, 0]) * 2.0 + random_columns_2[1:, 1] = np.sin(random_columns_2[1:, 1]) * 2.0 + # move one point farther out so we don't have two perfect circles + random_columns_2[0, 0] = np.cos(random_columns_2[0, 0]) * 3.3 + random_columns_2[0, 1] = np.sin(random_columns_2[0, 1]) * 3.3 + self.path_1 = random_columns + self.path_2 = random_columns_2 + self.path_1_4d = np.insert(self.path_1, 3, 5, axis=1) + self.path_2_4d = np.insert(self.path_2, 3, 27, axis=1) + + def test_symmetry(self): + # Ensure that the directed (asymmetric) Hausdorff distance is + # actually asymmetric + + forward = directed_hausdorff(self.path_1, self.path_2)[0] + reverse = directed_hausdorff(self.path_2, self.path_1)[0] + assert forward != reverse + + def test_brute_force_comparison_forward(self): + # Ensure that the algorithm for directed_hausdorff gives the + # same result as the simple / brute force approach in the + # forward direction. + actual = directed_hausdorff(self.path_1, self.path_2)[0] + # brute force over rows: + expected = max(np.amin(distance.cdist(self.path_1, self.path_2), + axis=1)) + assert_allclose(actual, expected) + + def test_brute_force_comparison_reverse(self): + # Ensure that the algorithm for directed_hausdorff gives the + # same result as the simple / brute force approach in the + # reverse direction. + actual = directed_hausdorff(self.path_2, self.path_1)[0] + # brute force over columns: + expected = max(np.amin(distance.cdist(self.path_1, self.path_2), + axis=0)) + assert_allclose(actual, expected) + + def test_degenerate_case(self): + # The directed Hausdorff distance must be zero if both input + # data arrays match. + actual = directed_hausdorff(self.path_1, self.path_1)[0] + assert_allclose(actual, 0.0) + + def test_2d_data_forward(self): + # Ensure that 2D data is handled properly for a simple case + # relative to brute force approach. + actual = directed_hausdorff(self.path_1[..., :2], + self.path_2[..., :2])[0] + expected = max(np.amin(distance.cdist(self.path_1[..., :2], + self.path_2[..., :2]), + axis=1)) + assert_allclose(actual, expected) + + def test_4d_data_reverse(self): + # Ensure that 4D data is handled properly for a simple case + # relative to brute force approach. + actual = directed_hausdorff(self.path_2_4d, self.path_1_4d)[0] + # brute force over columns: + expected = max(np.amin(distance.cdist(self.path_1_4d, self.path_2_4d), + axis=0)) + assert_allclose(actual, expected) + + def test_indices(self): + # Ensure that correct point indices are returned -- they should + # correspond to the Hausdorff pair + path_simple_1 = np.array([[-1,-12],[0,0], [1,1], [3,7], [1,2]]) + path_simple_2 = np.array([[0,0], [1,1], [4,100], [10,9]]) + actual = directed_hausdorff(path_simple_2, path_simple_1)[1:] + expected = (2, 3) + assert_array_equal(actual, expected) + + def test_random_state(self): + # ensure that the global random state is not modified because + # the directed Hausdorff algorithm uses randomization + rs = check_random_state(None) + old_global_state = rs.get_state() + directed_hausdorff(self.path_1, self.path_2) + rs2 = check_random_state(None) + new_global_state = rs2.get_state() + assert_equal(new_global_state, old_global_state) + + @pytest.mark.parametrize("seed", [None, 27870671, np.random.default_rng(177)]) + def test_random_state_None_int(self, seed): + # check that seed values of None or int do not alter global + # random state + rs = check_random_state(None) + old_global_state = rs.get_state() + directed_hausdorff(self.path_1, self.path_2, seed) + rs2 = check_random_state(None) + new_global_state = rs2.get_state() + assert_equal(new_global_state, old_global_state) + + def test_invalid_dimensions(self): + # Ensure that a ValueError is raised when the number of columns + # is not the same + rng = np.random.default_rng(189048172503940875434364128139223470523) + A = rng.random((3, 2)) + B = rng.random((3, 5)) + msg = r"need to have the same number of columns" + with pytest.raises(ValueError, match=msg): + directed_hausdorff(A, B) + + # preserve use of legacy keyword `seed` during SPEC 7 transition + @pytest.mark.parametrize("A, B, seed, expected", [ + # the two cases from gh-11332 + ([(0,0)], + [(0,1), (0,0)], + np.int64(0), + (0.0, 0, 1)), + ([(0,0)], + [(0,1), (0,0)], + 1, + (0.0, 0, 1)), + # gh-11332 cases with a Generator + ([(0,0)], + [(0,1), (0,0)], + np.random.default_rng(0), + (0.0, 0, 1)), + ([(0,0)], + [(0,1), (0,0)], + np.random.default_rng(1), + (0.0, 0, 1)), + # slightly more complex case + ([(-5, 3), (0,0)], + [(0,1), (0,0), (-5, 3)], + 77098, + # the maximum minimum distance will + # be the last one found, but a unique + # solution is not guaranteed more broadly + (0.0, 1, 1)), + # repeated with Generator seeding + ([(-5, 3), (0,0)], + [(0,1), (0,0), (-5, 3)], + np.random.default_rng(77098), + # NOTE: using a Generator changes the + # indices but not the distance (unique solution + # not guaranteed) + (0.0, 0, 2)), + ]) + def test_subsets(self, A, B, seed, expected, num_parallel_threads): + # verify fix for gh-11332 + actual = directed_hausdorff(u=A, v=B, seed=seed) + # check distance + assert_allclose(actual[0], expected[0]) + starting_seed = seed + if hasattr(seed, 'bit_generator'): + starting_seed = seed.bit_generator._seed_seq.entropy + # check indices + if num_parallel_threads == 1 or starting_seed != 77098: + assert actual[1:] == expected[1:] + + if not isinstance(seed, np.random.RandomState): + # Check that new `rng` keyword is also accepted + actual = directed_hausdorff(u=A, v=B, rng=seed) + assert_allclose(actual[0], expected[0]) + + +@pytest.mark.xslow +def test_massive_arr_overflow(): + # on 64-bit systems we should be able to + # handle arrays that exceed the indexing + # size of a 32-bit signed integer + try: + import psutil + except ModuleNotFoundError: + pytest.skip("psutil required to check available memory") + if psutil.virtual_memory().available < 80*2**30: + # Don't run the test if there is less than 80 gig of RAM available. + pytest.skip('insufficient memory available to run this test') + size = int(3e9) + arr1 = np.zeros(shape=(size, 2)) + arr2 = np.zeros(shape=(3, 2)) + arr1[size - 1] = [5, 5] + actual = directed_hausdorff(u=arr1, v=arr2) + assert_allclose(actual[0], 7.0710678118654755) + assert_allclose(actual[1], size - 1) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_kdtree.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_kdtree.py new file mode 100644 index 0000000000000000000000000000000000000000..c1c41db04ebef538eb2bf2b3ad4bbe74d4c91cb2 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_kdtree.py @@ -0,0 +1,1536 @@ +# Copyright Anne M. Archibald 2008 +# Released under the scipy license + +import os +from numpy.testing import (assert_equal, assert_array_equal, assert_, + assert_almost_equal, assert_array_almost_equal, + assert_allclose) +from pytest import raises as assert_raises +import pytest +from platform import python_implementation +import numpy as np +from scipy.spatial import KDTree, Rectangle, distance_matrix, cKDTree +from scipy.spatial._ckdtree import cKDTreeNode +from scipy.spatial import minkowski_distance + +import itertools + +@pytest.fixture(params=[KDTree, cKDTree]) +def kdtree_type(request): + return request.param + + +def KDTreeTest(kls): + """Class decorator to create test cases for KDTree and cKDTree + + Tests use the class variable ``kdtree_type`` as the tree constructor. + """ + if not kls.__name__.startswith('_Test'): + raise RuntimeError("Expected a class name starting with _Test") + + for tree in (KDTree, cKDTree): + test_name = kls.__name__[1:] + '_' + tree.__name__ + + if test_name in globals(): + raise RuntimeError("Duplicated test name: " + test_name) + + # Create a new sub-class with kdtree_type defined + test_case = type(test_name, (kls,), {'kdtree_type': tree}) + globals()[test_name] = test_case + return kls + + +def distance_box(a, b, p, boxsize): + diff = a - b + diff[diff > 0.5 * boxsize] -= boxsize + diff[diff < -0.5 * boxsize] += boxsize + d = minkowski_distance(diff, 0, p) + return d + +class ConsistencyTests: + def distance(self, a, b, p): + return minkowski_distance(a, b, p) + + def test_nearest(self): + x = self.x + d, i = self.kdtree.query(x, 1) + assert_almost_equal(d**2, np.sum((x-self.data[i])**2)) + eps = 1e-8 + assert_(np.all(np.sum((self.data-x[np.newaxis, :])**2, axis=1) > d**2-eps)) + + def test_m_nearest(self): + x = self.x + m = self.m + dd, ii = self.kdtree.query(x, m) + d = np.amax(dd) + i = ii[np.argmax(dd)] + assert_almost_equal(d**2, np.sum((x-self.data[i])**2)) + eps = 1e-8 + assert_equal( + np.sum(np.sum((self.data-x[np.newaxis, :])**2, axis=1) < d**2+eps), + m, + ) + + def test_points_near(self): + x = self.x + d = self.d + dd, ii = self.kdtree.query(x, k=self.kdtree.n, distance_upper_bound=d) + eps = 1e-8 + hits = 0 + for near_d, near_i in zip(dd, ii): + if near_d == np.inf: + continue + hits += 1 + assert_almost_equal(near_d**2, np.sum((x-self.data[near_i])**2)) + assert_(near_d < d+eps, f"near_d={near_d:g} should be less than {d:g}") + assert_equal(np.sum(self.distance(self.data, x, 2) < d**2+eps), hits) + + def test_points_near_l1(self): + x = self.x + d = self.d + dd, ii = self.kdtree.query(x, k=self.kdtree.n, p=1, distance_upper_bound=d) + eps = 1e-8 + hits = 0 + for near_d, near_i in zip(dd, ii): + if near_d == np.inf: + continue + hits += 1 + assert_almost_equal(near_d, self.distance(x, self.data[near_i], 1)) + assert_(near_d < d+eps, f"near_d={near_d:g} should be less than {d:g}") + assert_equal(np.sum(self.distance(self.data, x, 1) < d+eps), hits) + + def test_points_near_linf(self): + x = self.x + d = self.d + dd, ii = self.kdtree.query(x, k=self.kdtree.n, p=np.inf, distance_upper_bound=d) + eps = 1e-8 + hits = 0 + for near_d, near_i in zip(dd, ii): + if near_d == np.inf: + continue + hits += 1 + assert_almost_equal(near_d, self.distance(x, self.data[near_i], np.inf)) + assert_(near_d < d+eps, f"near_d={near_d:g} should be less than {d:g}") + assert_equal(np.sum(self.distance(self.data, x, np.inf) < d+eps), hits) + + def test_approx(self): + x = self.x + k = self.k + eps = 0.1 + d_real, i_real = self.kdtree.query(x, k) + d, i = self.kdtree.query(x, k, eps=eps) + assert_(np.all(d <= d_real*(1+eps))) + + +@KDTreeTest +class _Test_random(ConsistencyTests): + def setup_method(self): + self.n = 100 + self.m = 4 + np.random.seed(1234) + self.data = np.random.randn(self.n, self.m) + self.kdtree = self.kdtree_type(self.data, leafsize=2) + self.x = np.random.randn(self.m) + self.d = 0.2 + self.k = 10 + + +@KDTreeTest +class _Test_random_far(_Test_random): + def setup_method(self): + super().setup_method() + self.x = np.random.randn(self.m)+10 + + +@KDTreeTest +class _Test_small(ConsistencyTests): + def setup_method(self): + self.data = np.array([[0, 0, 0], + [0, 0, 1], + [0, 1, 0], + [0, 1, 1], + [1, 0, 0], + [1, 0, 1], + [1, 1, 0], + [1, 1, 1]]) + self.kdtree = self.kdtree_type(self.data) + self.n = self.kdtree.n + self.m = self.kdtree.m + np.random.seed(1234) + self.x = np.random.randn(3) + self.d = 0.5 + self.k = 4 + + def test_nearest(self): + assert_array_equal( + self.kdtree.query((0, 0, 0.1), 1), + (0.1, 0)) + + def test_nearest_two(self): + assert_array_equal( + self.kdtree.query((0, 0, 0.1), 2), + ([0.1, 0.9], [0, 1])) + + +@KDTreeTest +class _Test_small_nonleaf(_Test_small): + def setup_method(self): + super().setup_method() + self.kdtree = self.kdtree_type(self.data, leafsize=1) + + +class Test_vectorization_KDTree: + def setup_method(self): + self.data = np.array([[0, 0, 0], + [0, 0, 1], + [0, 1, 0], + [0, 1, 1], + [1, 0, 0], + [1, 0, 1], + [1, 1, 0], + [1, 1, 1]]) + self.kdtree = KDTree(self.data) + + def test_single_query(self): + d, i = self.kdtree.query(np.array([0, 0, 0])) + assert_(isinstance(d, float)) + assert_(np.issubdtype(i, np.signedinteger)) + + def test_vectorized_query(self): + d, i = self.kdtree.query(np.zeros((2, 4, 3))) + assert_equal(np.shape(d), (2, 4)) + assert_equal(np.shape(i), (2, 4)) + + def test_single_query_multiple_neighbors(self): + s = 23 + kk = self.kdtree.n+s + d, i = self.kdtree.query(np.array([0, 0, 0]), k=kk) + assert_equal(np.shape(d), (kk,)) + assert_equal(np.shape(i), (kk,)) + assert_(np.all(~np.isfinite(d[-s:]))) + assert_(np.all(i[-s:] == self.kdtree.n)) + + def test_vectorized_query_multiple_neighbors(self): + s = 23 + kk = self.kdtree.n+s + d, i = self.kdtree.query(np.zeros((2, 4, 3)), k=kk) + assert_equal(np.shape(d), (2, 4, kk)) + assert_equal(np.shape(i), (2, 4, kk)) + assert_(np.all(~np.isfinite(d[:, :, -s:]))) + assert_(np.all(i[:, :, -s:] == self.kdtree.n)) + + def test_query_raises_for_k_none(self): + x = 1.0 + with pytest.raises(ValueError, match="k must be an integer or*"): + self.kdtree.query(x, k=None) + +class Test_vectorization_cKDTree: + def setup_method(self): + self.data = np.array([[0, 0, 0], + [0, 0, 1], + [0, 1, 0], + [0, 1, 1], + [1, 0, 0], + [1, 0, 1], + [1, 1, 0], + [1, 1, 1]]) + self.kdtree = cKDTree(self.data) + + def test_single_query(self): + d, i = self.kdtree.query([0, 0, 0]) + assert_(isinstance(d, float)) + assert_(isinstance(i, int)) + + def test_vectorized_query(self): + d, i = self.kdtree.query(np.zeros((2, 4, 3))) + assert_equal(np.shape(d), (2, 4)) + assert_equal(np.shape(i), (2, 4)) + + def test_vectorized_query_noncontiguous_values(self): + np.random.seed(1234) + qs = np.random.randn(3, 1000).T + ds, i_s = self.kdtree.query(qs) + for q, d, i in zip(qs, ds, i_s): + assert_equal(self.kdtree.query(q), (d, i)) + + def test_single_query_multiple_neighbors(self): + s = 23 + kk = self.kdtree.n+s + d, i = self.kdtree.query([0, 0, 0], k=kk) + assert_equal(np.shape(d), (kk,)) + assert_equal(np.shape(i), (kk,)) + assert_(np.all(~np.isfinite(d[-s:]))) + assert_(np.all(i[-s:] == self.kdtree.n)) + + def test_vectorized_query_multiple_neighbors(self): + s = 23 + kk = self.kdtree.n+s + d, i = self.kdtree.query(np.zeros((2, 4, 3)), k=kk) + assert_equal(np.shape(d), (2, 4, kk)) + assert_equal(np.shape(i), (2, 4, kk)) + assert_(np.all(~np.isfinite(d[:, :, -s:]))) + assert_(np.all(i[:, :, -s:] == self.kdtree.n)) + +class ball_consistency: + tol = 0.0 + + def distance(self, a, b, p): + return minkowski_distance(a * 1.0, b * 1.0, p) + + def test_in_ball(self): + x = np.atleast_2d(self.x) + d = np.broadcast_to(self.d, x.shape[:-1]) + l = self.T.query_ball_point(x, self.d, p=self.p, eps=self.eps) + for i, ind in enumerate(l): + dist = self.distance(self.data[ind], x[i], self.p) - d[i]*(1.+self.eps) + norm = self.distance(self.data[ind], x[i], self.p) + d[i]*(1.+self.eps) + assert_array_equal(dist < self.tol * norm, True) + + def test_found_all(self): + x = np.atleast_2d(self.x) + d = np.broadcast_to(self.d, x.shape[:-1]) + l = self.T.query_ball_point(x, self.d, p=self.p, eps=self.eps) + for i, ind in enumerate(l): + c = np.ones(self.T.n, dtype=bool) + c[ind] = False + dist = self.distance(self.data[c], x[i], self.p) - d[i]/(1.+self.eps) + norm = self.distance(self.data[c], x[i], self.p) + d[i]/(1.+self.eps) + assert_array_equal(dist > -self.tol * norm, True) + +@KDTreeTest +class _Test_random_ball(ball_consistency): + def setup_method(self): + n = 100 + m = 4 + np.random.seed(1234) + self.data = np.random.randn(n, m) + self.T = self.kdtree_type(self.data, leafsize=2) + self.x = np.random.randn(m) + self.p = 2. + self.eps = 0 + self.d = 0.2 + + +@KDTreeTest +class _Test_random_ball_periodic(ball_consistency): + def distance(self, a, b, p): + return distance_box(a, b, p, 1.0) + + def setup_method(self): + n = 10000 + m = 4 + np.random.seed(1234) + self.data = np.random.uniform(size=(n, m)) + self.T = self.kdtree_type(self.data, leafsize=2, boxsize=1) + self.x = np.full(m, 0.1) + self.p = 2. + self.eps = 0 + self.d = 0.2 + + def test_in_ball_outside(self): + l = self.T.query_ball_point(self.x + 1.0, self.d, p=self.p, eps=self.eps) + for i in l: + assert_(self.distance(self.data[i], self.x, self.p) <= self.d*(1.+self.eps)) + l = self.T.query_ball_point(self.x - 1.0, self.d, p=self.p, eps=self.eps) + for i in l: + assert_(self.distance(self.data[i], self.x, self.p) <= self.d*(1.+self.eps)) + + def test_found_all_outside(self): + c = np.ones(self.T.n, dtype=bool) + l = self.T.query_ball_point(self.x + 1.0, self.d, p=self.p, eps=self.eps) + c[l] = False + assert np.all( + self.distance(self.data[c], self.x, self.p) >= self.d/(1.+self.eps) + ) + + l = self.T.query_ball_point(self.x - 1.0, self.d, p=self.p, eps=self.eps) + c[l] = False + assert np.all( + self.distance(self.data[c], self.x, self.p) >= self.d/(1.+self.eps) + ) + + +@KDTreeTest +class _Test_random_ball_largep_issue9890(ball_consistency): + + # allow some roundoff errors due to numerical issues + tol = 1e-13 + + def setup_method(self): + n = 1000 + m = 2 + np.random.seed(123) + self.data = np.random.randint(100, 1000, size=(n, m)) + self.T = self.kdtree_type(self.data) + self.x = self.data + self.p = 100 + self.eps = 0 + self.d = 10 + + +@KDTreeTest +class _Test_random_ball_approx(_Test_random_ball): + + def setup_method(self): + super().setup_method() + self.eps = 0.1 + + +@KDTreeTest +class _Test_random_ball_approx_periodic(_Test_random_ball): + + def setup_method(self): + super().setup_method() + self.eps = 0.1 + + +@KDTreeTest +class _Test_random_ball_far(_Test_random_ball): + + def setup_method(self): + super().setup_method() + self.d = 2. + +@KDTreeTest +class _Test_random_ball_far_periodic(_Test_random_ball_periodic): + + def setup_method(self): + super().setup_method() + self.d = 2. + + +@KDTreeTest +class _Test_random_ball_l1(_Test_random_ball): + + def setup_method(self): + super().setup_method() + self.p = 1 + + +@KDTreeTest +class _Test_random_ball_linf(_Test_random_ball): + + def setup_method(self): + super().setup_method() + self.p = np.inf + + +def test_random_ball_vectorized(kdtree_type): + n = 20 + m = 5 + np.random.seed(1234) + T = kdtree_type(np.random.randn(n, m)) + + r = T.query_ball_point(np.random.randn(2, 3, m), 1) + assert_equal(r.shape, (2, 3)) + assert_(isinstance(r[0, 0], list)) + + +@pytest.mark.fail_slow(5) +def test_query_ball_point_multithreading(kdtree_type): + np.random.seed(0) + n = 5000 + k = 2 + points = np.random.randn(n, k) + T = kdtree_type(points) + l1 = T.query_ball_point(points, 0.003, workers=1) + l2 = T.query_ball_point(points, 0.003, workers=64) + l3 = T.query_ball_point(points, 0.003, workers=-1) + + for i in range(n): + if l1[i] or l2[i]: + assert_array_equal(l1[i], l2[i]) + + for i in range(n): + if l1[i] or l3[i]: + assert_array_equal(l1[i], l3[i]) + + +class two_trees_consistency: + + def distance(self, a, b, p): + return minkowski_distance(a, b, p) + + def test_all_in_ball(self): + r = self.T1.query_ball_tree(self.T2, self.d, p=self.p, eps=self.eps) + for i, l in enumerate(r): + for j in l: + assert (self.distance(self.data1[i], self.data2[j], self.p) + <= self.d*(1.+self.eps)) + + def test_found_all(self): + r = self.T1.query_ball_tree(self.T2, self.d, p=self.p, eps=self.eps) + for i, l in enumerate(r): + c = np.ones(self.T2.n, dtype=bool) + c[l] = False + assert np.all(self.distance(self.data2[c], self.data1[i], self.p) + >= self.d/(1.+self.eps)) + + +@KDTreeTest +class _Test_two_random_trees(two_trees_consistency): + + def setup_method(self): + n = 50 + m = 4 + np.random.seed(1234) + self.data1 = np.random.randn(n, m) + self.T1 = self.kdtree_type(self.data1, leafsize=2) + self.data2 = np.random.randn(n, m) + self.T2 = self.kdtree_type(self.data2, leafsize=2) + self.p = 2. + self.eps = 0 + self.d = 0.2 + + +@KDTreeTest +class _Test_two_random_trees_periodic(two_trees_consistency): + def distance(self, a, b, p): + return distance_box(a, b, p, 1.0) + + def setup_method(self): + n = 50 + m = 4 + np.random.seed(1234) + self.data1 = np.random.uniform(size=(n, m)) + self.T1 = self.kdtree_type(self.data1, leafsize=2, boxsize=1.0) + self.data2 = np.random.uniform(size=(n, m)) + self.T2 = self.kdtree_type(self.data2, leafsize=2, boxsize=1.0) + self.p = 2. + self.eps = 0 + self.d = 0.2 + + +@KDTreeTest +class _Test_two_random_trees_far(_Test_two_random_trees): + + def setup_method(self): + super().setup_method() + self.d = 2 + + +@KDTreeTest +class _Test_two_random_trees_far_periodic(_Test_two_random_trees_periodic): + + def setup_method(self): + super().setup_method() + self.d = 2 + + +@KDTreeTest +class _Test_two_random_trees_linf(_Test_two_random_trees): + + def setup_method(self): + super().setup_method() + self.p = np.inf + + +@KDTreeTest +class _Test_two_random_trees_linf_periodic(_Test_two_random_trees_periodic): + + def setup_method(self): + super().setup_method() + self.p = np.inf + + +class Test_rectangle: + + def setup_method(self): + self.rect = Rectangle([0, 0], [1, 1]) + + def test_min_inside(self): + assert_almost_equal(self.rect.min_distance_point([0.5, 0.5]), 0) + + def test_min_one_side(self): + assert_almost_equal(self.rect.min_distance_point([0.5, 1.5]), 0.5) + + def test_min_two_sides(self): + assert_almost_equal(self.rect.min_distance_point([2, 2]), np.sqrt(2)) + + def test_max_inside(self): + assert_almost_equal(self.rect.max_distance_point([0.5, 0.5]), 1/np.sqrt(2)) + + def test_max_one_side(self): + assert_almost_equal(self.rect.max_distance_point([0.5, 1.5]), + np.hypot(0.5, 1.5)) + + def test_max_two_sides(self): + assert_almost_equal(self.rect.max_distance_point([2, 2]), 2*np.sqrt(2)) + + def test_split(self): + less, greater = self.rect.split(0, 0.1) + assert_array_equal(less.maxes, [0.1, 1]) + assert_array_equal(less.mins, [0, 0]) + assert_array_equal(greater.maxes, [1, 1]) + assert_array_equal(greater.mins, [0.1, 0]) + + +def test_distance_l2(): + assert_almost_equal(minkowski_distance([0, 0], [1, 1], 2), np.sqrt(2)) + + +def test_distance_l1(): + assert_almost_equal(minkowski_distance([0, 0], [1, 1], 1), 2) + + +def test_distance_linf(): + assert_almost_equal(minkowski_distance([0, 0], [1, 1], np.inf), 1) + + +def test_distance_vectorization(): + np.random.seed(1234) + x = np.random.randn(10, 1, 3) + y = np.random.randn(1, 7, 3) + assert_equal(minkowski_distance(x, y).shape, (10, 7)) + + +class count_neighbors_consistency: + def test_one_radius(self): + r = 0.2 + assert_equal(self.T1.count_neighbors(self.T2, r), + np.sum([len(l) for l in self.T1.query_ball_tree(self.T2, r)])) + + def test_large_radius(self): + r = 1000 + assert_equal(self.T1.count_neighbors(self.T2, r), + np.sum([len(l) for l in self.T1.query_ball_tree(self.T2, r)])) + + def test_multiple_radius(self): + rs = np.exp(np.linspace(np.log(0.01), np.log(10), 3)) + results = self.T1.count_neighbors(self.T2, rs) + assert_(np.all(np.diff(results) >= 0)) + for r, result in zip(rs, results): + assert_equal(self.T1.count_neighbors(self.T2, r), result) + +@KDTreeTest +class _Test_count_neighbors(count_neighbors_consistency): + def setup_method(self): + n = 50 + m = 2 + np.random.seed(1234) + self.T1 = self.kdtree_type(np.random.randn(n, m), leafsize=2) + self.T2 = self.kdtree_type(np.random.randn(n, m), leafsize=2) + + +class sparse_distance_matrix_consistency: + + def distance(self, a, b, p): + return minkowski_distance(a, b, p) + + def test_consistency_with_neighbors(self): + M = self.T1.sparse_distance_matrix(self.T2, self.r) + r = self.T1.query_ball_tree(self.T2, self.r) + for i, l in enumerate(r): + for j in l: + assert_almost_equal( + M[i, j], + self.distance(self.T1.data[i], self.T2.data[j], self.p), + decimal=14 + ) + for ((i, j), d) in M.items(): + assert_(j in r[i]) + + def test_zero_distance(self): + # raises an exception for bug 870 (FIXME: Does it?) + self.T1.sparse_distance_matrix(self.T1, self.r) + + def test_consistency(self): + # Test consistency with a distance_matrix + M1 = self.T1.sparse_distance_matrix(self.T2, self.r) + expected = distance_matrix(self.T1.data, self.T2.data) + expected[expected > self.r] = 0 + assert_array_almost_equal(M1.toarray(), expected, decimal=14) + + def test_against_logic_error_regression(self): + # regression test for gh-5077 logic error + np.random.seed(0) + too_many = np.array(np.random.randn(18, 2), dtype=int) + tree = self.kdtree_type( + too_many, balanced_tree=False, compact_nodes=False) + d = tree.sparse_distance_matrix(tree, 3).toarray() + assert_array_almost_equal(d, d.T, decimal=14) + + def test_ckdtree_return_types(self): + # brute-force reference + ref = np.zeros((self.n, self.n)) + for i in range(self.n): + for j in range(self.n): + v = self.data1[i, :] - self.data2[j, :] + ref[i, j] = np.dot(v, v) + ref = np.sqrt(ref) + ref[ref > self.r] = 0. + # test return type 'dict' + dist = np.zeros((self.n, self.n)) + r = self.T1.sparse_distance_matrix(self.T2, self.r, output_type='dict') + for i, j in r.keys(): + dist[i, j] = r[(i, j)] + assert_array_almost_equal(ref, dist, decimal=14) + # test return type 'ndarray' + dist = np.zeros((self.n, self.n)) + r = self.T1.sparse_distance_matrix(self.T2, self.r, + output_type='ndarray') + for k in range(r.shape[0]): + i = r['i'][k] + j = r['j'][k] + v = r['v'][k] + dist[i, j] = v + assert_array_almost_equal(ref, dist, decimal=14) + # test return type 'dok_matrix' + r = self.T1.sparse_distance_matrix(self.T2, self.r, + output_type='dok_matrix') + assert_array_almost_equal(ref, r.toarray(), decimal=14) + # test return type 'coo_matrix' + r = self.T1.sparse_distance_matrix(self.T2, self.r, + output_type='coo_matrix') + assert_array_almost_equal(ref, r.toarray(), decimal=14) + + +@KDTreeTest +class _Test_sparse_distance_matrix(sparse_distance_matrix_consistency): + def setup_method(self): + n = 50 + m = 4 + np.random.seed(1234) + data1 = np.random.randn(n, m) + data2 = np.random.randn(n, m) + self.T1 = self.kdtree_type(data1, leafsize=2) + self.T2 = self.kdtree_type(data2, leafsize=2) + self.r = 0.5 + self.p = 2 + self.data1 = data1 + self.data2 = data2 + self.n = n + self.m = m + + +def test_distance_matrix(): + m = 10 + n = 11 + k = 4 + np.random.seed(1234) + xs = np.random.randn(m, k) + ys = np.random.randn(n, k) + ds = distance_matrix(xs, ys) + assert_equal(ds.shape, (m, n)) + for i in range(m): + for j in range(n): + assert_almost_equal(minkowski_distance(xs[i], ys[j]), ds[i, j]) + + +def test_distance_matrix_looping(): + m = 10 + n = 11 + k = 4 + np.random.seed(1234) + xs = np.random.randn(m, k) + ys = np.random.randn(n, k) + ds = distance_matrix(xs, ys) + dsl = distance_matrix(xs, ys, threshold=1) + assert_equal(ds, dsl) + + +def check_onetree_query(T, d): + r = T.query_ball_tree(T, d) + s = set() + for i, l in enumerate(r): + for j in l: + if i < j: + s.add((i, j)) + + assert_(s == T.query_pairs(d)) + +def test_onetree_query(kdtree_type): + np.random.seed(0) + n = 50 + k = 4 + points = np.random.randn(n, k) + T = kdtree_type(points) + check_onetree_query(T, 0.1) + + points = np.random.randn(3*n, k) + points[:n] *= 0.001 + points[n:2*n] += 2 + T = kdtree_type(points) + check_onetree_query(T, 0.1) + check_onetree_query(T, 0.001) + check_onetree_query(T, 0.00001) + check_onetree_query(T, 1e-6) + + +def test_query_pairs_single_node(kdtree_type): + tree = kdtree_type([[0, 1]]) + assert_equal(tree.query_pairs(0.5), set()) + + +def test_kdtree_query_pairs(kdtree_type): + np.random.seed(0) + n = 50 + k = 2 + r = 0.1 + r2 = r**2 + points = np.random.randn(n, k) + T = kdtree_type(points) + # brute force reference + brute = set() + for i in range(n): + for j in range(i+1, n): + v = points[i, :] - points[j, :] + if np.dot(v, v) <= r2: + brute.add((i, j)) + l0 = sorted(brute) + # test default return type + s = T.query_pairs(r) + l1 = sorted(s) + assert_array_equal(l0, l1) + # test return type 'set' + s = T.query_pairs(r, output_type='set') + l1 = sorted(s) + assert_array_equal(l0, l1) + # test return type 'ndarray' + s = set() + arr = T.query_pairs(r, output_type='ndarray') + for i in range(arr.shape[0]): + s.add((int(arr[i, 0]), int(arr[i, 1]))) + l2 = sorted(s) + assert_array_equal(l0, l2) + + +def test_query_pairs_eps(kdtree_type): + spacing = np.sqrt(2) + # irrational spacing to have potential rounding errors + x_range = np.linspace(0, 3 * spacing, 4) + y_range = np.linspace(0, 3 * spacing, 4) + xy_array = [(xi, yi) for xi in x_range for yi in y_range] + tree = kdtree_type(xy_array) + pairs_eps = tree.query_pairs(r=spacing, eps=.1) + # result: 24 with eps, 16 without due to rounding + pairs = tree.query_pairs(r=spacing * 1.01) + # result: 24 + assert_equal(pairs, pairs_eps) + + +def test_ball_point_ints(kdtree_type): + # Regression test for #1373. + x, y = np.mgrid[0:4, 0:4] + points = list(zip(x.ravel(), y.ravel())) + tree = kdtree_type(points) + assert_equal(sorted([4, 8, 9, 12]), + sorted(tree.query_ball_point((2, 0), 1))) + points = np.asarray(points, dtype=float) + tree = kdtree_type(points) + assert_equal(sorted([4, 8, 9, 12]), + sorted(tree.query_ball_point((2, 0), 1))) + + +def test_kdtree_comparisons(): + # Regression test: node comparisons were done wrong in 0.12 w/Py3. + nodes = [KDTree.node() for _ in range(3)] + assert_equal(sorted(nodes), sorted(nodes[::-1])) + + +def test_kdtree_build_modes(kdtree_type): + # check if different build modes for KDTree give similar query results + np.random.seed(0) + n = 5000 + k = 4 + points = np.random.randn(n, k) + T1 = kdtree_type(points).query(points, k=5)[-1] + T2 = kdtree_type(points, compact_nodes=False).query(points, k=5)[-1] + T3 = kdtree_type(points, balanced_tree=False).query(points, k=5)[-1] + T4 = kdtree_type(points, compact_nodes=False, + balanced_tree=False).query(points, k=5)[-1] + assert_array_equal(T1, T2) + assert_array_equal(T1, T3) + assert_array_equal(T1, T4) + +def test_kdtree_pickle(kdtree_type): + # test if it is possible to pickle a KDTree + import pickle + np.random.seed(0) + n = 50 + k = 4 + points = np.random.randn(n, k) + T1 = kdtree_type(points) + tmp = pickle.dumps(T1) + T2 = pickle.loads(tmp) + T1 = T1.query(points, k=5)[-1] + T2 = T2.query(points, k=5)[-1] + assert_array_equal(T1, T2) + +def test_kdtree_pickle_boxsize(kdtree_type): + # test if it is possible to pickle a periodic KDTree + import pickle + np.random.seed(0) + n = 50 + k = 4 + points = np.random.uniform(size=(n, k)) + T1 = kdtree_type(points, boxsize=1.0) + tmp = pickle.dumps(T1) + T2 = pickle.loads(tmp) + T1 = T1.query(points, k=5)[-1] + T2 = T2.query(points, k=5)[-1] + assert_array_equal(T1, T2) + +def test_kdtree_copy_data(kdtree_type): + # check if copy_data=True makes the kd-tree + # impervious to data corruption by modification of + # the data arrray + np.random.seed(0) + n = 5000 + k = 4 + points = np.random.randn(n, k) + T = kdtree_type(points, copy_data=True) + q = points.copy() + T1 = T.query(q, k=5)[-1] + points[...] = np.random.randn(n, k) + T2 = T.query(q, k=5)[-1] + assert_array_equal(T1, T2) + +def test_ckdtree_parallel(kdtree_type, monkeypatch): + # check if parallel=True also generates correct query results + np.random.seed(0) + n = 5000 + k = 4 + points = np.random.randn(n, k) + T = kdtree_type(points) + T1 = T.query(points, k=5, workers=64)[-1] + T2 = T.query(points, k=5, workers=-1)[-1] + T3 = T.query(points, k=5)[-1] + assert_array_equal(T1, T2) + assert_array_equal(T1, T3) + + monkeypatch.setattr(os, 'cpu_count', lambda: None) + with pytest.raises(NotImplementedError, match="Cannot determine the"): + T.query(points, 1, workers=-1) + + +def test_ckdtree_view(): + # Check that the nodes can be correctly viewed from Python. + # This test also sanity checks each node in the cKDTree, and + # thus verifies the internal structure of the kd-tree. + np.random.seed(0) + n = 100 + k = 4 + points = np.random.randn(n, k) + kdtree = cKDTree(points) + + # walk the whole kd-tree and sanity check each node + def recurse_tree(n): + assert_(isinstance(n, cKDTreeNode)) + if n.split_dim == -1: + assert_(n.lesser is None) + assert_(n.greater is None) + assert_(n.indices.shape[0] <= kdtree.leafsize) + else: + recurse_tree(n.lesser) + recurse_tree(n.greater) + x = n.lesser.data_points[:, n.split_dim] + y = n.greater.data_points[:, n.split_dim] + assert_(x.max() < y.min()) + + recurse_tree(kdtree.tree) + # check that indices are correctly retrieved + n = kdtree.tree + assert_array_equal(np.sort(n.indices), range(100)) + # check that data_points are correctly retrieved + assert_array_equal(kdtree.data[n.indices, :], n.data_points) + +# KDTree is specialized to type double points, so no need to make +# a unit test corresponding to test_ball_point_ints() + +def test_kdtree_list_k(kdtree_type): + # check kdtree periodic boundary + n = 200 + m = 2 + klist = [1, 2, 3] + kint = 3 + + np.random.seed(1234) + data = np.random.uniform(size=(n, m)) + kdtree = kdtree_type(data, leafsize=1) + + # check agreement between arange(1, k+1) and k + dd, ii = kdtree.query(data, klist) + dd1, ii1 = kdtree.query(data, kint) + assert_equal(dd, dd1) + assert_equal(ii, ii1) + + # now check skipping one element + klist = np.array([1, 3]) + kint = 3 + dd, ii = kdtree.query(data, kint) + dd1, ii1 = kdtree.query(data, klist) + assert_equal(dd1, dd[..., klist - 1]) + assert_equal(ii1, ii[..., klist - 1]) + + # check k == 1 special case + # and k == [1] non-special case + dd, ii = kdtree.query(data, 1) + dd1, ii1 = kdtree.query(data, [1]) + assert_equal(len(dd.shape), 1) + assert_equal(len(dd1.shape), 2) + assert_equal(dd, np.ravel(dd1)) + assert_equal(ii, np.ravel(ii1)) + +@pytest.mark.fail_slow(10) +def test_kdtree_box(kdtree_type): + # check ckdtree periodic boundary + n = 2000 + m = 3 + k = 3 + np.random.seed(1234) + data = np.random.uniform(size=(n, m)) + kdtree = kdtree_type(data, leafsize=1, boxsize=1.0) + + # use the standard python KDTree for the simulated periodic box + kdtree2 = kdtree_type(data, leafsize=1) + + for p in [1, 2, 3.0, np.inf]: + dd, ii = kdtree.query(data, k, p=p) + + dd1, ii1 = kdtree.query(data + 1.0, k, p=p) + assert_almost_equal(dd, dd1) + assert_equal(ii, ii1) + + dd1, ii1 = kdtree.query(data - 1.0, k, p=p) + assert_almost_equal(dd, dd1) + assert_equal(ii, ii1) + + dd2, ii2 = simulate_periodic_box(kdtree2, data, k, boxsize=1.0, p=p) + assert_almost_equal(dd, dd2) + assert_equal(ii, ii2) + +def test_kdtree_box_0boxsize(kdtree_type): + # check ckdtree periodic boundary that mimics non-periodic + n = 2000 + m = 2 + k = 3 + np.random.seed(1234) + data = np.random.uniform(size=(n, m)) + kdtree = kdtree_type(data, leafsize=1, boxsize=0.0) + + # use the standard python KDTree for the simulated periodic box + kdtree2 = kdtree_type(data, leafsize=1) + + for p in [1, 2, np.inf]: + dd, ii = kdtree.query(data, k, p=p) + + dd1, ii1 = kdtree2.query(data, k, p=p) + assert_almost_equal(dd, dd1) + assert_equal(ii, ii1) + +def test_kdtree_box_upper_bounds(kdtree_type): + data = np.linspace(0, 2, 10).reshape(-1, 2) + data[:, 1] += 10 + with pytest.raises(ValueError): + kdtree_type(data, leafsize=1, boxsize=1.0) + with pytest.raises(ValueError): + kdtree_type(data, leafsize=1, boxsize=(0.0, 2.0)) + # skip a dimension. + kdtree_type(data, leafsize=1, boxsize=(2.0, 0.0)) + +def test_kdtree_box_lower_bounds(kdtree_type): + data = np.linspace(-1, 1, 10) + assert_raises(ValueError, kdtree_type, data, leafsize=1, boxsize=1.0) + +def simulate_periodic_box(kdtree, data, k, boxsize, p): + dd = [] + ii = [] + x = np.arange(3 ** data.shape[1]) + nn = np.array(np.unravel_index(x, [3] * data.shape[1])).T + nn = nn - 1.0 + for n in nn: + image = data + n * 1.0 * boxsize + dd2, ii2 = kdtree.query(image, k, p=p) + dd2 = dd2.reshape(-1, k) + ii2 = ii2.reshape(-1, k) + dd.append(dd2) + ii.append(ii2) + dd = np.concatenate(dd, axis=-1) + ii = np.concatenate(ii, axis=-1) + + result = np.empty([len(data), len(nn) * k], dtype=[ + ('ii', 'i8'), + ('dd', 'f8')]) + result['ii'][:] = ii + result['dd'][:] = dd + result.sort(order='dd') + return result['dd'][:, :k], result['ii'][:, :k] + + +@pytest.mark.skipif(python_implementation() == 'PyPy', + reason="Fails on PyPy CI runs. See #9507") +def test_ckdtree_memuse(): + # unit test adaptation of gh-5630 + + # NOTE: this will fail when run via valgrind, + # because rss is no longer a reliable memory usage indicator. + + try: + import resource + except ImportError: + # resource is not available on Windows + return + # Make some data + dx, dy = 0.05, 0.05 + y, x = np.mgrid[slice(1, 5 + dy, dy), + slice(1, 5 + dx, dx)] + z = np.sin(x)**10 + np.cos(10 + y*x) * np.cos(x) + z_copy = np.empty_like(z) + z_copy[:] = z + # Place FILLVAL in z_copy at random number of random locations + FILLVAL = 99. + mask = np.random.randint(0, z.size, np.random.randint(50) + 5) + z_copy.flat[mask] = FILLVAL + igood = np.vstack(np.nonzero(x != FILLVAL)).T + ibad = np.vstack(np.nonzero(x == FILLVAL)).T + mem_use = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss + # burn-in + for i in range(10): + tree = cKDTree(igood) + # count memleaks while constructing and querying cKDTree + num_leaks = 0 + for i in range(100): + mem_use = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss + tree = cKDTree(igood) + dist, iquery = tree.query(ibad, k=4, p=2) + new_mem_use = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss + if new_mem_use > mem_use: + num_leaks += 1 + # ideally zero leaks, but errors might accidentally happen + # outside cKDTree + assert_(num_leaks < 10) + +def test_kdtree_weights(kdtree_type): + + data = np.linspace(0, 1, 4).reshape(-1, 1) + tree1 = kdtree_type(data, leafsize=1) + weights = np.ones(len(data), dtype='f4') + + nw = tree1._build_weights(weights) + assert_array_equal(nw, [4, 2, 1, 1, 2, 1, 1]) + + assert_raises(ValueError, tree1._build_weights, weights[:-1]) + + for i in range(10): + # since weights are uniform, these shall agree: + c1 = tree1.count_neighbors(tree1, np.linspace(0, 10, i)) + c2 = tree1.count_neighbors(tree1, np.linspace(0, 10, i), + weights=(weights, weights)) + c3 = tree1.count_neighbors(tree1, np.linspace(0, 10, i), + weights=(weights, None)) + c4 = tree1.count_neighbors(tree1, np.linspace(0, 10, i), + weights=(None, weights)) + tree1.count_neighbors(tree1, np.linspace(0, 10, i), + weights=weights) + + assert_array_equal(c1, c2) + assert_array_equal(c1, c3) + assert_array_equal(c1, c4) + + for i in range(len(data)): + # this tests removal of one data point by setting weight to 0 + w1 = weights.copy() + w1[i] = 0 + data2 = data[w1 != 0] + tree2 = kdtree_type(data2) + + c1 = tree1.count_neighbors(tree1, np.linspace(0, 10, 100), + weights=(w1, w1)) + # "c2 is correct" + c2 = tree2.count_neighbors(tree2, np.linspace(0, 10, 100)) + + assert_array_equal(c1, c2) + + #this asserts for two different trees, singular weights + # crashes + assert_raises(ValueError, tree1.count_neighbors, + tree2, np.linspace(0, 10, 100), weights=w1) + +@pytest.mark.fail_slow(10) +def test_kdtree_count_neighbous_multiple_r(kdtree_type): + n = 2000 + m = 2 + np.random.seed(1234) + data = np.random.normal(size=(n, m)) + kdtree = kdtree_type(data, leafsize=1) + r0 = [0, 0.01, 0.01, 0.02, 0.05] + i0 = np.arange(len(r0)) + n0 = kdtree.count_neighbors(kdtree, r0) + nnc = kdtree.count_neighbors(kdtree, r0, cumulative=False) + assert_equal(n0, nnc.cumsum()) + + for i, r in zip(itertools.permutations(i0), + itertools.permutations(r0)): + # permute n0 by i and it shall agree + n = kdtree.count_neighbors(kdtree, r) + assert_array_equal(n, n0[list(i)]) + +def test_len0_arrays(kdtree_type): + # make sure len-0 arrays are handled correctly + # in range queries (gh-5639) + rng = np.random.RandomState(1234) + X = rng.rand(10, 2) + Y = rng.rand(10, 2) + tree = kdtree_type(X) + # query_ball_point (single) + d, i = tree.query([.5, .5], k=1) + z = tree.query_ball_point([.5, .5], 0.1*d) + assert_array_equal(z, []) + # query_ball_point (multiple) + d, i = tree.query(Y, k=1) + mind = d.min() + z = tree.query_ball_point(Y, 0.1*mind) + y = np.empty(shape=(10, ), dtype=object) + y.fill([]) + assert_array_equal(y, z) + # query_ball_tree + other = kdtree_type(Y) + y = tree.query_ball_tree(other, 0.1*mind) + assert_array_equal(10*[[]], y) + # count_neighbors + y = tree.count_neighbors(other, 0.1*mind) + assert_(y == 0) + # sparse_distance_matrix + y = tree.sparse_distance_matrix(other, 0.1*mind, output_type='dok_matrix') + assert_array_equal(y == np.zeros((10, 10)), True) + y = tree.sparse_distance_matrix(other, 0.1*mind, output_type='coo_matrix') + assert_array_equal(y == np.zeros((10, 10)), True) + y = tree.sparse_distance_matrix(other, 0.1*mind, output_type='dict') + assert_equal(y, {}) + y = tree.sparse_distance_matrix(other, 0.1*mind, output_type='ndarray') + _dtype = [('i', np.intp), ('j', np.intp), ('v', np.float64)] + res_dtype = np.dtype(_dtype, align=True) + z = np.empty(shape=(0, ), dtype=res_dtype) + assert_array_equal(y, z) + # query_pairs + d, i = tree.query(X, k=2) + mind = d[:, -1].min() + y = tree.query_pairs(0.1*mind, output_type='set') + assert_equal(y, set()) + y = tree.query_pairs(0.1*mind, output_type='ndarray') + z = np.empty(shape=(0, 2), dtype=np.intp) + assert_array_equal(y, z) + +def test_kdtree_duplicated_inputs(kdtree_type): + # check kdtree with duplicated inputs + n = 1024 + for m in range(1, 8): + data = np.ones((n, m)) + data[n//2:] = 2 + + for balanced, compact in itertools.product((False, True), repeat=2): + kdtree = kdtree_type(data, balanced_tree=balanced, + compact_nodes=compact, leafsize=1) + assert kdtree.size == 3 + + tree = (kdtree.tree if kdtree_type is cKDTree else + kdtree.tree._node) + + assert_equal( + np.sort(tree.lesser.indices), + np.arange(0, n // 2)) + assert_equal( + np.sort(tree.greater.indices), + np.arange(n // 2, n)) + + +def test_kdtree_noncumulative_nondecreasing(kdtree_type): + # check kdtree with duplicated inputs + + # it shall not divide more than 3 nodes. + # root left (1), and right (2) + kdtree = kdtree_type([[0]], leafsize=1) + + assert_raises(ValueError, kdtree.count_neighbors, + kdtree, [0.1, 0], cumulative=False) + +def test_short_knn(kdtree_type): + + # The test case is based on github: #6425 by @SteveDoyle2 + + xyz = np.array([ + [0., 0., 0.], + [1.01, 0., 0.], + [0., 1., 0.], + [0., 1.01, 0.], + [1., 0., 0.], + [1., 1., 0.]], + dtype='float64') + + ckdt = kdtree_type(xyz) + + deq, ieq = ckdt.query(xyz, k=4, distance_upper_bound=0.2) + + assert_array_almost_equal(deq, + [[0., np.inf, np.inf, np.inf], + [0., 0.01, np.inf, np.inf], + [0., 0.01, np.inf, np.inf], + [0., 0.01, np.inf, np.inf], + [0., 0.01, np.inf, np.inf], + [0., np.inf, np.inf, np.inf]]) + +def test_query_ball_point_vector_r(kdtree_type): + + np.random.seed(1234) + data = np.random.normal(size=(100, 3)) + query = np.random.normal(size=(100, 3)) + tree = kdtree_type(data) + d = np.random.uniform(0, 0.3, size=len(query)) + + rvector = tree.query_ball_point(query, d) + rscalar = [tree.query_ball_point(qi, di) for qi, di in zip(query, d)] + for a, b in zip(rvector, rscalar): + assert_array_equal(sorted(a), sorted(b)) + +def test_query_ball_point_length(kdtree_type): + + np.random.seed(1234) + data = np.random.normal(size=(100, 3)) + query = np.random.normal(size=(100, 3)) + tree = kdtree_type(data) + d = 0.3 + + length = tree.query_ball_point(query, d, return_length=True) + length2 = [len(ind) for ind in tree.query_ball_point(query, d, return_length=False)] + length3 = [len(tree.query_ball_point(qi, d)) for qi in query] + length4 = [tree.query_ball_point(qi, d, return_length=True) for qi in query] + assert_array_equal(length, length2) + assert_array_equal(length, length3) + assert_array_equal(length, length4) + +def test_discontiguous(kdtree_type): + + np.random.seed(1234) + data = np.random.normal(size=(100, 3)) + d_contiguous = np.arange(100) * 0.04 + d_discontiguous = np.ascontiguousarray( + np.arange(100)[::-1] * 0.04)[::-1] + query_contiguous = np.random.normal(size=(100, 3)) + query_discontiguous = np.ascontiguousarray(query_contiguous.T).T + assert query_discontiguous.strides[-1] != query_contiguous.strides[-1] + assert d_discontiguous.strides[-1] != d_contiguous.strides[-1] + + tree = kdtree_type(data) + + length1 = tree.query_ball_point(query_contiguous, + d_contiguous, return_length=True) + length2 = tree.query_ball_point(query_discontiguous, + d_discontiguous, return_length=True) + + assert_array_equal(length1, length2) + + d1, i1 = tree.query(query_contiguous, 1) + d2, i2 = tree.query(query_discontiguous, 1) + + assert_array_equal(d1, d2) + assert_array_equal(i1, i2) + + +@pytest.mark.parametrize("balanced_tree, compact_nodes", + [(True, False), + (True, True), + (False, False), + (False, True)]) +def test_kdtree_empty_input(kdtree_type, balanced_tree, compact_nodes): + # https://github.com/scipy/scipy/issues/5040 + np.random.seed(1234) + empty_v3 = np.empty(shape=(0, 3)) + query_v3 = np.ones(shape=(1, 3)) + query_v2 = np.ones(shape=(2, 3)) + + tree = kdtree_type(empty_v3, balanced_tree=balanced_tree, + compact_nodes=compact_nodes) + length = tree.query_ball_point(query_v3, 0.3, return_length=True) + assert length == 0 + + dd, ii = tree.query(query_v2, 2) + assert ii.shape == (2, 2) + assert dd.shape == (2, 2) + assert np.isinf(dd).all() + + N = tree.count_neighbors(tree, [0, 1]) + assert_array_equal(N, [0, 0]) + + M = tree.sparse_distance_matrix(tree, 0.3) + assert M.shape == (0, 0) + +@KDTreeTest +class _Test_sorted_query_ball_point: + def setup_method(self): + np.random.seed(1234) + self.x = np.random.randn(100, 1) + self.ckdt = self.kdtree_type(self.x) + + def test_return_sorted_True(self): + idxs_list = self.ckdt.query_ball_point(self.x, 1., return_sorted=True) + for idxs in idxs_list: + assert_array_equal(idxs, sorted(idxs)) + + for xi in self.x: + idxs = self.ckdt.query_ball_point(xi, 1., return_sorted=True) + assert_array_equal(idxs, sorted(idxs)) + + def test_return_sorted_None(self): + """Previous behavior was to sort the returned indices if there were + multiple points per query but not sort them if there was a single point + per query.""" + idxs_list = self.ckdt.query_ball_point(self.x, 1.) + for idxs in idxs_list: + assert_array_equal(idxs, sorted(idxs)) + + idxs_list_single = [self.ckdt.query_ball_point(xi, 1.) for xi in self.x] + idxs_list_False = self.ckdt.query_ball_point(self.x, 1., return_sorted=False) + for idxs0, idxs1 in zip(idxs_list_False, idxs_list_single): + assert_array_equal(idxs0, idxs1) + + +def test_kdtree_complex_data(): + # Test that KDTree rejects complex input points (gh-9108) + points = np.random.rand(10, 2).view(complex) + + with pytest.raises(TypeError, match="complex data"): + t = KDTree(points) + + t = KDTree(points.real) + + with pytest.raises(TypeError, match="complex data"): + t.query(points) + + with pytest.raises(TypeError, match="complex data"): + t.query_ball_point(points, r=1) + + +def test_kdtree_tree_access(): + # Test KDTree.tree can be used to traverse the KDTree + np.random.seed(1234) + points = np.random.rand(100, 4) + t = KDTree(points) + root = t.tree + + assert isinstance(root, KDTree.innernode) + assert root.children == points.shape[0] + + # Visit the tree and assert some basic properties for each node + nodes = [root] + while nodes: + n = nodes.pop(-1) + + if isinstance(n, KDTree.leafnode): + assert isinstance(n.children, int) + assert n.children == len(n.idx) + assert_array_equal(points[n.idx], n._node.data_points) + else: + assert isinstance(n, KDTree.innernode) + assert isinstance(n.split_dim, int) + assert 0 <= n.split_dim < t.m + assert isinstance(n.split, float) + assert isinstance(n.children, int) + assert n.children == n.less.children + n.greater.children + nodes.append(n.greater) + nodes.append(n.less) + + +def test_kdtree_attributes(): + # Test KDTree's attributes are available + np.random.seed(1234) + points = np.random.rand(100, 4) + t = KDTree(points) + + assert isinstance(t.m, int) + assert t.n == points.shape[0] + + assert isinstance(t.n, int) + assert t.m == points.shape[1] + + assert isinstance(t.leafsize, int) + assert t.leafsize == 10 + + assert_array_equal(t.maxes, np.amax(points, axis=0)) + assert_array_equal(t.mins, np.amin(points, axis=0)) + assert t.data is points + + +@pytest.mark.parametrize("kdtree_class", [KDTree, cKDTree]) +def test_kdtree_count_neighbors_weighted(kdtree_class): + rng = np.random.RandomState(1234) + r = np.arange(0.05, 1, 0.05) + + A = rng.random(21).reshape((7,3)) + B = rng.random(45).reshape((15,3)) + + wA = rng.random(7) + wB = rng.random(15) + + kdA = kdtree_class(A) + kdB = kdtree_class(B) + + nAB = kdA.count_neighbors(kdB, r, cumulative=False, weights=(wA,wB)) + + # Compare against brute-force + weights = wA[None, :] * wB[:, None] + dist = np.linalg.norm(A[None, :, :] - B[:, None, :], axis=-1) + expect = [np.sum(weights[(prev_radius < dist) & (dist <= radius)]) + for prev_radius, radius in zip(itertools.chain([0], r[:-1]), r)] + assert_allclose(nAB, expect) + + +def test_kdtree_nan(): + vals = [1, 5, -10, 7, -4, -16, -6, 6, 3, -11] + n = len(vals) + data = np.concatenate([vals, np.full(n, np.nan)])[:, None] + with pytest.raises(ValueError, match="must be finite"): + KDTree(data) + + +def test_nonfinite_inputs_gh_18223(): + rng = np.random.default_rng(12345) + coords = rng.uniform(size=(100, 3), low=0.0, high=0.1) + t = KDTree(coords, balanced_tree=False, compact_nodes=False) + bad_coord = [np.nan for _ in range(3)] + + with pytest.raises(ValueError, match="must be finite"): + t.query(bad_coord) + with pytest.raises(ValueError, match="must be finite"): + t.query_ball_point(bad_coord, 1) + + coords[0, :] = np.nan + with pytest.raises(ValueError, match="must be finite"): + KDTree(coords, balanced_tree=True, compact_nodes=False) + with pytest.raises(ValueError, match="must be finite"): + KDTree(coords, balanced_tree=False, compact_nodes=True) + with pytest.raises(ValueError, match="must be finite"): + KDTree(coords, balanced_tree=True, compact_nodes=True) + with pytest.raises(ValueError, match="must be finite"): + KDTree(coords, balanced_tree=False, compact_nodes=False) + + +@pytest.mark.parametrize("incantation", [cKDTree, KDTree]) +def test_gh_18800(incantation): + # our prohibition on non-finite values + # in kd-tree workflows means we need + # coercion to NumPy arrays enforced + + class ArrLike(np.ndarray): + def __new__(cls, input_array): + obj = np.asarray(input_array).view(cls) + # we override all() to mimic the problem + # pandas DataFrames encountered in gh-18800 + obj.all = None + return obj + + def __array_finalize__(self, obj): + if obj is None: + return + self.all = getattr(obj, 'all', None) + + points = [ + [66.22, 32.54], + [22.52, 22.39], + [31.01, 81.21], + ] + arr = np.array(points) + arr_like = ArrLike(arr) + tree = incantation(points, 10) + tree.query(arr_like, 1) + tree.query_ball_point(arr_like, 200) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_qhull.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_qhull.py new file mode 100644 index 0000000000000000000000000000000000000000..9f4ccd1e5349ac4c3680d16bdfcc1f71418cbf1d --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_qhull.py @@ -0,0 +1,1311 @@ +import os +import copy + +import numpy as np +from numpy.testing import (assert_equal, assert_almost_equal, + assert_, assert_allclose, assert_array_equal) +import pytest +from pytest import raises as assert_raises + +import scipy.spatial._qhull as qhull +from scipy.spatial import cKDTree as KDTree # type: ignore[attr-defined] +from scipy.spatial import Voronoi + +import itertools + +def sorted_tuple(x): + return tuple(sorted(x)) + + +def assert_unordered_tuple_list_equal(a, b, tpl=tuple): + if isinstance(a, np.ndarray): + a = a.tolist() + if isinstance(b, np.ndarray): + b = b.tolist() + a = list(map(tpl, a)) + a.sort() + b = list(map(tpl, b)) + b.sort() + assert_equal(a, b) + + +np.random.seed(1234) + +points = [(0,0), (0,1), (1,0), (1,1), (0.5, 0.5), (0.5, 1.5)] + +pathological_data_1 = np.array([ + [-3.14,-3.14], [-3.14,-2.36], [-3.14,-1.57], [-3.14,-0.79], + [-3.14,0.0], [-3.14,0.79], [-3.14,1.57], [-3.14,2.36], + [-3.14,3.14], [-2.36,-3.14], [-2.36,-2.36], [-2.36,-1.57], + [-2.36,-0.79], [-2.36,0.0], [-2.36,0.79], [-2.36,1.57], + [-2.36,2.36], [-2.36,3.14], [-1.57,-0.79], [-1.57,0.79], + [-1.57,-1.57], [-1.57,0.0], [-1.57,1.57], [-1.57,-3.14], + [-1.57,-2.36], [-1.57,2.36], [-1.57,3.14], [-0.79,-1.57], + [-0.79,1.57], [-0.79,-3.14], [-0.79,-2.36], [-0.79,-0.79], + [-0.79,0.0], [-0.79,0.79], [-0.79,2.36], [-0.79,3.14], + [0.0,-3.14], [0.0,-2.36], [0.0,-1.57], [0.0,-0.79], [0.0,0.0], + [0.0,0.79], [0.0,1.57], [0.0,2.36], [0.0,3.14], [0.79,-3.14], + [0.79,-2.36], [0.79,-0.79], [0.79,0.0], [0.79,0.79], + [0.79,2.36], [0.79,3.14], [0.79,-1.57], [0.79,1.57], + [1.57,-3.14], [1.57,-2.36], [1.57,2.36], [1.57,3.14], + [1.57,-1.57], [1.57,0.0], [1.57,1.57], [1.57,-0.79], + [1.57,0.79], [2.36,-3.14], [2.36,-2.36], [2.36,-1.57], + [2.36,-0.79], [2.36,0.0], [2.36,0.79], [2.36,1.57], + [2.36,2.36], [2.36,3.14], [3.14,-3.14], [3.14,-2.36], + [3.14,-1.57], [3.14,-0.79], [3.14,0.0], [3.14,0.79], + [3.14,1.57], [3.14,2.36], [3.14,3.14], +]) + +pathological_data_2 = np.array([ + [-1, -1], [-1, 0], [-1, 1], + [0, -1], [0, 0], [0, 1], + [1, -1 - np.finfo(np.float64).eps], [1, 0], [1, 1], +]) + +bug_2850_chunks = [np.random.rand(10, 2), + np.array([[0,0], [0,1], [1,0], [1,1]]) # add corners + ] + +# same with some additional chunks +bug_2850_chunks_2 = (bug_2850_chunks + + [np.random.rand(10, 2), + 0.25 + np.array([[0,0], [0,1], [1,0], [1,1]])]) + +DATASETS = { + 'some-points': np.asarray(points), + 'random-2d': np.random.rand(30, 2), + 'random-3d': np.random.rand(30, 3), + 'random-4d': np.random.rand(30, 4), + 'random-5d': np.random.rand(30, 5), + 'random-6d': np.random.rand(10, 6), + 'random-7d': np.random.rand(10, 7), + 'random-8d': np.random.rand(10, 8), + 'pathological-1': pathological_data_1, + 'pathological-2': pathological_data_2 +} + +INCREMENTAL_DATASETS = { + 'bug-2850': (bug_2850_chunks, None), + 'bug-2850-2': (bug_2850_chunks_2, None), +} + + +def _add_inc_data(name, chunksize): + """ + Generate incremental datasets from basic data sets + """ + points = DATASETS[name] + ndim = points.shape[1] + + opts = None + nmin = ndim + 2 + + if name == 'some-points': + # since Qz is not allowed, use QJ + opts = 'QJ Pp' + elif name == 'pathological-1': + # include enough points so that we get different x-coordinates + nmin = 12 + + chunks = [points[:nmin]] + for j in range(nmin, len(points), chunksize): + chunks.append(points[j:j+chunksize]) + + new_name = f"{name}-chunk-{chunksize}" + assert new_name not in INCREMENTAL_DATASETS + INCREMENTAL_DATASETS[new_name] = (chunks, opts) + + +for name in DATASETS: + for chunksize in 1, 4, 16: + _add_inc_data(name, chunksize) + + +class Test_Qhull: + def test_swapping(self): + # Check that Qhull state swapping works + + x = qhull._Qhull(b'v', + np.array([[0,0],[0,1],[1,0],[1,1.],[0.5,0.5]]), + b'Qz') + xd = copy.deepcopy(x.get_voronoi_diagram()) + + y = qhull._Qhull(b'v', + np.array([[0,0],[0,1],[1,0],[1,2.]]), + b'Qz') + yd = copy.deepcopy(y.get_voronoi_diagram()) + + xd2 = copy.deepcopy(x.get_voronoi_diagram()) + x.close() + yd2 = copy.deepcopy(y.get_voronoi_diagram()) + y.close() + + assert_raises(RuntimeError, x.get_voronoi_diagram) + assert_raises(RuntimeError, y.get_voronoi_diagram) + + assert_allclose(xd[0], xd2[0]) + assert_unordered_tuple_list_equal(xd[1], xd2[1], tpl=sorted_tuple) + assert_unordered_tuple_list_equal(xd[2], xd2[2], tpl=sorted_tuple) + assert_unordered_tuple_list_equal(xd[3], xd2[3], tpl=sorted_tuple) + assert_array_equal(xd[4], xd2[4]) + + assert_allclose(yd[0], yd2[0]) + assert_unordered_tuple_list_equal(yd[1], yd2[1], tpl=sorted_tuple) + assert_unordered_tuple_list_equal(yd[2], yd2[2], tpl=sorted_tuple) + assert_unordered_tuple_list_equal(yd[3], yd2[3], tpl=sorted_tuple) + assert_array_equal(yd[4], yd2[4]) + + x.close() + assert_raises(RuntimeError, x.get_voronoi_diagram) + y.close() + assert_raises(RuntimeError, y.get_voronoi_diagram) + + def test_issue_8051(self): + points = np.array( + [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2],[2, 0], [2, 1], [2, 2]] + ) + Voronoi(points) + + +class TestUtilities: + """ + Check that utility functions work. + + """ + + def test_find_simplex(self): + # Simple check that simplex finding works + points = np.array([(0,0), (0,1), (1,1), (1,0)], dtype=np.float64) + tri = qhull.Delaunay(points) + + # +---+ + # |\ 0| + # | \ | + # |1 \| + # +---+ + + assert_equal(tri.simplices, [[1, 3, 2], [3, 1, 0]]) + + for p in [(0.25, 0.25, 1), + (0.75, 0.75, 0), + (0.3, 0.2, 1)]: + i = tri.find_simplex(p[:2]) + assert_equal(i, p[2], err_msg=f'{p!r}') + j = qhull.tsearch(tri, p[:2]) + assert_equal(i, j) + + def test_plane_distance(self): + # Compare plane distance from hyperplane equations obtained from Qhull + # to manually computed plane equations + x = np.array([(0,0), (1, 1), (1, 0), (0.99189033, 0.37674127), + (0.99440079, 0.45182168)], dtype=np.float64) + p = np.array([0.99966555, 0.15685619], dtype=np.float64) + + tri = qhull.Delaunay(x) + + z = tri.lift_points(x) + pz = tri.lift_points(p) + + dist = tri.plane_distance(p) + + for j, v in enumerate(tri.simplices): + x1 = z[v[0]] + x2 = z[v[1]] + x3 = z[v[2]] + + n = np.cross(x1 - x3, x2 - x3) + n /= np.sqrt(np.dot(n, n)) + n *= -np.sign(n[2]) + + d = np.dot(n, pz - x3) + + assert_almost_equal(dist[j], d) + + def test_convex_hull(self): + # Simple check that the convex hull seems to works + points = np.array([(0,0), (0,1), (1,1), (1,0)], dtype=np.float64) + tri = qhull.Delaunay(points) + + # +---+ + # |\ 0| + # | \ | + # |1 \| + # +---+ + + assert_equal(tri.convex_hull, [[3, 2], [1, 2], [1, 0], [3, 0]]) + + def test_volume_area(self): + #Basic check that we get back the correct volume and area for a cube + points = np.array([(0, 0, 0), (0, 1, 0), (1, 0, 0), (1, 1, 0), + (0, 0, 1), (0, 1, 1), (1, 0, 1), (1, 1, 1)]) + hull = qhull.ConvexHull(points) + + assert_allclose(hull.volume, 1., rtol=1e-14, + err_msg="Volume of cube is incorrect") + assert_allclose(hull.area, 6., rtol=1e-14, + err_msg="Area of cube is incorrect") + + def test_random_volume_area(self): + #Test that the results for a random 10-point convex are + #coherent with the output of qconvex Qt s FA + points = np.array([(0.362568364506, 0.472712355305, 0.347003084477), + (0.733731893414, 0.634480295684, 0.950513180209), + (0.511239955611, 0.876839441267, 0.418047827863), + (0.0765906233393, 0.527373281342, 0.6509863541), + (0.146694972056, 0.596725793348, 0.894860986685), + (0.513808585741, 0.069576205858, 0.530890338876), + (0.512343805118, 0.663537132612, 0.037689295973), + (0.47282965018, 0.462176697655, 0.14061843691), + (0.240584597123, 0.778660020591, 0.722913476339), + (0.951271745935, 0.967000673944, 0.890661319684)]) + + hull = qhull.ConvexHull(points) + assert_allclose(hull.volume, 0.14562013, rtol=1e-07, + err_msg="Volume of random polyhedron is incorrect") + assert_allclose(hull.area, 1.6670425, rtol=1e-07, + err_msg="Area of random polyhedron is incorrect") + + def test_incremental_volume_area_random_input(self): + """Test that incremental mode gives the same volume/area as + non-incremental mode and incremental mode with restart""" + nr_points = 20 + dim = 3 + points = np.random.random((nr_points, dim)) + inc_hull = qhull.ConvexHull(points[:dim+1, :], incremental=True) + inc_restart_hull = qhull.ConvexHull(points[:dim+1, :], incremental=True) + for i in range(dim+1, nr_points): + hull = qhull.ConvexHull(points[:i+1, :]) + inc_hull.add_points(points[i:i+1, :]) + inc_restart_hull.add_points(points[i:i+1, :], restart=True) + assert_allclose(hull.volume, inc_hull.volume, rtol=1e-7) + assert_allclose(hull.volume, inc_restart_hull.volume, rtol=1e-7) + assert_allclose(hull.area, inc_hull.area, rtol=1e-7) + assert_allclose(hull.area, inc_restart_hull.area, rtol=1e-7) + + def _check_barycentric_transforms(self, tri, err_msg="", + unit_cube=False, + unit_cube_tol=0): + """Check that a triangulation has reasonable barycentric transforms""" + vertices = tri.points[tri.simplices] + sc = 1/(tri.ndim + 1.0) + centroids = vertices.sum(axis=1) * sc + + # Either: (i) the simplex has a `nan` barycentric transform, + # or, (ii) the centroid is in the simplex + + def barycentric_transform(tr, x): + r = tr[:,-1,:] + Tinv = tr[:,:-1,:] + return np.einsum('ijk,ik->ij', Tinv, x - r) + + eps = np.finfo(float).eps + + c = barycentric_transform(tri.transform, centroids) + with np.errstate(invalid="ignore"): + ok = np.isnan(c).all(axis=1) | (abs(c - sc)/sc < 0.1).all(axis=1) + + assert_(ok.all(), f"{err_msg} {np.nonzero(~ok)}") + + # Invalid simplices must be (nearly) zero volume + q = vertices[:,:-1,:] - vertices[:,-1,None,:] + volume = np.array([np.linalg.det(q[k,:,:]) + for k in range(tri.nsimplex)]) + ok = np.isfinite(tri.transform[:,0,0]) | (volume < np.sqrt(eps)) + assert_(ok.all(), f"{err_msg} {np.nonzero(~ok)}") + + # Also, find_simplex for the centroid should end up in some + # simplex for the non-degenerate cases + j = tri.find_simplex(centroids) + ok = (j != -1) | np.isnan(tri.transform[:,0,0]) + assert_(ok.all(), f"{err_msg} {np.nonzero(~ok)}") + + if unit_cube: + # If in unit cube, no interior point should be marked out of hull + at_boundary = (centroids <= unit_cube_tol).any(axis=1) + at_boundary |= (centroids >= 1 - unit_cube_tol).any(axis=1) + + ok = (j != -1) | at_boundary + assert_(ok.all(), f"{err_msg} {np.nonzero(~ok)}") + + @pytest.mark.fail_slow(10) + def test_degenerate_barycentric_transforms(self): + # The triangulation should not produce invalid barycentric + # transforms that stump the simplex finding + data = np.load(os.path.join(os.path.dirname(__file__), 'data', + 'degenerate_pointset.npz')) + points = data['c'] + data.close() + + tri = qhull.Delaunay(points) + + # Check that there are not too many invalid simplices + bad_count = np.isnan(tri.transform[:,0,0]).sum() + assert_(bad_count < 23, bad_count) + + # Check the transforms + self._check_barycentric_transforms(tri) + + @pytest.mark.slow + @pytest.mark.fail_slow(20) + # OK per https://github.com/scipy/scipy/pull/20487#discussion_r1572684869 + def test_more_barycentric_transforms(self): + # Triangulate some "nasty" grids + + eps = np.finfo(float).eps + + npoints = {2: 70, 3: 11, 4: 5, 5: 3} + + for ndim in range(2, 6): + # Generate an uniform grid in n-d unit cube + x = np.linspace(0, 1, npoints[ndim]) + grid = np.c_[ + list(map(np.ravel, np.broadcast_arrays(*np.ix_(*([x]*ndim))))) + ].T + + err_msg = f"ndim={ndim}" + + # Check using regular grid + tri = qhull.Delaunay(grid) + self._check_barycentric_transforms(tri, err_msg=err_msg, + unit_cube=True) + + # Check with eps-perturbations + np.random.seed(1234) + m = (np.random.rand(grid.shape[0]) < 0.2) + grid[m,:] += 2*eps*(np.random.rand(*grid[m,:].shape) - 0.5) + + tri = qhull.Delaunay(grid) + self._check_barycentric_transforms(tri, err_msg=err_msg, + unit_cube=True, + unit_cube_tol=2*eps) + + # Check with duplicated data + tri = qhull.Delaunay(np.r_[grid, grid]) + self._check_barycentric_transforms(tri, err_msg=err_msg, + unit_cube=True, + unit_cube_tol=2*eps) + + +class TestVertexNeighborVertices: + def _check(self, tri): + expected = [set() for j in range(tri.points.shape[0])] + for s in tri.simplices: + for a in s: + for b in s: + if a != b: + expected[a].add(b) + + indptr, indices = tri.vertex_neighbor_vertices + + got = [set(map(int, indices[indptr[j]:indptr[j+1]])) + for j in range(tri.points.shape[0])] + + assert_equal(got, expected, err_msg=f"{got!r} != {expected!r}") + + def test_triangle(self): + points = np.array([(0,0), (0,1), (1,0)], dtype=np.float64) + tri = qhull.Delaunay(points) + self._check(tri) + + def test_rectangle(self): + points = np.array([(0,0), (0,1), (1,1), (1,0)], dtype=np.float64) + tri = qhull.Delaunay(points) + self._check(tri) + + def test_complicated(self): + points = np.array([(0,0), (0,1), (1,1), (1,0), + (0.5, 0.5), (0.9, 0.5)], dtype=np.float64) + tri = qhull.Delaunay(points) + self._check(tri) + + +class TestDelaunay: + """ + Check that triangulation works. + + """ + def test_masked_array_fails(self): + masked_array = np.ma.masked_all(1) + assert_raises(ValueError, qhull.Delaunay, masked_array) + + # Shouldn't be inherently unsafe; retry with cpython 3.14 once traceback + # thread safety issues are fixed (also goes for other test with same name + # further down) + def test_array_with_nans_fails(self): + points_with_nan = np.array([(0,0), (0,1), (1,1), (1,np.nan)], dtype=np.float64) + assert_raises(ValueError, qhull.Delaunay, points_with_nan) + + def test_nd_simplex(self): + # simple smoke test: triangulate a n-dimensional simplex + for nd in range(2, 8): + points = np.zeros((nd+1, nd)) + for j in range(nd): + points[j,j] = 1.0 + points[-1,:] = 1.0 + + tri = qhull.Delaunay(points) + + tri.simplices.sort() + + assert_equal(tri.simplices, np.arange(nd+1, dtype=int)[None, :]) + assert_equal(tri.neighbors, -1 + np.zeros((nd+1), dtype=int)[None,:]) + + def test_2d_square(self): + # simple smoke test: 2d square + points = np.array([(0,0), (0,1), (1,1), (1,0)], dtype=np.float64) + tri = qhull.Delaunay(points) + + assert_equal(tri.simplices, [[1, 3, 2], [3, 1, 0]]) + assert_equal(tri.neighbors, [[-1, -1, 1], [-1, -1, 0]]) + + def test_duplicate_points(self): + x = np.array([0, 1, 0, 1], dtype=np.float64) + y = np.array([0, 0, 1, 1], dtype=np.float64) + + xp = np.r_[x, x] + yp = np.r_[y, y] + + # shouldn't fail on duplicate points + qhull.Delaunay(np.c_[x, y]) + qhull.Delaunay(np.c_[xp, yp]) + + def test_pathological(self): + # both should succeed + points = DATASETS['pathological-1'] + tri = qhull.Delaunay(points) + assert_equal(tri.points[tri.simplices].max(), points.max()) + assert_equal(tri.points[tri.simplices].min(), points.min()) + + points = DATASETS['pathological-2'] + tri = qhull.Delaunay(points) + assert_equal(tri.points[tri.simplices].max(), points.max()) + assert_equal(tri.points[tri.simplices].min(), points.min()) + + def test_joggle(self): + # Check that the option QJ indeed guarantees that all input points + # occur as vertices of the triangulation + + points = np.random.rand(10, 2) + points = np.r_[points, points] # duplicate input data + + tri = qhull.Delaunay(points, qhull_options="QJ Qbb Pp") + assert_array_equal(np.unique(tri.simplices.ravel()), + np.arange(len(points))) + + def test_coplanar(self): + # Check that the coplanar point output option indeed works + points = np.random.rand(10, 2) + points = np.r_[points, points] # duplicate input data + + tri = qhull.Delaunay(points) + + assert_(len(np.unique(tri.simplices.ravel())) == len(points)//2) + assert_(len(tri.coplanar) == len(points)//2) + + assert_(len(np.unique(tri.coplanar[:,2])) == len(points)//2) + + assert_(np.all(tri.vertex_to_simplex >= 0)) + + def test_furthest_site(self): + points = [(0, 0), (0, 1), (1, 0), (0.5, 0.5), (1.1, 1.1)] + tri = qhull.Delaunay(points, furthest_site=True) + + expected = np.array([(1, 4, 0), (4, 2, 0)]) # from Qhull + assert_array_equal(tri.simplices, expected) + + @pytest.mark.parametrize("name", sorted(INCREMENTAL_DATASETS)) + def test_incremental(self, name): + # Test incremental construction of the triangulation + + chunks, opts = INCREMENTAL_DATASETS[name] + points = np.concatenate(chunks, axis=0) + + obj = qhull.Delaunay(chunks[0], incremental=True, + qhull_options=opts) + for chunk in chunks[1:]: + obj.add_points(chunk) + + obj2 = qhull.Delaunay(points) + + obj3 = qhull.Delaunay(chunks[0], incremental=True, + qhull_options=opts) + if len(chunks) > 1: + obj3.add_points(np.concatenate(chunks[1:], axis=0), + restart=True) + + # Check that the incremental mode agrees with upfront mode + if name.startswith('pathological'): + # XXX: These produce valid but different triangulations. + # They look OK when plotted, but how to check them? + + assert_array_equal(np.unique(obj.simplices.ravel()), + np.arange(points.shape[0])) + assert_array_equal(np.unique(obj2.simplices.ravel()), + np.arange(points.shape[0])) + else: + assert_unordered_tuple_list_equal(obj.simplices, obj2.simplices, + tpl=sorted_tuple) + + assert_unordered_tuple_list_equal(obj2.simplices, obj3.simplices, + tpl=sorted_tuple) + + +def assert_hulls_equal(points, facets_1, facets_2): + # Check that two convex hulls constructed from the same point set + # are equal + + facets_1 = set(map(sorted_tuple, facets_1)) + facets_2 = set(map(sorted_tuple, facets_2)) + + if facets_1 != facets_2 and points.shape[1] == 2: + # The direct check fails for the pathological cases + # --- then the convex hull from Delaunay differs (due + # to rounding error etc.) from the hull computed + # otherwise, by the question whether (tricoplanar) + # points that lie almost exactly on the hull are + # included as vertices of the hull or not. + # + # So we check the result, and accept it if the Delaunay + # hull line segments are a subset of the usual hull. + + eps = 1000 * np.finfo(float).eps + + for a, b in facets_1: + for ap, bp in facets_2: + t = points[bp] - points[ap] + t /= np.linalg.norm(t) # tangent + n = np.array([-t[1], t[0]]) # normal + + # check that the two line segments are parallel + # to the same line + c1 = np.dot(n, points[b] - points[ap]) + c2 = np.dot(n, points[a] - points[ap]) + if not np.allclose(np.dot(c1, n), 0): + continue + if not np.allclose(np.dot(c2, n), 0): + continue + + # Check that the segment (a, b) is contained in (ap, bp) + c1 = np.dot(t, points[a] - points[ap]) + c2 = np.dot(t, points[b] - points[ap]) + c3 = np.dot(t, points[bp] - points[ap]) + if c1 < -eps or c1 > c3 + eps: + continue + if c2 < -eps or c2 > c3 + eps: + continue + + # OK: + break + else: + raise AssertionError("comparison fails") + + # it was OK + return + + assert_equal(facets_1, facets_2) + + +class TestConvexHull: + def test_masked_array_fails(self): + masked_array = np.ma.masked_all(1) + assert_raises(ValueError, qhull.ConvexHull, masked_array) + + def test_array_with_nans_fails(self): + points_with_nan = np.array([(0,0), (1,1), (2,np.nan)], dtype=np.float64) + assert_raises(ValueError, qhull.ConvexHull, points_with_nan) + + @pytest.mark.parametrize("name", sorted(DATASETS)) + def test_hull_consistency_tri(self, name): + # Check that a convex hull returned by qhull in ndim + # and the hull constructed from ndim delaunay agree + points = DATASETS[name] + + tri = qhull.Delaunay(points) + hull = qhull.ConvexHull(points) + + assert_hulls_equal(points, tri.convex_hull, hull.simplices) + + # Check that the hull extremes are as expected + if points.shape[1] == 2: + assert_equal(np.unique(hull.simplices), np.sort(hull.vertices)) + else: + assert_equal(np.unique(hull.simplices), hull.vertices) + + @pytest.mark.parametrize("name", sorted(INCREMENTAL_DATASETS)) + def test_incremental(self, name): + # Test incremental construction of the convex hull + chunks, _ = INCREMENTAL_DATASETS[name] + points = np.concatenate(chunks, axis=0) + + obj = qhull.ConvexHull(chunks[0], incremental=True) + for chunk in chunks[1:]: + obj.add_points(chunk) + + obj2 = qhull.ConvexHull(points) + + obj3 = qhull.ConvexHull(chunks[0], incremental=True) + if len(chunks) > 1: + obj3.add_points(np.concatenate(chunks[1:], axis=0), + restart=True) + + # Check that the incremental mode agrees with upfront mode + assert_hulls_equal(points, obj.simplices, obj2.simplices) + assert_hulls_equal(points, obj.simplices, obj3.simplices) + + def test_vertices_2d(self): + # The vertices should be in counterclockwise order in 2-D + np.random.seed(1234) + points = np.random.rand(30, 2) + + hull = qhull.ConvexHull(points) + assert_equal(np.unique(hull.simplices), np.sort(hull.vertices)) + + # Check counterclockwiseness + x, y = hull.points[hull.vertices].T + angle = np.arctan2(y - y.mean(), x - x.mean()) + assert_(np.all(np.diff(np.unwrap(angle)) > 0)) + + def test_volume_area(self): + # Basic check that we get back the correct volume and area for a cube + points = np.array([(0, 0, 0), (0, 1, 0), (1, 0, 0), (1, 1, 0), + (0, 0, 1), (0, 1, 1), (1, 0, 1), (1, 1, 1)]) + tri = qhull.ConvexHull(points) + + assert_allclose(tri.volume, 1., rtol=1e-14) + assert_allclose(tri.area, 6., rtol=1e-14) + + @pytest.mark.parametrize("incremental", [False, True]) + def test_good2d(self, incremental): + # Make sure the QGn option gives the correct value of "good". + points = np.array([[0.2, 0.2], + [0.2, 0.4], + [0.4, 0.4], + [0.4, 0.2], + [0.3, 0.6]]) + hull = qhull.ConvexHull(points=points, + incremental=incremental, + qhull_options='QG4') + expected = np.array([False, True, False, False], dtype=bool) + actual = hull.good + assert_equal(actual, expected) + + @pytest.mark.parametrize("visibility", [ + "QG4", # visible=True + "QG-4", # visible=False + ]) + @pytest.mark.parametrize("new_gen, expected", [ + # add generator that places QG4 inside hull + # so all facets are invisible + (np.array([[0.3, 0.7]]), + np.array([False, False, False, False, False], dtype=bool)), + # adding a generator on the opposite side of the square + # should preserve the single visible facet & add one invisible + # facet + (np.array([[0.3, -0.7]]), + np.array([False, True, False, False, False], dtype=bool)), + # split the visible facet on top of the square into two + # visible facets, with visibility at the end of the array + # because add_points concatenates + (np.array([[0.3, 0.41]]), + np.array([False, False, False, True, True], dtype=bool)), + # with our current Qhull options, coplanarity will not count + # for visibility; this case shifts one visible & one invisible + # facet & adds a coplanar facet + # simplex at index position 2 is the shifted visible facet + # the final simplex is the coplanar facet + (np.array([[0.5, 0.6], [0.6, 0.6]]), + np.array([False, False, True, False, False], dtype=bool)), + # place the new generator such that it envelops the query + # point within the convex hull, but only just barely within + # the double precision limit + # NOTE: testing exact degeneracy is less predictable than this + # scenario, perhaps because of the default Qt option we have + # enabled for Qhull to handle precision matters + (np.array([[0.3, 0.6 + 1e-16]]), + np.array([False, False, False, False, False], dtype=bool)), + ]) + def test_good2d_incremental_changes(self, new_gen, expected, + visibility): + # use the usual square convex hull + # generators from test_good2d + points = np.array([[0.2, 0.2], + [0.2, 0.4], + [0.4, 0.4], + [0.4, 0.2], + [0.3, 0.6]]) + hull = qhull.ConvexHull(points=points, + incremental=True, + qhull_options=visibility) + hull.add_points(new_gen) + actual = hull.good + if '-' in visibility: + expected = np.invert(expected) + assert_equal(actual, expected) + + @pytest.mark.parametrize("incremental", [False, True]) + def test_good2d_no_option(self, incremental): + # handle case where good attribute doesn't exist + # because Qgn or Qg-n wasn't specified + points = np.array([[0.2, 0.2], + [0.2, 0.4], + [0.4, 0.4], + [0.4, 0.2], + [0.3, 0.6]]) + hull = qhull.ConvexHull(points=points, + incremental=incremental) + actual = hull.good + assert actual is None + # preserve None after incremental addition + if incremental: + hull.add_points(np.zeros((1, 2))) + actual = hull.good + assert actual is None + + @pytest.mark.parametrize("incremental", [False, True]) + def test_good2d_inside(self, incremental): + # Make sure the QGn option gives the correct value of "good". + # When point n is inside the convex hull of the rest, good is + # all False. + points = np.array([[0.2, 0.2], + [0.2, 0.4], + [0.4, 0.4], + [0.4, 0.2], + [0.3, 0.3]]) + hull = qhull.ConvexHull(points=points, + incremental=incremental, + qhull_options='QG4') + expected = np.array([False, False, False, False], dtype=bool) + actual = hull.good + assert_equal(actual, expected) + + @pytest.mark.parametrize("incremental", [False, True]) + def test_good3d(self, incremental): + # Make sure the QGn option gives the correct value of "good" + # for a 3d figure + points = np.array([[0.0, 0.0, 0.0], + [0.90029516, -0.39187448, 0.18948093], + [0.48676420, -0.72627633, 0.48536925], + [0.57651530, -0.81179274, -0.09285832], + [0.67846893, -0.71119562, 0.18406710]]) + hull = qhull.ConvexHull(points=points, + incremental=incremental, + qhull_options='QG0') + expected = np.array([True, False, False, False], dtype=bool) + assert_equal(hull.good, expected) + +class TestVoronoi: + + @pytest.mark.parametrize("qhull_opts, extra_pts", [ + # option Qz (default for SciPy) will add + # an extra point at infinity + ("Qbb Qc Qz", 1), + ("Qbb Qc", 0), + ]) + @pytest.mark.parametrize("n_pts", [50, 100]) + @pytest.mark.parametrize("ndim", [2, 3]) + def test_point_region_structure(self, + qhull_opts, + n_pts, + extra_pts, + ndim): + # see gh-16773 + rng = np.random.default_rng(7790) + points = rng.random((n_pts, ndim)) + vor = Voronoi(points, qhull_options=qhull_opts) + pt_region = vor.point_region + assert pt_region.max() == n_pts - 1 + extra_pts + assert pt_region.size == len(vor.regions) - extra_pts + assert len(vor.regions) == n_pts + extra_pts + assert vor.points.shape[0] == n_pts + # if there is an empty sublist in the Voronoi + # regions data structure, it should never be + # indexed because it corresponds to an internally + # added point at infinity and is not a member of the + # generators (input points) + if extra_pts: + sublens = [len(x) for x in vor.regions] + # only one point at infinity (empty region) + # is allowed + assert sublens.count(0) == 1 + assert sublens.index(0) not in pt_region + + def test_masked_array_fails(self): + masked_array = np.ma.masked_all(1) + assert_raises(ValueError, qhull.Voronoi, masked_array) + + def test_simple(self): + # Simple case with known Voronoi diagram + points = [(0, 0), (0, 1), (0, 2), + (1, 0), (1, 1), (1, 2), + (2, 0), (2, 1), (2, 2)] + + # qhull v o Fv Qbb Qc Qz < dat + output = """ + 2 + 5 10 1 + -10.101 -10.101 + 0.5 0.5 + 0.5 1.5 + 1.5 0.5 + 1.5 1.5 + 2 0 1 + 3 2 0 1 + 2 0 2 + 3 3 0 1 + 4 1 2 4 3 + 3 4 0 2 + 2 0 3 + 3 4 0 3 + 2 0 4 + 0 + 12 + 4 0 3 0 1 + 4 0 1 0 1 + 4 1 4 1 2 + 4 1 2 0 2 + 4 2 5 0 2 + 4 3 4 1 3 + 4 3 6 0 3 + 4 4 5 2 4 + 4 4 7 3 4 + 4 5 8 0 4 + 4 6 7 0 3 + 4 7 8 0 4 + """ + self._compare_qvoronoi(points, output) + + def _compare_qvoronoi(self, points, output, **kw): + """Compare to output from 'qvoronoi o Fv < data' to Voronoi()""" + + # Parse output + output = [list(map(float, x.split())) for x in output.strip().splitlines()] + nvertex = int(output[1][0]) + vertices = list(map(tuple, output[3:2+nvertex])) # exclude inf + nregion = int(output[1][1]) + regions = [[int(y)-1 for y in x[1:]] + for x in output[2+nvertex:2+nvertex+nregion]] + ridge_points = [[int(y) for y in x[1:3]] + for x in output[3+nvertex+nregion:]] + ridge_vertices = [[int(y)-1 for y in x[3:]] + for x in output[3+nvertex+nregion:]] + + # Compare results + vor = qhull.Voronoi(points, **kw) + + def sorttuple(x): + return tuple(sorted(x)) + + assert_allclose(vor.vertices, vertices) + assert_equal(set(map(tuple, vor.regions)), + set(map(tuple, regions))) + + p1 = list(zip(list(map(sorttuple, ridge_points)), + list(map(sorttuple, ridge_vertices)))) + p2 = list(zip(list(map(sorttuple, vor.ridge_points.tolist())), + list(map(sorttuple, vor.ridge_vertices)))) + p1.sort() + p2.sort() + + assert_equal(p1, p2) + + @pytest.mark.parametrize("name", sorted(DATASETS)) + def test_ridges(self, name): + # Check that the ridges computed by Voronoi indeed separate + # the regions of nearest neighborhood, by comparing the result + # to KDTree. + + points = DATASETS[name] + + tree = KDTree(points) + vor = qhull.Voronoi(points) + + for p, v in vor.ridge_dict.items(): + # consider only finite ridges + if not np.all(np.asarray(v) >= 0): + continue + + ridge_midpoint = vor.vertices[v].mean(axis=0) + d = 1e-6 * (points[p[0]] - ridge_midpoint) + + dist, k = tree.query(ridge_midpoint + d, k=1) + assert_equal(k, p[0]) + + dist, k = tree.query(ridge_midpoint - d, k=1) + assert_equal(k, p[1]) + + def test_furthest_site(self): + points = [(0, 0), (0, 1), (1, 0), (0.5, 0.5), (1.1, 1.1)] + + # qhull v o Fv Qbb Qc Qu < dat + output = """ + 2 + 3 5 1 + -10.101 -10.101 + 0.6000000000000001 0.5 + 0.5 0.6000000000000001 + 3 0 2 1 + 2 0 1 + 2 0 2 + 0 + 3 0 2 1 + 5 + 4 0 2 0 2 + 4 0 4 1 2 + 4 0 1 0 1 + 4 1 4 0 1 + 4 2 4 0 2 + """ + self._compare_qvoronoi(points, output, furthest_site=True) + + def test_furthest_site_flag(self): + points = [(0, 0), (0, 1), (1, 0), (0.5, 0.5), (1.1, 1.1)] + + vor = Voronoi(points) + assert_equal(vor.furthest_site,False) + vor = Voronoi(points,furthest_site=True) + assert_equal(vor.furthest_site,True) + + @pytest.mark.fail_slow(10) + @pytest.mark.parametrize("name", sorted(INCREMENTAL_DATASETS)) + def test_incremental(self, name): + # Test incremental construction of the triangulation + + if INCREMENTAL_DATASETS[name][0][0].shape[1] > 3: + # too slow (testing of the result --- qhull is still fast) + return + + chunks, opts = INCREMENTAL_DATASETS[name] + points = np.concatenate(chunks, axis=0) + + obj = qhull.Voronoi(chunks[0], incremental=True, + qhull_options=opts) + for chunk in chunks[1:]: + obj.add_points(chunk) + + obj2 = qhull.Voronoi(points) + + obj3 = qhull.Voronoi(chunks[0], incremental=True, + qhull_options=opts) + if len(chunks) > 1: + obj3.add_points(np.concatenate(chunks[1:], axis=0), + restart=True) + + # -- Check that the incremental mode agrees with upfront mode + assert_equal(len(obj.point_region), len(obj2.point_region)) + assert_equal(len(obj.point_region), len(obj3.point_region)) + + # The vertices may be in different order or duplicated in + # the incremental map + for objx in obj, obj3: + vertex_map = {-1: -1} + for i, v in enumerate(objx.vertices): + for j, v2 in enumerate(obj2.vertices): + if np.allclose(v, v2): + vertex_map[i] = j + + def remap(x): + if hasattr(x, '__len__'): + return tuple({remap(y) for y in x}) + try: + return vertex_map[x] + except KeyError as e: + message = (f"incremental result has spurious vertex " + f"at {objx.vertices[x]!r}") + raise AssertionError(message) from e + + def simplified(x): + items = set(map(sorted_tuple, x)) + if () in items: + items.remove(()) + items = [x for x in items if len(x) > 1] + items.sort() + return items + + assert_equal( + simplified(remap(objx.regions)), + simplified(obj2.regions) + ) + assert_equal( + simplified(remap(objx.ridge_vertices)), + simplified(obj2.ridge_vertices) + ) + + # XXX: compare ridge_points --- not clear exactly how to do this + + +class Test_HalfspaceIntersection: + def assert_unordered_allclose(self, arr1, arr2, rtol=1e-7): + """Check that every line in arr1 is only once in arr2""" + assert_equal(arr1.shape, arr2.shape) + + truths = np.zeros((arr1.shape[0],), dtype=bool) + for l1 in arr1: + indexes = np.nonzero((abs(arr2 - l1) < rtol).all(axis=1))[0] + assert_equal(indexes.shape, (1,)) + truths[indexes[0]] = True + assert_(truths.all()) + + @pytest.mark.parametrize("dt", [np.float64, int]) + def test_cube_halfspace_intersection(self, dt): + halfspaces = np.array([[-1, 0, 0], + [0, -1, 0], + [1, 0, -2], + [0, 1, -2]], dtype=dt) + feasible_point = np.array([1, 1], dtype=dt) + + points = np.array([[0.0, 0.0], [2.0, 0.0], [0.0, 2.0], [2.0, 2.0]]) + + hull = qhull.HalfspaceIntersection(halfspaces, feasible_point) + + assert_allclose(hull.intersections, points) + + def test_self_dual_polytope_intersection(self): + fname = os.path.join(os.path.dirname(__file__), 'data', + 'selfdual-4d-polytope.txt') + ineqs = np.genfromtxt(fname) + halfspaces = -np.hstack((ineqs[:, 1:], ineqs[:, :1])) + + feas_point = np.array([0., 0., 0., 0.]) + hs = qhull.HalfspaceIntersection(halfspaces, feas_point) + + assert_equal(hs.intersections.shape, (24, 4)) + + assert_almost_equal(hs.dual_volume, 32.0) + assert_equal(len(hs.dual_facets), 24) + for facet in hs.dual_facets: + assert_equal(len(facet), 6) + + dists = halfspaces[:, -1] + halfspaces[:, :-1].dot(feas_point) + self.assert_unordered_allclose((halfspaces[:, :-1].T/dists).T, hs.dual_points) + + points = itertools.permutations([0., 0., 0.5, -0.5]) + for point in points: + assert_equal(np.sum((hs.intersections == point).all(axis=1)), 1) + + def test_wrong_feasible_point(self): + halfspaces = np.array([[-1.0, 0.0, 0.0], + [0.0, -1.0, 0.0], + [1.0, 0.0, -1.0], + [0.0, 1.0, -1.0]]) + feasible_point = np.array([0.5, 0.5, 0.5]) + #Feasible point is (ndim,) instead of (ndim-1,) + assert_raises(ValueError, + qhull.HalfspaceIntersection, halfspaces, feasible_point) + feasible_point = np.array([[0.5], [0.5]]) + #Feasible point is (ndim-1, 1) instead of (ndim-1,) + assert_raises(ValueError, + qhull.HalfspaceIntersection, halfspaces, feasible_point) + feasible_point = np.array([[0.5, 0.5]]) + #Feasible point is (1, ndim-1) instead of (ndim-1,) + assert_raises(ValueError, + qhull.HalfspaceIntersection, halfspaces, feasible_point) + + feasible_point = np.array([-0.5, -0.5]) + #Feasible point is outside feasible region + assert_raises(qhull.QhullError, + qhull.HalfspaceIntersection, halfspaces, feasible_point) + + def test_incremental(self): + #Cube + halfspaces = np.array([[0., 0., -1., -0.5], + [0., -1., 0., -0.5], + [-1., 0., 0., -0.5], + [1., 0., 0., -0.5], + [0., 1., 0., -0.5], + [0., 0., 1., -0.5]]) + #Cut each summit + extra_normals = np.array([[1., 1., 1.], + [1., 1., -1.], + [1., -1., 1.], + [1, -1., -1.]]) + offsets = np.array([[-1.]]*8) + extra_halfspaces = np.hstack((np.vstack((extra_normals, -extra_normals)), + offsets)) + + feas_point = np.array([0., 0., 0.]) + + inc_hs = qhull.HalfspaceIntersection(halfspaces, feas_point, incremental=True) + + inc_res_hs = qhull.HalfspaceIntersection(halfspaces, feas_point, + incremental=True) + + for i, ehs in enumerate(extra_halfspaces): + inc_hs.add_halfspaces(ehs[np.newaxis, :]) + + inc_res_hs.add_halfspaces(ehs[np.newaxis, :], restart=True) + + total = np.vstack((halfspaces, extra_halfspaces[:i+1, :])) + + hs = qhull.HalfspaceIntersection(total, feas_point) + + assert_allclose(inc_hs.halfspaces, inc_res_hs.halfspaces) + assert_allclose(inc_hs.halfspaces, hs.halfspaces) + + #Direct computation and restart should have points in same order + assert_allclose(hs.intersections, inc_res_hs.intersections) + #Incremental will have points in different order than direct computation + self.assert_unordered_allclose(inc_hs.intersections, hs.intersections) + + inc_hs.close() + + def test_cube(self): + # Halfspaces of the cube: + halfspaces = np.array([[-1., 0., 0., 0.], # x >= 0 + [1., 0., 0., -1.], # x <= 1 + [0., -1., 0., 0.], # y >= 0 + [0., 1., 0., -1.], # y <= 1 + [0., 0., -1., 0.], # z >= 0 + [0., 0., 1., -1.]]) # z <= 1 + point = np.array([0.5, 0.5, 0.5]) + + hs = qhull.HalfspaceIntersection(halfspaces, point) + + # qhalf H0.5,0.5,0.5 o < input.txt + qhalf_points = np.array([ + [-2, 0, 0], + [2, 0, 0], + [0, -2, 0], + [0, 2, 0], + [0, 0, -2], + [0, 0, 2]]) + qhalf_facets = [ + [2, 4, 0], + [4, 2, 1], + [5, 2, 0], + [2, 5, 1], + [3, 4, 1], + [4, 3, 0], + [5, 3, 1], + [3, 5, 0]] + + assert len(qhalf_facets) == len(hs.dual_facets) + for a, b in zip(qhalf_facets, hs.dual_facets): + assert set(a) == set(b) # facet orientation can differ + + assert_allclose(hs.dual_points, qhalf_points) + + @pytest.mark.parametrize("k", range(1,4)) + def test_halfspace_batch(self, k): + # Test that we can add halfspaces a few at a time + big_square = np.array([[ 1., 0., -2.], + [-1., 0., -2.], + [ 0., 1., -2.], + [ 0., -1., -2.]]) + + small_square = np.array([[ 1., 0., -1.], + [-1., 0., -1.], + [ 0., 1., -1.], + [ 0., -1., -1.]]) + + hs = qhull.HalfspaceIntersection(big_square, + np.array([0.3141, 0.2718]), + incremental=True) + + hs.add_halfspaces(small_square[0:k,:]) + hs.add_halfspaces(small_square[k:4,:]) + hs.close() + + # Check the intersections are correct (they are the corners of the small square) + expected_intersections = np.array([[1., 1.], + [1., -1.], + [-1., 1.], + [-1., -1.]]) + actual_intersections = hs.intersections + # They may be in any order, so just check that under some permutation + # expected=actual. + + ind1 = np.lexsort((actual_intersections[:, 1], actual_intersections[:, 0])) + ind2 = np.lexsort((expected_intersections[:, 1], expected_intersections[:, 0])) + assert_allclose(actual_intersections[ind1], expected_intersections[ind2]) + + + @pytest.mark.parametrize("halfspaces", [ + (np.array([-0.70613882, -0.45589431, 0.04178256])), + (np.array([[-0.70613882, -0.45589431, 0.04178256], + [0.70807342, -0.45464871, -0.45969769], + [0., 0.76515026, -0.35614825]])), + ]) + def test_gh_19865(self, halfspaces): + # starting off with a feasible interior point and + # adding halfspaces for which it is no longer feasible + # should result in an error rather than a problematic + # intersection polytope + initial_square = np.array( + [[1, 0, -1], [0, 1, -1], [-1, 0, -1], [0, -1, -1]] + ) + incremental_intersector = qhull.HalfspaceIntersection(initial_square, + np.zeros(2), + incremental=True) + with pytest.raises(qhull.QhullError, match="feasible.*-0.706.*"): + incremental_intersector.add_halfspaces(halfspaces) + + + def test_gh_19865_3d(self): + # 3d case where closed half space is enforced for + # feasibility + halfspaces = np.array([[1, 1, 1, -1], # doesn't exclude origin + [-1, -1, -1, -1], # doesn't exclude origin + [1, 0, 0, 0]]) # the origin is on the line + initial_cube = np.array([[1, 0, 0, -1], + [-1, 0, 0, -1], + [0, 1, 0, -1], + [0, -1, 0, -1], + [0, 0, 1, -1], + [0, 0, -1, -1]]) + incremental_intersector = qhull.HalfspaceIntersection(initial_cube, + np.zeros(3), + incremental=True) + with pytest.raises(qhull.QhullError, match="feasible.*[1 0 0 0]"): + incremental_intersector.add_halfspaces(halfspaces) + + + def test_2d_add_halfspace_input(self): + # incrementally added halfspaces should respect the 2D + # array shape requirement + initial_square = np.array( + [[1, 0, -1], [0, 1, -1], [-1, 0, -1], [0, -1, -1]] + ) + incremental_intersector = qhull.HalfspaceIntersection(initial_square, + np.zeros(2), + incremental=True) + with pytest.raises(ValueError, match="2D array"): + incremental_intersector.add_halfspaces(np.ones((4, 4, 4))) + + def test_1d_add_halfspace_input(self): + # we do allow 1D `halfspaces` input to add_halfspaces() + initial_square = np.array( + [[1, 0, -1], [0, 1, -1], [-1, 0, -1], [0, -1, -1]] + ) + incremental_intersector = qhull.HalfspaceIntersection(initial_square, + np.zeros(2), + incremental=True) + assert_allclose(incremental_intersector.dual_vertices, np.arange(4)) + incremental_intersector.add_halfspaces(np.array([2, 2, -1])) + assert_allclose(incremental_intersector.dual_vertices, np.arange(5)) + + +@pytest.mark.parametrize("diagram_type", [Voronoi, qhull.Delaunay]) +def test_gh_20623(diagram_type): + rng = np.random.default_rng(123) + invalid_data = rng.random((4, 10, 3)) + with pytest.raises(ValueError, match="dimensions"): + diagram_type(invalid_data) + + +def test_gh_21286(): + generators = np.array([[0, 0], [0, 1.1], [1, 0], [1, 1]]) + tri = qhull.Delaunay(generators) + # verify absence of segfault reported in ticket: + with pytest.raises(IndexError): + tri.find_simplex(1) + with pytest.raises(IndexError): + # strikingly, Delaunay object has shape + # () just like np.asanyarray(1) above + tri.find_simplex(tri) + + +def test_find_simplex_ndim_err(): + generators = np.array([[0, 0], [0, 1.1], [1, 0], [1, 1]]) + tri = qhull.Delaunay(generators) + with pytest.raises(ValueError): + tri.find_simplex([2, 2, 2]) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_slerp.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_slerp.py new file mode 100644 index 0000000000000000000000000000000000000000..001701e8e85f275e61e10c59086065385cc2e516 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_slerp.py @@ -0,0 +1,465 @@ +import math +import warnings + +import numpy as np +from numpy.testing import assert_allclose + +import pytest +from scipy.spatial import geometric_slerp + + +def _generate_spherical_points(ndim=3, n_pts=2): + # generate uniform points on sphere + # see: https://stackoverflow.com/a/23785326 + # tentatively extended to arbitrary dims + # for 0-sphere it will always produce antipodes + np.random.seed(123) + points = np.random.normal(size=(n_pts, ndim)) + points /= np.linalg.norm(points, axis=1)[:, np.newaxis] + return points[0], points[1] + + +class TestGeometricSlerp: + # Test various properties of the geometric slerp code + + @pytest.mark.parametrize("n_dims", [2, 3, 5, 7, 9]) + @pytest.mark.parametrize("n_pts", [0, 3, 17]) + def test_shape_property(self, n_dims, n_pts): + # geometric_slerp output shape should match + # input dimensionality & requested number + # of interpolation points + start, end = _generate_spherical_points(n_dims, 2) + + actual = geometric_slerp(start=start, + end=end, + t=np.linspace(0, 1, n_pts)) + + assert actual.shape == (n_pts, n_dims) + + @pytest.mark.parametrize("n_dims", [2, 3, 5, 7, 9]) + @pytest.mark.parametrize("n_pts", [3, 17]) + def test_include_ends(self, n_dims, n_pts): + # geometric_slerp should return a data structure + # that includes the start and end coordinates + # when t includes 0 and 1 ends + # this is convenient for plotting surfaces represented + # by interpolations for example + + # the generator doesn't work so well for the unit + # sphere (it always produces antipodes), so use + # custom values there + start, end = _generate_spherical_points(n_dims, 2) + + actual = geometric_slerp(start=start, + end=end, + t=np.linspace(0, 1, n_pts)) + + assert_allclose(actual[0], start) + assert_allclose(actual[-1], end) + + @pytest.mark.parametrize("start, end", [ + # both arrays are not flat + (np.zeros((1, 3)), np.ones((1, 3))), + # only start array is not flat + (np.zeros((1, 3)), np.ones(3)), + # only end array is not flat + (np.zeros(1), np.ones((3, 1))), + ]) + def test_input_shape_flat(self, start, end): + # geometric_slerp should handle input arrays that are + # not flat appropriately + with pytest.raises(ValueError, match='one-dimensional'): + geometric_slerp(start=start, + end=end, + t=np.linspace(0, 1, 10)) + + @pytest.mark.parametrize("start, end", [ + # 7-D and 3-D ends + (np.zeros(7), np.ones(3)), + # 2-D and 1-D ends + (np.zeros(2), np.ones(1)), + # empty, "3D" will also get caught this way + (np.array([]), np.ones(3)), + ]) + def test_input_dim_mismatch(self, start, end): + # geometric_slerp must appropriately handle cases where + # an interpolation is attempted across two different + # dimensionalities + with pytest.raises(ValueError, match='dimensions'): + geometric_slerp(start=start, + end=end, + t=np.linspace(0, 1, 10)) + + @pytest.mark.parametrize("start, end", [ + # both empty + (np.array([]), np.array([])), + ]) + def test_input_at_least1d(self, start, end): + # empty inputs to geometric_slerp must + # be handled appropriately when not detected + # by mismatch + with pytest.raises(ValueError, match='at least two-dim'): + geometric_slerp(start=start, + end=end, + t=np.linspace(0, 1, 10)) + + @pytest.mark.parametrize("start, end, expected", [ + # North and South Poles are definitely antipodes + # but should be handled gracefully now + (np.array([0, 0, 1.0]), np.array([0, 0, -1.0]), "warning"), + # this case will issue a warning & be handled + # gracefully as well; + # North Pole was rotated very slightly + # using r = R.from_euler('x', 0.035, degrees=True) + # to achieve Euclidean distance offset from diameter by + # 9.328908379124812e-08, within the default tol + (np.array([0.00000000e+00, + -6.10865200e-04, + 9.99999813e-01]), np.array([0, 0, -1.0]), "warning"), + # this case should succeed without warning because a + # sufficiently large + # rotation was applied to North Pole point to shift it + # to a Euclidean distance of 2.3036691931821451e-07 + # from South Pole, which is larger than tol + (np.array([0.00000000e+00, + -9.59930941e-04, + 9.99999539e-01]), np.array([0, 0, -1.0]), "success"), + ]) + def test_handle_antipodes(self, start, end, expected): + # antipodal points must be handled appropriately; + # there are an infinite number of possible geodesic + # interpolations between them in higher dims + if expected == "warning": + with pytest.warns(UserWarning, match='antipodes'): + res = geometric_slerp(start=start, + end=end, + t=np.linspace(0, 1, 10)) + else: + res = geometric_slerp(start=start, + end=end, + t=np.linspace(0, 1, 10)) + + # antipodes or near-antipodes should still produce + # slerp paths on the surface of the sphere (but they + # may be ambiguous): + assert_allclose(np.linalg.norm(res, axis=1), 1.0) + + @pytest.mark.parametrize("start, end, expected", [ + # 2-D with n_pts=4 (two new interpolation points) + # this is an actual circle + (np.array([1, 0]), + np.array([0, 1]), + np.array([[1, 0], + [np.sqrt(3) / 2, 0.5], # 30 deg on unit circle + [0.5, np.sqrt(3) / 2], # 60 deg on unit circle + [0, 1]])), + # likewise for 3-D (add z = 0 plane) + # this is an ordinary sphere + (np.array([1, 0, 0]), + np.array([0, 1, 0]), + np.array([[1, 0, 0], + [np.sqrt(3) / 2, 0.5, 0], + [0.5, np.sqrt(3) / 2, 0], + [0, 1, 0]])), + # for 5-D, pad more columns with constants + # zeros are easiest--non-zero values on unit + # circle are more difficult to reason about + # at higher dims + (np.array([1, 0, 0, 0, 0]), + np.array([0, 1, 0, 0, 0]), + np.array([[1, 0, 0, 0, 0], + [np.sqrt(3) / 2, 0.5, 0, 0, 0], + [0.5, np.sqrt(3) / 2, 0, 0, 0], + [0, 1, 0, 0, 0]])), + + ]) + def test_straightforward_examples(self, start, end, expected): + # some straightforward interpolation tests, sufficiently + # simple to use the unit circle to deduce expected values; + # for larger dimensions, pad with constants so that the + # data is N-D but simpler to reason about + actual = geometric_slerp(start=start, + end=end, + t=np.linspace(0, 1, 4)) + assert_allclose(actual, expected, atol=1e-16) + + @pytest.mark.parametrize("start, end", [ + (np.array([1]), + np.array([0])), + (np.array([0]), + np.array([1])), + (np.array([-17.7]), + np.array([165.9])), + ]) + def test_0_sphere_handling(self, start, end): + # it does not make sense to interpolate the set of + # two points that is the 0-sphere + with pytest.raises(ValueError, match='at least two-dim'): + _ = geometric_slerp(start=start, + end=end, + t=np.linspace(0, 1, 4)) + + @pytest.mark.parametrize("tol", [ + # an integer currently raises + 5, + # string raises + "7", + # list and arrays also raise + [5, 6, 7], np.array(9.0), + ]) + def test_tol_type(self, tol): + # geometric_slerp() should raise if tol is not + # a suitable float type + with pytest.raises(ValueError, match='must be a float'): + _ = geometric_slerp(start=np.array([1, 0]), + end=np.array([0, 1]), + t=np.linspace(0, 1, 5), + tol=tol) + + @pytest.mark.parametrize("tol", [ + -5e-6, + -7e-10, + ]) + def test_tol_sign(self, tol): + # geometric_slerp() currently handles negative + # tol values, as long as they are floats + _ = geometric_slerp(start=np.array([1, 0]), + end=np.array([0, 1]), + t=np.linspace(0, 1, 5), + tol=tol) + + @pytest.mark.parametrize("start, end", [ + # 1-sphere (circle) with one point at origin + # and the other on the circle + (np.array([1, 0]), np.array([0, 0])), + # 2-sphere (normal sphere) with both points + # just slightly off sphere by the same amount + # in different directions + (np.array([1 + 1e-6, 0, 0]), + np.array([0, 1 - 1e-6, 0])), + # same thing in 4-D + (np.array([1 + 1e-6, 0, 0, 0]), + np.array([0, 1 - 1e-6, 0, 0])), + ]) + def test_unit_sphere_enforcement(self, start, end): + # geometric_slerp() should raise on input that clearly + # cannot be on an n-sphere of radius 1 + with pytest.raises(ValueError, match='unit n-sphere'): + geometric_slerp(start=start, + end=end, + t=np.linspace(0, 1, 5)) + + @pytest.mark.parametrize("start, end", [ + # 1-sphere 45 degree case + (np.array([1, 0]), + np.array([np.sqrt(2) / 2., + np.sqrt(2) / 2.])), + # 2-sphere 135 degree case + (np.array([1, 0]), + np.array([-np.sqrt(2) / 2., + np.sqrt(2) / 2.])), + ]) + @pytest.mark.parametrize("t_func", [ + np.linspace, np.logspace]) + def test_order_handling(self, start, end, t_func): + # geometric_slerp() should handle scenarios with + # ascending and descending t value arrays gracefully; + # results should simply be reversed + + # for scrambled / unsorted parameters, the same values + # should be returned, just in scrambled order + + num_t_vals = 20 + np.random.seed(789) + forward_t_vals = t_func(0, 10, num_t_vals) + # normalize to max of 1 + forward_t_vals /= forward_t_vals.max() + reverse_t_vals = np.flipud(forward_t_vals) + shuffled_indices = np.arange(num_t_vals) + np.random.shuffle(shuffled_indices) + scramble_t_vals = forward_t_vals.copy()[shuffled_indices] + + forward_results = geometric_slerp(start=start, + end=end, + t=forward_t_vals) + reverse_results = geometric_slerp(start=start, + end=end, + t=reverse_t_vals) + scrambled_results = geometric_slerp(start=start, + end=end, + t=scramble_t_vals) + + # check fidelity to input order + assert_allclose(forward_results, np.flipud(reverse_results)) + assert_allclose(forward_results[shuffled_indices], + scrambled_results) + + @pytest.mark.parametrize("t", [ + # string: + "15, 5, 7", + # complex numbers currently produce a warning + # but not sure we need to worry about it too much: + # [3 + 1j, 5 + 2j], + ]) + def test_t_values_conversion(self, t): + with pytest.raises(ValueError): + _ = geometric_slerp(start=np.array([1]), + end=np.array([0]), + t=t) + + def test_accept_arraylike(self): + # array-like support requested by reviewer + # in gh-10380 + actual = geometric_slerp([1, 0], [0, 1], [0, 1/3, 0.5, 2/3, 1]) + + # expected values are based on visual inspection + # of the unit circle for the progressions along + # the circumference provided in t + expected = np.array([[1, 0], + [np.sqrt(3) / 2, 0.5], + [np.sqrt(2) / 2, + np.sqrt(2) / 2], + [0.5, np.sqrt(3) / 2], + [0, 1]], dtype=np.float64) + # Tyler's original Cython implementation of geometric_slerp + # can pass at atol=0 here, but on balance we will accept + # 1e-16 for an implementation that avoids Cython and + # makes up accuracy ground elsewhere + assert_allclose(actual, expected, atol=1e-16) + + def test_scalar_t(self): + # when t is a scalar, return value is a single + # interpolated point of the appropriate dimensionality + # requested by reviewer in gh-10380 + actual = geometric_slerp([1, 0], [0, 1], 0.5) + expected = np.array([np.sqrt(2) / 2, + np.sqrt(2) / 2], dtype=np.float64) + assert actual.shape == (2,) + assert_allclose(actual, expected) + + @pytest.mark.parametrize('start', [ + np.array([1, 0, 0]), + np.array([0, 1]), + ]) + @pytest.mark.parametrize('t', [ + np.array(1), + np.array([1]), + np.array([[1]]), + np.array([[[1]]]), + np.array([]), + np.linspace(0, 1, 5), + ]) + def test_degenerate_input(self, start, t): + if np.asarray(t).ndim > 1: + with pytest.raises(ValueError): + geometric_slerp(start=start, end=start, t=t) + else: + + shape = (t.size,) + start.shape + expected = np.full(shape, start) + + actual = geometric_slerp(start=start, end=start, t=t) + assert_allclose(actual, expected) + + # Check that degenerate and non-degenerate + # inputs yield the same size + non_degenerate = geometric_slerp(start=start, end=start[::-1], t=t) + assert actual.size == non_degenerate.size + + @pytest.mark.parametrize('k', np.logspace(-10, -1, 10)) + def test_numerical_stability_pi(self, k): + # geometric_slerp should have excellent numerical + # stability for angles approaching pi between + # the start and end points + angle = np.pi - k + ts = np.linspace(0, 1, 100) + P = np.array([1, 0, 0, 0]) + Q = np.array([np.cos(angle), np.sin(angle), 0, 0]) + # the test should only be enforced for cases where + # geometric_slerp determines that the input is actually + # on the unit sphere + with warnings.catch_warnings(): + warnings.simplefilter("ignore", UserWarning) + result = geometric_slerp(P, Q, ts, 1e-18) + norms = np.linalg.norm(result, axis=1) + error = np.max(np.abs(norms - 1)) + assert error < 4e-15 + + @pytest.mark.parametrize('t', [ + [[0, 0.5]], + [[[[[[[[[0, 0.5]]]]]]]]], + ]) + def test_interpolation_param_ndim(self, t): + # regression test for gh-14465 + arr1 = np.array([0, 1]) + arr2 = np.array([1, 0]) + + with pytest.raises(ValueError): + geometric_slerp(start=arr1, + end=arr2, + t=t) + + with pytest.raises(ValueError): + geometric_slerp(start=arr1, + end=arr1, + t=t) + + + @pytest.mark.parametrize("start, end, t, expected", [ + # verify intuitive cases for t > 1 or < 0 (extrapolation) + + # quarter way around the unit circle, doubling to + # half way around (allowed antipode since non-ambiguous + # geodesic): + ([0, 1], [1, 0], 2, [0, -1]), + # 1/8 way around the unit circle, quadrupling to half way + # (another allowed non-ambiguous antipode) + ([0, 1], [math.sqrt(2)/2, math.sqrt(2)/2], 4, [0, -1]), + # 1/8 way around the unit circle, 6x to 3/4 way around (270 deg) + ([0, 1], [math.sqrt(2)/2, math.sqrt(2)/2], 6, [-1, 0]), + # 1/8 way around the unit circle, 7x to 315 deg + ([0, 1], [math.sqrt(2)/2, math.sqrt(2)/2], 7, + [-math.sqrt(2)/2, math.sqrt(2)/2]), + # the above three extrapolations in reverse order should be returned + # in that same order: + ([0, 1], + [math.sqrt(2)/2, math.sqrt(2)/2], + [7, 6, 4], + [[-math.sqrt(2)/2, math.sqrt(2)/2], + [-1, 0], + [0, -1]]), + # same case in 3d (sphere), in the xy plane: + ([0, 1, 0], + [math.sqrt(2)/2, math.sqrt(2)/2, 0], + [7, 6, 4], + [[-math.sqrt(2)/2, math.sqrt(2)/2, 0], + [-1, 0, 0], + [0, -1, 0]]), + # 1/8 way around the unit circle, moving 300 deg backwards + # should end up at pi/6 (since there is no forward travel with + # negative extrapolation) + ([0, 1], [math.sqrt(2)/2, math.sqrt(2)/2], (-300/45), [math.sqrt(3)/2, 0.5]), + ]) + def test_extrapolation_basic(self, start, end, t, expected): + actual_path = geometric_slerp(start=start, + end=end, + t=t) + assert_allclose(actual_path, expected, atol=2e-16) + + @pytest.mark.parametrize("start, end, t, expected", [ + # cases where start and end proper are antipodes + # and t > 1 or < 0; these cases should issue a warning due to + # geodesic ambiguity + + # North to South on unit sphere, then back to North again; + # there are an infinite number of possible routes, but they all + # return back to North + ([0, 0, 1], [0, 0, -1], -2, [0, 0, 1]), + # move "backwards" to South pole via an infinite number + # of possible routes + ([0, 0, 1], [0, 0, -1], -1, [0, 0, -1]), + ]) + def test_extrapolation_antipodes(self, start, end, t, expected): + with pytest.warns(UserWarning, match='antipodes'): + actual_path = geometric_slerp(start=start, end=end, t=t) + assert_allclose(actual_path, expected, atol=2.8e-16) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_spherical_voronoi.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_spherical_voronoi.py new file mode 100644 index 0000000000000000000000000000000000000000..8bf4764e9e37312d08f25870327457107b9dcd91 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/tests/test_spherical_voronoi.py @@ -0,0 +1,358 @@ +import numpy as np +import itertools +from numpy.testing import (assert_equal, + assert_almost_equal, + assert_array_equal, + assert_array_almost_equal) +import pytest +from pytest import raises as assert_raises +from scipy.spatial import SphericalVoronoi, distance +from scipy.optimize import linear_sum_assignment +from scipy.constants import golden as phi +from scipy.special import gamma + + +TOL = 1E-10 + + +def _generate_tetrahedron(): + return np.array([[1, 1, 1], [1, -1, -1], [-1, 1, -1], [-1, -1, 1]]) + + +def _generate_cube(): + return np.array(list(itertools.product([-1, 1.], repeat=3))) + + +def _generate_octahedron(): + return np.array([[-1, 0, 0], [+1, 0, 0], [0, -1, 0], + [0, +1, 0], [0, 0, -1], [0, 0, +1]]) + + +def _generate_dodecahedron(): + + x1 = _generate_cube() + x2 = np.array([[0, -phi, -1 / phi], + [0, -phi, +1 / phi], + [0, +phi, -1 / phi], + [0, +phi, +1 / phi]]) + x3 = np.array([[-1 / phi, 0, -phi], + [+1 / phi, 0, -phi], + [-1 / phi, 0, +phi], + [+1 / phi, 0, +phi]]) + x4 = np.array([[-phi, -1 / phi, 0], + [-phi, +1 / phi, 0], + [+phi, -1 / phi, 0], + [+phi, +1 / phi, 0]]) + return np.concatenate((x1, x2, x3, x4)) + + +def _generate_icosahedron(): + x = np.array([[0, -1, -phi], + [0, -1, +phi], + [0, +1, -phi], + [0, +1, +phi]]) + return np.concatenate([np.roll(x, i, axis=1) for i in range(3)]) + + +def _generate_polytope(name): + polygons = ["triangle", "square", "pentagon", "hexagon", "heptagon", + "octagon", "nonagon", "decagon", "undecagon", "dodecagon"] + polyhedra = ["tetrahedron", "cube", "octahedron", "dodecahedron", + "icosahedron"] + if name not in polygons and name not in polyhedra: + raise ValueError("unrecognized polytope") + + if name in polygons: + n = polygons.index(name) + 3 + thetas = np.linspace(0, 2 * np.pi, n, endpoint=False) + p = np.vstack([np.cos(thetas), np.sin(thetas)]).T + elif name == "tetrahedron": + p = _generate_tetrahedron() + elif name == "cube": + p = _generate_cube() + elif name == "octahedron": + p = _generate_octahedron() + elif name == "dodecahedron": + p = _generate_dodecahedron() + elif name == "icosahedron": + p = _generate_icosahedron() + + return p / np.linalg.norm(p, axis=1, keepdims=True) + + +def _hypersphere_area(dim, radius): + # https://en.wikipedia.org/wiki/N-sphere#Closed_forms + return 2 * np.pi**(dim / 2) / gamma(dim / 2) * radius**(dim - 1) + + +def _sample_sphere(n, dim, seed=None): + # Sample points uniformly at random from the hypersphere + rng = np.random.RandomState(seed=seed) + points = rng.randn(n, dim) + points /= np.linalg.norm(points, axis=1, keepdims=True) + return points + + +class TestSphericalVoronoi: + + def setup_method(self): + self.points = np.array([ + [-0.78928481, -0.16341094, 0.59188373], + [-0.66839141, 0.73309634, 0.12578818], + [0.32535778, -0.92476944, -0.19734181], + [-0.90177102, -0.03785291, -0.43055335], + [0.71781344, 0.68428936, 0.12842096], + [-0.96064876, 0.23492353, -0.14820556], + [0.73181537, -0.22025898, -0.6449281], + [0.79979205, 0.54555747, 0.25039913]] + ) + + def test_constructor(self): + center = np.array([1, 2, 3]) + radius = 2 + s1 = SphericalVoronoi(self.points) + # user input checks in SphericalVoronoi now require + # the radius / center to match the generators so adjust + # accordingly here + s2 = SphericalVoronoi(self.points * radius, radius) + s3 = SphericalVoronoi(self.points + center, center=center) + s4 = SphericalVoronoi(self.points * radius + center, radius, center) + assert_array_equal(s1.center, np.array([0, 0, 0])) + assert_equal(s1.radius, 1) + assert_array_equal(s2.center, np.array([0, 0, 0])) + assert_equal(s2.radius, 2) + assert_array_equal(s3.center, center) + assert_equal(s3.radius, 1) + assert_array_equal(s4.center, center) + assert_equal(s4.radius, radius) + + # Test a non-sequence/-ndarray based array-like + s5 = SphericalVoronoi(memoryview(self.points)) # type: ignore[arg-type] + assert_array_equal(s5.center, np.array([0, 0, 0])) + assert_equal(s5.radius, 1) + + def test_vertices_regions_translation_invariance(self): + sv_origin = SphericalVoronoi(self.points) + center = np.array([1, 1, 1]) + sv_translated = SphericalVoronoi(self.points + center, center=center) + assert_equal(sv_origin.regions, sv_translated.regions) + assert_array_almost_equal(sv_origin.vertices + center, + sv_translated.vertices) + + def test_vertices_regions_scaling_invariance(self): + sv_unit = SphericalVoronoi(self.points) + sv_scaled = SphericalVoronoi(self.points * 2, 2) + assert_equal(sv_unit.regions, sv_scaled.regions) + assert_array_almost_equal(sv_unit.vertices * 2, + sv_scaled.vertices) + + def test_old_radius_api_error(self): + with pytest.raises(ValueError, match='`radius` is `None`. *'): + SphericalVoronoi(self.points, radius=None) + + def test_sort_vertices_of_regions(self): + sv = SphericalVoronoi(self.points) + unsorted_regions = sv.regions + sv.sort_vertices_of_regions() + assert_equal(sorted(sv.regions), sorted(unsorted_regions)) + + def test_sort_vertices_of_regions_flattened(self): + expected = sorted([[0, 6, 5, 2, 3], [2, 3, 10, 11, 8, 7], [0, 6, 4, 1], + [4, 8, 7, 5, 6], [9, 11, 10], [2, 7, 5], + [1, 4, 8, 11, 9], [0, 3, 10, 9, 1]]) + expected = list(itertools.chain(*sorted(expected))) # type: ignore + sv = SphericalVoronoi(self.points) + sv.sort_vertices_of_regions() + actual = list(itertools.chain(*sorted(sv.regions))) + assert_array_equal(actual, expected) + + def test_sort_vertices_of_regions_dimensionality(self): + points = np.array([[1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1], + [0.5, 0.5, 0.5, 0.5]]) + with pytest.raises(TypeError, match="three-dimensional"): + sv = SphericalVoronoi(points) + sv.sort_vertices_of_regions() + + def test_num_vertices(self): + # for any n >= 3, a spherical Voronoi diagram has 2n - 4 + # vertices; this is a direct consequence of Euler's formula + # as explained by Dinis and Mamede (2010) Proceedings of the + # 2010 International Symposium on Voronoi Diagrams in Science + # and Engineering + sv = SphericalVoronoi(self.points) + expected = self.points.shape[0] * 2 - 4 + actual = sv.vertices.shape[0] + assert_equal(actual, expected) + + def test_voronoi_circles(self): + sv = SphericalVoronoi(self.points) + for vertex in sv.vertices: + distances = distance.cdist(sv.points, np.array([vertex])) + closest = np.array(sorted(distances)[0:3]) + assert_almost_equal(closest[0], closest[1], 7, str(vertex)) + assert_almost_equal(closest[0], closest[2], 7, str(vertex)) + + def test_duplicate_point_handling(self): + # an exception should be raised for degenerate generators + # related to Issue# 7046 + self.degenerate = np.concatenate((self.points, self.points)) + with assert_raises(ValueError): + SphericalVoronoi(self.degenerate) + + def test_incorrect_radius_handling(self): + # an exception should be raised if the radius provided + # cannot possibly match the input generators + with assert_raises(ValueError): + SphericalVoronoi(self.points, radius=0.98) + + def test_incorrect_center_handling(self): + # an exception should be raised if the center provided + # cannot possibly match the input generators + with assert_raises(ValueError): + SphericalVoronoi(self.points, center=[0.1, 0, 0]) + + @pytest.mark.parametrize("dim", range(2, 6)) + @pytest.mark.parametrize("shift", [False, True]) + def test_single_hemisphere_handling(self, dim, shift): + n = 10 + points = _sample_sphere(n, dim, seed=0) + points[:, 0] = np.abs(points[:, 0]) + center = (np.arange(dim) + 1) * shift + sv = SphericalVoronoi(points + center, center=center) + dots = np.einsum('ij,ij->i', sv.vertices - center, + sv.points[sv._simplices[:, 0]] - center) + circumradii = np.arccos(np.clip(dots, -1, 1)) + assert np.max(circumradii) > np.pi / 2 + + @pytest.mark.parametrize("n", [1, 2, 10]) + @pytest.mark.parametrize("dim", range(2, 6)) + @pytest.mark.parametrize("shift", [False, True]) + def test_rank_deficient(self, n, dim, shift): + center = (np.arange(dim) + 1) * shift + points = _sample_sphere(n, dim - 1, seed=0) + points = np.hstack([points, np.zeros((n, 1))]) + with pytest.raises(ValueError, match="Rank of input points"): + SphericalVoronoi(points + center, center=center) + + @pytest.mark.parametrize("dim", range(2, 6)) + def test_higher_dimensions(self, dim): + n = 100 + points = _sample_sphere(n, dim, seed=0) + sv = SphericalVoronoi(points) + assert sv.vertices.shape[1] == dim + assert len(sv.regions) == n + + # verify Euler characteristic + cell_counts = [] + simplices = np.sort(sv._simplices) + for i in range(1, dim + 1): + cells = [] + for indices in itertools.combinations(range(dim), i): + cells.append(simplices[:, list(indices)]) + cells = np.unique(np.concatenate(cells), axis=0) + cell_counts.append(len(cells)) + expected_euler = 1 + (-1)**(dim-1) + actual_euler = sum([(-1)**i * e for i, e in enumerate(cell_counts)]) + assert expected_euler == actual_euler + + @pytest.mark.parametrize("dim", range(2, 6)) + def test_cross_polytope_regions(self, dim): + # The hypercube is the dual of the cross-polytope, so the voronoi + # vertices of the cross-polytope lie on the points of the hypercube. + + # generate points of the cross-polytope + points = np.concatenate((-np.eye(dim), np.eye(dim))) + sv = SphericalVoronoi(points) + assert all([len(e) == 2**(dim - 1) for e in sv.regions]) + + # generate points of the hypercube + expected = np.vstack(list(itertools.product([-1, 1], repeat=dim))) + expected = expected.astype(np.float64) / np.sqrt(dim) + + # test that Voronoi vertices are correctly placed + dist = distance.cdist(sv.vertices, expected) + res = linear_sum_assignment(dist) + assert dist[res].sum() < TOL + + @pytest.mark.parametrize("dim", range(2, 6)) + def test_hypercube_regions(self, dim): + # The cross-polytope is the dual of the hypercube, so the voronoi + # vertices of the hypercube lie on the points of the cross-polytope. + + # generate points of the hypercube + points = np.vstack(list(itertools.product([-1, 1], repeat=dim))) + points = points.astype(np.float64) / np.sqrt(dim) + sv = SphericalVoronoi(points) + + # generate points of the cross-polytope + expected = np.concatenate((-np.eye(dim), np.eye(dim))) + + # test that Voronoi vertices are correctly placed + dist = distance.cdist(sv.vertices, expected) + res = linear_sum_assignment(dist) + assert dist[res].sum() < TOL + + @pytest.mark.parametrize("n", [10, 500]) + @pytest.mark.parametrize("dim", [2, 3]) + @pytest.mark.parametrize("radius", [0.5, 1, 2]) + @pytest.mark.parametrize("shift", [False, True]) + @pytest.mark.parametrize("single_hemisphere", [False, True]) + def test_area_reconstitution(self, n, dim, radius, shift, + single_hemisphere): + points = _sample_sphere(n, dim, seed=0) + + # move all points to one side of the sphere for single-hemisphere test + if single_hemisphere: + points[:, 0] = np.abs(points[:, 0]) + + center = (np.arange(dim) + 1) * shift + points = radius * points + center + + sv = SphericalVoronoi(points, radius=radius, center=center) + areas = sv.calculate_areas() + assert_almost_equal(areas.sum(), _hypersphere_area(dim, radius)) + + @pytest.mark.parametrize("poly", ["triangle", "dodecagon", + "tetrahedron", "cube", "octahedron", + "dodecahedron", "icosahedron"]) + def test_equal_area_reconstitution(self, poly): + points = _generate_polytope(poly) + n, dim = points.shape + sv = SphericalVoronoi(points) + areas = sv.calculate_areas() + assert_almost_equal(areas, _hypersphere_area(dim, 1) / n) + + def test_area_unsupported_dimension(self): + dim = 4 + points = np.concatenate((-np.eye(dim), np.eye(dim))) + sv = SphericalVoronoi(points) + with pytest.raises(TypeError, match="Only supported"): + sv.calculate_areas() + + @pytest.mark.parametrize("radius", [1, 1.]) + @pytest.mark.parametrize("center", [None, (1, 2, 3), (1., 2., 3.)]) + def test_attribute_types(self, radius, center): + points = radius * self.points + if center is not None: + points += center + + sv = SphericalVoronoi(points, radius=radius, center=center) + assert sv.points.dtype is np.dtype(np.float64) + assert sv.center.dtype is np.dtype(np.float64) + assert isinstance(sv.radius, float) + + def test_region_types(self): + # Tests that region integer type does not change + # See Issue #13412 + sv = SphericalVoronoi(self.points) + dtype = type(sv.regions[0][0]) + # also enforce nested list type per gh-19177 + for region in sv.regions: + assert isinstance(region, list) + sv.sort_vertices_of_regions() + assert isinstance(sv.regions[0][0], dtype) + sv.sort_vertices_of_regions() + assert isinstance(sv.regions[0][0], dtype) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1490a18e2ef0b0435fdada41f6f083aa89a3d859 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/__init__.py @@ -0,0 +1,31 @@ +""" +Spatial Transformations (:mod:`scipy.spatial.transform`) +======================================================== + +.. currentmodule:: scipy.spatial.transform + +This package implements various spatial transformations. For now, rotations +and rigid transforms (rotations and translations) are supported. + +Rotations in 3 dimensions +------------------------- +.. autosummary:: + :toctree: generated/ + + RigidTransform + Rotation + Slerp + RotationSpline +""" +from ._rotation import Rotation, Slerp +from ._rigid_transform import RigidTransform +from ._rotation_spline import RotationSpline + +# Deprecated namespaces, to be removed in v2.0.0 +from . import rotation + +__all__ = ['Rotation', 'Slerp', 'RotationSpline', 'RigidTransform'] + +from scipy._lib._testutils import PytestTester +test = PytestTester(__name__) +del PytestTester diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rigid_transform.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rigid_transform.py new file mode 100644 index 0000000000000000000000000000000000000000..5c6936d557961da76bc74d04da6774a74dee49ca --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rigid_transform.py @@ -0,0 +1,1947 @@ +from __future__ import annotations + +from collections.abc import Iterable, Iterator +from types import EllipsisType, ModuleType, NotImplementedType +from collections.abc import Callable + +import numpy as np + +from scipy._lib._array_api import ( + array_namespace, + is_numpy, + ArrayLike, + Array, + xp_capabilities, +) +from scipy.spatial.transform import Rotation +from scipy.spatial.transform._rotation import _promote +import scipy.spatial.transform._rigid_transform_cy as cython_backend +import scipy.spatial.transform._rigid_transform_xp as xp_backend +import scipy._lib.array_api_extra as xpx +from scipy._lib.array_api_compat import device +from scipy._lib._array_api import xp_promote +from scipy._lib._util import broadcastable + + +__all__ = ["RigidTransform"] + +backend_registry = {array_namespace(np.empty(0)): cython_backend} + + +def select_backend(xp: ModuleType, cython_compatible: bool): + """Select the backend for the given array library. + + We need this selection function because the Cython backend for numpy does not + support quaternions of arbitrary dimensions. We therefore only use the Array API + backend for numpy if we are dealing with rotations of more than one leading + dimension. + """ + if is_numpy(xp) and not cython_compatible: + return xp_backend + return backend_registry.get(xp, xp_backend) + + +@xp_capabilities() +def normalize_dual_quaternion(dual_quat: ArrayLike) -> Array: + """Normalize dual quaternion.""" + xp = array_namespace(dual_quat) + dual_quat = _promote(dual_quat, xp=xp) + single = dual_quat.ndim == 1 and is_numpy(xp) + if single: + dual_quat = xpx.atleast_nd(dual_quat, ndim=2, xp=xp) + cython_compatible = dual_quat.ndim < 3 + dq = select_backend(xp, cython_compatible).normalize_dual_quaternion(dual_quat) + if single: + return dq[0] + return dq + + +class RigidTransform: + """Rigid transform in 3 dimensions. + + This class provides an interface to initialize from and represent rigid + transforms (rotation and translation) in 3D space. In different fields, + this type of transform may be referred to as "*pose*" (especially in + robotics), "*extrinsic parameters*", or the "*model matrix*" (especially in + computer graphics), but the core concept is the same: a rotation and + translation describing the orientation of one 3D coordinate frame relative + to another. Mathematically, these transforms belong to the Special + Euclidean group SE(3), which encodes rotation (SO(3)) plus translation. + + The following operations on rigid transforms are supported: + + - Application on vectors + - Transformation composition + - Transformation inversion + - Transformation indexing + + Note that coordinate systems must be right-handed. Because of this, this + class more precisely represents *proper* rigid transformations in SE(3) + rather than rigid transforms in E(3) more generally [1]_. + + Indexing within a transform is supported since multiple transforms can be + stored within a single `RigidTransform` instance. + + Multiple transforms can be stored in a single `RigidTransform` object, which can be + initialized using N-dimensional arrays and supports broadcasting for all + operations. + + To create `RigidTransform` objects use ``from_...`` methods (see examples + below). ``RigidTransform(...)`` is not supposed to be instantiated directly. + + For rigorous introductions to rigid transforms, see [2]_, [3]_, and [4]_. + + Attributes + ---------- + single + rotation + translation + + Methods + ------- + __len__ + __getitem__ + __mul__ + __pow__ + from_matrix + from_rotation + from_translation + from_components + from_exp_coords + from_dual_quat + as_matrix + as_components + as_exp_coords + as_dual_quat + concatenate + mean + apply + inv + identity + + References + ---------- + .. [1] https://en.wikipedia.org/wiki/Rigid_transformation + .. [2] https://motion.cs.illinois.edu/RoboticSystems/CoordinateTransformations.html + .. [3] https://www.brainvoyager.com/bv/doc/UsersGuide/CoordsAndTransforms/SpatialTransformationMatrices.html + .. [4] Kevin M. Lynch and Frank C. Park, "Modern Robotics: Mechanics, + Planning, and Control" Chapter 3.3, 2017, Cambridge University Press. + https://hades.mech.northwestern.edu/images/2/25/MR-v2.pdf#page=107.31 + .. [5] Paul Furgale, "Representing Robot Pose: The good, the bad, and the + ugly", June 9, 2014. + https://rpg.ifi.uzh.ch/docs/teaching/2024/FurgaleTutorial.pdf + + Notes + ----- + .. versionadded:: 1.16.0 + + Examples + -------- + A `RigidTransform` instance can be initialized in any of the above formats + and converted to any of the others. The underlying object is independent of + the representation used for initialization. + + **Notation Conventions and Composition** + + The notation here largely follows the convention defined in [5]_. When we + name transforms, we read the subscripts from right to left. So ``tf_A_B`` + represents a transform A <- B and can be interpreted as: + + - the coordinates and orientation of B relative to A + - the transformation of points from B to A + - the pose of B described in A's coordinate system + + .. parsed-literal:: + :class: highlight-none + + tf_A_B + ^ ^ + | | + | --- from B + | + ----- to A + + When composing transforms, the order is important. Transforms are not + commutative, so in general ``tf_A_B * tf_B_C`` is not the same as + ``tf_B_C * tf_A_B``. Transforms are composed and applied to vectors + right-to-left. So ``(tf_A_B * tf_B_C).apply(p_C)`` is the same as + ``tf_A_B.apply(tf_B_C.apply(p_C))``. + + When composed, transforms should be ordered such that the multiplication + operator is surrounded by a single frame, so the frame "cancels out" and + the outside frames are left. In the example below, B cancels out and the + outside frames A and C are left. Or to put it another way, A <- C is the + same as A <- B <- C. + + .. parsed-literal:: + :class: highlight-none + + ----------- B cancels out + | | + v v + tf_A_C = tf_A_B * tf_B_C + ^ ^ + | | + ------------ to A, from C are left + + When we notate vectors, we write the subscript of the frame that the vector + is defined in. So ``p_B`` means the point ``p`` defined in frame B. To + transform this point from frame B to coordinates in frame A, we apply the + transform ``tf_A_B`` to the vector, lining things up such that the notated + B frames are next to each other and "cancel out". + + .. parsed-literal:: + :class: highlight-none + + ------------ B cancels out + | | + v v + p_A = tf_A_B.apply(p_B) + ^ + | + -------------- A is left + + **Visualization** + + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + The following function can be used to plot transforms with Matplotlib + by showing how they transform the standard x, y, z coordinate axes: + + >>> import matplotlib.pyplot as plt + >>> colors = ("#FF6666", "#005533", "#1199EE") # Colorblind-safe RGB + >>> def plot_transformed_axes(ax, tf, name=None, scale=1): + ... r = tf.rotation + ... t = tf.translation + ... loc = np.array([t, t]) + ... for i, (axis, c) in enumerate(zip((ax.xaxis, ax.yaxis, ax.zaxis), + ... colors)): + ... axlabel = axis.axis_name + ... axis.set_label_text(axlabel) + ... axis.label.set_color(c) + ... axis.line.set_color(c) + ... axis.set_tick_params(colors=c) + ... line = np.zeros((2, 3)) + ... line[1, i] = scale + ... line_rot = r.apply(line) + ... line_plot = line_rot + loc + ... ax.plot(line_plot[:, 0], line_plot[:, 1], line_plot[:, 2], c) + ... text_loc = line[1]*1.2 + ... text_loc_rot = r.apply(text_loc) + ... text_plot = text_loc_rot + t + ... ax.text(*text_plot, axlabel.upper(), color=c, + ... va="center", ha="center") + ... ax.text(*tf.translation, name, color="k", va="center", ha="center", + ... bbox={"fc": "w", "alpha": 0.8, "boxstyle": "circle"}) + + **Defining Frames** + + Let's work through an example. + + First, define the "world frame" A, also called the "base frame". + All frames are the identity transform from their own perspective. + + >>> tf_A = Tf.identity() + + We will visualize a new frame B in A's coordinate system. So we need to + define the transform that converts coordinates from frame B to frame A + (A <- B). + + Physically, let's imagine constructing B from A by: + + 1) Rotating A by +90 degrees around its x-axis. + 2) Translating the rotated frame 2 units in A's -x direction. + + From A's perspective, B is at [-2, 0, 0] and rotated +90 degrees about the + x-axis, which is exactly the transform A <- B. + + >>> t_A_B = np.array([-2, 0, 0]) + >>> r_A_B = R.from_euler('xyz', [90, 0, 0], degrees=True) + >>> tf_A_B = Tf.from_components(t_A_B, r_A_B) + + Let's plot these frames. + + >>> fig, ax = plt.subplots(subplot_kw={"projection": "3d"}) + >>> plot_transformed_axes(ax, tf_A, name="tfA") # A plotted in A + >>> plot_transformed_axes(ax, tf_A_B, name="tfAB") # B plotted in A + >>> ax.set_title("A, B frames with respect to A") + >>> ax.set_aspect("equal") + >>> ax.figure.set_size_inches(6, 5) + >>> plt.show() + + Now let's visualize a new frame C in B's coordinate system. + Let's imagine constructing C from B by: + + 1) Translating B by 2 units in its +z direction. + 2) Rotating B by +30 degrees around its z-axis. + + >>> t_B_C = np.array([0, 0, 2]) + >>> r_B_C = R.from_euler('xyz', [0, 0, 30], degrees=True) + >>> tf_B_C = Tf.from_components(t_B_C, r_B_C) + + In order to plot these frames from a consistent perspective, we need to + calculate the transform between A and C. Note that we do not make this + transform directly, but instead compose intermediate transforms that let us + get from C to A: + + >>> tf_A_C = tf_A_B * tf_B_C # A <- B <- C + + Now we can plot these three frames from A's perspective. + + >>> fig, ax = plt.subplots(subplot_kw={"projection": "3d"}) + >>> plot_transformed_axes(ax, tf_A, name="tfA") # A plotted in A + >>> plot_transformed_axes(ax, tf_A_B, name="tfAB") # B plotted in A + >>> plot_transformed_axes(ax, tf_A_C, name="tfAC") # C plotted in A + >>> ax.set_title("A, B, C frames with respect to A") + >>> ax.set_aspect("equal") + >>> ax.figure.set_size_inches(6, 5) + >>> plt.show() + + **Transforming Vectors** + + Let's transform a vector from A, to B and C. To do this, we will first + invert the transforms we already have from B and C, to A. + + >>> tf_B_A = tf_A_B.inv() # B <- A + >>> tf_C_A = tf_A_C.inv() # C <- A + + Now we can define a point in A and use the above transforms to get its + coordinates in B and C: + + >>> p1_A = np.array([1, 0, 0]) # +1 in x_A direction + >>> p1_B = tf_B_A.apply(p1_A) + >>> p1_C = tf_C_A.apply(p1_A) + >>> print(p1_A) # Original point 1 in A + [1 0 0] + >>> print(p1_B) # Point 1 in B + [3. 0. 0.] + >>> print(p1_C) # Point 1 in C + [ 2.59807621 -1.5 -2. ] + + We can also do the reverse. We define a point in C and transform it to A: + + >>> p2_C = np.array([0, 1, 0]) # +1 in y_C direction + >>> p2_A = tf_A_C.apply(p2_C) + >>> print(p2_C) # Original point 2 in C + [0 1 0] + >>> print(p2_A) # Point 2 in A + [-2.5 -2. 0.8660254] + + Plot the frames with respect to A again, but also plot these two points: + + >>> fig, ax = plt.subplots(subplot_kw={"projection": "3d"}) + >>> plot_transformed_axes(ax, tf_A, name="tfA") # A plotted in A + >>> plot_transformed_axes(ax, tf_A_B, name="tfAB") # B plotted in A + >>> plot_transformed_axes(ax, tf_A_C, name="tfAC") # C plotted in A + >>> ax.scatter(p1_A[0], p1_A[1], p1_A[2], color=colors[0]) # +1 x_A + >>> ax.scatter(p2_A[0], p2_A[1], p2_A[2], color=colors[1]) # +1 y_C + >>> ax.set_title("A, B, C frames and points with respect to A") + >>> ax.set_aspect("equal") + >>> ax.figure.set_size_inches(6, 5) + >>> plt.show() + + **Switching Base Frames** + + Up to this point, we have been visualizing frames from A's perspective. + Let's use the transforms we defined to visualize the frames from C's + perspective. + + Now C is the "base frame" or "world frame". All frames are the identity + transform from their own perspective. + + >>> tf_C = Tf.identity() + + We've already defined the transform C <- A, and can obtain C <- B by + inverting the existing transform B <- C. + + >>> tf_C_B = tf_B_C.inv() # C <- B + + This lets us plot everything from C's perspective: + + >>> fig, ax = plt.subplots(subplot_kw={"projection": "3d"}) + >>> plot_transformed_axes(ax, tf_C, name="tfC") # C plotted in C + >>> plot_transformed_axes(ax, tf_C_B, name="tfCB") # B plotted in C + >>> plot_transformed_axes(ax, tf_C_A, name="tfCA") # A plotted in C + >>> ax.scatter(p1_C[0], p1_C[1], p1_C[2], color=colors[0]) + >>> ax.scatter(p2_C[0], p2_C[1], p2_C[2], color=colors[1]) + >>> ax.set_title("A, B, C frames and points with respect to C") + >>> ax.set_aspect("equal") + >>> ax.figure.set_size_inches(6, 5) + >>> plt.show() + """ + + def __init__(self, matrix: ArrayLike, normalize: bool = True, copy: bool = True): + """Initialize from a 4x4 transformation matrix. + + Rotations are not meant to be initialized directly. Please use one of + the `from_...` methods instead. + + Parameters + ---------- + matrix : array_like, shape (..., 4, 4) + A single transformation matrix or a stack of transformation + matrices. + normalize : bool, optional + If True, orthonormalize the rotation matrix using singular value + decomposition. If False, the rotation matrix is not checked for + orthogonality or right-handedness. + copy : bool, optional + If True, copy the input matrix. If False, a reference to the input + matrix is used. If normalize is True, the input matrix is always + copied regardless of the value of copy. + + Returns + ------- + transform : `RigidTransform` instance + """ + xp = array_namespace(matrix) + self._xp = xp + matrix = _promote(matrix, xp=xp) + if matrix.shape[-2:] != (4, 4): + raise ValueError( + f"Expected `matrix` to have shape (..., 4, 4), got {matrix.shape}." + ) + # We only need the _single flag for the cython backend. The Array API backend + # uses broadcasting by default and hence returns the correct shape without + # additional _single logic + self._single = matrix.ndim == 2 and is_numpy(xp) + if self._single: + matrix = xpx.atleast_nd(matrix, ndim=3, xp=xp) + + self._backend = select_backend(xp, matrix.ndim < 4) + self._matrix = self._backend.from_matrix(matrix, normalize, copy) + + def __repr__(self): + m = f"{self.as_matrix()!r}".splitlines() + # bump indent (+27 characters) + m[1:] = [" " * 27 + m[i] for i in range(1, len(m))] + return "RigidTransform.from_matrix(" + "\n".join(m) + ")" + + @staticmethod + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def from_matrix(matrix: ArrayLike) -> RigidTransform: + """Initialize from a 4x4 transformation matrix. + + Parameters + ---------- + matrix : array_like, shape (..., 4, 4) + Transformation matrices. Each matrix[..., :, :] represents a 4x4 + transformation matrix. + + Returns + ------- + transform : `RigidTransform` instance + + Notes + ----- + 4x4 rigid transformation matrices are of the form:: + + [ tx] + [ R ty] + [ tz] + [ 0 0 0 1] + + where ``R`` is a 3x3 rotation matrix and ``t = [tx, ty, tz]`` is a 3x1 + translation vector. As rotation matrices must be proper orthogonal, the + rotation component is orthonormalized using singular value decomposition + before initialization. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> import numpy as np + + Creating a transform from a single matrix: + + >>> m = np.array([[0, 1, 0, 2], + ... [0, 0, 1, 3], + ... [1, 0, 0, 4], + ... [0, 0, 0, 1]]) + >>> tf = Tf.from_matrix(m) + >>> tf.as_matrix() + array([[0., 1., 0., 2.], + [0., 0., 1., 3.], + [1., 0., 0., 4.], + [0., 0., 0., 1.]]) + >>> tf.single + True + + Creating a transform from an N-dimensional array of matrices: + + >>> m = np.tile(np.eye(4), (2, 5, 1, 1)) # Shape (2, 5, 4, 4) + >>> tf = Tf.from_matrix(m) + >>> tf.shape + (2, 5) + >>> tf.single + False + >>> len(tf) + 2 + + Matrices with a rotation component that is not proper orthogonal are + orthogonalized using singular value decomposition before initialization: + + >>> tf = Tf.from_matrix(np.diag([2, 2, 2, 1])) + >>> tf.as_matrix() + array([[1., 0., 0., 0.], + [0., 1., 0., 0.], + [0., 0., 1., 0.], + [0., 0., 0., 1.]]) + """ + return RigidTransform(matrix, normalize=True, copy=True) + + @staticmethod + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def from_rotation(rotation: Rotation) -> RigidTransform: + """Initialize from a rotation, without a translation. + + When applying this transform to a vector ``v``, the result is the + same as if the rotation was applied to the vector. + ``Tf.from_rotation(r).apply(v) == r.apply(v)`` + + Parameters + ---------- + rotation : `Rotation` instance + A single rotation or a rotation with N leading dimensions. + + Returns + ------- + transform : `RigidTransform` instance + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Creating a transform from a single rotation: + + >>> r = R.from_euler("ZYX", [90, 30, 0], degrees=True) + >>> r.apply([1, 0, 0]) + array([0. , 0.8660254, -0.5 ]) + >>> tf = Tf.from_rotation(r) + >>> tf.apply([1, 0, 0]) + array([0. , 0.8660254, -0.5 ]) + >>> tf.single + True + + The upper 3x3 submatrix of the transformation matrix is the rotation + matrix: + + >>> np.allclose(tf.as_matrix()[:3, :3], r.as_matrix(), atol=1e-12) + True + + Creating multiple transforms from a rotation with N leading dimensions: + + >>> r = R.from_euler("ZYX", [[90, 30, 0], [45, 30, 60]], degrees=True) + >>> r.apply([1, 0, 0]) + array([[0. , 0.8660254 , -0.5 ], + [0.61237244, 0.61237244, -0.5 ]]) + >>> tf = Tf.from_rotation(r) + >>> tf.apply([1, 0, 0]) + array([[0. , 0.8660254 , -0.5 ], + [0.61237244, 0.61237244, -0.5 ]]) + >>> tf.single + False + >>> len(tf) + 2 + """ + if not isinstance(rotation, Rotation): + raise TypeError( + "Expected `rotation` to be a `Rotation` instance, " + f"got {type(rotation)}." + ) + quat = rotation.as_quat() + xp = array_namespace(quat) + backend = select_backend(xp, quat.ndim < 3) + matrix = backend.from_rotation(quat) + return RigidTransform._from_raw_matrix(matrix, xp, backend) + + @staticmethod + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def from_translation(translation: ArrayLike) -> RigidTransform: + """Initialize from a translation numpy array, without a rotation. + + When applying this transform to a vector ``v``, the result is the same + as if the translation and vector were added together. If ``t`` is the + displacement vector of the translation, then: + + ``Tf.from_translation(t).apply(v) == t + v`` + + Parameters + ---------- + translation : array_like, shape (..., 3) + Translation vectors. Each translation[..., :] represents a 3D + translation vector. + + Returns + ------- + transform : `RigidTransform` instance + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> import numpy as np + + Creating a transform from a single translation vector: + + >>> t = np.array([2, 3, 4]) + >>> t + np.array([1, 0, 0]) + array([3, 3, 4]) + >>> tf = Tf.from_translation(t) + >>> tf.apply([1, 0, 0]) + array([3., 3., 4.]) + >>> tf.single + True + + The top 3x1 points in the rightmost column of the transformation matrix + is the translation vector: + + >>> tf.as_matrix() + array([[1., 0., 0., 2.], + [0., 1., 0., 3.], + [0., 0., 1., 4.], + [0., 0., 0., 1.]]) + >>> np.allclose(tf.as_matrix()[:3, 3], t) + True + + Creating multiple transforms from an N-dimensional array of translation + vectors: + + >>> t = np.array([[2, 3, 4], [1, 0, 0]]) + >>> t + np.array([1, 0, 0]) + array([[3, 3, 4], + [2, 0, 0]]) + >>> tf = Tf.from_translation(t) + >>> tf.apply([1, 0, 0]) + array([[3., 3., 4.], + [2., 0., 0.]]) + >>> np.allclose(tf.as_matrix()[:, :3, 3], t) + True + >>> tf.single + False + >>> len(tf) + 2 + """ + xp = array_namespace(translation) + translation = _promote(translation, xp=xp) + backend = select_backend(xp, translation.ndim < 3) + matrix = backend.from_translation(translation) + return RigidTransform._from_raw_matrix(matrix, xp, backend) + + @staticmethod + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def from_components(translation: ArrayLike, rotation: Rotation) -> RigidTransform: + """Initialize a rigid transform from translation and rotation + components. + + When creating a rigid transform from a translation and rotation, the + translation is applied after the rotation, such that + ``tf = Tf.from_components(translation, rotation)`` + is equivalent to + ``tf = Tf.from_translation(translation) * Tf.from_rotation(rotation)``. + + When applying a transform to a vector ``v``, the result is the + same as if the transform was applied to the vector in the + following way: ``tf.apply(v) == translation + rotation.apply(v)`` + + Parameters + ---------- + translation : array_like, shape (..., 3) + Translation vectors. Each translation[..., :] represents a 3D + translation vector. + rotation : `Rotation` instance + Rotation objects. The shape must be broadcastable with the + translation shape. + + Returns + ------- + transform : `RigidTransform` instance + Rigid transform objects. The shape is determined by broadcasting + the translation and rotation shapes together. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Creating from a single rotation and translation: + + >>> t = np.array([2, 3, 4]) + >>> r = R.from_euler("ZYX", [90, 30, 0], degrees=True) + >>> r.as_matrix() + array([[ 0. , -1., 0. ], + [ 0.8660254, 0., 0.5 ], + [-0.5 , 0., 0.8660254 ]]) + >>> tf = Tf.from_components(t, r) + >>> tf.rotation.as_matrix() + array([[ 0. , -1., 0. ], + [ 0.8660254, 0., 0.5 ], + [-0.5 , 0., 0.8660254 ]]) + >>> tf.translation + array([2., 3., 4.]) + >>> tf.single + True + + When applying a transform to a vector ``v``, the result is the same as + if the transform was applied to the vector in the following way: + ``tf.apply(v) == translation + rotation.apply(v)`` + + >>> r.apply([1, 0, 0]) + array([0. , 0.8660254, -0.5 ]) + >>> t + r.apply([1, 0, 0]) + array([2. , 3.8660254, 3.5 ]) + >>> tf.apply([1, 0, 0]) + array([2. , 3.8660254, 3.5 ]) + """ + rotation_tf = RigidTransform.from_rotation(rotation) + return RigidTransform.from_translation(translation) * rotation_tf + + @staticmethod + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def from_exp_coords(exp_coords: ArrayLike) -> RigidTransform: + r"""Initialize from exponential coordinates of transform. + + This implements the exponential map that converts 6-dimensional real + vectors to SE(3). + + An exponential coordinate vector consists of 6 elements + ``[rx, ry, rz, vx, vy, vz]``. The first 3 encode rotation (and form a + rotation vector used in `Rotation.from_rotvec`) and the last 3 encode + translation (and form a translation vector for pure translations). + The exponential mapping can be expressed as matrix exponential + ``T = exp(tau)``, where ``T`` is a 4x4 matrix representing a rigid + transform and ``tau`` is a 4x4 matrix formed from the elements of an + exponential coordinate vector:: + + tau = [ 0 -rz ry vx] + [ rz 0 -rx vy] + [-ry rx 0 vz] + [ 0 0 0 1] + + Parameters + ---------- + exp_coords : array_like, shape (..., 6) + Exponential coordinate vectors. Each exp_coords[..., :] represents + a 6D exponential coordinate vector with the expected order of + components ``[rx, ry, rz, vx, vy, vz]``. The first 3 components + encode rotation and the last 3 encode translation. + + Returns + ------- + transform : `RigidTransform` instance + Rigid transform objects with the same leading dimensions as the input. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> import numpy as np + + Creating from a single 6d vector of exponential coordinates: + + >>> tf = Tf.from_exp_coords([ + ... -2.01041204, -0.52983629, 0.65773501, + ... 0.10386614, 0.05855009, 0.54959179]) + >>> tf.as_matrix() + array([[0.76406621, 0.10504613, -0.63652819, -0.10209961], + [0.59956454, -0.47987325, 0.64050295, 0.40158789], + [-0.2381705, -0.87102639, -0.42963687, 0.19637636], + [0., 0., 0., 1.]]) + >>> tf.single + True + + A vector of zeros represents the identity transform: + + >>> tf = Tf.from_exp_coords(np.zeros(6)) + >>> tf.as_matrix() + array([[1., 0., 0., 0.], + [0., 1., 0., 0.], + [0., 0., 1., 0.], + [0., 0., 0., 1.]]) + + The last three numbers encode translation. If the first three numbers + are zero, the last three components can be interpreted as the + translation: + + >>> tf_trans = Tf.from_exp_coords([0, 0, 0, 4.3, -2, 3.4]) + >>> tf_trans.translation + array([4.3, -2., 3.4]) + + The first three numbers encode rotation as a rotation vector: + + >>> tf_rot = Tf.from_exp_coords([0.5, 0.3, 0.1, 0, 0, 0]) + >>> tf_rot.rotation.as_rotvec() + array([0.5, 0.3, 0.1]) + + Combining translation and rotation preserves the rotation vector, + but changes the last three components as they encode translation and + rotation: + + >>> (tf_trans * tf_rot).as_exp_coords() + array([0.5, 0.3, 0.1, 3.64305882, -1.25879559, 4.46109265]) + """ + xp = array_namespace(exp_coords) + exp_coords = xp_promote(exp_coords, force_floating=True, xp=xp) + if exp_coords.shape[-1] != 6: + raise ValueError( + f"Expected `exp_coords` to have shape (..., 6), got {exp_coords.shape}." + ) + backend = select_backend(xp, cython_compatible=exp_coords.ndim < 3) + matrix = backend.from_exp_coords(exp_coords) + return RigidTransform._from_raw_matrix(matrix, xp, backend) + + @staticmethod + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def from_dual_quat( + dual_quat: ArrayLike, *, scalar_first: bool = False + ) -> RigidTransform: + """Initialize from a unit dual quaternion. + + Unit dual quaternions encode orientation in a real unit quaternion + and translation in a dual quaternion. There is a double cover, i.e., + the unit dual quaternions q and -q represent the same transform. + + Unit dual quaternions must have a real quaternion with unit norm and + a dual quaternion that is orthogonal to the real quaternion to satisfy + the unit norm constraint. This function will enforce both properties + through normalization. + + Parameters + ---------- + dual_quat : array_like, shape (..., 8) + Unit dual quaternions. Each dual_quat[..., :] represents a unit + dual quaternion. The real part is stored in the first four + components and the dual part in the last four components. + scalar_first : bool, optional + Whether the scalar component goes first or last in the two + individual quaternions that represent the real and the dual part. + Default is False, i.e. the scalar-last order is used. + + Returns + ------- + transform : `RigidTransform` instance + Rigid transform objects with the same leading dimensions as the input. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> import numpy as np + + Creating from a single unit dual quaternion: + + >>> tf = Tf.from_dual_quat([ + ... 0.0617101, -0.06483886, 0.31432811, 0.94508498, + ... 0.04985168, -0.26119618, 0.1691491, -0.07743254]) + >>> tf.as_matrix() + array([[0.79398752, -0.60213598, -0.08376202, 0.24605262], + [0.58613113, 0.79477941, -0.15740392, -0.4932833], + [0.16135089, 0.07588122, 0.98397557, 0.34262676], + [0., 0., 0., 1.]]) + >>> tf.single + True + """ + xp = array_namespace(dual_quat) + dual_quat = _promote(dual_quat, xp=xp) + backend = select_backend(xp, dual_quat.ndim < 3) + matrix = backend.from_dual_quat(dual_quat, scalar_first=scalar_first) + return RigidTransform._from_raw_matrix(matrix, xp, backend) + + @staticmethod + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def identity( + num: int | None = None, *, shape: int | tuple[int, ...] | None = None + ) -> RigidTransform: + """Initialize an identity transform. + + Composition with the identity transform has no effect, and + applying the identity transform to a vector has no effect. + + Parameters + ---------- + num : int, optional + Number of identity transforms to generate. If None (default), + then a single transform is generated. + shape : int or tuple of ints, optional + Shape of the identity transforms. If specified, `num` must + be None. + + Returns + ------- + transform : `RigidTransform` instance + The identity transform. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Creating a single identity transform: + + >>> tf = Tf.identity() + >>> tf.as_matrix() + array([[1., 0., 0., 0.], + [0., 1., 0., 0.], + [0., 0., 1., 0.], + [0., 0., 0., 1.]]) + >>> tf.single + True + + The identity transform can be applied to a vector without effect: + + >>> tf.apply([1, 2, 3]) + array([1., 2., 3.]) + + The identity transform when composed with another transform has no + effect: + + >>> rng = np.random.default_rng(123) + >>> t = rng.random(3) + >>> r = R.random(rng=rng) + >>> tf = Tf.from_components(t, r) + >>> np.allclose((Tf.identity() * tf).as_matrix(), + ... tf.as_matrix(), atol=1e-12) + True + + Multiple identity transforms can be generated at once: + + >>> tf = Tf.identity(2) + >>> tf.as_matrix() + array([[[1., 0., 0., 0.], + [0., 1., 0., 0.], + [0., 0., 1., 0.], + [0., 0., 0., 1.]], + [[1., 0., 0., 0.], + [0., 1., 0., 0.], + [0., 0., 1., 0.], + [0., 0., 0., 1.]]]) + >>> tf.single + False + >>> len(tf) + 2 + """ + if num is not None and shape is not None: + raise ValueError("Only one of `num` and `shape` can be specified.") + if num is None and shape is None: + shape = () + elif num is not None: + shape = (num,) + elif isinstance(shape, int): + shape = (shape,) + elif not isinstance(shape, tuple): + raise ValueError("`shape` must be an int or a tuple of ints or None.") + matrix = np.tile(np.eye(4), shape + (1, 1)) + # No need for a backend call here since identity is easy to construct and we are + # currently not offering a backend-specific identity matrix + return RigidTransform._from_raw_matrix(matrix, array_namespace(matrix)) + + @staticmethod + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def concatenate( + transforms: RigidTransform | Iterable[RigidTransform], + ) -> RigidTransform: + """ + Concatenate a sequence of `RigidTransform` objects into a + single object. + + Parameters + ---------- + transforms : sequence of `RigidTransform` + If a single `RigidTransform` instance is passed in, a copy of + it is returned. + + Returns + ------- + transform : `RigidTransform` instance + The concatenated transform. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> tf1 = Tf.from_translation([1, 0, 0]) + >>> tf2 = Tf.from_translation([[2, 0, 0], [3, 0, 0]]) + >>> Tf.concatenate([tf1, tf2]).translation + array([[1., 0., 0.], + [2., 0., 0.], + [3., 0., 0.]]) + """ + if isinstance(transforms, RigidTransform): + return RigidTransform._from_raw_matrix( + transforms.as_matrix(), transforms._xp + ) + if not all(isinstance(x, RigidTransform) for x in transforms): + raise TypeError("input must contain RigidTransform objects only") + + xp = array_namespace(transforms[0].as_matrix()) + matrix = xp.concat( + [xpx.atleast_nd(x.as_matrix(), ndim=3, xp=xp) for x in transforms] + ) + return RigidTransform._from_raw_matrix(matrix, xp, None) + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def mean(self, + weights: ArrayLike | None = None, + axis: None | int | tuple[int, ...] = None + ) -> RigidTransform: + """Get the mean of the transforms. + + The mean of a set of transforms is the same as the mean of its + rotation and translation components. + + The mean used for the rotation component is the chordal L2 mean (also + called the projected or induced arithmetic mean) [1]_. If ``A`` is a + set of rotation matrices, then the mean ``M`` is the rotation matrix + that minimizes the following loss function: + + .. math:: + + L(M) = \\sum_{i = 1}^{n} w_i \\lVert \\mathbf{A}_i - + \\mathbf{M} \\rVert^2 , + + where :math:`w_i`'s are the `weights` corresponding to each matrix. + + Parameters + ---------- + weights : array_like shape (..., N), optional + Weights describing the relative importance of the transforms. If + None (default), then all values in `weights` are assumed to be + equal. If given, the shape of `weights` must be broadcastable to + the transform shape. Weights must be non-negative. + axis : None, int, or tuple of ints, optional + Axis or axes along which the means are computed. The default is to + compute the mean of all transforms. + + Returns + ------- + mean : `RigidTransform` instance + Single transform containing the mean of the transforms in the + current instance. + + References + ---------- + .. [1] Hartley, Richard, et al., + "Rotation Averaging", International Journal of Computer Vision + 103, 2013, pp. 267-305. + + Examples + -------- + >>> import numpy as np + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> from scipy.spatial.transform import Rotation as R + >>> rng = np.random.default_rng(seed=123) + + The mean of a set of transforms is the same as the mean of the + translation and rotation components: + + >>> t = rng.random((4, 3)) + >>> r = R.random(4, rng=rng) + >>> tf = Tf.from_components(t, r) + >>> tf.mean().as_matrix() + array([[ 0.61593485, -0.74508342, 0.25588075, 0.66999034], + [-0.59353615, -0.65246765, -0.47116962, 0.25481794], + [ 0.51801458, 0.13833531, -0.84411151, 0.52429339], + [0., 0., 0., 1.]]) + >>> Tf.from_components(t.mean(axis=0), r.mean()).as_matrix() + array([[ 0.61593485, -0.74508342, 0.25588075, 0.66999034], + [-0.59353615, -0.65246765, -0.47116962, 0.25481794], + [ 0.51801458, 0.13833531, -0.84411151, 0.52429339], + [0., 0., 0., 1.]]) + """ + mean = self._backend.mean(self._matrix, weights=weights, axis=axis) + return RigidTransform._from_raw_matrix(mean, xp=self._xp, + backend=self._backend) + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def as_matrix(self) -> Array: + """Return a copy of the matrix representation of the transform. + + 4x4 rigid transformation matrices are of the form:: + + [ tx] + [ R ty] + [ tz] + [ 0 0 0 1] + + where ``R`` is a 3x3 orthonormal rotation matrix and + ``t = [tx, ty, tz]`` is a 3x1 translation vector. + + Returns + ------- + matrix : numpy.ndarray, shape (..., 4, 4) + Transformation matrices with the same leading dimensions as the transform. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + A transformation matrix is a 4x4 matrix formed from a 3x3 rotation + matrix and a 3x1 translation vector: + + >>> t = np.array([2, 3, 4]) + >>> r = R.from_matrix([[0, 0, 1], + ... [1, 0, 0], + ... [0, 1, 0]]) + >>> tf = Tf.from_components(t, r) + >>> tf.as_matrix() + array([[ 0., 0., 1., 2.], + [ 1., 0., 0., 3.], + [ 0., 1., 0., 4.], + [ 0., 0., 0., 1.]]) + + >>> Tf.identity(2).as_matrix() + array([[[1., 0., 0., 0.], + [0., 1., 0., 0.], + [0., 0., 1., 0.], + [0., 0., 0., 1.]], + [[1., 0., 0., 0.], + [0., 1., 0., 0.], + [0., 0., 1., 0.], + [0., 0., 0., 1.]]]) + """ + matrix = self._xp.asarray(self._matrix, copy=True) + if self._single: + return matrix[0, ...] + return matrix + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def as_components(self) -> tuple[Array, Rotation]: + """Return the translation and rotation components of the transform, + where the rotation is applied first, followed by the translation. + + 4x4 rigid transformation matrices are of the form:: + + [ tx] + [ R ty] + [ tz] + [ 0 0 0 1] + + Where ``R`` is a 3x3 orthonormal rotation matrix and + ``t = [tx, ty, tz]`` is a 3x1 translation vector. This function + returns the rotation corresponding to this rotation matrix + ``r = Rotation.from_matrix(R)`` and the translation vector ``t``. + + When applying a transform ``tf`` to a vector ``v``, the result is the same + as if the rotation and translation components were applied to the vector + with the following operation: + ``tf.apply(v) == translation + rotation.apply(v)``. + + Returns + ------- + translation : numpy.ndarray, shape (..., 3) + The translation of the transform. + rotation : `Rotation` instance + The rotation of the transform. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Recover the rotation and translation from a transform: + + >>> t = np.array([2, 3, 4]) + >>> r = R.from_matrix([[0, 0, 1], + ... [1, 0, 0], + ... [0, 1, 0]]) + >>> tf = Tf.from_components(t, r) + >>> t, r = tf.as_components() + >>> t + array([2., 3., 4.]) + >>> r.as_matrix() + array([[0., 0., 1.], + [1., 0., 0.], + [0., 1., 0.]]) + + The transform applied to a vector is equivalent to the rotation applied + to the vector, followed by the translation: + + >>> t + r.apply([1, 0, 0]) + array([2., 4., 4.]) + >>> tf.apply([1, 0, 0]) + array([2., 4., 4.]) + """ + return self.translation, self.rotation + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def as_exp_coords(self) -> Array: + """Return the exponential coordinates of the transform. + + This implements the logarithmic map that converts SE(3) to 6-dimensional + real vectors. + + This is an inverse of `from_exp_coords` where details on the mapping can + be found. + + Returns + ------- + exp_coords : numpy.ndarray, shape (..., 6) + Exponential coordinate vectors with the same leading dimensions as the + transform. The first three components define the rotation and the last + three components define the translation. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> import numpy as np + + Get exponential coordinates of the identity matrix: + + >>> Tf.identity().as_exp_coords() + array([0., 0., 0., 0., 0., 0.]) + """ + exp_coords = self._backend.as_exp_coords(self._matrix) + if self._single: + exp_coords = exp_coords[0, ...] + return exp_coords + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def as_dual_quat(self, *, scalar_first: bool = False) -> Array: + """Return the dual quaternion representation of the transform. + + Unit dual quaternions encode orientation in a real unit quaternion + and translation in a dual quaternion. There is a double cover, i.e., + the unit dual quaternions q and -q represent the same transform. + + Parameters + ---------- + scalar_first : bool, optional + Whether the scalar component goes first or last in the two + individual quaternions that represent the real and the dual part. + Default is False, i.e. the scalar-last order is used. + + Returns + ------- + dual_quat : numpy.ndarray, shape (..., 8) + Unit dual quaternion vectors with the same leading dimensions as the + transform. The real part is stored in the first four components and the + dual part in the last four components. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> import numpy as np + + Get identity dual quaternion (we use scalar-last by default): + + >>> Tf.identity().as_dual_quat() + array([0., 0., 0., 1., 0., 0., 0., 0.]) + + When we want to use the scalar-first convention, we use the argument: + + >>> Tf.identity().as_dual_quat(scalar_first=True) + array([1., 0., 0., 0., 0., 0., 0., 0.]) + """ + dual_quat = self._backend.as_dual_quat(self._matrix, scalar_first=scalar_first) + if self._single: + dual_quat = dual_quat[0] + return dual_quat + + def __len__(self) -> int: + """Return the length of the leading transform dimension. + + A transform can store an N-dimensional array of transforms. The length is the + size of the first dimension of this array. If the transform is a single + transform, the length is not defined and an error is raised. + + Returns + ------- + length : int + The number of transforms in this object. + + Raises + ------ + TypeError + If the transform is a single transform. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> import numpy as np + >>> tf = Tf.identity(3) + >>> len(tf) + 3 + + An N-dimensional array of transforms returns its first dimension size: + + >>> t = np.ones((5, 2, 3, 1, 3)) + >>> tf = Tf.from_translation(t) + >>> len(tf) + 5 + + A single transform has no length: + + >>> tf = Tf.from_translation([1, 0, 0]) + >>> len(tf) # doctest: +IGNORE_EXCEPTION_DETAIL + Traceback (most recent call last): + ... + TypeError: Single transform has no len(). + """ + # We don't use self._single here because we also want to raise an error for + # Array API backends that call len() on single RigidTransform objects. + if self.single: + raise TypeError("Single transform has no len") + return self._matrix.shape[0] + + @xp_capabilities( + jax_jit=False, + skip_backends=[("dask.array", "cannot handle zero-length rigid transforms")], + ) + def __getitem__( + self, indexer: int | slice | EllipsisType | None | ArrayLike + ) -> RigidTransform: + """Extract transform(s) at given index(es) from this object. + + Creates a new `RigidTransform` instance containing a subset of + transforms stored in this object. + + Parameters + ---------- + indexer : int or slice or array_like + Specifies which transform(s) to extract. A single indexer must be + specified, i.e. as if indexing a 1 dimensional array or list. + + Returns + ------- + transform : `RigidTransform` instance + Contains + - a single transform, if `indexer` is a single index + - a stack of transform(s), if `indexer` is a slice, or an index + array. + + Raises + ------ + TypeError + If the transform is a single transform. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> t = [[0, 0, 0], [1, 0, 0], [2, 0, 0]] # 3 translations + >>> tf = Tf.from_translation(t) + + A single index returns a single transform: + + >>> tf[0].as_matrix() + array([[1., 0., 0., 0.], + [0., 1., 0., 0.], + [0., 0., 1., 0.], + [0., 0., 0., 1.]]) + + A slice returns a stack of transforms: + + >>> tf[1:3].translation + array([[1., 0., 0.], + [2., 0., 0.]]) + + An index array returns a stack of transforms: + + >>> tf[[0, 2]].translation + array([[0., 0., 0.], + [2., 0., 0.]]) + """ + if self.single: + raise TypeError("Single transform is not subscriptable.") + + is_array = isinstance(indexer, type(self._matrix)) + xp = self._xp + # Masking is only specified in the Array API when the array is the sole index + # This special case handling is necessary to support boolean indexing and + # integer array indexing with take (see + # https://github.com/data-apis/array-api/pull/900#issuecomment-2674432480) + # Ideally we would converge to [indexer, ...] indexing, but this is not + # supported for now. + if is_array and indexer.dtype == xp.bool: + return RigidTransform(self._matrix[indexer], normalize=False) + if is_array and xp.isdtype(indexer.dtype, "integral"): + if self._matrix.shape[0] == 0: + raise IndexError("cannot take from an empty array") + return RigidTransform( + xp.take(self._matrix, indexer, axis=0), normalize=False + ) + return RigidTransform(self._matrix[indexer, ...], normalize=False) + + @xp_capabilities( + jax_jit=False, + skip_backends=[("dask.array", "cannot handle zero-length rigid transforms")], + ) + def __setitem__( + self, + indexer: int | slice | EllipsisType | None | ArrayLike, + value: RigidTransform, + ): + """Set transform(s) at given index(es) in this object. + + Parameters + ---------- + indexer : int or slice or array_like + Specifies which transform(s) to replace. A single indexer must be + specified, i.e. as if indexing a 1 dimensional array or list. + + value : `RigidTransform` instance + The transform(s) to set. + + Raises + ------ + TypeError + If the transform is a single transform. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> t = [[0, 0, 0], [1, 0, 0], [2, 0, 0]] # 3 translations + >>> tf = Tf.from_translation(t) + + Set a single transform: + + >>> tf[0] = Tf.from_translation([9, 9, 9]) + >>> tf.translation + array([[9., 9., 9.], + [1., 0., 0.], + [2., 0., 0.]]) + """ + if self.single: + raise TypeError("Single transform is not subscriptable.") + + if not isinstance(value, RigidTransform): + raise TypeError("value must be a RigidTransform object") + + self._matrix = self._backend.setitem(self._matrix, indexer, value.as_matrix()) + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def __mul__(self, other: RigidTransform) -> RigidTransform | NotImplementedType: + """Compose this transform with the other. + + If ``p`` and ``q`` are two transforms, then the composition of '``q`` + followed by ``p``' is equivalent to ``p * q``. In terms of + transformation matrices, the composition can be expressed as + ``p.as_matrix() @ q.as_matrix()``. + + In terms of translations and rotations, the composition when applied to + a vector ``v`` is equivalent to + ``p.translation + p.rotation.apply(q.translation) + + (p.rotation * q.rotation).apply(v)``. + + This function supports composition of multiple transforms at a time using + broadcasting rules. The resulting shape for two `RigidTransform` instances + ``p`` and ``q`` is `np.broadcast_shapes(p.shape, q.shape)`. + + Parameters + ---------- + other : `RigidTransform` instance + Transform(s) to be composed with this one. The shapes must be + broadcastable. + + Returns + ------- + `RigidTransform` instance + The composed transform. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Compose two transforms: + + >>> tf1 = Tf.from_translation([1, 0, 0]) + >>> tf2 = Tf.from_translation([0, 1, 0]) + >>> tf = tf1 * tf2 + >>> tf.translation + array([1., 1., 0.]) + >>> tf.single + True + + When applied to a vector, the composition of two transforms is applied + in right-to-left order. + + >>> t1, r1 = [1, 2, 3], R.from_euler('z', 60, degrees=True) + >>> t2, r2 = [0, 1, 0], R.from_euler('x', 30, degrees=True) + >>> tf1 = Tf.from_components(t1, r1) + >>> tf2 = Tf.from_components(t2, r2) + >>> tf = tf1 * tf2 + >>> tf.apply([1, 0, 0]) + array([0.6339746, 3.3660254, 3. ]) + >>> tf1.apply(tf2.apply([1, 0, 0])) + array([0.6339746, 3.3660254, 3. ]) + + When at least one of the transforms is not single, the result is a stack + of transforms. + + >>> tf1 = Tf.from_translation([1, 0, 0]) + >>> tf2 = Tf.from_translation([[0, 2, 0], [0, 0, 3]]) + >>> tf = tf1 * tf2 + >>> tf.translation + array([[1., 2., 0.], + [1., 0., 3.]]) + >>> tf.single + False + >>> len(tf) + 2 + + Broadcasting rules apply when composing multiple transforms at a time. + + >>> tf1 = Tf.from_translation(np.ones((5, 1, 3))) # Shape (5, 1, 3) + >>> tf2 = Tf.from_translation(np.ones((1, 4, 3))) # Shape (1, 4, 3) + >>> tf = tf1 * tf2 # Shape (5, 4, 3) + >>> tf.translation.shape + (5, 4, 3) + """ + if not isinstance(other, RigidTransform): + # If other is not a RigidTransform, we return NotImplemented to allow other + # types to implement __rmul__ + return NotImplemented + if not broadcastable(self._matrix.shape, other._matrix.shape): + raise ValueError( + f"Cannot broadcast {self._matrix.shape[:-2]} transforms in " + f"first to {other._matrix.shape[:-2]} transforms in second object." + ) + cython_compatible = self._matrix.ndim < 4 and other._matrix.ndim < 4 + backend = select_backend(self._xp, cython_compatible=cython_compatible) + matrix = backend.compose_transforms(self._matrix, other._matrix) + # Only necessary for cython. Array API broadcasting handles this by default + if self._single and other._single: + matrix = matrix[0, ...] + return RigidTransform(matrix, normalize=True, copy=False) + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def __pow__(self, n: float) -> RigidTransform: + """Compose this transform with itself `n` times. + + A rigid transform `p` when raised to non-integer powers can be thought + of as finding a fraction of the transformation. For example, a power of + 0.5 finds a "halfway" transform from the identity to `p`. + + This is implemented by applying screw linear interpolation (ScLERP) + between `p` and the identity transform, where the angle of the rotation + component is scaled by `n`, and the translation is proportionally + adjusted along the screw axis. + + ``q = p ** n`` can also be expressed as + ``q = RigidTransform.from_exp_coords(p.as_exp_coords() * n)``. + + If `n` is negative, then the transform is inverted before the power + is applied. In other words, ``p ** -abs(n) == p.inv() ** abs(n)``. + + Parameters + ---------- + n : float + The number of times to compose the transform with itself. + + Returns + ------- + `RigidTransform` instance + If the input Rotation `p` contains `N` multiple rotations, then + the output will contain `N` rotations where the `i` th rotation + is equal to ``p[i] ** n``. + + Notes + ----- + There are three notable cases: if ``n == 1`` then a copy of the original + transform is returned, if ``n == 0`` then the identity transform is + returned, and if ``n == -1`` then the inverse transform is returned. + + Note that fractional powers ``n`` which effectively take a root of + rotation, do so using the shortest path smallest representation of that + angle (the principal root). This means that powers of ``n`` and ``1/n`` + are not necessarily inverses of each other. For example, a 0.5 power of + a +240 degree rotation will be calculated as the 0.5 power of a -120 + degree rotation, with the result being a rotation of -60 rather than + +120 degrees. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> import numpy as np + + A power of 2 returns the transform composed with itself: + + >>> tf = Tf.from_translation([1, 2, 3]) + >>> (tf ** 2).translation + array([2., 4., 6.]) + >>> (tf ** 2).as_matrix() + array([[1., 0., 0., 2.], + [0., 1., 0., 4.], + [0., 0., 1., 6.], + [0., 0., 0., 1.]]) + + A negative power returns the inverse of the transform raised to the + absolute value of `n`: + + >>> (tf ** -2).translation + array([-2., -4., -6.]) + >>> np.allclose((tf ** -2).as_matrix(), (tf.inv() ** 2).as_matrix(), + ... atol=1e-12) + True + + A power of 0 returns the identity transform: + + >>> (tf ** 0).as_matrix() + array([[1., 0., 0., 0.], + [0., 1., 0., 0.], + [0., 0., 1., 0.], + [0., 0., 0., 1.]]) + + A power of 1 returns a copy of the original transform: + + >>> (tf ** 1).as_matrix() + array([[1., 0., 0., 1.], + [0., 1., 0., 2.], + [0., 0., 1., 3.], + [0., 0., 0., 1.]]) + + A fractional power returns a transform with a scaled rotation and + translated along the screw axis. Here we take the square root of the + transform, which when squared recovers the original transform: + + >>> tf_half = (tf ** 0.5) + >>> tf_half.translation + array([0.5, 1., 1.5]) + >>> (tf_half ** 2).as_matrix() + array([[1., 0., 0., 1.], + [0., 1., 0., 2.], + [0., 0., 1., 3.], + [0., 0., 0., 1.]]) + """ + matrix = self._backend.pow(self._matrix, n) + if self._single: + matrix = matrix[0, ...] + return RigidTransform._from_raw_matrix(matrix, self._xp, self._backend) + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def inv(self) -> RigidTransform: + """Invert this transform. + + Composition of a transform with its inverse results in an identity + transform. + + A rigid transform is a composition of a rotation and a translation, + where the rotation is applied first, followed by the translation. So the + inverse transform is equivalent to the inverse translation followed by + the inverse rotation. + + Returns + ------- + `RigidTransform` instance + The inverse of this transform. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + A transform composed with its inverse results in an identity transform: + + >>> rng = np.random.default_rng(seed=123) + >>> t = rng.random(3) + >>> r = R.random(rng=rng) + >>> tf = Tf.from_components(t, r) + >>> tf.as_matrix() + array([[-0.45431291, 0.67276178, -0.58394466, 0.68235186], + [-0.23272031, 0.54310598, 0.80676958, 0.05382102], + [ 0.85990758, 0.50242162, -0.09017473, 0.22035987], + [ 0. , 0. , 0. , 1. ]]) + + >>> (tf.inv() * tf).as_matrix() + array([[[1., 0., 0., 0.], + [0., 1., 0., 0.], + [0., 0., 1., 0.], + [0., 0., 0., 1.]]]) + + The inverse rigid transform is the same as the inverse translation + followed by the inverse rotation: + + >>> t, r = tf.as_components() + >>> r_inv = r.inv() # inverse rotation + >>> t_inv = -t # inverse translation + >>> tf_r_inv = Tf.from_rotation(r_inv) + >>> tf_t_inv = Tf.from_translation(t_inv) + >>> np.allclose((tf_r_inv * tf_t_inv).as_matrix(), + ... tf.inv().as_matrix(), + ... atol=1e-12) + True + >>> (tf_r_inv * tf_t_inv * tf).as_matrix() + array([[[1., 0., 0., 0.], + [0., 1., 0., 0.], + [0., 0., 1., 0.], + [0., 0., 0., 1.]]]) + """ + matrix = self._backend.inv(self._matrix) + if self._single: + matrix = matrix[0, ...] + return RigidTransform._from_raw_matrix(matrix, self._xp, self._backend) + + @xp_capabilities( + skip_backends=[ + ("dask.array", "missing linalg.cross/det functions"), + ("cupy", "missing .mT attribute in cupy<14.*"), + ] + ) + def apply(self, vector: ArrayLike, inverse: bool = False) -> Array: + """Apply the transform to a vector. + + If the original frame transforms to the final frame by this transform, + then its application to a vector can be seen in two ways: + + - As a projection of vector components expressed in the final frame + to the original frame. + - As the physical transformation of a vector being glued to the + original frame as it transforms. In this case the vector + components are expressed in the original frame before and after + the transformation. + + In terms of rotation matrices and translation vectors, this application + is the same as + ``self.translation + self.rotation.as_matrix() @ vector``. + + Parameters + ---------- + vector : array_like, shape (..., 3) + Vector(s) to be transformed. Each vector[..., :] represents a 3D + vector. + inverse : bool, optional + If True, the inverse of the transform is applied to the vector. + + Returns + ------- + transformed_vector : numpy.ndarray, shape (..., 3) + The transformed vector(s) with shape determined by broadcasting + the transform and vector shapes together. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Apply a single transform to a vector. Here the transform is just a + translation, so the result is the vector added to the translation + vector. + + >>> t = np.array([1, 2, 3]) + >>> tf = Tf.from_translation(t) + >>> t + np.array([1, 0, 0]) + array([2, 2, 3]) + >>> tf.apply([1, 0, 0]) + array([2., 2., 3.]) + + Apply a single transform to a stack of vectors: + + >>> tf.apply([[1, 0, 0], [0, 1, 0]]) + array([[2., 2., 3.], + [1., 3., 3.]]) + + Apply the inverse of a transform to a vector, so the result is the + negative of the translation vector added to the vector. + + >>> -t + np.array([1, 0, 0]) + array([0, -2, -3]) + >>> tf.apply([1, 0, 0], inverse=True) + array([0., -2., -3.]) + + Broadcasting is supported when applying multiple transforms to an N-dimensional + array of vectors. + + >>> tf = Tf.from_translation(np.ones((4, 5, 1, 3))) + >>> vectors = np.zeros((2, 3)) + >>> tf.apply(vectors).shape + (4, 5, 2, 3) + + For transforms which are not just pure translations, applying it to a + vector is the same as applying the rotation component to the vector and + then adding the translation component. + + >>> r = R.from_euler('z', 60, degrees=True) + >>> tf = Tf.from_components(t, r) + >>> t + r.apply([1, 0, 0]) + array([1.5, 2.8660254, 3. ]) + >>> tf.apply([1, 0, 0]) + array([1.5, 2.8660254, 3. ]) + + When applying the inverse of a transform, the result is the negative of + the translation vector added to the vector, and then rotated by the + inverse rotation. + + >>> r.inv().apply(-t + np.array([1, 0, 0])) + array([-1.73205081, -1. , -3. ]) + >>> tf.apply([1, 0, 0], inverse=True) + array([-1.73205081, -1. , -3. ]) + """ + # We do not use the cached xp here to catch cases where matrix and vector have + # different xp instances. + xp = array_namespace(self._matrix, vector) + vector = xp.asarray( + vector, dtype=self._matrix.dtype, device=device(self._matrix) + ) + cython_compatible = self._matrix.ndim < 4 and vector.ndim < 3 + backend = select_backend(xp, cython_compatible=cython_compatible) + result = backend.apply(self._matrix, vector, inverse) + if self._single and vector.ndim == 1: + result = result[0, ...] + return result + + @property + def rotation(self) -> Rotation: + """Return the rotation component of the transform. + + A transform is a composition of a rotation and a translation, such that + when applied to a vector, the vector is first rotated and then + translated. This property returns the rotation part of the transform. + + Returns + ------- + rotation : `Rotation` instance + A single rotation or a stack of rotations. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + The rotation component is extracted from the transform: + + >>> t = np.array([1, 0, 0]) + >>> r = R.random(3) + >>> tf = Tf.from_components(t, r) + >>> np.allclose(tf.rotation.as_matrix(), r.as_matrix()) + True + """ + if self._single: + return Rotation.from_matrix(self._matrix[0, :3, :3]) + return Rotation.from_matrix(self._matrix[..., :3, :3]) + + @property + def translation(self) -> Array: + """Return the translation component of the transform. + + A transform is a composition of a rotation and a translation, such that + when applied to a vector, the vector is first rotated and then + translated. This property returns the translation part of the transform. + + Returns + ------- + translation : numpy.ndarray, shape (..., 3) + Translation vectors with the same leading dimensions as the transform. + + Examples + -------- + >>> from scipy.spatial.transform import RigidTransform as Tf + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + The translation component is extracted from the transform: + + >>> t = np.array([[1, 0, 0], [2, 0, 0], [3, 0, 0]]) + >>> r = R.random() + >>> tf = Tf.from_components(t, r) + >>> np.allclose(tf.translation, t) + True + """ + if self._single: + return self._xp.asarray(self._matrix[0, :3, 3], copy=True) + return self._xp.asarray(self._matrix[..., :3, 3], copy=True) + + @property + def single(self) -> bool: + """Whether this instance represents a single transform. + + Single transforms are not subscriptable, and do not have a length. + + Returns + ------- + single : bool + True if this instance represents a single transform, False + otherwise. + """ + return self._single or self._matrix.ndim == 2 + + @property + def shape(self) -> tuple[int, ...]: + """The shape of the transform's leading dimensions.""" + if self._single or self._matrix.ndim == 2: + return () + return self._matrix.shape[:-2] + + def __reduce__(self) -> tuple[Callable, tuple]: + """Reduce the RigidTransform for pickling. + + We store modules inside RigidTransforms which cannot be pickled. To circumvent + this, we pickle only the matrix and restore the cached modules from the matrix + type in `from_matrix`. + """ + matrix = self._matrix + if self._single: + matrix = matrix[0, ...] + return (self.__class__.from_matrix, (matrix,)) + + @xp_capabilities() + def __iter__(self) -> Iterator[RigidTransform]: + """Iterate over transforms.""" + if self._single or self._matrix.ndim == 2: + raise TypeError("Single transform is not iterable.") + # We return a generator that yields a new RigidTransform object for each + # transform in the current object. We cannot rely on the default implementation + # because jax will not raise an IndexError for out-of-bounds indices. + for i in range(self._matrix.shape[0]): + yield RigidTransform._from_raw_matrix( + self._matrix[i, ...], self._xp, self._backend + ) + + @staticmethod + def _from_raw_matrix( + matrix: Array, xp: ModuleType, backend: ModuleType | None = None + ) -> RigidTransform: + """Create a RigidTransform skipping all sanitization steps. + + This method is is intended for internal, performant creation of RigidTransforms + with matrices that are guaranteed to be valid. + """ + tf = RigidTransform.__new__(RigidTransform) + tf._single = matrix.ndim == 2 and is_numpy(xp) + if tf._single: + matrix = xpx.atleast_nd(matrix, ndim=3, xp=xp) + tf._matrix = matrix + tf._xp = xp + if backend is None: + backend = select_backend(xp, matrix.ndim < 4) + tf._backend = backend + return tf diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rigid_transform_xp.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rigid_transform_xp.py new file mode 100644 index 0000000000000000000000000000000000000000..8096a854cce1b43a049459b8b109f8b6e6c40f66 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rigid_transform_xp.py @@ -0,0 +1,448 @@ +from types import EllipsisType + +from scipy._lib._array_api import ( + array_namespace, + Array, + ArrayLike, + is_lazy_array, + xp_vector_norm, + xp_result_type, + xp_promote, + is_array_api_obj, +) +import scipy._lib.array_api_extra as xpx +from scipy.spatial.transform._rotation_xp import ( + as_matrix as quat_as_matrix, + from_matrix as quat_from_matrix, + _from_matrix_orthogonal as quat_from_matrix_orthogonal, + from_rotvec as quat_from_rotvec, + as_rotvec as quat_as_rotvec, + compose_quat, + from_quat, + inv as quat_inv, + mean as quat_mean, +) +from scipy._lib.array_api_compat import device as xp_device +from scipy._lib._util import broadcastable + + +def from_matrix(matrix: Array, normalize: bool = True, copy: bool = True) -> Array: + xp = array_namespace(matrix) + # Shape check should be done before calling this function + if normalize or copy: + matrix = xp.asarray(matrix, copy=True) + + last_row_ok = xp.all( + matrix[..., 3, :] == xp.asarray([0, 0, 0, 1.0], device=xp_device(matrix)), + axis=-1, + ) + lazy = is_lazy_array(matrix) + # We delay lazy branch checks until after normalization to avoid overwriting nans + # with the rotation matrix + if not lazy and xp.any(~last_row_ok): + if last_row_ok.shape == (): + idx = () + else: + idx = tuple(int(i[0]) for i in xp.nonzero(~last_row_ok)) + vals = matrix[idx + (3, ...)] + raise ValueError( + f"Expected last row of transformation matrix {idx} to be " + f"exactly [0, 0, 0, 1], got {vals}" + ) + + # The quat_from_matrix() method orthogonalizes the rotation + # component of the transformation matrix. While this does have some + # overhead in converting a rotation matrix to a quaternion and back, it + # allows for skipping singular value decomposition for near-orthogonal + # matrices, which is a computationally expensive operation. + if normalize: + rotmat = quat_as_matrix(quat_from_matrix(matrix[..., :3, :3])) + matrix = xpx.at(matrix)[..., :3, :3].set(rotmat) + # Lazy branch matrix invalidation + if lazy: + matrix = xp.where(last_row_ok[..., None, None], matrix, xp.nan) + return matrix + + +def from_rotation(quat: Array) -> Array: + xp = array_namespace(quat) + rotmat = quat_as_matrix(quat) + matrix = xp.zeros( + (*rotmat.shape[:-2], 4, 4), dtype=quat.dtype, device=xp_device(quat) + ) + matrix = xpx.at(matrix)[..., :3, :3].set(rotmat) + matrix = xpx.at(matrix)[..., 3, 3].set(1) + return matrix + + +def from_translation(translation: Array) -> Array: + xp = array_namespace(translation) + + if translation.shape[-1] != 3: + raise ValueError( + f"Expected `translation` to have shape (..., 3), got {translation.shape}." + ) + device = xp_device(translation) + dtype = xp_result_type(translation, force_floating=True, xp=xp) + eye = xp.eye(4, dtype=dtype, device=device) + + matrix = xpx.atleast_nd(eye, ndim=translation.ndim + 1, xp=xp) + matrix = xp.zeros( + (*translation.shape[:-1], 4, 4), + dtype=dtype, + device=device, + ) + matrix = xpx.at(matrix)[...].set(xp.eye(4, dtype=dtype, device=device)) + matrix = xpx.at(matrix)[..., :3, 3].set( + xp_promote(translation, force_floating=True, xp=xp) + ) + return matrix + + +def from_components(translation: Array, quat: Array) -> Array: + return compose_transforms(from_translation(translation), from_rotation(quat)) + + +def from_exp_coords(exp_coords: Array) -> Array: + rot_vec = exp_coords[..., :3] + rot_matrix = quat_as_matrix(quat_from_rotvec(rot_vec)) + translation_transform = _compute_se3_exp_translation_transform(rot_vec) + translations = (translation_transform @ exp_coords[..., 3:, None])[..., 0] + return _create_transformation_matrix(translations, rot_matrix) + + +def from_dual_quat(dual_quat: Array, *, scalar_first: bool = False) -> Array: + xp = array_namespace(dual_quat) + + if dual_quat.shape[-1] != 8: + raise ValueError( + f"Expected `dual_quat` to have shape (..., 8), got {dual_quat.shape}." + ) + + real_part = dual_quat[..., :4] + dual_part = dual_quat[..., 4:] + if scalar_first: + real_part = xp.roll(real_part, -1, axis=-1) + dual_part = xp.roll(dual_part, -1, axis=-1) + + real_part, dual_part = _normalize_dual_quaternion(real_part, dual_part) + + rot_quat = from_quat(real_part) + + translation = 2.0 * compose_quat(dual_part, quat_inv(rot_quat))[..., :3] + matrix = _create_transformation_matrix(translation, quat_as_matrix(rot_quat)) + + return matrix + + +def as_exp_coords(matrix: Array) -> Array: + xp = array_namespace(matrix) + rot_vec = quat_as_rotvec(quat_from_matrix_orthogonal(matrix[..., :3, :3])) + translation_transform = _compute_se3_log_translation_transform(rot_vec) + translations = (translation_transform @ matrix[..., :3, 3][..., None])[..., 0] + exp_coords = xp.concat([rot_vec, translations], axis=-1) + return exp_coords + + +def as_dual_quat(matrix: Array, *, scalar_first: bool = False) -> Array: + xp = array_namespace(matrix) + real_parts = quat_from_matrix_orthogonal(matrix[..., :3, :3]) + + pure_translation_quats = xp.empty( + (*matrix.shape[:-2], 4), dtype=matrix.dtype, device=xp_device(matrix) + ) + pure_translation_quats = xpx.at(pure_translation_quats)[..., :3].set( + matrix[..., :3, 3] + ) + pure_translation_quats = xpx.at(pure_translation_quats)[..., 3].set(0.0) + + dual_parts = 0.5 * compose_quat(pure_translation_quats, real_parts) + + if scalar_first: + real_parts = xp.roll(real_parts, 1, axis=-1) + dual_parts = xp.roll(dual_parts, 1, axis=-1) + + dual_quats = xp.concat([real_parts, dual_parts], axis=-1) + return dual_quats + + +def compose_transforms(tf_matrix: Array, other_tf_matrix: Array) -> Array: + if not broadcastable(tf_matrix.shape, other_tf_matrix.shape): + len_a = tf_matrix.shape[0] if tf_matrix.ndim == 3 else 1 + len_b = other_tf_matrix.shape[0] if other_tf_matrix.ndim == 3 else 1 + raise ValueError( + "Expected equal number of transforms in both or a " + "single transform in either object, got " + f"{len_a} transforms in first and {len_b}" + "transforms in second object." + ) + return tf_matrix @ other_tf_matrix + + +def inv(matrix: Array) -> Array: + xp = array_namespace(matrix) + r_inv = xp.matrix_transpose(matrix[..., :3, :3]) + # Matrix multiplication of r_inv and translation vector + t_inv = -(r_inv @ matrix[..., :3, 3][..., None])[..., 0] + matrix = xp.zeros( + (*matrix.shape[:-2], 4, 4), dtype=matrix.dtype, device=xp_device(matrix) + ) + matrix = xpx.at(matrix)[..., :3, :3].set(r_inv) + matrix = xpx.at(matrix)[..., :3, 3].set(t_inv) + matrix = xpx.at(matrix)[..., 3, 3].set(1) + return matrix + + +def apply(matrix: Array, vector: Array, inverse: bool = False) -> Array: + xp = array_namespace(matrix) + if vector.shape[-1] != 3: + raise ValueError(f"Expected vector to have shape (..., 3), got {vector.shape}.") + vec = xp.empty( + (*vector.shape[:-1], 4), dtype=vector.dtype, device=xp_device(vector) + ) + vec = xpx.at(vec)[..., :3].set(vector) + vec = xpx.at(vec)[..., 3].set(1) + vec = vec[..., None] + + if inverse: + matrix = inv(matrix) + + # We raise a ValueError manually here because letting the function run its course + # would raise heterogeneous error types and messages for different frameworks. + # However, the error only mimics numpy's error message and does not provide the + # same amount of context. + if not broadcastable(matrix.shape, vec.shape): + raise ValueError("operands could not be broadcast together") + return (matrix @ vec)[..., :3, 0] + + +def pow(matrix: Array, n: float | Array) -> Array: + xp = array_namespace(matrix) + device = xp_device(matrix) + # If n is an array, we sanitize it to a scalar and promote quat and n to + # the same dtype. + if is_array_api_obj(n): + if n.shape == (1,): + n = n[0] + elif n.ndim != 0: + raise ValueError("Array exponent must be a scalar") + matrix, n = xp_promote(matrix, n, force_floating=True, xp=xp) + + # If n is a lazy array, we cannot take fast paths for special cases. + if is_lazy_array(n): + # Lazy execution. We compute all special cases and the general case + result = from_exp_coords(as_exp_coords(matrix) * n) + identity = xp.eye(4, dtype=matrix.dtype, device=device) + result = xp.where(n == 0, identity, result) + result = xp.where(n == -1, inv(matrix), result) + result = xp.where(n == 1, matrix, result) + return result + if n == 0: + identity = xp.eye(4, dtype=matrix.dtype, device=device) + identity = xpx.atleast_nd(identity, ndim=matrix.ndim, xp=xp) + return xp.tile(identity, (*matrix.shape[:-2], 1, 1)) + elif n == -1: + return inv(matrix) + elif n == 1: + return matrix + return from_exp_coords(as_exp_coords(matrix) * n) + + +def mean( + matrix: Array, + weights: ArrayLike | None = None, + axis: None | int | tuple[int, ...] = None +) -> Array: + xp = array_namespace(matrix) + if matrix.shape[0] == 0: + raise ValueError("Mean of an empty rotation set is undefined.") + # Axis logic: For None, we reduce over all axes. For int, we only reduce over that + # axis. For tuple, we reduce over all specified axes. + all_axes = tuple(range(matrix.ndim - 2)) + if axis is None: + axis = all_axes + elif isinstance(axis, int): + axis = (axis,) + if not isinstance(axis, tuple): + raise ValueError("`axis` must be None, int, or tuple of ints.") + # Ensure all axes are within bounds + if (axis != () and + (min(axis) < -(matrix.ndim - 2) or max(axis) > (matrix.ndim - 3)) + ): + raise ValueError( + f"axis {axis} is out of bounds for transform with shape " + f"{matrix.shape[:-2]}." + ) + # Ensure all axes are positive and unique + axis = tuple(sorted(set(x % (matrix.ndim - 2) for x in axis))) + + lazy = is_lazy_array(matrix) + quats = quat_from_matrix_orthogonal(matrix[..., :3, :3]) + if weights is None: + quats_mean = quat_mean(quats, axis=axis) + else: + neg_weights = weights < 0 + any_neg_weights = xp.any(neg_weights) + if not lazy and any_neg_weights: + raise ValueError("`weights` must be non-negative.") + if weights.shape != matrix.shape[:-2]: + raise ValueError( + f"Expected `weights` to match transform shape, got shape " + f"{weights.shape} for {matrix.shape[:-2]} transformations." + ) + quats_mean = quat_mean(quats, weights=weights, axis=axis) + r_mean = quat_as_matrix(quats_mean) + + t = matrix[..., :3, 3] + if weights is None: + t_mean = xp.mean(t, axis=axis) + else: + norm = xp.sum(weights[..., None], axis=axis) + wsum = xp.sum(t * weights[..., None], axis=axis) + t_mean = wsum / norm + + tf = _create_transformation_matrix(t_mean, r_mean) + if weights is not None and lazy: + # We cannot raise on negative weights because jit code needs to be + # non-branching. We return NaN instead + mask = xp.where(any_neg_weights, xp.nan, 1.0) + tf = mask * tf + return tf + + +def setitem( + matrix: Array, + indexer: Array | int | tuple | slice | EllipsisType | None, + value: Array, +) -> Array: + xp = array_namespace(matrix) + if isinstance(indexer, EllipsisType): + return xpx.at(matrix)[indexer].set(value) + if is_array_api_obj(indexer) and indexer.dtype == xp.bool: + return xpx.at(matrix)[indexer].set(value) + return xpx.at(matrix)[indexer, ...].set(value) + + +def normalize_dual_quaternion(dual_quat: Array) -> Array: + """Normalize dual quaternion.""" + xp = array_namespace(dual_quat) + real, dual = _normalize_dual_quaternion(dual_quat[..., :4], dual_quat[..., 4:]) + return xp.concat((real, dual), axis=-1) + + +def _create_transformation_matrix( + translations: Array, rotation_matrices: Array +) -> Array: + if not translations.shape[:-1] == rotation_matrices.shape[:-2]: + raise ValueError( + "The number of rotation matrices and translations must be the same." + ) + xp = array_namespace(translations) + matrix = xp.empty( + (*translations.shape[:-1], 4, 4), + dtype=translations.dtype, + device=xp_device(translations), + ) + matrix = xpx.at(matrix)[..., :3, :3].set(rotation_matrices) + matrix = xpx.at(matrix)[..., :3, 3].set(translations) + matrix = xpx.at(matrix)[..., 3, :3].set(0) + matrix = xpx.at(matrix)[..., 3, 3].set(1) + return matrix + + +def _compute_se3_exp_translation_transform(rot_vec: Array) -> Array: + """Compute the transformation matrix from the se3 translation part to SE3 + translation. + + The transformation matrix depends on the rotation vector. + """ + xp = array_namespace(rot_vec) + device = xp_device(rot_vec) + dtype = rot_vec.dtype + angle = xp_vector_norm(rot_vec, axis=-1, keepdims=True, xp=xp) + small_scale = angle < 1e-3 + + k1_small = 0.5 - angle**2 / 24 + angle**4 / 720 + # Avoid division by zero for non-branching computations. The value will get + # discarded in the xp.where selection. + safe_angle = angle + xp.asarray(small_scale, dtype=dtype, device=device) + k1 = (1.0 - xp.cos(angle)) / safe_angle**2 + k1 = xp.where(small_scale, k1_small, k1) + + k2_small = 1 / 6 - angle**2 / 120 + angle**4 / 5040 + # Again, avoid division by zero by adding one to all near-zero angles. + safe_angle = angle + xp.asarray(small_scale, dtype=dtype, device=device) + k2 = (angle - xp.sin(angle)) / safe_angle**3 + k2 = xp.where(small_scale, k2_small, k2) + + s = _create_skew_matrix(rot_vec) + eye = xp.eye(3, dtype=dtype, device=device) + + return eye + k1[..., None] * s + k2[..., None] * s @ s + + +def _compute_se3_log_translation_transform(rot_vec: Array) -> Array: + """Compute the transformation matrix from SE3 translation to the se3 + translation part. + + It is the inverse of `_compute_se3_exp_translation_transform` in a closed + analytical form. + """ + xp = array_namespace(rot_vec) + dtype = rot_vec.dtype + device = xp_device(rot_vec) + angle = xp_vector_norm(rot_vec, axis=-1, keepdims=True, xp=xp) + mask = angle < 1e-3 + + k_small = 1 / 12 + angle**2 / 720 + angle**4 / 30240 + safe_angle = angle + xp.asarray(mask, dtype=dtype, device=device) + k = (1 - 0.5 * angle / xp.tan(0.5 * safe_angle)) / safe_angle**2 + k = xp.where(mask, k_small, k) + + s = _create_skew_matrix(rot_vec) + + return xp.eye(3, dtype=dtype, device=device) - 0.5 * s + k[..., None] * s @ s + + +def _create_skew_matrix(vec: Array) -> Array: + """Create skew-symmetric (aka cross-product) matrix for stack of vectors.""" + xp = array_namespace(vec) + result = xp.zeros((*vec.shape[:-1], 3, 3), dtype=vec.dtype, device=xp_device(vec)) + result = xpx.at(result)[..., 0, 1].set(-vec[..., 2]) + result = xpx.at(result)[..., 0, 2].set(vec[..., 1]) + result = xpx.at(result)[..., 1, 0].set(vec[..., 2]) + result = xpx.at(result)[..., 1, 2].set(-vec[..., 0]) + result = xpx.at(result)[..., 2, 0].set(-vec[..., 1]) + result = xpx.at(result)[..., 2, 1].set(vec[..., 0]) + return result + + +def _normalize_dual_quaternion( + real_part: Array, dual_part: Array +) -> tuple[Array, Array]: + """Ensure that the dual quaternion has unit norm. + + The norm is a dual number and must be 1 + 0 * epsilon, which means that + the real quaternion must have unit norm and the dual quaternion must be + orthogonal to the real quaternion. + """ + xp = array_namespace(real_part) + + real_norm = xp_vector_norm(real_part, axis=-1, keepdims=True, xp=xp) + + # special case: real quaternion is 0, we set it to identity + zero_real_mask = real_norm == 0.0 + unit_quat = xp.asarray( + [0.0, 0.0, 0.0, 1.0], dtype=real_part.dtype, device=xp_device(real_part) + ) + real_part = xp.where(zero_real_mask, unit_quat, real_part) + real_norm = xp.where(zero_real_mask, 1.0, real_norm) + + # 1. ensure unit real quaternion + real_part = real_part / real_norm + dual_part = dual_part / real_norm + + # 2. ensure orthogonality of real and dual quaternion + dual_part -= xp.sum(real_part * dual_part, axis=-1, keepdims=True) * real_part + + return real_part, dual_part diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rotation.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rotation.py new file mode 100644 index 0000000000000000000000000000000000000000..c57c081cff89cc3704e75d3cb66b90bfa1611c18 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rotation.py @@ -0,0 +1,2865 @@ +from __future__ import annotations + +from collections.abc import Iterable, Iterator +from types import EllipsisType, ModuleType, NotImplementedType + +import numpy as np + +import scipy.spatial.transform._rotation_cy as cython_backend +import scipy.spatial.transform._rotation_xp as xp_backend +from scipy.spatial.transform._rotation_groups import create_group +from scipy._lib._array_api import ( + array_namespace, + Array, + is_numpy, + ArrayLike, + is_lazy_array, + xp_capabilities, + xp_promote, +) +from scipy._lib.array_api_compat import device as xp_device +import scipy._lib.array_api_extra as xpx +from scipy._lib._util import _transition_to_rng, broadcastable + +backend_registry = {array_namespace(np.empty(0)): cython_backend} + + +def select_backend(xp: ModuleType, cython_compatible: bool): + """Select the backend for the given array library. + + We need this selection function because the Cython backend for numpy does not + support quaternions of arbitrary dimensions. We therefore only use the Array API + backend for numpy if we are dealing with rotations of more than one leading + dimension. + """ + if is_numpy(xp) and not cython_compatible: + return xp_backend + return backend_registry.get(xp, xp_backend) + + +@xp_capabilities() +def _promote(*args: tuple[ArrayLike, ...], xp: ModuleType) -> Array: + """Promote arrays to float64 for numpy, else according to the Array API spec. + + The return array dtype follows the following rules: + - If quat is an ArrayLike or NumPy array, we always promote to float64 + - If quat is an Array from frameworks other than NumPy, we preserve the precision + of the input array dtype. + + The first rule is required by the cython backend signatures that expect + cython.double views. The second rule is necessary to promote non-floating arrays + to the correct type in frameworks that may not support double precision (e.g. + jax by default). + """ + if is_numpy(xp): + args += (np.empty(0, dtype=np.float64),) # Force float64 conversion + out = xp_promote(*args, force_floating=True, xp=xp) + if len(args) == 2: # One argument was passed + the added empty array + return out[0] + return out[:-1] + return xp_promote(*args, force_floating=True, xp=xp) + + +class Rotation: + """Rotation in 3 dimensions. + + This class provides an interface to initialize from and represent rotations + with: + + - Quaternions + - Rotation Matrices + - Rotation Vectors + - Modified Rodrigues Parameters + - Euler Angles + - Davenport Angles (Generalized Euler Angles) + + The following operations on rotations are supported: + + - Application on vectors + - Rotation Composition + - Rotation Inversion + - Rotation Indexing + + A `Rotation` instance can contain a single rotation transform or rotations of + multiple leading dimensions. E.g., it is possible to have an N-dimensional array of + (N, M, K) rotations. When applied to other rotations or vectors, standard + broadcasting rules apply. + + Indexing within a rotation is supported to access a subset of the rotations stored + in a `Rotation` instance. + + To create `Rotation` objects use ``from_...`` methods (see examples below). + ``Rotation(...)`` is not supposed to be instantiated directly. + + Attributes + ---------- + single + + Methods + ------- + __len__ + from_quat + from_matrix + from_rotvec + from_mrp + from_euler + from_davenport + as_quat + as_matrix + as_rotvec + as_mrp + as_euler + as_davenport + concatenate + apply + __mul__ + __pow__ + inv + magnitude + approx_equal + mean + reduce + create_group + __getitem__ + identity + random + align_vectors + + See Also + -------- + Slerp + + Notes + ----- + .. versionadded:: 1.2.0 + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + A `Rotation` instance can be initialized in any of the above formats and + converted to any of the others. The underlying object is independent of the + representation used for initialization. + + Consider a counter-clockwise rotation of 90 degrees about the z-axis. This + corresponds to the following quaternion (in scalar-last format): + + >>> r = R.from_quat([0, 0, np.sin(np.pi/4), np.cos(np.pi/4)]) + + The rotation can be expressed in any of the other formats: + + >>> r.as_matrix() + array([[ 2.22044605e-16, -1.00000000e+00, 0.00000000e+00], + [ 1.00000000e+00, 2.22044605e-16, 0.00000000e+00], + [ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]) + >>> r.as_rotvec() + array([0. , 0. , 1.57079633]) + >>> r.as_euler('zyx', degrees=True) + array([90., 0., 0.]) + + The same rotation can be initialized using a rotation matrix: + + >>> r = R.from_matrix([[0, -1, 0], + ... [1, 0, 0], + ... [0, 0, 1]]) + + Representation in other formats: + + >>> r.as_quat() + array([0. , 0. , 0.70710678, 0.70710678]) + >>> r.as_rotvec() + array([0. , 0. , 1.57079633]) + >>> r.as_euler('zyx', degrees=True) + array([90., 0., 0.]) + + The rotation vector corresponding to this rotation is given by: + + >>> r = R.from_rotvec(np.pi/2 * np.array([0, 0, 1])) + + Representation in other formats: + + >>> r.as_quat() + array([0. , 0. , 0.70710678, 0.70710678]) + >>> r.as_matrix() + array([[ 2.22044605e-16, -1.00000000e+00, 0.00000000e+00], + [ 1.00000000e+00, 2.22044605e-16, 0.00000000e+00], + [ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]) + >>> r.as_euler('zyx', degrees=True) + array([90., 0., 0.]) + + The ``from_euler`` method is quite flexible in the range of input formats + it supports. Here we initialize a single rotation about a single axis: + + >>> r = R.from_euler('z', 90, degrees=True) + + Again, the object is representation independent and can be converted to any + other format: + + >>> r.as_quat() + array([0. , 0. , 0.70710678, 0.70710678]) + >>> r.as_matrix() + array([[ 2.22044605e-16, -1.00000000e+00, 0.00000000e+00], + [ 1.00000000e+00, 2.22044605e-16, 0.00000000e+00], + [ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]) + >>> r.as_rotvec() + array([0. , 0. , 1.57079633]) + + It is also possible to initialize multiple rotations in a single instance + using any of the ``from_...`` functions. Here we initialize a stack of 3 + rotations using the ``from_euler`` method: + + >>> r = R.from_euler('zyx', [ + ... [90, 0, 0], + ... [0, 45, 0], + ... [45, 60, 30]], degrees=True) + + The other representations also now return a stack of 3 rotations. For + example: + + >>> r.as_quat() + array([[0. , 0. , 0.70710678, 0.70710678], + [0. , 0.38268343, 0. , 0.92387953], + [0.39190384, 0.36042341, 0.43967974, 0.72331741]]) + + Applying the above rotations onto a vector: + + >>> v = [1, 2, 3] + >>> r.apply(v) + array([[-2. , 1. , 3. ], + [ 2.82842712, 2. , 1.41421356], + [ 2.24452282, 0.78093109, 2.89002836]]) + + A `Rotation` instance can be indexed and sliced as if it were an ND array: + + >>> r.as_quat() + array([[0. , 0. , 0.70710678, 0.70710678], + [0. , 0.38268343, 0. , 0.92387953], + [0.39190384, 0.36042341, 0.43967974, 0.72331741]]) + >>> p = r[0] + >>> p.as_matrix() + array([[ 2.22044605e-16, -1.00000000e+00, 0.00000000e+00], + [ 1.00000000e+00, 2.22044605e-16, 0.00000000e+00], + [ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]) + >>> q = r[1:3] + >>> q.as_quat() + array([[0. , 0.38268343, 0. , 0.92387953], + [0.39190384, 0.36042341, 0.43967974, 0.72331741]]) + + In fact it can be converted to numpy.array: + + >>> r_array = np.asarray(r) + >>> r_array.shape + (3,) + >>> r_array[0].as_matrix() + array([[ 2.22044605e-16, -1.00000000e+00, 0.00000000e+00], + [ 1.00000000e+00, 2.22044605e-16, 0.00000000e+00], + [ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]) + + Multiple rotations can be composed using the ``*`` operator: + + >>> r1 = R.from_euler('z', 90, degrees=True) + >>> r2 = R.from_rotvec([np.pi/4, 0, 0]) + >>> v = [1, 2, 3] + >>> r2.apply(r1.apply(v)) + array([-2. , -1.41421356, 2.82842712]) + >>> r3 = r2 * r1 # Note the order + >>> r3.apply(v) + array([-2. , -1.41421356, 2.82842712]) + + A rotation can be composed with itself using the ``**`` operator: + + >>> p = R.from_rotvec([1, 0, 0]) + >>> q = p ** 2 + >>> q.as_rotvec() + array([2., 0., 0.]) + + Finally, it is also possible to invert rotations: + + >>> r1 = R.from_euler('z', [[90], [45]], degrees=True) + >>> r2 = r1.inv() + >>> r2.as_euler('zyx', degrees=True) + array([[-90., 0., 0.], + [-45., 0., 0.]]) + + The following function can be used to plot rotations with Matplotlib by + showing how they transform the standard x, y, z coordinate axes: + + >>> import matplotlib.pyplot as plt + + >>> def plot_rotated_axes(ax, r, name=None, offset=(0, 0, 0), scale=1): + ... colors = ("#FF6666", "#005533", "#1199EE") # Colorblind-safe RGB + ... loc = np.array([offset, offset]) + ... for i, (axis, c) in enumerate(zip((ax.xaxis, ax.yaxis, ax.zaxis), + ... colors)): + ... axlabel = axis.axis_name + ... axis.set_label_text(axlabel) + ... axis.label.set_color(c) + ... axis.line.set_color(c) + ... axis.set_tick_params(colors=c) + ... line = np.zeros((2, 3)) + ... line[1, i] = scale + ... line_rot = r.apply(line) + ... line_plot = line_rot + loc + ... ax.plot(line_plot[:, 0], line_plot[:, 1], line_plot[:, 2], c) + ... text_loc = line[1]*1.2 + ... text_loc_rot = r.apply(text_loc) + ... text_plot = text_loc_rot + loc[0] + ... ax.text(*text_plot, axlabel.upper(), color=c, + ... va="center", ha="center") + ... ax.text(*offset, name, color="k", va="center", ha="center", + ... bbox={"fc": "w", "alpha": 0.8, "boxstyle": "circle"}) + + Create three rotations - the identity and two Euler rotations using + intrinsic and extrinsic conventions: + + >>> r0 = R.identity() + >>> r1 = R.from_euler("ZYX", [90, -30, 0], degrees=True) # intrinsic + >>> r2 = R.from_euler("zyx", [90, -30, 0], degrees=True) # extrinsic + + Add all three rotations to a single plot: + + >>> ax = plt.figure().add_subplot(projection="3d", proj_type="ortho") + >>> plot_rotated_axes(ax, r0, name="r0", offset=(0, 0, 0)) + >>> plot_rotated_axes(ax, r1, name="r1", offset=(3, 0, 0)) + >>> plot_rotated_axes(ax, r2, name="r2", offset=(6, 0, 0)) + >>> _ = ax.annotate( + ... "r0: Identity Rotation\\n" + ... "r1: Intrinsic Euler Rotation (ZYX)\\n" + ... "r2: Extrinsic Euler Rotation (zyx)", + ... xy=(0.6, 0.7), xycoords="axes fraction", ha="left" + ... ) + >>> ax.set(xlim=(-1.25, 7.25), ylim=(-1.25, 1.25), zlim=(-1.25, 1.25)) + >>> ax.set(xticks=range(-1, 8), yticks=[-1, 0, 1], zticks=[-1, 0, 1]) + >>> ax.set_aspect("equal", adjustable="box") + >>> ax.figure.set_size_inches(6, 5) + >>> plt.tight_layout() + + Show the plot: + + >>> plt.show() + + These examples serve as an overview into the `Rotation` class and highlight + major functionalities. For more thorough examples of the range of input and + output formats supported, consult the individual method's examples. + + """ + + def __init__( + self, + quat: ArrayLike, + normalize: bool = True, + copy: bool = True, + scalar_first: bool = False, + ): + xp = array_namespace(quat) + self._xp = xp + quat = _promote(quat, xp=xp) + if quat.shape[-1] != 4: + raise ValueError( + f"Expected `quat` to have shape (..., 4), got {quat.shape}." + ) + # Single NumPy quats or list of quats are accelerated by the cython backend. + # This backend needs inputs with fixed ndim, so we always expand to 2D and + # select the 0th element if quat was single to get the correct shape. For other + # frameworks and quaternion tensors we use the generic array API backend. + self._single = quat.ndim == 1 and is_numpy(xp) + if self._single: + quat = xpx.atleast_nd(quat, ndim=2, xp=xp) + self._backend = select_backend(xp, cython_compatible=quat.ndim < 3) + self._quat: Array = self._backend.from_quat( + quat, normalize=normalize, copy=copy, scalar_first=scalar_first + ) + + @staticmethod + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def from_quat(quat: ArrayLike, *, scalar_first: bool = False) -> Rotation: + """Initialize from quaternions. + + Rotations in 3 dimensions can be represented using unit norm + quaternions [1]_. + + The 4 components of a quaternion are divided into a scalar part ``w`` + and a vector part ``(x, y, z)`` and can be expressed from the angle + ``theta`` and the axis ``n`` of a rotation as follows:: + + w = cos(theta / 2) + x = sin(theta / 2) * n_x + y = sin(theta / 2) * n_y + z = sin(theta / 2) * n_z + + There are 2 conventions to order the components in a quaternion: + + - scalar-first order -- ``(w, x, y, z)`` + - scalar-last order -- ``(x, y, z, w)`` + + The choice is controlled by `scalar_first` argument. + By default, it is False and the scalar-last order is assumed. + + Advanced users may be interested in the "double cover" of 3D space by + the quaternion representation [2]_. As of version 1.11.0, the + following subset (and only this subset) of operations on a `Rotation` + ``r`` corresponding to a quaternion ``q`` are guaranteed to preserve + the double cover property: ``r = Rotation.from_quat(q)``, + ``r.as_quat(canonical=False)``, ``r.inv()``, and composition using the + ``*`` operator such as ``r*r``. + + Parameters + ---------- + quat : array_like, shape (..., 4) + Each row is a (possibly non-unit norm) quaternion representing an + active rotation. Each quaternion will be normalized to unit norm. + scalar_first : bool, optional + Whether the scalar component goes first or last. + Default is False, i.e. the scalar-last order is assumed. + + Returns + ------- + rotation : `Rotation` instance + Object containing the rotations represented by input quaternions. + + References + ---------- + .. [1] https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation + .. [2] Hanson, Andrew J. "Visualizing quaternions." + Morgan Kaufmann Publishers Inc., San Francisco, CA. 2006. + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + + A rotation can be initialized from a quaternion with the scalar-last + (default) or scalar-first component order as shown below: + + >>> r = R.from_quat([0, 0, 0, 1]) + >>> r.as_matrix() + array([[1., 0., 0.], + [0., 1., 0.], + [0., 0., 1.]]) + >>> r = R.from_quat([1, 0, 0, 0], scalar_first=True) + >>> r.as_matrix() + array([[1., 0., 0.], + [0., 1., 0.], + [0., 0., 1.]]) + + It is possible to initialize multiple rotations in a single object by + passing an N-dimensional array: + + >>> r = R.from_quat([[ + ... [1, 0, 0, 0], + ... [0, 0, 0, 1] + ... ]]) + >>> r.as_quat() + array([[[1., 0., 0., 0.], + [0., 0., 0., 1.]]]) + >>> r.as_quat().shape + (1, 2, 4) + + It is also possible to have a stack of a single rotation: + + >>> r = R.from_quat([[0, 0, 0, 1]]) + >>> r.as_quat() + array([[0., 0., 0., 1.]]) + >>> r.as_quat().shape + (1, 4) + + Quaternions are normalized before initialization. + + >>> r = R.from_quat([0, 0, 1, 1]) + >>> r.as_quat() + array([0. , 0. , 0.70710678, 0.70710678]) + """ + return Rotation(quat, normalize=True, scalar_first=scalar_first) + + @staticmethod + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def from_matrix(matrix: ArrayLike, *, assume_valid: bool = False) -> Rotation: + """Initialize from rotation matrix. + + Rotations in 3 dimensions can be represented with 3 x 3 orthogonal + matrices [1]_. If the input is not orthogonal, an approximation is + created by orthogonalizing the input matrix using the method described + in [2]_, and then converting the orthogonal rotation matrices to + quaternions using the algorithm described in [3]_. Matrices must be + right-handed. + + Parameters + ---------- + matrix : array_like, shape (..., 3, 3) + A single matrix or an ND array of matrices, where the last two dimensions + contain the rotation matrices. + assume_valid : bool, optional + Must be False unless users can guarantee the input is a valid rotation + matrix, i.e. it is orthogonal, rows and columns have unit norm and the + determinant is 1. Setting this to True without ensuring these properties + is unsafe and will silently lead to incorrect results. If True, + normalization steps are skipped, which can improve runtime performance. + Default is False. + + Returns + ------- + rotation : `Rotation` instance + Object containing the rotations represented by the rotation + matrices. + + References + ---------- + .. [1] https://en.wikipedia.org/wiki/Rotation_matrix#In_three_dimensions + .. [2] https://en.wikipedia.org/wiki/Orthogonal_Procrustes_problem + .. [3] F. Landis Markley, "Unit Quaternion from Rotation Matrix", + Journal of guidance, control, and dynamics vol. 31.2, pp. + 440-442, 2008. + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Initialize a single rotation: + + >>> r = R.from_matrix([ + ... [0, -1, 0], + ... [1, 0, 0], + ... [0, 0, 1]]) + >>> r.single + True + >>> r.as_matrix().shape + (3, 3) + + Initialize multiple rotations in a single object: + + >>> r = R.from_matrix([ + ... [ + ... [0, -1, 0], + ... [1, 0, 0], + ... [0, 0, 1], + ... ], + ... [ + ... [1, 0, 0], + ... [0, 0, -1], + ... [0, 1, 0], + ... ]]) + >>> r.as_matrix().shape + (2, 3, 3) + >>> r.single + False + >>> len(r) + 2 + + If input matrices are not special orthogonal (orthogonal with + determinant equal to +1), then a special orthogonal estimate is stored: + + >>> a = np.array([ + ... [0, -0.5, 0], + ... [0.5, 0, 0], + ... [0, 0, 0.5]]) + >>> np.linalg.det(a) + 0.125 + >>> r = R.from_matrix(a) + >>> matrix = r.as_matrix() + >>> matrix + array([[ 0., -1., 0.], + [ 1., 0., 0.], + [ 0., 0., 1.]]) + >>> np.linalg.det(matrix) + 1.0 + + It is also possible to have a stack containing a single rotation: + + >>> r = R.from_matrix([[ + ... [0, -1, 0], + ... [1, 0, 0], + ... [0, 0, 1]]]) + >>> r.as_matrix() + array([[[ 0., -1., 0.], + [ 1., 0., 0.], + [ 0., 0., 1.]]]) + >>> r.as_matrix().shape + (1, 3, 3) + + We can also create an N-dimensional array of rotations: + + >>> r = R.from_matrix(np.tile(np.eye(3), (2, 3, 1, 1))) + >>> r.shape + (2, 3) + + Notes + ----- + This function was called from_dcm before. + + .. versionadded:: 1.4.0 + """ + xp = array_namespace(matrix) + matrix = _promote(matrix, xp=xp) + # Resulting quat will have 1 less dimension than matrix + backend = select_backend(xp, cython_compatible=matrix.ndim < 4) + quat = backend.from_matrix(matrix, assume_valid=assume_valid) + return Rotation._from_raw_quat(quat, xp=xp, backend=backend) + + @staticmethod + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def from_rotvec(rotvec: ArrayLike, degrees: bool = False) -> Rotation: + """Initialize from rotation vectors. + + A rotation vector is a 3 dimensional vector which is co-directional to + the axis of rotation and whose norm gives the angle of rotation [1]_. + + Parameters + ---------- + rotvec : array_like, shape (..., 3) + A single vector or an ND array of vectors, where the last dimension + contains the rotation vectors. + degrees : bool, optional + If True, then the given magnitudes are assumed to be in degrees. + Default is False. + + .. versionadded:: 1.7.0 + + Returns + ------- + rotation : `Rotation` instance + Object containing the rotations represented by input rotation + vectors. + + References + ---------- + .. [1] https://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation#Rotation_vector + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Initialize a single rotation: + + >>> r = R.from_rotvec(np.pi/2 * np.array([0, 0, 1])) + >>> r.as_rotvec() + array([0. , 0. , 1.57079633]) + >>> r.as_rotvec().shape + (3,) + + Initialize a rotation in degrees, and view it in degrees: + + >>> r = R.from_rotvec(45 * np.array([0, 1, 0]), degrees=True) + >>> r.as_rotvec(degrees=True) + array([ 0., 45., 0.]) + + Initialize multiple rotations in one object: + + >>> r = R.from_rotvec([ + ... [0, 0, np.pi/2], + ... [np.pi/2, 0, 0]]) + >>> r.as_rotvec() + array([[0. , 0. , 1.57079633], + [1.57079633, 0. , 0. ]]) + >>> r.as_rotvec().shape + (2, 3) + + It is also possible to have a stack of a single rotation: + + >>> r = R.from_rotvec([[0, 0, np.pi/2]]) + >>> r.as_rotvec().shape + (1, 3) + + """ + xp = array_namespace(rotvec) + rotvec = _promote(rotvec, xp=xp) + backend = select_backend(xp, cython_compatible=rotvec.ndim < 3) + quat = backend.from_rotvec(rotvec, degrees=degrees) + return Rotation._from_raw_quat(quat, xp=xp, backend=backend) + + @staticmethod + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def from_euler(seq: str, angles: ArrayLike, degrees: bool = False) -> Rotation: + """Initialize from Euler angles. + + Rotations in 3-D can be represented by a sequence of 3 + rotations around a sequence of axes. In theory, any three axes spanning + the 3-D Euclidean space are enough. In practice, the axes of rotation are + chosen to be the basis vectors. + + The three rotations can either be in a global frame of reference + (extrinsic) or in a body centred frame of reference (intrinsic), which + is attached to, and moves with, the object under rotation [1]_. + + Parameters + ---------- + seq : string + Specifies sequence of axes for rotations. Up to 3 characters + belonging to the set {'X', 'Y', 'Z'} for intrinsic rotations, or + {'x', 'y', 'z'} for extrinsic rotations. Extrinsic and intrinsic + rotations cannot be mixed in one function call. + angles : float or array_like, shape (..., [1 or 2 or 3]) + Euler angles specified in radians (`degrees` is False) or degrees + (`degrees` is True). + Each character in `seq` defines one axis around which `angles` turns. + The resulting rotation has the shape np.atleast_1d(angles).shape[:-1]. + Dimensionless angles are thus only valid for single character `seq`. + + degrees : bool, optional + If True, then the given angles are assumed to be in degrees. + Default is False. + + Returns + ------- + rotation : `Rotation` instance + Object containing the rotation represented by the sequence of + rotations around given axes with given angles. + + References + ---------- + .. [1] https://en.wikipedia.org/wiki/Euler_angles#Definition_by_intrinsic_rotations + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + + Initialize a single rotation along a single axis: + + >>> r = R.from_euler('x', 90, degrees=True) + >>> r.as_quat().shape + (4,) + + Initialize a single rotation with a given axis sequence: + + >>> r = R.from_euler('zyx', [90, 45, 30], degrees=True) + >>> r.as_quat().shape + (4,) + + Initialize a stack with a single rotation around a single axis: + + >>> r = R.from_euler('x', [[90]], degrees=True) + >>> r.as_quat().shape + (1, 4) + + Initialize a stack with a single rotation with an axis sequence: + + >>> r = R.from_euler('zyx', [[90, 45, 30]], degrees=True) + >>> r.as_quat().shape + (1, 4) + + Initialize multiple elementary rotations in one object: + + >>> r = R.from_euler('x', [[90], [45], [30]], degrees=True) + >>> r.as_quat().shape + (3, 4) + + Initialize multiple rotations in one object: + + >>> r = R.from_euler('zyx', [[90, 45, 30], [35, 45, 90]], degrees=True) + >>> r.as_quat().shape + (2, 4) + + """ + xp = array_namespace(angles) + angles = _promote(angles, xp=xp) + backend = select_backend(xp, cython_compatible=angles.ndim < 3) + quat = backend.from_euler(seq, angles, degrees=degrees) + return Rotation._from_raw_quat(quat, xp=xp, backend=backend) + + @staticmethod + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def from_davenport( + axes: ArrayLike, + order: str, + angles: ArrayLike | float, + degrees: bool = False, + ) -> Rotation: + """Initialize from Davenport angles. + + Rotations in 3-D can be represented by a sequence of 3 + rotations around a sequence of axes. + + The three rotations can either be in a global frame of reference + (extrinsic) or in a body centred frame of reference (intrinsic), which + is attached to, and moves with, the object under rotation [1]_. + + For both Euler angles and Davenport angles, consecutive axes must + be are orthogonal (``axis2`` is orthogonal to both ``axis1`` and + ``axis3``). For Euler angles, there is an additional relationship + between ``axis1`` or ``axis3``, with two possibilities: + + - ``axis1`` and ``axis3`` are also orthogonal (asymmetric sequence) + - ``axis1 == axis3`` (symmetric sequence) + + For Davenport angles, this last relationship is relaxed [2]_, and only + the consecutive orthogonal axes requirement is maintained. + + Parameters + ---------- + axes : array_like, shape (3,) or (..., [1 or 2 or 3], 3) + Axis of rotation, if one dimensional. If two or more dimensional, describes + the sequence of axes for rotations, where each axes[..., i, :] is the ith + axis. If more than one axis is given, then the second axis must be + orthogonal to both the first and third axes. + order : string + If it is equal to 'e' or 'extrinsic', the sequence will be + extrinsic. If it is equal to 'i' or 'intrinsic', sequence + will be treated as intrinsic. + angles : float or array_like, shape (..., [1 or 2 or 3]) + Angles specified in radians (`degrees` is False) or degrees + (`degrees` is True). + Each angle i in the last dimension of `angles` turns around the corresponding + axis axis[..., i, :]. The resulting rotation has the shape + np.broadcast_shapes(np.atleast_2d(axes).shape[:-2], np.atleast_1d(angles).shape[:-1]) + Dimensionless angles are thus only valid for a single axis. + + degrees : bool, optional + If True, then the given angles are assumed to be in degrees. + Default is False. + + Returns + ------- + rotation : `Rotation` instance + Object containing the rotation represented by the sequence of + rotations around given axes with given angles. + + References + ---------- + .. [1] https://en.wikipedia.org/wiki/Euler_angles#Definition_by_intrinsic_rotations + .. [2] Shuster, Malcolm & Markley, Landis. (2003). Generalization of + the Euler Angles. Journal of the Astronautical Sciences. 51. 123-132. + 10.1007/BF03546304. + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + + Davenport angles are a generalization of Euler angles, when we use the + canonical basis axes: + + >>> ex = [1, 0, 0] + >>> ey = [0, 1, 0] + >>> ez = [0, 0, 1] + + Initialize a single rotation with a given axis sequence: + + >>> axes = [ez, ey, ex] + >>> r = R.from_davenport(axes, 'extrinsic', [90, 0, 0], degrees=True) + >>> r.as_quat().shape + (4,) + + It is equivalent to Euler angles in this case: + + >>> r.as_euler('zyx', degrees=True) + array([90., 0., -0.]) + + Initialize multiple rotations in one object: + + >>> r = R.from_davenport(axes, 'extrinsic', [[90, 45, 30], [35, 45, 90]], degrees=True) + >>> r.as_quat().shape + (2, 4) + + Using only one or two axes is also possible: + + >>> r = R.from_davenport([ez, ex], 'extrinsic', [[90, 45], [35, 45]], degrees=True) + >>> r.as_quat().shape + (2, 4) + + Non-canonical axes are possible, and they do not need to be normalized, + as long as consecutive axes are orthogonal: + + >>> e1 = [2, 0, 0] + >>> e2 = [0, 1, 0] + >>> e3 = [1, 0, 1] + >>> axes = [e1, e2, e3] + >>> r = R.from_davenport(axes, 'extrinsic', [90, 45, 30], degrees=True) + >>> r.as_quat() + [ 0.701057, 0.430459, -0.092296, 0.560986] + """ # noqa: E501 + xp = array_namespace(axes) + axes, angles = _promote(axes, angles, xp=xp) + cython_compatible = axes.ndim < 3 and angles.ndim < 2 + backend = select_backend(xp, cython_compatible=cython_compatible) + quat = backend.from_davenport(axes, order, angles, degrees) + return Rotation._from_raw_quat(quat, xp=xp, backend=backend) + + @staticmethod + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def from_mrp(mrp: ArrayLike) -> Rotation: + """Initialize from Modified Rodrigues Parameters (MRPs). + + MRPs are a 3 dimensional vector co-directional to the axis of rotation and whose + magnitude is equal to ``tan(theta / 4)``, where ``theta`` is the angle of + rotation (in radians) [1]_. + + MRPs have a singularity at 360 degrees which can be avoided by ensuring the + angle of rotation does not exceed 180 degrees, i.e. switching the direction of + the rotation when it is past 180 degrees. + + Parameters + ---------- + mrp : array_like, shape (..., 3) + A single vector or an ND array of vectors, where the last dimension + contains the rotation parameters. + + Returns + ------- + rotation : `Rotation` instance + Object containing the rotations represented by input MRPs. + + References + ---------- + .. [1] Shuster, M. D. "A Survey of Attitude Representations", + The Journal of Astronautical Sciences, Vol. 41, No.4, 1993, + pp. 475-476 + + Notes + ----- + + .. versionadded:: 1.6.0 + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Initialize a single rotation: + + >>> r = R.from_mrp([0, 0, 1]) + >>> r.as_euler('xyz', degrees=True) + array([0. , 0. , 180. ]) + >>> r.as_euler('xyz').shape + (3,) + + Initialize multiple rotations in one object: + + >>> r = R.from_mrp([ + ... [0, 0, 1], + ... [1, 0, 0]]) + >>> r.as_euler('xyz', degrees=True) + array([[0. , 0. , 180. ], + [180.0 , 0. , 0. ]]) + >>> r.as_euler('xyz').shape + (2, 3) + + It is also possible to have a stack of a single rotation: + + >>> r = R.from_mrp([[0, 0, np.pi/2]]) + >>> r.as_euler('xyz').shape + (1, 3) + + """ + xp = array_namespace(mrp) + mrp = _promote(mrp, xp=xp) + backend = select_backend(xp, cython_compatible=mrp.ndim < 3) + quat = backend.from_mrp(mrp) + return Rotation._from_raw_quat(quat, xp=xp, backend=backend) + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def as_quat(self, canonical: bool = False, *, scalar_first: bool = False) -> Array: + """Represent as quaternions. + + Rotations in 3 dimensions can be represented using unit norm + quaternions [1]_. + + The 4 components of a quaternion are divided into a scalar part ``w`` + and a vector part ``(x, y, z)`` and can be expressed from the angle + ``theta`` and the axis ``n`` of a rotation as follows:: + + w = cos(theta / 2) + x = sin(theta / 2) * n_x + y = sin(theta / 2) * n_y + z = sin(theta / 2) * n_z + + There are 2 conventions to order the components in a quaternion: + + - scalar-first order -- ``(w, x, y, z)`` + - scalar-last order -- ``(x, y, z, w)`` + + The choice is controlled by `scalar_first` argument. + By default, it is False and the scalar-last order is used. + + The mapping from quaternions to rotations is + two-to-one, i.e. quaternions ``q`` and ``-q``, where ``-q`` simply + reverses the sign of each component, represent the same spatial + rotation. + + Parameters + ---------- + canonical : `bool`, default False + Whether to map the redundant double cover of rotation space to a + unique "canonical" single cover. If True, then the quaternion is + chosen from {q, -q} such that the w term is positive. If the w term + is 0, then the quaternion is chosen such that the first nonzero + term of the x, y, and z terms is positive. + scalar_first : bool, optional + Whether the scalar component goes first or last. + Default is False, i.e. the scalar-last order is used. + + Returns + ------- + quat : `numpy.ndarray`, shape (..., 4) + Shape depends on shape of inputs used for initialization. + + References + ---------- + .. [1] https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + A rotation can be represented as a quaternion with either scalar-last + (default) or scalar-first component order. + This is shown for a single rotation: + + >>> r = R.from_matrix(np.eye(3)) + >>> r.as_quat() + array([0., 0., 0., 1.]) + >>> r.as_quat(scalar_first=True) + array([1., 0., 0., 0.]) + + The resulting shape of the quaternion is always the shape of the Rotation + object with an added last dimension of size 4. E.g. when the `Rotation` object + contains an N-dimensional array (N, M, K) of rotations, the result will be a + 4-dimensional array: + + >>> r = R.from_rotvec(np.ones((2, 3, 4, 3))) + >>> r.as_quat().shape + (2, 3, 4, 4) + + Quaternions can be mapped from a redundant double cover of the + rotation space to a canonical representation with a positive w term. + + >>> r = R.from_quat([0, 0, 0, -1]) + >>> r.as_quat() + array([0. , 0. , 0. , -1.]) + >>> r.as_quat(canonical=True) + array([0. , 0. , 0. , 1.]) + """ + quat = self._backend.as_quat( + self._quat, canonical=canonical, scalar_first=scalar_first + ) + if self._single: + return quat[0, ...] + return quat + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def as_matrix(self) -> Array: + """Represent as rotation matrix. + + 3D rotations can be represented using rotation matrices, which + are 3 x 3 real orthogonal matrices with determinant equal to +1 [1]_. + + Returns + ------- + matrix : ndarray, shape (..., 3) + Shape depends on shape of inputs used for initialization. + + References + ---------- + .. [1] https://en.wikipedia.org/wiki/Rotation_matrix#In_three_dimensions + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Represent a single rotation: + + >>> r = R.from_rotvec([0, 0, np.pi/2]) + >>> r.as_matrix() + array([[ 2.22044605e-16, -1.00000000e+00, 0.00000000e+00], + [ 1.00000000e+00, 2.22044605e-16, 0.00000000e+00], + [ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]) + >>> r.as_matrix().shape + (3, 3) + + Represent a stack with a single rotation: + + >>> r = R.from_quat([[1, 1, 0, 0]]) + >>> r.as_matrix() + array([[[ 0., 1., 0.], + [ 1., 0., 0.], + [ 0., 0., -1.]]]) + >>> r.as_matrix().shape + (1, 3, 3) + + Represent multiple rotations: + + >>> r = R.from_rotvec([[np.pi/2, 0, 0], [0, 0, np.pi/2]]) + >>> r.as_matrix() + array([[[ 1.00000000e+00, 0.00000000e+00, 0.00000000e+00], + [ 0.00000000e+00, 2.22044605e-16, -1.00000000e+00], + [ 0.00000000e+00, 1.00000000e+00, 2.22044605e-16]], + [[ 2.22044605e-16, -1.00000000e+00, 0.00000000e+00], + [ 1.00000000e+00, 2.22044605e-16, 0.00000000e+00], + [ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]]) + >>> r.as_matrix().shape + (2, 3, 3) + + Notes + ----- + This function was called as_dcm before. + + .. versionadded:: 1.4.0 + """ + matrix = self._backend.as_matrix(self._quat) + if self._single: + return matrix[0, ...] + return matrix + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def as_rotvec(self, degrees: bool = False) -> Array: + """Represent as rotation vectors. + + A rotation vector is a 3 dimensional vector which is co-directional to + the axis of rotation and whose norm gives the angle of rotation [1]_. + + Parameters + ---------- + degrees : boolean, optional + Returned magnitudes are in degrees if this flag is True, else they are + in radians. Default is False. + + .. versionadded:: 1.7.0 + + Returns + ------- + rotvec : ndarray, shape (..., 3) + Shape depends on shape of inputs used for initialization. + + References + ---------- + .. [1] https://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation#Rotation_vector + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Represent a single rotation: + + >>> r = R.from_euler('z', 90, degrees=True) + >>> r.as_rotvec() + array([0. , 0. , 1.57079633]) + >>> r.as_rotvec().shape + (3,) + + Represent a rotation in degrees: + + >>> r = R.from_euler('YX', (-90, -90), degrees=True) + >>> s = r.as_rotvec(degrees=True) + >>> s + array([-69.2820323, -69.2820323, -69.2820323]) + >>> np.linalg.norm(s) + 120.00000000000001 + + Represent a stack with a single rotation: + + >>> r = R.from_quat([[0, 0, 1, 1]]) + >>> r.as_rotvec() + array([[0. , 0. , 1.57079633]]) + >>> r.as_rotvec().shape + (1, 3) + + Represent multiple rotations in a single object: + + >>> r = R.from_quat([[0, 0, 1, 1], [1, 1, 0, 1]]) + >>> r.as_rotvec() + array([[0. , 0. , 1.57079633], + [1.35102172, 1.35102172, 0. ]]) + >>> r.as_rotvec().shape + (2, 3) + + """ + rotvec = self._backend.as_rotvec(self._quat, degrees=degrees) + if self._single: + return rotvec[0, ...] + return rotvec + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def as_euler( + self, seq: str, degrees: bool = False, *, suppress_warnings: bool = False + ) -> Array: + """Represent as Euler angles. + + Any orientation can be expressed as a composition of 3 elementary + rotations. Once the axis sequence has been chosen, Euler angles define + the angle of rotation around each respective axis [1]_. + + The algorithm from [2]_ has been used to calculate Euler angles for the + rotation about a given sequence of axes. + + Euler angles suffer from the problem of gimbal lock [3]_, where the + representation loses a degree of freedom and it is not possible to + determine the first and third angles uniquely. In this case, + a warning is raised (unless the ``suppress_warnings`` option is used), + and the third angle is set to zero. Note however that the returned + angles still represent the correct rotation. + + Parameters + ---------- + seq : string, length 3 + 3 characters belonging to the set {'X', 'Y', 'Z'} for intrinsic + rotations, or {'x', 'y', 'z'} for extrinsic rotations [1]_. + Adjacent axes cannot be the same. + Extrinsic and intrinsic rotations cannot be mixed in one function + call. + degrees : boolean, optional + Returned angles are in degrees if this flag is True, else they are + in radians. Default is False. + suppress_warnings : boolean, optional + Disable warnings about gimbal lock. Default is False. + + Returns + ------- + angles : ndarray, shape (..., 3) + Shape depends on shape of inputs used to initialize object. + The returned angles are in the range: + + - First angle belongs to [-180, 180] degrees (both inclusive) + - Third angle belongs to [-180, 180] degrees (both inclusive) + - Second angle belongs to: + + - [-90, 90] degrees if all axes are different (like xyz) + - [0, 180] degrees if first and third axes are the same + (like zxz) + + References + ---------- + .. [1] https://en.wikipedia.org/wiki/Euler_angles#Definition_by_intrinsic_rotations + .. [2] Bernardes E, Viollet S (2022) Quaternion to Euler angles + conversion: A direct, general and computationally efficient + method. PLoS ONE 17(11): e0276302. + https://doi.org/10.1371/journal.pone.0276302 + .. [3] https://en.wikipedia.org/wiki/Gimbal_lock#In_applied_mathematics + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Represent a single rotation: + + >>> r = R.from_rotvec([0, 0, np.pi/2]) + >>> r.as_euler('zxy', degrees=True) + array([90., 0., 0.]) + >>> r.as_euler('zxy', degrees=True).shape + (3,) + + Represent a stack of single rotation: + + >>> r = R.from_rotvec([[0, 0, np.pi/2]]) + >>> r.as_euler('zxy', degrees=True) + array([[90., 0., 0.]]) + >>> r.as_euler('zxy', degrees=True).shape + (1, 3) + + Represent multiple rotations in a single object: + + >>> r = R.from_rotvec([ + ... [0, 0, np.pi/2], + ... [0, -np.pi/3, 0], + ... [np.pi/4, 0, 0]]) + >>> r.as_euler('zxy', degrees=True) + array([[ 90., 0., 0.], + [ 0., 0., -60.], + [ 0., 45., 0.]]) + >>> r.as_euler('zxy', degrees=True).shape + (3, 3) + + """ + euler = self._backend.as_euler( + self._quat, seq, degrees=degrees, suppress_warnings=suppress_warnings + ) + if self._single: + return euler[0, ...] + return euler + + @xp_capabilities( + skip_backends=[ + ("dask.array", "missing linalg.cross/det functions and .mT attribute"), + ("cupy", "missing .mT attribute in cupy<14.*"), + ] + ) + def as_davenport( + self, + axes: ArrayLike, + order: str, + degrees: bool = False, + *, + suppress_warnings: bool = False, + ) -> Array: + """Represent as Davenport angles. + + Any orientation can be expressed as a composition of 3 elementary + rotations. + + For both Euler angles and Davenport angles, consecutive axes must + be are orthogonal (``axis2`` is orthogonal to both ``axis1`` and + ``axis3``). For Euler angles, there is an additional relationship + between ``axis1`` or ``axis3``, with two possibilities: + + - ``axis1`` and ``axis3`` are also orthogonal (asymmetric sequence) + - ``axis1 == axis3`` (symmetric sequence) + + For Davenport angles, this last relationship is relaxed [1]_, and only + the consecutive orthogonal axes requirement is maintained. + + A slightly modified version of the algorithm from [2]_ has been used to + calculate Davenport angles for the rotation about a given sequence of + axes. + + Davenport angles, just like Euler angles, suffer from the problem of + gimbal lock [3]_, where the representation loses a degree of freedom + and it is not possible to determine the first and third angles + uniquely. In this case, a warning is raised (unless the + ``suppress_warnings`` option is used), and the third angle is set + to zero. Note however that the returned angles still represent the + correct rotation. + + Parameters + ---------- + axes : array_like, shape (..., [1 or 2 or 3], 3) or (..., 3) + Axis of rotation, if one dimensional. If N dimensional, describes the + sequence of axes for rotations, where each axes[..., i, :] is the ith + axis. If more than one axis is given, then the second axis must be + orthogonal to both the first and third axes. + order : string + If it belongs to the set {'e', 'extrinsic'}, the sequence will be + extrinsic. If it belongs to the set {'i', 'intrinsic'}, sequence + will be treated as intrinsic. + degrees : boolean, optional + Returned angles are in degrees if this flag is True, else they are + in radians. Default is False. + suppress_warnings : boolean, optional + Disable warnings about gimbal lock. Default is False. + + Returns + ------- + angles : ndarray, shape (..., 3) + Shape depends on shape of inputs used to initialize object. + The returned angles are in the range: + + - First angle belongs to [-180, 180] degrees (both inclusive) + - Third angle belongs to [-180, 180] degrees (both inclusive) + - Second angle belongs to a set of size 180 degrees, + given by: ``[-abs(lambda), 180 - abs(lambda)]``, where ``lambda`` + is the angle between the first and third axes. + + References + ---------- + .. [1] Shuster, Malcolm & Markley, Landis. (2003). Generalization of + the Euler Angles. Journal of the Astronautical Sciences. 51. 123-132. + 10.1007/BF03546304. + .. [2] Bernardes E, Viollet S (2022) Quaternion to Euler angles + conversion: A direct, general and computationally efficient method. + PLoS ONE 17(11): e0276302. 10.1371/journal.pone.0276302 + .. [3] https://en.wikipedia.org/wiki/Gimbal_lock#In_applied_mathematics + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Davenport angles are a generalization of Euler angles, when we use the + canonical basis axes: + + >>> ex = [1, 0, 0] + >>> ey = [0, 1, 0] + >>> ez = [0, 0, 1] + + Represent a single rotation: + + >>> r = R.from_rotvec([0, 0, np.pi/2]) + >>> r.as_davenport([ez, ex, ey], 'extrinsic', degrees=True) + array([90., 0., 0.]) + >>> r.as_euler('zxy', degrees=True) + array([90., 0., 0.]) + >>> r.as_davenport([ez, ex, ey], 'extrinsic', degrees=True).shape + (3,) + + Represent a stack of single rotation: + + >>> r = R.from_rotvec([[0, 0, np.pi/2]]) + >>> r.as_davenport([ez, ex, ey], 'extrinsic', degrees=True) + array([[90., 0., 0.]]) + >>> r.as_davenport([ez, ex, ey], 'extrinsic', degrees=True).shape + (1, 3) + + Represent multiple rotations in a single object: + + >>> r = R.from_rotvec([ + ... [0, 0, 90], + ... [45, 0, 0]], degrees=True) + >>> r.as_davenport([ez, ex, ey], 'extrinsic', degrees=True) + array([[90., 0., 0.], + [ 0., 45., 0.]]) + >>> r.as_davenport([ez, ex, ey], 'extrinsic', degrees=True).shape + (2, 3) + """ + axes = self._xp.asarray( + axes, dtype=self._quat.dtype, device=xp_device(self._quat) + ) + davenport = self._backend.as_davenport( + self._quat, axes, order, degrees, suppress_warnings=suppress_warnings + ) + if self._single: + return davenport[0, ...] + return davenport + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def as_mrp(self) -> Array: + """Represent as Modified Rodrigues Parameters (MRPs). + + MRPs are a 3 dimensional vector co-directional to the axis of rotation and whose + magnitude is equal to ``tan(theta / 4)``, where ``theta`` is the angle of + rotation (in radians) [1]_. + + MRPs have a singularity at 360 degrees which can be avoided by ensuring the + angle of rotation does not exceed 180 degrees, i.e. switching the direction of + the rotation when it is past 180 degrees. This function will always return MRPs + corresponding to a rotation of less than or equal to 180 degrees. + + Returns + ------- + mrps : ndarray, shape (..., 3) + Shape depends on shape of inputs used for initialization. + + References + ---------- + .. [1] Shuster, M. D. "A Survey of Attitude Representations", + The Journal of Astronautical Sciences, Vol. 41, No.4, 1993, + pp. 475-476 + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Represent a single rotation: + + >>> r = R.from_rotvec([0, 0, np.pi]) + >>> r.as_mrp() + array([0. , 0. , 1. ]) + >>> r.as_mrp().shape + (3,) + + Represent a stack with a single rotation: + + >>> r = R.from_euler('xyz', [[180, 0, 0]], degrees=True) + >>> r.as_mrp() + array([[1. , 0. , 0. ]]) + >>> r.as_mrp().shape + (1, 3) + + Represent multiple rotations: + + >>> r = R.from_rotvec([[np.pi/2, 0, 0], [0, 0, np.pi/2]]) + >>> r.as_mrp() + array([[0.41421356, 0. , 0. ], + [0. , 0. , 0.41421356]]) + >>> r.as_mrp().shape + (2, 3) + + Notes + ----- + + .. versionadded:: 1.6.0 + """ + mrp = self._backend.as_mrp(self._quat) + if self._single: + return mrp[0, ...] + return mrp + + @staticmethod + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def concatenate(rotations: Rotation | Iterable[Rotation]) -> Rotation: + """Concatenate a sequence of `Rotation` objects into a single object. + + This is useful if you want to, for example, take the mean of a set of + rotations and need to pack them into a single object to do so. + + Parameters + ---------- + rotations : sequence of `Rotation` objects + The rotations to concatenate. If a single `Rotation` object is + passed in, a copy is returned. + + Returns + ------- + concatenated : `Rotation` instance + The concatenated rotations. + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> r1 = R.from_rotvec([0, 0, 1]) + >>> r2 = R.from_rotvec([0, 0, 2]) + >>> rc = R.concatenate([r1, r2]) + >>> rc.as_rotvec() + array([[0., 0., 1.], + [0., 0., 2.]]) + >>> rc.mean().as_rotvec() + array([0., 0., 1.5]) + + Concatenation of a split rotation recovers the original object. + + >>> rs = [r for r in rc] + >>> R.concatenate(rs).as_rotvec() + array([[0., 0., 1.], + [0., 0., 2.]]) + + Note that it may be simpler to create the desired rotations by passing + in a single list of the data during initialization, rather then by + concatenating: + + >>> R.from_rotvec([[0, 0, 1], [0, 0, 2]]).as_rotvec() + array([[0., 0., 1.], + [0., 0., 2.]]) + + Notes + ----- + .. versionadded:: 1.8.0 + """ + if isinstance(rotations, Rotation): + return Rotation(rotations.as_quat(), normalize=False, copy=True) + if not all(isinstance(x, Rotation) for x in rotations): + raise TypeError("input must contain Rotation objects only") + + xp = array_namespace(rotations[0].as_quat()) + quats = xp.concat( + [xpx.atleast_nd(x.as_quat(), ndim=2, xp=xp) for x in rotations] + ) + return Rotation._from_raw_quat(quats, xp=xp) + + @xp_capabilities( + skip_backends=[ + ("dask.array", "missing linalg.cross/det functions and .mT attribute"), + ("cupy", "missing .mT attribute in cupy<14.*"), + ] + ) + def apply(self, vectors: ArrayLike, inverse: bool = False) -> Array: + """Apply this rotation to a set of vectors. + + If the original frame rotates to the final frame by this rotation, then + its application to a vector can be seen in two ways: + + - As a projection of vector components expressed in the final frame + to the original frame. + - As the physical rotation of a vector being glued to the original + frame as it rotates. In this case the vector components are + expressed in the original frame before and after the rotation. + + In terms of rotation matrices, this application is the same as + ``self.as_matrix() @ vectors``. + + Parameters + ---------- + vectors : array_like, shape (..., 3) + Each `vectors[..., :]` represents a vector in 3D space. The shape of + rotations and shape of vectors given must follow standard numpy + broadcasting rules: either one of them equals unity or they both + equal each other. + inverse : boolean, optional + If True then the inverse of the rotation(s) is applied to the input + vectors. Default is False. + + Returns + ------- + rotated_vectors : ndarray, shape (..., 3) + Result of applying rotation on input vectors. + Shape is determined according to numpy broadcasting rules. I.e., the result + will have the shape `np.broadcast_shapes(r.shape, v.shape[:-1]) + (3,)` + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Single rotation applied on a single vector: + + >>> vector = np.array([1, 0, 0]) + >>> r = R.from_rotvec([0, 0, np.pi/2]) + >>> r.as_matrix() + array([[ 2.22044605e-16, -1.00000000e+00, 0.00000000e+00], + [ 1.00000000e+00, 2.22044605e-16, 0.00000000e+00], + [ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]]) + >>> r.apply(vector) + array([2.22044605e-16, 1.00000000e+00, 0.00000000e+00]) + >>> r.apply(vector).shape + (3,) + + Single rotation applied on multiple vectors: + + >>> vectors = np.array([ + ... [1, 0, 0], + ... [1, 2, 3]]) + >>> r = R.from_rotvec([0, 0, np.pi/4]) + >>> r.as_matrix() + array([[ 0.70710678, -0.70710678, 0. ], + [ 0.70710678, 0.70710678, 0. ], + [ 0. , 0. , 1. ]]) + >>> r.apply(vectors) + array([[ 0.70710678, 0.70710678, 0. ], + [-0.70710678, 2.12132034, 3. ]]) + >>> r.apply(vectors).shape + (2, 3) + + Multiple rotations on a single vector: + + >>> r = R.from_rotvec([[0, 0, np.pi/4], [np.pi/2, 0, 0]]) + >>> vector = np.array([1,2,3]) + >>> r.as_matrix() + array([[[ 7.07106781e-01, -7.07106781e-01, 0.00000000e+00], + [ 7.07106781e-01, 7.07106781e-01, 0.00000000e+00], + [ 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]], + [[ 1.00000000e+00, 0.00000000e+00, 0.00000000e+00], + [ 0.00000000e+00, 2.22044605e-16, -1.00000000e+00], + [ 0.00000000e+00, 1.00000000e+00, 2.22044605e-16]]]) + >>> r.apply(vector) + array([[-0.70710678, 2.12132034, 3. ], + [ 1. , -3. , 2. ]]) + >>> r.apply(vector).shape + (2, 3) + + Multiple rotations on multiple vectors. Each rotation is applied on the + corresponding vector: + + >>> r = R.from_euler('zxy', [ + ... [0, 0, 90], + ... [45, 30, 60]], degrees=True) + >>> vectors = [ + ... [1, 2, 3], + ... [1, 0, -1]] + >>> r.apply(vectors) + array([[ 3. , 2. , -1. ], + [-0.09026039, 1.11237244, -0.86860844]]) + >>> r.apply(vectors).shape + (2, 3) + + Broadcasting rules apply: + + >>> r = R.from_rotvec(np.tile([0, 0, np.pi/4], (5, 1, 4, 1))) + >>> vectors = np.ones((3, 4, 3)) + >>> r.shape, vectors.shape + ((5, 1, 4), (3, 4, 3)) + >>> r.apply(vectors).shape + (5, 3, 4, 3) + + It is also possible to apply the inverse rotation: + + >>> r = R.from_euler('zxy', [ + ... [0, 0, 90], + ... [45, 30, 60]], degrees=True) + >>> vectors = [ + ... [1, 2, 3], + ... [1, 0, -1]] + >>> r.apply(vectors, inverse=True) + array([[-3. , 2. , 1. ], + [ 1.09533535, -0.8365163 , 0.3169873 ]]) + + """ + vectors = self._xp.asarray( + vectors, device=xp_device(self._quat), dtype=self._quat.dtype + ) + single_vector = vectors.ndim == 1 + # Numpy optimization: The Cython backend typing requires us to have fixed + # dimensions, so for the Numpy case we always broadcast the vector to 2D. + if vectors.shape[-1] != 3: + raise ValueError(f"Expected input of shape (..., 3), got {vectors.shape}.") + if is_numpy(self._xp): + vectors = xpx.atleast_nd(vectors, ndim=2, xp=self._xp) + cython_compatible = self._quat.ndim < 3 and vectors.ndim < 3 + backend = select_backend(self._xp, cython_compatible=cython_compatible) + result = backend.apply(self._quat, vectors, inverse=inverse) + if self._single and single_vector: + return result[0, ...] + return result + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def __mul__(self, other: Rotation) -> Rotation | NotImplementedType: + """Compose this rotation with the other. + + If `p` and `q` are two rotations, then the composition of 'q followed + by p' is equivalent to `p * q`. In terms of rotation matrices, + the composition can be expressed as + ``p.as_matrix() @ q.as_matrix()``. + + Parameters + ---------- + other : `Rotation` instance + Object containing the rotations to be composed with this one. Note + that rotation compositions are not commutative, so ``p * q`` is + generally different from ``q * p``. + + Returns + ------- + composition : `Rotation` instance + This function supports composition of multiple rotations at a time. + Composition follows standard numpy broadcasting rules. The resulting + `Rotation` object will have the shape + `np.broadcast_shapes(p.shape, q.shape)`. In dimensions with size > 1, + rotations are composed with matching indices. In dimensions with only + one rotation, the single rotation is composed with each rotation in the + other object. + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Composition of two single rotations: + + >>> p = R.from_quat([0, 0, 1, 1]) + >>> q = R.from_quat([1, 0, 0, 1]) + >>> p.as_matrix() + array([[ 0., -1., 0.], + [ 1., 0., 0.], + [ 0., 0., 1.]]) + >>> q.as_matrix() + array([[ 1., 0., 0.], + [ 0., 0., -1.], + [ 0., 1., 0.]]) + >>> r = p * q + >>> r.as_matrix() + array([[0., 0., 1.], + [1., 0., 0.], + [0., 1., 0.]]) + + Composition of two objects containing equal number of rotations: + + >>> p = R.from_quat([[0, 0, 1, 1], [1, 0, 0, 1]]) + >>> q = R.from_rotvec([[np.pi/4, 0, 0], [-np.pi/4, 0, np.pi/4]]) + >>> p.as_quat() + array([[0. , 0. , 0.70710678, 0.70710678], + [0.70710678, 0. , 0. , 0.70710678]]) + >>> q.as_quat() + array([[ 0.38268343, 0. , 0. , 0.92387953], + [-0.37282173, 0. , 0.37282173, 0.84971049]]) + >>> r = p * q + >>> r.as_quat() + array([[ 0.27059805, 0.27059805, 0.65328148, 0.65328148], + [ 0.33721128, -0.26362477, 0.26362477, 0.86446082]]) + + Broadcasting rules apply: + >>> p = R.from_quat(np.tile(np.array([0, 0, 1, 1]), (5, 1, 1))) + >>> q = R.from_quat(np.tile(np.array([1, 0, 0, 1]), (1, 6, 1))) + >>> p.shape, q.shape + ((5, 1), (1, 6)) + >>> r = p * q + >>> r.shape + (5, 6) + """ + # Check that other is a Rotation object. We want to return NotImplemented + # instead of raising an error to allow other types to implement __rmul__. + # Python will then automatically try to delegate the multiplication to the + # other type. + # See https://github.com/scipy/scipy/issues/21541 + if not isinstance(other, Rotation): + return NotImplemented + if not broadcastable(self._quat.shape, other._quat.shape): + raise ValueError( + f"Cannot broadcast {self._quat.shape[:-1]} rotations in " + f"first to {other._quat.shape[:-1]} rotations in second object." + ) + cython_compatible = self._quat.ndim < 3 and other._quat.ndim < 3 + backend = select_backend(self._xp, cython_compatible=cython_compatible) + quat = backend.compose_quat(self._quat, other._quat) + if self._single and other._single: + quat = quat[0] + return Rotation(quat, normalize=True, copy=False) + + @xp_capabilities( + skip_backends=[("dask.array", "cannot handle zero-length rotations")] + ) + def __pow__(self, n: float | Array, modulus: None = None) -> Rotation: + """Compose this rotation with itself `n` times. + + Composition of a rotation ``p`` with itself can be extended to + non-integer ``n`` by considering the power ``n`` to be a scale factor + applied to the angle of rotation about the rotation's fixed axis. The + expression ``q = p ** n`` can also be expressed as + ``q = Rotation.from_rotvec(n * p.as_rotvec())``. + + If ``n`` is negative, then the rotation is inverted before the power + is applied. In other words, ``p ** -abs(n) == p.inv() ** abs(n)``. + + Parameters + ---------- + n : float | Array + The number of times to compose the rotation with itself. If `n` is + an array, then it must be 0d or 1d with shape (1,). + modulus : None + This overridden argument is not applicable to Rotations and must be + ``None``. + + Returns + ------- + power : `Rotation` instance + The resulting rotation will be of the same shape as the original rotation + object. Each element of the output is the corresponding element of the + input rotation raised to the power of ``n``. + + Notes + ----- + For example, a power of 2 will double the angle of rotation, and a + power of 0.5 will halve the angle. There are three notable cases: if + ``n == 1`` then the original rotation is returned, if ``n == 0`` + then the identity rotation is returned, and if ``n == -1`` then + ``p.inv()`` is returned. + + Note that fractional powers ``n`` which effectively take a root of + rotation, do so using the shortest path smallest representation of that + angle (the principal root). This means that powers of ``n`` and ``1/n`` + are not necessarily inverses of each other. For example, a 0.5 power of + a +240 degree rotation will be calculated as the 0.5 power of a -120 + degree rotation, with the result being a rotation of -60 rather than + +120 degrees. + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + + Raising a rotation to a power: + + >>> p = R.from_rotvec([1, 0, 0]) + >>> q = p ** 2 + >>> q.as_rotvec() + array([2., 0., 0.]) + >>> r = p ** 0.5 + >>> r.as_rotvec() + array([0.5, 0., 0.]) + + Inverse powers do not necessarily cancel out: + + >>> p = R.from_rotvec([0, 0, 120], degrees=True) + >>> ((p ** 2) ** 0.5).as_rotvec(degrees=True) + array([ -0., -0., -60.]) + + """ + if modulus is not None: + raise NotImplementedError("modulus not supported") + quat = self._backend.pow(self._quat, n) + if self._single: + quat = quat[0] + return Rotation._from_raw_quat(quat, xp=self._xp, backend=self._backend) + + @xp_capabilities( + skip_backends=[("dask.array", "cannot handle zero-length rotations")] + ) + def inv(self) -> Rotation: + """Invert this rotation. + + Composition of a rotation with its inverse results in an identity + transformation. + + Returns + ------- + inverse : `Rotation` instance + Object containing inverse of the rotations in the current instance. + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + + Inverting a single rotation: + + >>> p = R.from_euler('z', 45, degrees=True) + >>> q = p.inv() + >>> q.as_euler('zyx', degrees=True) + array([-45., 0., 0.]) + + Inverting multiple rotations: + + >>> p = R.from_rotvec([[0, 0, np.pi/3], [-np.pi/4, 0, 0]]) + >>> q = p.inv() + >>> q.as_rotvec() + array([[-0. , -0. , -1.04719755], + [ 0.78539816, -0. , -0. ]]) + + """ + q_inv = self._backend.inv(self._quat) + if self._single: + q_inv = q_inv[0, ...] + return Rotation._from_raw_quat(q_inv, xp=self._xp, backend=self._backend) + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def magnitude(self) -> Array: + """Get the magnitude(s) of the rotation(s). + + Returns + ------- + magnitude : ndarray or float + Angle(s) in radians, float if object contains a single rotation + and ndarray if object contains ND rotations. The magnitude + will always be in the range [0, pi]. + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + >>> r = R.from_quat(np.eye(4)) + >>> r.as_quat() + array([[ 1., 0., 0., 0.], + [ 0., 1., 0., 0.], + [ 0., 0., 1., 0.], + [ 0., 0., 0., 1.]]) + >>> r.magnitude() + array([3.14159265, 3.14159265, 3.14159265, 0. ]) + + Magnitude of a single rotation: + + >>> r[0].magnitude() + 3.141592653589793 + """ + magnitude = self._backend.magnitude(self._quat) + if self._single: + # Special handling for numpy and single rotations. self._single is only set + # if xp is numpy. We therefore know that magnitude is a numpy array and + # that it contains a single element. Previously this code returned a Python + # float in that case. Here we return a numpy float64 scalar. All other + # Array API libraries return 0d arrays instead. + # See https://github.com/scipy/scipy/pull/23198#issuecomment-3003757848 + return magnitude[0] + return magnitude + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def approx_equal( + self, other: Rotation, atol: float | None = None, degrees: bool = False + ) -> Array: + """Determine if another rotation is approximately equal to this one. + + Equality is measured by calculating the smallest angle between the + rotations, and checking to see if it is smaller than `atol`. + + Parameters + ---------- + other : `Rotation` instance + Object containing the rotations to measure against this one. + atol : float, optional + The absolute angular tolerance, below which the rotations are + considered equal. If not given, then set to 1e-8 radians by + default. + degrees : bool, optional + If True and `atol` is given, then `atol` is measured in degrees. If + False (default), then atol is measured in radians. + + Returns + ------- + approx_equal : ndarray or bool + Whether the rotations are approximately equal, bool if object + contains a single rotation and ndarray if object contains multiple + rotations. + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> import numpy as np + >>> p = R.from_quat([0, 0, 0, 1]) + >>> q = R.from_quat(np.eye(4)) + >>> p.approx_equal(q) + array([False, False, False, True]) + + Approximate equality for a single rotation: + + >>> p.approx_equal(q[0]) + False + """ + cython_compatible = self._quat.ndim < 3 and other._quat.ndim < 3 + backend = select_backend(self._xp, cython_compatible=cython_compatible) + return backend.approx_equal(self._quat, other._quat, atol=atol, degrees=degrees) + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def mean( + self, + weights: ArrayLike | None = None, + axis: None | int | tuple[int, ...] = None, + ) -> Rotation: + """Get the mean of the rotations. + + The mean used is the chordal L2 mean (also called the projected or + induced arithmetic mean) [1]_. If ``A`` is a set of rotation matrices, + then the mean ``M`` is the rotation matrix that minimizes the + following loss function: + + .. math:: + + L(M) = \\sum_{i = 1}^{n} w_i \\lVert \\mathbf{A}_i - + \\mathbf{M} \\rVert^2 , + + where :math:`w_i`'s are the `weights` corresponding to each matrix. + + Parameters + ---------- + weights : array_like shape (..., N), optional + Weights describing the relative importance of the rotations. If + None (default), then all values in `weights` are assumed to be + equal. If given, the shape of `weights` must be broadcastable to + the rotation shape. Weights must be non-negative. + axis : None, int, or tuple of ints, optional + Axis or axes along which the means are computed. The default is to + compute the mean of all rotations. + + Returns + ------- + mean : `Rotation` instance + Single rotation containing the mean of the rotations in the + current instance. + + References + ---------- + .. [1] Hartley, Richard, et al., + "Rotation Averaging", International Journal of Computer Vision + 103, 2013, pp. 267-305. + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> r = R.from_euler('zyx', [[0, 0, 0], + ... [1, 0, 0], + ... [0, 1, 0], + ... [0, 0, 1]], degrees=True) + >>> r.mean().as_euler('zyx', degrees=True) + array([0.24945696, 0.25054542, 0.24945696]) + """ + mean = self._backend.mean(self._quat, weights=weights, axis=axis) + return Rotation._from_raw_quat(mean, xp=self._xp, backend=self._backend) + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def reduce( + self, + left: Rotation | None = None, + right: Rotation | None = None, + return_indices: bool = False, + ) -> Rotation | tuple[Rotation, Array, Array]: + """Reduce this rotation with the provided rotation groups. + + Reduction of a rotation ``p`` is a transformation of the form + ``q = l * p * r``, where ``l`` and ``r`` are chosen from `left` and + `right` respectively, such that rotation ``q`` has the smallest + magnitude. + + If `left` and `right` are rotation groups representing symmetries of + two objects rotated by ``p``, then ``q`` is the rotation of the + smallest magnitude to align these objects considering their symmetries. + + Parameters + ---------- + left : `Rotation` instance, optional + Object containing the left rotation(s). Default value (None) + corresponds to the identity rotation. + right : `Rotation` instance, optional + Object containing the right rotation(s). Default value (None) + corresponds to the identity rotation. + return_indices : bool, optional + Whether to return the indices of the rotations from `left` and + `right` used for reduction. + + Returns + ------- + reduced : `Rotation` instance + Object containing reduced rotations. + left_best, right_best: integer ndarray + Indices of elements from `left` and `right` used for reduction. + """ + left = left.as_quat() if left is not None else None + right = right.as_quat() if right is not None else None + reduced, left_idx, right_idx = self._backend.reduce( + self._quat, left=left, right=right + ) + if self._single: + reduced = reduced[0, ...] + rot = Rotation._from_raw_quat(reduced, xp=self._xp, backend=self._backend) + if return_indices: + left_idx = left_idx if left is not None else None + right_idx = right_idx if right is not None else None + return rot, left_idx, right_idx + return rot + + @classmethod + def create_group(cls, group: str, axis: str = "Z") -> Rotation: + """Create a 3D rotation group. + + Parameters + ---------- + group : string + The name of the group. Must be one of 'I', 'O', 'T', 'Dn', 'Cn', + where `n` is a positive integer. The groups are: + + * I: Icosahedral group + * O: Octahedral group + * T: Tetrahedral group + * D: Dicyclic group + * C: Cyclic group + + axis : integer + The cyclic rotation axis. Must be one of ['X', 'Y', 'Z'] (or + lowercase). Default is 'Z'. Ignored for groups 'I', 'O', and 'T'. + + Returns + ------- + rotation : `Rotation` instance + Object containing the elements of the rotation group. + + Notes + ----- + This method generates rotation groups only. The full 3-dimensional + point groups [PointGroups]_ also contain reflections. + + References + ---------- + .. [PointGroups] `Point groups + `_ + on Wikipedia. + """ + # TODO: We defer the implementation of groups for arbitrary Array API frameworks + # to the follow-up PR that adds general Array API support for Rotations. + return create_group(cls, group, axis=axis) + + @xp_capabilities( + jax_jit=False, + skip_backends=[("dask.array", "cannot handle zero-length rotations")], + ) + def __getitem__(self, indexer: int | slice | EllipsisType | None) -> Rotation: + """Extract rotation(s) at given index(es) from object. + + Create a new `Rotation` instance containing a subset of rotations + stored in this object. + + Parameters + ---------- + indexer : index, slice, or index array + Specifies which rotation(s) to extract. A single indexer must be + specified, i.e. as if indexing a 1 dimensional array or list. + + Returns + ------- + rotation : `Rotation` instance + Contains + - a single rotation, if `indexer` is a single index + - a stack of rotation(s), if `indexer` is a slice, or and index + array. + + Raises + ------ + TypeError if the instance was created as a single rotation. + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> rs = R.from_quat([ + ... [1, 1, 0, 0], + ... [0, 1, 0, 1], + ... [1, 1, -1, 0]]) # These quats are normalized + >>> rs.as_quat() + array([[ 0.70710678, 0.70710678, 0. , 0. ], + [ 0. , 0.70710678, 0. , 0.70710678], + [ 0.57735027, 0.57735027, -0.57735027, 0. ]]) + + Indexing using a single index: + + >>> a = rs[0] + >>> a.as_quat() + array([0.70710678, 0.70710678, 0. , 0. ]) + + Array slicing: + + >>> b = rs[1:3] + >>> b.as_quat() + array([[ 0. , 0.70710678, 0. , 0.70710678], + [ 0.57735027, 0.57735027, -0.57735027, 0. ]]) + + List comprehension to split each rotation into its own object: + + >>> c = [r for r in rs] + >>> print([r.as_quat() for r in c]) + [array([ 0.70710678, 0.70710678, 0. , 0. ]), + array([ 0. , 0.70710678, 0. , 0.70710678]), + array([ 0.57735027, 0.57735027, -0.57735027, 0. ])] + + Concatenation of split rotations will recover the original object: + + >>> R.concatenate([a, b]).as_quat() + array([[ 0.70710678, 0.70710678, 0. , 0. ], + [ 0. , 0.70710678, 0. , 0.70710678], + [ 0.57735027, 0.57735027, -0.57735027, 0. ]]) + """ + if self._single or self._quat.ndim == 1: + raise TypeError("Single rotation is not subscriptable.") + is_array = isinstance(indexer, type(self._quat)) + # Masking is only specified in the Array API when the array is the sole index + # TODO: This special case handling is mainly a result of Array API limitations. + # Ideally we would get rid of them altogether and converge to [indexer, ...] + # indexing. + if is_array and indexer.dtype == self._xp.bool: + return Rotation(self._quat[indexer], normalize=False) + if is_array and self._xp.isdtype(indexer.dtype, "integral"): + # xp.take is implementation-defined for zero-dim arrays, hence we raise + # pre-emptively to have consistent behavior across frameworks. + if self._quat.shape[0] == 0: + raise IndexError("cannot do a non-empty take from an empty axes.") + return Rotation(self._xp.take(self._quat, indexer, axis=0), normalize=False) + return Rotation(self._quat[indexer, ...], normalize=False) + + @xp_capabilities( + jax_jit=False, + skip_backends=[("dask.array", "cannot handle zero-length rotations")], + ) + def __setitem__(self, indexer: int | slice | EllipsisType | None, value: Rotation): + """Set rotation(s) at given index(es) from object. + + Parameters + ---------- + indexer : index, slice, or index array + Specifies which rotation(s) to replace. A single indexer must be + specified, i.e. as if indexing a 1 dimensional array or list. + + value : `Rotation` instance + The rotations to set. + + Raises + ------ + TypeError if the instance was created as a single rotation. + + Notes + ----- + + .. versionadded:: 1.8.0 + """ + if self._single or self._quat.ndim == 1: + raise TypeError("Single rotation is not subscriptable.") + + if not isinstance(value, Rotation): + raise TypeError("value must be a Rotation object") + + self._quat = self._backend.setitem(self._quat, value.as_quat(), indexer) + + @staticmethod + def identity( + num: int | None = None, *, shape: int | tuple[int, ...] | None = None + ) -> Rotation: + """Get identity rotation(s). + + Composition with the identity rotation has no effect. + + Parameters + ---------- + num : int or None, optional + Number of identity rotations to generate. If None (default), then a + single rotation is generated. + shape : int or tuple of ints, optional + Shape of identity rotations to generate. If specified, `num` must + be None. + + Returns + ------- + identity : Rotation object + The identity rotation. + """ + # TODO: We should move to one single way of specifying the output shape and + # deprecate `num`. + if num is not None and shape is not None: + raise ValueError("Only one of `num` or `shape` can be specified.") + quat = cython_backend.identity(num, shape=shape) + return Rotation._from_raw_quat(quat, xp=array_namespace(quat)) + + @staticmethod + @_transition_to_rng("random_state", position_num=2) + def random( + num: int | None = None, + rng: np.random.Generator | None = None, + *, + shape: tuple[int, ...] | None = None, + ) -> Rotation: + r"""Generate rotations that are uniformly distributed on a sphere. + + Formally, the rotations follow the Haar-uniform distribution over the SO(3) + group. + + Parameters + ---------- + num : int or None, optional + Number of random rotations to generate. If None (default), then a + single rotation is generated. + rng : `numpy.random.Generator`, optional + Pseudorandom number generator state. When `rng` is None, a new + `numpy.random.Generator` is created using entropy from the + operating system. Types other than `numpy.random.Generator` are + passed to `numpy.random.default_rng` to instantiate a `Generator`. + shape : tuple of ints, optional + Shape of random rotations to generate. If specified, `num` must be None. + + Returns + ------- + random_rotation : `Rotation` instance + Contains a single rotation if `num` is None. Otherwise contains a + stack of `num` rotations. + + Notes + ----- + This function is optimized for efficiently sampling random rotation + matrices in three dimensions. For generating random rotation matrices + in higher dimensions, see `scipy.stats.special_ortho_group`. + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + + Sample a single rotation: + + >>> R.random().as_euler('zxy', degrees=True) + array([-110.5976185 , 55.32758512, 76.3289269 ]) # random + + Sample a stack of rotations: + + >>> R.random(5).as_euler('zxy', degrees=True) + array([[-110.5976185 , 55.32758512, 76.3289269 ], # random + [ -91.59132005, -14.3629884 , -93.91933182], + [ 25.23835501, 45.02035145, -121.67867086], + [ -51.51414184, -15.29022692, -172.46870023], + [ -81.63376847, -27.39521579, 2.60408416]]) + + See Also + -------- + scipy.stats.special_ortho_group + + """ + # TODO: We should move to one single way of specifying the output shape and + # deprecate `num`. + if num is not None and shape is not None: + raise ValueError("Only one of `num` or `shape` can be specified.") + sample = cython_backend.random(num, rng, shape=shape) + return Rotation(sample, normalize=True, copy=False) + + @staticmethod + @xp_capabilities( + skip_backends=[ + ("dask.array", "missing linalg.cross/det functions and .mT attribute"), + ("cupy", "missing .mT attribute in cupy<14.*"), + ] + ) + def align_vectors( + a: ArrayLike, + b: ArrayLike, + weights: ArrayLike | None = None, + return_sensitivity: bool = False, + ) -> tuple[Rotation, float] | tuple[Rotation, float, Array]: + """Estimate a rotation to optimally align two sets of vectors. + + Find a rotation between frames A and B which best aligns a set of + vectors `a` and `b` observed in these frames. The following loss + function is minimized to solve for the rotation matrix + :math:`C`: + + .. math:: + + L(C) = \\frac{1}{2} \\sum_{i = 1}^{n} w_i \\lVert \\mathbf{a}_i - + C \\mathbf{b}_i \\rVert^2 , + + where :math:`w_i`'s are the `weights` corresponding to each vector. + + The rotation is estimated with Kabsch algorithm [1]_, and solves what + is known as the "pointing problem", or "Wahba's problem" [2]_. + + Note that the length of each vector in this formulation acts as an + implicit weight. So for use cases where all vectors need to be + weighted equally, you should normalize them to unit length prior to + calling this method. + + There are two special cases. The first is if a single vector is given + for `a` and `b`, in which the shortest distance rotation that aligns + `b` to `a` is returned. + + The second is when one of the weights is infinity. In this case, the + shortest distance rotation between the primary infinite weight vectors + is calculated as above. Then, the rotation about the aligned primary + vectors is calculated such that the secondary vectors are optimally + aligned per the above loss function. The result is the composition + of these two rotations. The result via this process is the same as the + Kabsch algorithm as the corresponding weight approaches infinity in + the limit. For a single secondary vector this is known as the + "align-constrain" algorithm [3]_. + + For both special cases (single vectors or an infinite weight), the + sensitivity matrix does not have physical meaning and an error will be + raised if it is requested. For an infinite weight, the primary vectors + act as a constraint with perfect alignment, so their contribution to + `rssd` will be forced to 0 even if they are of different lengths. + + Parameters + ---------- + a : array_like, shape (3,) or (N, 3) + Vector components observed in initial frame A. Each row of `a` + denotes a vector. + b : array_like, shape (3,) or (N, 3) + Vector components observed in another frame B. Each row of `b` + denotes a vector. + weights : array_like shape (N,), optional + Weights describing the relative importance of the vector + observations. If None (default), then all values in `weights` are + assumed to be 1. One and only one weight may be infinity, and + weights must be positive. + return_sensitivity : bool, optional + Whether to return the sensitivity matrix. See Notes for details. + Default is False. + + Returns + ------- + rotation : `Rotation` instance + Best estimate of the rotation that transforms `b` to `a`. + rssd : float + Stands for "root sum squared distance". Square root of the weighted + sum of the squared distances between the given sets of vectors + after alignment. It is equal to ``sqrt(2 * minimum_loss)``, where + ``minimum_loss`` is the loss function evaluated for the found + optimal rotation. + Note that the result will also be weighted by the vectors' + magnitudes, so perfectly aligned vector pairs will have nonzero + `rssd` if they are not of the same length. This can be avoided by + normalizing them to unit length prior to calling this method, + though note that doing this will change the resulting rotation. + sensitivity_matrix : ndarray, shape (3, 3) + Sensitivity matrix of the estimated rotation estimate as explained + in Notes. Returned only when `return_sensitivity` is True. Not + valid if aligning a single pair of vectors or if there is an + infinite weight, in which cases an error will be raised. + + Notes + ----- + The sensitivity matrix gives the sensitivity of the estimated rotation + to small perturbations of the vector measurements. Specifically we + consider the rotation estimate error as a small rotation vector of + frame A. The sensitivity matrix is proportional to the covariance of + this rotation vector assuming that the vectors in `a` was measured with + errors significantly less than their lengths. To get the true + covariance matrix, the returned sensitivity matrix must be multiplied + by harmonic mean [4]_ of variance in each observation. Note that + `weights` are supposed to be inversely proportional to the observation + variances to get consistent results. For example, if all vectors are + measured with the same accuracy of 0.01 (`weights` must be all equal), + then you should multiple the sensitivity matrix by 0.01**2 to get the + covariance. + + Refer to [5]_ for more rigorous discussion of the covariance + estimation. See [6]_ for more discussion of the pointing problem and + minimal proper pointing. + + This function does not support broadcasting or ND arrays with N > 2. + + References + ---------- + .. [1] https://en.wikipedia.org/wiki/Kabsch_algorithm + .. [2] https://en.wikipedia.org/wiki/Wahba%27s_problem + .. [3] Magner, Robert, + "Extending target tracking capabilities through trajectory and + momentum setpoint optimization." Small Satellite Conference, + 2018. + .. [4] https://en.wikipedia.org/wiki/Harmonic_mean + .. [5] F. Landis Markley, + "Attitude determination using vector observations: a fast + optimal matrix algorithm", Journal of Astronautical Sciences, + Vol. 41, No.2, 1993, pp. 261-280. + .. [6] Bar-Itzhack, Itzhack Y., Daniel Hershkowitz, and Leiba Rodman, + "Pointing in Real Euclidean Space", Journal of Guidance, + Control, and Dynamics, Vol. 20, No. 5, 1997, pp. 916-922. + + Examples + -------- + >>> import numpy as np + >>> from scipy.spatial.transform import Rotation as R + + Here we run the baseline Kabsch algorithm to best align two sets of + vectors, where there is noise on the last two vector measurements of + the ``b`` set: + + >>> a = [[0, 1, 0], [0, 1, 1], [0, 1, 1]] + >>> b = [[1, 0, 0], [1, 1.1, 0], [1, 0.9, 0]] + >>> rot, rssd, sens = R.align_vectors(a, b, return_sensitivity=True) + >>> rot.as_matrix() + array([[0., 0., 1.], + [1., 0., 0.], + [0., 1., 0.]]) + + When we apply the rotation to ``b``, we get vectors close to ``a``: + + >>> rot.apply(b) + array([[0. , 1. , 0. ], + [0. , 1. , 1.1], + [0. , 1. , 0.9]]) + + The error for the first vector is 0, and for the last two the error is + magnitude 0.1. The `rssd` is the square root of the sum of the + weighted squared errors, and the default weights are all 1, so in this + case the `rssd` is calculated as + ``sqrt(1 * 0**2 + 1 * 0.1**2 + 1 * (-0.1)**2) = 0.141421356237308`` + + >>> a - rot.apply(b) + array([[ 0., 0., 0. ], + [ 0., 0., -0.1], + [ 0., 0., 0.1]]) + >>> np.sqrt(np.sum(np.ones(3) @ (a - rot.apply(b))**2)) + 0.141421356237308 + >>> rssd + 0.141421356237308 + + The sensitivity matrix for this example is as follows: + + >>> sens + array([[0.2, 0. , 0.], + [0. , 1.5, 1.], + [0. , 1. , 1.]]) + + Special case 1: Find a minimum rotation between single vectors: + + >>> a = [1, 0, 0] + >>> b = [0, 1, 0] + >>> rot, _ = R.align_vectors(a, b) + >>> rot.as_matrix() + array([[0., 1., 0.], + [-1., 0., 0.], + [0., 0., 1.]]) + >>> rot.apply(b) + array([1., 0., 0.]) + + Special case 2: One infinite weight. Here we find a rotation between + primary and secondary vectors that can align exactly: + + >>> a = [[0, 1, 0], [0, 1, 1]] + >>> b = [[1, 0, 0], [1, 1, 0]] + >>> rot, _ = R.align_vectors(a, b, weights=[np.inf, 1]) + >>> rot.as_matrix() + array([[0., 0., 1.], + [1., 0., 0.], + [0., 1., 0.]]) + >>> rot.apply(b) + array([[0., 1., 0.], + [0., 1., 1.]]) + + Here the secondary vectors must be best-fit: + + >>> a = [[0, 1, 0], [0, 1, 1]] + >>> b = [[1, 0, 0], [1, 2, 0]] + >>> rot, _ = R.align_vectors(a, b, weights=[np.inf, 1]) + >>> rot.as_matrix() + array([[0., 0., 1.], + [1., 0., 0.], + [0., 1., 0.]]) + >>> rot.apply(b) + array([[0., 1., 0.], + [0., 1., 2.]]) + """ + xp = array_namespace(a) + a, b, weights = _promote(a, b, weights, xp=xp) + cython_compatible = ( + (a.ndim < 3) & (b.ndim < 3) & (weights is None or weights.ndim < 2) + ) + backend = select_backend(xp, cython_compatible=cython_compatible) + q, rssd, sensitivity = backend.align_vectors(a, b, weights, return_sensitivity) + if return_sensitivity: + return Rotation._from_raw_quat(q, xp=xp, backend=backend), rssd, sensitivity + return Rotation._from_raw_quat(q, xp=xp, backend=backend), rssd + + def __getstate__(self) -> tuple[Array, bool]: + return (self._quat, self._single) + + def __setstate__(self, state: tuple[Array, bool]): + quat, single = state + xp = array_namespace(quat) + self._xp = xp + self._quat = xp.asarray(quat, copy=True) + self._backend = select_backend(xp, cython_compatible=self._quat.ndim < 3) + self._single = single + + @property + def single(self) -> bool: + """Whether this instance represents a single rotation.""" + return self._single or self._quat.ndim == 1 + + @property + def shape(self) -> tuple[int, ...]: + """The shape of the rotation's leading dimensions.""" + if self._single: + return () + return self._quat.shape[:-1] + + def __bool__(self) -> bool: + """Comply with Python convention for objects to be True. + + Required because `Rotation.__len__()` is defined and not always truthy. + """ + return True + + def __len__(self) -> int: + """Number of rotations contained in this object. + + Multiple rotations can be stored in a single instance. + + Returns + ------- + length : int + Number of rotations stored in object. + + Raises + ------ + TypeError if the instance was created as a single rotation. + """ + if self._single or self._quat.ndim == 1: + raise TypeError("Single rotation has no len().") + return self._quat.shape[0] + + @xp_capabilities( + skip_backends=[("dask.array", "missing linalg.cross/det functions")] + ) + def __repr__(self) -> str: + m = f"{self.as_matrix()!r}".splitlines() + # bump indent (+21 characters) + m[1:] = [" " * 21 + m[i] for i in range(1, len(m))] + return "Rotation.from_matrix(" + "\n".join(m) + ")" + + @xp_capabilities() + def __iter__(self) -> Iterator[Rotation]: + """Iterate over rotations.""" + if self._single or self._quat.ndim == 1: + raise TypeError("Single rotation is not iterable.") + # We return a generator that yields a new Rotation object for each rotation + # in the current object. We cannot rely on the default implementation using + # __getitem__ because jax will not raise an IndexError for out-of-bounds + # indices. + for i in range(self._quat.shape[0]): + yield Rotation(self._quat[i, ...], normalize=False, copy=False) + + @staticmethod + def _from_raw_quat( + quat: Array, xp: ModuleType, backend: ModuleType | None = None + ) -> Rotation: + """Create a Rotation skipping all sanitization steps. + + This method is intended for internal, performant creation of Rotations with + quaternions that are guaranteed to be valid. + """ + rot = Rotation.__new__(Rotation) + rot._single = quat.ndim == 1 and is_numpy(xp) + if rot._single: + quat = xpx.atleast_nd(quat, ndim=2, xp=xp) + rot._quat = quat + rot._xp = xp + if backend is None: + backend = select_backend(xp, cython_compatible=quat.ndim < 3) + rot._backend = backend + return rot + + +class Slerp: + """Spherical Linear Interpolation of Rotations. + + The interpolation between consecutive rotations is performed as a rotation + around a fixed axis with a constant angular velocity [1]_. This ensures + that the interpolated rotations follow the shortest path between initial + and final orientations. + + Parameters + ---------- + times : array_like, shape (N,) + Times of the known rotations. At least 2 times must be specified. + rotations : `Rotation` instance + Rotations to perform the interpolation between. Must contain N + rotations. + + Methods + ------- + __call__ + + See Also + -------- + Rotation + + Notes + ----- + This class only supports interpolation of rotations with a single leading + dimension. + + .. versionadded:: 1.2.0 + + References + ---------- + .. [1] https://en.wikipedia.org/wiki/Slerp#Quaternion_Slerp + + Examples + -------- + >>> from scipy.spatial.transform import Rotation as R + >>> from scipy.spatial.transform import Slerp + + Setup the fixed keyframe rotations and times: + + >>> key_rots = R.random(5, random_state=2342345) + >>> key_times = [0, 1, 2, 3, 4] + + Create the interpolator object: + + >>> slerp = Slerp(key_times, key_rots) + + Interpolate the rotations at the given times: + + >>> times = [0, 0.5, 0.25, 1, 1.5, 2, 2.75, 3, 3.25, 3.60, 4] + >>> interp_rots = slerp(times) + + The keyframe rotations expressed as Euler angles: + + >>> key_rots.as_euler('xyz', degrees=True) + array([[ 14.31443779, -27.50095894, -3.7275787 ], + [ -1.79924227, -24.69421529, 164.57701743], + [146.15020772, 43.22849451, -31.34891088], + [ 46.39959442, 11.62126073, -45.99719267], + [-88.94647804, -49.64400082, -65.80546984]]) + + The interpolated rotations expressed as Euler angles. These agree with the + keyframe rotations at both endpoints of the range of keyframe times. + + >>> interp_rots.as_euler('xyz', degrees=True) + array([[ 14.31443779, -27.50095894, -3.7275787 ], + [ 4.74588574, -32.44683966, 81.25139984], + [ 10.71094749, -31.56690154, 38.06896408], + [ -1.79924227, -24.69421529, 164.57701743], + [ 11.72796022, 51.64207311, -171.7374683 ], + [ 146.15020772, 43.22849451, -31.34891088], + [ 68.10921869, 20.67625074, -48.74886034], + [ 46.39959442, 11.62126073, -45.99719267], + [ 12.35552615, 4.21525086, -64.89288124], + [ -30.08117143, -19.90769513, -78.98121326], + [ -88.94647804, -49.64400082, -65.80546984]]) + + """ + + @xp_capabilities( + jax_jit=False, skip_backends=[("dask.array", "missing linalg.cross function")] + ) + def __init__(self, times: ArrayLike, rotations: Rotation): + if not isinstance(rotations, Rotation): + raise TypeError("`rotations` must be a `Rotation` instance.") + + if rotations.single or len(rotations) <= 1: + raise ValueError("`rotations` must be a sequence of at least 2 rotations.") + + q = rotations.as_quat() + if q.ndim > 2: + raise ValueError( + "Rotations with more than 1 leading dimension are not supported." + ) + + xp = array_namespace(q) + times = xp.asarray(times, device=xp_device(q), dtype=q.dtype) + if times.ndim != 1: + raise ValueError( + "Expected times to be specified in a 1 dimensional array, got " + f"{times.ndim} dimensions." + ) + + if times.shape[0] != len(rotations): + raise ValueError( + "Expected number of rotations to be equal to number of timestamps " + f"given, got {len(rotations)} rotations and {times.shape[0]} " + "timestamps." + ) + self.times = times + self.timedelta = xp.diff(times) + + # We cannot check for values for lazy backends, so we cannot raise an error on + # timedelta < 0 for lazy backends. Instead, we set timedelta to nans + neg_mask = xp.any(self.timedelta <= 0) + if is_lazy_array(neg_mask): + self.timedelta = xp.where(neg_mask, xp.nan, self.timedelta) + self.times = xp.where(neg_mask, xp.nan, self.times) + elif xp.any(neg_mask): + raise ValueError("Times must be in strictly increasing order.") + + self.rotations = rotations[:-1] + self.rotvecs = (self.rotations.inv() * rotations[1:]).as_rotvec() + + @xp_capabilities() + def __call__(self, times: ArrayLike) -> Rotation: + """Interpolate rotations. + + Compute the interpolated rotations at the given `times`. + + Parameters + ---------- + times : array_like + Times to compute the interpolations at. Can be a scalar or + 1-dimensional. + + Returns + ------- + interpolated_rotation : `Rotation` instance + Object containing the rotations computed at given `times`. + + """ + xp = array_namespace(self.times) + device = xp_device(self.times) + # Clearly differentiate from self.times property + compute_times = xp.asarray(times, device=device, dtype=self.times.dtype) + if compute_times.ndim > 1: + raise ValueError("`times` must be at most 1-dimensional.") + + single_time = compute_times.ndim == 0 + compute_times = xpx.atleast_nd(compute_times, ndim=1, xp=xp) + + # side = 'left' (default) excludes t_min. + ind = xp.searchsorted(self.times, compute_times) - 1 + # Include t_min. Without this step, index for t_min equals -1 + ind = xpx.at(ind, compute_times == self.times[0]).set(0) + # We cannot error out on invalid indices for jit compiled code. To not produce + # an index error, we set the index to 0 in case it is out of bounds, and later + # set the result to nan. + invalid_ind = (ind < 0) | (ind > len(self.rotations) - 1) + if is_lazy_array(invalid_ind): + ind = xpx.at(ind, invalid_ind).set(0) + elif xp.any(invalid_ind): + raise ValueError( + f"Interpolation times must be within the range [{self.times[0]}, " + f"{self.times[-1]}], both inclusive." + ) + + alpha = (compute_times - self.times[ind]) / self.timedelta[ind] + alpha = xpx.at(alpha, invalid_ind).set(xp.nan) + + # The array API does not support integer arrays + ellipsis indexing and won't + # stabilize this feature due to blockers in PyTorch. Therefore we need to + # construct the index for the last dimension manually. + # See https://github.com/scipy/scipy/pull/23249#discussion_r2198363047 + result = self.rotations[ind] * Rotation.from_rotvec( + self.rotvecs[ind[:, None], xp.arange(3, device=device)] * alpha[:, None] + ) + + if single_time: + result = result[0] + + return result diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rotation_groups.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rotation_groups.py new file mode 100644 index 0000000000000000000000000000000000000000..870e9b9e2b44bff56b8228a70607e29f8173accc --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rotation_groups.py @@ -0,0 +1,140 @@ +import numpy as np +from scipy.constants import golden as phi + + +def icosahedral(cls): + g1 = tetrahedral(cls).as_quat() + a = 0.5 + b = 0.5 / phi + c = phi / 2 + g2 = np.array([[+a, +b, +c, 0], + [+a, +b, -c, 0], + [+a, +c, 0, +b], + [+a, +c, 0, -b], + [+a, -b, +c, 0], + [+a, -b, -c, 0], + [+a, -c, 0, +b], + [+a, -c, 0, -b], + [+a, 0, +b, +c], + [+a, 0, +b, -c], + [+a, 0, -b, +c], + [+a, 0, -b, -c], + [+b, +a, 0, +c], + [+b, +a, 0, -c], + [+b, +c, +a, 0], + [+b, +c, -a, 0], + [+b, -a, 0, +c], + [+b, -a, 0, -c], + [+b, -c, +a, 0], + [+b, -c, -a, 0], + [+b, 0, +c, +a], + [+b, 0, +c, -a], + [+b, 0, -c, +a], + [+b, 0, -c, -a], + [+c, +a, +b, 0], + [+c, +a, -b, 0], + [+c, +b, 0, +a], + [+c, +b, 0, -a], + [+c, -a, +b, 0], + [+c, -a, -b, 0], + [+c, -b, 0, +a], + [+c, -b, 0, -a], + [+c, 0, +a, +b], + [+c, 0, +a, -b], + [+c, 0, -a, +b], + [+c, 0, -a, -b], + [0, +a, +c, +b], + [0, +a, +c, -b], + [0, +a, -c, +b], + [0, +a, -c, -b], + [0, +b, +a, +c], + [0, +b, +a, -c], + [0, +b, -a, +c], + [0, +b, -a, -c], + [0, +c, +b, +a], + [0, +c, +b, -a], + [0, +c, -b, +a], + [0, +c, -b, -a]]) + return cls.from_quat(np.concatenate((g1, g2))) + + +def octahedral(cls): + g1 = tetrahedral(cls).as_quat() + c = np.sqrt(2) / 2 + g2 = np.array([[+c, 0, 0, +c], + [0, +c, 0, +c], + [0, 0, +c, +c], + [0, 0, -c, +c], + [0, -c, 0, +c], + [-c, 0, 0, +c], + [0, +c, +c, 0], + [0, -c, +c, 0], + [+c, 0, +c, 0], + [-c, 0, +c, 0], + [+c, +c, 0, 0], + [-c, +c, 0, 0]]) + return cls.from_quat(np.concatenate((g1, g2))) + + +def tetrahedral(cls): + g1 = np.eye(4) + c = 0.5 + g2 = np.array([[c, -c, -c, +c], + [c, -c, +c, +c], + [c, +c, -c, +c], + [c, +c, +c, +c], + [c, -c, -c, -c], + [c, -c, +c, -c], + [c, +c, -c, -c], + [c, +c, +c, -c]]) + return cls.from_quat(np.concatenate((g1, g2))) + + +def dicyclic(cls, n, axis=2): + g1 = cyclic(cls, n, axis).as_rotvec() + + thetas = np.linspace(0, np.pi, n, endpoint=False) + rv = np.pi * np.vstack([np.zeros(n), np.cos(thetas), np.sin(thetas)]).T + g2 = np.roll(rv, axis, axis=1) + return cls.from_rotvec(np.concatenate((g1, g2))) + + +def cyclic(cls, n, axis=2): + thetas = np.linspace(0, 2 * np.pi, n, endpoint=False) + rv = np.vstack([thetas, np.zeros(n), np.zeros(n)]).T + return cls.from_rotvec(np.roll(rv, axis, axis=1)) + + +def create_group(cls, group, axis='Z'): + if not isinstance(group, str): + raise ValueError("`group` argument must be a string") + + permitted_axes = ['x', 'y', 'z', 'X', 'Y', 'Z'] + if axis not in permitted_axes: + raise ValueError("`axis` must be one of " + ", ".join(permitted_axes)) + + if group in ['I', 'O', 'T']: + symbol = group + order = 1 + elif group[:1] in ['C', 'D'] and group[1:].isdigit(): + symbol = group[:1] + order = int(group[1:]) + else: + raise ValueError("`group` must be one of 'I', 'O', 'T', 'Dn', 'Cn'") + + if order < 1: + raise ValueError("Group order must be positive") + + axis = 'xyz'.index(axis.lower()) + if symbol == 'I': + return icosahedral(cls) + elif symbol == 'O': + return octahedral(cls) + elif symbol == 'T': + return tetrahedral(cls) + elif symbol == 'D': + return dicyclic(cls, order, axis=axis) + elif symbol == 'C': + return cyclic(cls, order, axis=axis) + else: + assert False diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rotation_spline.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rotation_spline.py new file mode 100644 index 0000000000000000000000000000000000000000..9d6b99a5af898bff9ee9148b8712f861c54740fd --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rotation_spline.py @@ -0,0 +1,465 @@ +import numpy as np +from scipy.linalg import solve_banded +from ._rotation import Rotation + + +def _create_skew_matrix(x): + """Create skew-symmetric matrices corresponding to vectors. + + Parameters + ---------- + x : ndarray, shape (n, 3) + Set of vectors. + + Returns + ------- + ndarray, shape (n, 3, 3) + """ + result = np.zeros((len(x), 3, 3)) + result[:, 0, 1] = -x[:, 2] + result[:, 0, 2] = x[:, 1] + result[:, 1, 0] = x[:, 2] + result[:, 1, 2] = -x[:, 0] + result[:, 2, 0] = -x[:, 1] + result[:, 2, 1] = x[:, 0] + return result + + +def _matrix_vector_product_of_stacks(A, b): + """Compute the product of stack of matrices and vectors.""" + return np.einsum("ijk,ik->ij", A, b) + + +def _angular_rate_to_rotvec_dot_matrix(rotvecs): + """Compute matrices to transform angular rates to rot. vector derivatives. + + The matrices depend on the current attitude represented as a rotation + vector. + + Parameters + ---------- + rotvecs : ndarray, shape (n, 3) + Set of rotation vectors. + + Returns + ------- + ndarray, shape (n, 3, 3) + """ + norm = np.linalg.norm(rotvecs, axis=1) + k = np.empty_like(norm) + + mask = norm > 1e-4 + nm = norm[mask] + k[mask] = (1 - 0.5 * nm / np.tan(0.5 * nm)) / nm**2 + mask = ~mask + nm = norm[mask] + k[mask] = 1/12 + 1/720 * nm**2 + + skew = _create_skew_matrix(rotvecs) + + result = np.empty((len(rotvecs), 3, 3)) + result[:] = np.identity(3) + result[:] += 0.5 * skew + result[:] += k[:, None, None] * np.matmul(skew, skew) + + return result + + +def _rotvec_dot_to_angular_rate_matrix(rotvecs): + """Compute matrices to transform rot. vector derivatives to angular rates. + + The matrices depend on the current attitude represented as a rotation + vector. + + Parameters + ---------- + rotvecs : ndarray, shape (n, 3) + Set of rotation vectors. + + Returns + ------- + ndarray, shape (n, 3, 3) + """ + norm = np.linalg.norm(rotvecs, axis=1) + k1 = np.empty_like(norm) + k2 = np.empty_like(norm) + + mask = norm > 1e-4 + nm = norm[mask] + k1[mask] = (1 - np.cos(nm)) / nm ** 2 + k2[mask] = (nm - np.sin(nm)) / nm ** 3 + + mask = ~mask + nm = norm[mask] + k1[mask] = 0.5 - nm ** 2 / 24 + k2[mask] = 1 / 6 - nm ** 2 / 120 + + skew = _create_skew_matrix(rotvecs) + + result = np.empty((len(rotvecs), 3, 3)) + result[:] = np.identity(3) + result[:] -= k1[:, None, None] * skew + result[:] += k2[:, None, None] * np.matmul(skew, skew) + + return result + + +def _angular_acceleration_nonlinear_term(rotvecs, rotvecs_dot): + """Compute the non-linear term in angular acceleration. + + The angular acceleration contains a quadratic term with respect to + the derivative of the rotation vector. This function computes that. + + Parameters + ---------- + rotvecs : ndarray, shape (n, 3) + Set of rotation vectors. + rotvecs_dot : ndarray, shape (n, 3) + Set of rotation vector derivatives. + + Returns + ------- + ndarray, shape (n, 3) + """ + norm = np.linalg.norm(rotvecs, axis=1) + dp = np.sum(rotvecs * rotvecs_dot, axis=1) + cp = np.cross(rotvecs, rotvecs_dot) + ccp = np.cross(rotvecs, cp) + dccp = np.cross(rotvecs_dot, cp) + + k1 = np.empty_like(norm) + k2 = np.empty_like(norm) + k3 = np.empty_like(norm) + + mask = norm > 1e-4 + nm = norm[mask] + k1[mask] = (-nm * np.sin(nm) - 2 * (np.cos(nm) - 1)) / nm ** 4 + k2[mask] = (-2 * nm + 3 * np.sin(nm) - nm * np.cos(nm)) / nm ** 5 + k3[mask] = (nm - np.sin(nm)) / nm ** 3 + + mask = ~mask + nm = norm[mask] + k1[mask] = 1/12 - nm ** 2 / 180 + k2[mask] = -1/60 + nm ** 2 / 12604 + k3[mask] = 1/6 - nm ** 2 / 120 + + dp = dp[:, None] + k1 = k1[:, None] + k2 = k2[:, None] + k3 = k3[:, None] + + return dp * (k1 * cp + k2 * ccp) + k3 * dccp + + +def _compute_angular_rate(rotvecs, rotvecs_dot): + """Compute angular rates given rotation vectors and its derivatives. + + Parameters + ---------- + rotvecs : ndarray, shape (n, 3) + Set of rotation vectors. + rotvecs_dot : ndarray, shape (n, 3) + Set of rotation vector derivatives. + + Returns + ------- + ndarray, shape (n, 3) + """ + return _matrix_vector_product_of_stacks( + _rotvec_dot_to_angular_rate_matrix(rotvecs), rotvecs_dot) + + +def _compute_angular_acceleration(rotvecs, rotvecs_dot, rotvecs_dot_dot): + """Compute angular acceleration given rotation vector and its derivatives. + + Parameters + ---------- + rotvecs : ndarray, shape (n, 3) + Set of rotation vectors. + rotvecs_dot : ndarray, shape (n, 3) + Set of rotation vector derivatives. + rotvecs_dot_dot : ndarray, shape (n, 3) + Set of rotation vector second derivatives. + + Returns + ------- + ndarray, shape (n, 3) + """ + return (_compute_angular_rate(rotvecs, rotvecs_dot_dot) + + _angular_acceleration_nonlinear_term(rotvecs, rotvecs_dot)) + + +def _create_block_3_diagonal_matrix(A, B, d): + """Create a 3-diagonal block matrix as banded. + + The matrix has the following structure: + + DB... + ADB.. + .ADB. + ..ADB + ...AD + + The blocks A, B and D are 3-by-3 matrices. The D matrices has the form + d * I. + + Parameters + ---------- + A : ndarray, shape (n, 3, 3) + Stack of A blocks. + B : ndarray, shape (n, 3, 3) + Stack of B blocks. + d : ndarray, shape (n + 1,) + Values for diagonal blocks. + + Returns + ------- + ndarray, shape (11, 3 * (n + 1)) + Matrix in the banded form as used by `scipy.linalg.solve_banded`. + """ + ind = np.arange(3) + ind_blocks = np.arange(len(A)) + + A_i = np.empty_like(A, dtype=int) + A_i[:] = ind[:, None] + A_i += 3 * (1 + ind_blocks[:, None, None]) + + A_j = np.empty_like(A, dtype=int) + A_j[:] = ind + A_j += 3 * ind_blocks[:, None, None] + + B_i = np.empty_like(B, dtype=int) + B_i[:] = ind[:, None] + B_i += 3 * ind_blocks[:, None, None] + + B_j = np.empty_like(B, dtype=int) + B_j[:] = ind + B_j += 3 * (1 + ind_blocks[:, None, None]) + + diag_i = diag_j = np.arange(3 * len(d)) + i = np.hstack((A_i.ravel(), B_i.ravel(), diag_i)) + j = np.hstack((A_j.ravel(), B_j.ravel(), diag_j)) + values = np.hstack((A.ravel(), B.ravel(), np.repeat(d, 3))) + + u = 5 + l = 5 + result = np.zeros((u + l + 1, 3 * len(d))) + result[u + i - j, j] = values + return result + + +class RotationSpline: + """Interpolate rotations with continuous angular rate and acceleration. + + The rotation vectors between each consecutive orientation are cubic + functions of time and it is guaranteed that angular rate and acceleration + are continuous. Such interpolation are analogous to cubic spline + interpolation. + + Refer to [1]_ for math and implementation details. + + Parameters + ---------- + times : array_like, shape (N,) + Times of the known rotations. At least 2 times must be specified. + rotations : `Rotation` instance + Rotations to perform the interpolation between. Must contain N + rotations. + + Methods + ------- + __call__ + + References + ---------- + .. [1] `Smooth Attitude Interpolation + `_ + + Examples + -------- + >>> from scipy.spatial.transform import Rotation, RotationSpline + >>> import numpy as np + + Define the sequence of times and rotations from the Euler angles: + + >>> times = [0, 10, 20, 40] + >>> angles = [[-10, 20, 30], [0, 15, 40], [-30, 45, 30], [20, 45, 90]] + >>> rotations = Rotation.from_euler('XYZ', angles, degrees=True) + + Create the interpolator object: + + >>> spline = RotationSpline(times, rotations) + + Interpolate the Euler angles, angular rate and acceleration: + + >>> angular_rate = np.rad2deg(spline(times, 1)) + >>> angular_acceleration = np.rad2deg(spline(times, 2)) + >>> times_plot = np.linspace(times[0], times[-1], 100) + >>> angles_plot = spline(times_plot).as_euler('XYZ', degrees=True) + >>> angular_rate_plot = np.rad2deg(spline(times_plot, 1)) + >>> angular_acceleration_plot = np.rad2deg(spline(times_plot, 2)) + + On this plot you see that Euler angles are continuous and smooth: + + >>> import matplotlib.pyplot as plt + >>> plt.plot(times_plot, angles_plot) + >>> plt.plot(times, angles, 'x') + >>> plt.title("Euler angles") + >>> plt.show() + + The angular rate is also smooth: + + >>> plt.plot(times_plot, angular_rate_plot) + >>> plt.plot(times, angular_rate, 'x') + >>> plt.title("Angular rate") + >>> plt.show() + + The angular acceleration is continuous, but not smooth. Also note that + the angular acceleration is not a piecewise-linear function, because + it is different from the second derivative of the rotation vector (which + is a piecewise-linear function as in the cubic spline). + + >>> plt.plot(times_plot, angular_acceleration_plot) + >>> plt.plot(times, angular_acceleration, 'x') + >>> plt.title("Angular acceleration") + >>> plt.show() + """ + # Parameters for the solver for angular rate. + MAX_ITER = 10 + TOL = 1e-9 + + def _solve_for_angular_rates(self, dt, angular_rates, rotvecs): + angular_rate_first = angular_rates[0].copy() + + A = _angular_rate_to_rotvec_dot_matrix(rotvecs) + A_inv = _rotvec_dot_to_angular_rate_matrix(rotvecs) + M = _create_block_3_diagonal_matrix( + 2 * A_inv[1:-1] / dt[1:-1, None, None], + 2 * A[1:-1] / dt[1:-1, None, None], + 4 * (1 / dt[:-1] + 1 / dt[1:])) + + b0 = 6 * (rotvecs[:-1] * dt[:-1, None] ** -2 + + rotvecs[1:] * dt[1:, None] ** -2) + b0[0] -= 2 / dt[0] * A_inv[0].dot(angular_rate_first) + b0[-1] -= 2 / dt[-1] * A[-1].dot(angular_rates[-1]) + + for iteration in range(self.MAX_ITER): + rotvecs_dot = _matrix_vector_product_of_stacks(A, angular_rates) + delta_beta = _angular_acceleration_nonlinear_term( + rotvecs[:-1], rotvecs_dot[:-1]) + b = b0 - delta_beta + angular_rates_new = solve_banded((5, 5), M, b.ravel()) + angular_rates_new = angular_rates_new.reshape((-1, 3)) + + delta = np.abs(angular_rates_new - angular_rates[:-1]) + angular_rates[:-1] = angular_rates_new + if np.all(delta < self.TOL * (1 + np.abs(angular_rates_new))): + break + + rotvecs_dot = _matrix_vector_product_of_stacks(A, angular_rates) + angular_rates = np.vstack((angular_rate_first, angular_rates[:-1])) + + return angular_rates, rotvecs_dot + + def __init__(self, times, rotations): + from scipy.interpolate import PPoly + + if rotations.single: + raise ValueError("`rotations` must be a sequence of rotations.") + + if rotations.as_quat().ndim > 2: + raise ValueError( + "Rotations with more than 1 leading dimension are not supported." + ) + + if len(rotations) == 1: + raise ValueError("`rotations` must contain at least 2 rotations.") + + times = np.asarray(times, dtype=float) + if times.ndim != 1: + raise ValueError("`times` must be 1-dimensional.") + + if len(times) != len(rotations): + raise ValueError("Expected number of rotations to be equal to " + "number of timestamps given, " + f"got {len(rotations)} rotations " + f"and {len(times)} timestamps.") + + dt = np.diff(times) + if np.any(dt <= 0): + raise ValueError("Values in `times` must be in a strictly " + "increasing order.") + + rotvecs = (rotations[:-1].inv() * rotations[1:]).as_rotvec() + angular_rates = rotvecs / dt[:, None] + + if len(rotations) == 2: + rotvecs_dot = angular_rates + else: + angular_rates, rotvecs_dot = self._solve_for_angular_rates( + dt, angular_rates, rotvecs) + + dt = dt[:, None] + coeff = np.empty((4, len(times) - 1, 3)) + coeff[0] = (-2 * rotvecs + dt * angular_rates + + dt * rotvecs_dot) / dt ** 3 + coeff[1] = (3 * rotvecs - 2 * dt * angular_rates + - dt * rotvecs_dot) / dt ** 2 + coeff[2] = angular_rates + coeff[3] = 0 + + self.times = times + self.rotations = rotations + self.interpolator = PPoly(coeff, times) + + def __call__(self, times, order=0): + """Compute interpolated values. + + Parameters + ---------- + times : float or array_like + Times of interest. + order : {0, 1, 2}, optional + Order of differentiation: + + * 0 (default) : return Rotation + * 1 : return the angular rate in rad/sec + * 2 : return the angular acceleration in rad/sec/sec + + Returns + ------- + Interpolated Rotation, angular rate or acceleration. + """ + if order not in [0, 1, 2]: + raise ValueError("`order` must be 0, 1 or 2.") + + times = np.asarray(times, dtype=float) + if times.ndim > 1: + raise ValueError("`times` must be at most 1-dimensional.") + + singe_time = times.ndim == 0 + times = np.atleast_1d(times) + + rotvecs = self.interpolator(times) + if order == 0: + index = np.searchsorted(self.times, times, side='right') + index -= 1 + index[index < 0] = 0 + n_segments = len(self.times) - 1 + index[index > n_segments - 1] = n_segments - 1 + result = self.rotations[index] * Rotation.from_rotvec(rotvecs) + elif order == 1: + rotvecs_dot = self.interpolator(times, 1) + result = _compute_angular_rate(rotvecs, rotvecs_dot) + elif order == 2: + rotvecs_dot = self.interpolator(times, 1) + rotvecs_dot_dot = self.interpolator(times, 2) + result = _compute_angular_acceleration(rotvecs, rotvecs_dot, + rotvecs_dot_dot) + else: + assert False + + if singe_time: + result = result[0] + + return result diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rotation_xp.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rotation_xp.py new file mode 100644 index 0000000000000000000000000000000000000000..007fcf385e3aa560f09ad3509aceb61fa6d33fb5 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/_rotation_xp.py @@ -0,0 +1,1137 @@ +"""Array API backend for the `Rotation` class. + +This module provides generic, functional implementations of the `Rotation` class methods +that work with any Array API-compatible backend. +""" + +# Parts of the implementation are adapted from the cython backend and +# https://github.com/jax-ml/jax/blob/d695aa4c63ffcebefce52794427c46bad576680c/jax/_src/scipy/spatial/transform.py. +import re +import warnings +from types import EllipsisType + +import numpy as np +from scipy._lib._array_api import ( + array_namespace, + Array, + ArrayLike, + is_lazy_array, + xp_vector_norm, + xp_result_type, + xp_promote, + is_jax, +) +from scipy._lib._util import broadcastable +from scipy._lib.array_api_compat import device as xp_device +from scipy._lib.array_api_compat import is_array_api_obj +import scipy._lib.array_api_extra as xpx + + +def from_quat( + quat: Array, + normalize: bool = True, + copy: bool = True, + *, + scalar_first: bool = False, +) -> Array: + xp = array_namespace(quat) + if scalar_first: + quat = xp.roll(quat, -1, axis=-1) + # Normalize will always copy, so we avoid the extra copy if we normalize + if copy and not normalize: + quat = xp.asarray(quat, copy=True) + if normalize: + quat = _normalize_quaternion(quat) + return quat + + +def from_matrix(matrix: Array, assume_valid: bool = False) -> Array: + xp = array_namespace(matrix) + device = xp_device(matrix) + + if not assume_valid: + mask = xp.linalg.det(matrix) <= 0 + lazy = is_lazy_array(mask) + # Only non-lazy backends raise an error for non-positive determinants. + if not lazy and xp.any(mask): + ind = int(xp.nonzero(xpx.atleast_nd(mask, ndim=1, xp=xp))[0][0]) + raise ValueError( + "Non-positive determinant (left-handed or null coordinate frame) in " + f"rotation matrix {ind}: {matrix[ind, ...]}." + ) + elif lazy: + matrix = xp.where(mask[..., None, None], xp.nan, matrix) + + gramians = matrix @ xp.matrix_transpose(matrix) + eye = xp.eye(3, dtype=matrix.dtype, device=device) + is_orthogonal = xp.all( + xpx.isclose(gramians, eye, atol=1e-12, xp=xp), axis=(-2, -1) + ) + + if lazy: + # Lazy backends do not support non-concrete boolean indexing or any form of + # computation without statically known shapes, so we always compute SVD and + # use xp.where to select the result. + U, _, Vt = xp.linalg.svd(matrix, full_matrices=False) + matrix = xp.where(is_orthogonal[..., None, None], matrix, U @ Vt) + elif not xp.all(is_orthogonal): + # For eager frameworks, only compute SVD if needed. + is_not_orthogonal = ~is_orthogonal + U, _, Vt = xp.linalg.svd(matrix[is_not_orthogonal], full_matrices=False) + matrix = xpx.at(matrix)[is_not_orthogonal].set(U @ Vt) + + return _from_matrix_orthogonal(matrix) + + +def _from_matrix_orthogonal(matrix: Array) -> Array: + """Convert known orthogonal rotation matrix to quaternion""" + xp = array_namespace(matrix) + device = xp_device(matrix) + + matrix_trace = matrix[..., 0, 0] + matrix[..., 1, 1] + matrix[..., 2, 2] + decision = xp.stack( + [matrix[..., 0, 0], matrix[..., 1, 1], matrix[..., 2, 2], matrix_trace], + axis=-1, + ) + choice = xp.argmax(decision, axis=-1, keepdims=True) + quat = xp.empty((*matrix.shape[:-2], 4), dtype=matrix.dtype, device=device) + + # The Array API does not support mixing integer indexing with ellipsis, so we cannot + # follow the same pattern as the cython backend. Instead, we compute each case + # explicitly and assemble the final result with `xp.where`. + # TODO: Revisit this implementation if the array API supports mixed integer and + # ellipsis indexing. + + # Case 0 + quat_0 = xp.stack( + [ + 1 - matrix_trace[...] + 2 * matrix[..., 0, 0], + matrix[..., 1, 0] + matrix[..., 0, 1], + matrix[..., 2, 0] + matrix[..., 0, 2], + matrix[..., 2, 1] - matrix[..., 1, 2], + ], + axis=-1, + ) + quat = xp.where(choice == 0, quat_0, quat) + + # Case 1 + quat_1 = xp.stack( + [ + matrix[..., 1, 0] + matrix[..., 0, 1], + 1 - matrix_trace[...] + 2 * matrix[..., 1, 1], + matrix[..., 2, 1] + matrix[..., 1, 2], + matrix[..., 0, 2] - matrix[..., 2, 0], + ], + axis=-1, + ) + quat = xp.where(choice == 1, quat_1, quat) + + # Case 2 + quat_2 = xp.stack( + [ + matrix[..., 2, 0] + matrix[..., 0, 2], + matrix[..., 2, 1] + matrix[..., 1, 2], + 1 - matrix_trace[...] + 2 * matrix[..., 2, 2], + matrix[..., 1, 0] - matrix[..., 0, 1], + ], + axis=-1, + ) + quat = xp.where(choice == 2, quat_2, quat) + + # Case 3 + quat_3 = xp.stack( + [ + matrix[..., 2, 1] - matrix[..., 1, 2], + matrix[..., 0, 2] - matrix[..., 2, 0], + matrix[..., 1, 0] - matrix[..., 0, 1], + 1 + matrix_trace[...], + ], + axis=-1, + ) + quat = xp.where(choice == 3, quat_3, quat) + + return _normalize_quaternion(quat) + + +def from_rotvec(rotvec: Array, degrees: bool = False) -> Array: + xp = array_namespace(rotvec) + if rotvec.shape[-1] != 3: + raise ValueError( + f"Expected `rot_vec` to have shape (..., 3), got {rotvec.shape}" + ) + rotvec = _deg2rad(rotvec) if degrees else rotvec + + angle = xp_vector_norm(rotvec, axis=-1, keepdims=True, xp=xp) + small_angle = angle <= 1e-3 + angle2 = angle**2 + small_scale = 0.5 - angle2 / 48 + angle2**2 / 3840 + # We need to handle the case where angle is 0 to avoid division by zero. We use the + # value of the Taylor series approximation, but non-branching operations require + # that we still divide by the angle. Since we do not use the result where the angle + # is close to 0, this is safe. + div_angle = angle + xp.asarray(small_angle, dtype=angle.dtype) + large_scale = xp.sin(angle / 2) / div_angle + scale = xp.where(small_angle, small_scale, large_scale) + quat = xp.concat([rotvec * scale, xp.cos(angle / 2)], axis=-1) + return quat + + +def from_mrp(mrp: Array) -> Array: + xp = array_namespace(mrp) + if mrp.shape[-1] != 3: + raise ValueError(f"Expected `mrp` to have shape (..., 3), got {mrp.shape}") + mrp2_plus_1 = xp.linalg.vecdot(mrp, mrp, axis=-1)[..., None] + 1 + q_no_norm = xp.concat([2 * mrp[..., :3], (2 - mrp2_plus_1)], axis=-1) + quat = q_no_norm / mrp2_plus_1 + return quat + + +def from_euler(seq: str, angles: Array, degrees: bool = False) -> Array: + xp = array_namespace(angles) + num_axes = len(seq) + if num_axes < 1 or num_axes > 3: + raise ValueError( + "Expected axis specification to be a non-empty " + f"string of up to 3 characters, got {seq}" + ) + + intrinsic = re.match(r"^[XYZ]{1,3}$", seq) is not None + extrinsic = re.match(r"^[xyz]{1,3}$", seq) is not None + if not (intrinsic or extrinsic): + raise ValueError( + "Expected axes from `seq` to be from ['x', 'y', " + f"'z'] or ['X', 'Y', 'Z'], got {seq}" + ) + + if any(seq[i] == seq[i + 1] for i in range(num_axes - 1)): + raise ValueError(f"Expected consecutive axes to be different, got {seq}") + + if degrees: + angles = _deg2rad(angles) + + angles = xpx.atleast_nd(angles, ndim=1, xp=xp) + + if angles.shape[-1] != num_axes: + raise ValueError( + "Expected last dimension of `angles` to match number of sequence axes " + f"specified, got {angles.shape[-1]}." + ) + axes = [_elementary_basis_index(x) for x in seq.lower()] + q = _elementary_quat_compose(axes, angles, intrinsic) + return q + + +def from_davenport( + axes: Array, order: str, angles: Array | float, degrees: bool = False +) -> Array: + xp = array_namespace(axes) + device = xp_device(axes) + if order in ["e", "extrinsic"]: # Must be static, cannot be jitted + extrinsic = True + elif order in ["i", "intrinsic"]: + extrinsic = False + else: + raise ValueError( + "order should be 'e'/'extrinsic' for extrinsic sequences or 'i'/" + f"'intrinsic' for intrinsic sequences, got {order}" + ) + + if axes.shape[-1] != 3: + raise ValueError("Axes must be vectors of length 3.") + + axes = xpx.atleast_nd(axes, ndim=2, xp=xp) + angles = xpx.atleast_nd(angles, ndim=1, xp=xp) + num_axes = axes.shape[-2] + if num_axes < 1 or num_axes > 3: + raise ValueError(f"Expected up to 3 axes, got {num_axes}") + + axes = axes / xp_vector_norm(axes, axis=-1, keepdims=True, xp=xp) + + # Check if axes are orthogonal. Shape checks also work for lazy backends. + axes_not_orthogonal = xp.zeros(axes.shape[:-2], dtype=xp.bool, device=device) + if num_axes > 1: + # Cannot be True yet, so we do not need to use xp.logical_or + axes_not_orthogonal = axes_not_orthogonal | ( + xp.abs(xp.vecdot(axes[..., 0, :], axes[..., 1, :])) > 1e-7 + ) + if num_axes > 2: + axes_not_orthogonal = axes_not_orthogonal | ( + xp.abs(xp.vecdot(axes[..., 1, :], axes[..., 2, :])) > 1e-7 + ) + if not is_lazy_array(axes_not_orthogonal) and xp.any(axes_not_orthogonal): + raise ValueError("Consecutive axes must be orthogonal.") + else: + axes = xp.where(axes_not_orthogonal[..., None, None], xp.nan, axes) + + if degrees: + angles = _deg2rad(angles) + + if ( + not broadcastable(axes.shape[:-1], angles.shape) + or axes.shape[-2] != angles.shape[-1] + ): + raise ValueError( + f"Expected `angles` to match number of axes, got {angles.shape} angles " + f"and {axes.shape} axes." + ) + + q_shape = angles.shape[:-1] + (4,) + q = xp.zeros(q_shape, dtype=angles.dtype, device=xp_device(angles)) + q = xpx.at(q)[..., 3].set(1) + + for i in range(num_axes): + qi = from_rotvec(angles[..., i, None] * axes[..., i, :]) + q = compose_quat(qi, q) if extrinsic else compose_quat(q, qi) + return q + + +def as_quat( + quat: Array, canonical: bool = False, *, scalar_first: bool = False +) -> Array: + xp = array_namespace(quat) + if canonical: + quat = _quat_canonical(quat) + if scalar_first: + quat = xp.roll(quat, 1, axis=-1) + return quat + + +def as_matrix(quat: Array) -> Array: + xp = array_namespace(quat) + x = quat[..., 0] + y = quat[..., 1] + z = quat[..., 2] + w = quat[..., 3] + + x2 = x * x + y2 = y * y + z2 = z * z + w2 = w * w + + xy = x * y + zw = z * w + xz = x * z + yw = y * w + yz = y * z + xw = x * w + + matrix_elements = [ + x2 - y2 - z2 + w2, + 2 * (xy - zw), + 2 * (xz + yw), + 2 * (xy + zw), + -x2 + y2 - z2 + w2, + 2 * (yz - xw), + 2 * (xz - yw), + 2 * (yz + xw), + -x2 - y2 + z2 + w2, + ] + matrix = xp.reshape(xp.stack(matrix_elements, axis=-1), (*quat.shape[:-1], 3, 3)) + return matrix + + +def as_rotvec(quat: Array, degrees: bool = False) -> Array: + xp = array_namespace(quat) + quat = _quat_canonical(quat) + ax_norm = xp_vector_norm(quat[..., :3], axis=-1, keepdims=True, xp=xp) + angle = 2 * xp.atan2(ax_norm, quat[..., 3][..., None]) + small_angle = angle <= 1e-3 + angle2 = angle**2 + small_scale = 2 + angle2 / 12 + 7 * angle2**2 / 2880 + # We need to handle the case where sin(angle/2) is 0 to avoid division by zero. We + # use the value of the Taylor series approximation, but non-branching operations + # require that we still divide by the sin. Since we do not use the result where the + # angle is close to 0, adding one to the sin where we discard the result is safe. + div_sin = xp.sin(angle / 2.0) + xp.asarray(small_angle, dtype=angle.dtype) + large_scale = angle / div_sin + scale = xp.where(small_angle, small_scale, large_scale) + if degrees: + scale = _rad2deg(scale) + rotvec = scale * quat[..., :3] + return rotvec + + +def as_mrp(quat: Array) -> Array: + xp = array_namespace(quat) + one = xp.asarray(1.0, device=xp_device(quat), dtype=quat.dtype) + sign = xp.where(quat[..., 3, None] < 0, -1, one) + denominator = 1.0 + sign * quat[..., 3, None] + return sign * quat[..., :3] / denominator + + +def as_euler( + quat: Array, seq: str, degrees: bool = False, *, suppress_warnings: bool = False +) -> Array: + xp = array_namespace(quat) + + # Sanitize the sequence + if len(seq) != 3: + raise ValueError(f"Expected 3 axes, got {seq}.") + intrinsic = re.match(r"^[XYZ]{1,3}$", seq) is not None + extrinsic = re.match(r"^[xyz]{1,3}$", seq) is not None + if not (intrinsic or extrinsic): + raise ValueError( + "Expected axes from `seq` to be from ['x', 'y', 'z'] or ['X', 'Y', 'Z'], " + f"got {seq}" + ) + if any(seq[i] == seq[i + 1] for i in range(2)): + raise ValueError(f"Expected consecutive axes to be different, got {seq}") + + device = xp_device(quat) + axes = [_elementary_basis_index(x) for x in seq.lower()] + axes = axes if extrinsic else axes[::-1] + i, j, k = axes + symmetric = i == k + k = 3 - i - j if symmetric else k + + mask = xp.asarray(symmetric, device=device) + sign = xp.asarray((i - j) * (j - k) * (k - i) // 2, dtype=quat.dtype, device=device) + # Permute quaternion elements + a = xp.where(mask, quat[..., 3], quat[..., 3] - quat[..., j]) + b = xp.where(mask, quat[..., i], quat[..., i] + quat[..., k] * sign) + c = xp.where(mask, quat[..., j], quat[..., j] + quat[..., 3]) + d = xp.where(mask, quat[..., k] * sign, quat[..., k] * sign - quat[..., i]) + + angles = _get_angles( + extrinsic, symmetric, sign, xp.pi / 2, a, b, c, d, suppress_warnings + ) + return _rad2deg(angles) if degrees else angles + + +def as_davenport( + quat: Array, + axes: ArrayLike, + order: str, + degrees: bool = False, + *, + suppress_warnings: bool = False, +) -> Array: + xp = array_namespace(quat) + + # Check argument validity + if order in ["e", "extrinsic"]: + extrinsic = True + elif order in ["i", "intrinsic"]: + extrinsic = False + else: + raise ValueError( + "order should be 'e'/'extrinsic' for extrinsic sequences or 'i'/'intrinsic'" + f" for intrinsic sequences, got {order}" + ) + if axes.shape[-2] != 3: + raise ValueError(f"Expected 3 axes, got {axes.shape}.") + if axes.shape[-1] != 3: + raise ValueError("Axes must be vectors of length 3.") + if not broadcastable(axes.shape[:-2], quat.shape[:-1]): + raise ValueError( + f"Expected `axes` to match number of rotations, got {axes.shape} axes " + f"and {quat.shape} rotations." + ) + + # normalize axes + axes = axes / xp_vector_norm(axes, axis=-1, keepdims=True, xp=xp) + vdot_ax0_ax1 = xp.vecdot(axes[..., 0, :], axes[..., 1, :]) + vdot_ax1_ax2 = xp.vecdot(axes[..., 1, :], axes[..., 2, :]) + is_invalid = (vdot_ax0_ax1 >= 1e-7) | (vdot_ax1_ax2 >= 1e-7) + if is_lazy_array(is_invalid): + axes = xp.where(is_invalid[..., None, None], xp.nan, axes) + elif xp.any(is_invalid): + raise ValueError("Consecutive axes must be orthogonal.") + + angles = _compute_davenport_from_quat( + quat, + axes[..., 0, :], + axes[..., 1, :], + axes[..., 2, :], + extrinsic, + suppress_warnings, + ) + if degrees: + angles = _rad2deg(angles) + return angles + + +def inv(quat: Array) -> Array: + return xpx.at(quat)[..., :3].multiply(-1, copy=True) + + +def magnitude(quat: Array) -> Array: + xp = array_namespace(quat) + sin_q = xp_vector_norm(quat[..., :3], axis=-1, xp=xp) + cos_q = xp.abs(quat[..., 3]) + angles = 2 * xp.atan2(sin_q, cos_q) + return angles + + +def approx_equal( + quat: Array, other: Array, atol: float | None = None, degrees: bool = False +) -> Array: + if atol is None: + if degrees: + warnings.warn( + "atol must be set to use the degrees flag, defaulting to 1e-8 radians.", + stacklevel=2, + ) + atol = 1e-8 + elif degrees: + atol = _deg2rad(atol) + + if not broadcastable(quat.shape, other.shape): + raise ValueError( + f"Expected broadcastable shapes in both rotations, got {quat.shape[:-1]} " + f"rotations in first and {other.shape[:-1]} rotations in second object." + ) + + quat_result = compose_quat(other, inv(quat)) + angles = magnitude(quat_result) + return angles < atol + + +def mean( + quat: Array, + weights: ArrayLike | None = None, + axis: None | int | tuple[int, ...] = None, +) -> Array: + xp = array_namespace(quat) + device = xp_device(quat) + dtype = xp_result_type(quat, force_floating=True, xp=xp) + if quat.shape[0] == 0: + raise ValueError("Mean of an empty rotation set is undefined.") + # Axis logic: For None, we reduce over all axes. For int, we only reduce over that + # axis. For tuple, we reduce over all specified axes. + all_axes = tuple(range(quat.ndim - 1)) + if axis is None: + axis = all_axes + elif isinstance(axis, int): + axis = (axis,) + if not isinstance(axis, tuple): + raise ValueError("`axis` must be None, int, or tuple of ints.") + # Ensure all axes are within bounds + if axis != () and (min(axis) < -(quat.ndim - 1) or max(axis) > (quat.ndim - 2)): + raise ValueError( + f"axis {axis} is out of bounds for rotation with shape {quat.shape[:-1]}." + ) + # Ensure all axes are positive and unique + axis = tuple(sorted(set(x % (quat.ndim - 1) for x in axis))) + + lazy = is_lazy_array(quat) + # Branching code is okay for checks that include meta info such as shapes and types + quat_expand = quat[..., None, :] + if weights is None: + K = xp.matrix_transpose(quat_expand) @ quat_expand + else: + weights = xp.asarray(weights, dtype=dtype, device=device) + neg_weights = weights < 0 + if not lazy and xp.any(neg_weights): + raise ValueError("`weights` must be non-negative.") + elif lazy: + # We cannot check for negative weights because jit code needs to be + # non-branching. We return NaN instead + weights = xp.where(neg_weights, xp.nan, weights) + + if not broadcastable(quat.shape[:-1], weights.shape): + raise ValueError( + "Expected `weights` to be broadcastable to rotation shape, got shape " + f"{weights.shape} for {quat.shape[:-1]} rotations." + ) + + # Make sure we can transpose quat + weighted_quat = weights[..., None, None] * quat_expand + K = xp.matrix_transpose(weighted_quat) @ quat_expand + + # Move reduction axes to the end + keep_axes = tuple(i for i in all_axes if i not in axis) + axes_order = keep_axes + axis + K_reordered = xp.moveaxis(K, axes_order, all_axes) + # Reshape to flatten reduction axes + new_shape = K_reordered.shape[: len(keep_axes)] + (-1, 4, 4) + K = xp.mean(xp.reshape(K_reordered, new_shape), axis=-3) + _, v = xp.linalg.eigh(K) + return v[..., -1] + + +def reduce( + quat: Array, + left: Array | None = None, + right: Array | None = None, +) -> tuple[Array, Array | None, Array | None]: + if left is None and right is None: + return quat, None, None + # DECISION: We cannot have variable number of return arguments for jit compiled + # functions. We therefore always return the indices, and filter out later. + # TOOD: Properly support broadcasting. + xp = array_namespace(quat) + quat = xpx.atleast_nd(quat, ndim=2, xp=xp) + if left is None: + left = xp.ones_like(quat) + if right is None: + right = xp.ones_like(quat) + + # We want to calculate the real components of q = l * p * r. It can + # be shown that: + # qs = ls * ps * rs - ls * dot(pv, rv) - ps * dot(lv, rv) + # - rs * dot(lv, pv) - dot(cross(lv, pv), rv) + # where ls and lv denote the scalar and vector components of l. + + p = quat + ps, pv = _split_rotation(p, xp) + ls, lv = _split_rotation(left, xp) + rs, rv = _split_rotation(right, xp) + + # Compute each term without einsum (not accessible in the Array API) + # First term: np.einsum("i,j,k", ls, ps, rs) + term1 = ls[..., :, None, None] * ps[..., None, :, None] * rs[..., None, None, :] + # Second term: np.einsum('i,jx,kx', ls, pv, rv) + prv = xp.sum(pv[..., :, None, :] * rv[..., None, :, :], axis=-1) + term2 = ls[..., :, None, None] * prv[..., None, :, :] + # Third term: np.einsum('ix,j,kx', lv, ps, rv) + lrv = xp.sum(lv[..., :, None, :] * rv[..., None, :, :], axis=-1) + term3 = ps[..., None, :, None] * lrv[..., :, None, :] + # Fourth term: np.einsum('ix,jx,k', lv, pv, rs) + lpv = xp.sum(lv[..., :, None, :] * pv[..., None, :, :], axis=-1) + term4 = rs[..., None, None, :] * lpv[..., :, :, None] + # Fifth term: np.einsum('xyz,ix,jy,kz', e, lv, pv, rv). We want to avoid expanding + # the einsum into a 6D tensor to avoid excessive memory usage. Instead, we compute + # the cross product between lv and pv and then compute the dot product with rv. + # First compute cross products between lv and pv + lv_expanded = lv[..., :, None, :] + pv_expanded = pv[..., None, :, :] + cross_lp = xp.linalg.cross(lv_expanded, pv_expanded) + # Then compute dot product with rv + term5 = xp.sum(cross_lp[..., :, :, None, :] * rv[..., None, None, :, :], axis=-1) + # Combine all terms with proper shape alignment + qs = xp.abs(term1 - term2 - term3 - term4 - term5) + qs = xp.reshape(xp.moveaxis(qs, 1, 0), (qs.shape[1], -1)) + + # Find best indices from scalar components + max_ind = xp.argmax(xp.reshape(qs, (qs.shape[0], -1)), axis=1) + left_best = max_ind // rv.shape[0] + right_best = max_ind % rv.shape[0] + # Array API limitation: Integer index arrays are only allowed with integer indices + # TODO: Can we somehow avoid this? + all_idx = xp.reshape(xp.arange(left.shape[-1]), (1, -1)) + left_idx = xp.reshape(left_best, (-1, 1)) + left = left[left_idx, all_idx] + right_idx = xp.reshape(right_best, (-1, 1)) + right = right[right_idx, all_idx] + + # Reduce the rotation using the best indices + reduced = compose_quat(left, compose_quat(p, right)) + + if left is None: + left_best = None + if right is None: + right_best = None + return reduced, left_best, right_best + + +def apply(quat: Array, points: Array, inverse: bool = False) -> Array: + xp = array_namespace(quat) + mat = as_matrix(quat) + # We do not have access to einsum. To avoid broadcasting issues, we add a singleton + # dimension to the points array and remove it after the operation. + points = points[..., None] + if not broadcastable(mat.shape, points.shape): + raise ValueError( + f"Cannot broadcast {quat.shape[:-1]} rotations to {points.shape[:-1]} " + "vectors." + ) + if inverse: + # TODO: Replace with .mT once numpy 2.0 is the minimum supported version + return (xp.matrix_transpose(mat) @ points)[..., 0] + return (mat @ points)[..., 0] + + +def setitem( + quat: Array, value: Array, indexer: int | slice | EllipsisType | None +) -> Array: + return xpx.at(quat)[indexer, ...].set(value) + + +def align_vectors( + a: Array, b: Array, weights: Array | None = None, return_sensitivity: bool = False +) -> tuple[Array, Array, Array]: + xp = array_namespace(a) + # Check input vectors + dtype = xp_result_type(a, b, force_floating=True, xp=xp) + a_original = xp.asarray(a, dtype=dtype) + b_original = xp.asarray(b, dtype=dtype) + a = xpx.atleast_nd(a_original, ndim=2, xp=xp) + b = xpx.atleast_nd(b_original, ndim=2, xp=xp) + if a.shape[-1] != 3: + raise ValueError( + f"Expected input `a` to have shape (3,) or (N, 3), got {a_original.shape}" + ) + if b.shape[-1] != 3: + raise ValueError( + f"Expected input `b` to have shape (3,) or (N, 3), got {b_original.shape}" + ) + if a.shape != b.shape: + raise ValueError( + "Expected inputs `a` and `b` to have same shapes" + f", got {a_original.shape} and {b_original.shape} respectively." + ) + if a.ndim > 2 or b.ndim > 2: # This function does not support broadcasting + raise ValueError( + "Expected inputs `a` and `b` to have shape (3,) or (N, 3), got " + f"{a_original.shape} and {b_original.shape} respectively." + ) + N = a.shape[0] + + # Check weights + if weights is None: + weights = xp.ones(N, device=xp_device(a), dtype=a.dtype) + else: + weights = xp.asarray(weights, device=xp_device(a), dtype=a.dtype) + if weights.ndim != 1: + raise ValueError( + f"Expected `weights` to be 1 dimensional, got shape {weights.shape}." + ) + if N > 1 and (weights.shape[0] != N): + raise ValueError( + "Expected `weights` to have number of values equal to number of input " + f"vectors, got {weights.shape[0]} values and {N} vectors." + ) + # We can only check for negative weights in eager execution models. Lazy + # backends will return NaNs instead. + negative_weights = weights < 0 + if not is_lazy_array(negative_weights) and xp.any(negative_weights): + raise ValueError("`weights` may not contain negative values") + weights = xp.where(negative_weights, xp.nan, weights) + + # For the special case of a single vector pair, we use the infinite + # weight code path + weight_is_inf = xp.asarray([True]) if N == 1 else weights == xp.inf + n_inf = xp.sum(xp.astype(weight_is_inf, a.dtype)) + # We can only error out on multiple infinite weights or sensitivity return with + # infinite weights in eager execution models. Lazy backends will return NaNs. + if not is_lazy_array(n_inf): + if n_inf > 1: + raise ValueError("Only one infinite weight is allowed") + if n_inf == 1 and return_sensitivity: + raise ValueError( + "Cannot return sensitivity matrix with an " + "infinite weight or one vector pair" + ) + + weights = xp.where(n_inf > 1, xp.nan, weights) + + inf_branch = xp.any(weight_is_inf, axis=-1) + # DECISION: We cannot compute both branches for all frameworks. There are two main + # reasons: + # 1. Computing both for eager execution models is expensive. + # 2. Some operations will fail when running the unused branch because of numerical + # and algorithmical issues. Numpy e.g. will raise an exception when trying to + # compute the svd of a matrix with infinite weights. To prevent this, we only + # compute the branch that is needed. Lazy backends however require us to take the + # full compute graph. Therefore, we use xp.where for lazy backends and a branching + # version for eager frameworks. + # + # Note that we could also solve this by exploiting the externals of xpx.apply_where. + # However, we'd have to rely on the implementation details of apply_where, which is + # something we should avoid. + # See https://github.com/scipy/scipy/pull/22777#discussion_r2028868364 + if is_lazy_array(inf_branch): + q_opt, rssd, sensitivity = _align_vectors(a, b, weights) + q_opt_inf, rssd_inf, sensitivity_inf = _align_vectors_fixed(a, b, weights) + q_opt = xp.where(inf_branch, q_opt_inf, q_opt) + rssd = xp.where(inf_branch, rssd_inf, rssd) + sensitivity = xp.where(inf_branch, sensitivity_inf, sensitivity) + else: + if xp.any(inf_branch): + q_opt, rssd, sensitivity = _align_vectors_fixed(a, b, weights) + else: + q_opt, rssd, sensitivity = _align_vectors(a, b, weights) + return q_opt, rssd, sensitivity + + +def _align_vectors(a: Array, b: Array, weights: Array) -> tuple[Array, Array, Array]: + xp = array_namespace(a) + device = xp_device(a) + B = (weights[:, None] * a).mT @ b + u, s, vh = xp.linalg.svd(B) + + # Correct improper rotation if necessary (as in Kabsch algorithm) + neg_det = xp.linalg.det(u @ vh) < 0 + s = xpx.at(s)[..., -1].set(xp.where(neg_det, -s[..., -1], s[..., -1])) + u = xpx.at(u)[..., :, -1].set(xp.where(neg_det, -u[..., :, -1], u[..., :, -1])) + + C = u @ vh + + # DECISION: We cannot branch on the condition because jit code needs to be + # non-branching. Hence, we omit the check for uniqueness + # (s[1] + s[2] < 1e-16 * s[0]) + ssd = xp.sum(weights * xp.sum(b**2 + a**2, axis=-1), axis=-1) - 2 * xp.sum( + s, axis=-1 + ) + rssd = xp.sqrt(xp.maximum(ssd, xp.zeros(1, device=device)))[..., 0] + + # TODO: We currently need to always compute the sensitivity matrix because lazy code + # needs to be non-branching. We should check if compilers can optimize the where + # statement (e.g. in jax) and check if we can have an eager version that only + # evaluates the branch that is needed. + # See xpx.apply_where, issue: https://github.com/data-apis/array-api-extra/pull/141 + zeta = (s[..., 0] + s[..., 1]) * (s[..., 1] + s[..., 2]) * (s[..., 2] + s[..., 0]) + kappa = s[..., 0] * s[..., 1] + s[..., 1] * s[..., 2] + s[..., 2] * s[..., 0] + eye = xp.eye(3, dtype=a.dtype, device=device) + sensitivity = xp.mean(weights) / zeta * (kappa * eye + B @ B.mT) + q_opt = _from_matrix_orthogonal(C) + return q_opt, rssd, sensitivity + + +def _align_vectors_fixed( + a: Array, b: Array, weights: Array +) -> tuple[Array, Array, Array]: + xp = array_namespace(a) + device = xp_device(a) + N = a.shape[0] + weight_is_inf = xp.asarray([True], device=device) if N == 1 else weights == xp.inf + # We cannot use boolean masks for indexing because of jax. For the same reason, we + # also cannot use dynamic slices. As a workaround, we roll the array so that the + # infinitely weighted vector is at index 0. We then use static slices to get the + # primary and secondary vectors. + # + # Note that argmax fulfils a secondary purpose here: + # When we trace this function with jax, this function might get executed even if + # weight_is_inf does not have a single valid entry. Argmax will still give us a + # valid index which allows us to proceed with the function (the results are + # discarded anyways), whereas boolean indexing would result in invalid, zero-shaped + # arrays. + + inf_idx = xp.argmax(xp.astype(weight_is_inf, xp.uint8)) + # xp.argmax returns an Array, but the specification of xp.roll does not support + # Arrays as shifts. For lazy execution models we cannot convert to int because this + # raises a concretization error. However, jax does accept Arrays as shifts which + # allows jit compiling the function. Hence we do not convert to int for jax. + # See https://github.com/data-apis/array-api/issues/914#issuecomment-2918959918 + if not is_jax(xp): + inf_idx = int(inf_idx) + a_sorted = xp.roll(a, shift=-inf_idx, axis=0) + b_sorted = xp.roll(b, shift=-inf_idx, axis=0) + weights_sorted = xp.roll(weights, shift=-inf_idx, axis=0) + + a_pri = a_sorted[0, ...][None, ...] # Effectively [[0], ...] + b_pri = b_sorted[0, ...][None, ...] + a_pri_norm = xp_vector_norm(a_pri, axis=-1, keepdims=True, xp=xp) + b_pri_norm = xp_vector_norm(b_pri, axis=-1, keepdims=True, xp=xp) + if not is_lazy_array(a_pri_norm): + if xp.any(a_pri_norm == 0) or xp.any(b_pri_norm == 0): + raise ValueError("Cannot align zero length primary vectors") + + # We cannot error out on zero length vectors. We set the norm to NaN to avoid + # division by zero and mark the result as invalid. + a_pri_norm = xpx.at(a_pri_norm)[a_pri_norm == 0].set(xp.nan) + b_pri_norm = xpx.at(b_pri_norm)[b_pri_norm == 0].set(xp.nan) + + a_pri = a_pri / a_pri_norm + b_pri = b_pri / b_pri_norm + + # We first find the minimum angle rotation between the primary + # vectors. + cross = xp.linalg.cross(b_pri[..., 0, :], a_pri[..., 0, :]) + cross_norm = xp_vector_norm(cross, axis=-1, xp=xp) + theta = xp.atan2(cross_norm, xp.sum(a_pri[..., 0, :] * b_pri[..., 0, :], axis=-1)) + tolerance = 1e-3 # tolerance for small angle approximation (rad) + q_flip = xp.asarray([0.0, 0.0, 0.0, 1.0], dtype=a_pri.dtype, device=device) + + # Near pi radians, the Taylor series approximation of x/sin(x) diverges, so for + # numerical stability we flip pi and then rotate back by the small angle pi - theta + flip = xp.pi - theta < tolerance + # For antiparallel vectors, cross = [0, 0, 0] so we need to manually set an + # arbitrary orthogonal axis of rotation + i = xp.argmin(xp.abs(a_pri[..., 0, :])) + # TODO: Array API does not support fancy indexing __setitem__. The code is + # equivalent to doing the following: + # r_components = xp.zeros(3) + # r_components = xpx.at(r_components)[i - 1].set(a_pri[0, i - 2]) + # r_components = xpx.at(r_components)[i - 2].set(-a_pri[0, i - 1]) + r_components = xp.stack( + [ + xp.where(i == 1, a_pri[0, 2], xp.where(i == 2, -a_pri[0, 1], 0)), + xp.where(i == 2, a_pri[0, 0], xp.where(i == 0, -a_pri[0, 2], 0)), + xp.where(i == 0, a_pri[0, 1], xp.where(i == 1, -a_pri[0, 0], 0)), + ] + ) + r = xp.where(cross_norm == 0, r_components, cross) + + q_flip = xp.where(flip, from_rotvec(r / xp_vector_norm(r, xp=xp) * xp.pi), q_flip) + theta = xp.where(flip, xp.pi - theta, theta) + cross = xp.where(flip, -cross, cross) + + # Small angle Taylor series approximation for numerical stability + theta2 = theta * theta + small_scale = xp.abs(theta) < tolerance + r_small_scale = cross * (1 + theta2 / 6 + theta2 * theta2 * 7 / 360) + # We need to handle the case where theta is 0 to avoid division by zero. We use the + # value of the Taylor series approximation, but non-branching operations require + # that we still divide by the angle. Since we do not use the result where the angle + # is close to 0, this is safe. + theta = theta + xp.asarray(small_scale, dtype=theta.dtype) + r_large_scale = cross * theta / xp.sin(theta) + r = xp.where(small_scale, r_small_scale, r_large_scale) + q_pri = compose_quat(from_rotvec(r), q_flip) + + # Case 1): No secondary vectors, q_opt is q_pri -> Immediately done + # Case 2): Secondary vectors exist + # We cannot use boolean masks here because of jax + a_sec = a_sorted[1:, ...] + b_sec = b_sorted[1:, ...] + weights_sec = weights_sorted[1:] + + # We apply the first rotation to the b vectors to align the + # primary vectors, resulting in vectors c. The secondary + # vectors must now be rotated about that primary vector to best + # align c to a. + c_sec = apply(q_pri, b_sec) + + # Calculate vector components for the angle calculation. The + # angle phi to rotate a single 2D vector C to align to 2D + # vector A in the xy plane can be found with the equation + # phi = atan2(cross(C, A), dot(C, A)) + # = atan2(|C|*|A|*sin(phi), |C|*|A|*cos(phi)) + # The below equations perform the same operation, but with the + # 3D rotation restricted to the 2D plane normal to a_pri, where + # the secondary vectors are projected into that plane. We then + # find the composite angle from the weighted sum of the + # axial components in that plane, minimizing the 2D alignment + # problem. + sin_term = xp.linalg.vecdot(xp.linalg.cross(c_sec, a_sec), a_pri) + cos_term = xp.linalg.vecdot(c_sec, a_sec) - ( + xp.linalg.vecdot(c_sec, a_pri) * xp.linalg.vecdot(a_sec, a_pri) + ) + phi = xp.atan2(xp.sum(weights_sec * sin_term), xp.sum(weights_sec * cos_term)) + q_sec = from_rotvec(phi * a_pri[0, ...]) + + # Compose these to get the optimal rotation + q_opt = q_pri if N == 1 else compose_quat(q_sec, q_pri) + + # Calculate the root sum squared distance. We force the error to + # be zero for the infinite weight vectors since they will align + # exactly. + mask = ((N > 1) | (weights[0] == xp.inf)) & weight_is_inf + # Skip non-infinite weight single vectors pairs, we used the + # infinite weight code path but don't want to zero that weight + weights_inf_zero = xpx.at(weights, mask).set(0, copy=True, xp=xp) + a_est = apply(q_opt, b) + rssd = xp.sqrt(xp.sum(weights_inf_zero @ (a - a_est) ** 2)) + + mask = xp.any(xp.isnan(weights), axis=-1) + q_opt = xp.where(mask, xp.nan, q_opt) + return q_opt, rssd, xp.asarray(xp.nan, device=device) + + +def pow(quat: Array, n: float | Array) -> Array: + xp = array_namespace(quat) + device = xp_device(quat) + # If n is an array, we sanitize it to a scalar and promote quat and n to + # the same dtype. + if is_array_api_obj(n): + if n.shape == (1,): + n = n[0] + elif n.ndim != 0: + raise ValueError("Array exponent must be a scalar") + quat, n = xp_promote(quat, n, force_floating=True, xp=xp) + + # If n is a lazy array, we cannot take fast paths for special cases. + if is_lazy_array(n): + result = from_rotvec(n * as_rotvec(quat)) # general scaling of rotation angle + # Special cases 0 -> identity, -1 -> inv, 1 -> copy + identity = xp.zeros((*quat.shape[:-1], 4), dtype=quat.dtype, device=device) + identity = xpx.at(identity)[..., 3].set(1) + result = xp.where(n == 0, identity, result) + result = xp.where(n == -1, inv(quat), result) + result = xp.where(n == 1, quat, result) + return result + if n == 0: + identity = xp.zeros((*quat.shape[:-1], 4), dtype=quat.dtype, device=device) + return xpx.at(identity)[..., 3].set(1) + if n == -1: + return inv(quat) + if n == 1: + return quat + return from_rotvec(n * as_rotvec(quat)) + + +def _normalize_quaternion(quat: Array) -> Array: + xp = array_namespace(quat) + quat_norm = xp_vector_norm(quat, axis=-1, keepdims=True, xp=xp) + zero_norm = quat_norm == 0 + if is_lazy_array(quat_norm): + quat = xp.where(zero_norm, xp.nan, quat) + elif xp.any(zero_norm): + raise ValueError("Found zero norm quaternions in `quat`.") + return quat / quat_norm + + +def _quat_canonical(quat: Array) -> Array: + xp = array_namespace(quat) + mask = quat[..., 3] < 0 + zero_w = quat[..., 3] == 0 + mask = mask | (zero_w & (quat[..., 0] < 0)) + zero_wx = zero_w & (quat[..., 0] == 0) + mask = mask | (zero_wx & (quat[..., 1] < 0)) + zero_wxy = zero_wx & (quat[..., 1] == 0) + mask = mask | (zero_wxy & (quat[..., 2] < 0)) + return xp.where(mask[..., None], -quat, quat) + + +def _elementary_basis_index(axis: str) -> int: + if axis == "x": + return 0 + elif axis == "y": + return 1 + elif axis == "z": + return 2 + raise ValueError(f"Expected axis to be from ['x', 'y', 'z'], got {axis}") + + +def _compute_davenport_from_quat( + quat: Array, + n1: Array, + n2: Array, + n3: Array, + extrinsic: bool, + suppress_warnings: bool, +) -> Array: + # The algorithm assumes extrinsic frame transformations. The algorithm + # in the paper is formulated for rotation quaternions, which are stored + # directly by Rotation. + # Adapt the algorithm for our case by reversing both axis sequence and + # angles for intrinsic rotations when needed + xp = array_namespace(quat) + n1, n3 = (n1, n3) if extrinsic else (n3, n1) + + n_cross = xp.linalg.cross(n1, n2) + lamb = xp.atan2(xp.vecdot(n3, n_cross), xp.vecdot(n3, n1)) + + # alternative set of angles compatible with as_euler implementation + mask = lamb < 0 + n2 = xp.where(mask[..., None], -n2, n2) + lamb = xp.where(mask, -lamb, lamb) + n_cross = xp.where(mask[..., None], -n_cross, n_cross) + correct_set = mask + + quat_lamb = xp.concat( + (xp.sin(lamb / 2)[..., None] * n2, xp.cos(lamb / 2)[..., None]), axis=-1 + ) + + q_trans = compose_quat(quat_lamb, quat) + a = q_trans[..., 3] + b = xp.linalg.vecdot(q_trans[..., :3], n1) + c = xp.linalg.vecdot(q_trans[..., :3], n2) + d = xp.linalg.vecdot(q_trans[..., :3], n_cross) + + angles = _get_angles(extrinsic, False, 1, lamb, a, b, c, d, suppress_warnings) + angles = xpx.at(angles)[..., 1].set( + xp.where(correct_set, -angles[..., 1], angles[..., 1]) + ) + + return angles + + +def _elementary_quat_compose(axes: list[int], angles: Array, intrinsic: bool) -> Array: + xp = array_namespace(angles) + device = xp_device(angles) + quat = _make_elementary_quat(axes[0], angles[..., 0], device=device, xp=xp) + for i in range(1, len(axes)): + ax_quat = _make_elementary_quat(axes[i], angles[..., i], device=device, xp=xp) + quat = compose_quat(quat, ax_quat) if intrinsic else compose_quat(ax_quat, quat) + return quat + + +def _make_elementary_quat(axis: int, angle: Array, device, xp) -> Array: + quat = xp.zeros((*angle.shape, 4), dtype=angle.dtype, device=device) + quat = xpx.at(quat)[..., 3].set(xp.cos(angle / 2.0)) + quat = xpx.at(quat)[..., axis].set(xp.sin(angle / 2.0)) + return quat + + +def _get_angles( + extrinsic: bool, + symmetric: bool, + sign: int, + lamb: float, + a: Array, + b: Array, + c: Array, + d: Array, + suppress_warnings: bool, +) -> Array: + xp = array_namespace(a) + device = xp_device(a) + eps = 1e-7 + half_sum = xp.atan2(b, a) + half_diff = xp.atan2(d, c) + # We zero-initialize to automatically cover singular cases where the second angle is + # not defined uniquely. + angles = xp.zeros((*a.shape, 3), dtype=a.dtype, device=device) + + angles = xpx.at(angles)[..., 1].set(2 * xp.atan2(xp.hypot(c, d), xp.hypot(a, b))) + + angle_first = 0 if extrinsic else 2 + angle_third = 2 if extrinsic else 0 + + # Check if the second angle is close to 0 or pi, causing a singularity. + # - Case 0: Second angle is neither close to 0 nor pi. + # - Case 1: Second angle is close to 0. + # - Case 2: Second angle is close to pi. + case1 = xp.abs(angles[..., 1]) <= eps + case2 = xp.abs(angles[..., 1] - xp.pi) <= eps + case0 = ~(case1 | case2) + if not suppress_warnings and not is_lazy_array(case0) and xp.any(~case0): + warnings.warn( + "Gimbal lock detected. Setting third angle to zero " + "since it is not possible to uniquely determine " + "all angles.", + stacklevel=3, + ) + + # This writes case1 into a0 where True and case2 everywhere else. This is sound + # because we later overwrite any values without singularity with the regular value + # of case0. The second angle is covered by default since we zero-initialized the + # second dimension. + a0 = xp.where(case1, 2 * half_sum, 2 * half_diff * (-1 if extrinsic else 1)) + angles = xpx.at(angles)[..., 0].set(a0) + + # We overwrite the values of angles without singularities (case0) + a1 = xp.where(case0, half_sum - half_diff, angles[..., angle_first]) + angles = xpx.at(angles)[..., angle_first].set(a1) + + # Same as above but for the third angle. We overwrite the non-singular case0 values + a3 = xp.where(case0, half_sum + half_diff, angles[..., angle_third]) + if not symmetric: + a3 = a3 * sign + angles = xpx.at(angles)[..., 1].set(angles[..., 1] - lamb) + angles = xpx.at(angles)[..., angle_third].set(a3) + + angles = (angles + xp.pi) % (2 * xp.pi) - xp.pi + return angles + + +def compose_quat(p: Array, q: Array) -> Array: + xp = array_namespace(p) + cross = xp.linalg.cross(p[..., :3], q[..., :3]) + qx = p[..., 3] * q[..., 0] + q[..., 3] * p[..., 0] + cross[..., 0] + qy = p[..., 3] * q[..., 1] + q[..., 3] * p[..., 1] + cross[..., 1] + qz = p[..., 3] * q[..., 2] + q[..., 3] * p[..., 2] + cross[..., 2] + qw = ( + p[..., 3] * q[..., 3] + - p[..., 0] * q[..., 0] + - p[..., 1] * q[..., 1] + - p[..., 2] * q[..., 2] + ) + quat = xp.stack([qx, qy, qz, qw], axis=-1) + return quat + + +def _split_rotation(q: Array, xp) -> tuple[Array, Array]: + q = xpx.atleast_nd(q, ndim=2, xp=xp) + return q[..., -1], q[..., :-1] + + +def _deg2rad(angles: Array) -> Array: + return angles * (np.pi / 180.0) + + +def _rad2deg(angles: Array) -> Array: + return angles * (180.0 / np.pi) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/rotation.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/rotation.py new file mode 100644 index 0000000000000000000000000000000000000000..a719437415124f4afc842b98c708836c1fe68f22 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/rotation.py @@ -0,0 +1,21 @@ +# This file is not meant for public use and will be removed in SciPy v2.0.0. +# Use the `scipy.spatial` namespace for importing the functions +# included below. + +from scipy._lib.deprecation import _sub_module_deprecation + + +__all__ = [ # noqa: F822 + 'Rotation', + 'Slerp', +] + + +def __dir__(): + return __all__ + + +def __getattr__(name): + return _sub_module_deprecation(sub_package="spatial.transform", module="rotation", + private_modules=["_rotation"], all=__all__, + attribute=name) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/tests/__init__.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/tests/test_rotation_groups.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/tests/test_rotation_groups.py new file mode 100644 index 0000000000000000000000000000000000000000..0e43ef31b8f25e0c5d767c601757375f65677bf2 --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/tests/test_rotation_groups.py @@ -0,0 +1,169 @@ +import pytest + +import numpy as np +from numpy.testing import assert_array_almost_equal +from scipy.spatial.transform import Rotation +from scipy.optimize import linear_sum_assignment +from scipy.spatial.distance import cdist +from scipy.constants import golden as phi +from scipy.spatial import cKDTree + + +TOL = 1E-12 +NS = range(1, 13) +NAMES = ["I", "O", "T"] + [f"C{n}" for n in NS] + [f"D{n}" for n in NS] +SIZES = [60, 24, 12] + list(NS) + [2 * n for n in NS] + + +def _calculate_rmsd(P, Q): + """Calculates the root-mean-square distance between the points of P and Q. + The distance is taken as the minimum over all possible matchings. It is + zero if P and Q are identical and non-zero if not. + """ + distance_matrix = cdist(P, Q, metric='sqeuclidean') + matching = linear_sum_assignment(distance_matrix) + return np.sqrt(distance_matrix[matching].sum()) + + +def _generate_pyramid(n, axis): + thetas = np.linspace(0, 2 * np.pi, n + 1)[:-1] + P = np.vstack([np.zeros(n), np.cos(thetas), np.sin(thetas)]).T + P = np.concatenate((P, [[1, 0, 0]])) + return np.roll(P, axis, axis=1) + + +def _generate_prism(n, axis): + thetas = np.linspace(0, 2 * np.pi, n + 1)[:-1] + bottom = np.vstack([-np.ones(n), np.cos(thetas), np.sin(thetas)]).T + top = np.vstack([+np.ones(n), np.cos(thetas), np.sin(thetas)]).T + P = np.concatenate((bottom, top)) + return np.roll(P, axis, axis=1) + + +def _generate_icosahedron(): + x = np.array([[0, -1, -phi], + [0, -1, +phi], + [0, +1, -phi], + [0, +1, +phi]]) + return np.concatenate([np.roll(x, i, axis=1) for i in range(3)]) + + +def _generate_octahedron(): + return np.array([[-1, 0, 0], [+1, 0, 0], [0, -1, 0], + [0, +1, 0], [0, 0, -1], [0, 0, +1]]) + + +def _generate_tetrahedron(): + return np.array([[1, 1, 1], [1, -1, -1], [-1, 1, -1], [-1, -1, 1]]) + + +@pytest.mark.parametrize("name", [-1, None, True, np.array(['C3'])]) +def test_group_type(name): + with pytest.raises(ValueError, + match="must be a string"): + Rotation.create_group(name) + + +@pytest.mark.parametrize("name", ["Q", " ", "CA", "C ", "DA", "D ", "I2", ""]) +def test_group_name(name): + with pytest.raises(ValueError, + match="must be one of 'I', 'O', 'T', 'Dn', 'Cn'"): + Rotation.create_group(name) + + +@pytest.mark.parametrize("name", ["C0", "D0"]) +def test_group_order_positive(name): + with pytest.raises(ValueError, + match="Group order must be positive"): + Rotation.create_group(name) + + +@pytest.mark.parametrize("axis", ['A', 'b', 0, 1, 2, 4, False, None]) +def test_axis_valid(axis): + with pytest.raises(ValueError, + match="`axis` must be one of"): + Rotation.create_group("C1", axis) + + +def test_icosahedral(): + """The icosahedral group fixes the rotations of an icosahedron. Here we + test that the icosahedron is invariant after application of the elements + of the rotation group.""" + P = _generate_icosahedron() + for g in Rotation.create_group("I"): + g = Rotation.from_quat(g.as_quat()) + assert _calculate_rmsd(P, g.apply(P)) < TOL + + +def test_octahedral(): + """Test that the octahedral group correctly fixes the rotations of an + octahedron.""" + P = _generate_octahedron() + for g in Rotation.create_group("O"): + assert _calculate_rmsd(P, g.apply(P)) < TOL + + +def test_tetrahedral(): + """Test that the tetrahedral group correctly fixes the rotations of a + tetrahedron.""" + P = _generate_tetrahedron() + for g in Rotation.create_group("T"): + assert _calculate_rmsd(P, g.apply(P)) < TOL + + +@pytest.mark.parametrize("n", NS) +@pytest.mark.parametrize("axis", 'XYZ') +def test_dicyclic(n, axis): + """Test that the dicyclic group correctly fixes the rotations of a + prism.""" + P = _generate_prism(n, axis='XYZ'.index(axis)) + for g in Rotation.create_group(f"D{n}", axis=axis): + assert _calculate_rmsd(P, g.apply(P)) < TOL + + +@pytest.mark.parametrize("n", NS) +@pytest.mark.parametrize("axis", 'XYZ') +def test_cyclic(n, axis): + """Test that the cyclic group correctly fixes the rotations of a + pyramid.""" + P = _generate_pyramid(n, axis='XYZ'.index(axis)) + for g in Rotation.create_group(f"C{n}", axis=axis): + assert _calculate_rmsd(P, g.apply(P)) < TOL + + +@pytest.mark.parametrize("name, size", zip(NAMES, SIZES)) +def test_group_sizes(name, size): + assert len(Rotation.create_group(name)) == size + + +@pytest.mark.parametrize("name, size", zip(NAMES, SIZES)) +def test_group_no_duplicates(name, size): + g = Rotation.create_group(name) + kdtree = cKDTree(g.as_quat()) + assert len(kdtree.query_pairs(1E-3)) == 0 + + +@pytest.mark.parametrize("name, size", zip(NAMES, SIZES)) +def test_group_symmetry(name, size): + g = Rotation.create_group(name) + q = np.concatenate((-g.as_quat(), g.as_quat())) + distance = np.sort(cdist(q, q)) + deltas = np.max(distance, axis=0) - np.min(distance, axis=0) + assert (deltas < TOL).all() + + +@pytest.mark.parametrize("name", NAMES) +def test_reduction(name): + """Test that the elements of the rotation group are correctly + mapped onto the identity rotation.""" + g = Rotation.create_group(name) + f = g.reduce(g) + assert_array_almost_equal(f.magnitude(), np.zeros(len(g))) + + +@pytest.mark.parametrize("name", NAMES) +def test_single_reduction(name): + g = Rotation.create_group(name) + f = g[-1].reduce(g) + assert_array_almost_equal(f.magnitude(), 0) + assert f.as_quat().shape == (4,) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/tests/test_rotation_spline.py b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/tests/test_rotation_spline.py new file mode 100644 index 0000000000000000000000000000000000000000..d268659e06416506243593bc8a4c2e8febf3f98e --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/spatial/transform/tests/test_rotation_spline.py @@ -0,0 +1,188 @@ +from itertools import product +import numpy as np +from numpy.testing import assert_allclose +import pytest +from scipy.spatial.transform import Rotation, RotationSpline +from scipy.spatial.transform._rotation_spline import ( + _angular_rate_to_rotvec_dot_matrix, + _rotvec_dot_to_angular_rate_matrix, + _matrix_vector_product_of_stacks, + _angular_acceleration_nonlinear_term, + _create_block_3_diagonal_matrix) + + +pytestmark = pytest.mark.skip_xp_backends(np_only=True) + + +def test_angular_rate_to_rotvec_conversions(): + np.random.seed(0) + rv = np.random.randn(4, 3) + A = _angular_rate_to_rotvec_dot_matrix(rv) + A_inv = _rotvec_dot_to_angular_rate_matrix(rv) + + # When the rotation vector is aligned with the angular rate, then + # the rotation vector rate and angular rate are the same. + assert_allclose(_matrix_vector_product_of_stacks(A, rv), rv) + assert_allclose(_matrix_vector_product_of_stacks(A_inv, rv), rv) + + # A and A_inv must be reciprocal to each other. + I_stack = np.empty((4, 3, 3)) + I_stack[:] = np.eye(3) + assert_allclose(np.matmul(A, A_inv), I_stack, atol=1e-15) + + +def test_angular_rate_nonlinear_term(): + # The only simple test is to check that the term is zero when + # the rotation vector + np.random.seed(0) + rv = np.random.rand(4, 3) + assert_allclose(_angular_acceleration_nonlinear_term(rv, rv), 0, + atol=1e-19) + + +def test_create_block_3_diagonal_matrix(): + np.random.seed(0) + A = np.empty((4, 3, 3)) + A[:] = np.arange(1, 5)[:, None, None] + + B = np.empty((4, 3, 3)) + B[:] = -np.arange(1, 5)[:, None, None] + d = 10 * np.arange(10, 15) + + banded = _create_block_3_diagonal_matrix(A, B, d) + + # Convert the banded matrix to the full matrix. + k, l = list(zip(*product(np.arange(banded.shape[0]), + np.arange(banded.shape[1])))) + k = np.asarray(k) + l = np.asarray(l) + + i = k - 5 + l + j = l + values = banded.ravel() + mask = (i >= 0) & (i < 15) + i = i[mask] + j = j[mask] + values = values[mask] + full = np.zeros((15, 15)) + full[i, j] = values + + zero = np.zeros((3, 3)) + eye = np.eye(3) + + # Create the reference full matrix in the most straightforward manner. + ref = np.block([ + [d[0] * eye, B[0], zero, zero, zero], + [A[0], d[1] * eye, B[1], zero, zero], + [zero, A[1], d[2] * eye, B[2], zero], + [zero, zero, A[2], d[3] * eye, B[3]], + [zero, zero, zero, A[3], d[4] * eye], + ]) + + assert_allclose(full, ref, atol=1e-19) + + +def test_spline_2_rotations(): + times = [0, 10] + rotations = Rotation.from_euler('xyz', [[0, 0, 0], [10, -20, 30]], + degrees=True) + spline = RotationSpline(times, rotations) + + rv = (rotations[0].inv() * rotations[1]).as_rotvec() + rate = rv / (times[1] - times[0]) + times_check = np.array([-1, 5, 12]) + dt = times_check - times[0] + rv_ref = rate * dt[:, None] + + assert_allclose(spline(times_check).as_rotvec(), rv_ref) + assert_allclose(spline(times_check, 1), np.resize(rate, (3, 3))) + assert_allclose(spline(times_check, 2), 0, atol=1e-16) + + +def test_constant_attitude(): + times = np.arange(10) + rotations = Rotation.from_rotvec(np.ones((10, 3))) + spline = RotationSpline(times, rotations) + + times_check = np.linspace(-1, 11) + assert_allclose(spline(times_check).as_rotvec(), 1, rtol=1e-15) + assert_allclose(spline(times_check, 1), 0, atol=1e-17) + assert_allclose(spline(times_check, 2), 0, atol=1e-17) + + assert_allclose(spline(5.5).as_rotvec(), 1, rtol=1e-15) + assert_allclose(spline(5.5, 1), 0, atol=1e-17) + assert_allclose(spline(5.5, 2), 0, atol=1e-17) + + +def test_spline_properties(): + times = np.array([0, 5, 15, 27]) + angles = [[-5, 10, 27], [3, 5, 38], [-12, 10, 25], [-15, 20, 11]] + + rotations = Rotation.from_euler('xyz', angles, degrees=True) + spline = RotationSpline(times, rotations) + + assert_allclose(spline(times).as_euler('xyz', degrees=True), angles) + assert_allclose(spline(0).as_euler('xyz', degrees=True), angles[0]) + + h = 1e-8 + rv0 = spline(times).as_rotvec() + rvm = spline(times - h).as_rotvec() + rvp = spline(times + h).as_rotvec() + # rtol bumped from 1e-15 to 1.5e-15 in gh18414 for linux 32 bit + assert_allclose(rv0, 0.5 * (rvp + rvm), rtol=1.5e-15) + + r0 = spline(times, 1) + rm = spline(times - h, 1) + rp = spline(times + h, 1) + assert_allclose(r0, 0.5 * (rm + rp), rtol=1e-14) + + a0 = spline(times, 2) + am = spline(times - h, 2) + ap = spline(times + h, 2) + assert_allclose(a0, am, rtol=1e-7) + assert_allclose(a0, ap, rtol=1e-7) + + +def test_error_handling(): + with pytest.raises(ValueError): + RotationSpline([1.0], Rotation.random()) + + r = Rotation.random(10) + t = np.arange(10).reshape(5, 2) + with pytest.raises(ValueError): + RotationSpline(t, r) + + t = np.arange(9) + with pytest.raises(ValueError): + RotationSpline(t, r) + + t = np.arange(10) + t[5] = 0 + with pytest.raises(ValueError): + RotationSpline(t, r) + + t = np.arange(10) + + s = RotationSpline(t, r) + with pytest.raises(ValueError): + s(10, -1) + + with pytest.raises(ValueError): + s(np.arange(10).reshape(5, 2)) + + r = Rotation.from_quat(np.array([[[0.0, 0, 0, 1], [1, 0, 0 ,0]]])) + t = np.arange(2) + with pytest.raises(ValueError): + RotationSpline(t, r) # More than 2 dimensions + + +@pytest.mark.skip_xp_backends("numpy") +def test_xp_errors(xp): + times = xp.asarray([0, 10]) + r = Rotation.random(2) + r = Rotation.from_quat(xp.asarray(r.as_quat())) + s = RotationSpline(times, r) + t = xp.asarray([0.5, 1.5]) + # RotationSpline does not have native Array API support, so we check that it + # converts any array to NumPy and outputs NumPy arrays. + assert isinstance(s(t).as_quat(), np.ndarray) diff --git a/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/special/tests/_cython_examples/meson.build b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/special/tests/_cython_examples/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..445155e371e5c162fbcb8a70d881c650cdb302ad --- /dev/null +++ b/URSA/.venv_ursa/lib/python3.12/site-packages/scipy/special/tests/_cython_examples/meson.build @@ -0,0 +1,34 @@ +project('random-build-examples', 'c', 'cpp', 'cython') + +fs = import('fs') + +py3 = import('python').find_installation(pure: false) + +cy = meson.get_compiler('cython') + +if not cy.version().version_compare('>=3.0.8') + error('tests requires Cython >= 3.0.8') +endif + +cython_args = [] +if cy.version().version_compare('>=3.1.0') + cython_args += ['-Xfreethreading_compatible=True'] +endif + +py3.extension_module( + 'extending', + 'extending.pyx', + install: false, + cython_args: cython_args, + c_args: ['-DCYTHON_CCOMPLEX=0'] # see gh-18975 for why we need this +) + +extending_cpp = fs.copyfile('extending.pyx', 'extending_cpp.pyx') +py3.extension_module( + 'extending_cpp', + extending_cpp, + install: false, + override_options : ['cython_language=cpp'], + cython_args: cython_args, + cpp_args: ['-DCYTHON_CCOMPLEX=0'] +)