diff --git a/lib/python3.12/site-packages/cloudpickle/__init__.py b/lib/python3.12/site-packages/cloudpickle/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..9faf0b6d81e958a7c41da4d920a5b77a2548b526
--- /dev/null
+++ b/lib/python3.12/site-packages/cloudpickle/__init__.py
@@ -0,0 +1,18 @@
+from . import cloudpickle
+from .cloudpickle import * # noqa
+
+__doc__ = cloudpickle.__doc__
+
+__version__ = "3.1.2"
+
+__all__ = [ # noqa
+ "__version__",
+ "Pickler",
+ "CloudPickler",
+ "dumps",
+ "loads",
+ "dump",
+ "load",
+ "register_pickle_by_value",
+ "unregister_pickle_by_value",
+]
diff --git a/lib/python3.12/site-packages/cloudpickle/__pycache__/__init__.cpython-312.pyc b/lib/python3.12/site-packages/cloudpickle/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8315ad786f53f23d782a92ea1150611fb3b50565
Binary files /dev/null and b/lib/python3.12/site-packages/cloudpickle/__pycache__/__init__.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/cloudpickle/__pycache__/cloudpickle.cpython-312.pyc b/lib/python3.12/site-packages/cloudpickle/__pycache__/cloudpickle.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..bffae5d590512e485c1bca0eb8026c0cfa0bd579
Binary files /dev/null and b/lib/python3.12/site-packages/cloudpickle/__pycache__/cloudpickle.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/cloudpickle/__pycache__/cloudpickle_fast.cpython-312.pyc b/lib/python3.12/site-packages/cloudpickle/__pycache__/cloudpickle_fast.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..cca8aa2614c98b2da2cebfe3ca4dbad1c0bab86b
Binary files /dev/null and b/lib/python3.12/site-packages/cloudpickle/__pycache__/cloudpickle_fast.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/cloudpickle/cloudpickle.py b/lib/python3.12/site-packages/cloudpickle/cloudpickle.py
new file mode 100644
index 0000000000000000000000000000000000000000..e600b35f28422096173a783380ec912a66b453cf
--- /dev/null
+++ b/lib/python3.12/site-packages/cloudpickle/cloudpickle.py
@@ -0,0 +1,1552 @@
+"""Pickler class to extend the standard pickle.Pickler functionality
+
+The main objective is to make it natural to perform distributed computing on
+clusters (such as PySpark, Dask, Ray...) with interactively defined code
+(functions, classes, ...) written in notebooks or console.
+
+In particular this pickler adds the following features:
+- serialize interactively-defined or locally-defined functions, classes,
+ enums, typevars, lambdas and nested functions to compiled byte code;
+- deal with some other non-serializable objects in an ad-hoc manner where
+ applicable.
+
+This pickler is therefore meant to be used for the communication between short
+lived Python processes running the same version of Python and libraries. In
+particular, it is not meant to be used for long term storage of Python objects.
+
+It does not include an unpickler, as standard Python unpickling suffices.
+
+This module was extracted from the `cloud` package, developed by `PiCloud, Inc.
+ `_.
+
+Copyright (c) 2012-now, CloudPickle developers and contributors.
+Copyright (c) 2012, Regents of the University of California.
+Copyright (c) 2009 `PiCloud, 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 the University of California, Berkeley 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 _collections_abc
+from collections import ChainMap, OrderedDict
+import abc
+import builtins
+import copyreg
+import dataclasses
+import dis
+from enum import Enum
+import io
+import itertools
+import logging
+import opcode
+import pickle
+from pickle import _getattribute as _pickle_getattribute
+import platform
+import struct
+import sys
+import threading
+import types
+import typing
+import uuid
+import warnings
+import weakref
+
+# The following import is required to be imported in the cloudpickle
+# namespace to be able to load pickle files generated with older versions of
+# cloudpickle. See: tests/test_backward_compat.py
+from types import CellType # noqa: F401
+
+
+# cloudpickle is meant for inter process communication: we expect all
+# communicating processes to run the same Python version hence we favor
+# communication speed over compatibility:
+DEFAULT_PROTOCOL = pickle.HIGHEST_PROTOCOL
+
+# Names of modules whose resources should be treated as dynamic.
+_PICKLE_BY_VALUE_MODULES = set()
+
+# Track the provenance of reconstructed dynamic classes to make it possible to
+# reconstruct instances from the matching singleton class definition when
+# appropriate and preserve the usual "isinstance" semantics of Python objects.
+_DYNAMIC_CLASS_TRACKER_BY_CLASS = weakref.WeakKeyDictionary()
+_DYNAMIC_CLASS_TRACKER_BY_ID = weakref.WeakValueDictionary()
+_DYNAMIC_CLASS_TRACKER_LOCK = threading.Lock()
+
+PYPY = platform.python_implementation() == "PyPy"
+
+builtin_code_type = None
+if PYPY:
+ # builtin-code objects only exist in pypy
+ builtin_code_type = type(float.__new__.__code__)
+
+_extract_code_globals_cache = weakref.WeakKeyDictionary()
+
+
+def _get_or_create_tracker_id(class_def):
+ with _DYNAMIC_CLASS_TRACKER_LOCK:
+ class_tracker_id = _DYNAMIC_CLASS_TRACKER_BY_CLASS.get(class_def)
+ if class_tracker_id is None:
+ class_tracker_id = uuid.uuid4().hex
+ _DYNAMIC_CLASS_TRACKER_BY_CLASS[class_def] = class_tracker_id
+ _DYNAMIC_CLASS_TRACKER_BY_ID[class_tracker_id] = class_def
+ return class_tracker_id
+
+
+def _lookup_class_or_track(class_tracker_id, class_def):
+ if class_tracker_id is not None:
+ with _DYNAMIC_CLASS_TRACKER_LOCK:
+ class_def = _DYNAMIC_CLASS_TRACKER_BY_ID.setdefault(
+ class_tracker_id, class_def
+ )
+ _DYNAMIC_CLASS_TRACKER_BY_CLASS[class_def] = class_tracker_id
+ return class_def
+
+
+def register_pickle_by_value(module):
+ """Register a module to make its functions and classes picklable by value.
+
+ By default, functions and classes that are attributes of an importable
+ module are to be pickled by reference, that is relying on re-importing
+ the attribute from the module at load time.
+
+ If `register_pickle_by_value(module)` is called, all its functions and
+ classes are subsequently to be pickled by value, meaning that they can
+ be loaded in Python processes where the module is not importable.
+
+ This is especially useful when developing a module in a distributed
+ execution environment: restarting the client Python process with the new
+ source code is enough: there is no need to re-install the new version
+ of the module on all the worker nodes nor to restart the workers.
+
+ Note: this feature is considered experimental. See the cloudpickle
+ README.md file for more details and limitations.
+ """
+ if not isinstance(module, types.ModuleType):
+ raise ValueError(f"Input should be a module object, got {str(module)} instead")
+ # In the future, cloudpickle may need a way to access any module registered
+ # for pickling by value in order to introspect relative imports inside
+ # functions pickled by value. (see
+ # https://github.com/cloudpipe/cloudpickle/pull/417#issuecomment-873684633).
+ # This access can be ensured by checking that module is present in
+ # sys.modules at registering time and assuming that it will still be in
+ # there when accessed during pickling. Another alternative would be to
+ # store a weakref to the module. Even though cloudpickle does not implement
+ # this introspection yet, in order to avoid a possible breaking change
+ # later, we still enforce the presence of module inside sys.modules.
+ if module.__name__ not in sys.modules:
+ raise ValueError(
+ f"{module} was not imported correctly, have you used an "
+ "`import` statement to access it?"
+ )
+ _PICKLE_BY_VALUE_MODULES.add(module.__name__)
+
+
+def unregister_pickle_by_value(module):
+ """Unregister that the input module should be pickled by value."""
+ if not isinstance(module, types.ModuleType):
+ raise ValueError(f"Input should be a module object, got {str(module)} instead")
+ if module.__name__ not in _PICKLE_BY_VALUE_MODULES:
+ raise ValueError(f"{module} is not registered for pickle by value")
+ else:
+ _PICKLE_BY_VALUE_MODULES.remove(module.__name__)
+
+
+def list_registry_pickle_by_value():
+ return _PICKLE_BY_VALUE_MODULES.copy()
+
+
+def _is_registered_pickle_by_value(module):
+ module_name = module.__name__
+ if module_name in _PICKLE_BY_VALUE_MODULES:
+ return True
+ while True:
+ parent_name = module_name.rsplit(".", 1)[0]
+ if parent_name == module_name:
+ break
+ if parent_name in _PICKLE_BY_VALUE_MODULES:
+ return True
+ module_name = parent_name
+ return False
+
+
+if sys.version_info >= (3, 14):
+ def _getattribute(obj, name):
+ return _pickle_getattribute(obj, name.split('.'))
+else:
+ def _getattribute(obj, name):
+ return _pickle_getattribute(obj, name)[0]
+
+
+def _whichmodule(obj, name):
+ """Find the module an object belongs to.
+
+ This function differs from ``pickle.whichmodule`` in two ways:
+ - it does not mangle the cases where obj's module is __main__ and obj was
+ not found in any module.
+ - Errors arising during module introspection are ignored, as those errors
+ are considered unwanted side effects.
+ """
+ module_name = getattr(obj, "__module__", None)
+
+ if module_name is not None:
+ return module_name
+ # Protect the iteration by using a copy of sys.modules against dynamic
+ # modules that trigger imports of other modules upon calls to getattr or
+ # other threads importing at the same time.
+ for module_name, module in sys.modules.copy().items():
+ # Some modules such as coverage can inject non-module objects inside
+ # sys.modules
+ if (
+ module_name == "__main__"
+ or module_name == "__mp_main__"
+ or module is None
+ or not isinstance(module, types.ModuleType)
+ ):
+ continue
+ try:
+ if _getattribute(module, name) is obj:
+ return module_name
+ except Exception:
+ pass
+ return None
+
+
+def _should_pickle_by_reference(obj, name=None):
+ """Test whether an function or a class should be pickled by reference
+
+ Pickling by reference means by that the object (typically a function or a
+ class) is an attribute of a module that is assumed to be importable in the
+ target Python environment. Loading will therefore rely on importing the
+ module and then calling `getattr` on it to access the function or class.
+
+ Pickling by reference is the only option to pickle functions and classes
+ in the standard library. In cloudpickle the alternative option is to
+ pickle by value (for instance for interactively or locally defined
+ functions and classes or for attributes of modules that have been
+ explicitly registered to be pickled by value.
+ """
+ if isinstance(obj, types.FunctionType) or issubclass(type(obj), type):
+ module_and_name = _lookup_module_and_qualname(obj, name=name)
+ if module_and_name is None:
+ return False
+ module, name = module_and_name
+ return not _is_registered_pickle_by_value(module)
+
+ elif isinstance(obj, types.ModuleType):
+ # We assume that sys.modules is primarily used as a cache mechanism for
+ # the Python import machinery. Checking if a module has been added in
+ # is sys.modules therefore a cheap and simple heuristic to tell us
+ # whether we can assume that a given module could be imported by name
+ # in another Python process.
+ if _is_registered_pickle_by_value(obj):
+ return False
+ return obj.__name__ in sys.modules
+ else:
+ raise TypeError(
+ "cannot check importability of {} instances".format(type(obj).__name__)
+ )
+
+
+def _lookup_module_and_qualname(obj, name=None):
+ if name is None:
+ name = getattr(obj, "__qualname__", None)
+ if name is None: # pragma: no cover
+ # This used to be needed for Python 2.7 support but is probably not
+ # needed anymore. However we keep the __name__ introspection in case
+ # users of cloudpickle rely on this old behavior for unknown reasons.
+ name = getattr(obj, "__name__", None)
+
+ module_name = _whichmodule(obj, name)
+
+ if module_name is None:
+ # In this case, obj.__module__ is None AND obj was not found in any
+ # imported module. obj is thus treated as dynamic.
+ return None
+
+ if module_name == "__main__":
+ return None
+
+ # Note: if module_name is in sys.modules, the corresponding module is
+ # assumed importable at unpickling time. See #357
+ module = sys.modules.get(module_name, None)
+ if module is None:
+ # The main reason why obj's module would not be imported is that this
+ # module has been dynamically created, using for example
+ # types.ModuleType. The other possibility is that module was removed
+ # from sys.modules after obj was created/imported. But this case is not
+ # supported, as the standard pickle does not support it either.
+ return None
+
+ try:
+ obj2 = _getattribute(module, name)
+ except AttributeError:
+ # obj was not found inside the module it points to
+ return None
+ if obj2 is not obj:
+ return None
+ return module, name
+
+
+def _extract_code_globals(co):
+ """Find all globals names read or written to by codeblock co."""
+ out_names = _extract_code_globals_cache.get(co)
+ if out_names is None:
+ # We use a dict with None values instead of a set to get a
+ # deterministic order and avoid introducing non-deterministic pickle
+ # bytes as a results.
+ out_names = {name: None for name in _walk_global_ops(co)}
+
+ # Declaring a function inside another one using the "def ..." syntax
+ # generates a constant code object corresponding to the one of the
+ # nested function's As the nested function may itself need global
+ # variables, we need to introspect its code, extract its globals, (look
+ # for code object in it's co_consts attribute..) and add the result to
+ # code_globals
+ if co.co_consts:
+ for const in co.co_consts:
+ if isinstance(const, types.CodeType):
+ out_names.update(_extract_code_globals(const))
+
+ _extract_code_globals_cache[co] = out_names
+
+ return out_names
+
+
+def _find_imported_submodules(code, top_level_dependencies):
+ """Find currently imported submodules used by a function.
+
+ Submodules used by a function need to be detected and referenced for the
+ function to work correctly at depickling time. Because submodules can be
+ referenced as attribute of their parent package (``package.submodule``), we
+ need a special introspection technique that does not rely on GLOBAL-related
+ opcodes to find references of them in a code object.
+
+ Example:
+ ```
+ import concurrent.futures
+ import cloudpickle
+ def func():
+ x = concurrent.futures.ThreadPoolExecutor
+ if __name__ == '__main__':
+ cloudpickle.dumps(func)
+ ```
+ The globals extracted by cloudpickle in the function's state include the
+ concurrent package, but not its submodule (here, concurrent.futures), which
+ is the module used by func. Find_imported_submodules will detect the usage
+ of concurrent.futures. Saving this module alongside with func will ensure
+ that calling func once depickled does not fail due to concurrent.futures
+ not being imported
+ """
+
+ subimports = []
+ # check if any known dependency is an imported package
+ for x in top_level_dependencies:
+ if (
+ isinstance(x, types.ModuleType)
+ and hasattr(x, "__package__")
+ and x.__package__
+ ):
+ # check if the package has any currently loaded sub-imports
+ prefix = x.__name__ + "."
+ # A concurrent thread could mutate sys.modules,
+ # make sure we iterate over a copy to avoid exceptions
+ for name in list(sys.modules):
+ # Older versions of pytest will add a "None" module to
+ # sys.modules.
+ if name is not None and name.startswith(prefix):
+ # check whether the function can address the sub-module
+ tokens = set(name[len(prefix) :].split("."))
+ if not tokens - set(code.co_names):
+ subimports.append(sys.modules[name])
+ return subimports
+
+
+# relevant opcodes
+STORE_GLOBAL = opcode.opmap["STORE_GLOBAL"]
+DELETE_GLOBAL = opcode.opmap["DELETE_GLOBAL"]
+LOAD_GLOBAL = opcode.opmap["LOAD_GLOBAL"]
+GLOBAL_OPS = (STORE_GLOBAL, DELETE_GLOBAL, LOAD_GLOBAL)
+HAVE_ARGUMENT = dis.HAVE_ARGUMENT
+EXTENDED_ARG = dis.EXTENDED_ARG
+
+
+_BUILTIN_TYPE_NAMES = {}
+for k, v in types.__dict__.items():
+ if type(v) is type:
+ _BUILTIN_TYPE_NAMES[v] = k
+
+
+def _builtin_type(name):
+ if name == "ClassType": # pragma: no cover
+ # Backward compat to load pickle files generated with cloudpickle
+ # < 1.3 even if loading pickle files from older versions is not
+ # officially supported.
+ return type
+ return getattr(types, name)
+
+
+def _walk_global_ops(code):
+ """Yield referenced name for global-referencing instructions in code."""
+ for instr in dis.get_instructions(code):
+ op = instr.opcode
+ if op in GLOBAL_OPS:
+ yield instr.argval
+
+
+def _extract_class_dict(cls):
+ """Retrieve a copy of the dict of a class without the inherited method."""
+ # Hack to circumvent non-predictable memoization caused by string interning.
+ # See the inline comment in _class_setstate for details.
+ clsdict = {"".join(k): cls.__dict__[k] for k in sorted(cls.__dict__)}
+
+ if len(cls.__bases__) == 1:
+ inherited_dict = cls.__bases__[0].__dict__
+ else:
+ inherited_dict = {}
+ for base in reversed(cls.__bases__):
+ inherited_dict.update(base.__dict__)
+ to_remove = []
+ for name, value in clsdict.items():
+ try:
+ base_value = inherited_dict[name]
+ if value is base_value:
+ to_remove.append(name)
+ except KeyError:
+ pass
+ for name in to_remove:
+ clsdict.pop(name)
+ return clsdict
+
+
+def is_tornado_coroutine(func):
+ """Return whether `func` is a Tornado coroutine function.
+
+ Running coroutines are not supported.
+ """
+ warnings.warn(
+ "is_tornado_coroutine is deprecated in cloudpickle 3.0 and will be "
+ "removed in cloudpickle 4.0. Use tornado.gen.is_coroutine_function "
+ "directly instead.",
+ category=DeprecationWarning,
+ )
+ if "tornado.gen" not in sys.modules:
+ return False
+ gen = sys.modules["tornado.gen"]
+ if not hasattr(gen, "is_coroutine_function"):
+ # Tornado version is too old
+ return False
+ return gen.is_coroutine_function(func)
+
+
+def subimport(name):
+ # We cannot do simply: `return __import__(name)`: Indeed, if ``name`` is
+ # the name of a submodule, __import__ will return the top-level root module
+ # of this submodule. For instance, __import__('os.path') returns the `os`
+ # module.
+ __import__(name)
+ return sys.modules[name]
+
+
+def dynamic_subimport(name, vars):
+ mod = types.ModuleType(name)
+ mod.__dict__.update(vars)
+ mod.__dict__["__builtins__"] = builtins.__dict__
+ return mod
+
+
+def _get_cell_contents(cell):
+ try:
+ return cell.cell_contents
+ except ValueError:
+ # Handle empty cells explicitly with a sentinel value.
+ return _empty_cell_value
+
+
+def instance(cls):
+ """Create a new instance of a class.
+
+ Parameters
+ ----------
+ cls : type
+ The class to create an instance of.
+
+ Returns
+ -------
+ instance : cls
+ A new instance of ``cls``.
+ """
+ return cls()
+
+
+@instance
+class _empty_cell_value:
+ """Sentinel for empty closures."""
+
+ @classmethod
+ def __reduce__(cls):
+ return cls.__name__
+
+
+def _make_function(code, globals, name, argdefs, closure):
+ # Setting __builtins__ in globals is needed for nogil CPython.
+ globals["__builtins__"] = __builtins__
+ return types.FunctionType(code, globals, name, argdefs, closure)
+
+
+def _make_empty_cell():
+ if False:
+ # trick the compiler into creating an empty cell in our lambda
+ cell = None
+ raise AssertionError("this route should not be executed")
+
+ return (lambda: cell).__closure__[0]
+
+
+def _make_cell(value=_empty_cell_value):
+ cell = _make_empty_cell()
+ if value is not _empty_cell_value:
+ cell.cell_contents = value
+ return cell
+
+
+def _make_skeleton_class(
+ type_constructor, name, bases, type_kwargs, class_tracker_id, extra
+):
+ """Build dynamic class with an empty __dict__ to be filled once memoized
+
+ If class_tracker_id is not None, try to lookup an existing class definition
+ matching that id. If none is found, track a newly reconstructed class
+ definition under that id so that other instances stemming from the same
+ class id will also reuse this class definition.
+
+ The "extra" variable is meant to be a dict (or None) that can be used for
+ forward compatibility shall the need arise.
+ """
+ # We need to intern the keys of the type_kwargs dict to avoid having
+ # different pickles for the same dynamic class depending on whether it was
+ # dynamically created or reconstructed from a pickled stream.
+ type_kwargs = {sys.intern(k): v for k, v in type_kwargs.items()}
+
+ skeleton_class = types.new_class(
+ name, bases, {"metaclass": type_constructor}, lambda ns: ns.update(type_kwargs)
+ )
+
+ return _lookup_class_or_track(class_tracker_id, skeleton_class)
+
+
+def _make_skeleton_enum(
+ bases, name, qualname, members, module, class_tracker_id, extra
+):
+ """Build dynamic enum with an empty __dict__ to be filled once memoized
+
+ The creation of the enum class is inspired by the code of
+ EnumMeta._create_.
+
+ If class_tracker_id is not None, try to lookup an existing enum definition
+ matching that id. If none is found, track a newly reconstructed enum
+ definition under that id so that other instances stemming from the same
+ class id will also reuse this enum definition.
+
+ The "extra" variable is meant to be a dict (or None) that can be used for
+ forward compatibility shall the need arise.
+ """
+ # enums always inherit from their base Enum class at the last position in
+ # the list of base classes:
+ enum_base = bases[-1]
+ metacls = enum_base.__class__
+ classdict = metacls.__prepare__(name, bases)
+
+ for member_name, member_value in members.items():
+ classdict[member_name] = member_value
+ enum_class = metacls.__new__(metacls, name, bases, classdict)
+ enum_class.__module__ = module
+ enum_class.__qualname__ = qualname
+
+ return _lookup_class_or_track(class_tracker_id, enum_class)
+
+
+def _make_typevar(name, bound, constraints, covariant, contravariant, class_tracker_id):
+ tv = typing.TypeVar(
+ name,
+ *constraints,
+ bound=bound,
+ covariant=covariant,
+ contravariant=contravariant,
+ )
+ return _lookup_class_or_track(class_tracker_id, tv)
+
+
+def _decompose_typevar(obj):
+ return (
+ obj.__name__,
+ obj.__bound__,
+ obj.__constraints__,
+ obj.__covariant__,
+ obj.__contravariant__,
+ _get_or_create_tracker_id(obj),
+ )
+
+
+def _typevar_reduce(obj):
+ # TypeVar instances require the module information hence why we
+ # are not using the _should_pickle_by_reference directly
+ module_and_name = _lookup_module_and_qualname(obj, name=obj.__name__)
+
+ if module_and_name is None:
+ return (_make_typevar, _decompose_typevar(obj))
+ elif _is_registered_pickle_by_value(module_and_name[0]):
+ return (_make_typevar, _decompose_typevar(obj))
+
+ return (getattr, module_and_name)
+
+
+def _get_bases(typ):
+ if "__orig_bases__" in getattr(typ, "__dict__", {}):
+ # For generic types (see PEP 560)
+ # Note that simply checking `hasattr(typ, '__orig_bases__')` is not
+ # correct. Subclasses of a fully-parameterized generic class does not
+ # have `__orig_bases__` defined, but `hasattr(typ, '__orig_bases__')`
+ # will return True because it's defined in the base class.
+ bases_attr = "__orig_bases__"
+ else:
+ # For regular class objects
+ bases_attr = "__bases__"
+ return getattr(typ, bases_attr)
+
+
+def _make_dict_keys(obj, is_ordered=False):
+ if is_ordered:
+ return OrderedDict.fromkeys(obj).keys()
+ else:
+ return dict.fromkeys(obj).keys()
+
+
+def _make_dict_values(obj, is_ordered=False):
+ if is_ordered:
+ return OrderedDict((i, _) for i, _ in enumerate(obj)).values()
+ else:
+ return {i: _ for i, _ in enumerate(obj)}.values()
+
+
+def _make_dict_items(obj, is_ordered=False):
+ if is_ordered:
+ return OrderedDict(obj).items()
+ else:
+ return obj.items()
+
+
+# COLLECTION OF OBJECTS __getnewargs__-LIKE METHODS
+# -------------------------------------------------
+
+
+def _class_getnewargs(obj):
+ type_kwargs = {}
+ if "__module__" in obj.__dict__:
+ type_kwargs["__module__"] = obj.__module__
+
+ __dict__ = obj.__dict__.get("__dict__", None)
+ if isinstance(__dict__, property):
+ type_kwargs["__dict__"] = __dict__
+
+ return (
+ type(obj),
+ obj.__name__,
+ _get_bases(obj),
+ type_kwargs,
+ _get_or_create_tracker_id(obj),
+ None,
+ )
+
+
+def _enum_getnewargs(obj):
+ members = {e.name: e.value for e in obj}
+ return (
+ obj.__bases__,
+ obj.__name__,
+ obj.__qualname__,
+ members,
+ obj.__module__,
+ _get_or_create_tracker_id(obj),
+ None,
+ )
+
+
+# COLLECTION OF OBJECTS RECONSTRUCTORS
+# ------------------------------------
+def _file_reconstructor(retval):
+ return retval
+
+
+# COLLECTION OF OBJECTS STATE GETTERS
+# -----------------------------------
+
+
+def _function_getstate(func):
+ # - Put func's dynamic attributes (stored in func.__dict__) in state. These
+ # attributes will be restored at unpickling time using
+ # f.__dict__.update(state)
+ # - Put func's members into slotstate. Such attributes will be restored at
+ # unpickling time by iterating over slotstate and calling setattr(func,
+ # slotname, slotvalue)
+ slotstate = {
+ # Hack to circumvent non-predictable memoization caused by string interning.
+ # See the inline comment in _class_setstate for details.
+ "__name__": "".join(func.__name__),
+ "__qualname__": "".join(func.__qualname__),
+ "__annotations__": func.__annotations__,
+ "__kwdefaults__": func.__kwdefaults__,
+ "__defaults__": func.__defaults__,
+ "__module__": func.__module__,
+ "__doc__": func.__doc__,
+ "__closure__": func.__closure__,
+ }
+
+ f_globals_ref = _extract_code_globals(func.__code__)
+ f_globals = {k: func.__globals__[k] for k in f_globals_ref if k in func.__globals__}
+
+ if func.__closure__ is not None:
+ closure_values = list(map(_get_cell_contents, func.__closure__))
+ else:
+ closure_values = ()
+
+ # Extract currently-imported submodules used by func. Storing these modules
+ # in a smoke _cloudpickle_subimports attribute of the object's state will
+ # trigger the side effect of importing these modules at unpickling time
+ # (which is necessary for func to work correctly once depickled)
+ slotstate["_cloudpickle_submodules"] = _find_imported_submodules(
+ func.__code__, itertools.chain(f_globals.values(), closure_values)
+ )
+ slotstate["__globals__"] = f_globals
+
+ # Hack to circumvent non-predictable memoization caused by string interning.
+ # See the inline comment in _class_setstate for details.
+ state = {"".join(k): v for k, v in func.__dict__.items()}
+ return state, slotstate
+
+
+def _class_getstate(obj):
+ clsdict = _extract_class_dict(obj)
+ clsdict.pop("__weakref__", None)
+
+ if issubclass(type(obj), abc.ABCMeta):
+ # If obj is an instance of an ABCMeta subclass, don't pickle the
+ # cache/negative caches populated during isinstance/issubclass
+ # checks, but pickle the list of registered subclasses of obj.
+ clsdict.pop("_abc_cache", None)
+ clsdict.pop("_abc_negative_cache", None)
+ clsdict.pop("_abc_negative_cache_version", None)
+ registry = clsdict.pop("_abc_registry", None)
+ if registry is None:
+ # The abc caches and registered subclasses of a
+ # class are bundled into the single _abc_impl attribute
+ clsdict.pop("_abc_impl", None)
+ (registry, _, _, _) = abc._get_dump(obj)
+
+ clsdict["_abc_impl"] = [subclass_weakref() for subclass_weakref in registry]
+ else:
+ # In the above if clause, registry is a set of weakrefs -- in
+ # this case, registry is a WeakSet
+ clsdict["_abc_impl"] = [type_ for type_ in registry]
+
+ if "__slots__" in clsdict:
+ # pickle string length optimization: member descriptors of obj are
+ # created automatically from obj's __slots__ attribute, no need to
+ # save them in obj's state
+ if isinstance(obj.__slots__, str):
+ clsdict.pop(obj.__slots__)
+ else:
+ for k in obj.__slots__:
+ clsdict.pop(k, None)
+
+ clsdict.pop("__dict__", None) # unpicklable property object
+
+ if sys.version_info >= (3, 14):
+ # PEP-649/749: __annotate_func__ contains a closure that references the class
+ # dict. We need to exclude it from pickling. Python will recreate it when
+ # __annotations__ is accessed at unpickling time.
+ clsdict.pop("__annotate_func__", None)
+
+ return (clsdict, {})
+
+
+def _enum_getstate(obj):
+ clsdict, slotstate = _class_getstate(obj)
+
+ members = {e.name: e.value for e in obj}
+ # Cleanup the clsdict that will be passed to _make_skeleton_enum:
+ # Those attributes are already handled by the metaclass.
+ for attrname in [
+ "_generate_next_value_",
+ "_member_names_",
+ "_member_map_",
+ "_member_type_",
+ "_value2member_map_",
+ ]:
+ clsdict.pop(attrname, None)
+ for member in members:
+ clsdict.pop(member)
+ # Special handling of Enum subclasses
+ return clsdict, slotstate
+
+
+# COLLECTIONS OF OBJECTS REDUCERS
+# -------------------------------
+# A reducer is a function taking a single argument (obj), and that returns a
+# tuple with all the necessary data to re-construct obj. Apart from a few
+# exceptions (list, dict, bytes, int, etc.), a reducer is necessary to
+# correctly pickle an object.
+# While many built-in objects (Exceptions objects, instances of the "object"
+# class, etc), are shipped with their own built-in reducer (invoked using
+# obj.__reduce__), some do not. The following methods were created to "fill
+# these holes".
+
+
+def _code_reduce(obj):
+ """code object reducer."""
+ # If you are not sure about the order of arguments, take a look at help
+ # of the specific type from types, for example:
+ # >>> from types import CodeType
+ # >>> help(CodeType)
+
+ # Hack to circumvent non-predictable memoization caused by string interning.
+ # See the inline comment in _class_setstate for details.
+ co_name = "".join(obj.co_name)
+
+ # Create shallow copies of these tuple to make cloudpickle payload deterministic.
+ # When creating a code object during load, copies of these four tuples are
+ # created, while in the main process, these tuples can be shared.
+ # By always creating copies, we make sure the resulting payload is deterministic.
+ co_names = tuple(name for name in obj.co_names)
+ co_varnames = tuple(name for name in obj.co_varnames)
+ co_freevars = tuple(name for name in obj.co_freevars)
+ co_cellvars = tuple(name for name in obj.co_cellvars)
+ if hasattr(obj, "co_exceptiontable"):
+ # Python 3.11 and later: there are some new attributes
+ # related to the enhanced exceptions.
+ args = (
+ obj.co_argcount,
+ obj.co_posonlyargcount,
+ obj.co_kwonlyargcount,
+ obj.co_nlocals,
+ obj.co_stacksize,
+ obj.co_flags,
+ obj.co_code,
+ obj.co_consts,
+ co_names,
+ co_varnames,
+ obj.co_filename,
+ co_name,
+ obj.co_qualname,
+ obj.co_firstlineno,
+ obj.co_linetable,
+ obj.co_exceptiontable,
+ co_freevars,
+ co_cellvars,
+ )
+ elif hasattr(obj, "co_linetable"):
+ # Python 3.10 and later: obj.co_lnotab is deprecated and constructor
+ # expects obj.co_linetable instead.
+ args = (
+ obj.co_argcount,
+ obj.co_posonlyargcount,
+ obj.co_kwonlyargcount,
+ obj.co_nlocals,
+ obj.co_stacksize,
+ obj.co_flags,
+ obj.co_code,
+ obj.co_consts,
+ co_names,
+ co_varnames,
+ obj.co_filename,
+ co_name,
+ obj.co_firstlineno,
+ obj.co_linetable,
+ co_freevars,
+ co_cellvars,
+ )
+ elif hasattr(obj, "co_nmeta"): # pragma: no cover
+ # "nogil" Python: modified attributes from 3.9
+ args = (
+ obj.co_argcount,
+ obj.co_posonlyargcount,
+ obj.co_kwonlyargcount,
+ obj.co_nlocals,
+ obj.co_framesize,
+ obj.co_ndefaultargs,
+ obj.co_nmeta,
+ obj.co_flags,
+ obj.co_code,
+ obj.co_consts,
+ co_varnames,
+ obj.co_filename,
+ co_name,
+ obj.co_firstlineno,
+ obj.co_lnotab,
+ obj.co_exc_handlers,
+ obj.co_jump_table,
+ co_freevars,
+ co_cellvars,
+ obj.co_free2reg,
+ obj.co_cell2reg,
+ )
+ else:
+ # Backward compat for 3.8 and 3.9
+ args = (
+ obj.co_argcount,
+ obj.co_posonlyargcount,
+ obj.co_kwonlyargcount,
+ obj.co_nlocals,
+ obj.co_stacksize,
+ obj.co_flags,
+ obj.co_code,
+ obj.co_consts,
+ co_names,
+ co_varnames,
+ obj.co_filename,
+ co_name,
+ obj.co_firstlineno,
+ obj.co_lnotab,
+ co_freevars,
+ co_cellvars,
+ )
+ return types.CodeType, args
+
+
+def _cell_reduce(obj):
+ """Cell (containing values of a function's free variables) reducer."""
+ try:
+ obj.cell_contents
+ except ValueError: # cell is empty
+ return _make_empty_cell, ()
+ else:
+ return _make_cell, (obj.cell_contents,)
+
+
+def _classmethod_reduce(obj):
+ orig_func = obj.__func__
+ return type(obj), (orig_func,)
+
+
+def _file_reduce(obj):
+ """Save a file."""
+ import io
+
+ if not hasattr(obj, "name") or not hasattr(obj, "mode"):
+ raise pickle.PicklingError(
+ "Cannot pickle files that do not map to an actual file"
+ )
+ if obj is sys.stdout:
+ return getattr, (sys, "stdout")
+ if obj is sys.stderr:
+ return getattr, (sys, "stderr")
+ if obj is sys.stdin:
+ raise pickle.PicklingError("Cannot pickle standard input")
+ if obj.closed:
+ raise pickle.PicklingError("Cannot pickle closed files")
+ if hasattr(obj, "isatty") and obj.isatty():
+ raise pickle.PicklingError("Cannot pickle files that map to tty objects")
+ if "r" not in obj.mode and "+" not in obj.mode:
+ raise pickle.PicklingError(
+ "Cannot pickle files that are not opened for reading: %s" % obj.mode
+ )
+
+ name = obj.name
+
+ retval = io.StringIO()
+
+ try:
+ # Read the whole file
+ curloc = obj.tell()
+ obj.seek(0)
+ contents = obj.read()
+ obj.seek(curloc)
+ except OSError as e:
+ raise pickle.PicklingError(
+ "Cannot pickle file %s as it cannot be read" % name
+ ) from e
+ retval.write(contents)
+ retval.seek(curloc)
+
+ retval.name = name
+ return _file_reconstructor, (retval,)
+
+
+def _getset_descriptor_reduce(obj):
+ return getattr, (obj.__objclass__, obj.__name__)
+
+
+def _mappingproxy_reduce(obj):
+ return types.MappingProxyType, (dict(obj),)
+
+
+def _memoryview_reduce(obj):
+ return bytes, (obj.tobytes(),)
+
+
+def _module_reduce(obj):
+ if _should_pickle_by_reference(obj):
+ return subimport, (obj.__name__,)
+ else:
+ # Some external libraries can populate the "__builtins__" entry of a
+ # module's `__dict__` with unpicklable objects (see #316). For that
+ # reason, we do not attempt to pickle the "__builtins__" entry, and
+ # restore a default value for it at unpickling time.
+ state = obj.__dict__.copy()
+ state.pop("__builtins__", None)
+ return dynamic_subimport, (obj.__name__, state)
+
+
+def _method_reduce(obj):
+ return (types.MethodType, (obj.__func__, obj.__self__))
+
+
+def _logger_reduce(obj):
+ return logging.getLogger, (obj.name,)
+
+
+def _root_logger_reduce(obj):
+ return logging.getLogger, ()
+
+
+def _property_reduce(obj):
+ return property, (obj.fget, obj.fset, obj.fdel, obj.__doc__)
+
+
+def _weakset_reduce(obj):
+ return weakref.WeakSet, (list(obj),)
+
+
+def _dynamic_class_reduce(obj):
+ """Save a class that can't be referenced as a module attribute.
+
+ This method is used to serialize classes that are defined inside
+ functions, or that otherwise can't be serialized as attribute lookups
+ from importable modules.
+ """
+ if Enum is not None and issubclass(obj, Enum):
+ return (
+ _make_skeleton_enum,
+ _enum_getnewargs(obj),
+ _enum_getstate(obj),
+ None,
+ None,
+ _class_setstate,
+ )
+ else:
+ return (
+ _make_skeleton_class,
+ _class_getnewargs(obj),
+ _class_getstate(obj),
+ None,
+ None,
+ _class_setstate,
+ )
+
+
+def _class_reduce(obj):
+ """Select the reducer depending on the dynamic nature of the class obj."""
+ if obj is type(None): # noqa
+ return type, (None,)
+ elif obj is type(Ellipsis):
+ return type, (Ellipsis,)
+ elif obj is type(NotImplemented):
+ return type, (NotImplemented,)
+ elif obj in _BUILTIN_TYPE_NAMES:
+ return _builtin_type, (_BUILTIN_TYPE_NAMES[obj],)
+ elif not _should_pickle_by_reference(obj):
+ return _dynamic_class_reduce(obj)
+ return NotImplemented
+
+
+def _dict_keys_reduce(obj):
+ # Safer not to ship the full dict as sending the rest might
+ # be unintended and could potentially cause leaking of
+ # sensitive information
+ return _make_dict_keys, (list(obj),)
+
+
+def _dict_values_reduce(obj):
+ # Safer not to ship the full dict as sending the rest might
+ # be unintended and could potentially cause leaking of
+ # sensitive information
+ return _make_dict_values, (list(obj),)
+
+
+def _dict_items_reduce(obj):
+ return _make_dict_items, (dict(obj),)
+
+
+def _odict_keys_reduce(obj):
+ # Safer not to ship the full dict as sending the rest might
+ # be unintended and could potentially cause leaking of
+ # sensitive information
+ return _make_dict_keys, (list(obj), True)
+
+
+def _odict_values_reduce(obj):
+ # Safer not to ship the full dict as sending the rest might
+ # be unintended and could potentially cause leaking of
+ # sensitive information
+ return _make_dict_values, (list(obj), True)
+
+
+def _odict_items_reduce(obj):
+ return _make_dict_items, (dict(obj), True)
+
+
+def _dataclass_field_base_reduce(obj):
+ return _get_dataclass_field_type_sentinel, (obj.name,)
+
+
+# COLLECTIONS OF OBJECTS STATE SETTERS
+# ------------------------------------
+# state setters are called at unpickling time, once the object is created and
+# it has to be updated to how it was at unpickling time.
+
+
+def _function_setstate(obj, state):
+ """Update the state of a dynamic function.
+
+ As __closure__ and __globals__ are readonly attributes of a function, we
+ cannot rely on the native setstate routine of pickle.load_build, that calls
+ setattr on items of the slotstate. Instead, we have to modify them inplace.
+ """
+ state, slotstate = state
+ obj.__dict__.update(state)
+
+ obj_globals = slotstate.pop("__globals__")
+ obj_closure = slotstate.pop("__closure__")
+ # _cloudpickle_subimports is a set of submodules that must be loaded for
+ # the pickled function to work correctly at unpickling time. Now that these
+ # submodules are depickled (hence imported), they can be removed from the
+ # object's state (the object state only served as a reference holder to
+ # these submodules)
+ slotstate.pop("_cloudpickle_submodules")
+
+ obj.__globals__.update(obj_globals)
+ obj.__globals__["__builtins__"] = __builtins__
+
+ if obj_closure is not None:
+ for i, cell in enumerate(obj_closure):
+ try:
+ value = cell.cell_contents
+ except ValueError: # cell is empty
+ continue
+ obj.__closure__[i].cell_contents = value
+
+ for k, v in slotstate.items():
+ setattr(obj, k, v)
+
+
+def _class_setstate(obj, state):
+ state, slotstate = state
+ registry = None
+ for attrname, attr in state.items():
+ if attrname == "_abc_impl":
+ registry = attr
+ else:
+ # Note: setting attribute names on a class automatically triggers their
+ # interning in CPython:
+ # https://github.com/python/cpython/blob/v3.12.0/Objects/object.c#L957
+ #
+ # This means that to get deterministic pickling for a dynamic class that
+ # was initially defined in a different Python process, the pickler
+ # needs to ensure that dynamic class and function attribute names are
+ # systematically copied into a non-interned version to avoid
+ # unpredictable pickle payloads.
+ #
+ # Indeed the Pickler's memoizer relies on physical object identity to break
+ # cycles in the reference graph of the object being serialized.
+ setattr(obj, attrname, attr)
+
+ if sys.version_info >= (3, 13) and "__firstlineno__" in state:
+ # Set the Python 3.13+ only __firstlineno__ attribute one more time, as it
+ # will be automatically deleted by the `setattr(obj, attrname, attr)` call
+ # above when `attrname` is "__firstlineno__". We assume that preserving this
+ # information might be important for some users and that it not stale in the
+ # context of cloudpickle usage, hence legitimate to propagate. Furthermore it
+ # is necessary to do so to keep deterministic chained pickling as tested in
+ # test_deterministic_str_interning_for_chained_dynamic_class_pickling.
+ obj.__firstlineno__ = state["__firstlineno__"]
+
+ if registry is not None:
+ for subclass in registry:
+ obj.register(subclass)
+
+ # PEP-649/749: During pickling, we excluded the __annotate_func__ attribute but it
+ # will be created by Python. Subsequently, annotations will be recreated when
+ # __annotations__ is accessed.
+
+ return obj
+
+
+# COLLECTION OF DATACLASS UTILITIES
+# ---------------------------------
+# There are some internal sentinel values whose identity must be preserved when
+# unpickling dataclass fields. Each sentinel value has a unique name that we can
+# use to retrieve its identity at unpickling time.
+
+
+_DATACLASSE_FIELD_TYPE_SENTINELS = {
+ dataclasses._FIELD.name: dataclasses._FIELD,
+ dataclasses._FIELD_CLASSVAR.name: dataclasses._FIELD_CLASSVAR,
+ dataclasses._FIELD_INITVAR.name: dataclasses._FIELD_INITVAR,
+}
+
+
+def _get_dataclass_field_type_sentinel(name):
+ return _DATACLASSE_FIELD_TYPE_SENTINELS[name]
+
+
+class Pickler(pickle.Pickler):
+ # set of reducers defined and used by cloudpickle (private)
+ _dispatch_table = {}
+ _dispatch_table[classmethod] = _classmethod_reduce
+ _dispatch_table[io.TextIOWrapper] = _file_reduce
+ _dispatch_table[logging.Logger] = _logger_reduce
+ _dispatch_table[logging.RootLogger] = _root_logger_reduce
+ _dispatch_table[memoryview] = _memoryview_reduce
+ _dispatch_table[property] = _property_reduce
+ _dispatch_table[staticmethod] = _classmethod_reduce
+ _dispatch_table[CellType] = _cell_reduce
+ _dispatch_table[types.CodeType] = _code_reduce
+ _dispatch_table[types.GetSetDescriptorType] = _getset_descriptor_reduce
+ _dispatch_table[types.ModuleType] = _module_reduce
+ _dispatch_table[types.MethodType] = _method_reduce
+ _dispatch_table[types.MappingProxyType] = _mappingproxy_reduce
+ _dispatch_table[weakref.WeakSet] = _weakset_reduce
+ _dispatch_table[typing.TypeVar] = _typevar_reduce
+ _dispatch_table[_collections_abc.dict_keys] = _dict_keys_reduce
+ _dispatch_table[_collections_abc.dict_values] = _dict_values_reduce
+ _dispatch_table[_collections_abc.dict_items] = _dict_items_reduce
+ _dispatch_table[type(OrderedDict().keys())] = _odict_keys_reduce
+ _dispatch_table[type(OrderedDict().values())] = _odict_values_reduce
+ _dispatch_table[type(OrderedDict().items())] = _odict_items_reduce
+ _dispatch_table[abc.abstractmethod] = _classmethod_reduce
+ _dispatch_table[abc.abstractclassmethod] = _classmethod_reduce
+ _dispatch_table[abc.abstractstaticmethod] = _classmethod_reduce
+ _dispatch_table[abc.abstractproperty] = _property_reduce
+ _dispatch_table[dataclasses._FIELD_BASE] = _dataclass_field_base_reduce
+
+ dispatch_table = ChainMap(_dispatch_table, copyreg.dispatch_table)
+
+ # function reducers are defined as instance methods of cloudpickle.Pickler
+ # objects, as they rely on a cloudpickle.Pickler attribute (globals_ref)
+ def _dynamic_function_reduce(self, func):
+ """Reduce a function that is not pickleable via attribute lookup."""
+ newargs = self._function_getnewargs(func)
+ state = _function_getstate(func)
+ return (_make_function, newargs, state, None, None, _function_setstate)
+
+ def _function_reduce(self, obj):
+ """Reducer for function objects.
+
+ If obj is a top-level attribute of a file-backed module, this reducer
+ returns NotImplemented, making the cloudpickle.Pickler fall back to
+ traditional pickle.Pickler routines to save obj. Otherwise, it reduces
+ obj using a custom cloudpickle reducer designed specifically to handle
+ dynamic functions.
+ """
+ if _should_pickle_by_reference(obj):
+ return NotImplemented
+ else:
+ return self._dynamic_function_reduce(obj)
+
+ def _function_getnewargs(self, func):
+ code = func.__code__
+
+ # base_globals represents the future global namespace of func at
+ # unpickling time. Looking it up and storing it in
+ # cloudpickle.Pickler.globals_ref allow functions sharing the same
+ # globals at pickling time to also share them once unpickled, at one
+ # condition: since globals_ref is an attribute of a cloudpickle.Pickler
+ # instance, and that a new cloudpickle.Pickler is created each time
+ # cloudpickle.dump or cloudpickle.dumps is called, functions also need
+ # to be saved within the same invocation of
+ # cloudpickle.dump/cloudpickle.dumps (for example:
+ # cloudpickle.dumps([f1, f2])). There is no such limitation when using
+ # cloudpickle.Pickler.dump, as long as the multiple invocations are
+ # bound to the same cloudpickle.Pickler instance.
+ base_globals = self.globals_ref.setdefault(id(func.__globals__), {})
+
+ if base_globals == {}:
+ # Add module attributes used to resolve relative imports
+ # instructions inside func.
+ for k in ["__package__", "__name__", "__path__", "__file__"]:
+ if k in func.__globals__:
+ base_globals[k] = func.__globals__[k]
+
+ # Do not bind the free variables before the function is created to
+ # avoid infinite recursion.
+ if func.__closure__ is None:
+ closure = None
+ else:
+ closure = tuple(_make_empty_cell() for _ in range(len(code.co_freevars)))
+
+ return code, base_globals, None, None, closure
+
+ def dump(self, obj):
+ try:
+ return super().dump(obj)
+ except RecursionError as e:
+ msg = "Could not pickle object as excessively deep recursion required."
+ raise pickle.PicklingError(msg) from e
+
+ def __init__(self, file, protocol=None, buffer_callback=None):
+ if protocol is None:
+ protocol = DEFAULT_PROTOCOL
+ super().__init__(file, protocol=protocol, buffer_callback=buffer_callback)
+ # map functions __globals__ attribute ids, to ensure that functions
+ # sharing the same global namespace at pickling time also share
+ # their global namespace at unpickling time.
+ self.globals_ref = {}
+ self.proto = int(protocol)
+
+ if not PYPY:
+ # pickle.Pickler is the C implementation of the CPython pickler and
+ # therefore we rely on reduce_override method to customize the pickler
+ # behavior.
+
+ # `cloudpickle.Pickler.dispatch` is only left for backward
+ # compatibility - note that when using protocol 5,
+ # `cloudpickle.Pickler.dispatch` is not an extension of
+ # `pickle._Pickler.dispatch` dictionary, because `cloudpickle.Pickler`
+ # subclasses the C-implemented `pickle.Pickler`, which does not expose
+ # a `dispatch` attribute. Earlier versions of `cloudpickle.Pickler`
+ # used `cloudpickle.Pickler.dispatch` as a class-level attribute
+ # storing all reducers implemented by cloudpickle, but the attribute
+ # name was not a great choice given because it would collide with a
+ # similarly named attribute in the pure-Python `pickle._Pickler`
+ # implementation in the standard library.
+ dispatch = dispatch_table
+
+ # Implementation of the reducer_override callback, in order to
+ # efficiently serialize dynamic functions and classes by subclassing
+ # the C-implemented `pickle.Pickler`.
+ # TODO: decorrelate reducer_override (which is tied to CPython's
+ # implementation - would it make sense to backport it to pypy? - and
+ # pickle's protocol 5 which is implementation agnostic. Currently, the
+ # availability of both notions coincide on CPython's pickle, but it may
+ # not be the case anymore when pypy implements protocol 5.
+
+ def reducer_override(self, obj):
+ """Type-agnostic reducing callback for function and classes.
+
+ For performance reasons, subclasses of the C `pickle.Pickler` class
+ cannot register custom reducers for functions and classes in the
+ dispatch_table attribute. Reducers for such types must instead
+ implemented via the special `reducer_override` method.
+
+ Note that this method will be called for any object except a few
+ builtin-types (int, lists, dicts etc.), which differs from reducers
+ in the Pickler's dispatch_table, each of them being invoked for
+ objects of a specific type only.
+
+ This property comes in handy for classes: although most classes are
+ instances of the ``type`` metaclass, some of them can be instances
+ of other custom metaclasses (such as enum.EnumMeta for example). In
+ particular, the metaclass will likely not be known in advance, and
+ thus cannot be special-cased using an entry in the dispatch_table.
+ reducer_override, among other things, allows us to register a
+ reducer that will be called for any class, independently of its
+ type.
+
+ Notes:
+
+ * reducer_override has the priority over dispatch_table-registered
+ reducers.
+ * reducer_override can be used to fix other limitations of
+ cloudpickle for other types that suffered from type-specific
+ reducers, such as Exceptions. See
+ https://github.com/cloudpipe/cloudpickle/issues/248
+ """
+ t = type(obj)
+ try:
+ is_anyclass = issubclass(t, type)
+ except TypeError: # t is not a class (old Boost; see SF #502085)
+ is_anyclass = False
+
+ if is_anyclass:
+ return _class_reduce(obj)
+ elif isinstance(obj, types.FunctionType):
+ return self._function_reduce(obj)
+ else:
+ # fallback to save_global, including the Pickler's
+ # dispatch_table
+ return NotImplemented
+
+ else:
+ # When reducer_override is not available, hack the pure-Python
+ # Pickler's types.FunctionType and type savers. Note: the type saver
+ # must override Pickler.save_global, because pickle.py contains a
+ # hard-coded call to save_global when pickling meta-classes.
+ dispatch = pickle.Pickler.dispatch.copy()
+
+ def _save_reduce_pickle5(
+ self,
+ func,
+ args,
+ state=None,
+ listitems=None,
+ dictitems=None,
+ state_setter=None,
+ obj=None,
+ ):
+ save = self.save
+ write = self.write
+ self.save_reduce(
+ func,
+ args,
+ state=None,
+ listitems=listitems,
+ dictitems=dictitems,
+ obj=obj,
+ )
+ # backport of the Python 3.8 state_setter pickle operations
+ save(state_setter)
+ save(obj) # simple BINGET opcode as obj is already memoized.
+ save(state)
+ write(pickle.TUPLE2)
+ # Trigger a state_setter(obj, state) function call.
+ write(pickle.REDUCE)
+ # The purpose of state_setter is to carry-out an
+ # inplace modification of obj. We do not care about what the
+ # method might return, so its output is eventually removed from
+ # the stack.
+ write(pickle.POP)
+
+ def save_global(self, obj, name=None, pack=struct.pack):
+ """Main dispatch method.
+
+ The name of this method is somewhat misleading: all types get
+ dispatched here.
+ """
+ if obj is type(None): # noqa
+ return self.save_reduce(type, (None,), obj=obj)
+ elif obj is type(Ellipsis):
+ return self.save_reduce(type, (Ellipsis,), obj=obj)
+ elif obj is type(NotImplemented):
+ return self.save_reduce(type, (NotImplemented,), obj=obj)
+ elif obj in _BUILTIN_TYPE_NAMES:
+ return self.save_reduce(
+ _builtin_type, (_BUILTIN_TYPE_NAMES[obj],), obj=obj
+ )
+
+ if name is not None:
+ super().save_global(obj, name=name)
+ elif not _should_pickle_by_reference(obj, name=name):
+ self._save_reduce_pickle5(*_dynamic_class_reduce(obj), obj=obj)
+ else:
+ super().save_global(obj, name=name)
+
+ dispatch[type] = save_global
+
+ def save_function(self, obj, name=None):
+ """Registered with the dispatch to handle all function types.
+
+ Determines what kind of function obj is (e.g. lambda, defined at
+ interactive prompt, etc) and handles the pickling appropriately.
+ """
+ if _should_pickle_by_reference(obj, name=name):
+ return super().save_global(obj, name=name)
+ elif PYPY and isinstance(obj.__code__, builtin_code_type):
+ return self.save_pypy_builtin_func(obj)
+ else:
+ return self._save_reduce_pickle5(
+ *self._dynamic_function_reduce(obj), obj=obj
+ )
+
+ def save_pypy_builtin_func(self, obj):
+ """Save pypy equivalent of builtin functions.
+
+ PyPy does not have the concept of builtin-functions. Instead,
+ builtin-functions are simple function instances, but with a
+ builtin-code attribute.
+ Most of the time, builtin functions should be pickled by attribute.
+ But PyPy has flaky support for __qualname__, so some builtin
+ functions such as float.__new__ will be classified as dynamic. For
+ this reason only, we created this special routine. Because
+ builtin-functions are not expected to have closure or globals,
+ there is no additional hack (compared the one already implemented
+ in pickle) to protect ourselves from reference cycles. A simple
+ (reconstructor, newargs, obj.__dict__) tuple is save_reduced. Note
+ also that PyPy improved their support for __qualname__ in v3.6, so
+ this routing should be removed when cloudpickle supports only PyPy
+ 3.6 and later.
+ """
+ rv = (
+ types.FunctionType,
+ (obj.__code__, {}, obj.__name__, obj.__defaults__, obj.__closure__),
+ obj.__dict__,
+ )
+ self.save_reduce(*rv, obj=obj)
+
+ dispatch[types.FunctionType] = save_function
+
+
+# Shorthands similar to pickle.dump/pickle.dumps
+
+
+def dump(obj, file, protocol=None, buffer_callback=None):
+ """Serialize obj as bytes streamed into file
+
+ protocol defaults to cloudpickle.DEFAULT_PROTOCOL which is an alias to
+ pickle.HIGHEST_PROTOCOL. This setting favors maximum communication
+ speed between processes running the same Python version.
+
+ Set protocol=pickle.DEFAULT_PROTOCOL instead if you need to ensure
+ compatibility with older versions of Python (although this is not always
+ guaranteed to work because cloudpickle relies on some internal
+ implementation details that can change from one Python version to the
+ next).
+ """
+ Pickler(file, protocol=protocol, buffer_callback=buffer_callback).dump(obj)
+
+
+def dumps(obj, protocol=None, buffer_callback=None):
+ """Serialize obj as a string of bytes allocated in memory
+
+ protocol defaults to cloudpickle.DEFAULT_PROTOCOL which is an alias to
+ pickle.HIGHEST_PROTOCOL. This setting favors maximum communication
+ speed between processes running the same Python version.
+
+ Set protocol=pickle.DEFAULT_PROTOCOL instead if you need to ensure
+ compatibility with older versions of Python (although this is not always
+ guaranteed to work because cloudpickle relies on some internal
+ implementation details that can change from one Python version to the
+ next).
+ """
+ with io.BytesIO() as file:
+ cp = Pickler(file, protocol=protocol, buffer_callback=buffer_callback)
+ cp.dump(obj)
+ return file.getvalue()
+
+
+# Include pickles unloading functions in this namespace for convenience.
+load, loads = pickle.load, pickle.loads
+
+# Backward compat alias.
+CloudPickler = Pickler
diff --git a/lib/python3.12/site-packages/cloudpickle/cloudpickle_fast.py b/lib/python3.12/site-packages/cloudpickle/cloudpickle_fast.py
new file mode 100644
index 0000000000000000000000000000000000000000..20280f0ca354a691861ab6f17821bbeb04632003
--- /dev/null
+++ b/lib/python3.12/site-packages/cloudpickle/cloudpickle_fast.py
@@ -0,0 +1,14 @@
+"""Compatibility module.
+
+It can be necessary to load files generated by previous versions of cloudpickle
+that rely on symbols being defined under the `cloudpickle.cloudpickle_fast`
+namespace.
+
+See: tests/test_backward_compat.py
+"""
+
+from . import cloudpickle
+
+
+def __getattr__(name):
+ return getattr(cloudpickle, name)
diff --git a/lib/python3.12/site-packages/ninja-1.13.0.dist-info/INSTALLER b/lib/python3.12/site-packages/ninja-1.13.0.dist-info/INSTALLER
new file mode 100644
index 0000000000000000000000000000000000000000..a1b589e38a32041e49332e5e81c2d363dc418d68
--- /dev/null
+++ b/lib/python3.12/site-packages/ninja-1.13.0.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/lib/python3.12/site-packages/ninja-1.13.0.dist-info/METADATA b/lib/python3.12/site-packages/ninja-1.13.0.dist-info/METADATA
new file mode 100644
index 0000000000000000000000000000000000000000..b2ef543b933135817ff56c1e5354c1c90e29f59a
--- /dev/null
+++ b/lib/python3.12/site-packages/ninja-1.13.0.dist-info/METADATA
@@ -0,0 +1,102 @@
+Metadata-Version: 2.1
+Name: ninja
+Version: 1.13.0
+Summary: Ninja is a small build system with a focus on speed
+Keywords: build,c++,cross-compilation,cross-platform,fortran,ninja
+Author-Email: Jean-Christophe Fillion-Robin , Henry Schreiner
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: Apache Software License
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: C
+Classifier: Programming Language :: C++
+Classifier: Programming Language :: Fortran
+Classifier: Programming Language :: Python
+Classifier: Topic :: Software Development :: Build Tools
+Classifier: Typing :: Typed
+Project-URL: Bug Tracker, https://github.com/scikit-build/ninja-python-distributions/issues
+Project-URL: Documentation, https://github.com/scikit-build/ninja-python-distributions#readme
+Project-URL: Download, https://github.com/ninja-build/ninja/releases
+Project-URL: Homepage, http://ninja-build.org/
+Project-URL: Mailing list, https://groups.google.com/forum/#!forum/scikit-build
+Project-URL: Source Code, https://github.com/scikit-build/ninja-python-distributions
+Requires-Python: >=3.8
+Description-Content-Type: text/x-rst
+
+==========================
+Ninja Python Distributions
+==========================
+
+`Ninja `_ is a small build system with a focus on speed.
+
+The latest Ninja python wheels provide `ninja 1.13.0.gd74ef.kitware.jobserver-pipe-1 `_ executable
+and `ninja_syntax.py` for generating `.ninja` files.
+
+.. image:: https://raw.githubusercontent.com/scikit-build/ninja-python-distributions/master/ninja-python-distributions-logo.png
+
+Latest Release
+--------------
+
+.. table::
+
+ +----------------------------------------------------------------------+---------------------------------------------------------------------------+
+ | Versions | Downloads |
+ +======================================================================+===========================================================================+
+ | .. image:: https://img.shields.io/pypi/v/ninja.svg | .. image:: https://img.shields.io/badge/downloads-2535k%20total-green.svg |
+ | :target: https://pypi.python.org/pypi/ninja | :target: https://pypi.python.org/pypi/ninja |
+ +----------------------------------------------------------------------+---------------------------------------------------------------------------+
+
+Build Status
+------------
+
+.. table::
+
+ +---------------+-------------------------------------------------------------------------------------------------------------+
+ | | GitHub Actions (Windows, macOS, Linux) |
+ +===============+=============================================================================================================+
+ | PyPI | .. image:: https://github.com/scikit-build/ninja-python-distributions/actions/workflows/build.yml/badge.svg |
+ | | :target: https://github.com/scikit-build/ninja-python-distributions/actions/workflows/build.yml |
+ +---------------+-------------------------------------------------------------------------------------------------------------+
+
+Maintainers
+-----------
+
+* `How to update ninja version ? `_
+
+* `How to make a release ? `_
+
+
+Miscellaneous
+-------------
+
+* Documentation: https://github.com/scikit-build/ninja-python-distributions#readme
+* Source code: https://github.com/scikit-build/ninja-python-distributions
+* Mailing list: https://groups.google.com/forum/#!forum/scikit-build
+
+Python Version Support
+----------------------
+
+Versions after 1.11.1.1 no longer support Python 2-3.6, and require manylinux2010+ on linux.
+Versions after 1.13 no longer support Python 3.7, and require manylinux2014+/musllinux_1_2+ on linux.
+
+License
+-------
+
+This project is maintained by Jean-Christophe Fillion-Robin from Kitware Inc.
+It is covered by the `Apache License, Version 2.0 `_.
+
+Ninja is also distributed under the `Apache License, Version 2.0 `_.
+For more information about Ninja, visit https://ninja-build.org
+
+Logo was originally created by Libby Rose from Kitware Inc.
+It is covered by `CC BY 4.0 `_.
+
+
+History
+-------
+
+ninja-python-distributions was initially developed in November 2016 by
+Jean-Christophe Fillion-Robin to facilitate the distribution of project using
+`scikit-build `_ and depending on CMake
+and Ninja.
diff --git a/lib/python3.12/site-packages/ninja-1.13.0.dist-info/RECORD b/lib/python3.12/site-packages/ninja-1.13.0.dist-info/RECORD
new file mode 100644
index 0000000000000000000000000000000000000000..ebd353f47262eaaebbadc74eb6b1aec8b26697a9
--- /dev/null
+++ b/lib/python3.12/site-packages/ninja-1.13.0.dist-info/RECORD
@@ -0,0 +1,18 @@
+../../../bin/ninja,sha256=aW-WKKednOUDFM-VVtfNGh0exSuP1Sgo9vnbFxlWW2c,372384
+ninja-1.13.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+ninja-1.13.0.dist-info/METADATA,sha256=jXb8Tjgs7c0ivK6qdIrzmz-nkxtyRCOW0VyxgWWdCk4,5148
+ninja-1.13.0.dist-info/RECORD,,
+ninja-1.13.0.dist-info/WHEEL,sha256=zzOwTeuxXsHOT9QV_vcZk1hX9KJAUdqJD7e-2jGJxLA,150
+ninja-1.13.0.dist-info/licenses/AUTHORS.rst,sha256=bGE1t_Lhm2ir8S7n_jbLDohP84fpJ5sNCuxvDVsKNQg,142
+ninja-1.13.0.dist-info/licenses/LICENSE_Apache_20,sha256=c7p036pSC0mkAbXSFFmoUjoUbzt1GKgz7qXvqFEwv2g,10273
+ninja/__init__.py,sha256=taDHI20kpmjxOT72PiSyE42Pvz3KLXlwMfTZvvnRMKM,1533
+ninja/__main__.py,sha256=6iPLwHHAc2TMbojFVcUzERrzN0RvIsywuZc4KpJCg_4,100
+ninja/__pycache__/__init__.cpython-312.pyc,,
+ninja/__pycache__/__main__.cpython-312.pyc,,
+ninja/__pycache__/_version.cpython-312.pyc,,
+ninja/__pycache__/ninja_syntax.cpython-312.pyc,,
+ninja/_version.py,sha256=M85oP8JJdZ4yZHcp9qfGYLKUYvnN3kTyQosVcYPCPow,19
+ninja/_version.pyi,sha256=j5kbzfm6lOn8BzASXWjGIA1yT0OlHTWqlbyZ8Si_o0E,118
+ninja/ninja_syntax.py,sha256=RCXZ6Roda3lwnbhtQw6I6bJcpE98mXUZ9jocnvC4IQY,8148
+ninja/ninja_syntax.pyi,sha256=5IHH7N9CTKnMDDetFKHOsPK0SOSK_7Q4YtgzhIMNLE0,1576
+ninja/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
diff --git a/lib/python3.12/site-packages/ninja-1.13.0.dist-info/WHEEL b/lib/python3.12/site-packages/ninja-1.13.0.dist-info/WHEEL
new file mode 100644
index 0000000000000000000000000000000000000000..0a6a9a310a0d2edd46721b7b00182339807a1e25
--- /dev/null
+++ b/lib/python3.12/site-packages/ninja-1.13.0.dist-info/WHEEL
@@ -0,0 +1,6 @@
+Wheel-Version: 1.0
+Generator: scikit-build-core 0.11.5
+Root-Is-Purelib: false
+Tag: py3-none-manylinux_2_17_x86_64
+Tag: py3-none-manylinux2014_x86_64
+
diff --git a/lib/python3.12/site-packages/ninja-1.13.0.dist-info/licenses/AUTHORS.rst b/lib/python3.12/site-packages/ninja-1.13.0.dist-info/licenses/AUTHORS.rst
new file mode 100644
index 0000000000000000000000000000000000000000..b1b06c180f71d5a97709335823145b230576f2c5
--- /dev/null
+++ b/lib/python3.12/site-packages/ninja-1.13.0.dist-info/licenses/AUTHORS.rst
@@ -0,0 +1,5 @@
+=======
+Credits
+=======
+
+Please see the GitHub project page at https://github.com/scikit-build/ninja-python-distributions/graphs/contributors
diff --git a/lib/python3.12/site-packages/ninja-1.13.0.dist-info/licenses/LICENSE_Apache_20 b/lib/python3.12/site-packages/ninja-1.13.0.dist-info/licenses/LICENSE_Apache_20
new file mode 100644
index 0000000000000000000000000000000000000000..37ec93a14fdcd0d6e525d97c0cfa6b314eaa98d8
--- /dev/null
+++ b/lib/python3.12/site-packages/ninja-1.13.0.dist-info/licenses/LICENSE_Apache_20
@@ -0,0 +1,191 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work
+
+To apply the Apache License to your work, attach the following boilerplate
+notice, with the fields enclosed by brackets "[]" replaced with your own
+identifying information. (Don't include the brackets!) The text should be
+enclosed in the appropriate comment syntax for the file format. We also
+recommend that a file or class name and description of purpose be included on
+the same "printed page" as the copyright notice for easier identification within
+third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/lib/python3.12/site-packages/numpy/__config__.py b/lib/python3.12/site-packages/numpy/__config__.py
new file mode 100644
index 0000000000000000000000000000000000000000..361cf053ddf1cf04a73f117f6bcffc7f928f6349
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/__config__.py
@@ -0,0 +1,162 @@
+# This file is generated by numpy's build process
+# It contains system_info results at the time of building this package.
+from enum import Enum
+from numpy.core._multiarray_umath import (
+ __cpu_features__,
+ __cpu_baseline__,
+ __cpu_dispatch__,
+)
+
+__all__ = ["show"]
+_built_with_meson = True
+
+
+class DisplayModes(Enum):
+ stdout = "stdout"
+ dicts = "dicts"
+
+
+def _cleanup(d):
+ """
+ Removes empty values in a `dict` recursively
+ This ensures we remove values that Meson could not provide to CONFIG
+ """
+ if isinstance(d, dict):
+ return {k: _cleanup(v) for k, v in d.items() if v and _cleanup(v)}
+ else:
+ return d
+
+
+CONFIG = _cleanup(
+ {
+ "Compilers": {
+ "c": {
+ "name": "gcc",
+ "linker": r"ld.bfd",
+ "version": "10.2.1",
+ "commands": r"cc",
+ "args": r"-fno-strict-aliasing",
+ "linker args": r"-Wl,--strip-debug, -fno-strict-aliasing",
+ },
+ "cython": {
+ "name": "cython",
+ "linker": r"cython",
+ "version": "3.0.8",
+ "commands": r"cython",
+ "args": r"",
+ "linker args": r"",
+ },
+ "c++": {
+ "name": "gcc",
+ "linker": r"ld.bfd",
+ "version": "10.2.1",
+ "commands": r"c++",
+ "args": r"",
+ "linker args": r"-Wl,--strip-debug",
+ },
+ },
+ "Machine Information": {
+ "host": {
+ "cpu": "x86_64",
+ "family": "x86_64",
+ "endian": "little",
+ "system": "linux",
+ },
+ "build": {
+ "cpu": "x86_64",
+ "family": "x86_64",
+ "endian": "little",
+ "system": "linux",
+ },
+ "cross-compiled": bool("False".lower().replace("false", "")),
+ },
+ "Build Dependencies": {
+ "blas": {
+ "name": "openblas64",
+ "found": bool("True".lower().replace("false", "")),
+ "version": "0.3.23.dev",
+ "detection method": "pkgconfig",
+ "include directory": r"/usr/local/include",
+ "lib directory": r"/usr/local/lib",
+ "openblas configuration": r"USE_64BITINT=1 DYNAMIC_ARCH=1 DYNAMIC_OLDER= NO_CBLAS= NO_LAPACK= NO_LAPACKE= NO_AFFINITY=1 USE_OPENMP= HASWELL MAX_THREADS=2",
+ "pc file directory": r"/usr/local/lib/pkgconfig",
+ },
+ "lapack": {
+ "name": "dep140551260102944",
+ "found": bool("True".lower().replace("false", "")),
+ "version": "1.26.4",
+ "detection method": "internal",
+ "include directory": r"unknown",
+ "lib directory": r"unknown",
+ "openblas configuration": r"unknown",
+ "pc file directory": r"unknown",
+ },
+ },
+ "Python Information": {
+ "path": r"/opt/python/cp312-cp312/bin/python",
+ "version": "3.12",
+ },
+ "SIMD Extensions": {
+ "baseline": __cpu_baseline__,
+ "found": [
+ feature for feature in __cpu_dispatch__ if __cpu_features__[feature]
+ ],
+ "not found": [
+ feature for feature in __cpu_dispatch__ if not __cpu_features__[feature]
+ ],
+ },
+ }
+)
+
+
+def _check_pyyaml():
+ import yaml
+
+ return yaml
+
+
+def show(mode=DisplayModes.stdout.value):
+ """
+ Show libraries and system information on which NumPy was built
+ and is being used
+
+ Parameters
+ ----------
+ mode : {`'stdout'`, `'dicts'`}, optional.
+ Indicates how to display the config information.
+ `'stdout'` prints to console, `'dicts'` returns a dictionary
+ of the configuration.
+
+ Returns
+ -------
+ out : {`dict`, `None`}
+ If mode is `'dicts'`, a dict is returned, else None
+
+ See Also
+ --------
+ get_include : Returns the directory containing NumPy C
+ header files.
+
+ Notes
+ -----
+ 1. The `'stdout'` mode will give more readable
+ output if ``pyyaml`` is installed
+
+ """
+ if mode == DisplayModes.stdout.value:
+ try: # Non-standard library, check import
+ yaml = _check_pyyaml()
+
+ print(yaml.dump(CONFIG))
+ except ModuleNotFoundError:
+ import warnings
+ import json
+
+ warnings.warn("Install `pyyaml` for better output", stacklevel=1)
+ print(json.dumps(CONFIG, indent=2))
+ elif mode == DisplayModes.dicts.value:
+ return CONFIG
+ else:
+ raise AttributeError(
+ f"Invalid `mode`, use one of: {', '.join([e.value for e in DisplayModes])}"
+ )
diff --git a/lib/python3.12/site-packages/numpy/__init__.cython-30.pxd b/lib/python3.12/site-packages/numpy/__init__.cython-30.pxd
new file mode 100644
index 0000000000000000000000000000000000000000..1409514f7a845501a7787f6acb3a5570502d330d
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/__init__.cython-30.pxd
@@ -0,0 +1,1050 @@
+# NumPy static imports for Cython >= 3.0
+#
+# If any of the PyArray_* functions are called, import_array must be
+# called first. This is done automatically by Cython 3.0+ if a call
+# is not detected inside of the module.
+#
+# Author: Dag Sverre Seljebotn
+#
+
+from cpython.ref cimport Py_INCREF
+from cpython.object cimport PyObject, PyTypeObject, PyObject_TypeCheck
+cimport libc.stdio as stdio
+
+
+cdef extern from *:
+ # Leave a marker that the NumPy declarations came from NumPy itself and not from Cython.
+ # See https://github.com/cython/cython/issues/3573
+ """
+ /* Using NumPy API declarations from "numpy/__init__.cython-30.pxd" */
+ """
+
+
+cdef extern from "Python.h":
+ ctypedef int Py_intptr_t
+
+cdef extern from "numpy/arrayobject.h":
+ ctypedef Py_intptr_t npy_intp
+ ctypedef size_t npy_uintp
+
+ cdef enum NPY_TYPES:
+ NPY_BOOL
+ NPY_BYTE
+ NPY_UBYTE
+ NPY_SHORT
+ NPY_USHORT
+ NPY_INT
+ NPY_UINT
+ NPY_LONG
+ NPY_ULONG
+ NPY_LONGLONG
+ NPY_ULONGLONG
+ NPY_FLOAT
+ NPY_DOUBLE
+ NPY_LONGDOUBLE
+ NPY_CFLOAT
+ NPY_CDOUBLE
+ NPY_CLONGDOUBLE
+ NPY_OBJECT
+ NPY_STRING
+ NPY_UNICODE
+ NPY_VOID
+ NPY_DATETIME
+ NPY_TIMEDELTA
+ NPY_NTYPES
+ NPY_NOTYPE
+
+ NPY_INT8
+ NPY_INT16
+ NPY_INT32
+ NPY_INT64
+ NPY_INT128
+ NPY_INT256
+ NPY_UINT8
+ NPY_UINT16
+ NPY_UINT32
+ NPY_UINT64
+ NPY_UINT128
+ NPY_UINT256
+ NPY_FLOAT16
+ NPY_FLOAT32
+ NPY_FLOAT64
+ NPY_FLOAT80
+ NPY_FLOAT96
+ NPY_FLOAT128
+ NPY_FLOAT256
+ NPY_COMPLEX32
+ NPY_COMPLEX64
+ NPY_COMPLEX128
+ NPY_COMPLEX160
+ NPY_COMPLEX192
+ NPY_COMPLEX256
+ NPY_COMPLEX512
+
+ NPY_INTP
+
+ ctypedef enum NPY_ORDER:
+ NPY_ANYORDER
+ NPY_CORDER
+ NPY_FORTRANORDER
+ NPY_KEEPORDER
+
+ ctypedef enum NPY_CASTING:
+ NPY_NO_CASTING
+ NPY_EQUIV_CASTING
+ NPY_SAFE_CASTING
+ NPY_SAME_KIND_CASTING
+ NPY_UNSAFE_CASTING
+
+ ctypedef enum NPY_CLIPMODE:
+ NPY_CLIP
+ NPY_WRAP
+ NPY_RAISE
+
+ ctypedef enum NPY_SCALARKIND:
+ NPY_NOSCALAR,
+ NPY_BOOL_SCALAR,
+ NPY_INTPOS_SCALAR,
+ NPY_INTNEG_SCALAR,
+ NPY_FLOAT_SCALAR,
+ NPY_COMPLEX_SCALAR,
+ NPY_OBJECT_SCALAR
+
+ ctypedef enum NPY_SORTKIND:
+ NPY_QUICKSORT
+ NPY_HEAPSORT
+ NPY_MERGESORT
+
+ ctypedef enum NPY_SEARCHSIDE:
+ NPY_SEARCHLEFT
+ NPY_SEARCHRIGHT
+
+ enum:
+ # DEPRECATED since NumPy 1.7 ! Do not use in new code!
+ NPY_C_CONTIGUOUS
+ NPY_F_CONTIGUOUS
+ NPY_CONTIGUOUS
+ NPY_FORTRAN
+ NPY_OWNDATA
+ NPY_FORCECAST
+ NPY_ENSURECOPY
+ NPY_ENSUREARRAY
+ NPY_ELEMENTSTRIDES
+ NPY_ALIGNED
+ NPY_NOTSWAPPED
+ NPY_WRITEABLE
+ NPY_ARR_HAS_DESCR
+
+ NPY_BEHAVED
+ NPY_BEHAVED_NS
+ NPY_CARRAY
+ NPY_CARRAY_RO
+ NPY_FARRAY
+ NPY_FARRAY_RO
+ NPY_DEFAULT
+
+ NPY_IN_ARRAY
+ NPY_OUT_ARRAY
+ NPY_INOUT_ARRAY
+ NPY_IN_FARRAY
+ NPY_OUT_FARRAY
+ NPY_INOUT_FARRAY
+
+ NPY_UPDATE_ALL
+
+ enum:
+ # Added in NumPy 1.7 to replace the deprecated enums above.
+ NPY_ARRAY_C_CONTIGUOUS
+ NPY_ARRAY_F_CONTIGUOUS
+ NPY_ARRAY_OWNDATA
+ NPY_ARRAY_FORCECAST
+ NPY_ARRAY_ENSURECOPY
+ NPY_ARRAY_ENSUREARRAY
+ NPY_ARRAY_ELEMENTSTRIDES
+ NPY_ARRAY_ALIGNED
+ NPY_ARRAY_NOTSWAPPED
+ NPY_ARRAY_WRITEABLE
+ NPY_ARRAY_WRITEBACKIFCOPY
+
+ NPY_ARRAY_BEHAVED
+ NPY_ARRAY_BEHAVED_NS
+ NPY_ARRAY_CARRAY
+ NPY_ARRAY_CARRAY_RO
+ NPY_ARRAY_FARRAY
+ NPY_ARRAY_FARRAY_RO
+ NPY_ARRAY_DEFAULT
+
+ NPY_ARRAY_IN_ARRAY
+ NPY_ARRAY_OUT_ARRAY
+ NPY_ARRAY_INOUT_ARRAY
+ NPY_ARRAY_IN_FARRAY
+ NPY_ARRAY_OUT_FARRAY
+ NPY_ARRAY_INOUT_FARRAY
+
+ NPY_ARRAY_UPDATE_ALL
+
+ cdef enum:
+ NPY_MAXDIMS
+
+ npy_intp NPY_MAX_ELSIZE
+
+ ctypedef void (*PyArray_VectorUnaryFunc)(void *, void *, npy_intp, void *, void *)
+
+ ctypedef struct PyArray_ArrayDescr:
+ # shape is a tuple, but Cython doesn't support "tuple shape"
+ # inside a non-PyObject declaration, so we have to declare it
+ # as just a PyObject*.
+ PyObject* shape
+
+ ctypedef struct PyArray_Descr:
+ pass
+
+ ctypedef class numpy.dtype [object PyArray_Descr, check_size ignore]:
+ # Use PyDataType_* macros when possible, however there are no macros
+ # for accessing some of the fields, so some are defined.
+ cdef PyTypeObject* typeobj
+ cdef char kind
+ cdef char type
+ # Numpy sometimes mutates this without warning (e.g. it'll
+ # sometimes change "|" to "<" in shared dtype objects on
+ # little-endian machines). If this matters to you, use
+ # PyArray_IsNativeByteOrder(dtype.byteorder) instead of
+ # directly accessing this field.
+ cdef char byteorder
+ cdef char flags
+ cdef int type_num
+ cdef int itemsize "elsize"
+ cdef int alignment
+ cdef object fields
+ cdef tuple names
+ # Use PyDataType_HASSUBARRAY to test whether this field is
+ # valid (the pointer can be NULL). Most users should access
+ # this field via the inline helper method PyDataType_SHAPE.
+ cdef PyArray_ArrayDescr* subarray
+
+ ctypedef class numpy.flatiter [object PyArrayIterObject, check_size ignore]:
+ # Use through macros
+ pass
+
+ ctypedef class numpy.broadcast [object PyArrayMultiIterObject, check_size ignore]:
+ # Use through macros
+ pass
+
+ ctypedef struct PyArrayObject:
+ # For use in situations where ndarray can't replace PyArrayObject*,
+ # like PyArrayObject**.
+ pass
+
+ ctypedef class numpy.ndarray [object PyArrayObject, check_size ignore]:
+ cdef __cythonbufferdefaults__ = {"mode": "strided"}
+
+ # NOTE: no field declarations since direct access is deprecated since NumPy 1.7
+ # Instead, we use properties that map to the corresponding C-API functions.
+
+ @property
+ cdef inline PyObject* base(self) nogil:
+ """Returns a borrowed reference to the object owning the data/memory.
+ """
+ return PyArray_BASE(self)
+
+ @property
+ cdef inline dtype descr(self):
+ """Returns an owned reference to the dtype of the array.
+ """
+ return PyArray_DESCR(self)
+
+ @property
+ cdef inline int ndim(self) nogil:
+ """Returns the number of dimensions in the array.
+ """
+ return PyArray_NDIM(self)
+
+ @property
+ cdef inline npy_intp *shape(self) nogil:
+ """Returns a pointer to the dimensions/shape of the array.
+ The number of elements matches the number of dimensions of the array (ndim).
+ Can return NULL for 0-dimensional arrays.
+ """
+ return PyArray_DIMS(self)
+
+ @property
+ cdef inline npy_intp *strides(self) nogil:
+ """Returns a pointer to the strides of the array.
+ The number of elements matches the number of dimensions of the array (ndim).
+ """
+ return PyArray_STRIDES(self)
+
+ @property
+ cdef inline npy_intp size(self) nogil:
+ """Returns the total size (in number of elements) of the array.
+ """
+ return PyArray_SIZE(self)
+
+ @property
+ cdef inline char* data(self) nogil:
+ """The pointer to the data buffer as a char*.
+ This is provided for legacy reasons to avoid direct struct field access.
+ For new code that needs this access, you probably want to cast the result
+ of `PyArray_DATA()` instead, which returns a 'void*'.
+ """
+ return PyArray_BYTES(self)
+
+ ctypedef unsigned char npy_bool
+
+ ctypedef signed char npy_byte
+ ctypedef signed short npy_short
+ ctypedef signed int npy_int
+ ctypedef signed long npy_long
+ ctypedef signed long long npy_longlong
+
+ ctypedef unsigned char npy_ubyte
+ ctypedef unsigned short npy_ushort
+ ctypedef unsigned int npy_uint
+ ctypedef unsigned long npy_ulong
+ ctypedef unsigned long long npy_ulonglong
+
+ ctypedef float npy_float
+ ctypedef double npy_double
+ ctypedef long double npy_longdouble
+
+ ctypedef signed char npy_int8
+ ctypedef signed short npy_int16
+ ctypedef signed int npy_int32
+ ctypedef signed long long npy_int64
+ ctypedef signed long long npy_int96
+ ctypedef signed long long npy_int128
+
+ ctypedef unsigned char npy_uint8
+ ctypedef unsigned short npy_uint16
+ ctypedef unsigned int npy_uint32
+ ctypedef unsigned long long npy_uint64
+ ctypedef unsigned long long npy_uint96
+ ctypedef unsigned long long npy_uint128
+
+ ctypedef float npy_float32
+ ctypedef double npy_float64
+ ctypedef long double npy_float80
+ ctypedef long double npy_float96
+ ctypedef long double npy_float128
+
+ ctypedef struct npy_cfloat:
+ float real
+ float imag
+
+ ctypedef struct npy_cdouble:
+ double real
+ double imag
+
+ ctypedef struct npy_clongdouble:
+ long double real
+ long double imag
+
+ ctypedef struct npy_complex64:
+ float real
+ float imag
+
+ ctypedef struct npy_complex128:
+ double real
+ double imag
+
+ ctypedef struct npy_complex160:
+ long double real
+ long double imag
+
+ ctypedef struct npy_complex192:
+ long double real
+ long double imag
+
+ ctypedef struct npy_complex256:
+ long double real
+ long double imag
+
+ ctypedef struct PyArray_Dims:
+ npy_intp *ptr
+ int len
+
+ int _import_array() except -1
+ # A second definition so _import_array isn't marked as used when we use it here.
+ # Do not use - subject to change any time.
+ int __pyx_import_array "_import_array"() except -1
+
+ #
+ # Macros from ndarrayobject.h
+ #
+ bint PyArray_CHKFLAGS(ndarray m, int flags) nogil
+ bint PyArray_IS_C_CONTIGUOUS(ndarray arr) nogil
+ bint PyArray_IS_F_CONTIGUOUS(ndarray arr) nogil
+ bint PyArray_ISCONTIGUOUS(ndarray m) nogil
+ bint PyArray_ISWRITEABLE(ndarray m) nogil
+ bint PyArray_ISALIGNED(ndarray m) nogil
+
+ int PyArray_NDIM(ndarray) nogil
+ bint PyArray_ISONESEGMENT(ndarray) nogil
+ bint PyArray_ISFORTRAN(ndarray) nogil
+ int PyArray_FORTRANIF(ndarray) nogil
+
+ void* PyArray_DATA(ndarray) nogil
+ char* PyArray_BYTES(ndarray) nogil
+
+ npy_intp* PyArray_DIMS(ndarray) nogil
+ npy_intp* PyArray_STRIDES(ndarray) nogil
+ npy_intp PyArray_DIM(ndarray, size_t) nogil
+ npy_intp PyArray_STRIDE(ndarray, size_t) nogil
+
+ PyObject *PyArray_BASE(ndarray) nogil # returns borrowed reference!
+ PyArray_Descr *PyArray_DESCR(ndarray) nogil # returns borrowed reference to dtype!
+ PyArray_Descr *PyArray_DTYPE(ndarray) nogil # returns borrowed reference to dtype! NP 1.7+ alias for descr.
+ int PyArray_FLAGS(ndarray) nogil
+ void PyArray_CLEARFLAGS(ndarray, int flags) nogil # Added in NumPy 1.7
+ void PyArray_ENABLEFLAGS(ndarray, int flags) nogil # Added in NumPy 1.7
+ npy_intp PyArray_ITEMSIZE(ndarray) nogil
+ int PyArray_TYPE(ndarray arr) nogil
+
+ object PyArray_GETITEM(ndarray arr, void *itemptr)
+ int PyArray_SETITEM(ndarray arr, void *itemptr, object obj) except -1
+
+ bint PyTypeNum_ISBOOL(int) nogil
+ bint PyTypeNum_ISUNSIGNED(int) nogil
+ bint PyTypeNum_ISSIGNED(int) nogil
+ bint PyTypeNum_ISINTEGER(int) nogil
+ bint PyTypeNum_ISFLOAT(int) nogil
+ bint PyTypeNum_ISNUMBER(int) nogil
+ bint PyTypeNum_ISSTRING(int) nogil
+ bint PyTypeNum_ISCOMPLEX(int) nogil
+ bint PyTypeNum_ISPYTHON(int) nogil
+ bint PyTypeNum_ISFLEXIBLE(int) nogil
+ bint PyTypeNum_ISUSERDEF(int) nogil
+ bint PyTypeNum_ISEXTENDED(int) nogil
+ bint PyTypeNum_ISOBJECT(int) nogil
+
+ bint PyDataType_ISBOOL(dtype) nogil
+ bint PyDataType_ISUNSIGNED(dtype) nogil
+ bint PyDataType_ISSIGNED(dtype) nogil
+ bint PyDataType_ISINTEGER(dtype) nogil
+ bint PyDataType_ISFLOAT(dtype) nogil
+ bint PyDataType_ISNUMBER(dtype) nogil
+ bint PyDataType_ISSTRING(dtype) nogil
+ bint PyDataType_ISCOMPLEX(dtype) nogil
+ bint PyDataType_ISPYTHON(dtype) nogil
+ bint PyDataType_ISFLEXIBLE(dtype) nogil
+ bint PyDataType_ISUSERDEF(dtype) nogil
+ bint PyDataType_ISEXTENDED(dtype) nogil
+ bint PyDataType_ISOBJECT(dtype) nogil
+ bint PyDataType_HASFIELDS(dtype) nogil
+ bint PyDataType_HASSUBARRAY(dtype) nogil
+
+ bint PyArray_ISBOOL(ndarray) nogil
+ bint PyArray_ISUNSIGNED(ndarray) nogil
+ bint PyArray_ISSIGNED(ndarray) nogil
+ bint PyArray_ISINTEGER(ndarray) nogil
+ bint PyArray_ISFLOAT(ndarray) nogil
+ bint PyArray_ISNUMBER(ndarray) nogil
+ bint PyArray_ISSTRING(ndarray) nogil
+ bint PyArray_ISCOMPLEX(ndarray) nogil
+ bint PyArray_ISPYTHON(ndarray) nogil
+ bint PyArray_ISFLEXIBLE(ndarray) nogil
+ bint PyArray_ISUSERDEF(ndarray) nogil
+ bint PyArray_ISEXTENDED(ndarray) nogil
+ bint PyArray_ISOBJECT(ndarray) nogil
+ bint PyArray_HASFIELDS(ndarray) nogil
+
+ bint PyArray_ISVARIABLE(ndarray) nogil
+
+ bint PyArray_SAFEALIGNEDCOPY(ndarray) nogil
+ bint PyArray_ISNBO(char) nogil # works on ndarray.byteorder
+ bint PyArray_IsNativeByteOrder(char) nogil # works on ndarray.byteorder
+ bint PyArray_ISNOTSWAPPED(ndarray) nogil
+ bint PyArray_ISBYTESWAPPED(ndarray) nogil
+
+ bint PyArray_FLAGSWAP(ndarray, int) nogil
+
+ bint PyArray_ISCARRAY(ndarray) nogil
+ bint PyArray_ISCARRAY_RO(ndarray) nogil
+ bint PyArray_ISFARRAY(ndarray) nogil
+ bint PyArray_ISFARRAY_RO(ndarray) nogil
+ bint PyArray_ISBEHAVED(ndarray) nogil
+ bint PyArray_ISBEHAVED_RO(ndarray) nogil
+
+
+ bint PyDataType_ISNOTSWAPPED(dtype) nogil
+ bint PyDataType_ISBYTESWAPPED(dtype) nogil
+
+ bint PyArray_DescrCheck(object)
+
+ bint PyArray_Check(object)
+ bint PyArray_CheckExact(object)
+
+ # Cannot be supported due to out arg:
+ # bint PyArray_HasArrayInterfaceType(object, dtype, object, object&)
+ # bint PyArray_HasArrayInterface(op, out)
+
+
+ bint PyArray_IsZeroDim(object)
+ # Cannot be supported due to ## ## in macro:
+ # bint PyArray_IsScalar(object, verbatim work)
+ bint PyArray_CheckScalar(object)
+ bint PyArray_IsPythonNumber(object)
+ bint PyArray_IsPythonScalar(object)
+ bint PyArray_IsAnyScalar(object)
+ bint PyArray_CheckAnyScalar(object)
+
+ ndarray PyArray_GETCONTIGUOUS(ndarray)
+ bint PyArray_SAMESHAPE(ndarray, ndarray) nogil
+ npy_intp PyArray_SIZE(ndarray) nogil
+ npy_intp PyArray_NBYTES(ndarray) nogil
+
+ object PyArray_FROM_O(object)
+ object PyArray_FROM_OF(object m, int flags)
+ object PyArray_FROM_OT(object m, int type)
+ object PyArray_FROM_OTF(object m, int type, int flags)
+ object PyArray_FROMANY(object m, int type, int min, int max, int flags)
+ object PyArray_ZEROS(int nd, npy_intp* dims, int type, int fortran)
+ object PyArray_EMPTY(int nd, npy_intp* dims, int type, int fortran)
+ void PyArray_FILLWBYTE(object, int val)
+ npy_intp PyArray_REFCOUNT(object)
+ object PyArray_ContiguousFromAny(op, int, int min_depth, int max_depth)
+ unsigned char PyArray_EquivArrTypes(ndarray a1, ndarray a2)
+ bint PyArray_EquivByteorders(int b1, int b2) nogil
+ object PyArray_SimpleNew(int nd, npy_intp* dims, int typenum)
+ object PyArray_SimpleNewFromData(int nd, npy_intp* dims, int typenum, void* data)
+ #object PyArray_SimpleNewFromDescr(int nd, npy_intp* dims, dtype descr)
+ object PyArray_ToScalar(void* data, ndarray arr)
+
+ void* PyArray_GETPTR1(ndarray m, npy_intp i) nogil
+ void* PyArray_GETPTR2(ndarray m, npy_intp i, npy_intp j) nogil
+ void* PyArray_GETPTR3(ndarray m, npy_intp i, npy_intp j, npy_intp k) nogil
+ void* PyArray_GETPTR4(ndarray m, npy_intp i, npy_intp j, npy_intp k, npy_intp l) nogil
+
+ # Cannot be supported due to out arg
+ # void PyArray_DESCR_REPLACE(descr)
+
+
+ object PyArray_Copy(ndarray)
+ object PyArray_FromObject(object op, int type, int min_depth, int max_depth)
+ object PyArray_ContiguousFromObject(object op, int type, int min_depth, int max_depth)
+ object PyArray_CopyFromObject(object op, int type, int min_depth, int max_depth)
+
+ object PyArray_Cast(ndarray mp, int type_num)
+ object PyArray_Take(ndarray ap, object items, int axis)
+ object PyArray_Put(ndarray ap, object items, object values)
+
+ void PyArray_ITER_RESET(flatiter it) nogil
+ void PyArray_ITER_NEXT(flatiter it) nogil
+ void PyArray_ITER_GOTO(flatiter it, npy_intp* destination) nogil
+ void PyArray_ITER_GOTO1D(flatiter it, npy_intp ind) nogil
+ void* PyArray_ITER_DATA(flatiter it) nogil
+ bint PyArray_ITER_NOTDONE(flatiter it) nogil
+
+ void PyArray_MultiIter_RESET(broadcast multi) nogil
+ void PyArray_MultiIter_NEXT(broadcast multi) nogil
+ void PyArray_MultiIter_GOTO(broadcast multi, npy_intp dest) nogil
+ void PyArray_MultiIter_GOTO1D(broadcast multi, npy_intp ind) nogil
+ void* PyArray_MultiIter_DATA(broadcast multi, npy_intp i) nogil
+ void PyArray_MultiIter_NEXTi(broadcast multi, npy_intp i) nogil
+ bint PyArray_MultiIter_NOTDONE(broadcast multi) nogil
+
+ # Functions from __multiarray_api.h
+
+ # Functions taking dtype and returning object/ndarray are disabled
+ # for now as they steal dtype references. I'm conservative and disable
+ # more than is probably needed until it can be checked further.
+ int PyArray_SetNumericOps (object) except -1
+ object PyArray_GetNumericOps ()
+ int PyArray_INCREF (ndarray) except * # uses PyArray_Item_INCREF...
+ int PyArray_XDECREF (ndarray) except * # uses PyArray_Item_DECREF...
+ void PyArray_SetStringFunction (object, int)
+ dtype PyArray_DescrFromType (int)
+ object PyArray_TypeObjectFromType (int)
+ char * PyArray_Zero (ndarray)
+ char * PyArray_One (ndarray)
+ #object PyArray_CastToType (ndarray, dtype, int)
+ int PyArray_CastTo (ndarray, ndarray) except -1
+ int PyArray_CastAnyTo (ndarray, ndarray) except -1
+ int PyArray_CanCastSafely (int, int) # writes errors
+ npy_bool PyArray_CanCastTo (dtype, dtype) # writes errors
+ int PyArray_ObjectType (object, int) except 0
+ dtype PyArray_DescrFromObject (object, dtype)
+ #ndarray* PyArray_ConvertToCommonType (object, int *)
+ dtype PyArray_DescrFromScalar (object)
+ dtype PyArray_DescrFromTypeObject (object)
+ npy_intp PyArray_Size (object)
+ #object PyArray_Scalar (void *, dtype, object)
+ #object PyArray_FromScalar (object, dtype)
+ void PyArray_ScalarAsCtype (object, void *)
+ #int PyArray_CastScalarToCtype (object, void *, dtype)
+ #int PyArray_CastScalarDirect (object, dtype, void *, int)
+ object PyArray_ScalarFromObject (object)
+ #PyArray_VectorUnaryFunc * PyArray_GetCastFunc (dtype, int)
+ object PyArray_FromDims (int, int *, int)
+ #object PyArray_FromDimsAndDataAndDescr (int, int *, dtype, char *)
+ #object PyArray_FromAny (object, dtype, int, int, int, object)
+ object PyArray_EnsureArray (object)
+ object PyArray_EnsureAnyArray (object)
+ #object PyArray_FromFile (stdio.FILE *, dtype, npy_intp, char *)
+ #object PyArray_FromString (char *, npy_intp, dtype, npy_intp, char *)
+ #object PyArray_FromBuffer (object, dtype, npy_intp, npy_intp)
+ #object PyArray_FromIter (object, dtype, npy_intp)
+ object PyArray_Return (ndarray)
+ #object PyArray_GetField (ndarray, dtype, int)
+ #int PyArray_SetField (ndarray, dtype, int, object) except -1
+ object PyArray_Byteswap (ndarray, npy_bool)
+ object PyArray_Resize (ndarray, PyArray_Dims *, int, NPY_ORDER)
+ int PyArray_MoveInto (ndarray, ndarray) except -1
+ int PyArray_CopyInto (ndarray, ndarray) except -1
+ int PyArray_CopyAnyInto (ndarray, ndarray) except -1
+ int PyArray_CopyObject (ndarray, object) except -1
+ object PyArray_NewCopy (ndarray, NPY_ORDER)
+ object PyArray_ToList (ndarray)
+ object PyArray_ToString (ndarray, NPY_ORDER)
+ int PyArray_ToFile (ndarray, stdio.FILE *, char *, char *) except -1
+ int PyArray_Dump (object, object, int) except -1
+ object PyArray_Dumps (object, int)
+ int PyArray_ValidType (int) # Cannot error
+ void PyArray_UpdateFlags (ndarray, int)
+ object PyArray_New (type, int, npy_intp *, int, npy_intp *, void *, int, int, object)
+ #object PyArray_NewFromDescr (type, dtype, int, npy_intp *, npy_intp *, void *, int, object)
+ #dtype PyArray_DescrNew (dtype)
+ dtype PyArray_DescrNewFromType (int)
+ double PyArray_GetPriority (object, double) # clears errors as of 1.25
+ object PyArray_IterNew (object)
+ object PyArray_MultiIterNew (int, ...)
+
+ int PyArray_PyIntAsInt (object) except? -1
+ npy_intp PyArray_PyIntAsIntp (object)
+ int PyArray_Broadcast (broadcast) except -1
+ void PyArray_FillObjectArray (ndarray, object) except *
+ int PyArray_FillWithScalar (ndarray, object) except -1
+ npy_bool PyArray_CheckStrides (int, int, npy_intp, npy_intp, npy_intp *, npy_intp *)
+ dtype PyArray_DescrNewByteorder (dtype, char)
+ object PyArray_IterAllButAxis (object, int *)
+ #object PyArray_CheckFromAny (object, dtype, int, int, int, object)
+ #object PyArray_FromArray (ndarray, dtype, int)
+ object PyArray_FromInterface (object)
+ object PyArray_FromStructInterface (object)
+ #object PyArray_FromArrayAttr (object, dtype, object)
+ #NPY_SCALARKIND PyArray_ScalarKind (int, ndarray*)
+ int PyArray_CanCoerceScalar (int, int, NPY_SCALARKIND)
+ object PyArray_NewFlagsObject (object)
+ npy_bool PyArray_CanCastScalar (type, type)
+ #int PyArray_CompareUCS4 (npy_ucs4 *, npy_ucs4 *, register size_t)
+ int PyArray_RemoveSmallest (broadcast) except -1
+ int PyArray_ElementStrides (object)
+ void PyArray_Item_INCREF (char *, dtype) except *
+ void PyArray_Item_XDECREF (char *, dtype) except *
+ object PyArray_FieldNames (object)
+ object PyArray_Transpose (ndarray, PyArray_Dims *)
+ object PyArray_TakeFrom (ndarray, object, int, ndarray, NPY_CLIPMODE)
+ object PyArray_PutTo (ndarray, object, object, NPY_CLIPMODE)
+ object PyArray_PutMask (ndarray, object, object)
+ object PyArray_Repeat (ndarray, object, int)
+ object PyArray_Choose (ndarray, object, ndarray, NPY_CLIPMODE)
+ int PyArray_Sort (ndarray, int, NPY_SORTKIND) except -1
+ object PyArray_ArgSort (ndarray, int, NPY_SORTKIND)
+ object PyArray_SearchSorted (ndarray, object, NPY_SEARCHSIDE, PyObject *)
+ object PyArray_ArgMax (ndarray, int, ndarray)
+ object PyArray_ArgMin (ndarray, int, ndarray)
+ object PyArray_Reshape (ndarray, object)
+ object PyArray_Newshape (ndarray, PyArray_Dims *, NPY_ORDER)
+ object PyArray_Squeeze (ndarray)
+ #object PyArray_View (ndarray, dtype, type)
+ object PyArray_SwapAxes (ndarray, int, int)
+ object PyArray_Max (ndarray, int, ndarray)
+ object PyArray_Min (ndarray, int, ndarray)
+ object PyArray_Ptp (ndarray, int, ndarray)
+ object PyArray_Mean (ndarray, int, int, ndarray)
+ object PyArray_Trace (ndarray, int, int, int, int, ndarray)
+ object PyArray_Diagonal (ndarray, int, int, int)
+ object PyArray_Clip (ndarray, object, object, ndarray)
+ object PyArray_Conjugate (ndarray, ndarray)
+ object PyArray_Nonzero (ndarray)
+ object PyArray_Std (ndarray, int, int, ndarray, int)
+ object PyArray_Sum (ndarray, int, int, ndarray)
+ object PyArray_CumSum (ndarray, int, int, ndarray)
+ object PyArray_Prod (ndarray, int, int, ndarray)
+ object PyArray_CumProd (ndarray, int, int, ndarray)
+ object PyArray_All (ndarray, int, ndarray)
+ object PyArray_Any (ndarray, int, ndarray)
+ object PyArray_Compress (ndarray, object, int, ndarray)
+ object PyArray_Flatten (ndarray, NPY_ORDER)
+ object PyArray_Ravel (ndarray, NPY_ORDER)
+ npy_intp PyArray_MultiplyList (npy_intp *, int)
+ int PyArray_MultiplyIntList (int *, int)
+ void * PyArray_GetPtr (ndarray, npy_intp*)
+ int PyArray_CompareLists (npy_intp *, npy_intp *, int)
+ #int PyArray_AsCArray (object*, void *, npy_intp *, int, dtype)
+ #int PyArray_As1D (object*, char **, int *, int)
+ #int PyArray_As2D (object*, char ***, int *, int *, int)
+ int PyArray_Free (object, void *)
+ #int PyArray_Converter (object, object*)
+ int PyArray_IntpFromSequence (object, npy_intp *, int) except -1
+ object PyArray_Concatenate (object, int)
+ object PyArray_InnerProduct (object, object)
+ object PyArray_MatrixProduct (object, object)
+ object PyArray_CopyAndTranspose (object)
+ object PyArray_Correlate (object, object, int)
+ int PyArray_TypestrConvert (int, int)
+ #int PyArray_DescrConverter (object, dtype*) except 0
+ #int PyArray_DescrConverter2 (object, dtype*) except 0
+ int PyArray_IntpConverter (object, PyArray_Dims *) except 0
+ #int PyArray_BufferConverter (object, chunk) except 0
+ int PyArray_AxisConverter (object, int *) except 0
+ int PyArray_BoolConverter (object, npy_bool *) except 0
+ int PyArray_ByteorderConverter (object, char *) except 0
+ int PyArray_OrderConverter (object, NPY_ORDER *) except 0
+ unsigned char PyArray_EquivTypes (dtype, dtype) # clears errors
+ #object PyArray_Zeros (int, npy_intp *, dtype, int)
+ #object PyArray_Empty (int, npy_intp *, dtype, int)
+ object PyArray_Where (object, object, object)
+ object PyArray_Arange (double, double, double, int)
+ #object PyArray_ArangeObj (object, object, object, dtype)
+ int PyArray_SortkindConverter (object, NPY_SORTKIND *) except 0
+ object PyArray_LexSort (object, int)
+ object PyArray_Round (ndarray, int, ndarray)
+ unsigned char PyArray_EquivTypenums (int, int)
+ int PyArray_RegisterDataType (dtype) except -1
+ int PyArray_RegisterCastFunc (dtype, int, PyArray_VectorUnaryFunc *) except -1
+ int PyArray_RegisterCanCast (dtype, int, NPY_SCALARKIND) except -1
+ #void PyArray_InitArrFuncs (PyArray_ArrFuncs *)
+ object PyArray_IntTupleFromIntp (int, npy_intp *)
+ int PyArray_TypeNumFromName (char *)
+ int PyArray_ClipmodeConverter (object, NPY_CLIPMODE *) except 0
+ #int PyArray_OutputConverter (object, ndarray*) except 0
+ object PyArray_BroadcastToShape (object, npy_intp *, int)
+ void _PyArray_SigintHandler (int)
+ void* _PyArray_GetSigintBuf ()
+ #int PyArray_DescrAlignConverter (object, dtype*) except 0
+ #int PyArray_DescrAlignConverter2 (object, dtype*) except 0
+ int PyArray_SearchsideConverter (object, void *) except 0
+ object PyArray_CheckAxis (ndarray, int *, int)
+ npy_intp PyArray_OverflowMultiplyList (npy_intp *, int)
+ int PyArray_CompareString (char *, char *, size_t)
+ int PyArray_SetBaseObject(ndarray, base) except -1 # NOTE: steals a reference to base! Use "set_array_base()" instead.
+
+
+# Typedefs that matches the runtime dtype objects in
+# the numpy module.
+
+# The ones that are commented out needs an IFDEF function
+# in Cython to enable them only on the right systems.
+
+ctypedef npy_int8 int8_t
+ctypedef npy_int16 int16_t
+ctypedef npy_int32 int32_t
+ctypedef npy_int64 int64_t
+#ctypedef npy_int96 int96_t
+#ctypedef npy_int128 int128_t
+
+ctypedef npy_uint8 uint8_t
+ctypedef npy_uint16 uint16_t
+ctypedef npy_uint32 uint32_t
+ctypedef npy_uint64 uint64_t
+#ctypedef npy_uint96 uint96_t
+#ctypedef npy_uint128 uint128_t
+
+ctypedef npy_float32 float32_t
+ctypedef npy_float64 float64_t
+#ctypedef npy_float80 float80_t
+#ctypedef npy_float128 float128_t
+
+ctypedef float complex complex64_t
+ctypedef double complex complex128_t
+
+# The int types are mapped a bit surprising --
+# numpy.int corresponds to 'l' and numpy.long to 'q'
+ctypedef npy_long int_t
+ctypedef npy_longlong longlong_t
+
+ctypedef npy_ulong uint_t
+ctypedef npy_ulonglong ulonglong_t
+
+ctypedef npy_intp intp_t
+ctypedef npy_uintp uintp_t
+
+ctypedef npy_double float_t
+ctypedef npy_double double_t
+ctypedef npy_longdouble longdouble_t
+
+ctypedef npy_cfloat cfloat_t
+ctypedef npy_cdouble cdouble_t
+ctypedef npy_clongdouble clongdouble_t
+
+ctypedef npy_cdouble complex_t
+
+cdef inline object PyArray_MultiIterNew1(a):
+ return PyArray_MultiIterNew(1, a)
+
+cdef inline object PyArray_MultiIterNew2(a, b):
+ return PyArray_MultiIterNew(2, a, b)
+
+cdef inline object PyArray_MultiIterNew3(a, b, c):
+ return PyArray_MultiIterNew(3, a, b, c)
+
+cdef inline object PyArray_MultiIterNew4(a, b, c, d):
+ return PyArray_MultiIterNew(4, a, b, c, d)
+
+cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
+ return PyArray_MultiIterNew(5, a, b, c, d, e)
+
+cdef inline tuple PyDataType_SHAPE(dtype d):
+ if PyDataType_HASSUBARRAY(d):
+ return d.subarray.shape
+ else:
+ return ()
+
+
+cdef extern from "numpy/ndarrayobject.h":
+ PyTypeObject PyTimedeltaArrType_Type
+ PyTypeObject PyDatetimeArrType_Type
+ ctypedef int64_t npy_timedelta
+ ctypedef int64_t npy_datetime
+
+cdef extern from "numpy/ndarraytypes.h":
+ ctypedef struct PyArray_DatetimeMetaData:
+ NPY_DATETIMEUNIT base
+ int64_t num
+
+cdef extern from "numpy/arrayscalars.h":
+
+ # abstract types
+ ctypedef class numpy.generic [object PyObject]:
+ pass
+ ctypedef class numpy.number [object PyObject]:
+ pass
+ ctypedef class numpy.integer [object PyObject]:
+ pass
+ ctypedef class numpy.signedinteger [object PyObject]:
+ pass
+ ctypedef class numpy.unsignedinteger [object PyObject]:
+ pass
+ ctypedef class numpy.inexact [object PyObject]:
+ pass
+ ctypedef class numpy.floating [object PyObject]:
+ pass
+ ctypedef class numpy.complexfloating [object PyObject]:
+ pass
+ ctypedef class numpy.flexible [object PyObject]:
+ pass
+ ctypedef class numpy.character [object PyObject]:
+ pass
+
+ ctypedef struct PyDatetimeScalarObject:
+ # PyObject_HEAD
+ npy_datetime obval
+ PyArray_DatetimeMetaData obmeta
+
+ ctypedef struct PyTimedeltaScalarObject:
+ # PyObject_HEAD
+ npy_timedelta obval
+ PyArray_DatetimeMetaData obmeta
+
+ ctypedef enum NPY_DATETIMEUNIT:
+ NPY_FR_Y
+ NPY_FR_M
+ NPY_FR_W
+ NPY_FR_D
+ NPY_FR_B
+ NPY_FR_h
+ NPY_FR_m
+ NPY_FR_s
+ NPY_FR_ms
+ NPY_FR_us
+ NPY_FR_ns
+ NPY_FR_ps
+ NPY_FR_fs
+ NPY_FR_as
+ NPY_FR_GENERIC
+
+
+#
+# ufunc API
+#
+
+cdef extern from "numpy/ufuncobject.h":
+
+ ctypedef void (*PyUFuncGenericFunction) (char **, npy_intp *, npy_intp *, void *)
+
+ ctypedef class numpy.ufunc [object PyUFuncObject, check_size ignore]:
+ cdef:
+ int nin, nout, nargs
+ int identity
+ PyUFuncGenericFunction *functions
+ void **data
+ int ntypes
+ int check_return
+ char *name
+ char *types
+ char *doc
+ void *ptr
+ PyObject *obj
+ PyObject *userloops
+
+ cdef enum:
+ PyUFunc_Zero
+ PyUFunc_One
+ PyUFunc_None
+ UFUNC_ERR_IGNORE
+ UFUNC_ERR_WARN
+ UFUNC_ERR_RAISE
+ UFUNC_ERR_CALL
+ UFUNC_ERR_PRINT
+ UFUNC_ERR_LOG
+ UFUNC_MASK_DIVIDEBYZERO
+ UFUNC_MASK_OVERFLOW
+ UFUNC_MASK_UNDERFLOW
+ UFUNC_MASK_INVALID
+ UFUNC_SHIFT_DIVIDEBYZERO
+ UFUNC_SHIFT_OVERFLOW
+ UFUNC_SHIFT_UNDERFLOW
+ UFUNC_SHIFT_INVALID
+ UFUNC_FPE_DIVIDEBYZERO
+ UFUNC_FPE_OVERFLOW
+ UFUNC_FPE_UNDERFLOW
+ UFUNC_FPE_INVALID
+ UFUNC_ERR_DEFAULT
+ UFUNC_ERR_DEFAULT2
+
+ object PyUFunc_FromFuncAndData(PyUFuncGenericFunction *,
+ void **, char *, int, int, int, int, char *, char *, int)
+ int PyUFunc_RegisterLoopForType(ufunc, int,
+ PyUFuncGenericFunction, int *, void *) except -1
+ void PyUFunc_f_f_As_d_d \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_d_d \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_f_f \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_g_g \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_F_F_As_D_D \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_F_F \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_D_D \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_G_G \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_O_O \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_ff_f_As_dd_d \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_ff_f \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_dd_d \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_gg_g \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_FF_F_As_DD_D \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_DD_D \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_FF_F \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_GG_G \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_OO_O \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_O_O_method \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_OO_O_method \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_On_Om \
+ (char **, npy_intp *, npy_intp *, void *)
+ int PyUFunc_GetPyValues \
+ (char *, int *, int *, PyObject **)
+ int PyUFunc_checkfperr \
+ (int, PyObject *, int *)
+ void PyUFunc_clearfperr()
+ int PyUFunc_getfperr()
+ int PyUFunc_handlefperr \
+ (int, PyObject *, int, int *) except -1
+ int PyUFunc_ReplaceLoopBySignature \
+ (ufunc, PyUFuncGenericFunction, int *, PyUFuncGenericFunction *)
+ object PyUFunc_FromFuncAndDataAndSignature \
+ (PyUFuncGenericFunction *, void **, char *, int, int, int,
+ int, char *, char *, int, char *)
+
+ int _import_umath() except -1
+
+cdef inline void set_array_base(ndarray arr, object base):
+ Py_INCREF(base) # important to do this before stealing the reference below!
+ PyArray_SetBaseObject(arr, base)
+
+cdef inline object get_array_base(ndarray arr):
+ base = PyArray_BASE(arr)
+ if base is NULL:
+ return None
+ return base
+
+# Versions of the import_* functions which are more suitable for
+# Cython code.
+cdef inline int import_array() except -1:
+ try:
+ __pyx_import_array()
+ except Exception:
+ raise ImportError("numpy.core.multiarray failed to import")
+
+cdef inline int import_umath() except -1:
+ try:
+ _import_umath()
+ except Exception:
+ raise ImportError("numpy.core.umath failed to import")
+
+cdef inline int import_ufunc() except -1:
+ try:
+ _import_umath()
+ except Exception:
+ raise ImportError("numpy.core.umath failed to import")
+
+
+cdef inline bint is_timedelta64_object(object obj):
+ """
+ Cython equivalent of `isinstance(obj, np.timedelta64)`
+
+ Parameters
+ ----------
+ obj : object
+
+ Returns
+ -------
+ bool
+ """
+ return PyObject_TypeCheck(obj, &PyTimedeltaArrType_Type)
+
+
+cdef inline bint is_datetime64_object(object obj):
+ """
+ Cython equivalent of `isinstance(obj, np.datetime64)`
+
+ Parameters
+ ----------
+ obj : object
+
+ Returns
+ -------
+ bool
+ """
+ return PyObject_TypeCheck(obj, &PyDatetimeArrType_Type)
+
+
+cdef inline npy_datetime get_datetime64_value(object obj) nogil:
+ """
+ returns the int64 value underlying scalar numpy datetime64 object
+
+ Note that to interpret this as a datetime, the corresponding unit is
+ also needed. That can be found using `get_datetime64_unit`.
+ """
+ return (obj).obval
+
+
+cdef inline npy_timedelta get_timedelta64_value(object obj) nogil:
+ """
+ returns the int64 value underlying scalar numpy timedelta64 object
+ """
+ return (obj).obval
+
+
+cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) nogil:
+ """
+ returns the unit part of the dtype for a numpy datetime64 object.
+ """
+ return (obj).obmeta.base
diff --git a/lib/python3.12/site-packages/numpy/__init__.pxd b/lib/python3.12/site-packages/numpy/__init__.pxd
new file mode 100644
index 0000000000000000000000000000000000000000..ca0a3a6c5288ac5ee384636fff3574ed257e49e4
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/__init__.pxd
@@ -0,0 +1,1015 @@
+# NumPy static imports for Cython < 3.0
+#
+# If any of the PyArray_* functions are called, import_array must be
+# called first.
+#
+# Author: Dag Sverre Seljebotn
+#
+
+DEF _buffer_format_string_len = 255
+
+cimport cpython.buffer as pybuf
+from cpython.ref cimport Py_INCREF
+from cpython.mem cimport PyObject_Malloc, PyObject_Free
+from cpython.object cimport PyObject, PyTypeObject
+from cpython.buffer cimport PyObject_GetBuffer
+from cpython.type cimport type
+cimport libc.stdio as stdio
+
+cdef extern from "Python.h":
+ ctypedef int Py_intptr_t
+ bint PyObject_TypeCheck(object obj, PyTypeObject* type)
+
+cdef extern from "numpy/arrayobject.h":
+ ctypedef Py_intptr_t npy_intp
+ ctypedef size_t npy_uintp
+
+ cdef enum NPY_TYPES:
+ NPY_BOOL
+ NPY_BYTE
+ NPY_UBYTE
+ NPY_SHORT
+ NPY_USHORT
+ NPY_INT
+ NPY_UINT
+ NPY_LONG
+ NPY_ULONG
+ NPY_LONGLONG
+ NPY_ULONGLONG
+ NPY_FLOAT
+ NPY_DOUBLE
+ NPY_LONGDOUBLE
+ NPY_CFLOAT
+ NPY_CDOUBLE
+ NPY_CLONGDOUBLE
+ NPY_OBJECT
+ NPY_STRING
+ NPY_UNICODE
+ NPY_VOID
+ NPY_DATETIME
+ NPY_TIMEDELTA
+ NPY_NTYPES
+ NPY_NOTYPE
+
+ NPY_INT8
+ NPY_INT16
+ NPY_INT32
+ NPY_INT64
+ NPY_INT128
+ NPY_INT256
+ NPY_UINT8
+ NPY_UINT16
+ NPY_UINT32
+ NPY_UINT64
+ NPY_UINT128
+ NPY_UINT256
+ NPY_FLOAT16
+ NPY_FLOAT32
+ NPY_FLOAT64
+ NPY_FLOAT80
+ NPY_FLOAT96
+ NPY_FLOAT128
+ NPY_FLOAT256
+ NPY_COMPLEX32
+ NPY_COMPLEX64
+ NPY_COMPLEX128
+ NPY_COMPLEX160
+ NPY_COMPLEX192
+ NPY_COMPLEX256
+ NPY_COMPLEX512
+
+ NPY_INTP
+
+ ctypedef enum NPY_ORDER:
+ NPY_ANYORDER
+ NPY_CORDER
+ NPY_FORTRANORDER
+ NPY_KEEPORDER
+
+ ctypedef enum NPY_CASTING:
+ NPY_NO_CASTING
+ NPY_EQUIV_CASTING
+ NPY_SAFE_CASTING
+ NPY_SAME_KIND_CASTING
+ NPY_UNSAFE_CASTING
+
+ ctypedef enum NPY_CLIPMODE:
+ NPY_CLIP
+ NPY_WRAP
+ NPY_RAISE
+
+ ctypedef enum NPY_SCALARKIND:
+ NPY_NOSCALAR,
+ NPY_BOOL_SCALAR,
+ NPY_INTPOS_SCALAR,
+ NPY_INTNEG_SCALAR,
+ NPY_FLOAT_SCALAR,
+ NPY_COMPLEX_SCALAR,
+ NPY_OBJECT_SCALAR
+
+ ctypedef enum NPY_SORTKIND:
+ NPY_QUICKSORT
+ NPY_HEAPSORT
+ NPY_MERGESORT
+
+ ctypedef enum NPY_SEARCHSIDE:
+ NPY_SEARCHLEFT
+ NPY_SEARCHRIGHT
+
+ enum:
+ # DEPRECATED since NumPy 1.7 ! Do not use in new code!
+ NPY_C_CONTIGUOUS
+ NPY_F_CONTIGUOUS
+ NPY_CONTIGUOUS
+ NPY_FORTRAN
+ NPY_OWNDATA
+ NPY_FORCECAST
+ NPY_ENSURECOPY
+ NPY_ENSUREARRAY
+ NPY_ELEMENTSTRIDES
+ NPY_ALIGNED
+ NPY_NOTSWAPPED
+ NPY_WRITEABLE
+ NPY_ARR_HAS_DESCR
+
+ NPY_BEHAVED
+ NPY_BEHAVED_NS
+ NPY_CARRAY
+ NPY_CARRAY_RO
+ NPY_FARRAY
+ NPY_FARRAY_RO
+ NPY_DEFAULT
+
+ NPY_IN_ARRAY
+ NPY_OUT_ARRAY
+ NPY_INOUT_ARRAY
+ NPY_IN_FARRAY
+ NPY_OUT_FARRAY
+ NPY_INOUT_FARRAY
+
+ NPY_UPDATE_ALL
+
+ enum:
+ # Added in NumPy 1.7 to replace the deprecated enums above.
+ NPY_ARRAY_C_CONTIGUOUS
+ NPY_ARRAY_F_CONTIGUOUS
+ NPY_ARRAY_OWNDATA
+ NPY_ARRAY_FORCECAST
+ NPY_ARRAY_ENSURECOPY
+ NPY_ARRAY_ENSUREARRAY
+ NPY_ARRAY_ELEMENTSTRIDES
+ NPY_ARRAY_ALIGNED
+ NPY_ARRAY_NOTSWAPPED
+ NPY_ARRAY_WRITEABLE
+ NPY_ARRAY_WRITEBACKIFCOPY
+
+ NPY_ARRAY_BEHAVED
+ NPY_ARRAY_BEHAVED_NS
+ NPY_ARRAY_CARRAY
+ NPY_ARRAY_CARRAY_RO
+ NPY_ARRAY_FARRAY
+ NPY_ARRAY_FARRAY_RO
+ NPY_ARRAY_DEFAULT
+
+ NPY_ARRAY_IN_ARRAY
+ NPY_ARRAY_OUT_ARRAY
+ NPY_ARRAY_INOUT_ARRAY
+ NPY_ARRAY_IN_FARRAY
+ NPY_ARRAY_OUT_FARRAY
+ NPY_ARRAY_INOUT_FARRAY
+
+ NPY_ARRAY_UPDATE_ALL
+
+ cdef enum:
+ NPY_MAXDIMS
+
+ npy_intp NPY_MAX_ELSIZE
+
+ ctypedef void (*PyArray_VectorUnaryFunc)(void *, void *, npy_intp, void *, void *)
+
+ ctypedef struct PyArray_ArrayDescr:
+ # shape is a tuple, but Cython doesn't support "tuple shape"
+ # inside a non-PyObject declaration, so we have to declare it
+ # as just a PyObject*.
+ PyObject* shape
+
+ ctypedef struct PyArray_Descr:
+ pass
+
+ ctypedef class numpy.dtype [object PyArray_Descr, check_size ignore]:
+ # Use PyDataType_* macros when possible, however there are no macros
+ # for accessing some of the fields, so some are defined.
+ cdef PyTypeObject* typeobj
+ cdef char kind
+ cdef char type
+ # Numpy sometimes mutates this without warning (e.g. it'll
+ # sometimes change "|" to "<" in shared dtype objects on
+ # little-endian machines). If this matters to you, use
+ # PyArray_IsNativeByteOrder(dtype.byteorder) instead of
+ # directly accessing this field.
+ cdef char byteorder
+ cdef char flags
+ cdef int type_num
+ cdef int itemsize "elsize"
+ cdef int alignment
+ cdef object fields
+ cdef tuple names
+ # Use PyDataType_HASSUBARRAY to test whether this field is
+ # valid (the pointer can be NULL). Most users should access
+ # this field via the inline helper method PyDataType_SHAPE.
+ cdef PyArray_ArrayDescr* subarray
+
+ ctypedef class numpy.flatiter [object PyArrayIterObject, check_size ignore]:
+ # Use through macros
+ pass
+
+ ctypedef class numpy.broadcast [object PyArrayMultiIterObject, check_size ignore]:
+ cdef int numiter
+ cdef npy_intp size, index
+ cdef int nd
+ cdef npy_intp *dimensions
+ cdef void **iters
+
+ ctypedef struct PyArrayObject:
+ # For use in situations where ndarray can't replace PyArrayObject*,
+ # like PyArrayObject**.
+ pass
+
+ ctypedef class numpy.ndarray [object PyArrayObject, check_size ignore]:
+ cdef __cythonbufferdefaults__ = {"mode": "strided"}
+
+ cdef:
+ # Only taking a few of the most commonly used and stable fields.
+ # One should use PyArray_* macros instead to access the C fields.
+ char *data
+ int ndim "nd"
+ npy_intp *shape "dimensions"
+ npy_intp *strides
+ dtype descr # deprecated since NumPy 1.7 !
+ PyObject* base # NOT PUBLIC, DO NOT USE !
+
+
+
+ ctypedef unsigned char npy_bool
+
+ ctypedef signed char npy_byte
+ ctypedef signed short npy_short
+ ctypedef signed int npy_int
+ ctypedef signed long npy_long
+ ctypedef signed long long npy_longlong
+
+ ctypedef unsigned char npy_ubyte
+ ctypedef unsigned short npy_ushort
+ ctypedef unsigned int npy_uint
+ ctypedef unsigned long npy_ulong
+ ctypedef unsigned long long npy_ulonglong
+
+ ctypedef float npy_float
+ ctypedef double npy_double
+ ctypedef long double npy_longdouble
+
+ ctypedef signed char npy_int8
+ ctypedef signed short npy_int16
+ ctypedef signed int npy_int32
+ ctypedef signed long long npy_int64
+ ctypedef signed long long npy_int96
+ ctypedef signed long long npy_int128
+
+ ctypedef unsigned char npy_uint8
+ ctypedef unsigned short npy_uint16
+ ctypedef unsigned int npy_uint32
+ ctypedef unsigned long long npy_uint64
+ ctypedef unsigned long long npy_uint96
+ ctypedef unsigned long long npy_uint128
+
+ ctypedef float npy_float32
+ ctypedef double npy_float64
+ ctypedef long double npy_float80
+ ctypedef long double npy_float96
+ ctypedef long double npy_float128
+
+ ctypedef struct npy_cfloat:
+ float real
+ float imag
+
+ ctypedef struct npy_cdouble:
+ double real
+ double imag
+
+ ctypedef struct npy_clongdouble:
+ long double real
+ long double imag
+
+ ctypedef struct npy_complex64:
+ float real
+ float imag
+
+ ctypedef struct npy_complex128:
+ double real
+ double imag
+
+ ctypedef struct npy_complex160:
+ long double real
+ long double imag
+
+ ctypedef struct npy_complex192:
+ long double real
+ long double imag
+
+ ctypedef struct npy_complex256:
+ long double real
+ long double imag
+
+ ctypedef struct PyArray_Dims:
+ npy_intp *ptr
+ int len
+
+ int _import_array() except -1
+ # A second definition so _import_array isn't marked as used when we use it here.
+ # Do not use - subject to change any time.
+ int __pyx_import_array "_import_array"() except -1
+
+ #
+ # Macros from ndarrayobject.h
+ #
+ bint PyArray_CHKFLAGS(ndarray m, int flags) nogil
+ bint PyArray_IS_C_CONTIGUOUS(ndarray arr) nogil
+ bint PyArray_IS_F_CONTIGUOUS(ndarray arr) nogil
+ bint PyArray_ISCONTIGUOUS(ndarray m) nogil
+ bint PyArray_ISWRITEABLE(ndarray m) nogil
+ bint PyArray_ISALIGNED(ndarray m) nogil
+
+ int PyArray_NDIM(ndarray) nogil
+ bint PyArray_ISONESEGMENT(ndarray) nogil
+ bint PyArray_ISFORTRAN(ndarray) nogil
+ int PyArray_FORTRANIF(ndarray) nogil
+
+ void* PyArray_DATA(ndarray) nogil
+ char* PyArray_BYTES(ndarray) nogil
+
+ npy_intp* PyArray_DIMS(ndarray) nogil
+ npy_intp* PyArray_STRIDES(ndarray) nogil
+ npy_intp PyArray_DIM(ndarray, size_t) nogil
+ npy_intp PyArray_STRIDE(ndarray, size_t) nogil
+
+ PyObject *PyArray_BASE(ndarray) nogil # returns borrowed reference!
+ PyArray_Descr *PyArray_DESCR(ndarray) nogil # returns borrowed reference to dtype!
+ int PyArray_FLAGS(ndarray) nogil
+ npy_intp PyArray_ITEMSIZE(ndarray) nogil
+ int PyArray_TYPE(ndarray arr) nogil
+
+ object PyArray_GETITEM(ndarray arr, void *itemptr)
+ int PyArray_SETITEM(ndarray arr, void *itemptr, object obj) except -1
+
+ bint PyTypeNum_ISBOOL(int) nogil
+ bint PyTypeNum_ISUNSIGNED(int) nogil
+ bint PyTypeNum_ISSIGNED(int) nogil
+ bint PyTypeNum_ISINTEGER(int) nogil
+ bint PyTypeNum_ISFLOAT(int) nogil
+ bint PyTypeNum_ISNUMBER(int) nogil
+ bint PyTypeNum_ISSTRING(int) nogil
+ bint PyTypeNum_ISCOMPLEX(int) nogil
+ bint PyTypeNum_ISPYTHON(int) nogil
+ bint PyTypeNum_ISFLEXIBLE(int) nogil
+ bint PyTypeNum_ISUSERDEF(int) nogil
+ bint PyTypeNum_ISEXTENDED(int) nogil
+ bint PyTypeNum_ISOBJECT(int) nogil
+
+ bint PyDataType_ISBOOL(dtype) nogil
+ bint PyDataType_ISUNSIGNED(dtype) nogil
+ bint PyDataType_ISSIGNED(dtype) nogil
+ bint PyDataType_ISINTEGER(dtype) nogil
+ bint PyDataType_ISFLOAT(dtype) nogil
+ bint PyDataType_ISNUMBER(dtype) nogil
+ bint PyDataType_ISSTRING(dtype) nogil
+ bint PyDataType_ISCOMPLEX(dtype) nogil
+ bint PyDataType_ISPYTHON(dtype) nogil
+ bint PyDataType_ISFLEXIBLE(dtype) nogil
+ bint PyDataType_ISUSERDEF(dtype) nogil
+ bint PyDataType_ISEXTENDED(dtype) nogil
+ bint PyDataType_ISOBJECT(dtype) nogil
+ bint PyDataType_HASFIELDS(dtype) nogil
+ bint PyDataType_HASSUBARRAY(dtype) nogil
+
+ bint PyArray_ISBOOL(ndarray) nogil
+ bint PyArray_ISUNSIGNED(ndarray) nogil
+ bint PyArray_ISSIGNED(ndarray) nogil
+ bint PyArray_ISINTEGER(ndarray) nogil
+ bint PyArray_ISFLOAT(ndarray) nogil
+ bint PyArray_ISNUMBER(ndarray) nogil
+ bint PyArray_ISSTRING(ndarray) nogil
+ bint PyArray_ISCOMPLEX(ndarray) nogil
+ bint PyArray_ISPYTHON(ndarray) nogil
+ bint PyArray_ISFLEXIBLE(ndarray) nogil
+ bint PyArray_ISUSERDEF(ndarray) nogil
+ bint PyArray_ISEXTENDED(ndarray) nogil
+ bint PyArray_ISOBJECT(ndarray) nogil
+ bint PyArray_HASFIELDS(ndarray) nogil
+
+ bint PyArray_ISVARIABLE(ndarray) nogil
+
+ bint PyArray_SAFEALIGNEDCOPY(ndarray) nogil
+ bint PyArray_ISNBO(char) nogil # works on ndarray.byteorder
+ bint PyArray_IsNativeByteOrder(char) nogil # works on ndarray.byteorder
+ bint PyArray_ISNOTSWAPPED(ndarray) nogil
+ bint PyArray_ISBYTESWAPPED(ndarray) nogil
+
+ bint PyArray_FLAGSWAP(ndarray, int) nogil
+
+ bint PyArray_ISCARRAY(ndarray) nogil
+ bint PyArray_ISCARRAY_RO(ndarray) nogil
+ bint PyArray_ISFARRAY(ndarray) nogil
+ bint PyArray_ISFARRAY_RO(ndarray) nogil
+ bint PyArray_ISBEHAVED(ndarray) nogil
+ bint PyArray_ISBEHAVED_RO(ndarray) nogil
+
+
+ bint PyDataType_ISNOTSWAPPED(dtype) nogil
+ bint PyDataType_ISBYTESWAPPED(dtype) nogil
+
+ bint PyArray_DescrCheck(object)
+
+ bint PyArray_Check(object)
+ bint PyArray_CheckExact(object)
+
+ # Cannot be supported due to out arg:
+ # bint PyArray_HasArrayInterfaceType(object, dtype, object, object&)
+ # bint PyArray_HasArrayInterface(op, out)
+
+
+ bint PyArray_IsZeroDim(object)
+ # Cannot be supported due to ## ## in macro:
+ # bint PyArray_IsScalar(object, verbatim work)
+ bint PyArray_CheckScalar(object)
+ bint PyArray_IsPythonNumber(object)
+ bint PyArray_IsPythonScalar(object)
+ bint PyArray_IsAnyScalar(object)
+ bint PyArray_CheckAnyScalar(object)
+
+ ndarray PyArray_GETCONTIGUOUS(ndarray)
+ bint PyArray_SAMESHAPE(ndarray, ndarray) nogil
+ npy_intp PyArray_SIZE(ndarray) nogil
+ npy_intp PyArray_NBYTES(ndarray) nogil
+
+ object PyArray_FROM_O(object)
+ object PyArray_FROM_OF(object m, int flags)
+ object PyArray_FROM_OT(object m, int type)
+ object PyArray_FROM_OTF(object m, int type, int flags)
+ object PyArray_FROMANY(object m, int type, int min, int max, int flags)
+ object PyArray_ZEROS(int nd, npy_intp* dims, int type, int fortran)
+ object PyArray_EMPTY(int nd, npy_intp* dims, int type, int fortran)
+ void PyArray_FILLWBYTE(object, int val)
+ npy_intp PyArray_REFCOUNT(object)
+ object PyArray_ContiguousFromAny(op, int, int min_depth, int max_depth)
+ unsigned char PyArray_EquivArrTypes(ndarray a1, ndarray a2)
+ bint PyArray_EquivByteorders(int b1, int b2) nogil
+ object PyArray_SimpleNew(int nd, npy_intp* dims, int typenum)
+ object PyArray_SimpleNewFromData(int nd, npy_intp* dims, int typenum, void* data)
+ #object PyArray_SimpleNewFromDescr(int nd, npy_intp* dims, dtype descr)
+ object PyArray_ToScalar(void* data, ndarray arr)
+
+ void* PyArray_GETPTR1(ndarray m, npy_intp i) nogil
+ void* PyArray_GETPTR2(ndarray m, npy_intp i, npy_intp j) nogil
+ void* PyArray_GETPTR3(ndarray m, npy_intp i, npy_intp j, npy_intp k) nogil
+ void* PyArray_GETPTR4(ndarray m, npy_intp i, npy_intp j, npy_intp k, npy_intp l) nogil
+
+ # Cannot be supported due to out arg
+ # void PyArray_DESCR_REPLACE(descr)
+
+
+ object PyArray_Copy(ndarray)
+ object PyArray_FromObject(object op, int type, int min_depth, int max_depth)
+ object PyArray_ContiguousFromObject(object op, int type, int min_depth, int max_depth)
+ object PyArray_CopyFromObject(object op, int type, int min_depth, int max_depth)
+
+ object PyArray_Cast(ndarray mp, int type_num)
+ object PyArray_Take(ndarray ap, object items, int axis)
+ object PyArray_Put(ndarray ap, object items, object values)
+
+ void PyArray_ITER_RESET(flatiter it) nogil
+ void PyArray_ITER_NEXT(flatiter it) nogil
+ void PyArray_ITER_GOTO(flatiter it, npy_intp* destination) nogil
+ void PyArray_ITER_GOTO1D(flatiter it, npy_intp ind) nogil
+ void* PyArray_ITER_DATA(flatiter it) nogil
+ bint PyArray_ITER_NOTDONE(flatiter it) nogil
+
+ void PyArray_MultiIter_RESET(broadcast multi) nogil
+ void PyArray_MultiIter_NEXT(broadcast multi) nogil
+ void PyArray_MultiIter_GOTO(broadcast multi, npy_intp dest) nogil
+ void PyArray_MultiIter_GOTO1D(broadcast multi, npy_intp ind) nogil
+ void* PyArray_MultiIter_DATA(broadcast multi, npy_intp i) nogil
+ void PyArray_MultiIter_NEXTi(broadcast multi, npy_intp i) nogil
+ bint PyArray_MultiIter_NOTDONE(broadcast multi) nogil
+
+ # Functions from __multiarray_api.h
+
+ # Functions taking dtype and returning object/ndarray are disabled
+ # for now as they steal dtype references. I'm conservative and disable
+ # more than is probably needed until it can be checked further.
+ int PyArray_SetNumericOps (object) except -1
+ object PyArray_GetNumericOps ()
+ int PyArray_INCREF (ndarray) except * # uses PyArray_Item_INCREF...
+ int PyArray_XDECREF (ndarray) except * # uses PyArray_Item_DECREF...
+ void PyArray_SetStringFunction (object, int)
+ dtype PyArray_DescrFromType (int)
+ object PyArray_TypeObjectFromType (int)
+ char * PyArray_Zero (ndarray)
+ char * PyArray_One (ndarray)
+ #object PyArray_CastToType (ndarray, dtype, int)
+ int PyArray_CastTo (ndarray, ndarray) except -1
+ int PyArray_CastAnyTo (ndarray, ndarray) except -1
+ int PyArray_CanCastSafely (int, int) # writes errors
+ npy_bool PyArray_CanCastTo (dtype, dtype) # writes errors
+ int PyArray_ObjectType (object, int) except 0
+ dtype PyArray_DescrFromObject (object, dtype)
+ #ndarray* PyArray_ConvertToCommonType (object, int *)
+ dtype PyArray_DescrFromScalar (object)
+ dtype PyArray_DescrFromTypeObject (object)
+ npy_intp PyArray_Size (object)
+ #object PyArray_Scalar (void *, dtype, object)
+ #object PyArray_FromScalar (object, dtype)
+ void PyArray_ScalarAsCtype (object, void *)
+ #int PyArray_CastScalarToCtype (object, void *, dtype)
+ #int PyArray_CastScalarDirect (object, dtype, void *, int)
+ object PyArray_ScalarFromObject (object)
+ #PyArray_VectorUnaryFunc * PyArray_GetCastFunc (dtype, int)
+ object PyArray_FromDims (int, int *, int)
+ #object PyArray_FromDimsAndDataAndDescr (int, int *, dtype, char *)
+ #object PyArray_FromAny (object, dtype, int, int, int, object)
+ object PyArray_EnsureArray (object)
+ object PyArray_EnsureAnyArray (object)
+ #object PyArray_FromFile (stdio.FILE *, dtype, npy_intp, char *)
+ #object PyArray_FromString (char *, npy_intp, dtype, npy_intp, char *)
+ #object PyArray_FromBuffer (object, dtype, npy_intp, npy_intp)
+ #object PyArray_FromIter (object, dtype, npy_intp)
+ object PyArray_Return (ndarray)
+ #object PyArray_GetField (ndarray, dtype, int)
+ #int PyArray_SetField (ndarray, dtype, int, object) except -1
+ object PyArray_Byteswap (ndarray, npy_bool)
+ object PyArray_Resize (ndarray, PyArray_Dims *, int, NPY_ORDER)
+ int PyArray_MoveInto (ndarray, ndarray) except -1
+ int PyArray_CopyInto (ndarray, ndarray) except -1
+ int PyArray_CopyAnyInto (ndarray, ndarray) except -1
+ int PyArray_CopyObject (ndarray, object) except -1
+ object PyArray_NewCopy (ndarray, NPY_ORDER)
+ object PyArray_ToList (ndarray)
+ object PyArray_ToString (ndarray, NPY_ORDER)
+ int PyArray_ToFile (ndarray, stdio.FILE *, char *, char *) except -1
+ int PyArray_Dump (object, object, int) except -1
+ object PyArray_Dumps (object, int)
+ int PyArray_ValidType (int) # Cannot error
+ void PyArray_UpdateFlags (ndarray, int)
+ object PyArray_New (type, int, npy_intp *, int, npy_intp *, void *, int, int, object)
+ #object PyArray_NewFromDescr (type, dtype, int, npy_intp *, npy_intp *, void *, int, object)
+ #dtype PyArray_DescrNew (dtype)
+ dtype PyArray_DescrNewFromType (int)
+ double PyArray_GetPriority (object, double) # clears errors as of 1.25
+ object PyArray_IterNew (object)
+ object PyArray_MultiIterNew (int, ...)
+
+ int PyArray_PyIntAsInt (object) except? -1
+ npy_intp PyArray_PyIntAsIntp (object)
+ int PyArray_Broadcast (broadcast) except -1
+ void PyArray_FillObjectArray (ndarray, object) except *
+ int PyArray_FillWithScalar (ndarray, object) except -1
+ npy_bool PyArray_CheckStrides (int, int, npy_intp, npy_intp, npy_intp *, npy_intp *)
+ dtype PyArray_DescrNewByteorder (dtype, char)
+ object PyArray_IterAllButAxis (object, int *)
+ #object PyArray_CheckFromAny (object, dtype, int, int, int, object)
+ #object PyArray_FromArray (ndarray, dtype, int)
+ object PyArray_FromInterface (object)
+ object PyArray_FromStructInterface (object)
+ #object PyArray_FromArrayAttr (object, dtype, object)
+ #NPY_SCALARKIND PyArray_ScalarKind (int, ndarray*)
+ int PyArray_CanCoerceScalar (int, int, NPY_SCALARKIND)
+ object PyArray_NewFlagsObject (object)
+ npy_bool PyArray_CanCastScalar (type, type)
+ #int PyArray_CompareUCS4 (npy_ucs4 *, npy_ucs4 *, register size_t)
+ int PyArray_RemoveSmallest (broadcast) except -1
+ int PyArray_ElementStrides (object)
+ void PyArray_Item_INCREF (char *, dtype) except *
+ void PyArray_Item_XDECREF (char *, dtype) except *
+ object PyArray_FieldNames (object)
+ object PyArray_Transpose (ndarray, PyArray_Dims *)
+ object PyArray_TakeFrom (ndarray, object, int, ndarray, NPY_CLIPMODE)
+ object PyArray_PutTo (ndarray, object, object, NPY_CLIPMODE)
+ object PyArray_PutMask (ndarray, object, object)
+ object PyArray_Repeat (ndarray, object, int)
+ object PyArray_Choose (ndarray, object, ndarray, NPY_CLIPMODE)
+ int PyArray_Sort (ndarray, int, NPY_SORTKIND) except -1
+ object PyArray_ArgSort (ndarray, int, NPY_SORTKIND)
+ object PyArray_SearchSorted (ndarray, object, NPY_SEARCHSIDE, PyObject *)
+ object PyArray_ArgMax (ndarray, int, ndarray)
+ object PyArray_ArgMin (ndarray, int, ndarray)
+ object PyArray_Reshape (ndarray, object)
+ object PyArray_Newshape (ndarray, PyArray_Dims *, NPY_ORDER)
+ object PyArray_Squeeze (ndarray)
+ #object PyArray_View (ndarray, dtype, type)
+ object PyArray_SwapAxes (ndarray, int, int)
+ object PyArray_Max (ndarray, int, ndarray)
+ object PyArray_Min (ndarray, int, ndarray)
+ object PyArray_Ptp (ndarray, int, ndarray)
+ object PyArray_Mean (ndarray, int, int, ndarray)
+ object PyArray_Trace (ndarray, int, int, int, int, ndarray)
+ object PyArray_Diagonal (ndarray, int, int, int)
+ object PyArray_Clip (ndarray, object, object, ndarray)
+ object PyArray_Conjugate (ndarray, ndarray)
+ object PyArray_Nonzero (ndarray)
+ object PyArray_Std (ndarray, int, int, ndarray, int)
+ object PyArray_Sum (ndarray, int, int, ndarray)
+ object PyArray_CumSum (ndarray, int, int, ndarray)
+ object PyArray_Prod (ndarray, int, int, ndarray)
+ object PyArray_CumProd (ndarray, int, int, ndarray)
+ object PyArray_All (ndarray, int, ndarray)
+ object PyArray_Any (ndarray, int, ndarray)
+ object PyArray_Compress (ndarray, object, int, ndarray)
+ object PyArray_Flatten (ndarray, NPY_ORDER)
+ object PyArray_Ravel (ndarray, NPY_ORDER)
+ npy_intp PyArray_MultiplyList (npy_intp *, int)
+ int PyArray_MultiplyIntList (int *, int)
+ void * PyArray_GetPtr (ndarray, npy_intp*)
+ int PyArray_CompareLists (npy_intp *, npy_intp *, int)
+ #int PyArray_AsCArray (object*, void *, npy_intp *, int, dtype)
+ #int PyArray_As1D (object*, char **, int *, int)
+ #int PyArray_As2D (object*, char ***, int *, int *, int)
+ int PyArray_Free (object, void *)
+ #int PyArray_Converter (object, object*)
+ int PyArray_IntpFromSequence (object, npy_intp *, int) except -1
+ object PyArray_Concatenate (object, int)
+ object PyArray_InnerProduct (object, object)
+ object PyArray_MatrixProduct (object, object)
+ object PyArray_CopyAndTranspose (object)
+ object PyArray_Correlate (object, object, int)
+ int PyArray_TypestrConvert (int, int)
+ #int PyArray_DescrConverter (object, dtype*) except 0
+ #int PyArray_DescrConverter2 (object, dtype*) except 0
+ int PyArray_IntpConverter (object, PyArray_Dims *) except 0
+ #int PyArray_BufferConverter (object, chunk) except 0
+ int PyArray_AxisConverter (object, int *) except 0
+ int PyArray_BoolConverter (object, npy_bool *) except 0
+ int PyArray_ByteorderConverter (object, char *) except 0
+ int PyArray_OrderConverter (object, NPY_ORDER *) except 0
+ unsigned char PyArray_EquivTypes (dtype, dtype) # clears errors
+ #object PyArray_Zeros (int, npy_intp *, dtype, int)
+ #object PyArray_Empty (int, npy_intp *, dtype, int)
+ object PyArray_Where (object, object, object)
+ object PyArray_Arange (double, double, double, int)
+ #object PyArray_ArangeObj (object, object, object, dtype)
+ int PyArray_SortkindConverter (object, NPY_SORTKIND *) except 0
+ object PyArray_LexSort (object, int)
+ object PyArray_Round (ndarray, int, ndarray)
+ unsigned char PyArray_EquivTypenums (int, int)
+ int PyArray_RegisterDataType (dtype) except -1
+ int PyArray_RegisterCastFunc (dtype, int, PyArray_VectorUnaryFunc *) except -1
+ int PyArray_RegisterCanCast (dtype, int, NPY_SCALARKIND) except -1
+ #void PyArray_InitArrFuncs (PyArray_ArrFuncs *)
+ object PyArray_IntTupleFromIntp (int, npy_intp *)
+ int PyArray_TypeNumFromName (char *)
+ int PyArray_ClipmodeConverter (object, NPY_CLIPMODE *) except 0
+ #int PyArray_OutputConverter (object, ndarray*) except 0
+ object PyArray_BroadcastToShape (object, npy_intp *, int)
+ void _PyArray_SigintHandler (int)
+ void* _PyArray_GetSigintBuf ()
+ #int PyArray_DescrAlignConverter (object, dtype*) except 0
+ #int PyArray_DescrAlignConverter2 (object, dtype*) except 0
+ int PyArray_SearchsideConverter (object, void *) except 0
+ object PyArray_CheckAxis (ndarray, int *, int)
+ npy_intp PyArray_OverflowMultiplyList (npy_intp *, int)
+ int PyArray_CompareString (char *, char *, size_t)
+ int PyArray_SetBaseObject(ndarray, base) except -1 # NOTE: steals a reference to base! Use "set_array_base()" instead.
+
+
+# Typedefs that matches the runtime dtype objects in
+# the numpy module.
+
+# The ones that are commented out needs an IFDEF function
+# in Cython to enable them only on the right systems.
+
+ctypedef npy_int8 int8_t
+ctypedef npy_int16 int16_t
+ctypedef npy_int32 int32_t
+ctypedef npy_int64 int64_t
+#ctypedef npy_int96 int96_t
+#ctypedef npy_int128 int128_t
+
+ctypedef npy_uint8 uint8_t
+ctypedef npy_uint16 uint16_t
+ctypedef npy_uint32 uint32_t
+ctypedef npy_uint64 uint64_t
+#ctypedef npy_uint96 uint96_t
+#ctypedef npy_uint128 uint128_t
+
+ctypedef npy_float32 float32_t
+ctypedef npy_float64 float64_t
+#ctypedef npy_float80 float80_t
+#ctypedef npy_float128 float128_t
+
+ctypedef float complex complex64_t
+ctypedef double complex complex128_t
+
+# The int types are mapped a bit surprising --
+# numpy.int corresponds to 'l' and numpy.long to 'q'
+ctypedef npy_long int_t
+ctypedef npy_longlong longlong_t
+
+ctypedef npy_ulong uint_t
+ctypedef npy_ulonglong ulonglong_t
+
+ctypedef npy_intp intp_t
+ctypedef npy_uintp uintp_t
+
+ctypedef npy_double float_t
+ctypedef npy_double double_t
+ctypedef npy_longdouble longdouble_t
+
+ctypedef npy_cfloat cfloat_t
+ctypedef npy_cdouble cdouble_t
+ctypedef npy_clongdouble clongdouble_t
+
+ctypedef npy_cdouble complex_t
+
+cdef inline object PyArray_MultiIterNew1(a):
+ return PyArray_MultiIterNew(1, a)
+
+cdef inline object PyArray_MultiIterNew2(a, b):
+ return PyArray_MultiIterNew(2, a, b)
+
+cdef inline object PyArray_MultiIterNew3(a, b, c):
+ return PyArray_MultiIterNew(3, a, b, c)
+
+cdef inline object PyArray_MultiIterNew4(a, b, c, d):
+ return PyArray_MultiIterNew(4, a, b, c, d)
+
+cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
+ return PyArray_MultiIterNew(5, a, b, c, d, e)
+
+cdef inline tuple PyDataType_SHAPE(dtype d):
+ if PyDataType_HASSUBARRAY(d):
+ return d.subarray.shape
+ else:
+ return ()
+
+
+cdef extern from "numpy/ndarrayobject.h":
+ PyTypeObject PyTimedeltaArrType_Type
+ PyTypeObject PyDatetimeArrType_Type
+ ctypedef int64_t npy_timedelta
+ ctypedef int64_t npy_datetime
+
+cdef extern from "numpy/ndarraytypes.h":
+ ctypedef struct PyArray_DatetimeMetaData:
+ NPY_DATETIMEUNIT base
+ int64_t num
+
+cdef extern from "numpy/arrayscalars.h":
+
+ # abstract types
+ ctypedef class numpy.generic [object PyObject]:
+ pass
+ ctypedef class numpy.number [object PyObject]:
+ pass
+ ctypedef class numpy.integer [object PyObject]:
+ pass
+ ctypedef class numpy.signedinteger [object PyObject]:
+ pass
+ ctypedef class numpy.unsignedinteger [object PyObject]:
+ pass
+ ctypedef class numpy.inexact [object PyObject]:
+ pass
+ ctypedef class numpy.floating [object PyObject]:
+ pass
+ ctypedef class numpy.complexfloating [object PyObject]:
+ pass
+ ctypedef class numpy.flexible [object PyObject]:
+ pass
+ ctypedef class numpy.character [object PyObject]:
+ pass
+
+ ctypedef struct PyDatetimeScalarObject:
+ # PyObject_HEAD
+ npy_datetime obval
+ PyArray_DatetimeMetaData obmeta
+
+ ctypedef struct PyTimedeltaScalarObject:
+ # PyObject_HEAD
+ npy_timedelta obval
+ PyArray_DatetimeMetaData obmeta
+
+ ctypedef enum NPY_DATETIMEUNIT:
+ NPY_FR_Y
+ NPY_FR_M
+ NPY_FR_W
+ NPY_FR_D
+ NPY_FR_B
+ NPY_FR_h
+ NPY_FR_m
+ NPY_FR_s
+ NPY_FR_ms
+ NPY_FR_us
+ NPY_FR_ns
+ NPY_FR_ps
+ NPY_FR_fs
+ NPY_FR_as
+ NPY_FR_GENERIC
+
+
+#
+# ufunc API
+#
+
+cdef extern from "numpy/ufuncobject.h":
+
+ ctypedef void (*PyUFuncGenericFunction) (char **, npy_intp *, npy_intp *, void *)
+
+ ctypedef class numpy.ufunc [object PyUFuncObject, check_size ignore]:
+ cdef:
+ int nin, nout, nargs
+ int identity
+ PyUFuncGenericFunction *functions
+ void **data
+ int ntypes
+ int check_return
+ char *name
+ char *types
+ char *doc
+ void *ptr
+ PyObject *obj
+ PyObject *userloops
+
+ cdef enum:
+ PyUFunc_Zero
+ PyUFunc_One
+ PyUFunc_None
+ UFUNC_ERR_IGNORE
+ UFUNC_ERR_WARN
+ UFUNC_ERR_RAISE
+ UFUNC_ERR_CALL
+ UFUNC_ERR_PRINT
+ UFUNC_ERR_LOG
+ UFUNC_MASK_DIVIDEBYZERO
+ UFUNC_MASK_OVERFLOW
+ UFUNC_MASK_UNDERFLOW
+ UFUNC_MASK_INVALID
+ UFUNC_SHIFT_DIVIDEBYZERO
+ UFUNC_SHIFT_OVERFLOW
+ UFUNC_SHIFT_UNDERFLOW
+ UFUNC_SHIFT_INVALID
+ UFUNC_FPE_DIVIDEBYZERO
+ UFUNC_FPE_OVERFLOW
+ UFUNC_FPE_UNDERFLOW
+ UFUNC_FPE_INVALID
+ UFUNC_ERR_DEFAULT
+ UFUNC_ERR_DEFAULT2
+
+ object PyUFunc_FromFuncAndData(PyUFuncGenericFunction *,
+ void **, char *, int, int, int, int, char *, char *, int)
+ int PyUFunc_RegisterLoopForType(ufunc, int,
+ PyUFuncGenericFunction, int *, void *) except -1
+ void PyUFunc_f_f_As_d_d \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_d_d \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_f_f \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_g_g \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_F_F_As_D_D \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_F_F \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_D_D \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_G_G \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_O_O \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_ff_f_As_dd_d \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_ff_f \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_dd_d \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_gg_g \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_FF_F_As_DD_D \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_DD_D \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_FF_F \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_GG_G \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_OO_O \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_O_O_method \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_OO_O_method \
+ (char **, npy_intp *, npy_intp *, void *)
+ void PyUFunc_On_Om \
+ (char **, npy_intp *, npy_intp *, void *)
+ int PyUFunc_GetPyValues \
+ (char *, int *, int *, PyObject **)
+ int PyUFunc_checkfperr \
+ (int, PyObject *, int *)
+ void PyUFunc_clearfperr()
+ int PyUFunc_getfperr()
+ int PyUFunc_handlefperr \
+ (int, PyObject *, int, int *) except -1
+ int PyUFunc_ReplaceLoopBySignature \
+ (ufunc, PyUFuncGenericFunction, int *, PyUFuncGenericFunction *)
+ object PyUFunc_FromFuncAndDataAndSignature \
+ (PyUFuncGenericFunction *, void **, char *, int, int, int,
+ int, char *, char *, int, char *)
+
+ int _import_umath() except -1
+
+cdef inline void set_array_base(ndarray arr, object base):
+ Py_INCREF(base) # important to do this before stealing the reference below!
+ PyArray_SetBaseObject(arr, base)
+
+cdef inline object get_array_base(ndarray arr):
+ base = PyArray_BASE(arr)
+ if base is NULL:
+ return None
+ return base
+
+# Versions of the import_* functions which are more suitable for
+# Cython code.
+cdef inline int import_array() except -1:
+ try:
+ __pyx_import_array()
+ except Exception:
+ raise ImportError("numpy.core.multiarray failed to import")
+
+cdef inline int import_umath() except -1:
+ try:
+ _import_umath()
+ except Exception:
+ raise ImportError("numpy.core.umath failed to import")
+
+cdef inline int import_ufunc() except -1:
+ try:
+ _import_umath()
+ except Exception:
+ raise ImportError("numpy.core.umath failed to import")
+
+cdef extern from *:
+ # Leave a marker that the NumPy declarations came from this file
+ # See https://github.com/cython/cython/issues/3573
+ """
+ /* NumPy API declarations from "numpy/__init__.pxd" */
+ """
+
+
+cdef inline bint is_timedelta64_object(object obj):
+ """
+ Cython equivalent of `isinstance(obj, np.timedelta64)`
+
+ Parameters
+ ----------
+ obj : object
+
+ Returns
+ -------
+ bool
+ """
+ return PyObject_TypeCheck(obj, &PyTimedeltaArrType_Type)
+
+
+cdef inline bint is_datetime64_object(object obj):
+ """
+ Cython equivalent of `isinstance(obj, np.datetime64)`
+
+ Parameters
+ ----------
+ obj : object
+
+ Returns
+ -------
+ bool
+ """
+ return PyObject_TypeCheck(obj, &PyDatetimeArrType_Type)
+
+
+cdef inline npy_datetime get_datetime64_value(object obj) nogil:
+ """
+ returns the int64 value underlying scalar numpy datetime64 object
+
+ Note that to interpret this as a datetime, the corresponding unit is
+ also needed. That can be found using `get_datetime64_unit`.
+ """
+ return (obj).obval
+
+
+cdef inline npy_timedelta get_timedelta64_value(object obj) nogil:
+ """
+ returns the int64 value underlying scalar numpy timedelta64 object
+ """
+ return (obj).obval
+
+
+cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) nogil:
+ """
+ returns the unit part of the dtype for a numpy datetime64 object.
+ """
+ return (obj).obmeta.base
diff --git a/lib/python3.12/site-packages/numpy/__init__.py b/lib/python3.12/site-packages/numpy/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..91da496a95271f8e3eb4f4ea2cbaec925325a1f5
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/__init__.py
@@ -0,0 +1,461 @@
+"""
+NumPy
+=====
+
+Provides
+ 1. An array object of arbitrary homogeneous items
+ 2. Fast mathematical operations over arrays
+ 3. Linear Algebra, Fourier Transforms, Random Number Generation
+
+How to use the documentation
+----------------------------
+Documentation is available in two forms: docstrings provided
+with the code, and a loose standing reference guide, available from
+`the NumPy homepage `_.
+
+We recommend exploring the docstrings using
+`IPython `_, an advanced Python shell with
+TAB-completion and introspection capabilities. See below for further
+instructions.
+
+The docstring examples assume that `numpy` has been imported as ``np``::
+
+ >>> import numpy as np
+
+Code snippets are indicated by three greater-than signs::
+
+ >>> x = 42
+ >>> x = x + 1
+
+Use the built-in ``help`` function to view a function's docstring::
+
+ >>> help(np.sort)
+ ... # doctest: +SKIP
+
+For some objects, ``np.info(obj)`` may provide additional help. This is
+particularly true if you see the line "Help on ufunc object:" at the top
+of the help() page. Ufuncs are implemented in C, not Python, for speed.
+The native Python help() does not know how to view their help, but our
+np.info() function does.
+
+To search for documents containing a keyword, do::
+
+ >>> np.lookfor('keyword')
+ ... # doctest: +SKIP
+
+General-purpose documents like a glossary and help on the basic concepts
+of numpy are available under the ``doc`` sub-module::
+
+ >>> from numpy import doc
+ >>> help(doc)
+ ... # doctest: +SKIP
+
+Available subpackages
+---------------------
+lib
+ Basic functions used by several sub-packages.
+random
+ Core Random Tools
+linalg
+ Core Linear Algebra Tools
+fft
+ Core FFT routines
+polynomial
+ Polynomial tools
+testing
+ NumPy testing tools
+distutils
+ Enhancements to distutils with support for
+ Fortran compilers support and more (for Python <= 3.11).
+
+Utilities
+---------
+test
+ Run numpy unittests
+show_config
+ Show numpy build configuration
+matlib
+ Make everything matrices.
+__version__
+ NumPy version string
+
+Viewing documentation using IPython
+-----------------------------------
+
+Start IPython and import `numpy` usually under the alias ``np``: `import
+numpy as np`. Then, directly past or use the ``%cpaste`` magic to paste
+examples into the shell. To see which functions are available in `numpy`,
+type ``np.`` (where ```` refers to the TAB key), or use
+``np.*cos*?`` (where ```` refers to the ENTER key) to narrow
+down the list. To view the docstring for a function, use
+``np.cos?`` (to view the docstring) and ``np.cos??`` (to view
+the source code).
+
+Copies vs. in-place operation
+-----------------------------
+Most of the functions in `numpy` return a copy of the array argument
+(e.g., `np.sort`). In-place versions of these functions are often
+available as array methods, i.e. ``x = np.array([1,2,3]); x.sort()``.
+Exceptions to this rule are documented.
+
+"""
+import sys
+import warnings
+
+from ._globals import _NoValue, _CopyMode
+# These exceptions were moved in 1.25 and are hidden from __dir__()
+from .exceptions import (
+ ComplexWarning, ModuleDeprecationWarning, VisibleDeprecationWarning,
+ TooHardError, AxisError)
+
+
+# If a version with git hash was stored, use that instead
+from . import version
+from .version import __version__
+
+# We first need to detect if we're being called as part of the numpy setup
+# procedure itself in a reliable manner.
+try:
+ __NUMPY_SETUP__
+except NameError:
+ __NUMPY_SETUP__ = False
+
+if __NUMPY_SETUP__:
+ sys.stderr.write('Running from numpy source directory.\n')
+else:
+ # Allow distributors to run custom init code before importing numpy.core
+ from . import _distributor_init
+
+ try:
+ from numpy.__config__ import show as show_config
+ except ImportError as e:
+ msg = """Error importing numpy: you should not try to import numpy from
+ its source directory; please exit the numpy source tree, and relaunch
+ your python interpreter from there."""
+ raise ImportError(msg) from e
+
+ __all__ = [
+ 'exceptions', 'ModuleDeprecationWarning', 'VisibleDeprecationWarning',
+ 'ComplexWarning', 'TooHardError', 'AxisError']
+
+ # mapping of {name: (value, deprecation_msg)}
+ __deprecated_attrs__ = {}
+
+ from . import core
+ from .core import *
+ from . import compat
+ from . import exceptions
+ from . import dtypes
+ from . import lib
+ # NOTE: to be revisited following future namespace cleanup.
+ # See gh-14454 and gh-15672 for discussion.
+ from .lib import *
+
+ from . import linalg
+ from . import fft
+ from . import polynomial
+ from . import random
+ from . import ctypeslib
+ from . import ma
+ from . import matrixlib as _mat
+ from .matrixlib import *
+
+ # Deprecations introduced in NumPy 1.20.0, 2020-06-06
+ import builtins as _builtins
+
+ _msg = (
+ "module 'numpy' has no attribute '{n}'.\n"
+ "`np.{n}` was a deprecated alias for the builtin `{n}`. "
+ "To avoid this error in existing code, use `{n}` by itself. "
+ "Doing this will not modify any behavior and is safe. {extended_msg}\n"
+ "The aliases was originally deprecated in NumPy 1.20; for more "
+ "details and guidance see the original release note at:\n"
+ " https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations")
+
+ _specific_msg = (
+ "If you specifically wanted the numpy scalar type, use `np.{}` here.")
+
+ _int_extended_msg = (
+ "When replacing `np.{}`, you may wish to use e.g. `np.int64` "
+ "or `np.int32` to specify the precision. If you wish to review "
+ "your current use, check the release note link for "
+ "additional information.")
+
+ _type_info = [
+ ("object", ""), # The NumPy scalar only exists by name.
+ ("bool", _specific_msg.format("bool_")),
+ ("float", _specific_msg.format("float64")),
+ ("complex", _specific_msg.format("complex128")),
+ ("str", _specific_msg.format("str_")),
+ ("int", _int_extended_msg.format("int"))]
+
+ __former_attrs__ = {
+ n: _msg.format(n=n, extended_msg=extended_msg)
+ for n, extended_msg in _type_info
+ }
+
+ # Future warning introduced in NumPy 1.24.0, 2022-11-17
+ _msg = (
+ "`np.{n}` is a deprecated alias for `{an}`. (Deprecated NumPy 1.24)")
+
+ # Some of these are awkward (since `np.str` may be preferable in the long
+ # term), but overall the names ending in 0 seem undesirable
+ _type_info = [
+ ("bool8", bool_, "np.bool_"),
+ ("int0", intp, "np.intp"),
+ ("uint0", uintp, "np.uintp"),
+ ("str0", str_, "np.str_"),
+ ("bytes0", bytes_, "np.bytes_"),
+ ("void0", void, "np.void"),
+ ("object0", object_,
+ "`np.object0` is a deprecated alias for `np.object_`. "
+ "`object` can be used instead. (Deprecated NumPy 1.24)")]
+
+ # Some of these could be defined right away, but most were aliases to
+ # the Python objects and only removed in NumPy 1.24. Defining them should
+ # probably wait for NumPy 1.26 or 2.0.
+ # When defined, these should possibly not be added to `__all__` to avoid
+ # import with `from numpy import *`.
+ __future_scalars__ = {"bool", "long", "ulong", "str", "bytes", "object"}
+
+ __deprecated_attrs__.update({
+ n: (alias, _msg.format(n=n, an=an)) for n, alias, an in _type_info})
+
+ import math
+
+ __deprecated_attrs__['math'] = (math,
+ "`np.math` is a deprecated alias for the standard library `math` "
+ "module (Deprecated Numpy 1.25). Replace usages of `np.math` with "
+ "`math`")
+
+ del math, _msg, _type_info
+
+ from .core import abs
+ # now that numpy modules are imported, can initialize limits
+ core.getlimits._register_known_types()
+
+ __all__.extend(['__version__', 'show_config'])
+ __all__.extend(core.__all__)
+ __all__.extend(_mat.__all__)
+ __all__.extend(lib.__all__)
+ __all__.extend(['linalg', 'fft', 'random', 'ctypeslib', 'ma'])
+
+ # Remove min and max from __all__ to avoid `from numpy import *` override
+ # the builtins min/max. Temporary fix for 1.25.x/1.26.x, see gh-24229.
+ __all__.remove('min')
+ __all__.remove('max')
+ __all__.remove('round')
+
+ # Remove one of the two occurrences of `issubdtype`, which is exposed as
+ # both `numpy.core.issubdtype` and `numpy.lib.issubdtype`.
+ __all__.remove('issubdtype')
+
+ # These are exported by np.core, but are replaced by the builtins below
+ # remove them to ensure that we don't end up with `np.long == np.int_`,
+ # which would be a breaking change.
+ del long, unicode
+ __all__.remove('long')
+ __all__.remove('unicode')
+
+ # Remove things that are in the numpy.lib but not in the numpy namespace
+ # Note that there is a test (numpy/tests/test_public_api.py:test_numpy_namespace)
+ # that prevents adding more things to the main namespace by accident.
+ # The list below will grow until the `from .lib import *` fixme above is
+ # taken care of
+ __all__.remove('Arrayterator')
+ del Arrayterator
+
+ # These names were removed in NumPy 1.20. For at least one release,
+ # attempts to access these names in the numpy namespace will trigger
+ # a warning, and calling the function will raise an exception.
+ _financial_names = ['fv', 'ipmt', 'irr', 'mirr', 'nper', 'npv', 'pmt',
+ 'ppmt', 'pv', 'rate']
+ __expired_functions__ = {
+ name: (f'In accordance with NEP 32, the function {name} was removed '
+ 'from NumPy version 1.20. A replacement for this function '
+ 'is available in the numpy_financial library: '
+ 'https://pypi.org/project/numpy-financial')
+ for name in _financial_names}
+
+ # Filter out Cython harmless warnings
+ warnings.filterwarnings("ignore", message="numpy.dtype size changed")
+ warnings.filterwarnings("ignore", message="numpy.ufunc size changed")
+ warnings.filterwarnings("ignore", message="numpy.ndarray size changed")
+
+ # oldnumeric and numarray were removed in 1.9. In case some packages import
+ # but do not use them, we define them here for backward compatibility.
+ oldnumeric = 'removed'
+ numarray = 'removed'
+
+ def __getattr__(attr):
+ # Warn for expired attributes, and return a dummy function
+ # that always raises an exception.
+ import warnings
+ import math
+ try:
+ msg = __expired_functions__[attr]
+ except KeyError:
+ pass
+ else:
+ warnings.warn(msg, DeprecationWarning, stacklevel=2)
+
+ def _expired(*args, **kwds):
+ raise RuntimeError(msg)
+
+ return _expired
+
+ # Emit warnings for deprecated attributes
+ try:
+ val, msg = __deprecated_attrs__[attr]
+ except KeyError:
+ pass
+ else:
+ warnings.warn(msg, DeprecationWarning, stacklevel=2)
+ return val
+
+ if attr in __future_scalars__:
+ # And future warnings for those that will change, but also give
+ # the AttributeError
+ warnings.warn(
+ f"In the future `np.{attr}` will be defined as the "
+ "corresponding NumPy scalar.", FutureWarning, stacklevel=2)
+
+ if attr in __former_attrs__:
+ raise AttributeError(__former_attrs__[attr])
+
+ if attr == 'testing':
+ import numpy.testing as testing
+ return testing
+ elif attr == 'Tester':
+ "Removed in NumPy 1.25.0"
+ raise RuntimeError("Tester was removed in NumPy 1.25.")
+
+ raise AttributeError("module {!r} has no attribute "
+ "{!r}".format(__name__, attr))
+
+ def __dir__():
+ public_symbols = globals().keys() | {'testing'}
+ public_symbols -= {
+ "core", "matrixlib",
+ # These were moved in 1.25 and may be deprecated eventually:
+ "ModuleDeprecationWarning", "VisibleDeprecationWarning",
+ "ComplexWarning", "TooHardError", "AxisError"
+ }
+ return list(public_symbols)
+
+ # Pytest testing
+ from numpy._pytesttester import PytestTester
+ test = PytestTester(__name__)
+ del PytestTester
+
+ def _sanity_check():
+ """
+ Quick sanity checks for common bugs caused by environment.
+ There are some cases e.g. with wrong BLAS ABI that cause wrong
+ results under specific runtime conditions that are not necessarily
+ achieved during test suite runs, and it is useful to catch those early.
+
+ See https://github.com/numpy/numpy/issues/8577 and other
+ similar bug reports.
+
+ """
+ try:
+ x = ones(2, dtype=float32)
+ if not abs(x.dot(x) - float32(2.0)) < 1e-5:
+ raise AssertionError()
+ except AssertionError:
+ msg = ("The current Numpy installation ({!r}) fails to "
+ "pass simple sanity checks. This can be caused for example "
+ "by incorrect BLAS library being linked in, or by mixing "
+ "package managers (pip, conda, apt, ...). Search closed "
+ "numpy issues for similar problems.")
+ raise RuntimeError(msg.format(__file__)) from None
+
+ _sanity_check()
+ del _sanity_check
+
+ def _mac_os_check():
+ """
+ Quick Sanity check for Mac OS look for accelerate build bugs.
+ Testing numpy polyfit calls init_dgelsd(LAPACK)
+ """
+ try:
+ c = array([3., 2., 1.])
+ x = linspace(0, 2, 5)
+ y = polyval(c, x)
+ _ = polyfit(x, y, 2, cov=True)
+ except ValueError:
+ pass
+
+ if sys.platform == "darwin":
+ from . import exceptions
+ with warnings.catch_warnings(record=True) as w:
+ _mac_os_check()
+ # Throw runtime error, if the test failed Check for warning and error_message
+ if len(w) > 0:
+ for _wn in w:
+ if _wn.category is exceptions.RankWarning:
+ # Ignore other warnings, they may not be relevant (see gh-25433).
+ error_message = f"{_wn.category.__name__}: {str(_wn.message)}"
+ msg = (
+ "Polyfit sanity test emitted a warning, most likely due "
+ "to using a buggy Accelerate backend."
+ "\nIf you compiled yourself, more information is available at:"
+ "\nhttps://numpy.org/devdocs/building/index.html"
+ "\nOtherwise report this to the vendor "
+ "that provided NumPy.\n\n{}\n".format(error_message))
+ raise RuntimeError(msg)
+ del _wn
+ del w
+ del _mac_os_check
+
+ # We usually use madvise hugepages support, but on some old kernels it
+ # is slow and thus better avoided.
+ # Specifically kernel version 4.6 had a bug fix which probably fixed this:
+ # https://github.com/torvalds/linux/commit/7cf91a98e607c2f935dbcc177d70011e95b8faff
+ import os
+ use_hugepage = os.environ.get("NUMPY_MADVISE_HUGEPAGE", None)
+ if sys.platform == "linux" and use_hugepage is None:
+ # If there is an issue with parsing the kernel version,
+ # set use_hugepages to 0. Usage of LooseVersion will handle
+ # the kernel version parsing better, but avoided since it
+ # will increase the import time. See: #16679 for related discussion.
+ try:
+ use_hugepage = 1
+ kernel_version = os.uname().release.split(".")[:2]
+ kernel_version = tuple(int(v) for v in kernel_version)
+ if kernel_version < (4, 6):
+ use_hugepage = 0
+ except ValueError:
+ use_hugepages = 0
+ elif use_hugepage is None:
+ # This is not Linux, so it should not matter, just enable anyway
+ use_hugepage = 1
+ else:
+ use_hugepage = int(use_hugepage)
+
+ # Note that this will currently only make a difference on Linux
+ core.multiarray._set_madvise_hugepage(use_hugepage)
+ del use_hugepage
+
+ # Give a warning if NumPy is reloaded or imported on a sub-interpreter
+ # We do this from python, since the C-module may not be reloaded and
+ # it is tidier organized.
+ core.multiarray._multiarray_umath._reload_guard()
+
+ # default to "weak" promotion for "NumPy 2".
+ core._set_promotion_state(
+ os.environ.get("NPY_PROMOTION_STATE",
+ "weak" if _using_numpy2_behavior() else "legacy"))
+
+ # Tell PyInstaller where to find hook-numpy.py
+ def _pyinstaller_hooks_dir():
+ from pathlib import Path
+ return [str(Path(__file__).with_name("_pyinstaller").resolve())]
+
+ # Remove symbols imported for internal use
+ del os
+
+
+# Remove symbols imported for internal use
+del sys, warnings
diff --git a/lib/python3.12/site-packages/numpy/__init__.pyi b/lib/python3.12/site-packages/numpy/__init__.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..a185bfe754e3d6ba5004f8cca06177e60a7aa13c
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/__init__.pyi
@@ -0,0 +1,4422 @@
+import builtins
+import sys
+import os
+import mmap
+import ctypes as ct
+import array as _array
+import datetime as dt
+import enum
+from abc import abstractmethod
+from types import TracebackType, MappingProxyType, GenericAlias
+from contextlib import ContextDecorator
+from contextlib import contextmanager
+
+from numpy._pytesttester import PytestTester
+from numpy.core._internal import _ctypes
+
+from numpy._typing import (
+ # Arrays
+ ArrayLike,
+ NDArray,
+ _SupportsArray,
+ _NestedSequence,
+ _FiniteNestedSequence,
+ _SupportsArray,
+ _ArrayLikeBool_co,
+ _ArrayLikeUInt_co,
+ _ArrayLikeInt_co,
+ _ArrayLikeFloat_co,
+ _ArrayLikeComplex_co,
+ _ArrayLikeNumber_co,
+ _ArrayLikeTD64_co,
+ _ArrayLikeDT64_co,
+ _ArrayLikeObject_co,
+ _ArrayLikeStr_co,
+ _ArrayLikeBytes_co,
+ _ArrayLikeUnknown,
+ _UnknownType,
+
+ # DTypes
+ DTypeLike,
+ _DTypeLike,
+ _DTypeLikeVoid,
+ _SupportsDType,
+ _VoidDTypeLike,
+
+ # Shapes
+ _Shape,
+ _ShapeLike,
+
+ # Scalars
+ _CharLike_co,
+ _BoolLike_co,
+ _IntLike_co,
+ _FloatLike_co,
+ _ComplexLike_co,
+ _TD64Like_co,
+ _NumberLike_co,
+ _ScalarLike_co,
+
+ # `number` precision
+ NBitBase,
+ _256Bit,
+ _128Bit,
+ _96Bit,
+ _80Bit,
+ _64Bit,
+ _32Bit,
+ _16Bit,
+ _8Bit,
+ _NBitByte,
+ _NBitShort,
+ _NBitIntC,
+ _NBitIntP,
+ _NBitInt,
+ _NBitLongLong,
+ _NBitHalf,
+ _NBitSingle,
+ _NBitDouble,
+ _NBitLongDouble,
+
+ # Character codes
+ _BoolCodes,
+ _UInt8Codes,
+ _UInt16Codes,
+ _UInt32Codes,
+ _UInt64Codes,
+ _Int8Codes,
+ _Int16Codes,
+ _Int32Codes,
+ _Int64Codes,
+ _Float16Codes,
+ _Float32Codes,
+ _Float64Codes,
+ _Complex64Codes,
+ _Complex128Codes,
+ _ByteCodes,
+ _ShortCodes,
+ _IntCCodes,
+ _IntPCodes,
+ _IntCodes,
+ _LongLongCodes,
+ _UByteCodes,
+ _UShortCodes,
+ _UIntCCodes,
+ _UIntPCodes,
+ _UIntCodes,
+ _ULongLongCodes,
+ _HalfCodes,
+ _SingleCodes,
+ _DoubleCodes,
+ _LongDoubleCodes,
+ _CSingleCodes,
+ _CDoubleCodes,
+ _CLongDoubleCodes,
+ _DT64Codes,
+ _TD64Codes,
+ _StrCodes,
+ _BytesCodes,
+ _VoidCodes,
+ _ObjectCodes,
+
+ # Ufuncs
+ _UFunc_Nin1_Nout1,
+ _UFunc_Nin2_Nout1,
+ _UFunc_Nin1_Nout2,
+ _UFunc_Nin2_Nout2,
+ _GUFunc_Nin2_Nout1,
+)
+
+from numpy._typing._callable import (
+ _BoolOp,
+ _BoolBitOp,
+ _BoolSub,
+ _BoolTrueDiv,
+ _BoolMod,
+ _BoolDivMod,
+ _TD64Div,
+ _IntTrueDiv,
+ _UnsignedIntOp,
+ _UnsignedIntBitOp,
+ _UnsignedIntMod,
+ _UnsignedIntDivMod,
+ _SignedIntOp,
+ _SignedIntBitOp,
+ _SignedIntMod,
+ _SignedIntDivMod,
+ _FloatOp,
+ _FloatMod,
+ _FloatDivMod,
+ _ComplexOp,
+ _NumberOp,
+ _ComparisonOp,
+)
+
+# NOTE: Numpy's mypy plugin is used for removing the types unavailable
+# to the specific platform
+from numpy._typing._extended_precision import (
+ uint128 as uint128,
+ uint256 as uint256,
+ int128 as int128,
+ int256 as int256,
+ float80 as float80,
+ float96 as float96,
+ float128 as float128,
+ float256 as float256,
+ complex160 as complex160,
+ complex192 as complex192,
+ complex256 as complex256,
+ complex512 as complex512,
+)
+
+from collections.abc import (
+ Callable,
+ Container,
+ Iterable,
+ Iterator,
+ Mapping,
+ Sequence,
+ Sized,
+)
+from typing import (
+ Literal as L,
+ Any,
+ Generator,
+ Generic,
+ IO,
+ NoReturn,
+ overload,
+ SupportsComplex,
+ SupportsFloat,
+ SupportsInt,
+ TypeVar,
+ Union,
+ Protocol,
+ SupportsIndex,
+ Final,
+ final,
+ ClassVar,
+)
+
+# Ensures that the stubs are picked up
+from numpy import (
+ ctypeslib as ctypeslib,
+ exceptions as exceptions,
+ fft as fft,
+ lib as lib,
+ linalg as linalg,
+ ma as ma,
+ polynomial as polynomial,
+ random as random,
+ testing as testing,
+ version as version,
+ exceptions as exceptions,
+ dtypes as dtypes,
+)
+
+from numpy.core import defchararray, records
+char = defchararray
+rec = records
+
+from numpy.core.function_base import (
+ linspace as linspace,
+ logspace as logspace,
+ geomspace as geomspace,
+)
+
+from numpy.core.fromnumeric import (
+ take as take,
+ reshape as reshape,
+ choose as choose,
+ repeat as repeat,
+ put as put,
+ swapaxes as swapaxes,
+ transpose as transpose,
+ partition as partition,
+ argpartition as argpartition,
+ sort as sort,
+ argsort as argsort,
+ argmax as argmax,
+ argmin as argmin,
+ searchsorted as searchsorted,
+ resize as resize,
+ squeeze as squeeze,
+ diagonal as diagonal,
+ trace as trace,
+ ravel as ravel,
+ nonzero as nonzero,
+ shape as shape,
+ compress as compress,
+ clip as clip,
+ sum as sum,
+ all as all,
+ any as any,
+ cumsum as cumsum,
+ ptp as ptp,
+ max as max,
+ min as min,
+ amax as amax,
+ amin as amin,
+ prod as prod,
+ cumprod as cumprod,
+ ndim as ndim,
+ size as size,
+ around as around,
+ round as round,
+ mean as mean,
+ std as std,
+ var as var,
+)
+
+from numpy.core._asarray import (
+ require as require,
+)
+
+from numpy.core._type_aliases import (
+ sctypes as sctypes,
+ sctypeDict as sctypeDict,
+)
+
+from numpy.core._ufunc_config import (
+ seterr as seterr,
+ geterr as geterr,
+ setbufsize as setbufsize,
+ getbufsize as getbufsize,
+ seterrcall as seterrcall,
+ geterrcall as geterrcall,
+ _ErrKind,
+ _ErrFunc,
+ _ErrDictOptional,
+)
+
+from numpy.core.arrayprint import (
+ set_printoptions as set_printoptions,
+ get_printoptions as get_printoptions,
+ array2string as array2string,
+ format_float_scientific as format_float_scientific,
+ format_float_positional as format_float_positional,
+ array_repr as array_repr,
+ array_str as array_str,
+ set_string_function as set_string_function,
+ printoptions as printoptions,
+)
+
+from numpy.core.einsumfunc import (
+ einsum as einsum,
+ einsum_path as einsum_path,
+)
+
+from numpy.core.multiarray import (
+ ALLOW_THREADS as ALLOW_THREADS,
+ BUFSIZE as BUFSIZE,
+ CLIP as CLIP,
+ MAXDIMS as MAXDIMS,
+ MAY_SHARE_BOUNDS as MAY_SHARE_BOUNDS,
+ MAY_SHARE_EXACT as MAY_SHARE_EXACT,
+ RAISE as RAISE,
+ WRAP as WRAP,
+ tracemalloc_domain as tracemalloc_domain,
+ array as array,
+ empty_like as empty_like,
+ empty as empty,
+ zeros as zeros,
+ concatenate as concatenate,
+ inner as inner,
+ where as where,
+ lexsort as lexsort,
+ can_cast as can_cast,
+ min_scalar_type as min_scalar_type,
+ result_type as result_type,
+ dot as dot,
+ vdot as vdot,
+ bincount as bincount,
+ copyto as copyto,
+ putmask as putmask,
+ packbits as packbits,
+ unpackbits as unpackbits,
+ shares_memory as shares_memory,
+ may_share_memory as may_share_memory,
+ asarray as asarray,
+ asanyarray as asanyarray,
+ ascontiguousarray as ascontiguousarray,
+ asfortranarray as asfortranarray,
+ arange as arange,
+ busday_count as busday_count,
+ busday_offset as busday_offset,
+ compare_chararrays as compare_chararrays,
+ datetime_as_string as datetime_as_string,
+ datetime_data as datetime_data,
+ frombuffer as frombuffer,
+ fromfile as fromfile,
+ fromiter as fromiter,
+ is_busday as is_busday,
+ promote_types as promote_types,
+ seterrobj as seterrobj,
+ geterrobj as geterrobj,
+ fromstring as fromstring,
+ frompyfunc as frompyfunc,
+ nested_iters as nested_iters,
+ flagsobj,
+)
+
+from numpy.core.numeric import (
+ zeros_like as zeros_like,
+ ones as ones,
+ ones_like as ones_like,
+ full as full,
+ full_like as full_like,
+ count_nonzero as count_nonzero,
+ isfortran as isfortran,
+ argwhere as argwhere,
+ flatnonzero as flatnonzero,
+ correlate as correlate,
+ convolve as convolve,
+ outer as outer,
+ tensordot as tensordot,
+ roll as roll,
+ rollaxis as rollaxis,
+ moveaxis as moveaxis,
+ cross as cross,
+ indices as indices,
+ fromfunction as fromfunction,
+ isscalar as isscalar,
+ binary_repr as binary_repr,
+ base_repr as base_repr,
+ identity as identity,
+ allclose as allclose,
+ isclose as isclose,
+ array_equal as array_equal,
+ array_equiv as array_equiv,
+)
+
+from numpy.core.numerictypes import (
+ maximum_sctype as maximum_sctype,
+ issctype as issctype,
+ obj2sctype as obj2sctype,
+ issubclass_ as issubclass_,
+ issubsctype as issubsctype,
+ issubdtype as issubdtype,
+ sctype2char as sctype2char,
+ nbytes as nbytes,
+ cast as cast,
+ ScalarType as ScalarType,
+ typecodes as typecodes,
+)
+
+from numpy.core.shape_base import (
+ atleast_1d as atleast_1d,
+ atleast_2d as atleast_2d,
+ atleast_3d as atleast_3d,
+ block as block,
+ hstack as hstack,
+ stack as stack,
+ vstack as vstack,
+)
+
+from numpy.exceptions import (
+ ComplexWarning as ComplexWarning,
+ ModuleDeprecationWarning as ModuleDeprecationWarning,
+ VisibleDeprecationWarning as VisibleDeprecationWarning,
+ TooHardError as TooHardError,
+ DTypePromotionError as DTypePromotionError,
+ AxisError as AxisError,
+)
+
+from numpy.lib import (
+ emath as emath,
+)
+
+from numpy.lib.arraypad import (
+ pad as pad,
+)
+
+from numpy.lib.arraysetops import (
+ ediff1d as ediff1d,
+ intersect1d as intersect1d,
+ setxor1d as setxor1d,
+ union1d as union1d,
+ setdiff1d as setdiff1d,
+ unique as unique,
+ in1d as in1d,
+ isin as isin,
+)
+
+from numpy.lib.arrayterator import (
+ Arrayterator as Arrayterator,
+)
+
+from numpy.lib.function_base import (
+ select as select,
+ piecewise as piecewise,
+ trim_zeros as trim_zeros,
+ copy as copy,
+ iterable as iterable,
+ percentile as percentile,
+ diff as diff,
+ gradient as gradient,
+ angle as angle,
+ unwrap as unwrap,
+ sort_complex as sort_complex,
+ disp as disp,
+ flip as flip,
+ rot90 as rot90,
+ extract as extract,
+ place as place,
+ asarray_chkfinite as asarray_chkfinite,
+ average as average,
+ bincount as bincount,
+ digitize as digitize,
+ cov as cov,
+ corrcoef as corrcoef,
+ median as median,
+ sinc as sinc,
+ hamming as hamming,
+ hanning as hanning,
+ bartlett as bartlett,
+ blackman as blackman,
+ kaiser as kaiser,
+ trapz as trapz,
+ i0 as i0,
+ add_newdoc as add_newdoc,
+ add_docstring as add_docstring,
+ meshgrid as meshgrid,
+ delete as delete,
+ insert as insert,
+ append as append,
+ interp as interp,
+ add_newdoc_ufunc as add_newdoc_ufunc,
+ quantile as quantile,
+)
+
+from numpy.lib.histograms import (
+ histogram_bin_edges as histogram_bin_edges,
+ histogram as histogram,
+ histogramdd as histogramdd,
+)
+
+from numpy.lib.index_tricks import (
+ ravel_multi_index as ravel_multi_index,
+ unravel_index as unravel_index,
+ mgrid as mgrid,
+ ogrid as ogrid,
+ r_ as r_,
+ c_ as c_,
+ s_ as s_,
+ index_exp as index_exp,
+ ix_ as ix_,
+ fill_diagonal as fill_diagonal,
+ diag_indices as diag_indices,
+ diag_indices_from as diag_indices_from,
+)
+
+from numpy.lib.nanfunctions import (
+ nansum as nansum,
+ nanmax as nanmax,
+ nanmin as nanmin,
+ nanargmax as nanargmax,
+ nanargmin as nanargmin,
+ nanmean as nanmean,
+ nanmedian as nanmedian,
+ nanpercentile as nanpercentile,
+ nanvar as nanvar,
+ nanstd as nanstd,
+ nanprod as nanprod,
+ nancumsum as nancumsum,
+ nancumprod as nancumprod,
+ nanquantile as nanquantile,
+)
+
+from numpy.lib.npyio import (
+ savetxt as savetxt,
+ loadtxt as loadtxt,
+ genfromtxt as genfromtxt,
+ recfromtxt as recfromtxt,
+ recfromcsv as recfromcsv,
+ load as load,
+ save as save,
+ savez as savez,
+ savez_compressed as savez_compressed,
+ packbits as packbits,
+ unpackbits as unpackbits,
+ fromregex as fromregex,
+)
+
+from numpy.lib.polynomial import (
+ poly as poly,
+ roots as roots,
+ polyint as polyint,
+ polyder as polyder,
+ polyadd as polyadd,
+ polysub as polysub,
+ polymul as polymul,
+ polydiv as polydiv,
+ polyval as polyval,
+ polyfit as polyfit,
+)
+
+from numpy.lib.shape_base import (
+ column_stack as column_stack,
+ row_stack as row_stack,
+ dstack as dstack,
+ array_split as array_split,
+ split as split,
+ hsplit as hsplit,
+ vsplit as vsplit,
+ dsplit as dsplit,
+ apply_over_axes as apply_over_axes,
+ expand_dims as expand_dims,
+ apply_along_axis as apply_along_axis,
+ kron as kron,
+ tile as tile,
+ get_array_wrap as get_array_wrap,
+ take_along_axis as take_along_axis,
+ put_along_axis as put_along_axis,
+)
+
+from numpy.lib.stride_tricks import (
+ broadcast_to as broadcast_to,
+ broadcast_arrays as broadcast_arrays,
+ broadcast_shapes as broadcast_shapes,
+)
+
+from numpy.lib.twodim_base import (
+ diag as diag,
+ diagflat as diagflat,
+ eye as eye,
+ fliplr as fliplr,
+ flipud as flipud,
+ tri as tri,
+ triu as triu,
+ tril as tril,
+ vander as vander,
+ histogram2d as histogram2d,
+ mask_indices as mask_indices,
+ tril_indices as tril_indices,
+ tril_indices_from as tril_indices_from,
+ triu_indices as triu_indices,
+ triu_indices_from as triu_indices_from,
+)
+
+from numpy.lib.type_check import (
+ mintypecode as mintypecode,
+ asfarray as asfarray,
+ real as real,
+ imag as imag,
+ iscomplex as iscomplex,
+ isreal as isreal,
+ iscomplexobj as iscomplexobj,
+ isrealobj as isrealobj,
+ nan_to_num as nan_to_num,
+ real_if_close as real_if_close,
+ typename as typename,
+ common_type as common_type,
+)
+
+from numpy.lib.ufunclike import (
+ fix as fix,
+ isposinf as isposinf,
+ isneginf as isneginf,
+)
+
+from numpy.lib.utils import (
+ issubclass_ as issubclass_,
+ issubsctype as issubsctype,
+ issubdtype as issubdtype,
+ deprecate as deprecate,
+ deprecate_with_doc as deprecate_with_doc,
+ get_include as get_include,
+ info as info,
+ source as source,
+ who as who,
+ lookfor as lookfor,
+ byte_bounds as byte_bounds,
+ safe_eval as safe_eval,
+ show_runtime as show_runtime,
+)
+
+from numpy.matrixlib import (
+ asmatrix as asmatrix,
+ mat as mat,
+ bmat as bmat,
+)
+
+_AnyStr_contra = TypeVar("_AnyStr_contra", str, bytes, contravariant=True)
+
+# Protocol for representing file-like-objects accepted
+# by `ndarray.tofile` and `fromfile`
+class _IOProtocol(Protocol):
+ def flush(self) -> object: ...
+ def fileno(self) -> int: ...
+ def tell(self) -> SupportsIndex: ...
+ def seek(self, offset: int, whence: int, /) -> object: ...
+
+# NOTE: `seek`, `write` and `flush` are technically only required
+# for `readwrite`/`write` modes
+class _MemMapIOProtocol(Protocol):
+ def flush(self) -> object: ...
+ def fileno(self) -> SupportsIndex: ...
+ def tell(self) -> int: ...
+ def seek(self, offset: int, whence: int, /) -> object: ...
+ def write(self, s: bytes, /) -> object: ...
+ @property
+ def read(self) -> object: ...
+
+class _SupportsWrite(Protocol[_AnyStr_contra]):
+ def write(self, s: _AnyStr_contra, /) -> object: ...
+
+__all__: list[str]
+__path__: list[str]
+__version__: str
+test: PytestTester
+
+# TODO: Move placeholders to their respective module once
+# their annotations are properly implemented
+#
+# Placeholders for classes
+
+def show_config() -> None: ...
+
+_NdArraySubClass = TypeVar("_NdArraySubClass", bound=ndarray[Any, Any])
+_DTypeScalar_co = TypeVar("_DTypeScalar_co", covariant=True, bound=generic)
+_ByteOrder = L["S", "<", ">", "=", "|", "L", "B", "N", "I"]
+
+@final
+class dtype(Generic[_DTypeScalar_co]):
+ names: None | tuple[builtins.str, ...]
+ def __hash__(self) -> int: ...
+ # Overload for subclass of generic
+ @overload
+ def __new__(
+ cls,
+ dtype: type[_DTypeScalar_co],
+ align: bool = ...,
+ copy: bool = ...,
+ metadata: dict[builtins.str, Any] = ...,
+ ) -> dtype[_DTypeScalar_co]: ...
+ # Overloads for string aliases, Python types, and some assorted
+ # other special cases. Order is sometimes important because of the
+ # subtype relationships
+ #
+ # bool < int < float < complex < object
+ #
+ # so we have to make sure the overloads for the narrowest type is
+ # first.
+ # Builtin types
+ @overload
+ def __new__(cls, dtype: type[bool], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[bool_]: ...
+ @overload
+ def __new__(cls, dtype: type[int], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[int_]: ...
+ @overload
+ def __new__(cls, dtype: None | type[float], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[float_]: ...
+ @overload
+ def __new__(cls, dtype: type[complex], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[complex_]: ...
+ @overload
+ def __new__(cls, dtype: type[builtins.str], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[str_]: ...
+ @overload
+ def __new__(cls, dtype: type[bytes], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[bytes_]: ...
+
+ # `unsignedinteger` string-based representations and ctypes
+ @overload
+ def __new__(cls, dtype: _UInt8Codes | type[ct.c_uint8], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[uint8]: ...
+ @overload
+ def __new__(cls, dtype: _UInt16Codes | type[ct.c_uint16], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[uint16]: ...
+ @overload
+ def __new__(cls, dtype: _UInt32Codes | type[ct.c_uint32], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[uint32]: ...
+ @overload
+ def __new__(cls, dtype: _UInt64Codes | type[ct.c_uint64], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[uint64]: ...
+ @overload
+ def __new__(cls, dtype: _UByteCodes | type[ct.c_ubyte], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[ubyte]: ...
+ @overload
+ def __new__(cls, dtype: _UShortCodes | type[ct.c_ushort], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[ushort]: ...
+ @overload
+ def __new__(cls, dtype: _UIntCCodes | type[ct.c_uint], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[uintc]: ...
+
+ # NOTE: We're assuming here that `uint_ptr_t == size_t`,
+ # an assumption that does not hold in rare cases (same for `ssize_t`)
+ @overload
+ def __new__(cls, dtype: _UIntPCodes | type[ct.c_void_p] | type[ct.c_size_t], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[uintp]: ...
+ @overload
+ def __new__(cls, dtype: _UIntCodes | type[ct.c_ulong], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[uint]: ...
+ @overload
+ def __new__(cls, dtype: _ULongLongCodes | type[ct.c_ulonglong], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[ulonglong]: ...
+
+ # `signedinteger` string-based representations and ctypes
+ @overload
+ def __new__(cls, dtype: _Int8Codes | type[ct.c_int8], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[int8]: ...
+ @overload
+ def __new__(cls, dtype: _Int16Codes | type[ct.c_int16], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[int16]: ...
+ @overload
+ def __new__(cls, dtype: _Int32Codes | type[ct.c_int32], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[int32]: ...
+ @overload
+ def __new__(cls, dtype: _Int64Codes | type[ct.c_int64], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[int64]: ...
+ @overload
+ def __new__(cls, dtype: _ByteCodes | type[ct.c_byte], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[byte]: ...
+ @overload
+ def __new__(cls, dtype: _ShortCodes | type[ct.c_short], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[short]: ...
+ @overload
+ def __new__(cls, dtype: _IntCCodes | type[ct.c_int], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[intc]: ...
+ @overload
+ def __new__(cls, dtype: _IntPCodes | type[ct.c_ssize_t], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[intp]: ...
+ @overload
+ def __new__(cls, dtype: _IntCodes | type[ct.c_long], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[int_]: ...
+ @overload
+ def __new__(cls, dtype: _LongLongCodes | type[ct.c_longlong], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[longlong]: ...
+
+ # `floating` string-based representations and ctypes
+ @overload
+ def __new__(cls, dtype: _Float16Codes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[float16]: ...
+ @overload
+ def __new__(cls, dtype: _Float32Codes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[float32]: ...
+ @overload
+ def __new__(cls, dtype: _Float64Codes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[float64]: ...
+ @overload
+ def __new__(cls, dtype: _HalfCodes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[half]: ...
+ @overload
+ def __new__(cls, dtype: _SingleCodes | type[ct.c_float], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[single]: ...
+ @overload
+ def __new__(cls, dtype: _DoubleCodes | type[ct.c_double], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[double]: ...
+ @overload
+ def __new__(cls, dtype: _LongDoubleCodes | type[ct.c_longdouble], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[longdouble]: ...
+
+ # `complexfloating` string-based representations
+ @overload
+ def __new__(cls, dtype: _Complex64Codes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[complex64]: ...
+ @overload
+ def __new__(cls, dtype: _Complex128Codes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[complex128]: ...
+ @overload
+ def __new__(cls, dtype: _CSingleCodes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[csingle]: ...
+ @overload
+ def __new__(cls, dtype: _CDoubleCodes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[cdouble]: ...
+ @overload
+ def __new__(cls, dtype: _CLongDoubleCodes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[clongdouble]: ...
+
+ # Miscellaneous string-based representations and ctypes
+ @overload
+ def __new__(cls, dtype: _BoolCodes | type[ct.c_bool], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[bool_]: ...
+ @overload
+ def __new__(cls, dtype: _TD64Codes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[timedelta64]: ...
+ @overload
+ def __new__(cls, dtype: _DT64Codes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[datetime64]: ...
+ @overload
+ def __new__(cls, dtype: _StrCodes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[str_]: ...
+ @overload
+ def __new__(cls, dtype: _BytesCodes | type[ct.c_char], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[bytes_]: ...
+ @overload
+ def __new__(cls, dtype: _VoidCodes, align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[void]: ...
+ @overload
+ def __new__(cls, dtype: _ObjectCodes | type[ct.py_object[Any]], align: bool = ..., copy: bool = ..., metadata: dict[builtins.str, Any] = ...) -> dtype[object_]: ...
+
+ # dtype of a dtype is the same dtype
+ @overload
+ def __new__(
+ cls,
+ dtype: dtype[_DTypeScalar_co],
+ align: bool = ...,
+ copy: bool = ...,
+ metadata: dict[builtins.str, Any] = ...,
+ ) -> dtype[_DTypeScalar_co]: ...
+ @overload
+ def __new__(
+ cls,
+ dtype: _SupportsDType[dtype[_DTypeScalar_co]],
+ align: bool = ...,
+ copy: bool = ...,
+ metadata: dict[builtins.str, Any] = ...,
+ ) -> dtype[_DTypeScalar_co]: ...
+ # Handle strings that can't be expressed as literals; i.e. s1, s2, ...
+ @overload
+ def __new__(
+ cls,
+ dtype: builtins.str,
+ align: bool = ...,
+ copy: bool = ...,
+ metadata: dict[builtins.str, Any] = ...,
+ ) -> dtype[Any]: ...
+ # Catchall overload for void-likes
+ @overload
+ def __new__(
+ cls,
+ dtype: _VoidDTypeLike,
+ align: bool = ...,
+ copy: bool = ...,
+ metadata: dict[builtins.str, Any] = ...,
+ ) -> dtype[void]: ...
+ # Catchall overload for object-likes
+ @overload
+ def __new__(
+ cls,
+ dtype: type[object],
+ align: bool = ...,
+ copy: bool = ...,
+ metadata: dict[builtins.str, Any] = ...,
+ ) -> dtype[object_]: ...
+
+ def __class_getitem__(self, item: Any) -> GenericAlias: ...
+
+ @overload
+ def __getitem__(self: dtype[void], key: list[builtins.str]) -> dtype[void]: ...
+ @overload
+ def __getitem__(self: dtype[void], key: builtins.str | SupportsIndex) -> dtype[Any]: ...
+
+ # NOTE: In the future 1-based multiplications will also yield `flexible` dtypes
+ @overload
+ def __mul__(self: _DType, value: L[1]) -> _DType: ...
+ @overload
+ def __mul__(self: _FlexDType, value: SupportsIndex) -> _FlexDType: ...
+ @overload
+ def __mul__(self, value: SupportsIndex) -> dtype[void]: ...
+
+ # NOTE: `__rmul__` seems to be broken when used in combination with
+ # literals as of mypy 0.902. Set the return-type to `dtype[Any]` for
+ # now for non-flexible dtypes.
+ @overload
+ def __rmul__(self: _FlexDType, value: SupportsIndex) -> _FlexDType: ...
+ @overload
+ def __rmul__(self, value: SupportsIndex) -> dtype[Any]: ...
+
+ def __gt__(self, other: DTypeLike) -> bool: ...
+ def __ge__(self, other: DTypeLike) -> bool: ...
+ def __lt__(self, other: DTypeLike) -> bool: ...
+ def __le__(self, other: DTypeLike) -> bool: ...
+
+ # Explicitly defined `__eq__` and `__ne__` to get around mypy's
+ # `strict_equality` option; even though their signatures are
+ # identical to their `object`-based counterpart
+ def __eq__(self, other: Any) -> bool: ...
+ def __ne__(self, other: Any) -> bool: ...
+
+ @property
+ def alignment(self) -> int: ...
+ @property
+ def base(self) -> dtype[Any]: ...
+ @property
+ def byteorder(self) -> builtins.str: ...
+ @property
+ def char(self) -> builtins.str: ...
+ @property
+ def descr(self) -> list[tuple[builtins.str, builtins.str] | tuple[builtins.str, builtins.str, _Shape]]: ...
+ @property
+ def fields(
+ self,
+ ) -> None | MappingProxyType[builtins.str, tuple[dtype[Any], int] | tuple[dtype[Any], int, Any]]: ...
+ @property
+ def flags(self) -> int: ...
+ @property
+ def hasobject(self) -> bool: ...
+ @property
+ def isbuiltin(self) -> int: ...
+ @property
+ def isnative(self) -> bool: ...
+ @property
+ def isalignedstruct(self) -> bool: ...
+ @property
+ def itemsize(self) -> int: ...
+ @property
+ def kind(self) -> builtins.str: ...
+ @property
+ def metadata(self) -> None | MappingProxyType[builtins.str, Any]: ...
+ @property
+ def name(self) -> builtins.str: ...
+ @property
+ def num(self) -> int: ...
+ @property
+ def shape(self) -> _Shape: ...
+ @property
+ def ndim(self) -> int: ...
+ @property
+ def subdtype(self) -> None | tuple[dtype[Any], _Shape]: ...
+ def newbyteorder(self: _DType, __new_order: _ByteOrder = ...) -> _DType: ...
+ @property
+ def str(self) -> builtins.str: ...
+ @property
+ def type(self) -> type[_DTypeScalar_co]: ...
+
+_ArrayLikeInt = Union[
+ int,
+ integer[Any],
+ Sequence[Union[int, integer[Any]]],
+ Sequence[Sequence[Any]], # TODO: wait for support for recursive types
+ ndarray[Any, Any]
+]
+
+_FlatIterSelf = TypeVar("_FlatIterSelf", bound=flatiter[Any])
+
+@final
+class flatiter(Generic[_NdArraySubClass]):
+ __hash__: ClassVar[None]
+ @property
+ def base(self) -> _NdArraySubClass: ...
+ @property
+ def coords(self) -> _Shape: ...
+ @property
+ def index(self) -> int: ...
+ def copy(self) -> _NdArraySubClass: ...
+ def __iter__(self: _FlatIterSelf) -> _FlatIterSelf: ...
+ def __next__(self: flatiter[ndarray[Any, dtype[_ScalarType]]]) -> _ScalarType: ...
+ def __len__(self) -> int: ...
+ @overload
+ def __getitem__(
+ self: flatiter[ndarray[Any, dtype[_ScalarType]]],
+ key: int | integer[Any] | tuple[int | integer[Any]],
+ ) -> _ScalarType: ...
+ @overload
+ def __getitem__(
+ self,
+ key: _ArrayLikeInt | slice | ellipsis | tuple[_ArrayLikeInt | slice | ellipsis],
+ ) -> _NdArraySubClass: ...
+ # TODO: `__setitem__` operates via `unsafe` casting rules, and can
+ # thus accept any type accepted by the relevant underlying `np.generic`
+ # constructor.
+ # This means that `value` must in reality be a supertype of `npt.ArrayLike`.
+ def __setitem__(
+ self,
+ key: _ArrayLikeInt | slice | ellipsis | tuple[_ArrayLikeInt | slice | ellipsis],
+ value: Any,
+ ) -> None: ...
+ @overload
+ def __array__(self: flatiter[ndarray[Any, _DType]], dtype: None = ..., /) -> ndarray[Any, _DType]: ...
+ @overload
+ def __array__(self, dtype: _DType, /) -> ndarray[Any, _DType]: ...
+
+_OrderKACF = L[None, "K", "A", "C", "F"]
+_OrderACF = L[None, "A", "C", "F"]
+_OrderCF = L[None, "C", "F"]
+
+_ModeKind = L["raise", "wrap", "clip"]
+_PartitionKind = L["introselect"]
+_SortKind = L["quicksort", "mergesort", "heapsort", "stable"]
+_SortSide = L["left", "right"]
+
+_ArraySelf = TypeVar("_ArraySelf", bound=_ArrayOrScalarCommon)
+
+class _ArrayOrScalarCommon:
+ @property
+ def T(self: _ArraySelf) -> _ArraySelf: ...
+ @property
+ def data(self) -> memoryview: ...
+ @property
+ def flags(self) -> flagsobj: ...
+ @property
+ def itemsize(self) -> int: ...
+ @property
+ def nbytes(self) -> int: ...
+ def __bool__(self) -> bool: ...
+ def __bytes__(self) -> bytes: ...
+ def __str__(self) -> str: ...
+ def __repr__(self) -> str: ...
+ def __copy__(self: _ArraySelf) -> _ArraySelf: ...
+ def __deepcopy__(self: _ArraySelf, memo: None | dict[int, Any], /) -> _ArraySelf: ...
+
+ # TODO: How to deal with the non-commutative nature of `==` and `!=`?
+ # xref numpy/numpy#17368
+ def __eq__(self, other: Any) -> Any: ...
+ def __ne__(self, other: Any) -> Any: ...
+ def copy(self: _ArraySelf, order: _OrderKACF = ...) -> _ArraySelf: ...
+ def dump(self, file: str | bytes | os.PathLike[str] | os.PathLike[bytes] | _SupportsWrite[bytes]) -> None: ...
+ def dumps(self) -> bytes: ...
+ def tobytes(self, order: _OrderKACF = ...) -> bytes: ...
+ # NOTE: `tostring()` is deprecated and therefore excluded
+ # def tostring(self, order=...): ...
+ def tofile(
+ self,
+ fid: str | bytes | os.PathLike[str] | os.PathLike[bytes] | _IOProtocol,
+ sep: str = ...,
+ format: str = ...,
+ ) -> None: ...
+ # generics and 0d arrays return builtin scalars
+ def tolist(self) -> Any: ...
+
+ @property
+ def __array_interface__(self) -> dict[str, Any]: ...
+ @property
+ def __array_priority__(self) -> float: ...
+ @property
+ def __array_struct__(self) -> Any: ... # builtins.PyCapsule
+ def __setstate__(self, state: tuple[
+ SupportsIndex, # version
+ _ShapeLike, # Shape
+ _DType_co, # DType
+ bool, # F-continuous
+ bytes | list[Any], # Data
+ ], /) -> None: ...
+ # a `bool_` is returned when `keepdims=True` and `self` is a 0d array
+
+ @overload
+ def all(
+ self,
+ axis: None = ...,
+ out: None = ...,
+ keepdims: L[False] = ...,
+ *,
+ where: _ArrayLikeBool_co = ...,
+ ) -> bool_: ...
+ @overload
+ def all(
+ self,
+ axis: None | _ShapeLike = ...,
+ out: None = ...,
+ keepdims: bool = ...,
+ *,
+ where: _ArrayLikeBool_co = ...,
+ ) -> Any: ...
+ @overload
+ def all(
+ self,
+ axis: None | _ShapeLike = ...,
+ out: _NdArraySubClass = ...,
+ keepdims: bool = ...,
+ *,
+ where: _ArrayLikeBool_co = ...,
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def any(
+ self,
+ axis: None = ...,
+ out: None = ...,
+ keepdims: L[False] = ...,
+ *,
+ where: _ArrayLikeBool_co = ...,
+ ) -> bool_: ...
+ @overload
+ def any(
+ self,
+ axis: None | _ShapeLike = ...,
+ out: None = ...,
+ keepdims: bool = ...,
+ *,
+ where: _ArrayLikeBool_co = ...,
+ ) -> Any: ...
+ @overload
+ def any(
+ self,
+ axis: None | _ShapeLike = ...,
+ out: _NdArraySubClass = ...,
+ keepdims: bool = ...,
+ *,
+ where: _ArrayLikeBool_co = ...,
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def argmax(
+ self,
+ axis: None = ...,
+ out: None = ...,
+ *,
+ keepdims: L[False] = ...,
+ ) -> intp: ...
+ @overload
+ def argmax(
+ self,
+ axis: SupportsIndex = ...,
+ out: None = ...,
+ *,
+ keepdims: bool = ...,
+ ) -> Any: ...
+ @overload
+ def argmax(
+ self,
+ axis: None | SupportsIndex = ...,
+ out: _NdArraySubClass = ...,
+ *,
+ keepdims: bool = ...,
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def argmin(
+ self,
+ axis: None = ...,
+ out: None = ...,
+ *,
+ keepdims: L[False] = ...,
+ ) -> intp: ...
+ @overload
+ def argmin(
+ self,
+ axis: SupportsIndex = ...,
+ out: None = ...,
+ *,
+ keepdims: bool = ...,
+ ) -> Any: ...
+ @overload
+ def argmin(
+ self,
+ axis: None | SupportsIndex = ...,
+ out: _NdArraySubClass = ...,
+ *,
+ keepdims: bool = ...,
+ ) -> _NdArraySubClass: ...
+
+ def argsort(
+ self,
+ axis: None | SupportsIndex = ...,
+ kind: None | _SortKind = ...,
+ order: None | str | Sequence[str] = ...,
+ ) -> ndarray[Any, Any]: ...
+
+ @overload
+ def choose(
+ self,
+ choices: ArrayLike,
+ out: None = ...,
+ mode: _ModeKind = ...,
+ ) -> ndarray[Any, Any]: ...
+ @overload
+ def choose(
+ self,
+ choices: ArrayLike,
+ out: _NdArraySubClass = ...,
+ mode: _ModeKind = ...,
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def clip(
+ self,
+ min: ArrayLike = ...,
+ max: None | ArrayLike = ...,
+ out: None = ...,
+ **kwargs: Any,
+ ) -> ndarray[Any, Any]: ...
+ @overload
+ def clip(
+ self,
+ min: None = ...,
+ max: ArrayLike = ...,
+ out: None = ...,
+ **kwargs: Any,
+ ) -> ndarray[Any, Any]: ...
+ @overload
+ def clip(
+ self,
+ min: ArrayLike = ...,
+ max: None | ArrayLike = ...,
+ out: _NdArraySubClass = ...,
+ **kwargs: Any,
+ ) -> _NdArraySubClass: ...
+ @overload
+ def clip(
+ self,
+ min: None = ...,
+ max: ArrayLike = ...,
+ out: _NdArraySubClass = ...,
+ **kwargs: Any,
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def compress(
+ self,
+ a: ArrayLike,
+ axis: None | SupportsIndex = ...,
+ out: None = ...,
+ ) -> ndarray[Any, Any]: ...
+ @overload
+ def compress(
+ self,
+ a: ArrayLike,
+ axis: None | SupportsIndex = ...,
+ out: _NdArraySubClass = ...,
+ ) -> _NdArraySubClass: ...
+
+ def conj(self: _ArraySelf) -> _ArraySelf: ...
+
+ def conjugate(self: _ArraySelf) -> _ArraySelf: ...
+
+ @overload
+ def cumprod(
+ self,
+ axis: None | SupportsIndex = ...,
+ dtype: DTypeLike = ...,
+ out: None = ...,
+ ) -> ndarray[Any, Any]: ...
+ @overload
+ def cumprod(
+ self,
+ axis: None | SupportsIndex = ...,
+ dtype: DTypeLike = ...,
+ out: _NdArraySubClass = ...,
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def cumsum(
+ self,
+ axis: None | SupportsIndex = ...,
+ dtype: DTypeLike = ...,
+ out: None = ...,
+ ) -> ndarray[Any, Any]: ...
+ @overload
+ def cumsum(
+ self,
+ axis: None | SupportsIndex = ...,
+ dtype: DTypeLike = ...,
+ out: _NdArraySubClass = ...,
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def max(
+ self,
+ axis: None | _ShapeLike = ...,
+ out: None = ...,
+ keepdims: bool = ...,
+ initial: _NumberLike_co = ...,
+ where: _ArrayLikeBool_co = ...,
+ ) -> Any: ...
+ @overload
+ def max(
+ self,
+ axis: None | _ShapeLike = ...,
+ out: _NdArraySubClass = ...,
+ keepdims: bool = ...,
+ initial: _NumberLike_co = ...,
+ where: _ArrayLikeBool_co = ...,
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def mean(
+ self,
+ axis: None | _ShapeLike = ...,
+ dtype: DTypeLike = ...,
+ out: None = ...,
+ keepdims: bool = ...,
+ *,
+ where: _ArrayLikeBool_co = ...,
+ ) -> Any: ...
+ @overload
+ def mean(
+ self,
+ axis: None | _ShapeLike = ...,
+ dtype: DTypeLike = ...,
+ out: _NdArraySubClass = ...,
+ keepdims: bool = ...,
+ *,
+ where: _ArrayLikeBool_co = ...,
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def min(
+ self,
+ axis: None | _ShapeLike = ...,
+ out: None = ...,
+ keepdims: bool = ...,
+ initial: _NumberLike_co = ...,
+ where: _ArrayLikeBool_co = ...,
+ ) -> Any: ...
+ @overload
+ def min(
+ self,
+ axis: None | _ShapeLike = ...,
+ out: _NdArraySubClass = ...,
+ keepdims: bool = ...,
+ initial: _NumberLike_co = ...,
+ where: _ArrayLikeBool_co = ...,
+ ) -> _NdArraySubClass: ...
+
+ def newbyteorder(
+ self: _ArraySelf,
+ __new_order: _ByteOrder = ...,
+ ) -> _ArraySelf: ...
+
+ @overload
+ def prod(
+ self,
+ axis: None | _ShapeLike = ...,
+ dtype: DTypeLike = ...,
+ out: None = ...,
+ keepdims: bool = ...,
+ initial: _NumberLike_co = ...,
+ where: _ArrayLikeBool_co = ...,
+ ) -> Any: ...
+ @overload
+ def prod(
+ self,
+ axis: None | _ShapeLike = ...,
+ dtype: DTypeLike = ...,
+ out: _NdArraySubClass = ...,
+ keepdims: bool = ...,
+ initial: _NumberLike_co = ...,
+ where: _ArrayLikeBool_co = ...,
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def ptp(
+ self,
+ axis: None | _ShapeLike = ...,
+ out: None = ...,
+ keepdims: bool = ...,
+ ) -> Any: ...
+ @overload
+ def ptp(
+ self,
+ axis: None | _ShapeLike = ...,
+ out: _NdArraySubClass = ...,
+ keepdims: bool = ...,
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def round(
+ self: _ArraySelf,
+ decimals: SupportsIndex = ...,
+ out: None = ...,
+ ) -> _ArraySelf: ...
+ @overload
+ def round(
+ self,
+ decimals: SupportsIndex = ...,
+ out: _NdArraySubClass = ...,
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def std(
+ self,
+ axis: None | _ShapeLike = ...,
+ dtype: DTypeLike = ...,
+ out: None = ...,
+ ddof: float = ...,
+ keepdims: bool = ...,
+ *,
+ where: _ArrayLikeBool_co = ...,
+ ) -> Any: ...
+ @overload
+ def std(
+ self,
+ axis: None | _ShapeLike = ...,
+ dtype: DTypeLike = ...,
+ out: _NdArraySubClass = ...,
+ ddof: float = ...,
+ keepdims: bool = ...,
+ *,
+ where: _ArrayLikeBool_co = ...,
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def sum(
+ self,
+ axis: None | _ShapeLike = ...,
+ dtype: DTypeLike = ...,
+ out: None = ...,
+ keepdims: bool = ...,
+ initial: _NumberLike_co = ...,
+ where: _ArrayLikeBool_co = ...,
+ ) -> Any: ...
+ @overload
+ def sum(
+ self,
+ axis: None | _ShapeLike = ...,
+ dtype: DTypeLike = ...,
+ out: _NdArraySubClass = ...,
+ keepdims: bool = ...,
+ initial: _NumberLike_co = ...,
+ where: _ArrayLikeBool_co = ...,
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def var(
+ self,
+ axis: None | _ShapeLike = ...,
+ dtype: DTypeLike = ...,
+ out: None = ...,
+ ddof: float = ...,
+ keepdims: bool = ...,
+ *,
+ where: _ArrayLikeBool_co = ...,
+ ) -> Any: ...
+ @overload
+ def var(
+ self,
+ axis: None | _ShapeLike = ...,
+ dtype: DTypeLike = ...,
+ out: _NdArraySubClass = ...,
+ ddof: float = ...,
+ keepdims: bool = ...,
+ *,
+ where: _ArrayLikeBool_co = ...,
+ ) -> _NdArraySubClass: ...
+
+_DType = TypeVar("_DType", bound=dtype[Any])
+_DType_co = TypeVar("_DType_co", covariant=True, bound=dtype[Any])
+_FlexDType = TypeVar("_FlexDType", bound=dtype[flexible])
+
+# TODO: Set the `bound` to something more suitable once we
+# have proper shape support
+_ShapeType = TypeVar("_ShapeType", bound=Any)
+_ShapeType2 = TypeVar("_ShapeType2", bound=Any)
+_NumberType = TypeVar("_NumberType", bound=number[Any])
+
+if sys.version_info >= (3, 12):
+ from collections.abc import Buffer as _SupportsBuffer
+else:
+ _SupportsBuffer = (
+ bytes
+ | bytearray
+ | memoryview
+ | _array.array[Any]
+ | mmap.mmap
+ | NDArray[Any]
+ | generic
+ )
+
+_T = TypeVar("_T")
+_T_co = TypeVar("_T_co", covariant=True)
+_T_contra = TypeVar("_T_contra", contravariant=True)
+_2Tuple = tuple[_T, _T]
+_CastingKind = L["no", "equiv", "safe", "same_kind", "unsafe"]
+
+_ArrayUInt_co = NDArray[Union[bool_, unsignedinteger[Any]]]
+_ArrayInt_co = NDArray[Union[bool_, integer[Any]]]
+_ArrayFloat_co = NDArray[Union[bool_, integer[Any], floating[Any]]]
+_ArrayComplex_co = NDArray[Union[bool_, integer[Any], floating[Any], complexfloating[Any, Any]]]
+_ArrayNumber_co = NDArray[Union[bool_, number[Any]]]
+_ArrayTD64_co = NDArray[Union[bool_, integer[Any], timedelta64]]
+
+# Introduce an alias for `dtype` to avoid naming conflicts.
+_dtype = dtype
+
+# `builtins.PyCapsule` unfortunately lacks annotations as of the moment;
+# use `Any` as a stopgap measure
+_PyCapsule = Any
+
+class _SupportsItem(Protocol[_T_co]):
+ def item(self, args: Any, /) -> _T_co: ...
+
+class _SupportsReal(Protocol[_T_co]):
+ @property
+ def real(self) -> _T_co: ...
+
+class _SupportsImag(Protocol[_T_co]):
+ @property
+ def imag(self) -> _T_co: ...
+
+class ndarray(_ArrayOrScalarCommon, Generic[_ShapeType, _DType_co]):
+ __hash__: ClassVar[None]
+ @property
+ def base(self) -> None | ndarray[Any, Any]: ...
+ @property
+ def ndim(self) -> int: ...
+ @property
+ def size(self) -> int: ...
+ @property
+ def real(
+ self: ndarray[_ShapeType, dtype[_SupportsReal[_ScalarType]]], # type: ignore[type-var]
+ ) -> ndarray[_ShapeType, _dtype[_ScalarType]]: ...
+ @real.setter
+ def real(self, value: ArrayLike) -> None: ...
+ @property
+ def imag(
+ self: ndarray[_ShapeType, dtype[_SupportsImag[_ScalarType]]], # type: ignore[type-var]
+ ) -> ndarray[_ShapeType, _dtype[_ScalarType]]: ...
+ @imag.setter
+ def imag(self, value: ArrayLike) -> None: ...
+ def __new__(
+ cls: type[_ArraySelf],
+ shape: _ShapeLike,
+ dtype: DTypeLike = ...,
+ buffer: None | _SupportsBuffer = ...,
+ offset: SupportsIndex = ...,
+ strides: None | _ShapeLike = ...,
+ order: _OrderKACF = ...,
+ ) -> _ArraySelf: ...
+
+ if sys.version_info >= (3, 12):
+ def __buffer__(self, flags: int, /) -> memoryview: ...
+
+ def __class_getitem__(self, item: Any) -> GenericAlias: ...
+
+ @overload
+ def __array__(self, dtype: None = ..., /) -> ndarray[Any, _DType_co]: ...
+ @overload
+ def __array__(self, dtype: _DType, /) -> ndarray[Any, _DType]: ...
+
+ def __array_ufunc__(
+ self,
+ ufunc: ufunc,
+ method: L["__call__", "reduce", "reduceat", "accumulate", "outer", "inner"],
+ *inputs: Any,
+ **kwargs: Any,
+ ) -> Any: ...
+
+ def __array_function__(
+ self,
+ func: Callable[..., Any],
+ types: Iterable[type],
+ args: Iterable[Any],
+ kwargs: Mapping[str, Any],
+ ) -> Any: ...
+
+ # NOTE: In practice any object is accepted by `obj`, but as `__array_finalize__`
+ # is a pseudo-abstract method the type has been narrowed down in order to
+ # grant subclasses a bit more flexibility
+ def __array_finalize__(self, obj: None | NDArray[Any], /) -> None: ...
+
+ def __array_wrap__(
+ self,
+ array: ndarray[_ShapeType2, _DType],
+ context: None | tuple[ufunc, tuple[Any, ...], int] = ...,
+ /,
+ ) -> ndarray[_ShapeType2, _DType]: ...
+
+ def __array_prepare__(
+ self,
+ array: ndarray[_ShapeType2, _DType],
+ context: None | tuple[ufunc, tuple[Any, ...], int] = ...,
+ /,
+ ) -> ndarray[_ShapeType2, _DType]: ...
+
+ @overload
+ def __getitem__(self, key: (
+ NDArray[integer[Any]]
+ | NDArray[bool_]
+ | tuple[NDArray[integer[Any]] | NDArray[bool_], ...]
+ )) -> ndarray[Any, _DType_co]: ...
+ @overload
+ def __getitem__(self, key: SupportsIndex | tuple[SupportsIndex, ...]) -> Any: ...
+ @overload
+ def __getitem__(self, key: (
+ None
+ | slice
+ | ellipsis
+ | SupportsIndex
+ | _ArrayLikeInt_co
+ | tuple[None | slice | ellipsis | _ArrayLikeInt_co | SupportsIndex, ...]
+ )) -> ndarray[Any, _DType_co]: ...
+ @overload
+ def __getitem__(self: NDArray[void], key: str) -> NDArray[Any]: ...
+ @overload
+ def __getitem__(self: NDArray[void], key: list[str]) -> ndarray[_ShapeType, _dtype[void]]: ...
+
+ @property
+ def ctypes(self) -> _ctypes[int]: ...
+ @property
+ def shape(self) -> _Shape: ...
+ @shape.setter
+ def shape(self, value: _ShapeLike) -> None: ...
+ @property
+ def strides(self) -> _Shape: ...
+ @strides.setter
+ def strides(self, value: _ShapeLike) -> None: ...
+ def byteswap(self: _ArraySelf, inplace: bool = ...) -> _ArraySelf: ...
+ def fill(self, value: Any) -> None: ...
+ @property
+ def flat(self: _NdArraySubClass) -> flatiter[_NdArraySubClass]: ...
+
+ # Use the same output type as that of the underlying `generic`
+ @overload
+ def item(
+ self: ndarray[Any, _dtype[_SupportsItem[_T]]], # type: ignore[type-var]
+ *args: SupportsIndex,
+ ) -> _T: ...
+ @overload
+ def item(
+ self: ndarray[Any, _dtype[_SupportsItem[_T]]], # type: ignore[type-var]
+ args: tuple[SupportsIndex, ...],
+ /,
+ ) -> _T: ...
+
+ @overload
+ def itemset(self, value: Any, /) -> None: ...
+ @overload
+ def itemset(self, item: _ShapeLike, value: Any, /) -> None: ...
+
+ @overload
+ def resize(self, new_shape: _ShapeLike, /, *, refcheck: bool = ...) -> None: ...
+ @overload
+ def resize(self, *new_shape: SupportsIndex, refcheck: bool = ...) -> None: ...
+
+ def setflags(
+ self, write: bool = ..., align: bool = ..., uic: bool = ...
+ ) -> None: ...
+
+ def squeeze(
+ self,
+ axis: None | SupportsIndex | tuple[SupportsIndex, ...] = ...,
+ ) -> ndarray[Any, _DType_co]: ...
+
+ def swapaxes(
+ self,
+ axis1: SupportsIndex,
+ axis2: SupportsIndex,
+ ) -> ndarray[Any, _DType_co]: ...
+
+ @overload
+ def transpose(self: _ArraySelf, axes: None | _ShapeLike, /) -> _ArraySelf: ...
+ @overload
+ def transpose(self: _ArraySelf, *axes: SupportsIndex) -> _ArraySelf: ...
+
+ def argpartition(
+ self,
+ kth: _ArrayLikeInt_co,
+ axis: None | SupportsIndex = ...,
+ kind: _PartitionKind = ...,
+ order: None | str | Sequence[str] = ...,
+ ) -> ndarray[Any, _dtype[intp]]: ...
+
+ def diagonal(
+ self,
+ offset: SupportsIndex = ...,
+ axis1: SupportsIndex = ...,
+ axis2: SupportsIndex = ...,
+ ) -> ndarray[Any, _DType_co]: ...
+
+ # 1D + 1D returns a scalar;
+ # all other with at least 1 non-0D array return an ndarray.
+ @overload
+ def dot(self, b: _ScalarLike_co, out: None = ...) -> ndarray[Any, Any]: ...
+ @overload
+ def dot(self, b: ArrayLike, out: None = ...) -> Any: ... # type: ignore[misc]
+ @overload
+ def dot(self, b: ArrayLike, out: _NdArraySubClass) -> _NdArraySubClass: ...
+
+ # `nonzero()` is deprecated for 0d arrays/generics
+ def nonzero(self) -> tuple[ndarray[Any, _dtype[intp]], ...]: ...
+
+ def partition(
+ self,
+ kth: _ArrayLikeInt_co,
+ axis: SupportsIndex = ...,
+ kind: _PartitionKind = ...,
+ order: None | str | Sequence[str] = ...,
+ ) -> None: ...
+
+ # `put` is technically available to `generic`,
+ # but is pointless as `generic`s are immutable
+ def put(
+ self,
+ ind: _ArrayLikeInt_co,
+ v: ArrayLike,
+ mode: _ModeKind = ...,
+ ) -> None: ...
+
+ @overload
+ def searchsorted( # type: ignore[misc]
+ self, # >= 1D array
+ v: _ScalarLike_co, # 0D array-like
+ side: _SortSide = ...,
+ sorter: None | _ArrayLikeInt_co = ...,
+ ) -> intp: ...
+ @overload
+ def searchsorted(
+ self, # >= 1D array
+ v: ArrayLike,
+ side: _SortSide = ...,
+ sorter: None | _ArrayLikeInt_co = ...,
+ ) -> ndarray[Any, _dtype[intp]]: ...
+
+ def setfield(
+ self,
+ val: ArrayLike,
+ dtype: DTypeLike,
+ offset: SupportsIndex = ...,
+ ) -> None: ...
+
+ def sort(
+ self,
+ axis: SupportsIndex = ...,
+ kind: None | _SortKind = ...,
+ order: None | str | Sequence[str] = ...,
+ ) -> None: ...
+
+ @overload
+ def trace(
+ self, # >= 2D array
+ offset: SupportsIndex = ...,
+ axis1: SupportsIndex = ...,
+ axis2: SupportsIndex = ...,
+ dtype: DTypeLike = ...,
+ out: None = ...,
+ ) -> Any: ...
+ @overload
+ def trace(
+ self, # >= 2D array
+ offset: SupportsIndex = ...,
+ axis1: SupportsIndex = ...,
+ axis2: SupportsIndex = ...,
+ dtype: DTypeLike = ...,
+ out: _NdArraySubClass = ...,
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def take( # type: ignore[misc]
+ self: ndarray[Any, _dtype[_ScalarType]],
+ indices: _IntLike_co,
+ axis: None | SupportsIndex = ...,
+ out: None = ...,
+ mode: _ModeKind = ...,
+ ) -> _ScalarType: ...
+ @overload
+ def take( # type: ignore[misc]
+ self,
+ indices: _ArrayLikeInt_co,
+ axis: None | SupportsIndex = ...,
+ out: None = ...,
+ mode: _ModeKind = ...,
+ ) -> ndarray[Any, _DType_co]: ...
+ @overload
+ def take(
+ self,
+ indices: _ArrayLikeInt_co,
+ axis: None | SupportsIndex = ...,
+ out: _NdArraySubClass = ...,
+ mode: _ModeKind = ...,
+ ) -> _NdArraySubClass: ...
+
+ def repeat(
+ self,
+ repeats: _ArrayLikeInt_co,
+ axis: None | SupportsIndex = ...,
+ ) -> ndarray[Any, _DType_co]: ...
+
+ def flatten(
+ self,
+ order: _OrderKACF = ...,
+ ) -> ndarray[Any, _DType_co]: ...
+
+ def ravel(
+ self,
+ order: _OrderKACF = ...,
+ ) -> ndarray[Any, _DType_co]: ...
+
+ @overload
+ def reshape(
+ self, shape: _ShapeLike, /, *, order: _OrderACF = ...
+ ) -> ndarray[Any, _DType_co]: ...
+ @overload
+ def reshape(
+ self, *shape: SupportsIndex, order: _OrderACF = ...
+ ) -> ndarray[Any, _DType_co]: ...
+
+ @overload
+ def astype(
+ self,
+ dtype: _DTypeLike[_ScalarType],
+ order: _OrderKACF = ...,
+ casting: _CastingKind = ...,
+ subok: bool = ...,
+ copy: bool | _CopyMode = ...,
+ ) -> NDArray[_ScalarType]: ...
+ @overload
+ def astype(
+ self,
+ dtype: DTypeLike,
+ order: _OrderKACF = ...,
+ casting: _CastingKind = ...,
+ subok: bool = ...,
+ copy: bool | _CopyMode = ...,
+ ) -> NDArray[Any]: ...
+
+ @overload
+ def view(self: _ArraySelf) -> _ArraySelf: ...
+ @overload
+ def view(self, type: type[_NdArraySubClass]) -> _NdArraySubClass: ...
+ @overload
+ def view(self, dtype: _DTypeLike[_ScalarType]) -> NDArray[_ScalarType]: ...
+ @overload
+ def view(self, dtype: DTypeLike) -> NDArray[Any]: ...
+ @overload
+ def view(
+ self,
+ dtype: DTypeLike,
+ type: type[_NdArraySubClass],
+ ) -> _NdArraySubClass: ...
+
+ @overload
+ def getfield(
+ self,
+ dtype: _DTypeLike[_ScalarType],
+ offset: SupportsIndex = ...
+ ) -> NDArray[_ScalarType]: ...
+ @overload
+ def getfield(
+ self,
+ dtype: DTypeLike,
+ offset: SupportsIndex = ...
+ ) -> NDArray[Any]: ...
+
+ # Dispatch to the underlying `generic` via protocols
+ def __int__(
+ self: ndarray[Any, _dtype[SupportsInt]], # type: ignore[type-var]
+ ) -> int: ...
+
+ def __float__(
+ self: ndarray[Any, _dtype[SupportsFloat]], # type: ignore[type-var]
+ ) -> float: ...
+
+ def __complex__(
+ self: ndarray[Any, _dtype[SupportsComplex]], # type: ignore[type-var]
+ ) -> complex: ...
+
+ def __index__(
+ self: ndarray[Any, _dtype[SupportsIndex]], # type: ignore[type-var]
+ ) -> int: ...
+
+ def __len__(self) -> int: ...
+ def __setitem__(self, key, value): ...
+ def __iter__(self) -> Any: ...
+ def __contains__(self, key) -> bool: ...
+
+ # The last overload is for catching recursive objects whose
+ # nesting is too deep.
+ # The first overload is for catching `bytes` (as they are a subtype of
+ # `Sequence[int]`) and `str`. As `str` is a recursive sequence of
+ # strings, it will pass through the final overload otherwise
+
+ @overload
+ def __lt__(self: _ArrayNumber_co, other: _ArrayLikeNumber_co) -> NDArray[bool_]: ...
+ @overload
+ def __lt__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> NDArray[bool_]: ...
+ @overload
+ def __lt__(self: NDArray[datetime64], other: _ArrayLikeDT64_co) -> NDArray[bool_]: ...
+ @overload
+ def __lt__(self: NDArray[object_], other: Any) -> NDArray[bool_]: ...
+ @overload
+ def __lt__(self: NDArray[Any], other: _ArrayLikeObject_co) -> NDArray[bool_]: ...
+
+ @overload
+ def __le__(self: _ArrayNumber_co, other: _ArrayLikeNumber_co) -> NDArray[bool_]: ...
+ @overload
+ def __le__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> NDArray[bool_]: ...
+ @overload
+ def __le__(self: NDArray[datetime64], other: _ArrayLikeDT64_co) -> NDArray[bool_]: ...
+ @overload
+ def __le__(self: NDArray[object_], other: Any) -> NDArray[bool_]: ...
+ @overload
+ def __le__(self: NDArray[Any], other: _ArrayLikeObject_co) -> NDArray[bool_]: ...
+
+ @overload
+ def __gt__(self: _ArrayNumber_co, other: _ArrayLikeNumber_co) -> NDArray[bool_]: ...
+ @overload
+ def __gt__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> NDArray[bool_]: ...
+ @overload
+ def __gt__(self: NDArray[datetime64], other: _ArrayLikeDT64_co) -> NDArray[bool_]: ...
+ @overload
+ def __gt__(self: NDArray[object_], other: Any) -> NDArray[bool_]: ...
+ @overload
+ def __gt__(self: NDArray[Any], other: _ArrayLikeObject_co) -> NDArray[bool_]: ...
+
+ @overload
+ def __ge__(self: _ArrayNumber_co, other: _ArrayLikeNumber_co) -> NDArray[bool_]: ...
+ @overload
+ def __ge__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> NDArray[bool_]: ...
+ @overload
+ def __ge__(self: NDArray[datetime64], other: _ArrayLikeDT64_co) -> NDArray[bool_]: ...
+ @overload
+ def __ge__(self: NDArray[object_], other: Any) -> NDArray[bool_]: ...
+ @overload
+ def __ge__(self: NDArray[Any], other: _ArrayLikeObject_co) -> NDArray[bool_]: ...
+
+ # Unary ops
+ @overload
+ def __abs__(self: NDArray[bool_]) -> NDArray[bool_]: ...
+ @overload
+ def __abs__(self: NDArray[complexfloating[_NBit1, _NBit1]]) -> NDArray[floating[_NBit1]]: ...
+ @overload
+ def __abs__(self: NDArray[_NumberType]) -> NDArray[_NumberType]: ...
+ @overload
+ def __abs__(self: NDArray[timedelta64]) -> NDArray[timedelta64]: ...
+ @overload
+ def __abs__(self: NDArray[object_]) -> Any: ...
+
+ @overload
+ def __invert__(self: NDArray[bool_]) -> NDArray[bool_]: ...
+ @overload
+ def __invert__(self: NDArray[_IntType]) -> NDArray[_IntType]: ...
+ @overload
+ def __invert__(self: NDArray[object_]) -> Any: ...
+
+ @overload
+ def __pos__(self: NDArray[_NumberType]) -> NDArray[_NumberType]: ...
+ @overload
+ def __pos__(self: NDArray[timedelta64]) -> NDArray[timedelta64]: ...
+ @overload
+ def __pos__(self: NDArray[object_]) -> Any: ...
+
+ @overload
+ def __neg__(self: NDArray[_NumberType]) -> NDArray[_NumberType]: ...
+ @overload
+ def __neg__(self: NDArray[timedelta64]) -> NDArray[timedelta64]: ...
+ @overload
+ def __neg__(self: NDArray[object_]) -> Any: ...
+
+ # Binary ops
+ @overload
+ def __matmul__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ... # type: ignore[misc]
+ @overload
+ def __matmul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __matmul__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __matmul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __matmul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...
+ @overload
+ def __matmul__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co) -> NDArray[number[Any]]: ...
+ @overload
+ def __matmul__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __matmul__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __rmatmul__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ... # type: ignore[misc]
+ @overload
+ def __rmatmul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rmatmul__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rmatmul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rmatmul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...
+ @overload
+ def __rmatmul__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co) -> NDArray[number[Any]]: ...
+ @overload
+ def __rmatmul__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __rmatmul__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __mod__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[int8]: ... # type: ignore[misc]
+ @overload
+ def __mod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __mod__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __mod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __mod__(self: _ArrayTD64_co, other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]]) -> NDArray[timedelta64]: ...
+ @overload
+ def __mod__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __mod__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __rmod__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[int8]: ... # type: ignore[misc]
+ @overload
+ def __rmod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rmod__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rmod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rmod__(self: _ArrayTD64_co, other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]]) -> NDArray[timedelta64]: ...
+ @overload
+ def __rmod__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __rmod__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __divmod__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> _2Tuple[NDArray[int8]]: ... # type: ignore[misc]
+ @overload
+ def __divmod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> _2Tuple[NDArray[unsignedinteger[Any]]]: ... # type: ignore[misc]
+ @overload
+ def __divmod__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> _2Tuple[NDArray[signedinteger[Any]]]: ... # type: ignore[misc]
+ @overload
+ def __divmod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _2Tuple[NDArray[floating[Any]]]: ... # type: ignore[misc]
+ @overload
+ def __divmod__(self: _ArrayTD64_co, other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]]) -> tuple[NDArray[int64], NDArray[timedelta64]]: ...
+
+ @overload
+ def __rdivmod__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> _2Tuple[NDArray[int8]]: ... # type: ignore[misc]
+ @overload
+ def __rdivmod__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> _2Tuple[NDArray[unsignedinteger[Any]]]: ... # type: ignore[misc]
+ @overload
+ def __rdivmod__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> _2Tuple[NDArray[signedinteger[Any]]]: ... # type: ignore[misc]
+ @overload
+ def __rdivmod__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> _2Tuple[NDArray[floating[Any]]]: ... # type: ignore[misc]
+ @overload
+ def __rdivmod__(self: _ArrayTD64_co, other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]]) -> tuple[NDArray[int64], NDArray[timedelta64]]: ...
+
+ @overload
+ def __add__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ... # type: ignore[misc]
+ @overload
+ def __add__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __add__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __add__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __add__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc]
+ @overload
+ def __add__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co) -> NDArray[number[Any]]: ...
+ @overload
+ def __add__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> NDArray[timedelta64]: ... # type: ignore[misc]
+ @overload
+ def __add__(self: _ArrayTD64_co, other: _ArrayLikeDT64_co) -> NDArray[datetime64]: ...
+ @overload
+ def __add__(self: NDArray[datetime64], other: _ArrayLikeTD64_co) -> NDArray[datetime64]: ...
+ @overload
+ def __add__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __add__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __radd__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ... # type: ignore[misc]
+ @overload
+ def __radd__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __radd__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __radd__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __radd__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc]
+ @overload
+ def __radd__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co) -> NDArray[number[Any]]: ...
+ @overload
+ def __radd__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> NDArray[timedelta64]: ... # type: ignore[misc]
+ @overload
+ def __radd__(self: _ArrayTD64_co, other: _ArrayLikeDT64_co) -> NDArray[datetime64]: ...
+ @overload
+ def __radd__(self: NDArray[datetime64], other: _ArrayLikeTD64_co) -> NDArray[datetime64]: ...
+ @overload
+ def __radd__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __radd__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __sub__(self: NDArray[_UnknownType], other: _ArrayLikeUnknown) -> NDArray[Any]: ...
+ @overload
+ def __sub__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NoReturn: ...
+ @overload
+ def __sub__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __sub__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __sub__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __sub__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc]
+ @overload
+ def __sub__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co) -> NDArray[number[Any]]: ...
+ @overload
+ def __sub__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> NDArray[timedelta64]: ... # type: ignore[misc]
+ @overload
+ def __sub__(self: NDArray[datetime64], other: _ArrayLikeTD64_co) -> NDArray[datetime64]: ...
+ @overload
+ def __sub__(self: NDArray[datetime64], other: _ArrayLikeDT64_co) -> NDArray[timedelta64]: ...
+ @overload
+ def __sub__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __sub__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __rsub__(self: NDArray[_UnknownType], other: _ArrayLikeUnknown) -> NDArray[Any]: ...
+ @overload
+ def __rsub__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NoReturn: ...
+ @overload
+ def __rsub__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rsub__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rsub__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rsub__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc]
+ @overload
+ def __rsub__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co) -> NDArray[number[Any]]: ...
+ @overload
+ def __rsub__(self: _ArrayTD64_co, other: _ArrayLikeTD64_co) -> NDArray[timedelta64]: ... # type: ignore[misc]
+ @overload
+ def __rsub__(self: _ArrayTD64_co, other: _ArrayLikeDT64_co) -> NDArray[datetime64]: ... # type: ignore[misc]
+ @overload
+ def __rsub__(self: NDArray[datetime64], other: _ArrayLikeDT64_co) -> NDArray[timedelta64]: ...
+ @overload
+ def __rsub__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __rsub__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __mul__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ... # type: ignore[misc]
+ @overload
+ def __mul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __mul__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __mul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __mul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc]
+ @overload
+ def __mul__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co) -> NDArray[number[Any]]: ...
+ @overload
+ def __mul__(self: _ArrayTD64_co, other: _ArrayLikeFloat_co) -> NDArray[timedelta64]: ...
+ @overload
+ def __mul__(self: _ArrayFloat_co, other: _ArrayLikeTD64_co) -> NDArray[timedelta64]: ...
+ @overload
+ def __mul__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __mul__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __rmul__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ... # type: ignore[misc]
+ @overload
+ def __rmul__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rmul__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rmul__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rmul__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc]
+ @overload
+ def __rmul__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co) -> NDArray[number[Any]]: ...
+ @overload
+ def __rmul__(self: _ArrayTD64_co, other: _ArrayLikeFloat_co) -> NDArray[timedelta64]: ...
+ @overload
+ def __rmul__(self: _ArrayFloat_co, other: _ArrayLikeTD64_co) -> NDArray[timedelta64]: ...
+ @overload
+ def __rmul__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __rmul__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __floordiv__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[int8]: ... # type: ignore[misc]
+ @overload
+ def __floordiv__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __floordiv__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __floordiv__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __floordiv__(self: NDArray[timedelta64], other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]]) -> NDArray[int64]: ...
+ @overload
+ def __floordiv__(self: NDArray[timedelta64], other: _ArrayLikeBool_co) -> NoReturn: ...
+ @overload
+ def __floordiv__(self: NDArray[timedelta64], other: _ArrayLikeFloat_co) -> NDArray[timedelta64]: ...
+ @overload
+ def __floordiv__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __floordiv__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __rfloordiv__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[int8]: ... # type: ignore[misc]
+ @overload
+ def __rfloordiv__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rfloordiv__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rfloordiv__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rfloordiv__(self: NDArray[timedelta64], other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]]) -> NDArray[int64]: ...
+ @overload
+ def __rfloordiv__(self: NDArray[bool_], other: _ArrayLikeTD64_co) -> NoReturn: ...
+ @overload
+ def __rfloordiv__(self: _ArrayFloat_co, other: _ArrayLikeTD64_co) -> NDArray[timedelta64]: ...
+ @overload
+ def __rfloordiv__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __rfloordiv__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __pow__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[int8]: ... # type: ignore[misc]
+ @overload
+ def __pow__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __pow__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __pow__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __pow__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...
+ @overload
+ def __pow__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co) -> NDArray[number[Any]]: ...
+ @overload
+ def __pow__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __pow__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __rpow__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[int8]: ... # type: ignore[misc]
+ @overload
+ def __rpow__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rpow__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rpow__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rpow__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ...
+ @overload
+ def __rpow__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co) -> NDArray[number[Any]]: ...
+ @overload
+ def __rpow__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __rpow__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __truediv__(self: _ArrayInt_co, other: _ArrayInt_co) -> NDArray[float64]: ... # type: ignore[misc]
+ @overload
+ def __truediv__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __truediv__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc]
+ @overload
+ def __truediv__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co) -> NDArray[number[Any]]: ...
+ @overload
+ def __truediv__(self: NDArray[timedelta64], other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]]) -> NDArray[float64]: ...
+ @overload
+ def __truediv__(self: NDArray[timedelta64], other: _ArrayLikeBool_co) -> NoReturn: ...
+ @overload
+ def __truediv__(self: NDArray[timedelta64], other: _ArrayLikeFloat_co) -> NDArray[timedelta64]: ...
+ @overload
+ def __truediv__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __truediv__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __rtruediv__(self: _ArrayInt_co, other: _ArrayInt_co) -> NDArray[float64]: ... # type: ignore[misc]
+ @overload
+ def __rtruediv__(self: _ArrayFloat_co, other: _ArrayLikeFloat_co) -> NDArray[floating[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rtruediv__(self: _ArrayComplex_co, other: _ArrayLikeComplex_co) -> NDArray[complexfloating[Any, Any]]: ... # type: ignore[misc]
+ @overload
+ def __rtruediv__(self: NDArray[number[Any]], other: _ArrayLikeNumber_co) -> NDArray[number[Any]]: ...
+ @overload
+ def __rtruediv__(self: NDArray[timedelta64], other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]]) -> NDArray[float64]: ...
+ @overload
+ def __rtruediv__(self: NDArray[bool_], other: _ArrayLikeTD64_co) -> NoReturn: ...
+ @overload
+ def __rtruediv__(self: _ArrayFloat_co, other: _ArrayLikeTD64_co) -> NDArray[timedelta64]: ...
+ @overload
+ def __rtruediv__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __rtruediv__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __lshift__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[int8]: ... # type: ignore[misc]
+ @overload
+ def __lshift__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __lshift__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ...
+ @overload
+ def __lshift__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __lshift__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __rlshift__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[int8]: ... # type: ignore[misc]
+ @overload
+ def __rlshift__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rlshift__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ...
+ @overload
+ def __rlshift__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __rlshift__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __rshift__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[int8]: ... # type: ignore[misc]
+ @overload
+ def __rshift__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rshift__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ...
+ @overload
+ def __rshift__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __rshift__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __rrshift__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[int8]: ... # type: ignore[misc]
+ @overload
+ def __rrshift__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rrshift__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ...
+ @overload
+ def __rrshift__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __rrshift__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __and__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ... # type: ignore[misc]
+ @overload
+ def __and__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __and__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ...
+ @overload
+ def __and__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __and__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __rand__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ... # type: ignore[misc]
+ @overload
+ def __rand__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rand__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ...
+ @overload
+ def __rand__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __rand__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __xor__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ... # type: ignore[misc]
+ @overload
+ def __xor__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __xor__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ...
+ @overload
+ def __xor__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __xor__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __rxor__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ... # type: ignore[misc]
+ @overload
+ def __rxor__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __rxor__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ...
+ @overload
+ def __rxor__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __rxor__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __or__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ... # type: ignore[misc]
+ @overload
+ def __or__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __or__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ...
+ @overload
+ def __or__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __or__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ @overload
+ def __ror__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ... # type: ignore[misc]
+ @overload
+ def __ror__(self: _ArrayUInt_co, other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[Any]]: ... # type: ignore[misc]
+ @overload
+ def __ror__(self: _ArrayInt_co, other: _ArrayLikeInt_co) -> NDArray[signedinteger[Any]]: ...
+ @overload
+ def __ror__(self: NDArray[object_], other: Any) -> Any: ...
+ @overload
+ def __ror__(self: NDArray[Any], other: _ArrayLikeObject_co) -> Any: ...
+
+ # `np.generic` does not support inplace operations
+
+ # NOTE: Inplace ops generally use "same_kind" casting w.r.t. to the left
+ # operand. An exception to this rule are unsigned integers though, which
+ # also accepts a signed integer for the right operand as long it is a 0D
+ # object and its value is >= 0
+ @overload
+ def __iadd__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ...
+ @overload
+ def __iadd__(self: NDArray[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co | _IntLike_co) -> NDArray[unsignedinteger[_NBit1]]: ...
+ @overload
+ def __iadd__(self: NDArray[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> NDArray[signedinteger[_NBit1]]: ...
+ @overload
+ def __iadd__(self: NDArray[floating[_NBit1]], other: _ArrayLikeFloat_co) -> NDArray[floating[_NBit1]]: ...
+ @overload
+ def __iadd__(self: NDArray[complexfloating[_NBit1, _NBit1]], other: _ArrayLikeComplex_co) -> NDArray[complexfloating[_NBit1, _NBit1]]: ...
+ @overload
+ def __iadd__(self: NDArray[timedelta64], other: _ArrayLikeTD64_co) -> NDArray[timedelta64]: ...
+ @overload
+ def __iadd__(self: NDArray[datetime64], other: _ArrayLikeTD64_co) -> NDArray[datetime64]: ...
+ @overload
+ def __iadd__(self: NDArray[object_], other: Any) -> NDArray[object_]: ...
+
+ @overload
+ def __isub__(self: NDArray[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co | _IntLike_co) -> NDArray[unsignedinteger[_NBit1]]: ...
+ @overload
+ def __isub__(self: NDArray[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> NDArray[signedinteger[_NBit1]]: ...
+ @overload
+ def __isub__(self: NDArray[floating[_NBit1]], other: _ArrayLikeFloat_co) -> NDArray[floating[_NBit1]]: ...
+ @overload
+ def __isub__(self: NDArray[complexfloating[_NBit1, _NBit1]], other: _ArrayLikeComplex_co) -> NDArray[complexfloating[_NBit1, _NBit1]]: ...
+ @overload
+ def __isub__(self: NDArray[timedelta64], other: _ArrayLikeTD64_co) -> NDArray[timedelta64]: ...
+ @overload
+ def __isub__(self: NDArray[datetime64], other: _ArrayLikeTD64_co) -> NDArray[datetime64]: ...
+ @overload
+ def __isub__(self: NDArray[object_], other: Any) -> NDArray[object_]: ...
+
+ @overload
+ def __imul__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ...
+ @overload
+ def __imul__(self: NDArray[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co | _IntLike_co) -> NDArray[unsignedinteger[_NBit1]]: ...
+ @overload
+ def __imul__(self: NDArray[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> NDArray[signedinteger[_NBit1]]: ...
+ @overload
+ def __imul__(self: NDArray[floating[_NBit1]], other: _ArrayLikeFloat_co) -> NDArray[floating[_NBit1]]: ...
+ @overload
+ def __imul__(self: NDArray[complexfloating[_NBit1, _NBit1]], other: _ArrayLikeComplex_co) -> NDArray[complexfloating[_NBit1, _NBit1]]: ...
+ @overload
+ def __imul__(self: NDArray[timedelta64], other: _ArrayLikeFloat_co) -> NDArray[timedelta64]: ...
+ @overload
+ def __imul__(self: NDArray[object_], other: Any) -> NDArray[object_]: ...
+
+ @overload
+ def __itruediv__(self: NDArray[floating[_NBit1]], other: _ArrayLikeFloat_co) -> NDArray[floating[_NBit1]]: ...
+ @overload
+ def __itruediv__(self: NDArray[complexfloating[_NBit1, _NBit1]], other: _ArrayLikeComplex_co) -> NDArray[complexfloating[_NBit1, _NBit1]]: ...
+ @overload
+ def __itruediv__(self: NDArray[timedelta64], other: _ArrayLikeBool_co) -> NoReturn: ...
+ @overload
+ def __itruediv__(self: NDArray[timedelta64], other: _ArrayLikeInt_co) -> NDArray[timedelta64]: ...
+ @overload
+ def __itruediv__(self: NDArray[object_], other: Any) -> NDArray[object_]: ...
+
+ @overload
+ def __ifloordiv__(self: NDArray[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co | _IntLike_co) -> NDArray[unsignedinteger[_NBit1]]: ...
+ @overload
+ def __ifloordiv__(self: NDArray[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> NDArray[signedinteger[_NBit1]]: ...
+ @overload
+ def __ifloordiv__(self: NDArray[floating[_NBit1]], other: _ArrayLikeFloat_co) -> NDArray[floating[_NBit1]]: ...
+ @overload
+ def __ifloordiv__(self: NDArray[complexfloating[_NBit1, _NBit1]], other: _ArrayLikeComplex_co) -> NDArray[complexfloating[_NBit1, _NBit1]]: ...
+ @overload
+ def __ifloordiv__(self: NDArray[timedelta64], other: _ArrayLikeBool_co) -> NoReturn: ...
+ @overload
+ def __ifloordiv__(self: NDArray[timedelta64], other: _ArrayLikeInt_co) -> NDArray[timedelta64]: ...
+ @overload
+ def __ifloordiv__(self: NDArray[object_], other: Any) -> NDArray[object_]: ...
+
+ @overload
+ def __ipow__(self: NDArray[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co | _IntLike_co) -> NDArray[unsignedinteger[_NBit1]]: ...
+ @overload
+ def __ipow__(self: NDArray[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> NDArray[signedinteger[_NBit1]]: ...
+ @overload
+ def __ipow__(self: NDArray[floating[_NBit1]], other: _ArrayLikeFloat_co) -> NDArray[floating[_NBit1]]: ...
+ @overload
+ def __ipow__(self: NDArray[complexfloating[_NBit1, _NBit1]], other: _ArrayLikeComplex_co) -> NDArray[complexfloating[_NBit1, _NBit1]]: ...
+ @overload
+ def __ipow__(self: NDArray[object_], other: Any) -> NDArray[object_]: ...
+
+ @overload
+ def __imod__(self: NDArray[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co | _IntLike_co) -> NDArray[unsignedinteger[_NBit1]]: ...
+ @overload
+ def __imod__(self: NDArray[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> NDArray[signedinteger[_NBit1]]: ...
+ @overload
+ def __imod__(self: NDArray[floating[_NBit1]], other: _ArrayLikeFloat_co) -> NDArray[floating[_NBit1]]: ...
+ @overload
+ def __imod__(self: NDArray[timedelta64], other: _SupportsArray[_dtype[timedelta64]] | _NestedSequence[_SupportsArray[_dtype[timedelta64]]]) -> NDArray[timedelta64]: ...
+ @overload
+ def __imod__(self: NDArray[object_], other: Any) -> NDArray[object_]: ...
+
+ @overload
+ def __ilshift__(self: NDArray[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co | _IntLike_co) -> NDArray[unsignedinteger[_NBit1]]: ...
+ @overload
+ def __ilshift__(self: NDArray[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> NDArray[signedinteger[_NBit1]]: ...
+ @overload
+ def __ilshift__(self: NDArray[object_], other: Any) -> NDArray[object_]: ...
+
+ @overload
+ def __irshift__(self: NDArray[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co | _IntLike_co) -> NDArray[unsignedinteger[_NBit1]]: ...
+ @overload
+ def __irshift__(self: NDArray[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> NDArray[signedinteger[_NBit1]]: ...
+ @overload
+ def __irshift__(self: NDArray[object_], other: Any) -> NDArray[object_]: ...
+
+ @overload
+ def __iand__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ...
+ @overload
+ def __iand__(self: NDArray[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co | _IntLike_co) -> NDArray[unsignedinteger[_NBit1]]: ...
+ @overload
+ def __iand__(self: NDArray[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> NDArray[signedinteger[_NBit1]]: ...
+ @overload
+ def __iand__(self: NDArray[object_], other: Any) -> NDArray[object_]: ...
+
+ @overload
+ def __ixor__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ...
+ @overload
+ def __ixor__(self: NDArray[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co | _IntLike_co) -> NDArray[unsignedinteger[_NBit1]]: ...
+ @overload
+ def __ixor__(self: NDArray[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> NDArray[signedinteger[_NBit1]]: ...
+ @overload
+ def __ixor__(self: NDArray[object_], other: Any) -> NDArray[object_]: ...
+
+ @overload
+ def __ior__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ...
+ @overload
+ def __ior__(self: NDArray[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co | _IntLike_co) -> NDArray[unsignedinteger[_NBit1]]: ...
+ @overload
+ def __ior__(self: NDArray[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> NDArray[signedinteger[_NBit1]]: ...
+ @overload
+ def __ior__(self: NDArray[object_], other: Any) -> NDArray[object_]: ...
+
+ @overload
+ def __imatmul__(self: NDArray[bool_], other: _ArrayLikeBool_co) -> NDArray[bool_]: ...
+ @overload
+ def __imatmul__(self: NDArray[unsignedinteger[_NBit1]], other: _ArrayLikeUInt_co) -> NDArray[unsignedinteger[_NBit1]]: ...
+ @overload
+ def __imatmul__(self: NDArray[signedinteger[_NBit1]], other: _ArrayLikeInt_co) -> NDArray[signedinteger[_NBit1]]: ...
+ @overload
+ def __imatmul__(self: NDArray[floating[_NBit1]], other: _ArrayLikeFloat_co) -> NDArray[floating[_NBit1]]: ...
+ @overload
+ def __imatmul__(self: NDArray[complexfloating[_NBit1, _NBit1]], other: _ArrayLikeComplex_co) -> NDArray[complexfloating[_NBit1, _NBit1]]: ...
+ @overload
+ def __imatmul__(self: NDArray[object_], other: Any) -> NDArray[object_]: ...
+
+ def __dlpack__(self: NDArray[number[Any]], *, stream: None = ...) -> _PyCapsule: ...
+ def __dlpack_device__(self) -> tuple[int, L[0]]: ...
+
+ # Keep `dtype` at the bottom to avoid name conflicts with `np.dtype`
+ @property
+ def dtype(self) -> _DType_co: ...
+
+# NOTE: while `np.generic` is not technically an instance of `ABCMeta`,
+# the `@abstractmethod` decorator is herein used to (forcefully) deny
+# the creation of `np.generic` instances.
+# The `# type: ignore` comments are necessary to silence mypy errors regarding
+# the missing `ABCMeta` metaclass.
+
+# See https://github.com/numpy/numpy-stubs/pull/80 for more details.
+
+_ScalarType = TypeVar("_ScalarType", bound=generic)
+_NBit1 = TypeVar("_NBit1", bound=NBitBase)
+_NBit2 = TypeVar("_NBit2", bound=NBitBase)
+
+class generic(_ArrayOrScalarCommon):
+ @abstractmethod
+ def __init__(self, *args: Any, **kwargs: Any) -> None: ...
+ @overload
+ def __array__(self: _ScalarType, dtype: None = ..., /) -> ndarray[Any, _dtype[_ScalarType]]: ...
+ @overload
+ def __array__(self, dtype: _DType, /) -> ndarray[Any, _DType]: ...
+ def __hash__(self) -> int: ...
+ @property
+ def base(self) -> None: ...
+ @property
+ def ndim(self) -> L[0]: ...
+ @property
+ def size(self) -> L[1]: ...
+ @property
+ def shape(self) -> tuple[()]: ...
+ @property
+ def strides(self) -> tuple[()]: ...
+ def byteswap(self: _ScalarType, inplace: L[False] = ...) -> _ScalarType: ...
+ @property
+ def flat(self: _ScalarType) -> flatiter[ndarray[Any, _dtype[_ScalarType]]]: ...
+
+ if sys.version_info >= (3, 12):
+ def __buffer__(self, flags: int, /) -> memoryview: ...
+
+ @overload
+ def astype(
+ self,
+ dtype: _DTypeLike[_ScalarType],
+ order: _OrderKACF = ...,
+ casting: _CastingKind = ...,
+ subok: bool = ...,
+ copy: bool | _CopyMode = ...,
+ ) -> _ScalarType: ...
+ @overload
+ def astype(
+ self,
+ dtype: DTypeLike,
+ order: _OrderKACF = ...,
+ casting: _CastingKind = ...,
+ subok: bool = ...,
+ copy: bool | _CopyMode = ...,
+ ) -> Any: ...
+
+ # NOTE: `view` will perform a 0D->scalar cast,
+ # thus the array `type` is irrelevant to the output type
+ @overload
+ def view(
+ self: _ScalarType,
+ type: type[ndarray[Any, Any]] = ...,
+ ) -> _ScalarType: ...
+ @overload
+ def view(
+ self,
+ dtype: _DTypeLike[_ScalarType],
+ type: type[ndarray[Any, Any]] = ...,
+ ) -> _ScalarType: ...
+ @overload
+ def view(
+ self,
+ dtype: DTypeLike,
+ type: type[ndarray[Any, Any]] = ...,
+ ) -> Any: ...
+
+ @overload
+ def getfield(
+ self,
+ dtype: _DTypeLike[_ScalarType],
+ offset: SupportsIndex = ...
+ ) -> _ScalarType: ...
+ @overload
+ def getfield(
+ self,
+ dtype: DTypeLike,
+ offset: SupportsIndex = ...
+ ) -> Any: ...
+
+ def item(
+ self, args: L[0] | tuple[()] | tuple[L[0]] = ..., /,
+ ) -> Any: ...
+
+ @overload
+ def take( # type: ignore[misc]
+ self: _ScalarType,
+ indices: _IntLike_co,
+ axis: None | SupportsIndex = ...,
+ out: None = ...,
+ mode: _ModeKind = ...,
+ ) -> _ScalarType: ...
+ @overload
+ def take( # type: ignore[misc]
+ self: _ScalarType,
+ indices: _ArrayLikeInt_co,
+ axis: None | SupportsIndex = ...,
+ out: None = ...,
+ mode: _ModeKind = ...,
+ ) -> ndarray[Any, _dtype[_ScalarType]]: ...
+ @overload
+ def take(
+ self,
+ indices: _ArrayLikeInt_co,
+ axis: None | SupportsIndex = ...,
+ out: _NdArraySubClass = ...,
+ mode: _ModeKind = ...,
+ ) -> _NdArraySubClass: ...
+
+ def repeat(
+ self: _ScalarType,
+ repeats: _ArrayLikeInt_co,
+ axis: None | SupportsIndex = ...,
+ ) -> ndarray[Any, _dtype[_ScalarType]]: ...
+
+ def flatten(
+ self: _ScalarType,
+ order: _OrderKACF = ...,
+ ) -> ndarray[Any, _dtype[_ScalarType]]: ...
+
+ def ravel(
+ self: _ScalarType,
+ order: _OrderKACF = ...,
+ ) -> ndarray[Any, _dtype[_ScalarType]]: ...
+
+ @overload
+ def reshape(
+ self: _ScalarType, shape: _ShapeLike, /, *, order: _OrderACF = ...
+ ) -> ndarray[Any, _dtype[_ScalarType]]: ...
+ @overload
+ def reshape(
+ self: _ScalarType, *shape: SupportsIndex, order: _OrderACF = ...
+ ) -> ndarray[Any, _dtype[_ScalarType]]: ...
+
+ def squeeze(
+ self: _ScalarType, axis: None | L[0] | tuple[()] = ...
+ ) -> _ScalarType: ...
+ def transpose(self: _ScalarType, axes: None | tuple[()] = ..., /) -> _ScalarType: ...
+ # Keep `dtype` at the bottom to avoid name conflicts with `np.dtype`
+ @property
+ def dtype(self: _ScalarType) -> _dtype[_ScalarType]: ...
+
+class number(generic, Generic[_NBit1]): # type: ignore
+ @property
+ def real(self: _ArraySelf) -> _ArraySelf: ...
+ @property
+ def imag(self: _ArraySelf) -> _ArraySelf: ...
+ def __class_getitem__(self, item: Any) -> GenericAlias: ...
+ def __int__(self) -> int: ...
+ def __float__(self) -> float: ...
+ def __complex__(self) -> complex: ...
+ def __neg__(self: _ArraySelf) -> _ArraySelf: ...
+ def __pos__(self: _ArraySelf) -> _ArraySelf: ...
+ def __abs__(self: _ArraySelf) -> _ArraySelf: ...
+ # Ensure that objects annotated as `number` support arithmetic operations
+ __add__: _NumberOp
+ __radd__: _NumberOp
+ __sub__: _NumberOp
+ __rsub__: _NumberOp
+ __mul__: _NumberOp
+ __rmul__: _NumberOp
+ __floordiv__: _NumberOp
+ __rfloordiv__: _NumberOp
+ __pow__: _NumberOp
+ __rpow__: _NumberOp
+ __truediv__: _NumberOp
+ __rtruediv__: _NumberOp
+ __lt__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
+ __le__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
+ __gt__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
+ __ge__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
+
+class bool_(generic):
+ def __init__(self, value: object = ..., /) -> None: ...
+ def item(
+ self, args: L[0] | tuple[()] | tuple[L[0]] = ..., /,
+ ) -> bool: ...
+ def tolist(self) -> bool: ...
+ @property
+ def real(self: _ArraySelf) -> _ArraySelf: ...
+ @property
+ def imag(self: _ArraySelf) -> _ArraySelf: ...
+ def __int__(self) -> int: ...
+ def __float__(self) -> float: ...
+ def __complex__(self) -> complex: ...
+ def __abs__(self: _ArraySelf) -> _ArraySelf: ...
+ __add__: _BoolOp[bool_]
+ __radd__: _BoolOp[bool_]
+ __sub__: _BoolSub
+ __rsub__: _BoolSub
+ __mul__: _BoolOp[bool_]
+ __rmul__: _BoolOp[bool_]
+ __floordiv__: _BoolOp[int8]
+ __rfloordiv__: _BoolOp[int8]
+ __pow__: _BoolOp[int8]
+ __rpow__: _BoolOp[int8]
+ __truediv__: _BoolTrueDiv
+ __rtruediv__: _BoolTrueDiv
+ def __invert__(self) -> bool_: ...
+ __lshift__: _BoolBitOp[int8]
+ __rlshift__: _BoolBitOp[int8]
+ __rshift__: _BoolBitOp[int8]
+ __rrshift__: _BoolBitOp[int8]
+ __and__: _BoolBitOp[bool_]
+ __rand__: _BoolBitOp[bool_]
+ __xor__: _BoolBitOp[bool_]
+ __rxor__: _BoolBitOp[bool_]
+ __or__: _BoolBitOp[bool_]
+ __ror__: _BoolBitOp[bool_]
+ __mod__: _BoolMod
+ __rmod__: _BoolMod
+ __divmod__: _BoolDivMod
+ __rdivmod__: _BoolDivMod
+ __lt__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
+ __le__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
+ __gt__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
+ __ge__: _ComparisonOp[_NumberLike_co, _ArrayLikeNumber_co]
+
+class object_(generic):
+ def __init__(self, value: object = ..., /) -> None: ...
+ @property
+ def real(self: _ArraySelf) -> _ArraySelf: ...
+ @property
+ def imag(self: _ArraySelf) -> _ArraySelf: ...
+ # The 3 protocols below may or may not raise,
+ # depending on the underlying object
+ def __int__(self) -> int: ...
+ def __float__(self) -> float: ...
+ def __complex__(self) -> complex: ...
+
+ if sys.version_info >= (3, 12):
+ def __release_buffer__(self, buffer: memoryview, /) -> None: ...
+
+# The `datetime64` constructors requires an object with the three attributes below,
+# and thus supports datetime duck typing
+class _DatetimeScalar(Protocol):
+ @property
+ def day(self) -> int: ...
+ @property
+ def month(self) -> int: ...
+ @property
+ def year(self) -> int: ...
+
+# TODO: `item`/`tolist` returns either `dt.date`, `dt.datetime` or `int`
+# depending on the unit
+class datetime64(generic):
+ @overload
+ def __init__(
+ self,
+ value: None | datetime64 | _CharLike_co | _DatetimeScalar = ...,
+ format: _CharLike_co | tuple[_CharLike_co, _IntLike_co] = ...,
+ /,
+ ) -> None: ...
+ @overload
+ def __init__(
+ self,
+ value: int,
+ format: _CharLike_co | tuple[_CharLike_co, _IntLike_co],
+ /,
+ ) -> None: ...
+ def __add__(self, other: _TD64Like_co) -> datetime64: ...
+ def __radd__(self, other: _TD64Like_co) -> datetime64: ...
+ @overload
+ def __sub__(self, other: datetime64) -> timedelta64: ...
+ @overload
+ def __sub__(self, other: _TD64Like_co) -> datetime64: ...
+ def __rsub__(self, other: datetime64) -> timedelta64: ...
+ __lt__: _ComparisonOp[datetime64, _ArrayLikeDT64_co]
+ __le__: _ComparisonOp[datetime64, _ArrayLikeDT64_co]
+ __gt__: _ComparisonOp[datetime64, _ArrayLikeDT64_co]
+ __ge__: _ComparisonOp[datetime64, _ArrayLikeDT64_co]
+
+_IntValue = Union[SupportsInt, _CharLike_co, SupportsIndex]
+_FloatValue = Union[None, _CharLike_co, SupportsFloat, SupportsIndex]
+_ComplexValue = Union[
+ None,
+ _CharLike_co,
+ SupportsFloat,
+ SupportsComplex,
+ SupportsIndex,
+ complex, # `complex` is not a subtype of `SupportsComplex`
+]
+
+class integer(number[_NBit1]): # type: ignore
+ @property
+ def numerator(self: _ScalarType) -> _ScalarType: ...
+ @property
+ def denominator(self) -> L[1]: ...
+ @overload
+ def __round__(self, ndigits: None = ...) -> int: ...
+ @overload
+ def __round__(self: _ScalarType, ndigits: SupportsIndex) -> _ScalarType: ...
+
+ # NOTE: `__index__` is technically defined in the bottom-most
+ # sub-classes (`int64`, `uint32`, etc)
+ def item(
+ self, args: L[0] | tuple[()] | tuple[L[0]] = ..., /,
+ ) -> int: ...
+ def tolist(self) -> int: ...
+ def is_integer(self) -> L[True]: ...
+ def bit_count(self: _ScalarType) -> int: ...
+ def __index__(self) -> int: ...
+ __truediv__: _IntTrueDiv[_NBit1]
+ __rtruediv__: _IntTrueDiv[_NBit1]
+ def __mod__(self, value: _IntLike_co) -> integer[Any]: ...
+ def __rmod__(self, value: _IntLike_co) -> integer[Any]: ...
+ def __invert__(self: _IntType) -> _IntType: ...
+ # Ensure that objects annotated as `integer` support bit-wise operations
+ def __lshift__(self, other: _IntLike_co) -> integer[Any]: ...
+ def __rlshift__(self, other: _IntLike_co) -> integer[Any]: ...
+ def __rshift__(self, other: _IntLike_co) -> integer[Any]: ...
+ def __rrshift__(self, other: _IntLike_co) -> integer[Any]: ...
+ def __and__(self, other: _IntLike_co) -> integer[Any]: ...
+ def __rand__(self, other: _IntLike_co) -> integer[Any]: ...
+ def __or__(self, other: _IntLike_co) -> integer[Any]: ...
+ def __ror__(self, other: _IntLike_co) -> integer[Any]: ...
+ def __xor__(self, other: _IntLike_co) -> integer[Any]: ...
+ def __rxor__(self, other: _IntLike_co) -> integer[Any]: ...
+
+class signedinteger(integer[_NBit1]):
+ def __init__(self, value: _IntValue = ..., /) -> None: ...
+ __add__: _SignedIntOp[_NBit1]
+ __radd__: _SignedIntOp[_NBit1]
+ __sub__: _SignedIntOp[_NBit1]
+ __rsub__: _SignedIntOp[_NBit1]
+ __mul__: _SignedIntOp[_NBit1]
+ __rmul__: _SignedIntOp[_NBit1]
+ __floordiv__: _SignedIntOp[_NBit1]
+ __rfloordiv__: _SignedIntOp[_NBit1]
+ __pow__: _SignedIntOp[_NBit1]
+ __rpow__: _SignedIntOp[_NBit1]
+ __lshift__: _SignedIntBitOp[_NBit1]
+ __rlshift__: _SignedIntBitOp[_NBit1]
+ __rshift__: _SignedIntBitOp[_NBit1]
+ __rrshift__: _SignedIntBitOp[_NBit1]
+ __and__: _SignedIntBitOp[_NBit1]
+ __rand__: _SignedIntBitOp[_NBit1]
+ __xor__: _SignedIntBitOp[_NBit1]
+ __rxor__: _SignedIntBitOp[_NBit1]
+ __or__: _SignedIntBitOp[_NBit1]
+ __ror__: _SignedIntBitOp[_NBit1]
+ __mod__: _SignedIntMod[_NBit1]
+ __rmod__: _SignedIntMod[_NBit1]
+ __divmod__: _SignedIntDivMod[_NBit1]
+ __rdivmod__: _SignedIntDivMod[_NBit1]
+
+int8 = signedinteger[_8Bit]
+int16 = signedinteger[_16Bit]
+int32 = signedinteger[_32Bit]
+int64 = signedinteger[_64Bit]
+
+byte = signedinteger[_NBitByte]
+short = signedinteger[_NBitShort]
+intc = signedinteger[_NBitIntC]
+intp = signedinteger[_NBitIntP]
+int_ = signedinteger[_NBitInt]
+longlong = signedinteger[_NBitLongLong]
+
+# TODO: `item`/`tolist` returns either `dt.timedelta` or `int`
+# depending on the unit
+class timedelta64(generic):
+ def __init__(
+ self,
+ value: None | int | _CharLike_co | dt.timedelta | timedelta64 = ...,
+ format: _CharLike_co | tuple[_CharLike_co, _IntLike_co] = ...,
+ /,
+ ) -> None: ...
+ @property
+ def numerator(self: _ScalarType) -> _ScalarType: ...
+ @property
+ def denominator(self) -> L[1]: ...
+
+ # NOTE: Only a limited number of units support conversion
+ # to builtin scalar types: `Y`, `M`, `ns`, `ps`, `fs`, `as`
+ def __int__(self) -> int: ...
+ def __float__(self) -> float: ...
+ def __complex__(self) -> complex: ...
+ def __neg__(self: _ArraySelf) -> _ArraySelf: ...
+ def __pos__(self: _ArraySelf) -> _ArraySelf: ...
+ def __abs__(self: _ArraySelf) -> _ArraySelf: ...
+ def __add__(self, other: _TD64Like_co) -> timedelta64: ...
+ def __radd__(self, other: _TD64Like_co) -> timedelta64: ...
+ def __sub__(self, other: _TD64Like_co) -> timedelta64: ...
+ def __rsub__(self, other: _TD64Like_co) -> timedelta64: ...
+ def __mul__(self, other: _FloatLike_co) -> timedelta64: ...
+ def __rmul__(self, other: _FloatLike_co) -> timedelta64: ...
+ __truediv__: _TD64Div[float64]
+ __floordiv__: _TD64Div[int64]
+ def __rtruediv__(self, other: timedelta64) -> float64: ...
+ def __rfloordiv__(self, other: timedelta64) -> int64: ...
+ def __mod__(self, other: timedelta64) -> timedelta64: ...
+ def __rmod__(self, other: timedelta64) -> timedelta64: ...
+ def __divmod__(self, other: timedelta64) -> tuple[int64, timedelta64]: ...
+ def __rdivmod__(self, other: timedelta64) -> tuple[int64, timedelta64]: ...
+ __lt__: _ComparisonOp[_TD64Like_co, _ArrayLikeTD64_co]
+ __le__: _ComparisonOp[_TD64Like_co, _ArrayLikeTD64_co]
+ __gt__: _ComparisonOp[_TD64Like_co, _ArrayLikeTD64_co]
+ __ge__: _ComparisonOp[_TD64Like_co, _ArrayLikeTD64_co]
+
+class unsignedinteger(integer[_NBit1]):
+ # NOTE: `uint64 + signedinteger -> float64`
+ def __init__(self, value: _IntValue = ..., /) -> None: ...
+ __add__: _UnsignedIntOp[_NBit1]
+ __radd__: _UnsignedIntOp[_NBit1]
+ __sub__: _UnsignedIntOp[_NBit1]
+ __rsub__: _UnsignedIntOp[_NBit1]
+ __mul__: _UnsignedIntOp[_NBit1]
+ __rmul__: _UnsignedIntOp[_NBit1]
+ __floordiv__: _UnsignedIntOp[_NBit1]
+ __rfloordiv__: _UnsignedIntOp[_NBit1]
+ __pow__: _UnsignedIntOp[_NBit1]
+ __rpow__: _UnsignedIntOp[_NBit1]
+ __lshift__: _UnsignedIntBitOp[_NBit1]
+ __rlshift__: _UnsignedIntBitOp[_NBit1]
+ __rshift__: _UnsignedIntBitOp[_NBit1]
+ __rrshift__: _UnsignedIntBitOp[_NBit1]
+ __and__: _UnsignedIntBitOp[_NBit1]
+ __rand__: _UnsignedIntBitOp[_NBit1]
+ __xor__: _UnsignedIntBitOp[_NBit1]
+ __rxor__: _UnsignedIntBitOp[_NBit1]
+ __or__: _UnsignedIntBitOp[_NBit1]
+ __ror__: _UnsignedIntBitOp[_NBit1]
+ __mod__: _UnsignedIntMod[_NBit1]
+ __rmod__: _UnsignedIntMod[_NBit1]
+ __divmod__: _UnsignedIntDivMod[_NBit1]
+ __rdivmod__: _UnsignedIntDivMod[_NBit1]
+
+uint8 = unsignedinteger[_8Bit]
+uint16 = unsignedinteger[_16Bit]
+uint32 = unsignedinteger[_32Bit]
+uint64 = unsignedinteger[_64Bit]
+
+ubyte = unsignedinteger[_NBitByte]
+ushort = unsignedinteger[_NBitShort]
+uintc = unsignedinteger[_NBitIntC]
+uintp = unsignedinteger[_NBitIntP]
+uint = unsignedinteger[_NBitInt]
+ulonglong = unsignedinteger[_NBitLongLong]
+
+class inexact(number[_NBit1]): # type: ignore
+ def __getnewargs__(self: inexact[_64Bit]) -> tuple[float, ...]: ...
+
+_IntType = TypeVar("_IntType", bound=integer[Any])
+_FloatType = TypeVar('_FloatType', bound=floating[Any])
+
+class floating(inexact[_NBit1]):
+ def __init__(self, value: _FloatValue = ..., /) -> None: ...
+ def item(
+ self, args: L[0] | tuple[()] | tuple[L[0]] = ...,
+ /,
+ ) -> float: ...
+ def tolist(self) -> float: ...
+ def is_integer(self) -> bool: ...
+ def hex(self: float64) -> str: ...
+ @classmethod
+ def fromhex(cls: type[float64], string: str, /) -> float64: ...
+ def as_integer_ratio(self) -> tuple[int, int]: ...
+ def __ceil__(self: float64) -> int: ...
+ def __floor__(self: float64) -> int: ...
+ def __trunc__(self: float64) -> int: ...
+ def __getnewargs__(self: float64) -> tuple[float]: ...
+ def __getformat__(self: float64, typestr: L["double", "float"], /) -> str: ...
+ @overload
+ def __round__(self, ndigits: None = ...) -> int: ...
+ @overload
+ def __round__(self: _ScalarType, ndigits: SupportsIndex) -> _ScalarType: ...
+ __add__: _FloatOp[_NBit1]
+ __radd__: _FloatOp[_NBit1]
+ __sub__: _FloatOp[_NBit1]
+ __rsub__: _FloatOp[_NBit1]
+ __mul__: _FloatOp[_NBit1]
+ __rmul__: _FloatOp[_NBit1]
+ __truediv__: _FloatOp[_NBit1]
+ __rtruediv__: _FloatOp[_NBit1]
+ __floordiv__: _FloatOp[_NBit1]
+ __rfloordiv__: _FloatOp[_NBit1]
+ __pow__: _FloatOp[_NBit1]
+ __rpow__: _FloatOp[_NBit1]
+ __mod__: _FloatMod[_NBit1]
+ __rmod__: _FloatMod[_NBit1]
+ __divmod__: _FloatDivMod[_NBit1]
+ __rdivmod__: _FloatDivMod[_NBit1]
+
+float16 = floating[_16Bit]
+float32 = floating[_32Bit]
+float64 = floating[_64Bit]
+
+half = floating[_NBitHalf]
+single = floating[_NBitSingle]
+double = floating[_NBitDouble]
+float_ = floating[_NBitDouble]
+longdouble = floating[_NBitLongDouble]
+longfloat = floating[_NBitLongDouble]
+
+# The main reason for `complexfloating` having two typevars is cosmetic.
+# It is used to clarify why `complex128`s precision is `_64Bit`, the latter
+# describing the two 64 bit floats representing its real and imaginary component
+
+class complexfloating(inexact[_NBit1], Generic[_NBit1, _NBit2]):
+ def __init__(self, value: _ComplexValue = ..., /) -> None: ...
+ def item(
+ self, args: L[0] | tuple[()] | tuple[L[0]] = ..., /,
+ ) -> complex: ...
+ def tolist(self) -> complex: ...
+ @property
+ def real(self) -> floating[_NBit1]: ... # type: ignore[override]
+ @property
+ def imag(self) -> floating[_NBit2]: ... # type: ignore[override]
+ def __abs__(self) -> floating[_NBit1]: ... # type: ignore[override]
+ def __getnewargs__(self: complex128) -> tuple[float, float]: ...
+ # NOTE: Deprecated
+ # def __round__(self, ndigits=...): ...
+ __add__: _ComplexOp[_NBit1]
+ __radd__: _ComplexOp[_NBit1]
+ __sub__: _ComplexOp[_NBit1]
+ __rsub__: _ComplexOp[_NBit1]
+ __mul__: _ComplexOp[_NBit1]
+ __rmul__: _ComplexOp[_NBit1]
+ __truediv__: _ComplexOp[_NBit1]
+ __rtruediv__: _ComplexOp[_NBit1]
+ __pow__: _ComplexOp[_NBit1]
+ __rpow__: _ComplexOp[_NBit1]
+
+complex64 = complexfloating[_32Bit, _32Bit]
+complex128 = complexfloating[_64Bit, _64Bit]
+
+csingle = complexfloating[_NBitSingle, _NBitSingle]
+singlecomplex = complexfloating[_NBitSingle, _NBitSingle]
+cdouble = complexfloating[_NBitDouble, _NBitDouble]
+complex_ = complexfloating[_NBitDouble, _NBitDouble]
+cfloat = complexfloating[_NBitDouble, _NBitDouble]
+clongdouble = complexfloating[_NBitLongDouble, _NBitLongDouble]
+clongfloat = complexfloating[_NBitLongDouble, _NBitLongDouble]
+longcomplex = complexfloating[_NBitLongDouble, _NBitLongDouble]
+
+class flexible(generic): ... # type: ignore
+
+# TODO: `item`/`tolist` returns either `bytes` or `tuple`
+# depending on whether or not it's used as an opaque bytes sequence
+# or a structure
+class void(flexible):
+ @overload
+ def __init__(self, value: _IntLike_co | bytes, /, dtype : None = ...) -> None: ...
+ @overload
+ def __init__(self, value: Any, /, dtype: _DTypeLikeVoid) -> None: ...
+ @property
+ def real(self: _ArraySelf) -> _ArraySelf: ...
+ @property
+ def imag(self: _ArraySelf) -> _ArraySelf: ...
+ def setfield(
+ self, val: ArrayLike, dtype: DTypeLike, offset: int = ...
+ ) -> None: ...
+ @overload
+ def __getitem__(self, key: str | SupportsIndex) -> Any: ...
+ @overload
+ def __getitem__(self, key: list[str]) -> void: ...
+ def __setitem__(
+ self,
+ key: str | list[str] | SupportsIndex,
+ value: ArrayLike,
+ ) -> None: ...
+
+class character(flexible): # type: ignore
+ def __int__(self) -> int: ...
+ def __float__(self) -> float: ...
+
+# NOTE: Most `np.bytes_` / `np.str_` methods return their
+# builtin `bytes` / `str` counterpart
+
+class bytes_(character, bytes):
+ @overload
+ def __init__(self, value: object = ..., /) -> None: ...
+ @overload
+ def __init__(
+ self, value: str, /, encoding: str = ..., errors: str = ...
+ ) -> None: ...
+ def item(
+ self, args: L[0] | tuple[()] | tuple[L[0]] = ..., /,
+ ) -> bytes: ...
+ def tolist(self) -> bytes: ...
+
+string_ = bytes_
+
+class str_(character, str):
+ @overload
+ def __init__(self, value: object = ..., /) -> None: ...
+ @overload
+ def __init__(
+ self, value: bytes, /, encoding: str = ..., errors: str = ...
+ ) -> None: ...
+ def item(
+ self, args: L[0] | tuple[()] | tuple[L[0]] = ..., /,
+ ) -> str: ...
+ def tolist(self) -> str: ...
+
+unicode_ = str_
+
+#
+# Constants
+#
+
+Inf: Final[float]
+Infinity: Final[float]
+NAN: Final[float]
+NINF: Final[float]
+NZERO: Final[float]
+NaN: Final[float]
+PINF: Final[float]
+PZERO: Final[float]
+e: Final[float]
+euler_gamma: Final[float]
+inf: Final[float]
+infty: Final[float]
+nan: Final[float]
+pi: Final[float]
+
+ERR_IGNORE: L[0]
+ERR_WARN: L[1]
+ERR_RAISE: L[2]
+ERR_CALL: L[3]
+ERR_PRINT: L[4]
+ERR_LOG: L[5]
+ERR_DEFAULT: L[521]
+
+SHIFT_DIVIDEBYZERO: L[0]
+SHIFT_OVERFLOW: L[3]
+SHIFT_UNDERFLOW: L[6]
+SHIFT_INVALID: L[9]
+
+FPE_DIVIDEBYZERO: L[1]
+FPE_OVERFLOW: L[2]
+FPE_UNDERFLOW: L[4]
+FPE_INVALID: L[8]
+
+FLOATING_POINT_SUPPORT: L[1]
+UFUNC_BUFSIZE_DEFAULT = BUFSIZE
+
+little_endian: Final[bool]
+True_: Final[bool_]
+False_: Final[bool_]
+
+UFUNC_PYVALS_NAME: L["UFUNC_PYVALS"]
+
+newaxis: None
+
+# See `numpy._typing._ufunc` for more concrete nin-/nout-specific stubs
+@final
+class ufunc:
+ @property
+ def __name__(self) -> str: ...
+ @property
+ def __doc__(self) -> str: ...
+ __call__: Callable[..., Any]
+ @property
+ def nin(self) -> int: ...
+ @property
+ def nout(self) -> int: ...
+ @property
+ def nargs(self) -> int: ...
+ @property
+ def ntypes(self) -> int: ...
+ @property
+ def types(self) -> list[str]: ...
+ # Broad return type because it has to encompass things like
+ #
+ # >>> np.logical_and.identity is True
+ # True
+ # >>> np.add.identity is 0
+ # True
+ # >>> np.sin.identity is None
+ # True
+ #
+ # and any user-defined ufuncs.
+ @property
+ def identity(self) -> Any: ...
+ # This is None for ufuncs and a string for gufuncs.
+ @property
+ def signature(self) -> None | str: ...
+ # The next four methods will always exist, but they will just
+ # raise a ValueError ufuncs with that don't accept two input
+ # arguments and return one output argument. Because of that we
+ # can't type them very precisely.
+ reduce: Any
+ accumulate: Any
+ reduceat: Any
+ outer: Any
+ # Similarly at won't be defined for ufuncs that return multiple
+ # outputs, so we can't type it very precisely.
+ at: Any
+
+# Parameters: `__name__`, `ntypes` and `identity`
+absolute: _UFunc_Nin1_Nout1[L['absolute'], L[20], None]
+add: _UFunc_Nin2_Nout1[L['add'], L[22], L[0]]
+arccos: _UFunc_Nin1_Nout1[L['arccos'], L[8], None]
+arccosh: _UFunc_Nin1_Nout1[L['arccosh'], L[8], None]
+arcsin: _UFunc_Nin1_Nout1[L['arcsin'], L[8], None]
+arcsinh: _UFunc_Nin1_Nout1[L['arcsinh'], L[8], None]
+arctan2: _UFunc_Nin2_Nout1[L['arctan2'], L[5], None]
+arctan: _UFunc_Nin1_Nout1[L['arctan'], L[8], None]
+arctanh: _UFunc_Nin1_Nout1[L['arctanh'], L[8], None]
+bitwise_and: _UFunc_Nin2_Nout1[L['bitwise_and'], L[12], L[-1]]
+bitwise_not: _UFunc_Nin1_Nout1[L['invert'], L[12], None]
+bitwise_or: _UFunc_Nin2_Nout1[L['bitwise_or'], L[12], L[0]]
+bitwise_xor: _UFunc_Nin2_Nout1[L['bitwise_xor'], L[12], L[0]]
+cbrt: _UFunc_Nin1_Nout1[L['cbrt'], L[5], None]
+ceil: _UFunc_Nin1_Nout1[L['ceil'], L[7], None]
+conj: _UFunc_Nin1_Nout1[L['conjugate'], L[18], None]
+conjugate: _UFunc_Nin1_Nout1[L['conjugate'], L[18], None]
+copysign: _UFunc_Nin2_Nout1[L['copysign'], L[4], None]
+cos: _UFunc_Nin1_Nout1[L['cos'], L[9], None]
+cosh: _UFunc_Nin1_Nout1[L['cosh'], L[8], None]
+deg2rad: _UFunc_Nin1_Nout1[L['deg2rad'], L[5], None]
+degrees: _UFunc_Nin1_Nout1[L['degrees'], L[5], None]
+divide: _UFunc_Nin2_Nout1[L['true_divide'], L[11], None]
+divmod: _UFunc_Nin2_Nout2[L['divmod'], L[15], None]
+equal: _UFunc_Nin2_Nout1[L['equal'], L[23], None]
+exp2: _UFunc_Nin1_Nout1[L['exp2'], L[8], None]
+exp: _UFunc_Nin1_Nout1[L['exp'], L[10], None]
+expm1: _UFunc_Nin1_Nout1[L['expm1'], L[8], None]
+fabs: _UFunc_Nin1_Nout1[L['fabs'], L[5], None]
+float_power: _UFunc_Nin2_Nout1[L['float_power'], L[4], None]
+floor: _UFunc_Nin1_Nout1[L['floor'], L[7], None]
+floor_divide: _UFunc_Nin2_Nout1[L['floor_divide'], L[21], None]
+fmax: _UFunc_Nin2_Nout1[L['fmax'], L[21], None]
+fmin: _UFunc_Nin2_Nout1[L['fmin'], L[21], None]
+fmod: _UFunc_Nin2_Nout1[L['fmod'], L[15], None]
+frexp: _UFunc_Nin1_Nout2[L['frexp'], L[4], None]
+gcd: _UFunc_Nin2_Nout1[L['gcd'], L[11], L[0]]
+greater: _UFunc_Nin2_Nout1[L['greater'], L[23], None]
+greater_equal: _UFunc_Nin2_Nout1[L['greater_equal'], L[23], None]
+heaviside: _UFunc_Nin2_Nout1[L['heaviside'], L[4], None]
+hypot: _UFunc_Nin2_Nout1[L['hypot'], L[5], L[0]]
+invert: _UFunc_Nin1_Nout1[L['invert'], L[12], None]
+isfinite: _UFunc_Nin1_Nout1[L['isfinite'], L[20], None]
+isinf: _UFunc_Nin1_Nout1[L['isinf'], L[20], None]
+isnan: _UFunc_Nin1_Nout1[L['isnan'], L[20], None]
+isnat: _UFunc_Nin1_Nout1[L['isnat'], L[2], None]
+lcm: _UFunc_Nin2_Nout1[L['lcm'], L[11], None]
+ldexp: _UFunc_Nin2_Nout1[L['ldexp'], L[8], None]
+left_shift: _UFunc_Nin2_Nout1[L['left_shift'], L[11], None]
+less: _UFunc_Nin2_Nout1[L['less'], L[23], None]
+less_equal: _UFunc_Nin2_Nout1[L['less_equal'], L[23], None]
+log10: _UFunc_Nin1_Nout1[L['log10'], L[8], None]
+log1p: _UFunc_Nin1_Nout1[L['log1p'], L[8], None]
+log2: _UFunc_Nin1_Nout1[L['log2'], L[8], None]
+log: _UFunc_Nin1_Nout1[L['log'], L[10], None]
+logaddexp2: _UFunc_Nin2_Nout1[L['logaddexp2'], L[4], float]
+logaddexp: _UFunc_Nin2_Nout1[L['logaddexp'], L[4], float]
+logical_and: _UFunc_Nin2_Nout1[L['logical_and'], L[20], L[True]]
+logical_not: _UFunc_Nin1_Nout1[L['logical_not'], L[20], None]
+logical_or: _UFunc_Nin2_Nout1[L['logical_or'], L[20], L[False]]
+logical_xor: _UFunc_Nin2_Nout1[L['logical_xor'], L[19], L[False]]
+matmul: _GUFunc_Nin2_Nout1[L['matmul'], L[19], None]
+maximum: _UFunc_Nin2_Nout1[L['maximum'], L[21], None]
+minimum: _UFunc_Nin2_Nout1[L['minimum'], L[21], None]
+mod: _UFunc_Nin2_Nout1[L['remainder'], L[16], None]
+modf: _UFunc_Nin1_Nout2[L['modf'], L[4], None]
+multiply: _UFunc_Nin2_Nout1[L['multiply'], L[23], L[1]]
+negative: _UFunc_Nin1_Nout1[L['negative'], L[19], None]
+nextafter: _UFunc_Nin2_Nout1[L['nextafter'], L[4], None]
+not_equal: _UFunc_Nin2_Nout1[L['not_equal'], L[23], None]
+positive: _UFunc_Nin1_Nout1[L['positive'], L[19], None]
+power: _UFunc_Nin2_Nout1[L['power'], L[18], None]
+rad2deg: _UFunc_Nin1_Nout1[L['rad2deg'], L[5], None]
+radians: _UFunc_Nin1_Nout1[L['radians'], L[5], None]
+reciprocal: _UFunc_Nin1_Nout1[L['reciprocal'], L[18], None]
+remainder: _UFunc_Nin2_Nout1[L['remainder'], L[16], None]
+right_shift: _UFunc_Nin2_Nout1[L['right_shift'], L[11], None]
+rint: _UFunc_Nin1_Nout1[L['rint'], L[10], None]
+sign: _UFunc_Nin1_Nout1[L['sign'], L[19], None]
+signbit: _UFunc_Nin1_Nout1[L['signbit'], L[4], None]
+sin: _UFunc_Nin1_Nout1[L['sin'], L[9], None]
+sinh: _UFunc_Nin1_Nout1[L['sinh'], L[8], None]
+spacing: _UFunc_Nin1_Nout1[L['spacing'], L[4], None]
+sqrt: _UFunc_Nin1_Nout1[L['sqrt'], L[10], None]
+square: _UFunc_Nin1_Nout1[L['square'], L[18], None]
+subtract: _UFunc_Nin2_Nout1[L['subtract'], L[21], None]
+tan: _UFunc_Nin1_Nout1[L['tan'], L[8], None]
+tanh: _UFunc_Nin1_Nout1[L['tanh'], L[8], None]
+true_divide: _UFunc_Nin2_Nout1[L['true_divide'], L[11], None]
+trunc: _UFunc_Nin1_Nout1[L['trunc'], L[7], None]
+
+abs = absolute
+
+class _CopyMode(enum.Enum):
+ ALWAYS: L[True]
+ IF_NEEDED: L[False]
+ NEVER: L[2]
+
+# Warnings
+class RankWarning(UserWarning): ...
+
+_CallType = TypeVar("_CallType", bound=_ErrFunc | _SupportsWrite[str])
+
+class errstate(Generic[_CallType], ContextDecorator):
+ call: _CallType
+ kwargs: _ErrDictOptional
+
+ # Expand `**kwargs` into explicit keyword-only arguments
+ def __init__(
+ self,
+ *,
+ call: _CallType = ...,
+ all: None | _ErrKind = ...,
+ divide: None | _ErrKind = ...,
+ over: None | _ErrKind = ...,
+ under: None | _ErrKind = ...,
+ invalid: None | _ErrKind = ...,
+ ) -> None: ...
+ def __enter__(self) -> None: ...
+ def __exit__(
+ self,
+ exc_type: None | type[BaseException],
+ exc_value: None | BaseException,
+ traceback: None | TracebackType,
+ /,
+ ) -> None: ...
+
+@contextmanager
+def _no_nep50_warning() -> Generator[None, None, None]: ...
+def _get_promotion_state() -> str: ...
+def _set_promotion_state(state: str, /) -> None: ...
+
+class ndenumerate(Generic[_ScalarType]):
+ iter: flatiter[NDArray[_ScalarType]]
+ @overload
+ def __new__(
+ cls, arr: _FiniteNestedSequence[_SupportsArray[dtype[_ScalarType]]],
+ ) -> ndenumerate[_ScalarType]: ...
+ @overload
+ def __new__(cls, arr: str | _NestedSequence[str]) -> ndenumerate[str_]: ...
+ @overload
+ def __new__(cls, arr: bytes | _NestedSequence[bytes]) -> ndenumerate[bytes_]: ...
+ @overload
+ def __new__(cls, arr: bool | _NestedSequence[bool]) -> ndenumerate[bool_]: ...
+ @overload
+ def __new__(cls, arr: int | _NestedSequence[int]) -> ndenumerate[int_]: ...
+ @overload
+ def __new__(cls, arr: float | _NestedSequence[float]) -> ndenumerate[float_]: ...
+ @overload
+ def __new__(cls, arr: complex | _NestedSequence[complex]) -> ndenumerate[complex_]: ...
+ def __next__(self: ndenumerate[_ScalarType]) -> tuple[_Shape, _ScalarType]: ...
+ def __iter__(self: _T) -> _T: ...
+
+class ndindex:
+ @overload
+ def __init__(self, shape: tuple[SupportsIndex, ...], /) -> None: ...
+ @overload
+ def __init__(self, *shape: SupportsIndex) -> None: ...
+ def __iter__(self: _T) -> _T: ...
+ def __next__(self) -> _Shape: ...
+
+class DataSource:
+ def __init__(
+ self,
+ destpath: None | str | os.PathLike[str] = ...,
+ ) -> None: ...
+ def __del__(self) -> None: ...
+ def abspath(self, path: str) -> str: ...
+ def exists(self, path: str) -> bool: ...
+
+ # Whether the file-object is opened in string or bytes mode (by default)
+ # depends on the file-extension of `path`
+ def open(
+ self,
+ path: str,
+ mode: str = ...,
+ encoding: None | str = ...,
+ newline: None | str = ...,
+ ) -> IO[Any]: ...
+
+# TODO: The type of each `__next__` and `iters` return-type depends
+# on the length and dtype of `args`; we can't describe this behavior yet
+# as we lack variadics (PEP 646).
+@final
+class broadcast:
+ def __new__(cls, *args: ArrayLike) -> broadcast: ...
+ @property
+ def index(self) -> int: ...
+ @property
+ def iters(self) -> tuple[flatiter[Any], ...]: ...
+ @property
+ def nd(self) -> int: ...
+ @property
+ def ndim(self) -> int: ...
+ @property
+ def numiter(self) -> int: ...
+ @property
+ def shape(self) -> _Shape: ...
+ @property
+ def size(self) -> int: ...
+ def __next__(self) -> tuple[Any, ...]: ...
+ def __iter__(self: _T) -> _T: ...
+ def reset(self) -> None: ...
+
+@final
+class busdaycalendar:
+ def __new__(
+ cls,
+ weekmask: ArrayLike = ...,
+ holidays: ArrayLike | dt.date | _NestedSequence[dt.date] = ...,
+ ) -> busdaycalendar: ...
+ @property
+ def weekmask(self) -> NDArray[bool_]: ...
+ @property
+ def holidays(self) -> NDArray[datetime64]: ...
+
+class finfo(Generic[_FloatType]):
+ dtype: dtype[_FloatType]
+ bits: int
+ eps: _FloatType
+ epsneg: _FloatType
+ iexp: int
+ machep: int
+ max: _FloatType
+ maxexp: int
+ min: _FloatType
+ minexp: int
+ negep: int
+ nexp: int
+ nmant: int
+ precision: int
+ resolution: _FloatType
+ smallest_subnormal: _FloatType
+ @property
+ def smallest_normal(self) -> _FloatType: ...
+ @property
+ def tiny(self) -> _FloatType: ...
+ @overload
+ def __new__(
+ cls, dtype: inexact[_NBit1] | _DTypeLike[inexact[_NBit1]]
+ ) -> finfo[floating[_NBit1]]: ...
+ @overload
+ def __new__(
+ cls, dtype: complex | float | type[complex] | type[float]
+ ) -> finfo[float_]: ...
+ @overload
+ def __new__(
+ cls, dtype: str
+ ) -> finfo[floating[Any]]: ...
+
+class iinfo(Generic[_IntType]):
+ dtype: dtype[_IntType]
+ kind: str
+ bits: int
+ key: str
+ @property
+ def min(self) -> int: ...
+ @property
+ def max(self) -> int: ...
+
+ @overload
+ def __new__(cls, dtype: _IntType | _DTypeLike[_IntType]) -> iinfo[_IntType]: ...
+ @overload
+ def __new__(cls, dtype: int | type[int]) -> iinfo[int_]: ...
+ @overload
+ def __new__(cls, dtype: str) -> iinfo[Any]: ...
+
+class format_parser:
+ dtype: dtype[void]
+ def __init__(
+ self,
+ formats: DTypeLike,
+ names: None | str | Sequence[str],
+ titles: None | str | Sequence[str],
+ aligned: bool = ...,
+ byteorder: None | _ByteOrder = ...,
+ ) -> None: ...
+
+class recarray(ndarray[_ShapeType, _DType_co]):
+ # NOTE: While not strictly mandatory, we're demanding here that arguments
+ # for the `format_parser`- and `dtype`-based dtype constructors are
+ # mutually exclusive
+ @overload
+ def __new__(
+ subtype,
+ shape: _ShapeLike,
+ dtype: None = ...,
+ buf: None | _SupportsBuffer = ...,
+ offset: SupportsIndex = ...,
+ strides: None | _ShapeLike = ...,
+ *,
+ formats: DTypeLike,
+ names: None | str | Sequence[str] = ...,
+ titles: None | str | Sequence[str] = ...,
+ byteorder: None | _ByteOrder = ...,
+ aligned: bool = ...,
+ order: _OrderKACF = ...,
+ ) -> recarray[Any, dtype[record]]: ...
+ @overload
+ def __new__(
+ subtype,
+ shape: _ShapeLike,
+ dtype: DTypeLike,
+ buf: None | _SupportsBuffer = ...,
+ offset: SupportsIndex = ...,
+ strides: None | _ShapeLike = ...,
+ formats: None = ...,
+ names: None = ...,
+ titles: None = ...,
+ byteorder: None = ...,
+ aligned: L[False] = ...,
+ order: _OrderKACF = ...,
+ ) -> recarray[Any, dtype[Any]]: ...
+ def __array_finalize__(self, obj: object) -> None: ...
+ def __getattribute__(self, attr: str) -> Any: ...
+ def __setattr__(self, attr: str, val: ArrayLike) -> None: ...
+ @overload
+ def __getitem__(self, indx: (
+ SupportsIndex
+ | _ArrayLikeInt_co
+ | tuple[SupportsIndex | _ArrayLikeInt_co, ...]
+ )) -> Any: ...
+ @overload
+ def __getitem__(self: recarray[Any, dtype[void]], indx: (
+ None
+ | slice
+ | ellipsis
+ | SupportsIndex
+ | _ArrayLikeInt_co
+ | tuple[None | slice | ellipsis | _ArrayLikeInt_co | SupportsIndex, ...]
+ )) -> recarray[Any, _DType_co]: ...
+ @overload
+ def __getitem__(self, indx: (
+ None
+ | slice
+ | ellipsis
+ | SupportsIndex
+ | _ArrayLikeInt_co
+ | tuple[None | slice | ellipsis | _ArrayLikeInt_co | SupportsIndex, ...]
+ )) -> ndarray[Any, _DType_co]: ...
+ @overload
+ def __getitem__(self, indx: str) -> NDArray[Any]: ...
+ @overload
+ def __getitem__(self, indx: list[str]) -> recarray[_ShapeType, dtype[record]]: ...
+ @overload
+ def field(self, attr: int | str, val: None = ...) -> Any: ...
+ @overload
+ def field(self, attr: int | str, val: ArrayLike) -> None: ...
+
+class record(void):
+ def __getattribute__(self, attr: str) -> Any: ...
+ def __setattr__(self, attr: str, val: ArrayLike) -> None: ...
+ def pprint(self) -> str: ...
+ @overload
+ def __getitem__(self, key: str | SupportsIndex) -> Any: ...
+ @overload
+ def __getitem__(self, key: list[str]) -> record: ...
+
+_NDIterFlagsKind = L[
+ "buffered",
+ "c_index",
+ "copy_if_overlap",
+ "common_dtype",
+ "delay_bufalloc",
+ "external_loop",
+ "f_index",
+ "grow_inner", "growinner",
+ "multi_index",
+ "ranged",
+ "refs_ok",
+ "reduce_ok",
+ "zerosize_ok",
+]
+
+_NDIterOpFlagsKind = L[
+ "aligned",
+ "allocate",
+ "arraymask",
+ "copy",
+ "config",
+ "nbo",
+ "no_subtype",
+ "no_broadcast",
+ "overlap_assume_elementwise",
+ "readonly",
+ "readwrite",
+ "updateifcopy",
+ "virtual",
+ "writeonly",
+ "writemasked"
+]
+
+@final
+class nditer:
+ def __new__(
+ cls,
+ op: ArrayLike | Sequence[ArrayLike],
+ flags: None | Sequence[_NDIterFlagsKind] = ...,
+ op_flags: None | Sequence[Sequence[_NDIterOpFlagsKind]] = ...,
+ op_dtypes: DTypeLike | Sequence[DTypeLike] = ...,
+ order: _OrderKACF = ...,
+ casting: _CastingKind = ...,
+ op_axes: None | Sequence[Sequence[SupportsIndex]] = ...,
+ itershape: None | _ShapeLike = ...,
+ buffersize: SupportsIndex = ...,
+ ) -> nditer: ...
+ def __enter__(self) -> nditer: ...
+ def __exit__(
+ self,
+ exc_type: None | type[BaseException],
+ exc_value: None | BaseException,
+ traceback: None | TracebackType,
+ ) -> None: ...
+ def __iter__(self) -> nditer: ...
+ def __next__(self) -> tuple[NDArray[Any], ...]: ...
+ def __len__(self) -> int: ...
+ def __copy__(self) -> nditer: ...
+ @overload
+ def __getitem__(self, index: SupportsIndex) -> NDArray[Any]: ...
+ @overload
+ def __getitem__(self, index: slice) -> tuple[NDArray[Any], ...]: ...
+ def __setitem__(self, index: slice | SupportsIndex, value: ArrayLike) -> None: ...
+ def close(self) -> None: ...
+ def copy(self) -> nditer: ...
+ def debug_print(self) -> None: ...
+ def enable_external_loop(self) -> None: ...
+ def iternext(self) -> bool: ...
+ def remove_axis(self, i: SupportsIndex, /) -> None: ...
+ def remove_multi_index(self) -> None: ...
+ def reset(self) -> None: ...
+ @property
+ def dtypes(self) -> tuple[dtype[Any], ...]: ...
+ @property
+ def finished(self) -> bool: ...
+ @property
+ def has_delayed_bufalloc(self) -> bool: ...
+ @property
+ def has_index(self) -> bool: ...
+ @property
+ def has_multi_index(self) -> bool: ...
+ @property
+ def index(self) -> int: ...
+ @property
+ def iterationneedsapi(self) -> bool: ...
+ @property
+ def iterindex(self) -> int: ...
+ @property
+ def iterrange(self) -> tuple[int, ...]: ...
+ @property
+ def itersize(self) -> int: ...
+ @property
+ def itviews(self) -> tuple[NDArray[Any], ...]: ...
+ @property
+ def multi_index(self) -> tuple[int, ...]: ...
+ @property
+ def ndim(self) -> int: ...
+ @property
+ def nop(self) -> int: ...
+ @property
+ def operands(self) -> tuple[NDArray[Any], ...]: ...
+ @property
+ def shape(self) -> tuple[int, ...]: ...
+ @property
+ def value(self) -> tuple[NDArray[Any], ...]: ...
+
+_MemMapModeKind = L[
+ "readonly", "r",
+ "copyonwrite", "c",
+ "readwrite", "r+",
+ "write", "w+",
+]
+
+class memmap(ndarray[_ShapeType, _DType_co]):
+ __array_priority__: ClassVar[float]
+ filename: str | None
+ offset: int
+ mode: str
+ @overload
+ def __new__(
+ subtype,
+ filename: str | bytes | os.PathLike[str] | os.PathLike[bytes] | _MemMapIOProtocol,
+ dtype: type[uint8] = ...,
+ mode: _MemMapModeKind = ...,
+ offset: int = ...,
+ shape: None | int | tuple[int, ...] = ...,
+ order: _OrderKACF = ...,
+ ) -> memmap[Any, dtype[uint8]]: ...
+ @overload
+ def __new__(
+ subtype,
+ filename: str | bytes | os.PathLike[str] | os.PathLike[bytes] | _MemMapIOProtocol,
+ dtype: _DTypeLike[_ScalarType],
+ mode: _MemMapModeKind = ...,
+ offset: int = ...,
+ shape: None | int | tuple[int, ...] = ...,
+ order: _OrderKACF = ...,
+ ) -> memmap[Any, dtype[_ScalarType]]: ...
+ @overload
+ def __new__(
+ subtype,
+ filename: str | bytes | os.PathLike[str] | os.PathLike[bytes] | _MemMapIOProtocol,
+ dtype: DTypeLike,
+ mode: _MemMapModeKind = ...,
+ offset: int = ...,
+ shape: None | int | tuple[int, ...] = ...,
+ order: _OrderKACF = ...,
+ ) -> memmap[Any, dtype[Any]]: ...
+ def __array_finalize__(self, obj: object) -> None: ...
+ def __array_wrap__(
+ self,
+ array: memmap[_ShapeType, _DType_co],
+ context: None | tuple[ufunc, tuple[Any, ...], int] = ...,
+ ) -> Any: ...
+ def flush(self) -> None: ...
+
+# TODO: Add a mypy plugin for managing functions whose output type is dependent
+# on the literal value of some sort of signature (e.g. `einsum` and `vectorize`)
+class vectorize:
+ pyfunc: Callable[..., Any]
+ cache: bool
+ signature: None | str
+ otypes: None | str
+ excluded: set[int | str]
+ __doc__: None | str
+ def __init__(
+ self,
+ pyfunc: Callable[..., Any],
+ otypes: None | str | Iterable[DTypeLike] = ...,
+ doc: None | str = ...,
+ excluded: None | Iterable[int | str] = ...,
+ cache: bool = ...,
+ signature: None | str = ...,
+ ) -> None: ...
+ def __call__(self, *args: Any, **kwargs: Any) -> Any: ...
+
+class poly1d:
+ @property
+ def variable(self) -> str: ...
+ @property
+ def order(self) -> int: ...
+ @property
+ def o(self) -> int: ...
+ @property
+ def roots(self) -> NDArray[Any]: ...
+ @property
+ def r(self) -> NDArray[Any]: ...
+
+ @property
+ def coeffs(self) -> NDArray[Any]: ...
+ @coeffs.setter
+ def coeffs(self, value: NDArray[Any]) -> None: ...
+
+ @property
+ def c(self) -> NDArray[Any]: ...
+ @c.setter
+ def c(self, value: NDArray[Any]) -> None: ...
+
+ @property
+ def coef(self) -> NDArray[Any]: ...
+ @coef.setter
+ def coef(self, value: NDArray[Any]) -> None: ...
+
+ @property
+ def coefficients(self) -> NDArray[Any]: ...
+ @coefficients.setter
+ def coefficients(self, value: NDArray[Any]) -> None: ...
+
+ __hash__: ClassVar[None] # type: ignore
+
+ @overload
+ def __array__(self, t: None = ...) -> NDArray[Any]: ...
+ @overload
+ def __array__(self, t: _DType) -> ndarray[Any, _DType]: ...
+
+ @overload
+ def __call__(self, val: _ScalarLike_co) -> Any: ...
+ @overload
+ def __call__(self, val: poly1d) -> poly1d: ...
+ @overload
+ def __call__(self, val: ArrayLike) -> NDArray[Any]: ...
+
+ def __init__(
+ self,
+ c_or_r: ArrayLike,
+ r: bool = ...,
+ variable: None | str = ...,
+ ) -> None: ...
+ def __len__(self) -> int: ...
+ def __neg__(self) -> poly1d: ...
+ def __pos__(self) -> poly1d: ...
+ def __mul__(self, other: ArrayLike) -> poly1d: ...
+ def __rmul__(self, other: ArrayLike) -> poly1d: ...
+ def __add__(self, other: ArrayLike) -> poly1d: ...
+ def __radd__(self, other: ArrayLike) -> poly1d: ...
+ def __pow__(self, val: _FloatLike_co) -> poly1d: ... # Integral floats are accepted
+ def __sub__(self, other: ArrayLike) -> poly1d: ...
+ def __rsub__(self, other: ArrayLike) -> poly1d: ...
+ def __div__(self, other: ArrayLike) -> poly1d: ...
+ def __truediv__(self, other: ArrayLike) -> poly1d: ...
+ def __rdiv__(self, other: ArrayLike) -> poly1d: ...
+ def __rtruediv__(self, other: ArrayLike) -> poly1d: ...
+ def __getitem__(self, val: int) -> Any: ...
+ def __setitem__(self, key: int, val: Any) -> None: ...
+ def __iter__(self) -> Iterator[Any]: ...
+ def deriv(self, m: SupportsInt | SupportsIndex = ...) -> poly1d: ...
+ def integ(
+ self,
+ m: SupportsInt | SupportsIndex = ...,
+ k: None | _ArrayLikeComplex_co | _ArrayLikeObject_co = ...,
+ ) -> poly1d: ...
+
+class matrix(ndarray[_ShapeType, _DType_co]):
+ __array_priority__: ClassVar[float]
+ def __new__(
+ subtype,
+ data: ArrayLike,
+ dtype: DTypeLike = ...,
+ copy: bool = ...,
+ ) -> matrix[Any, Any]: ...
+ def __array_finalize__(self, obj: object) -> None: ...
+
+ @overload
+ def __getitem__(self, key: (
+ SupportsIndex
+ | _ArrayLikeInt_co
+ | tuple[SupportsIndex | _ArrayLikeInt_co, ...]
+ )) -> Any: ...
+ @overload
+ def __getitem__(self, key: (
+ None
+ | slice
+ | ellipsis
+ | SupportsIndex
+ | _ArrayLikeInt_co
+ | tuple[None | slice | ellipsis | _ArrayLikeInt_co | SupportsIndex, ...]
+ )) -> matrix[Any, _DType_co]: ...
+ @overload
+ def __getitem__(self: NDArray[void], key: str) -> matrix[Any, dtype[Any]]: ...
+ @overload
+ def __getitem__(self: NDArray[void], key: list[str]) -> matrix[_ShapeType, dtype[void]]: ...
+
+ def __mul__(self, other: ArrayLike) -> matrix[Any, Any]: ...
+ def __rmul__(self, other: ArrayLike) -> matrix[Any, Any]: ...
+ def __imul__(self, other: ArrayLike) -> matrix[_ShapeType, _DType_co]: ...
+ def __pow__(self, other: ArrayLike) -> matrix[Any, Any]: ...
+ def __ipow__(self, other: ArrayLike) -> matrix[_ShapeType, _DType_co]: ...
+
+ @overload
+ def sum(self, axis: None = ..., dtype: DTypeLike = ..., out: None = ...) -> Any: ...
+ @overload
+ def sum(self, axis: _ShapeLike, dtype: DTypeLike = ..., out: None = ...) -> matrix[Any, Any]: ...
+ @overload
+ def sum(self, axis: None | _ShapeLike = ..., dtype: DTypeLike = ..., out: _NdArraySubClass = ...) -> _NdArraySubClass: ...
+
+ @overload
+ def mean(self, axis: None = ..., dtype: DTypeLike = ..., out: None = ...) -> Any: ...
+ @overload
+ def mean(self, axis: _ShapeLike, dtype: DTypeLike = ..., out: None = ...) -> matrix[Any, Any]: ...
+ @overload
+ def mean(self, axis: None | _ShapeLike = ..., dtype: DTypeLike = ..., out: _NdArraySubClass = ...) -> _NdArraySubClass: ...
+
+ @overload
+ def std(self, axis: None = ..., dtype: DTypeLike = ..., out: None = ..., ddof: float = ...) -> Any: ...
+ @overload
+ def std(self, axis: _ShapeLike, dtype: DTypeLike = ..., out: None = ..., ddof: float = ...) -> matrix[Any, Any]: ...
+ @overload
+ def std(self, axis: None | _ShapeLike = ..., dtype: DTypeLike = ..., out: _NdArraySubClass = ..., ddof: float = ...) -> _NdArraySubClass: ...
+
+ @overload
+ def var(self, axis: None = ..., dtype: DTypeLike = ..., out: None = ..., ddof: float = ...) -> Any: ...
+ @overload
+ def var(self, axis: _ShapeLike, dtype: DTypeLike = ..., out: None = ..., ddof: float = ...) -> matrix[Any, Any]: ...
+ @overload
+ def var(self, axis: None | _ShapeLike = ..., dtype: DTypeLike = ..., out: _NdArraySubClass = ..., ddof: float = ...) -> _NdArraySubClass: ...
+
+ @overload
+ def prod(self, axis: None = ..., dtype: DTypeLike = ..., out: None = ...) -> Any: ...
+ @overload
+ def prod(self, axis: _ShapeLike, dtype: DTypeLike = ..., out: None = ...) -> matrix[Any, Any]: ...
+ @overload
+ def prod(self, axis: None | _ShapeLike = ..., dtype: DTypeLike = ..., out: _NdArraySubClass = ...) -> _NdArraySubClass: ...
+
+ @overload
+ def any(self, axis: None = ..., out: None = ...) -> bool_: ...
+ @overload
+ def any(self, axis: _ShapeLike, out: None = ...) -> matrix[Any, dtype[bool_]]: ...
+ @overload
+ def any(self, axis: None | _ShapeLike = ..., out: _NdArraySubClass = ...) -> _NdArraySubClass: ...
+
+ @overload
+ def all(self, axis: None = ..., out: None = ...) -> bool_: ...
+ @overload
+ def all(self, axis: _ShapeLike, out: None = ...) -> matrix[Any, dtype[bool_]]: ...
+ @overload
+ def all(self, axis: None | _ShapeLike = ..., out: _NdArraySubClass = ...) -> _NdArraySubClass: ...
+
+ @overload
+ def max(self: NDArray[_ScalarType], axis: None = ..., out: None = ...) -> _ScalarType: ...
+ @overload
+ def max(self, axis: _ShapeLike, out: None = ...) -> matrix[Any, _DType_co]: ...
+ @overload
+ def max(self, axis: None | _ShapeLike = ..., out: _NdArraySubClass = ...) -> _NdArraySubClass: ...
+
+ @overload
+ def min(self: NDArray[_ScalarType], axis: None = ..., out: None = ...) -> _ScalarType: ...
+ @overload
+ def min(self, axis: _ShapeLike, out: None = ...) -> matrix[Any, _DType_co]: ...
+ @overload
+ def min(self, axis: None | _ShapeLike = ..., out: _NdArraySubClass = ...) -> _NdArraySubClass: ...
+
+ @overload
+ def argmax(self: NDArray[_ScalarType], axis: None = ..., out: None = ...) -> intp: ...
+ @overload
+ def argmax(self, axis: _ShapeLike, out: None = ...) -> matrix[Any, dtype[intp]]: ...
+ @overload
+ def argmax(self, axis: None | _ShapeLike = ..., out: _NdArraySubClass = ...) -> _NdArraySubClass: ...
+
+ @overload
+ def argmin(self: NDArray[_ScalarType], axis: None = ..., out: None = ...) -> intp: ...
+ @overload
+ def argmin(self, axis: _ShapeLike, out: None = ...) -> matrix[Any, dtype[intp]]: ...
+ @overload
+ def argmin(self, axis: None | _ShapeLike = ..., out: _NdArraySubClass = ...) -> _NdArraySubClass: ...
+
+ @overload
+ def ptp(self: NDArray[_ScalarType], axis: None = ..., out: None = ...) -> _ScalarType: ...
+ @overload
+ def ptp(self, axis: _ShapeLike, out: None = ...) -> matrix[Any, _DType_co]: ...
+ @overload
+ def ptp(self, axis: None | _ShapeLike = ..., out: _NdArraySubClass = ...) -> _NdArraySubClass: ...
+
+ def squeeze(self, axis: None | _ShapeLike = ...) -> matrix[Any, _DType_co]: ...
+ def tolist(self: matrix[Any, dtype[_SupportsItem[_T]]]) -> list[list[_T]]: ... # type: ignore[typevar]
+ def ravel(self, order: _OrderKACF = ...) -> matrix[Any, _DType_co]: ...
+ def flatten(self, order: _OrderKACF = ...) -> matrix[Any, _DType_co]: ...
+
+ @property
+ def T(self) -> matrix[Any, _DType_co]: ...
+ @property
+ def I(self) -> matrix[Any, Any]: ...
+ @property
+ def A(self) -> ndarray[_ShapeType, _DType_co]: ...
+ @property
+ def A1(self) -> ndarray[Any, _DType_co]: ...
+ @property
+ def H(self) -> matrix[Any, _DType_co]: ...
+ def getT(self) -> matrix[Any, _DType_co]: ...
+ def getI(self) -> matrix[Any, Any]: ...
+ def getA(self) -> ndarray[_ShapeType, _DType_co]: ...
+ def getA1(self) -> ndarray[Any, _DType_co]: ...
+ def getH(self) -> matrix[Any, _DType_co]: ...
+
+_CharType = TypeVar("_CharType", str_, bytes_)
+_CharDType = TypeVar("_CharDType", dtype[str_], dtype[bytes_])
+_CharArray = chararray[Any, dtype[_CharType]]
+
+class chararray(ndarray[_ShapeType, _CharDType]):
+ @overload
+ def __new__(
+ subtype,
+ shape: _ShapeLike,
+ itemsize: SupportsIndex | SupportsInt = ...,
+ unicode: L[False] = ...,
+ buffer: _SupportsBuffer = ...,
+ offset: SupportsIndex = ...,
+ strides: _ShapeLike = ...,
+ order: _OrderKACF = ...,
+ ) -> chararray[Any, dtype[bytes_]]: ...
+ @overload
+ def __new__(
+ subtype,
+ shape: _ShapeLike,
+ itemsize: SupportsIndex | SupportsInt = ...,
+ unicode: L[True] = ...,
+ buffer: _SupportsBuffer = ...,
+ offset: SupportsIndex = ...,
+ strides: _ShapeLike = ...,
+ order: _OrderKACF = ...,
+ ) -> chararray[Any, dtype[str_]]: ...
+
+ def __array_finalize__(self, obj: object) -> None: ...
+ def __mul__(self, other: _ArrayLikeInt_co) -> chararray[Any, _CharDType]: ...
+ def __rmul__(self, other: _ArrayLikeInt_co) -> chararray[Any, _CharDType]: ...
+ def __mod__(self, i: Any) -> chararray[Any, _CharDType]: ...
+
+ @overload
+ def __eq__(
+ self: _CharArray[str_],
+ other: _ArrayLikeStr_co,
+ ) -> NDArray[bool_]: ...
+ @overload
+ def __eq__(
+ self: _CharArray[bytes_],
+ other: _ArrayLikeBytes_co,
+ ) -> NDArray[bool_]: ...
+
+ @overload
+ def __ne__(
+ self: _CharArray[str_],
+ other: _ArrayLikeStr_co,
+ ) -> NDArray[bool_]: ...
+ @overload
+ def __ne__(
+ self: _CharArray[bytes_],
+ other: _ArrayLikeBytes_co,
+ ) -> NDArray[bool_]: ...
+
+ @overload
+ def __ge__(
+ self: _CharArray[str_],
+ other: _ArrayLikeStr_co,
+ ) -> NDArray[bool_]: ...
+ @overload
+ def __ge__(
+ self: _CharArray[bytes_],
+ other: _ArrayLikeBytes_co,
+ ) -> NDArray[bool_]: ...
+
+ @overload
+ def __le__(
+ self: _CharArray[str_],
+ other: _ArrayLikeStr_co,
+ ) -> NDArray[bool_]: ...
+ @overload
+ def __le__(
+ self: _CharArray[bytes_],
+ other: _ArrayLikeBytes_co,
+ ) -> NDArray[bool_]: ...
+
+ @overload
+ def __gt__(
+ self: _CharArray[str_],
+ other: _ArrayLikeStr_co,
+ ) -> NDArray[bool_]: ...
+ @overload
+ def __gt__(
+ self: _CharArray[bytes_],
+ other: _ArrayLikeBytes_co,
+ ) -> NDArray[bool_]: ...
+
+ @overload
+ def __lt__(
+ self: _CharArray[str_],
+ other: _ArrayLikeStr_co,
+ ) -> NDArray[bool_]: ...
+ @overload
+ def __lt__(
+ self: _CharArray[bytes_],
+ other: _ArrayLikeBytes_co,
+ ) -> NDArray[bool_]: ...
+
+ @overload
+ def __add__(
+ self: _CharArray[str_],
+ other: _ArrayLikeStr_co,
+ ) -> _CharArray[str_]: ...
+ @overload
+ def __add__(
+ self: _CharArray[bytes_],
+ other: _ArrayLikeBytes_co,
+ ) -> _CharArray[bytes_]: ...
+
+ @overload
+ def __radd__(
+ self: _CharArray[str_],
+ other: _ArrayLikeStr_co,
+ ) -> _CharArray[str_]: ...
+ @overload
+ def __radd__(
+ self: _CharArray[bytes_],
+ other: _ArrayLikeBytes_co,
+ ) -> _CharArray[bytes_]: ...
+
+ @overload
+ def center(
+ self: _CharArray[str_],
+ width: _ArrayLikeInt_co,
+ fillchar: _ArrayLikeStr_co = ...,
+ ) -> _CharArray[str_]: ...
+ @overload
+ def center(
+ self: _CharArray[bytes_],
+ width: _ArrayLikeInt_co,
+ fillchar: _ArrayLikeBytes_co = ...,
+ ) -> _CharArray[bytes_]: ...
+
+ @overload
+ def count(
+ self: _CharArray[str_],
+ sub: _ArrayLikeStr_co,
+ start: _ArrayLikeInt_co = ...,
+ end: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[int_]: ...
+ @overload
+ def count(
+ self: _CharArray[bytes_],
+ sub: _ArrayLikeBytes_co,
+ start: _ArrayLikeInt_co = ...,
+ end: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[int_]: ...
+
+ def decode(
+ self: _CharArray[bytes_],
+ encoding: None | str = ...,
+ errors: None | str = ...,
+ ) -> _CharArray[str_]: ...
+
+ def encode(
+ self: _CharArray[str_],
+ encoding: None | str = ...,
+ errors: None | str = ...,
+ ) -> _CharArray[bytes_]: ...
+
+ @overload
+ def endswith(
+ self: _CharArray[str_],
+ suffix: _ArrayLikeStr_co,
+ start: _ArrayLikeInt_co = ...,
+ end: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[bool_]: ...
+ @overload
+ def endswith(
+ self: _CharArray[bytes_],
+ suffix: _ArrayLikeBytes_co,
+ start: _ArrayLikeInt_co = ...,
+ end: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[bool_]: ...
+
+ def expandtabs(
+ self,
+ tabsize: _ArrayLikeInt_co = ...,
+ ) -> chararray[Any, _CharDType]: ...
+
+ @overload
+ def find(
+ self: _CharArray[str_],
+ sub: _ArrayLikeStr_co,
+ start: _ArrayLikeInt_co = ...,
+ end: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[int_]: ...
+ @overload
+ def find(
+ self: _CharArray[bytes_],
+ sub: _ArrayLikeBytes_co,
+ start: _ArrayLikeInt_co = ...,
+ end: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[int_]: ...
+
+ @overload
+ def index(
+ self: _CharArray[str_],
+ sub: _ArrayLikeStr_co,
+ start: _ArrayLikeInt_co = ...,
+ end: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[int_]: ...
+ @overload
+ def index(
+ self: _CharArray[bytes_],
+ sub: _ArrayLikeBytes_co,
+ start: _ArrayLikeInt_co = ...,
+ end: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[int_]: ...
+
+ @overload
+ def join(
+ self: _CharArray[str_],
+ seq: _ArrayLikeStr_co,
+ ) -> _CharArray[str_]: ...
+ @overload
+ def join(
+ self: _CharArray[bytes_],
+ seq: _ArrayLikeBytes_co,
+ ) -> _CharArray[bytes_]: ...
+
+ @overload
+ def ljust(
+ self: _CharArray[str_],
+ width: _ArrayLikeInt_co,
+ fillchar: _ArrayLikeStr_co = ...,
+ ) -> _CharArray[str_]: ...
+ @overload
+ def ljust(
+ self: _CharArray[bytes_],
+ width: _ArrayLikeInt_co,
+ fillchar: _ArrayLikeBytes_co = ...,
+ ) -> _CharArray[bytes_]: ...
+
+ @overload
+ def lstrip(
+ self: _CharArray[str_],
+ chars: None | _ArrayLikeStr_co = ...,
+ ) -> _CharArray[str_]: ...
+ @overload
+ def lstrip(
+ self: _CharArray[bytes_],
+ chars: None | _ArrayLikeBytes_co = ...,
+ ) -> _CharArray[bytes_]: ...
+
+ @overload
+ def partition(
+ self: _CharArray[str_],
+ sep: _ArrayLikeStr_co,
+ ) -> _CharArray[str_]: ...
+ @overload
+ def partition(
+ self: _CharArray[bytes_],
+ sep: _ArrayLikeBytes_co,
+ ) -> _CharArray[bytes_]: ...
+
+ @overload
+ def replace(
+ self: _CharArray[str_],
+ old: _ArrayLikeStr_co,
+ new: _ArrayLikeStr_co,
+ count: None | _ArrayLikeInt_co = ...,
+ ) -> _CharArray[str_]: ...
+ @overload
+ def replace(
+ self: _CharArray[bytes_],
+ old: _ArrayLikeBytes_co,
+ new: _ArrayLikeBytes_co,
+ count: None | _ArrayLikeInt_co = ...,
+ ) -> _CharArray[bytes_]: ...
+
+ @overload
+ def rfind(
+ self: _CharArray[str_],
+ sub: _ArrayLikeStr_co,
+ start: _ArrayLikeInt_co = ...,
+ end: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[int_]: ...
+ @overload
+ def rfind(
+ self: _CharArray[bytes_],
+ sub: _ArrayLikeBytes_co,
+ start: _ArrayLikeInt_co = ...,
+ end: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[int_]: ...
+
+ @overload
+ def rindex(
+ self: _CharArray[str_],
+ sub: _ArrayLikeStr_co,
+ start: _ArrayLikeInt_co = ...,
+ end: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[int_]: ...
+ @overload
+ def rindex(
+ self: _CharArray[bytes_],
+ sub: _ArrayLikeBytes_co,
+ start: _ArrayLikeInt_co = ...,
+ end: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[int_]: ...
+
+ @overload
+ def rjust(
+ self: _CharArray[str_],
+ width: _ArrayLikeInt_co,
+ fillchar: _ArrayLikeStr_co = ...,
+ ) -> _CharArray[str_]: ...
+ @overload
+ def rjust(
+ self: _CharArray[bytes_],
+ width: _ArrayLikeInt_co,
+ fillchar: _ArrayLikeBytes_co = ...,
+ ) -> _CharArray[bytes_]: ...
+
+ @overload
+ def rpartition(
+ self: _CharArray[str_],
+ sep: _ArrayLikeStr_co,
+ ) -> _CharArray[str_]: ...
+ @overload
+ def rpartition(
+ self: _CharArray[bytes_],
+ sep: _ArrayLikeBytes_co,
+ ) -> _CharArray[bytes_]: ...
+
+ @overload
+ def rsplit(
+ self: _CharArray[str_],
+ sep: None | _ArrayLikeStr_co = ...,
+ maxsplit: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[object_]: ...
+ @overload
+ def rsplit(
+ self: _CharArray[bytes_],
+ sep: None | _ArrayLikeBytes_co = ...,
+ maxsplit: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[object_]: ...
+
+ @overload
+ def rstrip(
+ self: _CharArray[str_],
+ chars: None | _ArrayLikeStr_co = ...,
+ ) -> _CharArray[str_]: ...
+ @overload
+ def rstrip(
+ self: _CharArray[bytes_],
+ chars: None | _ArrayLikeBytes_co = ...,
+ ) -> _CharArray[bytes_]: ...
+
+ @overload
+ def split(
+ self: _CharArray[str_],
+ sep: None | _ArrayLikeStr_co = ...,
+ maxsplit: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[object_]: ...
+ @overload
+ def split(
+ self: _CharArray[bytes_],
+ sep: None | _ArrayLikeBytes_co = ...,
+ maxsplit: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[object_]: ...
+
+ def splitlines(self, keepends: None | _ArrayLikeBool_co = ...) -> NDArray[object_]: ...
+
+ @overload
+ def startswith(
+ self: _CharArray[str_],
+ prefix: _ArrayLikeStr_co,
+ start: _ArrayLikeInt_co = ...,
+ end: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[bool_]: ...
+ @overload
+ def startswith(
+ self: _CharArray[bytes_],
+ prefix: _ArrayLikeBytes_co,
+ start: _ArrayLikeInt_co = ...,
+ end: None | _ArrayLikeInt_co = ...,
+ ) -> NDArray[bool_]: ...
+
+ @overload
+ def strip(
+ self: _CharArray[str_],
+ chars: None | _ArrayLikeStr_co = ...,
+ ) -> _CharArray[str_]: ...
+ @overload
+ def strip(
+ self: _CharArray[bytes_],
+ chars: None | _ArrayLikeBytes_co = ...,
+ ) -> _CharArray[bytes_]: ...
+
+ @overload
+ def translate(
+ self: _CharArray[str_],
+ table: _ArrayLikeStr_co,
+ deletechars: None | _ArrayLikeStr_co = ...,
+ ) -> _CharArray[str_]: ...
+ @overload
+ def translate(
+ self: _CharArray[bytes_],
+ table: _ArrayLikeBytes_co,
+ deletechars: None | _ArrayLikeBytes_co = ...,
+ ) -> _CharArray[bytes_]: ...
+
+ def zfill(self, width: _ArrayLikeInt_co) -> chararray[Any, _CharDType]: ...
+ def capitalize(self) -> chararray[_ShapeType, _CharDType]: ...
+ def title(self) -> chararray[_ShapeType, _CharDType]: ...
+ def swapcase(self) -> chararray[_ShapeType, _CharDType]: ...
+ def lower(self) -> chararray[_ShapeType, _CharDType]: ...
+ def upper(self) -> chararray[_ShapeType, _CharDType]: ...
+ def isalnum(self) -> ndarray[_ShapeType, dtype[bool_]]: ...
+ def isalpha(self) -> ndarray[_ShapeType, dtype[bool_]]: ...
+ def isdigit(self) -> ndarray[_ShapeType, dtype[bool_]]: ...
+ def islower(self) -> ndarray[_ShapeType, dtype[bool_]]: ...
+ def isspace(self) -> ndarray[_ShapeType, dtype[bool_]]: ...
+ def istitle(self) -> ndarray[_ShapeType, dtype[bool_]]: ...
+ def isupper(self) -> ndarray[_ShapeType, dtype[bool_]]: ...
+ def isnumeric(self) -> ndarray[_ShapeType, dtype[bool_]]: ...
+ def isdecimal(self) -> ndarray[_ShapeType, dtype[bool_]]: ...
+
+# NOTE: Deprecated
+# class MachAr: ...
+
+class _SupportsDLPack(Protocol[_T_contra]):
+ def __dlpack__(self, *, stream: None | _T_contra = ...) -> _PyCapsule: ...
+
+def from_dlpack(obj: _SupportsDLPack[None], /) -> NDArray[Any]: ...
diff --git a/lib/python3.12/site-packages/numpy/_distributor_init.py b/lib/python3.12/site-packages/numpy/_distributor_init.py
new file mode 100644
index 0000000000000000000000000000000000000000..25b0eed79fcabe6d6ad5a7b2bf45e5371f37d4a0
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/_distributor_init.py
@@ -0,0 +1,15 @@
+""" Distributor init file
+
+Distributors: you can add custom code here to support particular distributions
+of numpy.
+
+For example, this is a good place to put any BLAS/LAPACK initialization code.
+
+The numpy standard source distribution will not put code in this file, so you
+can safely replace this file with your own version.
+"""
+
+try:
+ from . import _distributor_init_local
+except ImportError:
+ pass
diff --git a/lib/python3.12/site-packages/numpy/_globals.py b/lib/python3.12/site-packages/numpy/_globals.py
new file mode 100644
index 0000000000000000000000000000000000000000..416a20f5e11b14b1da34e2bfb45c7961edc9097c
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/_globals.py
@@ -0,0 +1,95 @@
+"""
+Module defining global singleton classes.
+
+This module raises a RuntimeError if an attempt to reload it is made. In that
+way the identities of the classes defined here are fixed and will remain so
+even if numpy itself is reloaded. In particular, a function like the following
+will still work correctly after numpy is reloaded::
+
+ def foo(arg=np._NoValue):
+ if arg is np._NoValue:
+ ...
+
+That was not the case when the singleton classes were defined in the numpy
+``__init__.py`` file. See gh-7844 for a discussion of the reload problem that
+motivated this module.
+
+"""
+import enum
+
+from ._utils import set_module as _set_module
+
+__all__ = ['_NoValue', '_CopyMode']
+
+
+# Disallow reloading this module so as to preserve the identities of the
+# classes defined here.
+if '_is_loaded' in globals():
+ raise RuntimeError('Reloading numpy._globals is not allowed')
+_is_loaded = True
+
+
+class _NoValueType:
+ """Special keyword value.
+
+ The instance of this class may be used as the default value assigned to a
+ keyword if no other obvious default (e.g., `None`) is suitable,
+
+ Common reasons for using this keyword are:
+
+ - A new keyword is added to a function, and that function forwards its
+ inputs to another function or method which can be defined outside of
+ NumPy. For example, ``np.std(x)`` calls ``x.std``, so when a ``keepdims``
+ keyword was added that could only be forwarded if the user explicitly
+ specified ``keepdims``; downstream array libraries may not have added
+ the same keyword, so adding ``x.std(..., keepdims=keepdims)``
+ unconditionally could have broken previously working code.
+ - A keyword is being deprecated, and a deprecation warning must only be
+ emitted when the keyword is used.
+
+ """
+ __instance = None
+ def __new__(cls):
+ # ensure that only one instance exists
+ if not cls.__instance:
+ cls.__instance = super().__new__(cls)
+ return cls.__instance
+
+ def __repr__(self):
+ return ""
+
+
+_NoValue = _NoValueType()
+
+
+@_set_module("numpy")
+class _CopyMode(enum.Enum):
+ """
+ An enumeration for the copy modes supported
+ by numpy.copy() and numpy.array(). The following three modes are supported,
+
+ - ALWAYS: This means that a deep copy of the input
+ array will always be taken.
+ - IF_NEEDED: This means that a deep copy of the input
+ array will be taken only if necessary.
+ - NEVER: This means that the deep copy will never be taken.
+ If a copy cannot be avoided then a `ValueError` will be
+ raised.
+
+ Note that the buffer-protocol could in theory do copies. NumPy currently
+ assumes an object exporting the buffer protocol will never do this.
+ """
+
+ ALWAYS = True
+ IF_NEEDED = False
+ NEVER = 2
+
+ def __bool__(self):
+ # For backwards compatibility
+ if self == _CopyMode.ALWAYS:
+ return True
+
+ if self == _CopyMode.IF_NEEDED:
+ return False
+
+ raise ValueError(f"{self} is neither True nor False.")
diff --git a/lib/python3.12/site-packages/numpy/_pytesttester.py b/lib/python3.12/site-packages/numpy/_pytesttester.py
new file mode 100644
index 0000000000000000000000000000000000000000..1c38291ae3319a08bb665fe5c86dfa13e1655a4c
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/_pytesttester.py
@@ -0,0 +1,207 @@
+"""
+Pytest test running.
+
+This module implements the ``test()`` function for NumPy modules. The usual
+boiler plate for doing that is to put the following in the module
+``__init__.py`` file::
+
+ from numpy._pytesttester import PytestTester
+ test = PytestTester(__name__)
+ del PytestTester
+
+
+Warnings filtering and other runtime settings should be dealt with in the
+``pytest.ini`` file in the numpy repo root. The behavior of the test depends on
+whether or not that file is found as follows:
+
+* ``pytest.ini`` is present (develop mode)
+ All warnings except those explicitly filtered out are raised as error.
+* ``pytest.ini`` is absent (release mode)
+ DeprecationWarnings and PendingDeprecationWarnings are ignored, other
+ warnings are passed through.
+
+In practice, tests run from the numpy repo are run in develop mode. That
+includes the standard ``python runtests.py`` invocation.
+
+This module is imported by every numpy subpackage, so lies at the top level to
+simplify circular import issues. For the same reason, it contains no numpy
+imports at module scope, instead importing numpy within function calls.
+"""
+import sys
+import os
+
+__all__ = ['PytestTester']
+
+
+def _show_numpy_info():
+ import numpy as np
+
+ print("NumPy version %s" % np.__version__)
+ relaxed_strides = np.ones((10, 1), order="C").flags.f_contiguous
+ print("NumPy relaxed strides checking option:", relaxed_strides)
+ info = np.lib.utils._opt_info()
+ print("NumPy CPU features: ", (info if info else 'nothing enabled'))
+
+
+class PytestTester:
+ """
+ Pytest test runner.
+
+ A test function is typically added to a package's __init__.py like so::
+
+ from numpy._pytesttester import PytestTester
+ test = PytestTester(__name__).test
+ del PytestTester
+
+ Calling this test function finds and runs all tests associated with the
+ module and all its sub-modules.
+
+ Attributes
+ ----------
+ module_name : str
+ Full path to the package to test.
+
+ Parameters
+ ----------
+ module_name : module name
+ The name of the module to test.
+
+ Notes
+ -----
+ Unlike the previous ``nose``-based implementation, this class is not
+ publicly exposed as it performs some ``numpy``-specific warning
+ suppression.
+
+ """
+ def __init__(self, module_name):
+ self.module_name = module_name
+
+ def __call__(self, label='fast', verbose=1, extra_argv=None,
+ doctests=False, coverage=False, durations=-1, tests=None):
+ """
+ Run tests for module using pytest.
+
+ Parameters
+ ----------
+ label : {'fast', 'full'}, optional
+ Identifies the tests to run. When set to 'fast', tests decorated
+ with `pytest.mark.slow` are skipped, when 'full', the slow marker
+ is ignored.
+ verbose : int, optional
+ Verbosity value for test outputs, in the range 1-3. Default is 1.
+ extra_argv : list, optional
+ List with any extra arguments to pass to pytests.
+ doctests : bool, optional
+ .. note:: Not supported
+ coverage : bool, optional
+ If True, report coverage of NumPy code. Default is False.
+ Requires installation of (pip) pytest-cov.
+ durations : int, optional
+ If < 0, do nothing, If 0, report time of all tests, if > 0,
+ report the time of the slowest `timer` tests. Default is -1.
+ tests : test or list of tests
+ Tests to be executed with pytest '--pyargs'
+
+ Returns
+ -------
+ result : bool
+ Return True on success, false otherwise.
+
+ Notes
+ -----
+ Each NumPy module exposes `test` in its namespace to run all tests for
+ it. For example, to run all tests for numpy.lib:
+
+ >>> np.lib.test() #doctest: +SKIP
+
+ Examples
+ --------
+ >>> result = np.lib.test() #doctest: +SKIP
+ ...
+ 1023 passed, 2 skipped, 6 deselected, 1 xfailed in 10.39 seconds
+ >>> result
+ True
+
+ """
+ import pytest
+ import warnings
+
+ module = sys.modules[self.module_name]
+ module_path = os.path.abspath(module.__path__[0])
+
+ # setup the pytest arguments
+ pytest_args = ["-l"]
+
+ # offset verbosity. The "-q" cancels a "-v".
+ pytest_args += ["-q"]
+
+ if sys.version_info < (3, 12):
+ with warnings.catch_warnings():
+ warnings.simplefilter("always")
+ # Filter out distutils cpu warnings (could be localized to
+ # distutils tests). ASV has problems with top level import,
+ # so fetch module for suppression here.
+ from numpy.distutils import cpuinfo
+
+ with warnings.catch_warnings(record=True):
+ # Ignore the warning from importing the array_api submodule. This
+ # warning is done on import, so it would break pytest collection,
+ # but importing it early here prevents the warning from being
+ # issued when it imported again.
+ import numpy.array_api
+
+ # Filter out annoying import messages. Want these in both develop and
+ # release mode.
+ pytest_args += [
+ "-W ignore:Not importing directory",
+ "-W ignore:numpy.dtype size changed",
+ "-W ignore:numpy.ufunc size changed",
+ "-W ignore::UserWarning:cpuinfo",
+ ]
+
+ # When testing matrices, ignore their PendingDeprecationWarnings
+ pytest_args += [
+ "-W ignore:the matrix subclass is not",
+ "-W ignore:Importing from numpy.matlib is",
+ ]
+
+ if doctests:
+ pytest_args += ["--doctest-modules"]
+
+ if extra_argv:
+ pytest_args += list(extra_argv)
+
+ if verbose > 1:
+ pytest_args += ["-" + "v"*(verbose - 1)]
+
+ if coverage:
+ pytest_args += ["--cov=" + module_path]
+
+ if label == "fast":
+ # not importing at the top level to avoid circular import of module
+ from numpy.testing import IS_PYPY
+ if IS_PYPY:
+ pytest_args += ["-m", "not slow and not slow_pypy"]
+ else:
+ pytest_args += ["-m", "not slow"]
+
+ elif label != "full":
+ pytest_args += ["-m", label]
+
+ if durations >= 0:
+ pytest_args += ["--durations=%s" % durations]
+
+ if tests is None:
+ tests = [self.module_name]
+
+ pytest_args += ["--pyargs"] + list(tests)
+
+ # run tests.
+ _show_numpy_info()
+
+ try:
+ code = pytest.main(pytest_args)
+ except SystemExit as exc:
+ code = exc.code
+
+ return code == 0
diff --git a/lib/python3.12/site-packages/numpy/_pytesttester.pyi b/lib/python3.12/site-packages/numpy/_pytesttester.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..67ac87b33de164c710a25110d45545e24a06d42e
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/_pytesttester.pyi
@@ -0,0 +1,18 @@
+from collections.abc import Iterable
+from typing import Literal as L
+
+__all__: list[str]
+
+class PytestTester:
+ module_name: str
+ def __init__(self, module_name: str) -> None: ...
+ def __call__(
+ self,
+ label: L["fast", "full"] = ...,
+ verbose: int = ...,
+ extra_argv: None | Iterable[str] = ...,
+ doctests: L[False] = ...,
+ coverage: bool = ...,
+ durations: int = ...,
+ tests: None | Iterable[str] = ...,
+ ) -> bool: ...
diff --git a/lib/python3.12/site-packages/numpy/conftest.py b/lib/python3.12/site-packages/numpy/conftest.py
new file mode 100644
index 0000000000000000000000000000000000000000..f1a3eda989057713f3576b60580f2d06b664873c
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/conftest.py
@@ -0,0 +1,138 @@
+"""
+Pytest configuration and fixtures for the Numpy test suite.
+"""
+import os
+import tempfile
+
+import hypothesis
+import pytest
+import numpy
+
+from numpy.core._multiarray_tests import get_fpu_mode
+
+
+_old_fpu_mode = None
+_collect_results = {}
+
+# Use a known and persistent tmpdir for hypothesis' caches, which
+# can be automatically cleared by the OS or user.
+hypothesis.configuration.set_hypothesis_home_dir(
+ os.path.join(tempfile.gettempdir(), ".hypothesis")
+)
+
+# We register two custom profiles for Numpy - for details see
+# https://hypothesis.readthedocs.io/en/latest/settings.html
+# The first is designed for our own CI runs; the latter also
+# forces determinism and is designed for use via np.test()
+hypothesis.settings.register_profile(
+ name="numpy-profile", deadline=None, print_blob=True,
+)
+hypothesis.settings.register_profile(
+ name="np.test() profile",
+ deadline=None, print_blob=True, database=None, derandomize=True,
+ suppress_health_check=list(hypothesis.HealthCheck),
+)
+# Note that the default profile is chosen based on the presence
+# of pytest.ini, but can be overridden by passing the
+# --hypothesis-profile=NAME argument to pytest.
+_pytest_ini = os.path.join(os.path.dirname(__file__), "..", "pytest.ini")
+hypothesis.settings.load_profile(
+ "numpy-profile" if os.path.isfile(_pytest_ini) else "np.test() profile"
+)
+
+# The experimentalAPI is used in _umath_tests
+os.environ["NUMPY_EXPERIMENTAL_DTYPE_API"] = "1"
+
+def pytest_configure(config):
+ config.addinivalue_line("markers",
+ "valgrind_error: Tests that are known to error under valgrind.")
+ config.addinivalue_line("markers",
+ "leaks_references: Tests that are known to leak references.")
+ config.addinivalue_line("markers",
+ "slow: Tests that are very slow.")
+ config.addinivalue_line("markers",
+ "slow_pypy: Tests that are very slow on pypy.")
+
+
+def pytest_addoption(parser):
+ parser.addoption("--available-memory", action="store", default=None,
+ help=("Set amount of memory available for running the "
+ "test suite. This can result to tests requiring "
+ "especially large amounts of memory to be skipped. "
+ "Equivalent to setting environment variable "
+ "NPY_AVAILABLE_MEM. Default: determined"
+ "automatically."))
+
+
+def pytest_sessionstart(session):
+ available_mem = session.config.getoption('available_memory')
+ if available_mem is not None:
+ os.environ['NPY_AVAILABLE_MEM'] = available_mem
+
+
+#FIXME when yield tests are gone.
+@pytest.hookimpl()
+def pytest_itemcollected(item):
+ """
+ Check FPU precision mode was not changed during test collection.
+
+ The clumsy way we do it here is mainly necessary because numpy
+ still uses yield tests, which can execute code at test collection
+ time.
+ """
+ global _old_fpu_mode
+
+ mode = get_fpu_mode()
+
+ if _old_fpu_mode is None:
+ _old_fpu_mode = mode
+ elif mode != _old_fpu_mode:
+ _collect_results[item] = (_old_fpu_mode, mode)
+ _old_fpu_mode = mode
+
+
+@pytest.fixture(scope="function", autouse=True)
+def check_fpu_mode(request):
+ """
+ Check FPU precision mode was not changed during the test.
+ """
+ old_mode = get_fpu_mode()
+ yield
+ new_mode = get_fpu_mode()
+
+ if old_mode != new_mode:
+ raise AssertionError("FPU precision mode changed from {0:#x} to {1:#x}"
+ " during the test".format(old_mode, new_mode))
+
+ collect_result = _collect_results.get(request.node)
+ if collect_result is not None:
+ old_mode, new_mode = collect_result
+ raise AssertionError("FPU precision mode changed from {0:#x} to {1:#x}"
+ " when collecting the test".format(old_mode,
+ new_mode))
+
+
+@pytest.fixture(autouse=True)
+def add_np(doctest_namespace):
+ doctest_namespace['np'] = numpy
+
+@pytest.fixture(autouse=True)
+def env_setup(monkeypatch):
+ monkeypatch.setenv('PYTHONHASHSEED', '0')
+
+
+@pytest.fixture(params=[True, False])
+def weak_promotion(request):
+ """
+ Fixture to ensure "legacy" promotion state or change it to use the new
+ weak promotion (plus warning). `old_promotion` should be used as a
+ parameter in the function.
+ """
+ state = numpy._get_promotion_state()
+ if request.param:
+ numpy._set_promotion_state("weak_and_warn")
+ else:
+ numpy._set_promotion_state("legacy")
+
+ yield request.param
+ numpy._set_promotion_state(state)
diff --git a/lib/python3.12/site-packages/numpy/ctypeslib.py b/lib/python3.12/site-packages/numpy/ctypeslib.py
new file mode 100644
index 0000000000000000000000000000000000000000..d9f64fd9e716830ff33d4d787a0492c65d517603
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/ctypeslib.py
@@ -0,0 +1,545 @@
+"""
+============================
+``ctypes`` Utility Functions
+============================
+
+See Also
+--------
+load_library : Load a C library.
+ndpointer : Array restype/argtype with verification.
+as_ctypes : Create a ctypes array from an ndarray.
+as_array : Create an ndarray from a ctypes array.
+
+References
+----------
+.. [1] "SciPy Cookbook: ctypes", https://scipy-cookbook.readthedocs.io/items/Ctypes.html
+
+Examples
+--------
+Load the C library:
+
+>>> _lib = np.ctypeslib.load_library('libmystuff', '.') #doctest: +SKIP
+
+Our result type, an ndarray that must be of type double, be 1-dimensional
+and is C-contiguous in memory:
+
+>>> array_1d_double = np.ctypeslib.ndpointer(
+... dtype=np.double,
+... ndim=1, flags='CONTIGUOUS') #doctest: +SKIP
+
+Our C-function typically takes an array and updates its values
+in-place. For example::
+
+ void foo_func(double* x, int length)
+ {
+ int i;
+ for (i = 0; i < length; i++) {
+ x[i] = i*i;
+ }
+ }
+
+We wrap it using:
+
+>>> _lib.foo_func.restype = None #doctest: +SKIP
+>>> _lib.foo_func.argtypes = [array_1d_double, c_int] #doctest: +SKIP
+
+Then, we're ready to call ``foo_func``:
+
+>>> out = np.empty(15, dtype=np.double)
+>>> _lib.foo_func(out, len(out)) #doctest: +SKIP
+
+"""
+__all__ = ['load_library', 'ndpointer', 'c_intp', 'as_ctypes', 'as_array',
+ 'as_ctypes_type']
+
+import os
+from numpy import (
+ integer, ndarray, dtype as _dtype, asarray, frombuffer
+)
+from numpy.core.multiarray import _flagdict, flagsobj
+
+try:
+ import ctypes
+except ImportError:
+ ctypes = None
+
+if ctypes is None:
+ def _dummy(*args, **kwds):
+ """
+ Dummy object that raises an ImportError if ctypes is not available.
+
+ Raises
+ ------
+ ImportError
+ If ctypes is not available.
+
+ """
+ raise ImportError("ctypes is not available.")
+ load_library = _dummy
+ as_ctypes = _dummy
+ as_array = _dummy
+ from numpy import intp as c_intp
+ _ndptr_base = object
+else:
+ import numpy.core._internal as nic
+ c_intp = nic._getintp_ctype()
+ del nic
+ _ndptr_base = ctypes.c_void_p
+
+ # Adapted from Albert Strasheim
+ def load_library(libname, loader_path):
+ """
+ It is possible to load a library using
+
+ >>> lib = ctypes.cdll[] # doctest: +SKIP
+
+ But there are cross-platform considerations, such as library file extensions,
+ plus the fact Windows will just load the first library it finds with that name.
+ NumPy supplies the load_library function as a convenience.
+
+ .. versionchanged:: 1.20.0
+ Allow libname and loader_path to take any
+ :term:`python:path-like object`.
+
+ Parameters
+ ----------
+ libname : path-like
+ Name of the library, which can have 'lib' as a prefix,
+ but without an extension.
+ loader_path : path-like
+ Where the library can be found.
+
+ Returns
+ -------
+ ctypes.cdll[libpath] : library object
+ A ctypes library object
+
+ Raises
+ ------
+ OSError
+ If there is no library with the expected extension, or the
+ library is defective and cannot be loaded.
+ """
+ # Convert path-like objects into strings
+ libname = os.fsdecode(libname)
+ loader_path = os.fsdecode(loader_path)
+
+ ext = os.path.splitext(libname)[1]
+ if not ext:
+ import sys
+ import sysconfig
+ # Try to load library with platform-specific name, otherwise
+ # default to libname.[so|dll|dylib]. Sometimes, these files are
+ # built erroneously on non-linux platforms.
+ base_ext = ".so"
+ if sys.platform.startswith("darwin"):
+ base_ext = ".dylib"
+ elif sys.platform.startswith("win"):
+ base_ext = ".dll"
+ libname_ext = [libname + base_ext]
+ so_ext = sysconfig.get_config_var("EXT_SUFFIX")
+ if not so_ext == base_ext:
+ libname_ext.insert(0, libname + so_ext)
+ else:
+ libname_ext = [libname]
+
+ loader_path = os.path.abspath(loader_path)
+ if not os.path.isdir(loader_path):
+ libdir = os.path.dirname(loader_path)
+ else:
+ libdir = loader_path
+
+ for ln in libname_ext:
+ libpath = os.path.join(libdir, ln)
+ if os.path.exists(libpath):
+ try:
+ return ctypes.cdll[libpath]
+ except OSError:
+ ## defective lib file
+ raise
+ ## if no successful return in the libname_ext loop:
+ raise OSError("no file with expected extension")
+
+
+def _num_fromflags(flaglist):
+ num = 0
+ for val in flaglist:
+ num += _flagdict[val]
+ return num
+
+_flagnames = ['C_CONTIGUOUS', 'F_CONTIGUOUS', 'ALIGNED', 'WRITEABLE',
+ 'OWNDATA', 'WRITEBACKIFCOPY']
+def _flags_fromnum(num):
+ res = []
+ for key in _flagnames:
+ value = _flagdict[key]
+ if (num & value):
+ res.append(key)
+ return res
+
+
+class _ndptr(_ndptr_base):
+ @classmethod
+ def from_param(cls, obj):
+ if not isinstance(obj, ndarray):
+ raise TypeError("argument must be an ndarray")
+ if cls._dtype_ is not None \
+ and obj.dtype != cls._dtype_:
+ raise TypeError("array must have data type %s" % cls._dtype_)
+ if cls._ndim_ is not None \
+ and obj.ndim != cls._ndim_:
+ raise TypeError("array must have %d dimension(s)" % cls._ndim_)
+ if cls._shape_ is not None \
+ and obj.shape != cls._shape_:
+ raise TypeError("array must have shape %s" % str(cls._shape_))
+ if cls._flags_ is not None \
+ and ((obj.flags.num & cls._flags_) != cls._flags_):
+ raise TypeError("array must have flags %s" %
+ _flags_fromnum(cls._flags_))
+ return obj.ctypes
+
+
+class _concrete_ndptr(_ndptr):
+ """
+ Like _ndptr, but with `_shape_` and `_dtype_` specified.
+
+ Notably, this means the pointer has enough information to reconstruct
+ the array, which is not generally true.
+ """
+ def _check_retval_(self):
+ """
+ This method is called when this class is used as the .restype
+ attribute for a shared-library function, to automatically wrap the
+ pointer into an array.
+ """
+ return self.contents
+
+ @property
+ def contents(self):
+ """
+ Get an ndarray viewing the data pointed to by this pointer.
+
+ This mirrors the `contents` attribute of a normal ctypes pointer
+ """
+ full_dtype = _dtype((self._dtype_, self._shape_))
+ full_ctype = ctypes.c_char * full_dtype.itemsize
+ buffer = ctypes.cast(self, ctypes.POINTER(full_ctype)).contents
+ return frombuffer(buffer, dtype=full_dtype).squeeze(axis=0)
+
+
+# Factory for an array-checking class with from_param defined for
+# use with ctypes argtypes mechanism
+_pointer_type_cache = {}
+def ndpointer(dtype=None, ndim=None, shape=None, flags=None):
+ """
+ Array-checking restype/argtypes.
+
+ An ndpointer instance is used to describe an ndarray in restypes
+ and argtypes specifications. This approach is more flexible than
+ using, for example, ``POINTER(c_double)``, since several restrictions
+ can be specified, which are verified upon calling the ctypes function.
+ These include data type, number of dimensions, shape and flags. If a
+ given array does not satisfy the specified restrictions,
+ a ``TypeError`` is raised.
+
+ Parameters
+ ----------
+ dtype : data-type, optional
+ Array data-type.
+ ndim : int, optional
+ Number of array dimensions.
+ shape : tuple of ints, optional
+ Array shape.
+ flags : str or tuple of str
+ Array flags; may be one or more of:
+
+ - C_CONTIGUOUS / C / CONTIGUOUS
+ - F_CONTIGUOUS / F / FORTRAN
+ - OWNDATA / O
+ - WRITEABLE / W
+ - ALIGNED / A
+ - WRITEBACKIFCOPY / X
+
+ Returns
+ -------
+ klass : ndpointer type object
+ A type object, which is an ``_ndtpr`` instance containing
+ dtype, ndim, shape and flags information.
+
+ Raises
+ ------
+ TypeError
+ If a given array does not satisfy the specified restrictions.
+
+ Examples
+ --------
+ >>> clib.somefunc.argtypes = [np.ctypeslib.ndpointer(dtype=np.float64,
+ ... ndim=1,
+ ... flags='C_CONTIGUOUS')]
+ ... #doctest: +SKIP
+ >>> clib.somefunc(np.array([1, 2, 3], dtype=np.float64))
+ ... #doctest: +SKIP
+
+ """
+
+ # normalize dtype to an Optional[dtype]
+ if dtype is not None:
+ dtype = _dtype(dtype)
+
+ # normalize flags to an Optional[int]
+ num = None
+ if flags is not None:
+ if isinstance(flags, str):
+ flags = flags.split(',')
+ elif isinstance(flags, (int, integer)):
+ num = flags
+ flags = _flags_fromnum(num)
+ elif isinstance(flags, flagsobj):
+ num = flags.num
+ flags = _flags_fromnum(num)
+ if num is None:
+ try:
+ flags = [x.strip().upper() for x in flags]
+ except Exception as e:
+ raise TypeError("invalid flags specification") from e
+ num = _num_fromflags(flags)
+
+ # normalize shape to an Optional[tuple]
+ if shape is not None:
+ try:
+ shape = tuple(shape)
+ except TypeError:
+ # single integer -> 1-tuple
+ shape = (shape,)
+
+ cache_key = (dtype, ndim, shape, num)
+
+ try:
+ return _pointer_type_cache[cache_key]
+ except KeyError:
+ pass
+
+ # produce a name for the new type
+ if dtype is None:
+ name = 'any'
+ elif dtype.names is not None:
+ name = str(id(dtype))
+ else:
+ name = dtype.str
+ if ndim is not None:
+ name += "_%dd" % ndim
+ if shape is not None:
+ name += "_"+"x".join(str(x) for x in shape)
+ if flags is not None:
+ name += "_"+"_".join(flags)
+
+ if dtype is not None and shape is not None:
+ base = _concrete_ndptr
+ else:
+ base = _ndptr
+
+ klass = type("ndpointer_%s"%name, (base,),
+ {"_dtype_": dtype,
+ "_shape_" : shape,
+ "_ndim_" : ndim,
+ "_flags_" : num})
+ _pointer_type_cache[cache_key] = klass
+ return klass
+
+
+if ctypes is not None:
+ def _ctype_ndarray(element_type, shape):
+ """ Create an ndarray of the given element type and shape """
+ for dim in shape[::-1]:
+ element_type = dim * element_type
+ # prevent the type name include np.ctypeslib
+ element_type.__module__ = None
+ return element_type
+
+
+ def _get_scalar_type_map():
+ """
+ Return a dictionary mapping native endian scalar dtype to ctypes types
+ """
+ ct = ctypes
+ simple_types = [
+ ct.c_byte, ct.c_short, ct.c_int, ct.c_long, ct.c_longlong,
+ ct.c_ubyte, ct.c_ushort, ct.c_uint, ct.c_ulong, ct.c_ulonglong,
+ ct.c_float, ct.c_double,
+ ct.c_bool,
+ ]
+ return {_dtype(ctype): ctype for ctype in simple_types}
+
+
+ _scalar_type_map = _get_scalar_type_map()
+
+
+ def _ctype_from_dtype_scalar(dtype):
+ # swapping twice ensure that `=` is promoted to <, >, or |
+ dtype_with_endian = dtype.newbyteorder('S').newbyteorder('S')
+ dtype_native = dtype.newbyteorder('=')
+ try:
+ ctype = _scalar_type_map[dtype_native]
+ except KeyError as e:
+ raise NotImplementedError(
+ "Converting {!r} to a ctypes type".format(dtype)
+ ) from None
+
+ if dtype_with_endian.byteorder == '>':
+ ctype = ctype.__ctype_be__
+ elif dtype_with_endian.byteorder == '<':
+ ctype = ctype.__ctype_le__
+
+ return ctype
+
+
+ def _ctype_from_dtype_subarray(dtype):
+ element_dtype, shape = dtype.subdtype
+ ctype = _ctype_from_dtype(element_dtype)
+ return _ctype_ndarray(ctype, shape)
+
+
+ def _ctype_from_dtype_structured(dtype):
+ # extract offsets of each field
+ field_data = []
+ for name in dtype.names:
+ field_dtype, offset = dtype.fields[name][:2]
+ field_data.append((offset, name, _ctype_from_dtype(field_dtype)))
+
+ # ctypes doesn't care about field order
+ field_data = sorted(field_data, key=lambda f: f[0])
+
+ if len(field_data) > 1 and all(offset == 0 for offset, name, ctype in field_data):
+ # union, if multiple fields all at address 0
+ size = 0
+ _fields_ = []
+ for offset, name, ctype in field_data:
+ _fields_.append((name, ctype))
+ size = max(size, ctypes.sizeof(ctype))
+
+ # pad to the right size
+ if dtype.itemsize != size:
+ _fields_.append(('', ctypes.c_char * dtype.itemsize))
+
+ # we inserted manual padding, so always `_pack_`
+ return type('union', (ctypes.Union,), dict(
+ _fields_=_fields_,
+ _pack_=1,
+ __module__=None,
+ ))
+ else:
+ last_offset = 0
+ _fields_ = []
+ for offset, name, ctype in field_data:
+ padding = offset - last_offset
+ if padding < 0:
+ raise NotImplementedError("Overlapping fields")
+ if padding > 0:
+ _fields_.append(('', ctypes.c_char * padding))
+
+ _fields_.append((name, ctype))
+ last_offset = offset + ctypes.sizeof(ctype)
+
+
+ padding = dtype.itemsize - last_offset
+ if padding > 0:
+ _fields_.append(('', ctypes.c_char * padding))
+
+ # we inserted manual padding, so always `_pack_`
+ return type('struct', (ctypes.Structure,), dict(
+ _fields_=_fields_,
+ _pack_=1,
+ __module__=None,
+ ))
+
+
+ def _ctype_from_dtype(dtype):
+ if dtype.fields is not None:
+ return _ctype_from_dtype_structured(dtype)
+ elif dtype.subdtype is not None:
+ return _ctype_from_dtype_subarray(dtype)
+ else:
+ return _ctype_from_dtype_scalar(dtype)
+
+
+ def as_ctypes_type(dtype):
+ r"""
+ Convert a dtype into a ctypes type.
+
+ Parameters
+ ----------
+ dtype : dtype
+ The dtype to convert
+
+ Returns
+ -------
+ ctype
+ A ctype scalar, union, array, or struct
+
+ Raises
+ ------
+ NotImplementedError
+ If the conversion is not possible
+
+ Notes
+ -----
+ This function does not losslessly round-trip in either direction.
+
+ ``np.dtype(as_ctypes_type(dt))`` will:
+
+ - insert padding fields
+ - reorder fields to be sorted by offset
+ - discard field titles
+
+ ``as_ctypes_type(np.dtype(ctype))`` will:
+
+ - discard the class names of `ctypes.Structure`\ s and
+ `ctypes.Union`\ s
+ - convert single-element `ctypes.Union`\ s into single-element
+ `ctypes.Structure`\ s
+ - insert padding fields
+
+ """
+ return _ctype_from_dtype(_dtype(dtype))
+
+
+ def as_array(obj, shape=None):
+ """
+ Create a numpy array from a ctypes array or POINTER.
+
+ The numpy array shares the memory with the ctypes object.
+
+ The shape parameter must be given if converting from a ctypes POINTER.
+ The shape parameter is ignored if converting from a ctypes array
+ """
+ if isinstance(obj, ctypes._Pointer):
+ # convert pointers to an array of the desired shape
+ if shape is None:
+ raise TypeError(
+ 'as_array() requires a shape argument when called on a '
+ 'pointer')
+ p_arr_type = ctypes.POINTER(_ctype_ndarray(obj._type_, shape))
+ obj = ctypes.cast(obj, p_arr_type).contents
+
+ return asarray(obj)
+
+
+ def as_ctypes(obj):
+ """Create and return a ctypes object from a numpy array. Actually
+ anything that exposes the __array_interface__ is accepted."""
+ ai = obj.__array_interface__
+ if ai["strides"]:
+ raise TypeError("strided arrays not supported")
+ if ai["version"] != 3:
+ raise TypeError("only __array_interface__ version 3 supported")
+ addr, readonly = ai["data"]
+ if readonly:
+ raise TypeError("readonly arrays unsupported")
+
+ # can't use `_dtype((ai["typestr"], ai["shape"]))` here, as it overflows
+ # dtype.itemsize (gh-14214)
+ ctype_scalar = as_ctypes_type(ai["typestr"])
+ result_type = _ctype_ndarray(ctype_scalar, ai["shape"])
+ result = result_type.from_address(addr)
+ result.__keep = obj
+ return result
diff --git a/lib/python3.12/site-packages/numpy/ctypeslib.pyi b/lib/python3.12/site-packages/numpy/ctypeslib.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..3edf98e143cf17e8a14fe585be75f4735b1fa6e7
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/ctypeslib.pyi
@@ -0,0 +1,251 @@
+# NOTE: Numpy's mypy plugin is used for importing the correct
+# platform-specific `ctypes._SimpleCData[int]` sub-type
+from ctypes import c_int64 as _c_intp
+
+import os
+import sys
+import ctypes
+from collections.abc import Iterable, Sequence
+from typing import (
+ Literal as L,
+ Any,
+ Union,
+ TypeVar,
+ Generic,
+ overload,
+ ClassVar,
+)
+
+from numpy import (
+ ndarray,
+ dtype,
+ generic,
+ bool_,
+ byte,
+ short,
+ intc,
+ int_,
+ longlong,
+ ubyte,
+ ushort,
+ uintc,
+ uint,
+ ulonglong,
+ single,
+ double,
+ longdouble,
+ void,
+)
+from numpy.core._internal import _ctypes
+from numpy.core.multiarray import flagsobj
+from numpy._typing import (
+ # Arrays
+ NDArray,
+ _ArrayLike,
+
+ # Shapes
+ _ShapeLike,
+
+ # DTypes
+ DTypeLike,
+ _DTypeLike,
+ _VoidDTypeLike,
+ _BoolCodes,
+ _UByteCodes,
+ _UShortCodes,
+ _UIntCCodes,
+ _UIntCodes,
+ _ULongLongCodes,
+ _ByteCodes,
+ _ShortCodes,
+ _IntCCodes,
+ _IntCodes,
+ _LongLongCodes,
+ _SingleCodes,
+ _DoubleCodes,
+ _LongDoubleCodes,
+)
+
+# TODO: Add a proper `_Shape` bound once we've got variadic typevars
+_DType = TypeVar("_DType", bound=dtype[Any])
+_DTypeOptional = TypeVar("_DTypeOptional", bound=None | dtype[Any])
+_SCT = TypeVar("_SCT", bound=generic)
+
+_FlagsKind = L[
+ 'C_CONTIGUOUS', 'CONTIGUOUS', 'C',
+ 'F_CONTIGUOUS', 'FORTRAN', 'F',
+ 'ALIGNED', 'A',
+ 'WRITEABLE', 'W',
+ 'OWNDATA', 'O',
+ 'WRITEBACKIFCOPY', 'X',
+]
+
+# TODO: Add a shape typevar once we have variadic typevars (PEP 646)
+class _ndptr(ctypes.c_void_p, Generic[_DTypeOptional]):
+ # In practice these 4 classvars are defined in the dynamic class
+ # returned by `ndpointer`
+ _dtype_: ClassVar[_DTypeOptional]
+ _shape_: ClassVar[None]
+ _ndim_: ClassVar[None | int]
+ _flags_: ClassVar[None | list[_FlagsKind]]
+
+ @overload
+ @classmethod
+ def from_param(cls: type[_ndptr[None]], obj: ndarray[Any, Any]) -> _ctypes[Any]: ...
+ @overload
+ @classmethod
+ def from_param(cls: type[_ndptr[_DType]], obj: ndarray[Any, _DType]) -> _ctypes[Any]: ...
+
+class _concrete_ndptr(_ndptr[_DType]):
+ _dtype_: ClassVar[_DType]
+ _shape_: ClassVar[tuple[int, ...]]
+ @property
+ def contents(self) -> ndarray[Any, _DType]: ...
+
+def load_library(
+ libname: str | bytes | os.PathLike[str] | os.PathLike[bytes],
+ loader_path: str | bytes | os.PathLike[str] | os.PathLike[bytes],
+) -> ctypes.CDLL: ...
+
+__all__: list[str]
+
+c_intp = _c_intp
+
+@overload
+def ndpointer(
+ dtype: None = ...,
+ ndim: int = ...,
+ shape: None | _ShapeLike = ...,
+ flags: None | _FlagsKind | Iterable[_FlagsKind] | int | flagsobj = ...,
+) -> type[_ndptr[None]]: ...
+@overload
+def ndpointer(
+ dtype: _DTypeLike[_SCT],
+ ndim: int = ...,
+ *,
+ shape: _ShapeLike,
+ flags: None | _FlagsKind | Iterable[_FlagsKind] | int | flagsobj = ...,
+) -> type[_concrete_ndptr[dtype[_SCT]]]: ...
+@overload
+def ndpointer(
+ dtype: DTypeLike,
+ ndim: int = ...,
+ *,
+ shape: _ShapeLike,
+ flags: None | _FlagsKind | Iterable[_FlagsKind] | int | flagsobj = ...,
+) -> type[_concrete_ndptr[dtype[Any]]]: ...
+@overload
+def ndpointer(
+ dtype: _DTypeLike[_SCT],
+ ndim: int = ...,
+ shape: None = ...,
+ flags: None | _FlagsKind | Iterable[_FlagsKind] | int | flagsobj = ...,
+) -> type[_ndptr[dtype[_SCT]]]: ...
+@overload
+def ndpointer(
+ dtype: DTypeLike,
+ ndim: int = ...,
+ shape: None = ...,
+ flags: None | _FlagsKind | Iterable[_FlagsKind] | int | flagsobj = ...,
+) -> type[_ndptr[dtype[Any]]]: ...
+
+@overload
+def as_ctypes_type(dtype: _BoolCodes | _DTypeLike[bool_] | type[ctypes.c_bool]) -> type[ctypes.c_bool]: ...
+@overload
+def as_ctypes_type(dtype: _ByteCodes | _DTypeLike[byte] | type[ctypes.c_byte]) -> type[ctypes.c_byte]: ...
+@overload
+def as_ctypes_type(dtype: _ShortCodes | _DTypeLike[short] | type[ctypes.c_short]) -> type[ctypes.c_short]: ...
+@overload
+def as_ctypes_type(dtype: _IntCCodes | _DTypeLike[intc] | type[ctypes.c_int]) -> type[ctypes.c_int]: ...
+@overload
+def as_ctypes_type(dtype: _IntCodes | _DTypeLike[int_] | type[int | ctypes.c_long]) -> type[ctypes.c_long]: ...
+@overload
+def as_ctypes_type(dtype: _LongLongCodes | _DTypeLike[longlong] | type[ctypes.c_longlong]) -> type[ctypes.c_longlong]: ...
+@overload
+def as_ctypes_type(dtype: _UByteCodes | _DTypeLike[ubyte] | type[ctypes.c_ubyte]) -> type[ctypes.c_ubyte]: ...
+@overload
+def as_ctypes_type(dtype: _UShortCodes | _DTypeLike[ushort] | type[ctypes.c_ushort]) -> type[ctypes.c_ushort]: ...
+@overload
+def as_ctypes_type(dtype: _UIntCCodes | _DTypeLike[uintc] | type[ctypes.c_uint]) -> type[ctypes.c_uint]: ...
+@overload
+def as_ctypes_type(dtype: _UIntCodes | _DTypeLike[uint] | type[ctypes.c_ulong]) -> type[ctypes.c_ulong]: ...
+@overload
+def as_ctypes_type(dtype: _ULongLongCodes | _DTypeLike[ulonglong] | type[ctypes.c_ulonglong]) -> type[ctypes.c_ulonglong]: ...
+@overload
+def as_ctypes_type(dtype: _SingleCodes | _DTypeLike[single] | type[ctypes.c_float]) -> type[ctypes.c_float]: ...
+@overload
+def as_ctypes_type(dtype: _DoubleCodes | _DTypeLike[double] | type[float | ctypes.c_double]) -> type[ctypes.c_double]: ...
+@overload
+def as_ctypes_type(dtype: _LongDoubleCodes | _DTypeLike[longdouble] | type[ctypes.c_longdouble]) -> type[ctypes.c_longdouble]: ...
+@overload
+def as_ctypes_type(dtype: _VoidDTypeLike) -> type[Any]: ... # `ctypes.Union` or `ctypes.Structure`
+@overload
+def as_ctypes_type(dtype: str) -> type[Any]: ...
+
+@overload
+def as_array(obj: ctypes._PointerLike, shape: Sequence[int]) -> NDArray[Any]: ...
+@overload
+def as_array(obj: _ArrayLike[_SCT], shape: None | _ShapeLike = ...) -> NDArray[_SCT]: ...
+@overload
+def as_array(obj: object, shape: None | _ShapeLike = ...) -> NDArray[Any]: ...
+
+@overload
+def as_ctypes(obj: bool_) -> ctypes.c_bool: ...
+@overload
+def as_ctypes(obj: byte) -> ctypes.c_byte: ...
+@overload
+def as_ctypes(obj: short) -> ctypes.c_short: ...
+@overload
+def as_ctypes(obj: intc) -> ctypes.c_int: ...
+@overload
+def as_ctypes(obj: int_) -> ctypes.c_long: ...
+@overload
+def as_ctypes(obj: longlong) -> ctypes.c_longlong: ...
+@overload
+def as_ctypes(obj: ubyte) -> ctypes.c_ubyte: ...
+@overload
+def as_ctypes(obj: ushort) -> ctypes.c_ushort: ...
+@overload
+def as_ctypes(obj: uintc) -> ctypes.c_uint: ...
+@overload
+def as_ctypes(obj: uint) -> ctypes.c_ulong: ...
+@overload
+def as_ctypes(obj: ulonglong) -> ctypes.c_ulonglong: ...
+@overload
+def as_ctypes(obj: single) -> ctypes.c_float: ...
+@overload
+def as_ctypes(obj: double) -> ctypes.c_double: ...
+@overload
+def as_ctypes(obj: longdouble) -> ctypes.c_longdouble: ...
+@overload
+def as_ctypes(obj: void) -> Any: ... # `ctypes.Union` or `ctypes.Structure`
+@overload
+def as_ctypes(obj: NDArray[bool_]) -> ctypes.Array[ctypes.c_bool]: ...
+@overload
+def as_ctypes(obj: NDArray[byte]) -> ctypes.Array[ctypes.c_byte]: ...
+@overload
+def as_ctypes(obj: NDArray[short]) -> ctypes.Array[ctypes.c_short]: ...
+@overload
+def as_ctypes(obj: NDArray[intc]) -> ctypes.Array[ctypes.c_int]: ...
+@overload
+def as_ctypes(obj: NDArray[int_]) -> ctypes.Array[ctypes.c_long]: ...
+@overload
+def as_ctypes(obj: NDArray[longlong]) -> ctypes.Array[ctypes.c_longlong]: ...
+@overload
+def as_ctypes(obj: NDArray[ubyte]) -> ctypes.Array[ctypes.c_ubyte]: ...
+@overload
+def as_ctypes(obj: NDArray[ushort]) -> ctypes.Array[ctypes.c_ushort]: ...
+@overload
+def as_ctypes(obj: NDArray[uintc]) -> ctypes.Array[ctypes.c_uint]: ...
+@overload
+def as_ctypes(obj: NDArray[uint]) -> ctypes.Array[ctypes.c_ulong]: ...
+@overload
+def as_ctypes(obj: NDArray[ulonglong]) -> ctypes.Array[ctypes.c_ulonglong]: ...
+@overload
+def as_ctypes(obj: NDArray[single]) -> ctypes.Array[ctypes.c_float]: ...
+@overload
+def as_ctypes(obj: NDArray[double]) -> ctypes.Array[ctypes.c_double]: ...
+@overload
+def as_ctypes(obj: NDArray[longdouble]) -> ctypes.Array[ctypes.c_longdouble]: ...
+@overload
+def as_ctypes(obj: NDArray[void]) -> ctypes.Array[Any]: ... # `ctypes.Union` or `ctypes.Structure`
diff --git a/lib/python3.12/site-packages/numpy/dtypes.py b/lib/python3.12/site-packages/numpy/dtypes.py
new file mode 100644
index 0000000000000000000000000000000000000000..068a6a1a0f5b5382a7d0c4fcc2b6cd33f989fdfa
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/dtypes.py
@@ -0,0 +1,77 @@
+"""
+DType classes and utility (:mod:`numpy.dtypes`)
+===============================================
+
+This module is home to specific dtypes related functionality and their classes.
+For more general information about dtypes, also see `numpy.dtype` and
+:ref:`arrays.dtypes`.
+
+Similar to the builtin ``types`` module, this submodule defines types (classes)
+that are not widely used directly.
+
+.. versionadded:: NumPy 1.25
+
+ The dtypes module is new in NumPy 1.25. Previously DType classes were
+ only accessible indirectly.
+
+
+DType classes
+-------------
+
+The following are the classes of the corresponding NumPy dtype instances and
+NumPy scalar types. The classes can be used in ``isinstance`` checks and can
+also be instantiated or used directly. Direct use of these classes is not
+typical, since their scalar counterparts (e.g. ``np.float64``) or strings
+like ``"float64"`` can be used.
+
+.. list-table::
+ :header-rows: 1
+
+ * - Group
+ - DType class
+
+ * - Boolean
+ - ``BoolDType``
+
+ * - Bit-sized integers
+ - ``Int8DType``, ``UInt8DType``, ``Int16DType``, ``UInt16DType``,
+ ``Int32DType``, ``UInt32DType``, ``Int64DType``, ``UInt64DType``
+
+ * - C-named integers (may be aliases)
+ - ``ByteDType``, ``UByteDType``, ``ShortDType``, ``UShortDType``,
+ ``IntDType``, ``UIntDType``, ``LongDType``, ``ULongDType``,
+ ``LongLongDType``, ``ULongLongDType``
+
+ * - Floating point
+ - ``Float16DType``, ``Float32DType``, ``Float64DType``,
+ ``LongDoubleDType``
+
+ * - Complex
+ - ``Complex64DType``, ``Complex128DType``, ``CLongDoubleDType``
+
+ * - Strings
+ - ``BytesDType``, ``BytesDType``
+
+ * - Times
+ - ``DateTime64DType``, ``TimeDelta64DType``
+
+ * - Others
+ - ``ObjectDType``, ``VoidDType``
+
+"""
+
+__all__ = []
+
+
+def _add_dtype_helper(DType, alias):
+ # Function to add DTypes a bit more conveniently without channeling them
+ # through `numpy.core._multiarray_umath` namespace or similar.
+ from numpy import dtypes
+
+ setattr(dtypes, DType.__name__, DType)
+ __all__.append(DType.__name__)
+
+ if alias:
+ alias = alias.removeprefix("numpy.dtypes.")
+ setattr(dtypes, alias, DType)
+ __all__.append(alias)
diff --git a/lib/python3.12/site-packages/numpy/dtypes.pyi b/lib/python3.12/site-packages/numpy/dtypes.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..2f7e846f23d4de0dd7caa3198e3eb4fd339ebdbe
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/dtypes.pyi
@@ -0,0 +1,43 @@
+import numpy as np
+
+
+__all__: list[str]
+
+# Boolean:
+BoolDType = np.dtype[np.bool_]
+# Sized integers:
+Int8DType = np.dtype[np.int8]
+UInt8DType = np.dtype[np.uint8]
+Int16DType = np.dtype[np.int16]
+UInt16DType = np.dtype[np.uint16]
+Int32DType = np.dtype[np.int32]
+UInt32DType = np.dtype[np.uint32]
+Int64DType = np.dtype[np.int64]
+UInt64DType = np.dtype[np.uint64]
+# Standard C-named version/alias:
+ByteDType = np.dtype[np.byte]
+UByteDType = np.dtype[np.ubyte]
+ShortDType = np.dtype[np.short]
+UShortDType = np.dtype[np.ushort]
+IntDType = np.dtype[np.intc]
+UIntDType = np.dtype[np.uintc]
+LongDType = np.dtype[np.int_] # Unfortunately, the correct scalar
+ULongDType = np.dtype[np.uint] # Unfortunately, the correct scalar
+LongLongDType = np.dtype[np.longlong]
+ULongLongDType = np.dtype[np.ulonglong]
+# Floats
+Float16DType = np.dtype[np.float16]
+Float32DType = np.dtype[np.float32]
+Float64DType = np.dtype[np.float64]
+LongDoubleDType = np.dtype[np.longdouble]
+# Complex:
+Complex64DType = np.dtype[np.complex64]
+Complex128DType = np.dtype[np.complex128]
+CLongDoubleDType = np.dtype[np.clongdouble]
+# Others:
+ObjectDType = np.dtype[np.object_]
+BytesDType = np.dtype[np.bytes_]
+StrDType = np.dtype[np.str_]
+VoidDType = np.dtype[np.void]
+DateTime64DType = np.dtype[np.datetime64]
+TimeDelta64DType = np.dtype[np.timedelta64]
diff --git a/lib/python3.12/site-packages/numpy/exceptions.py b/lib/python3.12/site-packages/numpy/exceptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..2f843810141a7c2d78de9ff75f5a0db9e592c981
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/exceptions.py
@@ -0,0 +1,231 @@
+"""
+Exceptions and Warnings (:mod:`numpy.exceptions`)
+=================================================
+
+General exceptions used by NumPy. Note that some exceptions may be module
+specific, such as linear algebra errors.
+
+.. versionadded:: NumPy 1.25
+
+ The exceptions module is new in NumPy 1.25. Older exceptions remain
+ available through the main NumPy namespace for compatibility.
+
+.. currentmodule:: numpy.exceptions
+
+Warnings
+--------
+.. autosummary::
+ :toctree: generated/
+
+ ComplexWarning Given when converting complex to real.
+ VisibleDeprecationWarning Same as a DeprecationWarning, but more visible.
+
+Exceptions
+----------
+.. autosummary::
+ :toctree: generated/
+
+ AxisError Given when an axis was invalid.
+ DTypePromotionError Given when no common dtype could be found.
+ TooHardError Error specific to `numpy.shares_memory`.
+
+"""
+
+
+__all__ = [
+ "ComplexWarning", "VisibleDeprecationWarning", "ModuleDeprecationWarning",
+ "TooHardError", "AxisError", "DTypePromotionError"]
+
+
+# Disallow reloading this module so as to preserve the identities of the
+# classes defined here.
+if '_is_loaded' in globals():
+ raise RuntimeError('Reloading numpy._globals is not allowed')
+_is_loaded = True
+
+
+class ComplexWarning(RuntimeWarning):
+ """
+ The warning raised when casting a complex dtype to a real dtype.
+
+ As implemented, casting a complex number to a real discards its imaginary
+ part, but this behavior may not be what the user actually wants.
+
+ """
+ pass
+
+
+class ModuleDeprecationWarning(DeprecationWarning):
+ """Module deprecation warning.
+
+ .. warning::
+
+ This warning should not be used, since nose testing is not relevant
+ anymore.
+
+ The nose tester turns ordinary Deprecation warnings into test failures.
+ That makes it hard to deprecate whole modules, because they get
+ imported by default. So this is a special Deprecation warning that the
+ nose tester will let pass without making tests fail.
+
+ """
+
+
+class VisibleDeprecationWarning(UserWarning):
+ """Visible deprecation warning.
+
+ By default, python will not show deprecation warnings, so this class
+ can be used when a very visible warning is helpful, for example because
+ the usage is most likely a user bug.
+
+ """
+
+
+# Exception used in shares_memory()
+class TooHardError(RuntimeError):
+ """max_work was exceeded.
+
+ This is raised whenever the maximum number of candidate solutions
+ to consider specified by the ``max_work`` parameter is exceeded.
+ Assigning a finite number to max_work may have caused the operation
+ to fail.
+
+ """
+
+ pass
+
+
+class AxisError(ValueError, IndexError):
+ """Axis supplied was invalid.
+
+ This is raised whenever an ``axis`` parameter is specified that is larger
+ than the number of array dimensions.
+ For compatibility with code written against older numpy versions, which
+ raised a mixture of `ValueError` and `IndexError` for this situation, this
+ exception subclasses both to ensure that ``except ValueError`` and
+ ``except IndexError`` statements continue to catch `AxisError`.
+
+ .. versionadded:: 1.13
+
+ Parameters
+ ----------
+ axis : int or str
+ The out of bounds axis or a custom exception message.
+ If an axis is provided, then `ndim` should be specified as well.
+ ndim : int, optional
+ The number of array dimensions.
+ msg_prefix : str, optional
+ A prefix for the exception message.
+
+ Attributes
+ ----------
+ axis : int, optional
+ The out of bounds axis or ``None`` if a custom exception
+ message was provided. This should be the axis as passed by
+ the user, before any normalization to resolve negative indices.
+
+ .. versionadded:: 1.22
+ ndim : int, optional
+ The number of array dimensions or ``None`` if a custom exception
+ message was provided.
+
+ .. versionadded:: 1.22
+
+
+ Examples
+ --------
+ >>> array_1d = np.arange(10)
+ >>> np.cumsum(array_1d, axis=1)
+ Traceback (most recent call last):
+ ...
+ numpy.exceptions.AxisError: axis 1 is out of bounds for array of dimension 1
+
+ Negative axes are preserved:
+
+ >>> np.cumsum(array_1d, axis=-2)
+ Traceback (most recent call last):
+ ...
+ numpy.exceptions.AxisError: axis -2 is out of bounds for array of dimension 1
+
+ The class constructor generally takes the axis and arrays'
+ dimensionality as arguments:
+
+ >>> print(np.AxisError(2, 1, msg_prefix='error'))
+ error: axis 2 is out of bounds for array of dimension 1
+
+ Alternatively, a custom exception message can be passed:
+
+ >>> print(np.AxisError('Custom error message'))
+ Custom error message
+
+ """
+
+ __slots__ = ("axis", "ndim", "_msg")
+
+ def __init__(self, axis, ndim=None, msg_prefix=None):
+ if ndim is msg_prefix is None:
+ # single-argument form: directly set the error message
+ self._msg = axis
+ self.axis = None
+ self.ndim = None
+ else:
+ self._msg = msg_prefix
+ self.axis = axis
+ self.ndim = ndim
+
+ def __str__(self):
+ axis = self.axis
+ ndim = self.ndim
+
+ if axis is ndim is None:
+ return self._msg
+ else:
+ msg = f"axis {axis} is out of bounds for array of dimension {ndim}"
+ if self._msg is not None:
+ msg = f"{self._msg}: {msg}"
+ return msg
+
+
+class DTypePromotionError(TypeError):
+ """Multiple DTypes could not be converted to a common one.
+
+ This exception derives from ``TypeError`` and is raised whenever dtypes
+ cannot be converted to a single common one. This can be because they
+ are of a different category/class or incompatible instances of the same
+ one (see Examples).
+
+ Notes
+ -----
+ Many functions will use promotion to find the correct result and
+ implementation. For these functions the error will typically be chained
+ with a more specific error indicating that no implementation was found
+ for the input dtypes.
+
+ Typically promotion should be considered "invalid" between the dtypes of
+ two arrays when `arr1 == arr2` can safely return all ``False`` because the
+ dtypes are fundamentally different.
+
+ Examples
+ --------
+ Datetimes and complex numbers are incompatible classes and cannot be
+ promoted:
+
+ >>> np.result_type(np.dtype("M8[s]"), np.complex128)
+ DTypePromotionError: The DType could not
+ be promoted by . This means that no common
+ DType exists for the given inputs. For example they cannot be stored in a
+ single array unless the dtype is `object`. The full list of DTypes is:
+ (, )
+
+ For example for structured dtypes, the structure can mismatch and the
+ same ``DTypePromotionError`` is given when two structured dtypes with
+ a mismatch in their number of fields is given:
+
+ >>> dtype1 = np.dtype([("field1", np.float64), ("field2", np.int64)])
+ >>> dtype2 = np.dtype([("field1", np.float64)])
+ >>> np.promote_types(dtype1, dtype2)
+ DTypePromotionError: field names `('field1', 'field2')` and `('field1',)`
+ mismatch.
+
+ """
+ pass
diff --git a/lib/python3.12/site-packages/numpy/exceptions.pyi b/lib/python3.12/site-packages/numpy/exceptions.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..c76a0946b97b088c9f0c431eb559b5a3c86a4f6b
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/exceptions.pyi
@@ -0,0 +1,18 @@
+from typing import overload
+
+__all__: list[str]
+
+class ComplexWarning(RuntimeWarning): ...
+class ModuleDeprecationWarning(DeprecationWarning): ...
+class VisibleDeprecationWarning(UserWarning): ...
+class TooHardError(RuntimeError): ...
+class DTypePromotionError(TypeError): ...
+
+class AxisError(ValueError, IndexError):
+ axis: None | int
+ ndim: None | int
+ @overload
+ def __init__(self, axis: str, ndim: None = ..., msg_prefix: None = ...) -> None: ...
+ @overload
+ def __init__(self, axis: int, ndim: int, msg_prefix: None | str = ...) -> None: ...
+ def __str__(self) -> str: ...
diff --git a/lib/python3.12/site-packages/numpy/matlib.py b/lib/python3.12/site-packages/numpy/matlib.py
new file mode 100644
index 0000000000000000000000000000000000000000..e929fd9b1885f208afb6301f19cc21511adc098b
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/matlib.py
@@ -0,0 +1,378 @@
+import warnings
+
+# 2018-05-29, PendingDeprecationWarning added to matrix.__new__
+# 2020-01-23, numpy 1.19.0 PendingDeprecatonWarning
+warnings.warn("Importing from numpy.matlib is deprecated since 1.19.0. "
+ "The matrix subclass is not the recommended way to represent "
+ "matrices or deal with linear algebra (see "
+ "https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html). "
+ "Please adjust your code to use regular ndarray. ",
+ PendingDeprecationWarning, stacklevel=2)
+
+import numpy as np
+from numpy.matrixlib.defmatrix import matrix, asmatrix
+# Matlib.py contains all functions in the numpy namespace with a few
+# replacements. See doc/source/reference/routines.matlib.rst for details.
+# Need * as we're copying the numpy namespace.
+from numpy import * # noqa: F403
+
+__version__ = np.__version__
+
+__all__ = np.__all__[:] # copy numpy namespace
+__all__ += ['rand', 'randn', 'repmat']
+
+def empty(shape, dtype=None, order='C'):
+ """Return a new matrix of given shape and type, without initializing entries.
+
+ Parameters
+ ----------
+ shape : int or tuple of int
+ Shape of the empty matrix.
+ dtype : data-type, optional
+ Desired output data-type.
+ order : {'C', 'F'}, optional
+ Whether to store multi-dimensional data in row-major
+ (C-style) or column-major (Fortran-style) order in
+ memory.
+
+ See Also
+ --------
+ empty_like, zeros
+
+ Notes
+ -----
+ `empty`, unlike `zeros`, does not set the matrix values to zero,
+ and may therefore be marginally faster. On the other hand, it requires
+ the user to manually set all the values in the array, and should be
+ used with caution.
+
+ Examples
+ --------
+ >>> import numpy.matlib
+ >>> np.matlib.empty((2, 2)) # filled with random data
+ matrix([[ 6.76425276e-320, 9.79033856e-307], # random
+ [ 7.39337286e-309, 3.22135945e-309]])
+ >>> np.matlib.empty((2, 2), dtype=int)
+ matrix([[ 6600475, 0], # random
+ [ 6586976, 22740995]])
+
+ """
+ return ndarray.__new__(matrix, shape, dtype, order=order)
+
+def ones(shape, dtype=None, order='C'):
+ """
+ Matrix of ones.
+
+ Return a matrix of given shape and type, filled with ones.
+
+ Parameters
+ ----------
+ shape : {sequence of ints, int}
+ Shape of the matrix
+ dtype : data-type, optional
+ The desired data-type for the matrix, default is np.float64.
+ order : {'C', 'F'}, optional
+ Whether to store matrix in C- or Fortran-contiguous order,
+ default is 'C'.
+
+ Returns
+ -------
+ out : matrix
+ Matrix of ones of given shape, dtype, and order.
+
+ See Also
+ --------
+ ones : Array of ones.
+ matlib.zeros : Zero matrix.
+
+ Notes
+ -----
+ If `shape` has length one i.e. ``(N,)``, or is a scalar ``N``,
+ `out` becomes a single row matrix of shape ``(1,N)``.
+
+ Examples
+ --------
+ >>> np.matlib.ones((2,3))
+ matrix([[1., 1., 1.],
+ [1., 1., 1.]])
+
+ >>> np.matlib.ones(2)
+ matrix([[1., 1.]])
+
+ """
+ a = ndarray.__new__(matrix, shape, dtype, order=order)
+ a.fill(1)
+ return a
+
+def zeros(shape, dtype=None, order='C'):
+ """
+ Return a matrix of given shape and type, filled with zeros.
+
+ Parameters
+ ----------
+ shape : int or sequence of ints
+ Shape of the matrix
+ dtype : data-type, optional
+ The desired data-type for the matrix, default is float.
+ order : {'C', 'F'}, optional
+ Whether to store the result in C- or Fortran-contiguous order,
+ default is 'C'.
+
+ Returns
+ -------
+ out : matrix
+ Zero matrix of given shape, dtype, and order.
+
+ See Also
+ --------
+ numpy.zeros : Equivalent array function.
+ matlib.ones : Return a matrix of ones.
+
+ Notes
+ -----
+ If `shape` has length one i.e. ``(N,)``, or is a scalar ``N``,
+ `out` becomes a single row matrix of shape ``(1,N)``.
+
+ Examples
+ --------
+ >>> import numpy.matlib
+ >>> np.matlib.zeros((2, 3))
+ matrix([[0., 0., 0.],
+ [0., 0., 0.]])
+
+ >>> np.matlib.zeros(2)
+ matrix([[0., 0.]])
+
+ """
+ a = ndarray.__new__(matrix, shape, dtype, order=order)
+ a.fill(0)
+ return a
+
+def identity(n,dtype=None):
+ """
+ Returns the square identity matrix of given size.
+
+ Parameters
+ ----------
+ n : int
+ Size of the returned identity matrix.
+ dtype : data-type, optional
+ Data-type of the output. Defaults to ``float``.
+
+ Returns
+ -------
+ out : matrix
+ `n` x `n` matrix with its main diagonal set to one,
+ and all other elements zero.
+
+ See Also
+ --------
+ numpy.identity : Equivalent array function.
+ matlib.eye : More general matrix identity function.
+
+ Examples
+ --------
+ >>> import numpy.matlib
+ >>> np.matlib.identity(3, dtype=int)
+ matrix([[1, 0, 0],
+ [0, 1, 0],
+ [0, 0, 1]])
+
+ """
+ a = array([1]+n*[0], dtype=dtype)
+ b = empty((n, n), dtype=dtype)
+ b.flat = a
+ return b
+
+def eye(n,M=None, k=0, dtype=float, order='C'):
+ """
+ Return a matrix with ones on the diagonal and zeros elsewhere.
+
+ Parameters
+ ----------
+ n : int
+ Number of rows in the output.
+ M : int, optional
+ Number of columns in the output, defaults to `n`.
+ k : int, optional
+ Index of the diagonal: 0 refers to the main diagonal,
+ a positive value refers to an upper diagonal,
+ and a negative value to a lower diagonal.
+ dtype : dtype, optional
+ Data-type of the returned matrix.
+ order : {'C', 'F'}, optional
+ Whether the output should be stored in row-major (C-style) or
+ column-major (Fortran-style) order in memory.
+
+ .. versionadded:: 1.14.0
+
+ Returns
+ -------
+ I : matrix
+ A `n` x `M` matrix where all elements are equal to zero,
+ except for the `k`-th diagonal, whose values are equal to one.
+
+ See Also
+ --------
+ numpy.eye : Equivalent array function.
+ identity : Square identity matrix.
+
+ Examples
+ --------
+ >>> import numpy.matlib
+ >>> np.matlib.eye(3, k=1, dtype=float)
+ matrix([[0., 1., 0.],
+ [0., 0., 1.],
+ [0., 0., 0.]])
+
+ """
+ return asmatrix(np.eye(n, M=M, k=k, dtype=dtype, order=order))
+
+def rand(*args):
+ """
+ Return a matrix of random values with given shape.
+
+ Create a matrix of the given shape and propagate it with
+ random samples from a uniform distribution over ``[0, 1)``.
+
+ Parameters
+ ----------
+ \\*args : Arguments
+ Shape of the output.
+ If given as N integers, each integer specifies the size of one
+ dimension.
+ If given as a tuple, this tuple gives the complete shape.
+
+ Returns
+ -------
+ out : ndarray
+ The matrix of random values with shape given by `\\*args`.
+
+ See Also
+ --------
+ randn, numpy.random.RandomState.rand
+
+ Examples
+ --------
+ >>> np.random.seed(123)
+ >>> import numpy.matlib
+ >>> np.matlib.rand(2, 3)
+ matrix([[0.69646919, 0.28613933, 0.22685145],
+ [0.55131477, 0.71946897, 0.42310646]])
+ >>> np.matlib.rand((2, 3))
+ matrix([[0.9807642 , 0.68482974, 0.4809319 ],
+ [0.39211752, 0.34317802, 0.72904971]])
+
+ If the first argument is a tuple, other arguments are ignored:
+
+ >>> np.matlib.rand((2, 3), 4)
+ matrix([[0.43857224, 0.0596779 , 0.39804426],
+ [0.73799541, 0.18249173, 0.17545176]])
+
+ """
+ if isinstance(args[0], tuple):
+ args = args[0]
+ return asmatrix(np.random.rand(*args))
+
+def randn(*args):
+ """
+ Return a random matrix with data from the "standard normal" distribution.
+
+ `randn` generates a matrix filled with random floats sampled from a
+ univariate "normal" (Gaussian) distribution of mean 0 and variance 1.
+
+ Parameters
+ ----------
+ \\*args : Arguments
+ Shape of the output.
+ If given as N integers, each integer specifies the size of one
+ dimension. If given as a tuple, this tuple gives the complete shape.
+
+ Returns
+ -------
+ Z : matrix of floats
+ A matrix of floating-point samples drawn from the standard normal
+ distribution.
+
+ See Also
+ --------
+ rand, numpy.random.RandomState.randn
+
+ Notes
+ -----
+ For random samples from the normal distribution with mean ``mu`` and
+ standard deviation ``sigma``, use::
+
+ sigma * np.matlib.randn(...) + mu
+
+ Examples
+ --------
+ >>> np.random.seed(123)
+ >>> import numpy.matlib
+ >>> np.matlib.randn(1)
+ matrix([[-1.0856306]])
+ >>> np.matlib.randn(1, 2, 3)
+ matrix([[ 0.99734545, 0.2829785 , -1.50629471],
+ [-0.57860025, 1.65143654, -2.42667924]])
+
+ Two-by-four matrix of samples from the normal distribution with
+ mean 3 and standard deviation 2.5:
+
+ >>> 2.5 * np.matlib.randn((2, 4)) + 3
+ matrix([[1.92771843, 6.16484065, 0.83314899, 1.30278462],
+ [2.76322758, 6.72847407, 1.40274501, 1.8900451 ]])
+
+ """
+ if isinstance(args[0], tuple):
+ args = args[0]
+ return asmatrix(np.random.randn(*args))
+
+def repmat(a, m, n):
+ """
+ Repeat a 0-D to 2-D array or matrix MxN times.
+
+ Parameters
+ ----------
+ a : array_like
+ The array or matrix to be repeated.
+ m, n : int
+ The number of times `a` is repeated along the first and second axes.
+
+ Returns
+ -------
+ out : ndarray
+ The result of repeating `a`.
+
+ Examples
+ --------
+ >>> import numpy.matlib
+ >>> a0 = np.array(1)
+ >>> np.matlib.repmat(a0, 2, 3)
+ array([[1, 1, 1],
+ [1, 1, 1]])
+
+ >>> a1 = np.arange(4)
+ >>> np.matlib.repmat(a1, 2, 2)
+ array([[0, 1, 2, 3, 0, 1, 2, 3],
+ [0, 1, 2, 3, 0, 1, 2, 3]])
+
+ >>> a2 = np.asmatrix(np.arange(6).reshape(2, 3))
+ >>> np.matlib.repmat(a2, 2, 3)
+ matrix([[0, 1, 2, 0, 1, 2, 0, 1, 2],
+ [3, 4, 5, 3, 4, 5, 3, 4, 5],
+ [0, 1, 2, 0, 1, 2, 0, 1, 2],
+ [3, 4, 5, 3, 4, 5, 3, 4, 5]])
+
+ """
+ a = asanyarray(a)
+ ndim = a.ndim
+ if ndim == 0:
+ origrows, origcols = (1, 1)
+ elif ndim == 1:
+ origrows, origcols = (1, a.shape[0])
+ else:
+ origrows, origcols = a.shape
+ rows = origrows * m
+ cols = origcols * n
+ c = a.reshape(1, a.size).repeat(m, 0).reshape(rows, origcols).repeat(n, 0)
+ return c.reshape(rows, cols)
diff --git a/lib/python3.12/site-packages/numpy/polynomial/__init__.py b/lib/python3.12/site-packages/numpy/polynomial/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..c4e7baf2c683e27fca27f81e72c348fe8d225089
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/__init__.py
@@ -0,0 +1,185 @@
+"""
+A sub-package for efficiently dealing with polynomials.
+
+Within the documentation for this sub-package, a "finite power series,"
+i.e., a polynomial (also referred to simply as a "series") is represented
+by a 1-D numpy array of the polynomial's coefficients, ordered from lowest
+order term to highest. For example, array([1,2,3]) represents
+``P_0 + 2*P_1 + 3*P_2``, where P_n is the n-th order basis polynomial
+applicable to the specific module in question, e.g., `polynomial` (which
+"wraps" the "standard" basis) or `chebyshev`. For optimal performance,
+all operations on polynomials, including evaluation at an argument, are
+implemented as operations on the coefficients. Additional (module-specific)
+information can be found in the docstring for the module of interest.
+
+This package provides *convenience classes* for each of six different kinds
+of polynomials:
+
+ ======================== ================
+ **Name** **Provides**
+ ======================== ================
+ `~polynomial.Polynomial` Power series
+ `~chebyshev.Chebyshev` Chebyshev series
+ `~legendre.Legendre` Legendre series
+ `~laguerre.Laguerre` Laguerre series
+ `~hermite.Hermite` Hermite series
+ `~hermite_e.HermiteE` HermiteE series
+ ======================== ================
+
+These *convenience classes* provide a consistent interface for creating,
+manipulating, and fitting data with polynomials of different bases.
+The convenience classes are the preferred interface for the `~numpy.polynomial`
+package, and are available from the ``numpy.polynomial`` namespace.
+This eliminates the need to navigate to the corresponding submodules, e.g.
+``np.polynomial.Polynomial`` or ``np.polynomial.Chebyshev`` instead of
+``np.polynomial.polynomial.Polynomial`` or
+``np.polynomial.chebyshev.Chebyshev``, respectively.
+The classes provide a more consistent and concise interface than the
+type-specific functions defined in the submodules for each type of polynomial.
+For example, to fit a Chebyshev polynomial with degree ``1`` to data given
+by arrays ``xdata`` and ``ydata``, the
+`~chebyshev.Chebyshev.fit` class method::
+
+ >>> from numpy.polynomial import Chebyshev
+ >>> c = Chebyshev.fit(xdata, ydata, deg=1)
+
+is preferred over the `chebyshev.chebfit` function from the
+``np.polynomial.chebyshev`` module::
+
+ >>> from numpy.polynomial.chebyshev import chebfit
+ >>> c = chebfit(xdata, ydata, deg=1)
+
+See :doc:`routines.polynomials.classes` for more details.
+
+Convenience Classes
+===================
+
+The following lists the various constants and methods common to all of
+the classes representing the various kinds of polynomials. In the following,
+the term ``Poly`` represents any one of the convenience classes (e.g.
+`~polynomial.Polynomial`, `~chebyshev.Chebyshev`, `~hermite.Hermite`, etc.)
+while the lowercase ``p`` represents an **instance** of a polynomial class.
+
+Constants
+---------
+
+- ``Poly.domain`` -- Default domain
+- ``Poly.window`` -- Default window
+- ``Poly.basis_name`` -- String used to represent the basis
+- ``Poly.maxpower`` -- Maximum value ``n`` such that ``p**n`` is allowed
+- ``Poly.nickname`` -- String used in printing
+
+Creation
+--------
+
+Methods for creating polynomial instances.
+
+- ``Poly.basis(degree)`` -- Basis polynomial of given degree
+- ``Poly.identity()`` -- ``p`` where ``p(x) = x`` for all ``x``
+- ``Poly.fit(x, y, deg)`` -- ``p`` of degree ``deg`` with coefficients
+ determined by the least-squares fit to the data ``x``, ``y``
+- ``Poly.fromroots(roots)`` -- ``p`` with specified roots
+- ``p.copy()`` -- Create a copy of ``p``
+
+Conversion
+----------
+
+Methods for converting a polynomial instance of one kind to another.
+
+- ``p.cast(Poly)`` -- Convert ``p`` to instance of kind ``Poly``
+- ``p.convert(Poly)`` -- Convert ``p`` to instance of kind ``Poly`` or map
+ between ``domain`` and ``window``
+
+Calculus
+--------
+- ``p.deriv()`` -- Take the derivative of ``p``
+- ``p.integ()`` -- Integrate ``p``
+
+Validation
+----------
+- ``Poly.has_samecoef(p1, p2)`` -- Check if coefficients match
+- ``Poly.has_samedomain(p1, p2)`` -- Check if domains match
+- ``Poly.has_sametype(p1, p2)`` -- Check if types match
+- ``Poly.has_samewindow(p1, p2)`` -- Check if windows match
+
+Misc
+----
+- ``p.linspace()`` -- Return ``x, p(x)`` at equally-spaced points in ``domain``
+- ``p.mapparms()`` -- Return the parameters for the linear mapping between
+ ``domain`` and ``window``.
+- ``p.roots()`` -- Return the roots of `p`.
+- ``p.trim()`` -- Remove trailing coefficients.
+- ``p.cutdeg(degree)`` -- Truncate p to given degree
+- ``p.truncate(size)`` -- Truncate p to given size
+
+"""
+from .polynomial import Polynomial
+from .chebyshev import Chebyshev
+from .legendre import Legendre
+from .hermite import Hermite
+from .hermite_e import HermiteE
+from .laguerre import Laguerre
+
+__all__ = [
+ "set_default_printstyle",
+ "polynomial", "Polynomial",
+ "chebyshev", "Chebyshev",
+ "legendre", "Legendre",
+ "hermite", "Hermite",
+ "hermite_e", "HermiteE",
+ "laguerre", "Laguerre",
+]
+
+
+def set_default_printstyle(style):
+ """
+ Set the default format for the string representation of polynomials.
+
+ Values for ``style`` must be valid inputs to ``__format__``, i.e. 'ascii'
+ or 'unicode'.
+
+ Parameters
+ ----------
+ style : str
+ Format string for default printing style. Must be either 'ascii' or
+ 'unicode'.
+
+ Notes
+ -----
+ The default format depends on the platform: 'unicode' is used on
+ Unix-based systems and 'ascii' on Windows. This determination is based on
+ default font support for the unicode superscript and subscript ranges.
+
+ Examples
+ --------
+ >>> p = np.polynomial.Polynomial([1, 2, 3])
+ >>> c = np.polynomial.Chebyshev([1, 2, 3])
+ >>> np.polynomial.set_default_printstyle('unicode')
+ >>> print(p)
+ 1.0 + 2.0·x + 3.0·x²
+ >>> print(c)
+ 1.0 + 2.0·T₁(x) + 3.0·T₂(x)
+ >>> np.polynomial.set_default_printstyle('ascii')
+ >>> print(p)
+ 1.0 + 2.0 x + 3.0 x**2
+ >>> print(c)
+ 1.0 + 2.0 T_1(x) + 3.0 T_2(x)
+ >>> # Formatting supersedes all class/package-level defaults
+ >>> print(f"{p:unicode}")
+ 1.0 + 2.0·x + 3.0·x²
+ """
+ if style not in ('unicode', 'ascii'):
+ raise ValueError(
+ f"Unsupported format string '{style}'. Valid options are 'ascii' "
+ f"and 'unicode'"
+ )
+ _use_unicode = True
+ if style == 'ascii':
+ _use_unicode = False
+ from ._polybase import ABCPolyBase
+ ABCPolyBase._use_unicode = _use_unicode
+
+
+from numpy._pytesttester import PytestTester
+test = PytestTester(__name__)
+del PytestTester
diff --git a/lib/python3.12/site-packages/numpy/polynomial/__init__.pyi b/lib/python3.12/site-packages/numpy/polynomial/__init__.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..c9d1c27a96c2d8ccfeb9e378a2599c2e70003ee4
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/__init__.pyi
@@ -0,0 +1,22 @@
+from numpy._pytesttester import PytestTester
+
+from numpy.polynomial import (
+ chebyshev as chebyshev,
+ hermite as hermite,
+ hermite_e as hermite_e,
+ laguerre as laguerre,
+ legendre as legendre,
+ polynomial as polynomial,
+)
+from numpy.polynomial.chebyshev import Chebyshev as Chebyshev
+from numpy.polynomial.hermite import Hermite as Hermite
+from numpy.polynomial.hermite_e import HermiteE as HermiteE
+from numpy.polynomial.laguerre import Laguerre as Laguerre
+from numpy.polynomial.legendre import Legendre as Legendre
+from numpy.polynomial.polynomial import Polynomial as Polynomial
+
+__all__: list[str]
+__path__: list[str]
+test: PytestTester
+
+def set_default_printstyle(style): ...
diff --git a/lib/python3.12/site-packages/numpy/polynomial/_polybase.py b/lib/python3.12/site-packages/numpy/polynomial/_polybase.py
new file mode 100644
index 0000000000000000000000000000000000000000..9730574cf22e22823aaa0c77be9e630425cb2f79
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/_polybase.py
@@ -0,0 +1,1206 @@
+"""
+Abstract base class for the various polynomial Classes.
+
+The ABCPolyBase class provides the methods needed to implement the common API
+for the various polynomial classes. It operates as a mixin, but uses the
+abc module from the stdlib, hence it is only available for Python >= 2.6.
+
+"""
+import os
+import abc
+import numbers
+
+import numpy as np
+from . import polyutils as pu
+
+__all__ = ['ABCPolyBase']
+
+class ABCPolyBase(abc.ABC):
+ """An abstract base class for immutable series classes.
+
+ ABCPolyBase provides the standard Python numerical methods
+ '+', '-', '*', '//', '%', 'divmod', '**', and '()' along with the
+ methods listed below.
+
+ .. versionadded:: 1.9.0
+
+ Parameters
+ ----------
+ coef : array_like
+ Series coefficients in order of increasing degree, i.e.,
+ ``(1, 2, 3)`` gives ``1*P_0(x) + 2*P_1(x) + 3*P_2(x)``, where
+ ``P_i`` is the basis polynomials of degree ``i``.
+ domain : (2,) array_like, optional
+ Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
+ to the interval ``[window[0], window[1]]`` by shifting and scaling.
+ The default value is the derived class domain.
+ window : (2,) array_like, optional
+ Window, see domain for its use. The default value is the
+ derived class window.
+ symbol : str, optional
+ Symbol used to represent the independent variable in string
+ representations of the polynomial expression, e.g. for printing.
+ The symbol must be a valid Python identifier. Default value is 'x'.
+
+ .. versionadded:: 1.24
+
+ Attributes
+ ----------
+ coef : (N,) ndarray
+ Series coefficients in order of increasing degree.
+ domain : (2,) ndarray
+ Domain that is mapped to window.
+ window : (2,) ndarray
+ Window that domain is mapped to.
+ symbol : str
+ Symbol representing the independent variable.
+
+ Class Attributes
+ ----------------
+ maxpower : int
+ Maximum power allowed, i.e., the largest number ``n`` such that
+ ``p(x)**n`` is allowed. This is to limit runaway polynomial size.
+ domain : (2,) ndarray
+ Default domain of the class.
+ window : (2,) ndarray
+ Default window of the class.
+
+ """
+
+ # Not hashable
+ __hash__ = None
+
+ # Opt out of numpy ufuncs and Python ops with ndarray subclasses.
+ __array_ufunc__ = None
+
+ # Limit runaway size. T_n^m has degree n*m
+ maxpower = 100
+
+ # Unicode character mappings for improved __str__
+ _superscript_mapping = str.maketrans({
+ "0": "⁰",
+ "1": "¹",
+ "2": "²",
+ "3": "³",
+ "4": "⁴",
+ "5": "⁵",
+ "6": "⁶",
+ "7": "⁷",
+ "8": "⁸",
+ "9": "⁹"
+ })
+ _subscript_mapping = str.maketrans({
+ "0": "₀",
+ "1": "₁",
+ "2": "₂",
+ "3": "₃",
+ "4": "₄",
+ "5": "₅",
+ "6": "₆",
+ "7": "₇",
+ "8": "₈",
+ "9": "₉"
+ })
+ # Some fonts don't support full unicode character ranges necessary for
+ # the full set of superscripts and subscripts, including common/default
+ # fonts in Windows shells/terminals. Therefore, default to ascii-only
+ # printing on windows.
+ _use_unicode = not os.name == 'nt'
+
+ @property
+ def symbol(self):
+ return self._symbol
+
+ @property
+ @abc.abstractmethod
+ def domain(self):
+ pass
+
+ @property
+ @abc.abstractmethod
+ def window(self):
+ pass
+
+ @property
+ @abc.abstractmethod
+ def basis_name(self):
+ pass
+
+ @staticmethod
+ @abc.abstractmethod
+ def _add(c1, c2):
+ pass
+
+ @staticmethod
+ @abc.abstractmethod
+ def _sub(c1, c2):
+ pass
+
+ @staticmethod
+ @abc.abstractmethod
+ def _mul(c1, c2):
+ pass
+
+ @staticmethod
+ @abc.abstractmethod
+ def _div(c1, c2):
+ pass
+
+ @staticmethod
+ @abc.abstractmethod
+ def _pow(c, pow, maxpower=None):
+ pass
+
+ @staticmethod
+ @abc.abstractmethod
+ def _val(x, c):
+ pass
+
+ @staticmethod
+ @abc.abstractmethod
+ def _int(c, m, k, lbnd, scl):
+ pass
+
+ @staticmethod
+ @abc.abstractmethod
+ def _der(c, m, scl):
+ pass
+
+ @staticmethod
+ @abc.abstractmethod
+ def _fit(x, y, deg, rcond, full):
+ pass
+
+ @staticmethod
+ @abc.abstractmethod
+ def _line(off, scl):
+ pass
+
+ @staticmethod
+ @abc.abstractmethod
+ def _roots(c):
+ pass
+
+ @staticmethod
+ @abc.abstractmethod
+ def _fromroots(r):
+ pass
+
+ def has_samecoef(self, other):
+ """Check if coefficients match.
+
+ .. versionadded:: 1.6.0
+
+ Parameters
+ ----------
+ other : class instance
+ The other class must have the ``coef`` attribute.
+
+ Returns
+ -------
+ bool : boolean
+ True if the coefficients are the same, False otherwise.
+
+ """
+ if len(self.coef) != len(other.coef):
+ return False
+ elif not np.all(self.coef == other.coef):
+ return False
+ else:
+ return True
+
+ def has_samedomain(self, other):
+ """Check if domains match.
+
+ .. versionadded:: 1.6.0
+
+ Parameters
+ ----------
+ other : class instance
+ The other class must have the ``domain`` attribute.
+
+ Returns
+ -------
+ bool : boolean
+ True if the domains are the same, False otherwise.
+
+ """
+ return np.all(self.domain == other.domain)
+
+ def has_samewindow(self, other):
+ """Check if windows match.
+
+ .. versionadded:: 1.6.0
+
+ Parameters
+ ----------
+ other : class instance
+ The other class must have the ``window`` attribute.
+
+ Returns
+ -------
+ bool : boolean
+ True if the windows are the same, False otherwise.
+
+ """
+ return np.all(self.window == other.window)
+
+ def has_sametype(self, other):
+ """Check if types match.
+
+ .. versionadded:: 1.7.0
+
+ Parameters
+ ----------
+ other : object
+ Class instance.
+
+ Returns
+ -------
+ bool : boolean
+ True if other is same class as self
+
+ """
+ return isinstance(other, self.__class__)
+
+ def _get_coefficients(self, other):
+ """Interpret other as polynomial coefficients.
+
+ The `other` argument is checked to see if it is of the same
+ class as self with identical domain and window. If so,
+ return its coefficients, otherwise return `other`.
+
+ .. versionadded:: 1.9.0
+
+ Parameters
+ ----------
+ other : anything
+ Object to be checked.
+
+ Returns
+ -------
+ coef
+ The coefficients of`other` if it is a compatible instance,
+ of ABCPolyBase, otherwise `other`.
+
+ Raises
+ ------
+ TypeError
+ When `other` is an incompatible instance of ABCPolyBase.
+
+ """
+ if isinstance(other, ABCPolyBase):
+ if not isinstance(other, self.__class__):
+ raise TypeError("Polynomial types differ")
+ elif not np.all(self.domain == other.domain):
+ raise TypeError("Domains differ")
+ elif not np.all(self.window == other.window):
+ raise TypeError("Windows differ")
+ elif self.symbol != other.symbol:
+ raise ValueError("Polynomial symbols differ")
+ return other.coef
+ return other
+
+ def __init__(self, coef, domain=None, window=None, symbol='x'):
+ [coef] = pu.as_series([coef], trim=False)
+ self.coef = coef
+
+ if domain is not None:
+ [domain] = pu.as_series([domain], trim=False)
+ if len(domain) != 2:
+ raise ValueError("Domain has wrong number of elements.")
+ self.domain = domain
+
+ if window is not None:
+ [window] = pu.as_series([window], trim=False)
+ if len(window) != 2:
+ raise ValueError("Window has wrong number of elements.")
+ self.window = window
+
+ # Validation for symbol
+ try:
+ if not symbol.isidentifier():
+ raise ValueError(
+ "Symbol string must be a valid Python identifier"
+ )
+ # If a user passes in something other than a string, the above
+ # results in an AttributeError. Catch this and raise a more
+ # informative exception
+ except AttributeError:
+ raise TypeError("Symbol must be a non-empty string")
+
+ self._symbol = symbol
+
+ def __repr__(self):
+ coef = repr(self.coef)[6:-1]
+ domain = repr(self.domain)[6:-1]
+ window = repr(self.window)[6:-1]
+ name = self.__class__.__name__
+ return (f"{name}({coef}, domain={domain}, window={window}, "
+ f"symbol='{self.symbol}')")
+
+ def __format__(self, fmt_str):
+ if fmt_str == '':
+ return self.__str__()
+ if fmt_str not in ('ascii', 'unicode'):
+ raise ValueError(
+ f"Unsupported format string '{fmt_str}' passed to "
+ f"{self.__class__}.__format__. Valid options are "
+ f"'ascii' and 'unicode'"
+ )
+ if fmt_str == 'ascii':
+ return self._generate_string(self._str_term_ascii)
+ return self._generate_string(self._str_term_unicode)
+
+ def __str__(self):
+ if self._use_unicode:
+ return self._generate_string(self._str_term_unicode)
+ return self._generate_string(self._str_term_ascii)
+
+ def _generate_string(self, term_method):
+ """
+ Generate the full string representation of the polynomial, using
+ ``term_method`` to generate each polynomial term.
+ """
+ # Get configuration for line breaks
+ linewidth = np.get_printoptions().get('linewidth', 75)
+ if linewidth < 1:
+ linewidth = 1
+ out = pu.format_float(self.coef[0])
+ for i, coef in enumerate(self.coef[1:]):
+ out += " "
+ power = str(i + 1)
+ # Polynomial coefficient
+ # The coefficient array can be an object array with elements that
+ # will raise a TypeError with >= 0 (e.g. strings or Python
+ # complex). In this case, represent the coefficient as-is.
+ try:
+ if coef >= 0:
+ next_term = f"+ " + pu.format_float(coef, parens=True)
+ else:
+ next_term = f"- " + pu.format_float(-coef, parens=True)
+ except TypeError:
+ next_term = f"+ {coef}"
+ # Polynomial term
+ next_term += term_method(power, self.symbol)
+ # Length of the current line with next term added
+ line_len = len(out.split('\n')[-1]) + len(next_term)
+ # If not the last term in the polynomial, it will be two
+ # characters longer due to the +/- with the next term
+ if i < len(self.coef[1:]) - 1:
+ line_len += 2
+ # Handle linebreaking
+ if line_len >= linewidth:
+ next_term = next_term.replace(" ", "\n", 1)
+ out += next_term
+ return out
+
+ @classmethod
+ def _str_term_unicode(cls, i, arg_str):
+ """
+ String representation of single polynomial term using unicode
+ characters for superscripts and subscripts.
+ """
+ if cls.basis_name is None:
+ raise NotImplementedError(
+ "Subclasses must define either a basis_name, or override "
+ "_str_term_unicode(cls, i, arg_str)"
+ )
+ return (f"·{cls.basis_name}{i.translate(cls._subscript_mapping)}"
+ f"({arg_str})")
+
+ @classmethod
+ def _str_term_ascii(cls, i, arg_str):
+ """
+ String representation of a single polynomial term using ** and _ to
+ represent superscripts and subscripts, respectively.
+ """
+ if cls.basis_name is None:
+ raise NotImplementedError(
+ "Subclasses must define either a basis_name, or override "
+ "_str_term_ascii(cls, i, arg_str)"
+ )
+ return f" {cls.basis_name}_{i}({arg_str})"
+
+ @classmethod
+ def _repr_latex_term(cls, i, arg_str, needs_parens):
+ if cls.basis_name is None:
+ raise NotImplementedError(
+ "Subclasses must define either a basis name, or override "
+ "_repr_latex_term(i, arg_str, needs_parens)")
+ # since we always add parens, we don't care if the expression needs them
+ return f"{{{cls.basis_name}}}_{{{i}}}({arg_str})"
+
+ @staticmethod
+ def _repr_latex_scalar(x, parens=False):
+ # TODO: we're stuck with disabling math formatting until we handle
+ # exponents in this function
+ return r'\text{{{}}}'.format(pu.format_float(x, parens=parens))
+
+ def _repr_latex_(self):
+ # get the scaled argument string to the basis functions
+ off, scale = self.mapparms()
+ if off == 0 and scale == 1:
+ term = self.symbol
+ needs_parens = False
+ elif scale == 1:
+ term = f"{self._repr_latex_scalar(off)} + {self.symbol}"
+ needs_parens = True
+ elif off == 0:
+ term = f"{self._repr_latex_scalar(scale)}{self.symbol}"
+ needs_parens = True
+ else:
+ term = (
+ f"{self._repr_latex_scalar(off)} + "
+ f"{self._repr_latex_scalar(scale)}{self.symbol}"
+ )
+ needs_parens = True
+
+ mute = r"\color{{LightGray}}{{{}}}".format
+
+ parts = []
+ for i, c in enumerate(self.coef):
+ # prevent duplication of + and - signs
+ if i == 0:
+ coef_str = f"{self._repr_latex_scalar(c)}"
+ elif not isinstance(c, numbers.Real):
+ coef_str = f" + ({self._repr_latex_scalar(c)})"
+ elif not np.signbit(c):
+ coef_str = f" + {self._repr_latex_scalar(c, parens=True)}"
+ else:
+ coef_str = f" - {self._repr_latex_scalar(-c, parens=True)}"
+
+ # produce the string for the term
+ term_str = self._repr_latex_term(i, term, needs_parens)
+ if term_str == '1':
+ part = coef_str
+ else:
+ part = rf"{coef_str}\,{term_str}"
+
+ if c == 0:
+ part = mute(part)
+
+ parts.append(part)
+
+ if parts:
+ body = ''.join(parts)
+ else:
+ # in case somehow there are no coefficients at all
+ body = '0'
+
+ return rf"${self.symbol} \mapsto {body}$"
+
+
+
+ # Pickle and copy
+
+ def __getstate__(self):
+ ret = self.__dict__.copy()
+ ret['coef'] = self.coef.copy()
+ ret['domain'] = self.domain.copy()
+ ret['window'] = self.window.copy()
+ ret['symbol'] = self.symbol
+ return ret
+
+ def __setstate__(self, dict):
+ self.__dict__ = dict
+
+ # Call
+
+ def __call__(self, arg):
+ off, scl = pu.mapparms(self.domain, self.window)
+ arg = off + scl*arg
+ return self._val(arg, self.coef)
+
+ def __iter__(self):
+ return iter(self.coef)
+
+ def __len__(self):
+ return len(self.coef)
+
+ # Numeric properties.
+
+ def __neg__(self):
+ return self.__class__(
+ -self.coef, self.domain, self.window, self.symbol
+ )
+
+ def __pos__(self):
+ return self
+
+ def __add__(self, other):
+ othercoef = self._get_coefficients(other)
+ try:
+ coef = self._add(self.coef, othercoef)
+ except Exception:
+ return NotImplemented
+ return self.__class__(coef, self.domain, self.window, self.symbol)
+
+ def __sub__(self, other):
+ othercoef = self._get_coefficients(other)
+ try:
+ coef = self._sub(self.coef, othercoef)
+ except Exception:
+ return NotImplemented
+ return self.__class__(coef, self.domain, self.window, self.symbol)
+
+ def __mul__(self, other):
+ othercoef = self._get_coefficients(other)
+ try:
+ coef = self._mul(self.coef, othercoef)
+ except Exception:
+ return NotImplemented
+ return self.__class__(coef, self.domain, self.window, self.symbol)
+
+ def __truediv__(self, other):
+ # there is no true divide if the rhs is not a Number, although it
+ # could return the first n elements of an infinite series.
+ # It is hard to see where n would come from, though.
+ if not isinstance(other, numbers.Number) or isinstance(other, bool):
+ raise TypeError(
+ f"unsupported types for true division: "
+ f"'{type(self)}', '{type(other)}'"
+ )
+ return self.__floordiv__(other)
+
+ def __floordiv__(self, other):
+ res = self.__divmod__(other)
+ if res is NotImplemented:
+ return res
+ return res[0]
+
+ def __mod__(self, other):
+ res = self.__divmod__(other)
+ if res is NotImplemented:
+ return res
+ return res[1]
+
+ def __divmod__(self, other):
+ othercoef = self._get_coefficients(other)
+ try:
+ quo, rem = self._div(self.coef, othercoef)
+ except ZeroDivisionError:
+ raise
+ except Exception:
+ return NotImplemented
+ quo = self.__class__(quo, self.domain, self.window, self.symbol)
+ rem = self.__class__(rem, self.domain, self.window, self.symbol)
+ return quo, rem
+
+ def __pow__(self, other):
+ coef = self._pow(self.coef, other, maxpower=self.maxpower)
+ res = self.__class__(coef, self.domain, self.window, self.symbol)
+ return res
+
+ def __radd__(self, other):
+ try:
+ coef = self._add(other, self.coef)
+ except Exception:
+ return NotImplemented
+ return self.__class__(coef, self.domain, self.window, self.symbol)
+
+ def __rsub__(self, other):
+ try:
+ coef = self._sub(other, self.coef)
+ except Exception:
+ return NotImplemented
+ return self.__class__(coef, self.domain, self.window, self.symbol)
+
+ def __rmul__(self, other):
+ try:
+ coef = self._mul(other, self.coef)
+ except Exception:
+ return NotImplemented
+ return self.__class__(coef, self.domain, self.window, self.symbol)
+
+ def __rdiv__(self, other):
+ # set to __floordiv__ /.
+ return self.__rfloordiv__(other)
+
+ def __rtruediv__(self, other):
+ # An instance of ABCPolyBase is not considered a
+ # Number.
+ return NotImplemented
+
+ def __rfloordiv__(self, other):
+ res = self.__rdivmod__(other)
+ if res is NotImplemented:
+ return res
+ return res[0]
+
+ def __rmod__(self, other):
+ res = self.__rdivmod__(other)
+ if res is NotImplemented:
+ return res
+ return res[1]
+
+ def __rdivmod__(self, other):
+ try:
+ quo, rem = self._div(other, self.coef)
+ except ZeroDivisionError:
+ raise
+ except Exception:
+ return NotImplemented
+ quo = self.__class__(quo, self.domain, self.window, self.symbol)
+ rem = self.__class__(rem, self.domain, self.window, self.symbol)
+ return quo, rem
+
+ def __eq__(self, other):
+ res = (isinstance(other, self.__class__) and
+ np.all(self.domain == other.domain) and
+ np.all(self.window == other.window) and
+ (self.coef.shape == other.coef.shape) and
+ np.all(self.coef == other.coef) and
+ (self.symbol == other.symbol))
+ return res
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ #
+ # Extra methods.
+ #
+
+ def copy(self):
+ """Return a copy.
+
+ Returns
+ -------
+ new_series : series
+ Copy of self.
+
+ """
+ return self.__class__(self.coef, self.domain, self.window, self.symbol)
+
+ def degree(self):
+ """The degree of the series.
+
+ .. versionadded:: 1.5.0
+
+ Returns
+ -------
+ degree : int
+ Degree of the series, one less than the number of coefficients.
+
+ Examples
+ --------
+
+ Create a polynomial object for ``1 + 7*x + 4*x**2``:
+
+ >>> poly = np.polynomial.Polynomial([1, 7, 4])
+ >>> print(poly)
+ 1.0 + 7.0·x + 4.0·x²
+ >>> poly.degree()
+ 2
+
+ Note that this method does not check for non-zero coefficients.
+ You must trim the polynomial to remove any trailing zeroes:
+
+ >>> poly = np.polynomial.Polynomial([1, 7, 0])
+ >>> print(poly)
+ 1.0 + 7.0·x + 0.0·x²
+ >>> poly.degree()
+ 2
+ >>> poly.trim().degree()
+ 1
+
+ """
+ return len(self) - 1
+
+ def cutdeg(self, deg):
+ """Truncate series to the given degree.
+
+ Reduce the degree of the series to `deg` by discarding the
+ high order terms. If `deg` is greater than the current degree a
+ copy of the current series is returned. This can be useful in least
+ squares where the coefficients of the high degree terms may be very
+ small.
+
+ .. versionadded:: 1.5.0
+
+ Parameters
+ ----------
+ deg : non-negative int
+ The series is reduced to degree `deg` by discarding the high
+ order terms. The value of `deg` must be a non-negative integer.
+
+ Returns
+ -------
+ new_series : series
+ New instance of series with reduced degree.
+
+ """
+ return self.truncate(deg + 1)
+
+ def trim(self, tol=0):
+ """Remove trailing coefficients
+
+ Remove trailing coefficients until a coefficient is reached whose
+ absolute value greater than `tol` or the beginning of the series is
+ reached. If all the coefficients would be removed the series is set
+ to ``[0]``. A new series instance is returned with the new
+ coefficients. The current instance remains unchanged.
+
+ Parameters
+ ----------
+ tol : non-negative number.
+ All trailing coefficients less than `tol` will be removed.
+
+ Returns
+ -------
+ new_series : series
+ New instance of series with trimmed coefficients.
+
+ """
+ coef = pu.trimcoef(self.coef, tol)
+ return self.__class__(coef, self.domain, self.window, self.symbol)
+
+ def truncate(self, size):
+ """Truncate series to length `size`.
+
+ Reduce the series to length `size` by discarding the high
+ degree terms. The value of `size` must be a positive integer. This
+ can be useful in least squares where the coefficients of the
+ high degree terms may be very small.
+
+ Parameters
+ ----------
+ size : positive int
+ The series is reduced to length `size` by discarding the high
+ degree terms. The value of `size` must be a positive integer.
+
+ Returns
+ -------
+ new_series : series
+ New instance of series with truncated coefficients.
+
+ """
+ isize = int(size)
+ if isize != size or isize < 1:
+ raise ValueError("size must be a positive integer")
+ if isize >= len(self.coef):
+ coef = self.coef
+ else:
+ coef = self.coef[:isize]
+ return self.__class__(coef, self.domain, self.window, self.symbol)
+
+ def convert(self, domain=None, kind=None, window=None):
+ """Convert series to a different kind and/or domain and/or window.
+
+ Parameters
+ ----------
+ domain : array_like, optional
+ The domain of the converted series. If the value is None,
+ the default domain of `kind` is used.
+ kind : class, optional
+ The polynomial series type class to which the current instance
+ should be converted. If kind is None, then the class of the
+ current instance is used.
+ window : array_like, optional
+ The window of the converted series. If the value is None,
+ the default window of `kind` is used.
+
+ Returns
+ -------
+ new_series : series
+ The returned class can be of different type than the current
+ instance and/or have a different domain and/or different
+ window.
+
+ Notes
+ -----
+ Conversion between domains and class types can result in
+ numerically ill defined series.
+
+ """
+ if kind is None:
+ kind = self.__class__
+ if domain is None:
+ domain = kind.domain
+ if window is None:
+ window = kind.window
+ return self(kind.identity(domain, window=window, symbol=self.symbol))
+
+ def mapparms(self):
+ """Return the mapping parameters.
+
+ The returned values define a linear map ``off + scl*x`` that is
+ applied to the input arguments before the series is evaluated. The
+ map depends on the ``domain`` and ``window``; if the current
+ ``domain`` is equal to the ``window`` the resulting map is the
+ identity. If the coefficients of the series instance are to be
+ used by themselves outside this class, then the linear function
+ must be substituted for the ``x`` in the standard representation of
+ the base polynomials.
+
+ Returns
+ -------
+ off, scl : float or complex
+ The mapping function is defined by ``off + scl*x``.
+
+ Notes
+ -----
+ If the current domain is the interval ``[l1, r1]`` and the window
+ is ``[l2, r2]``, then the linear mapping function ``L`` is
+ defined by the equations::
+
+ L(l1) = l2
+ L(r1) = r2
+
+ """
+ return pu.mapparms(self.domain, self.window)
+
+ def integ(self, m=1, k=[], lbnd=None):
+ """Integrate.
+
+ Return a series instance that is the definite integral of the
+ current series.
+
+ Parameters
+ ----------
+ m : non-negative int
+ The number of integrations to perform.
+ k : array_like
+ Integration constants. The first constant is applied to the
+ first integration, the second to the second, and so on. The
+ list of values must less than or equal to `m` in length and any
+ missing values are set to zero.
+ lbnd : Scalar
+ The lower bound of the definite integral.
+
+ Returns
+ -------
+ new_series : series
+ A new series representing the integral. The domain is the same
+ as the domain of the integrated series.
+
+ """
+ off, scl = self.mapparms()
+ if lbnd is None:
+ lbnd = 0
+ else:
+ lbnd = off + scl*lbnd
+ coef = self._int(self.coef, m, k, lbnd, 1./scl)
+ return self.__class__(coef, self.domain, self.window, self.symbol)
+
+ def deriv(self, m=1):
+ """Differentiate.
+
+ Return a series instance of that is the derivative of the current
+ series.
+
+ Parameters
+ ----------
+ m : non-negative int
+ Find the derivative of order `m`.
+
+ Returns
+ -------
+ new_series : series
+ A new series representing the derivative. The domain is the same
+ as the domain of the differentiated series.
+
+ """
+ off, scl = self.mapparms()
+ coef = self._der(self.coef, m, scl)
+ return self.__class__(coef, self.domain, self.window, self.symbol)
+
+ def roots(self):
+ """Return the roots of the series polynomial.
+
+ Compute the roots for the series. Note that the accuracy of the
+ roots decreases the further outside the `domain` they lie.
+
+ Returns
+ -------
+ roots : ndarray
+ Array containing the roots of the series.
+
+ """
+ roots = self._roots(self.coef)
+ return pu.mapdomain(roots, self.window, self.domain)
+
+ def linspace(self, n=100, domain=None):
+ """Return x, y values at equally spaced points in domain.
+
+ Returns the x, y values at `n` linearly spaced points across the
+ domain. Here y is the value of the polynomial at the points x. By
+ default the domain is the same as that of the series instance.
+ This method is intended mostly as a plotting aid.
+
+ .. versionadded:: 1.5.0
+
+ Parameters
+ ----------
+ n : int, optional
+ Number of point pairs to return. The default value is 100.
+ domain : {None, array_like}, optional
+ If not None, the specified domain is used instead of that of
+ the calling instance. It should be of the form ``[beg,end]``.
+ The default is None which case the class domain is used.
+
+ Returns
+ -------
+ x, y : ndarray
+ x is equal to linspace(self.domain[0], self.domain[1], n) and
+ y is the series evaluated at element of x.
+
+ """
+ if domain is None:
+ domain = self.domain
+ x = np.linspace(domain[0], domain[1], n)
+ y = self(x)
+ return x, y
+
+ @classmethod
+ def fit(cls, x, y, deg, domain=None, rcond=None, full=False, w=None,
+ window=None, symbol='x'):
+ """Least squares fit to data.
+
+ Return a series instance that is the least squares fit to the data
+ `y` sampled at `x`. The domain of the returned instance can be
+ specified and this will often result in a superior fit with less
+ chance of ill conditioning.
+
+ Parameters
+ ----------
+ x : array_like, shape (M,)
+ x-coordinates of the M sample points ``(x[i], y[i])``.
+ y : array_like, shape (M,)
+ y-coordinates of the M sample points ``(x[i], y[i])``.
+ deg : int or 1-D array_like
+ Degree(s) of the fitting polynomials. If `deg` is a single integer
+ all terms up to and including the `deg`'th term are included in the
+ fit. For NumPy versions >= 1.11.0 a list of integers specifying the
+ degrees of the terms to include may be used instead.
+ domain : {None, [beg, end], []}, optional
+ Domain to use for the returned series. If ``None``,
+ then a minimal domain that covers the points `x` is chosen. If
+ ``[]`` the class domain is used. The default value was the
+ class domain in NumPy 1.4 and ``None`` in later versions.
+ The ``[]`` option was added in numpy 1.5.0.
+ rcond : float, optional
+ Relative condition number of the fit. Singular values smaller
+ than this relative to the largest singular value will be
+ ignored. The default value is len(x)*eps, where eps is the
+ relative precision of the float type, about 2e-16 in most
+ cases.
+ full : bool, optional
+ Switch determining nature of return value. When it is False
+ (the default) just the coefficients are returned, when True
+ diagnostic information from the singular value decomposition is
+ also returned.
+ w : array_like, shape (M,), optional
+ Weights. If not None, the weight ``w[i]`` applies to the unsquared
+ residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
+ chosen so that the errors of the products ``w[i]*y[i]`` all have
+ the same variance. When using inverse-variance weighting, use
+ ``w[i] = 1/sigma(y[i])``. The default value is None.
+
+ .. versionadded:: 1.5.0
+ window : {[beg, end]}, optional
+ Window to use for the returned series. The default
+ value is the default class domain
+
+ .. versionadded:: 1.6.0
+ symbol : str, optional
+ Symbol representing the independent variable. Default is 'x'.
+
+ Returns
+ -------
+ new_series : series
+ A series that represents the least squares fit to the data and
+ has the domain and window specified in the call. If the
+ coefficients for the unscaled and unshifted basis polynomials are
+ of interest, do ``new_series.convert().coef``.
+
+ [resid, rank, sv, rcond] : list
+ These values are only returned if ``full == True``
+
+ - resid -- sum of squared residuals of the least squares fit
+ - rank -- the numerical rank of the scaled Vandermonde matrix
+ - sv -- singular values of the scaled Vandermonde matrix
+ - rcond -- value of `rcond`.
+
+ For more details, see `linalg.lstsq`.
+
+ """
+ if domain is None:
+ domain = pu.getdomain(x)
+ elif type(domain) is list and len(domain) == 0:
+ domain = cls.domain
+
+ if window is None:
+ window = cls.window
+
+ xnew = pu.mapdomain(x, domain, window)
+ res = cls._fit(xnew, y, deg, w=w, rcond=rcond, full=full)
+ if full:
+ [coef, status] = res
+ return (
+ cls(coef, domain=domain, window=window, symbol=symbol), status
+ )
+ else:
+ coef = res
+ return cls(coef, domain=domain, window=window, symbol=symbol)
+
+ @classmethod
+ def fromroots(cls, roots, domain=[], window=None, symbol='x'):
+ """Return series instance that has the specified roots.
+
+ Returns a series representing the product
+ ``(x - r[0])*(x - r[1])*...*(x - r[n-1])``, where ``r`` is a
+ list of roots.
+
+ Parameters
+ ----------
+ roots : array_like
+ List of roots.
+ domain : {[], None, array_like}, optional
+ Domain for the resulting series. If None the domain is the
+ interval from the smallest root to the largest. If [] the
+ domain is the class domain. The default is [].
+ window : {None, array_like}, optional
+ Window for the returned series. If None the class window is
+ used. The default is None.
+ symbol : str, optional
+ Symbol representing the independent variable. Default is 'x'.
+
+ Returns
+ -------
+ new_series : series
+ Series with the specified roots.
+
+ """
+ [roots] = pu.as_series([roots], trim=False)
+ if domain is None:
+ domain = pu.getdomain(roots)
+ elif type(domain) is list and len(domain) == 0:
+ domain = cls.domain
+
+ if window is None:
+ window = cls.window
+
+ deg = len(roots)
+ off, scl = pu.mapparms(domain, window)
+ rnew = off + scl*roots
+ coef = cls._fromroots(rnew) / scl**deg
+ return cls(coef, domain=domain, window=window, symbol=symbol)
+
+ @classmethod
+ def identity(cls, domain=None, window=None, symbol='x'):
+ """Identity function.
+
+ If ``p`` is the returned series, then ``p(x) == x`` for all
+ values of x.
+
+ Parameters
+ ----------
+ domain : {None, array_like}, optional
+ If given, the array must be of the form ``[beg, end]``, where
+ ``beg`` and ``end`` are the endpoints of the domain. If None is
+ given then the class domain is used. The default is None.
+ window : {None, array_like}, optional
+ If given, the resulting array must be if the form
+ ``[beg, end]``, where ``beg`` and ``end`` are the endpoints of
+ the window. If None is given then the class window is used. The
+ default is None.
+ symbol : str, optional
+ Symbol representing the independent variable. Default is 'x'.
+
+ Returns
+ -------
+ new_series : series
+ Series of representing the identity.
+
+ """
+ if domain is None:
+ domain = cls.domain
+ if window is None:
+ window = cls.window
+ off, scl = pu.mapparms(window, domain)
+ coef = cls._line(off, scl)
+ return cls(coef, domain, window, symbol)
+
+ @classmethod
+ def basis(cls, deg, domain=None, window=None, symbol='x'):
+ """Series basis polynomial of degree `deg`.
+
+ Returns the series representing the basis polynomial of degree `deg`.
+
+ .. versionadded:: 1.7.0
+
+ Parameters
+ ----------
+ deg : int
+ Degree of the basis polynomial for the series. Must be >= 0.
+ domain : {None, array_like}, optional
+ If given, the array must be of the form ``[beg, end]``, where
+ ``beg`` and ``end`` are the endpoints of the domain. If None is
+ given then the class domain is used. The default is None.
+ window : {None, array_like}, optional
+ If given, the resulting array must be if the form
+ ``[beg, end]``, where ``beg`` and ``end`` are the endpoints of
+ the window. If None is given then the class window is used. The
+ default is None.
+ symbol : str, optional
+ Symbol representing the independent variable. Default is 'x'.
+
+ Returns
+ -------
+ new_series : series
+ A series with the coefficient of the `deg` term set to one and
+ all others zero.
+
+ """
+ if domain is None:
+ domain = cls.domain
+ if window is None:
+ window = cls.window
+ ideg = int(deg)
+
+ if ideg != deg or ideg < 0:
+ raise ValueError("deg must be non-negative integer")
+ return cls([0]*ideg + [1], domain, window, symbol)
+
+ @classmethod
+ def cast(cls, series, domain=None, window=None):
+ """Convert series to series of this class.
+
+ The `series` is expected to be an instance of some polynomial
+ series of one of the types supported by by the numpy.polynomial
+ module, but could be some other class that supports the convert
+ method.
+
+ .. versionadded:: 1.7.0
+
+ Parameters
+ ----------
+ series : series
+ The series instance to be converted.
+ domain : {None, array_like}, optional
+ If given, the array must be of the form ``[beg, end]``, where
+ ``beg`` and ``end`` are the endpoints of the domain. If None is
+ given then the class domain is used. The default is None.
+ window : {None, array_like}, optional
+ If given, the resulting array must be if the form
+ ``[beg, end]``, where ``beg`` and ``end`` are the endpoints of
+ the window. If None is given then the class window is used. The
+ default is None.
+
+ Returns
+ -------
+ new_series : series
+ A series of the same kind as the calling class and equal to
+ `series` when evaluated.
+
+ See Also
+ --------
+ convert : similar instance method
+
+ """
+ if domain is None:
+ domain = cls.domain
+ if window is None:
+ window = cls.window
+ return series.convert(domain, cls, window)
diff --git a/lib/python3.12/site-packages/numpy/polynomial/_polybase.pyi b/lib/python3.12/site-packages/numpy/polynomial/_polybase.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..25c740dbedd02ca6c3f6e1beb155876a967cb57c
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/_polybase.pyi
@@ -0,0 +1,71 @@
+import abc
+from typing import Any, ClassVar
+
+__all__: list[str]
+
+class ABCPolyBase(abc.ABC):
+ __hash__: ClassVar[None] # type: ignore[assignment]
+ __array_ufunc__: ClassVar[None]
+ maxpower: ClassVar[int]
+ coef: Any
+ @property
+ def symbol(self) -> str: ...
+ @property
+ @abc.abstractmethod
+ def domain(self): ...
+ @property
+ @abc.abstractmethod
+ def window(self): ...
+ @property
+ @abc.abstractmethod
+ def basis_name(self): ...
+ def has_samecoef(self, other): ...
+ def has_samedomain(self, other): ...
+ def has_samewindow(self, other): ...
+ def has_sametype(self, other): ...
+ def __init__(self, coef, domain=..., window=..., symbol: str = ...) -> None: ...
+ def __format__(self, fmt_str): ...
+ def __call__(self, arg): ...
+ def __iter__(self): ...
+ def __len__(self): ...
+ def __neg__(self): ...
+ def __pos__(self): ...
+ def __add__(self, other): ...
+ def __sub__(self, other): ...
+ def __mul__(self, other): ...
+ def __truediv__(self, other): ...
+ def __floordiv__(self, other): ...
+ def __mod__(self, other): ...
+ def __divmod__(self, other): ...
+ def __pow__(self, other): ...
+ def __radd__(self, other): ...
+ def __rsub__(self, other): ...
+ def __rmul__(self, other): ...
+ def __rdiv__(self, other): ...
+ def __rtruediv__(self, other): ...
+ def __rfloordiv__(self, other): ...
+ def __rmod__(self, other): ...
+ def __rdivmod__(self, other): ...
+ def __eq__(self, other): ...
+ def __ne__(self, other): ...
+ def copy(self): ...
+ def degree(self): ...
+ def cutdeg(self, deg): ...
+ def trim(self, tol=...): ...
+ def truncate(self, size): ...
+ def convert(self, domain=..., kind=..., window=...): ...
+ def mapparms(self): ...
+ def integ(self, m=..., k = ..., lbnd=...): ...
+ def deriv(self, m=...): ...
+ def roots(self): ...
+ def linspace(self, n=..., domain=...): ...
+ @classmethod
+ def fit(cls, x, y, deg, domain=..., rcond=..., full=..., w=..., window=...): ...
+ @classmethod
+ def fromroots(cls, roots, domain = ..., window=...): ...
+ @classmethod
+ def identity(cls, domain=..., window=...): ...
+ @classmethod
+ def basis(cls, deg, domain=..., window=...): ...
+ @classmethod
+ def cast(cls, series, domain=..., window=...): ...
diff --git a/lib/python3.12/site-packages/numpy/polynomial/chebyshev.py b/lib/python3.12/site-packages/numpy/polynomial/chebyshev.py
new file mode 100644
index 0000000000000000000000000000000000000000..efbe13e0cadb27e29bea430a858dea5110621a0c
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/chebyshev.py
@@ -0,0 +1,2082 @@
+"""
+====================================================
+Chebyshev Series (:mod:`numpy.polynomial.chebyshev`)
+====================================================
+
+This module provides a number of objects (mostly functions) useful for
+dealing with Chebyshev series, including a `Chebyshev` class that
+encapsulates the usual arithmetic operations. (General information
+on how this module represents and works with such polynomials is in the
+docstring for its "parent" sub-package, `numpy.polynomial`).
+
+Classes
+-------
+
+.. autosummary::
+ :toctree: generated/
+
+ Chebyshev
+
+
+Constants
+---------
+
+.. autosummary::
+ :toctree: generated/
+
+ chebdomain
+ chebzero
+ chebone
+ chebx
+
+Arithmetic
+----------
+
+.. autosummary::
+ :toctree: generated/
+
+ chebadd
+ chebsub
+ chebmulx
+ chebmul
+ chebdiv
+ chebpow
+ chebval
+ chebval2d
+ chebval3d
+ chebgrid2d
+ chebgrid3d
+
+Calculus
+--------
+
+.. autosummary::
+ :toctree: generated/
+
+ chebder
+ chebint
+
+Misc Functions
+--------------
+
+.. autosummary::
+ :toctree: generated/
+
+ chebfromroots
+ chebroots
+ chebvander
+ chebvander2d
+ chebvander3d
+ chebgauss
+ chebweight
+ chebcompanion
+ chebfit
+ chebpts1
+ chebpts2
+ chebtrim
+ chebline
+ cheb2poly
+ poly2cheb
+ chebinterpolate
+
+See also
+--------
+`numpy.polynomial`
+
+Notes
+-----
+The implementations of multiplication, division, integration, and
+differentiation use the algebraic identities [1]_:
+
+.. math::
+ T_n(x) = \\frac{z^n + z^{-n}}{2} \\\\
+ z\\frac{dx}{dz} = \\frac{z - z^{-1}}{2}.
+
+where
+
+.. math:: x = \\frac{z + z^{-1}}{2}.
+
+These identities allow a Chebyshev series to be expressed as a finite,
+symmetric Laurent series. In this module, this sort of Laurent series
+is referred to as a "z-series."
+
+References
+----------
+.. [1] A. T. Benjamin, et al., "Combinatorial Trigonometry with Chebyshev
+ Polynomials," *Journal of Statistical Planning and Inference 14*, 2008
+ (https://web.archive.org/web/20080221202153/https://www.math.hmc.edu/~benjamin/papers/CombTrig.pdf, pg. 4)
+
+"""
+import numpy as np
+import numpy.linalg as la
+from numpy.core.multiarray import normalize_axis_index
+
+from . import polyutils as pu
+from ._polybase import ABCPolyBase
+
+__all__ = [
+ 'chebzero', 'chebone', 'chebx', 'chebdomain', 'chebline', 'chebadd',
+ 'chebsub', 'chebmulx', 'chebmul', 'chebdiv', 'chebpow', 'chebval',
+ 'chebder', 'chebint', 'cheb2poly', 'poly2cheb', 'chebfromroots',
+ 'chebvander', 'chebfit', 'chebtrim', 'chebroots', 'chebpts1',
+ 'chebpts2', 'Chebyshev', 'chebval2d', 'chebval3d', 'chebgrid2d',
+ 'chebgrid3d', 'chebvander2d', 'chebvander3d', 'chebcompanion',
+ 'chebgauss', 'chebweight', 'chebinterpolate']
+
+chebtrim = pu.trimcoef
+
+#
+# A collection of functions for manipulating z-series. These are private
+# functions and do minimal error checking.
+#
+
+def _cseries_to_zseries(c):
+ """Convert Chebyshev series to z-series.
+
+ Convert a Chebyshev series to the equivalent z-series. The result is
+ never an empty array. The dtype of the return is the same as that of
+ the input. No checks are run on the arguments as this routine is for
+ internal use.
+
+ Parameters
+ ----------
+ c : 1-D ndarray
+ Chebyshev coefficients, ordered from low to high
+
+ Returns
+ -------
+ zs : 1-D ndarray
+ Odd length symmetric z-series, ordered from low to high.
+
+ """
+ n = c.size
+ zs = np.zeros(2*n-1, dtype=c.dtype)
+ zs[n-1:] = c/2
+ return zs + zs[::-1]
+
+
+def _zseries_to_cseries(zs):
+ """Convert z-series to a Chebyshev series.
+
+ Convert a z series to the equivalent Chebyshev series. The result is
+ never an empty array. The dtype of the return is the same as that of
+ the input. No checks are run on the arguments as this routine is for
+ internal use.
+
+ Parameters
+ ----------
+ zs : 1-D ndarray
+ Odd length symmetric z-series, ordered from low to high.
+
+ Returns
+ -------
+ c : 1-D ndarray
+ Chebyshev coefficients, ordered from low to high.
+
+ """
+ n = (zs.size + 1)//2
+ c = zs[n-1:].copy()
+ c[1:n] *= 2
+ return c
+
+
+def _zseries_mul(z1, z2):
+ """Multiply two z-series.
+
+ Multiply two z-series to produce a z-series.
+
+ Parameters
+ ----------
+ z1, z2 : 1-D ndarray
+ The arrays must be 1-D but this is not checked.
+
+ Returns
+ -------
+ product : 1-D ndarray
+ The product z-series.
+
+ Notes
+ -----
+ This is simply convolution. If symmetric/anti-symmetric z-series are
+ denoted by S/A then the following rules apply:
+
+ S*S, A*A -> S
+ S*A, A*S -> A
+
+ """
+ return np.convolve(z1, z2)
+
+
+def _zseries_div(z1, z2):
+ """Divide the first z-series by the second.
+
+ Divide `z1` by `z2` and return the quotient and remainder as z-series.
+ Warning: this implementation only applies when both z1 and z2 have the
+ same symmetry, which is sufficient for present purposes.
+
+ Parameters
+ ----------
+ z1, z2 : 1-D ndarray
+ The arrays must be 1-D and have the same symmetry, but this is not
+ checked.
+
+ Returns
+ -------
+
+ (quotient, remainder) : 1-D ndarrays
+ Quotient and remainder as z-series.
+
+ Notes
+ -----
+ This is not the same as polynomial division on account of the desired form
+ of the remainder. If symmetric/anti-symmetric z-series are denoted by S/A
+ then the following rules apply:
+
+ S/S -> S,S
+ A/A -> S,A
+
+ The restriction to types of the same symmetry could be fixed but seems like
+ unneeded generality. There is no natural form for the remainder in the case
+ where there is no symmetry.
+
+ """
+ z1 = z1.copy()
+ z2 = z2.copy()
+ lc1 = len(z1)
+ lc2 = len(z2)
+ if lc2 == 1:
+ z1 /= z2
+ return z1, z1[:1]*0
+ elif lc1 < lc2:
+ return z1[:1]*0, z1
+ else:
+ dlen = lc1 - lc2
+ scl = z2[0]
+ z2 /= scl
+ quo = np.empty(dlen + 1, dtype=z1.dtype)
+ i = 0
+ j = dlen
+ while i < j:
+ r = z1[i]
+ quo[i] = z1[i]
+ quo[dlen - i] = r
+ tmp = r*z2
+ z1[i:i+lc2] -= tmp
+ z1[j:j+lc2] -= tmp
+ i += 1
+ j -= 1
+ r = z1[i]
+ quo[i] = r
+ tmp = r*z2
+ z1[i:i+lc2] -= tmp
+ quo /= scl
+ rem = z1[i+1:i-1+lc2].copy()
+ return quo, rem
+
+
+def _zseries_der(zs):
+ """Differentiate a z-series.
+
+ The derivative is with respect to x, not z. This is achieved using the
+ chain rule and the value of dx/dz given in the module notes.
+
+ Parameters
+ ----------
+ zs : z-series
+ The z-series to differentiate.
+
+ Returns
+ -------
+ derivative : z-series
+ The derivative
+
+ Notes
+ -----
+ The zseries for x (ns) has been multiplied by two in order to avoid
+ using floats that are incompatible with Decimal and likely other
+ specialized scalar types. This scaling has been compensated by
+ multiplying the value of zs by two also so that the two cancels in the
+ division.
+
+ """
+ n = len(zs)//2
+ ns = np.array([-1, 0, 1], dtype=zs.dtype)
+ zs *= np.arange(-n, n+1)*2
+ d, r = _zseries_div(zs, ns)
+ return d
+
+
+def _zseries_int(zs):
+ """Integrate a z-series.
+
+ The integral is with respect to x, not z. This is achieved by a change
+ of variable using dx/dz given in the module notes.
+
+ Parameters
+ ----------
+ zs : z-series
+ The z-series to integrate
+
+ Returns
+ -------
+ integral : z-series
+ The indefinite integral
+
+ Notes
+ -----
+ The zseries for x (ns) has been multiplied by two in order to avoid
+ using floats that are incompatible with Decimal and likely other
+ specialized scalar types. This scaling has been compensated by
+ dividing the resulting zs by two.
+
+ """
+ n = 1 + len(zs)//2
+ ns = np.array([-1, 0, 1], dtype=zs.dtype)
+ zs = _zseries_mul(zs, ns)
+ div = np.arange(-n, n+1)*2
+ zs[:n] /= div[:n]
+ zs[n+1:] /= div[n+1:]
+ zs[n] = 0
+ return zs
+
+#
+# Chebyshev series functions
+#
+
+
+def poly2cheb(pol):
+ """
+ Convert a polynomial to a Chebyshev series.
+
+ Convert an array representing the coefficients of a polynomial (relative
+ to the "standard" basis) ordered from lowest degree to highest, to an
+ array of the coefficients of the equivalent Chebyshev series, ordered
+ from lowest to highest degree.
+
+ Parameters
+ ----------
+ pol : array_like
+ 1-D array containing the polynomial coefficients
+
+ Returns
+ -------
+ c : ndarray
+ 1-D array containing the coefficients of the equivalent Chebyshev
+ series.
+
+ See Also
+ --------
+ cheb2poly
+
+ Notes
+ -----
+ The easy way to do conversions between polynomial basis sets
+ is to use the convert method of a class instance.
+
+ Examples
+ --------
+ >>> from numpy import polynomial as P
+ >>> p = P.Polynomial(range(4))
+ >>> p
+ Polynomial([0., 1., 2., 3.], domain=[-1, 1], window=[-1, 1])
+ >>> c = p.convert(kind=P.Chebyshev)
+ >>> c
+ Chebyshev([1. , 3.25, 1. , 0.75], domain=[-1., 1.], window=[-1., 1.])
+ >>> P.chebyshev.poly2cheb(range(4))
+ array([1. , 3.25, 1. , 0.75])
+
+ """
+ [pol] = pu.as_series([pol])
+ deg = len(pol) - 1
+ res = 0
+ for i in range(deg, -1, -1):
+ res = chebadd(chebmulx(res), pol[i])
+ return res
+
+
+def cheb2poly(c):
+ """
+ Convert a Chebyshev series to a polynomial.
+
+ Convert an array representing the coefficients of a Chebyshev series,
+ ordered from lowest degree to highest, to an array of the coefficients
+ of the equivalent polynomial (relative to the "standard" basis) ordered
+ from lowest to highest degree.
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array containing the Chebyshev series coefficients, ordered
+ from lowest order term to highest.
+
+ Returns
+ -------
+ pol : ndarray
+ 1-D array containing the coefficients of the equivalent polynomial
+ (relative to the "standard" basis) ordered from lowest order term
+ to highest.
+
+ See Also
+ --------
+ poly2cheb
+
+ Notes
+ -----
+ The easy way to do conversions between polynomial basis sets
+ is to use the convert method of a class instance.
+
+ Examples
+ --------
+ >>> from numpy import polynomial as P
+ >>> c = P.Chebyshev(range(4))
+ >>> c
+ Chebyshev([0., 1., 2., 3.], domain=[-1, 1], window=[-1, 1])
+ >>> p = c.convert(kind=P.Polynomial)
+ >>> p
+ Polynomial([-2., -8., 4., 12.], domain=[-1., 1.], window=[-1., 1.])
+ >>> P.chebyshev.cheb2poly(range(4))
+ array([-2., -8., 4., 12.])
+
+ """
+ from .polynomial import polyadd, polysub, polymulx
+
+ [c] = pu.as_series([c])
+ n = len(c)
+ if n < 3:
+ return c
+ else:
+ c0 = c[-2]
+ c1 = c[-1]
+ # i is the current degree of c1
+ for i in range(n - 1, 1, -1):
+ tmp = c0
+ c0 = polysub(c[i - 2], c1)
+ c1 = polyadd(tmp, polymulx(c1)*2)
+ return polyadd(c0, polymulx(c1))
+
+
+#
+# These are constant arrays are of integer type so as to be compatible
+# with the widest range of other types, such as Decimal.
+#
+
+# Chebyshev default domain.
+chebdomain = np.array([-1, 1])
+
+# Chebyshev coefficients representing zero.
+chebzero = np.array([0])
+
+# Chebyshev coefficients representing one.
+chebone = np.array([1])
+
+# Chebyshev coefficients representing the identity x.
+chebx = np.array([0, 1])
+
+
+def chebline(off, scl):
+ """
+ Chebyshev series whose graph is a straight line.
+
+ Parameters
+ ----------
+ off, scl : scalars
+ The specified line is given by ``off + scl*x``.
+
+ Returns
+ -------
+ y : ndarray
+ This module's representation of the Chebyshev series for
+ ``off + scl*x``.
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyline
+ numpy.polynomial.legendre.legline
+ numpy.polynomial.laguerre.lagline
+ numpy.polynomial.hermite.hermline
+ numpy.polynomial.hermite_e.hermeline
+
+ Examples
+ --------
+ >>> import numpy.polynomial.chebyshev as C
+ >>> C.chebline(3,2)
+ array([3, 2])
+ >>> C.chebval(-3, C.chebline(3,2)) # should be -3
+ -3.0
+
+ """
+ if scl != 0:
+ return np.array([off, scl])
+ else:
+ return np.array([off])
+
+
+def chebfromroots(roots):
+ """
+ Generate a Chebyshev series with given roots.
+
+ The function returns the coefficients of the polynomial
+
+ .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
+
+ in Chebyshev form, where the `r_n` are the roots specified in `roots`.
+ If a zero has multiplicity n, then it must appear in `roots` n times.
+ For instance, if 2 is a root of multiplicity three and 3 is a root of
+ multiplicity 2, then `roots` looks something like [2, 2, 2, 3, 3]. The
+ roots can appear in any order.
+
+ If the returned coefficients are `c`, then
+
+ .. math:: p(x) = c_0 + c_1 * T_1(x) + ... + c_n * T_n(x)
+
+ The coefficient of the last term is not generally 1 for monic
+ polynomials in Chebyshev form.
+
+ Parameters
+ ----------
+ roots : array_like
+ Sequence containing the roots.
+
+ Returns
+ -------
+ out : ndarray
+ 1-D array of coefficients. If all roots are real then `out` is a
+ real array, if some of the roots are complex, then `out` is complex
+ even if all the coefficients in the result are real (see Examples
+ below).
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyfromroots
+ numpy.polynomial.legendre.legfromroots
+ numpy.polynomial.laguerre.lagfromroots
+ numpy.polynomial.hermite.hermfromroots
+ numpy.polynomial.hermite_e.hermefromroots
+
+ Examples
+ --------
+ >>> import numpy.polynomial.chebyshev as C
+ >>> C.chebfromroots((-1,0,1)) # x^3 - x relative to the standard basis
+ array([ 0. , -0.25, 0. , 0.25])
+ >>> j = complex(0,1)
+ >>> C.chebfromroots((-j,j)) # x^2 + 1 relative to the standard basis
+ array([1.5+0.j, 0. +0.j, 0.5+0.j])
+
+ """
+ return pu._fromroots(chebline, chebmul, roots)
+
+
+def chebadd(c1, c2):
+ """
+ Add one Chebyshev series to another.
+
+ Returns the sum of two Chebyshev series `c1` + `c2`. The arguments
+ are sequences of coefficients ordered from lowest order term to
+ highest, i.e., [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Chebyshev series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Array representing the Chebyshev series of their sum.
+
+ See Also
+ --------
+ chebsub, chebmulx, chebmul, chebdiv, chebpow
+
+ Notes
+ -----
+ Unlike multiplication, division, etc., the sum of two Chebyshev series
+ is a Chebyshev series (without having to "reproject" the result onto
+ the basis set) so addition, just like that of "standard" polynomials,
+ is simply "component-wise."
+
+ Examples
+ --------
+ >>> from numpy.polynomial import chebyshev as C
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> C.chebadd(c1,c2)
+ array([4., 4., 4.])
+
+ """
+ return pu._add(c1, c2)
+
+
+def chebsub(c1, c2):
+ """
+ Subtract one Chebyshev series from another.
+
+ Returns the difference of two Chebyshev series `c1` - `c2`. The
+ sequences of coefficients are from lowest order term to highest, i.e.,
+ [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Chebyshev series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Of Chebyshev series coefficients representing their difference.
+
+ See Also
+ --------
+ chebadd, chebmulx, chebmul, chebdiv, chebpow
+
+ Notes
+ -----
+ Unlike multiplication, division, etc., the difference of two Chebyshev
+ series is a Chebyshev series (without having to "reproject" the result
+ onto the basis set) so subtraction, just like that of "standard"
+ polynomials, is simply "component-wise."
+
+ Examples
+ --------
+ >>> from numpy.polynomial import chebyshev as C
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> C.chebsub(c1,c2)
+ array([-2., 0., 2.])
+ >>> C.chebsub(c2,c1) # -C.chebsub(c1,c2)
+ array([ 2., 0., -2.])
+
+ """
+ return pu._sub(c1, c2)
+
+
+def chebmulx(c):
+ """Multiply a Chebyshev series by x.
+
+ Multiply the polynomial `c` by x, where x is the independent
+ variable.
+
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of Chebyshev series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Array representing the result of the multiplication.
+
+ Notes
+ -----
+
+ .. versionadded:: 1.5.0
+
+ Examples
+ --------
+ >>> from numpy.polynomial import chebyshev as C
+ >>> C.chebmulx([1,2,3])
+ array([1. , 2.5, 1. , 1.5])
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ # The zero series needs special treatment
+ if len(c) == 1 and c[0] == 0:
+ return c
+
+ prd = np.empty(len(c) + 1, dtype=c.dtype)
+ prd[0] = c[0]*0
+ prd[1] = c[0]
+ if len(c) > 1:
+ tmp = c[1:]/2
+ prd[2:] = tmp
+ prd[0:-2] += tmp
+ return prd
+
+
+def chebmul(c1, c2):
+ """
+ Multiply one Chebyshev series by another.
+
+ Returns the product of two Chebyshev series `c1` * `c2`. The arguments
+ are sequences of coefficients, from lowest order "term" to highest,
+ e.g., [1,2,3] represents the series ``T_0 + 2*T_1 + 3*T_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Chebyshev series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Of Chebyshev series coefficients representing their product.
+
+ See Also
+ --------
+ chebadd, chebsub, chebmulx, chebdiv, chebpow
+
+ Notes
+ -----
+ In general, the (polynomial) product of two C-series results in terms
+ that are not in the Chebyshev polynomial basis set. Thus, to express
+ the product as a C-series, it is typically necessary to "reproject"
+ the product onto said basis set, which typically produces
+ "unintuitive live" (but correct) results; see Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial import chebyshev as C
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> C.chebmul(c1,c2) # multiplication requires "reprojection"
+ array([ 6.5, 12. , 12. , 4. , 1.5])
+
+ """
+ # c1, c2 are trimmed copies
+ [c1, c2] = pu.as_series([c1, c2])
+ z1 = _cseries_to_zseries(c1)
+ z2 = _cseries_to_zseries(c2)
+ prd = _zseries_mul(z1, z2)
+ ret = _zseries_to_cseries(prd)
+ return pu.trimseq(ret)
+
+
+def chebdiv(c1, c2):
+ """
+ Divide one Chebyshev series by another.
+
+ Returns the quotient-with-remainder of two Chebyshev series
+ `c1` / `c2`. The arguments are sequences of coefficients from lowest
+ order "term" to highest, e.g., [1,2,3] represents the series
+ ``T_0 + 2*T_1 + 3*T_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Chebyshev series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ [quo, rem] : ndarrays
+ Of Chebyshev series coefficients representing the quotient and
+ remainder.
+
+ See Also
+ --------
+ chebadd, chebsub, chebmulx, chebmul, chebpow
+
+ Notes
+ -----
+ In general, the (polynomial) division of one C-series by another
+ results in quotient and remainder terms that are not in the Chebyshev
+ polynomial basis set. Thus, to express these results as C-series, it
+ is typically necessary to "reproject" the results onto said basis
+ set, which typically produces "unintuitive" (but correct) results;
+ see Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial import chebyshev as C
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> C.chebdiv(c1,c2) # quotient "intuitive," remainder not
+ (array([3.]), array([-8., -4.]))
+ >>> c2 = (0,1,2,3)
+ >>> C.chebdiv(c2,c1) # neither "intuitive"
+ (array([0., 2.]), array([-2., -4.]))
+
+ """
+ # c1, c2 are trimmed copies
+ [c1, c2] = pu.as_series([c1, c2])
+ if c2[-1] == 0:
+ raise ZeroDivisionError()
+
+ # note: this is more efficient than `pu._div(chebmul, c1, c2)`
+ lc1 = len(c1)
+ lc2 = len(c2)
+ if lc1 < lc2:
+ return c1[:1]*0, c1
+ elif lc2 == 1:
+ return c1/c2[-1], c1[:1]*0
+ else:
+ z1 = _cseries_to_zseries(c1)
+ z2 = _cseries_to_zseries(c2)
+ quo, rem = _zseries_div(z1, z2)
+ quo = pu.trimseq(_zseries_to_cseries(quo))
+ rem = pu.trimseq(_zseries_to_cseries(rem))
+ return quo, rem
+
+
+def chebpow(c, pow, maxpower=16):
+ """Raise a Chebyshev series to a power.
+
+ Returns the Chebyshev series `c` raised to the power `pow`. The
+ argument `c` is a sequence of coefficients ordered from low to high.
+ i.e., [1,2,3] is the series ``T_0 + 2*T_1 + 3*T_2.``
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of Chebyshev series coefficients ordered from low to
+ high.
+ pow : integer
+ Power to which the series will be raised
+ maxpower : integer, optional
+ Maximum power allowed. This is mainly to limit growth of the series
+ to unmanageable size. Default is 16
+
+ Returns
+ -------
+ coef : ndarray
+ Chebyshev series of power.
+
+ See Also
+ --------
+ chebadd, chebsub, chebmulx, chebmul, chebdiv
+
+ Examples
+ --------
+ >>> from numpy.polynomial import chebyshev as C
+ >>> C.chebpow([1, 2, 3, 4], 2)
+ array([15.5, 22. , 16. , ..., 12.5, 12. , 8. ])
+
+ """
+ # note: this is more efficient than `pu._pow(chebmul, c1, c2)`, as it
+ # avoids converting between z and c series repeatedly
+
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ power = int(pow)
+ if power != pow or power < 0:
+ raise ValueError("Power must be a non-negative integer.")
+ elif maxpower is not None and power > maxpower:
+ raise ValueError("Power is too large")
+ elif power == 0:
+ return np.array([1], dtype=c.dtype)
+ elif power == 1:
+ return c
+ else:
+ # This can be made more efficient by using powers of two
+ # in the usual way.
+ zs = _cseries_to_zseries(c)
+ prd = zs
+ for i in range(2, power + 1):
+ prd = np.convolve(prd, zs)
+ return _zseries_to_cseries(prd)
+
+
+def chebder(c, m=1, scl=1, axis=0):
+ """
+ Differentiate a Chebyshev series.
+
+ Returns the Chebyshev series coefficients `c` differentiated `m` times
+ along `axis`. At each iteration the result is multiplied by `scl` (the
+ scaling factor is for use in a linear change of variable). The argument
+ `c` is an array of coefficients from low to high degree along each
+ axis, e.g., [1,2,3] represents the series ``1*T_0 + 2*T_1 + 3*T_2``
+ while [[1,2],[1,2]] represents ``1*T_0(x)*T_0(y) + 1*T_1(x)*T_0(y) +
+ 2*T_0(x)*T_1(y) + 2*T_1(x)*T_1(y)`` if axis=0 is ``x`` and axis=1 is
+ ``y``.
+
+ Parameters
+ ----------
+ c : array_like
+ Array of Chebyshev series coefficients. If c is multidimensional
+ the different axis correspond to different variables with the
+ degree in each axis given by the corresponding index.
+ m : int, optional
+ Number of derivatives taken, must be non-negative. (Default: 1)
+ scl : scalar, optional
+ Each differentiation is multiplied by `scl`. The end result is
+ multiplication by ``scl**m``. This is for use in a linear change of
+ variable. (Default: 1)
+ axis : int, optional
+ Axis over which the derivative is taken. (Default: 0).
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ der : ndarray
+ Chebyshev series of the derivative.
+
+ See Also
+ --------
+ chebint
+
+ Notes
+ -----
+ In general, the result of differentiating a C-series needs to be
+ "reprojected" onto the C-series basis set. Thus, typically, the
+ result of this function is "unintuitive," albeit correct; see Examples
+ section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial import chebyshev as C
+ >>> c = (1,2,3,4)
+ >>> C.chebder(c)
+ array([14., 12., 24.])
+ >>> C.chebder(c,3)
+ array([96.])
+ >>> C.chebder(c,scl=-1)
+ array([-14., -12., -24.])
+ >>> C.chebder(c,2,-1)
+ array([12., 96.])
+
+ """
+ c = np.array(c, ndmin=1, copy=True)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ c = c.astype(np.double)
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
+ if cnt < 0:
+ raise ValueError("The order of derivation must be non-negative")
+ iaxis = normalize_axis_index(iaxis, c.ndim)
+
+ if cnt == 0:
+ return c
+
+ c = np.moveaxis(c, iaxis, 0)
+ n = len(c)
+ if cnt >= n:
+ c = c[:1]*0
+ else:
+ for i in range(cnt):
+ n = n - 1
+ c *= scl
+ der = np.empty((n,) + c.shape[1:], dtype=c.dtype)
+ for j in range(n, 2, -1):
+ der[j - 1] = (2*j)*c[j]
+ c[j - 2] += (j*c[j])/(j - 2)
+ if n > 1:
+ der[1] = 4*c[2]
+ der[0] = c[1]
+ c = der
+ c = np.moveaxis(c, 0, iaxis)
+ return c
+
+
+def chebint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
+ """
+ Integrate a Chebyshev series.
+
+ Returns the Chebyshev series coefficients `c` integrated `m` times from
+ `lbnd` along `axis`. At each iteration the resulting series is
+ **multiplied** by `scl` and an integration constant, `k`, is added.
+ The scaling factor is for use in a linear change of variable. ("Buyer
+ beware": note that, depending on what one is doing, one may want `scl`
+ to be the reciprocal of what one might expect; for more information,
+ see the Notes section below.) The argument `c` is an array of
+ coefficients from low to high degree along each axis, e.g., [1,2,3]
+ represents the series ``T_0 + 2*T_1 + 3*T_2`` while [[1,2],[1,2]]
+ represents ``1*T_0(x)*T_0(y) + 1*T_1(x)*T_0(y) + 2*T_0(x)*T_1(y) +
+ 2*T_1(x)*T_1(y)`` if axis=0 is ``x`` and axis=1 is ``y``.
+
+ Parameters
+ ----------
+ c : array_like
+ Array of Chebyshev series coefficients. If c is multidimensional
+ the different axis correspond to different variables with the
+ degree in each axis given by the corresponding index.
+ m : int, optional
+ Order of integration, must be positive. (Default: 1)
+ k : {[], list, scalar}, optional
+ Integration constant(s). The value of the first integral at zero
+ is the first value in the list, the value of the second integral
+ at zero is the second value, etc. If ``k == []`` (the default),
+ all constants are set to zero. If ``m == 1``, a single scalar can
+ be given instead of a list.
+ lbnd : scalar, optional
+ The lower bound of the integral. (Default: 0)
+ scl : scalar, optional
+ Following each integration the result is *multiplied* by `scl`
+ before the integration constant is added. (Default: 1)
+ axis : int, optional
+ Axis over which the integral is taken. (Default: 0).
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ S : ndarray
+ C-series coefficients of the integral.
+
+ Raises
+ ------
+ ValueError
+ If ``m < 1``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
+ ``np.ndim(scl) != 0``.
+
+ See Also
+ --------
+ chebder
+
+ Notes
+ -----
+ Note that the result of each integration is *multiplied* by `scl`.
+ Why is this important to note? Say one is making a linear change of
+ variable :math:`u = ax + b` in an integral relative to `x`. Then
+ :math:`dx = du/a`, so one will need to set `scl` equal to
+ :math:`1/a`- perhaps not what one would have first thought.
+
+ Also note that, in general, the result of integrating a C-series needs
+ to be "reprojected" onto the C-series basis set. Thus, typically,
+ the result of this function is "unintuitive," albeit correct; see
+ Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial import chebyshev as C
+ >>> c = (1,2,3)
+ >>> C.chebint(c)
+ array([ 0.5, -0.5, 0.5, 0.5])
+ >>> C.chebint(c,3)
+ array([ 0.03125 , -0.1875 , 0.04166667, -0.05208333, 0.01041667, # may vary
+ 0.00625 ])
+ >>> C.chebint(c, k=3)
+ array([ 3.5, -0.5, 0.5, 0.5])
+ >>> C.chebint(c,lbnd=-2)
+ array([ 8.5, -0.5, 0.5, 0.5])
+ >>> C.chebint(c,scl=-2)
+ array([-1., 1., -1., -1.])
+
+ """
+ c = np.array(c, ndmin=1, copy=True)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ c = c.astype(np.double)
+ if not np.iterable(k):
+ k = [k]
+ cnt = pu._deprecate_as_int(m, "the order of integration")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
+ if cnt < 0:
+ raise ValueError("The order of integration must be non-negative")
+ if len(k) > cnt:
+ raise ValueError("Too many integration constants")
+ if np.ndim(lbnd) != 0:
+ raise ValueError("lbnd must be a scalar.")
+ if np.ndim(scl) != 0:
+ raise ValueError("scl must be a scalar.")
+ iaxis = normalize_axis_index(iaxis, c.ndim)
+
+ if cnt == 0:
+ return c
+
+ c = np.moveaxis(c, iaxis, 0)
+ k = list(k) + [0]*(cnt - len(k))
+ for i in range(cnt):
+ n = len(c)
+ c *= scl
+ if n == 1 and np.all(c[0] == 0):
+ c[0] += k[i]
+ else:
+ tmp = np.empty((n + 1,) + c.shape[1:], dtype=c.dtype)
+ tmp[0] = c[0]*0
+ tmp[1] = c[0]
+ if n > 1:
+ tmp[2] = c[1]/4
+ for j in range(2, n):
+ tmp[j + 1] = c[j]/(2*(j + 1))
+ tmp[j - 1] -= c[j]/(2*(j - 1))
+ tmp[0] += k[i] - chebval(lbnd, tmp)
+ c = tmp
+ c = np.moveaxis(c, 0, iaxis)
+ return c
+
+
+def chebval(x, c, tensor=True):
+ """
+ Evaluate a Chebyshev series at points x.
+
+ If `c` is of length `n + 1`, this function returns the value:
+
+ .. math:: p(x) = c_0 * T_0(x) + c_1 * T_1(x) + ... + c_n * T_n(x)
+
+ The parameter `x` is converted to an array only if it is a tuple or a
+ list, otherwise it is treated as a scalar. In either case, either `x`
+ or its elements must support multiplication and addition both with
+ themselves and with the elements of `c`.
+
+ If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
+ `c` is multidimensional, then the shape of the result depends on the
+ value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
+ x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
+ scalars have shape (,).
+
+ Trailing zeros in the coefficients will be used in the evaluation, so
+ they should be avoided if efficiency is a concern.
+
+ Parameters
+ ----------
+ x : array_like, compatible object
+ If `x` is a list or tuple, it is converted to an ndarray, otherwise
+ it is left unchanged and treated as a scalar. In either case, `x`
+ or its elements must support addition and multiplication with
+ themselves and with the elements of `c`.
+ c : array_like
+ Array of coefficients ordered so that the coefficients for terms of
+ degree n are contained in c[n]. If `c` is multidimensional the
+ remaining indices enumerate multiple polynomials. In the two
+ dimensional case the coefficients may be thought of as stored in
+ the columns of `c`.
+ tensor : boolean, optional
+ If True, the shape of the coefficient array is extended with ones
+ on the right, one for each dimension of `x`. Scalars have dimension 0
+ for this action. The result is that every column of coefficients in
+ `c` is evaluated for every element of `x`. If False, `x` is broadcast
+ over the columns of `c` for the evaluation. This keyword is useful
+ when `c` is multidimensional. The default value is True.
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ values : ndarray, algebra_like
+ The shape of the return value is described above.
+
+ See Also
+ --------
+ chebval2d, chebgrid2d, chebval3d, chebgrid3d
+
+ Notes
+ -----
+ The evaluation uses Clenshaw recursion, aka synthetic division.
+
+ """
+ c = np.array(c, ndmin=1, copy=True)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ c = c.astype(np.double)
+ if isinstance(x, (tuple, list)):
+ x = np.asarray(x)
+ if isinstance(x, np.ndarray) and tensor:
+ c = c.reshape(c.shape + (1,)*x.ndim)
+
+ if len(c) == 1:
+ c0 = c[0]
+ c1 = 0
+ elif len(c) == 2:
+ c0 = c[0]
+ c1 = c[1]
+ else:
+ x2 = 2*x
+ c0 = c[-2]
+ c1 = c[-1]
+ for i in range(3, len(c) + 1):
+ tmp = c0
+ c0 = c[-i] - c1
+ c1 = tmp + c1*x2
+ return c0 + c1*x
+
+
+def chebval2d(x, y, c):
+ """
+ Evaluate a 2-D Chebyshev series at points (x, y).
+
+ This function returns the values:
+
+ .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * T_i(x) * T_j(y)
+
+ The parameters `x` and `y` are converted to arrays only if they are
+ tuples or a lists, otherwise they are treated as a scalars and they
+ must have the same shape after conversion. In either case, either `x`
+ and `y` or their elements must support multiplication and addition both
+ with themselves and with the elements of `c`.
+
+ If `c` is a 1-D array a one is implicitly appended to its shape to make
+ it 2-D. The shape of the result will be c.shape[2:] + x.shape.
+
+ Parameters
+ ----------
+ x, y : array_like, compatible objects
+ The two dimensional series is evaluated at the points `(x, y)`,
+ where `x` and `y` must have the same shape. If `x` or `y` is a list
+ or tuple, it is first converted to an ndarray, otherwise it is left
+ unchanged and if it isn't an ndarray it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficient of the term
+ of multi-degree i,j is contained in ``c[i,j]``. If `c` has
+ dimension greater than 2 the remaining indices enumerate multiple
+ sets of coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional Chebyshev series at points formed
+ from pairs of corresponding values from `x` and `y`.
+
+ See Also
+ --------
+ chebval, chebgrid2d, chebval3d, chebgrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._valnd(chebval, c, x, y)
+
+
+def chebgrid2d(x, y, c):
+ """
+ Evaluate a 2-D Chebyshev series on the Cartesian product of x and y.
+
+ This function returns the values:
+
+ .. math:: p(a,b) = \\sum_{i,j} c_{i,j} * T_i(a) * T_j(b),
+
+ where the points `(a, b)` consist of all pairs formed by taking
+ `a` from `x` and `b` from `y`. The resulting points form a grid with
+ `x` in the first dimension and `y` in the second.
+
+ The parameters `x` and `y` are converted to arrays only if they are
+ tuples or a lists, otherwise they are treated as a scalars. In either
+ case, either `x` and `y` or their elements must support multiplication
+ and addition both with themselves and with the elements of `c`.
+
+ If `c` has fewer than two dimensions, ones are implicitly appended to
+ its shape to make it 2-D. The shape of the result will be c.shape[2:] +
+ x.shape + y.shape.
+
+ Parameters
+ ----------
+ x, y : array_like, compatible objects
+ The two dimensional series is evaluated at the points in the
+ Cartesian product of `x` and `y`. If `x` or `y` is a list or
+ tuple, it is first converted to an ndarray, otherwise it is left
+ unchanged and, if it isn't an ndarray, it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficient of the term of
+ multi-degree i,j is contained in `c[i,j]`. If `c` has dimension
+ greater than two the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional Chebyshev series at points in the
+ Cartesian product of `x` and `y`.
+
+ See Also
+ --------
+ chebval, chebval2d, chebval3d, chebgrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._gridnd(chebval, c, x, y)
+
+
+def chebval3d(x, y, z, c):
+ """
+ Evaluate a 3-D Chebyshev series at points (x, y, z).
+
+ This function returns the values:
+
+ .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * T_i(x) * T_j(y) * T_k(z)
+
+ The parameters `x`, `y`, and `z` are converted to arrays only if
+ they are tuples or a lists, otherwise they are treated as a scalars and
+ they must have the same shape after conversion. In either case, either
+ `x`, `y`, and `z` or their elements must support multiplication and
+ addition both with themselves and with the elements of `c`.
+
+ If `c` has fewer than 3 dimensions, ones are implicitly appended to its
+ shape to make it 3-D. The shape of the result will be c.shape[3:] +
+ x.shape.
+
+ Parameters
+ ----------
+ x, y, z : array_like, compatible object
+ The three dimensional series is evaluated at the points
+ `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
+ any of `x`, `y`, or `z` is a list or tuple, it is first converted
+ to an ndarray, otherwise it is left unchanged and if it isn't an
+ ndarray it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficient of the term of
+ multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
+ greater than 3 the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the multidimensional polynomial on points formed with
+ triples of corresponding values from `x`, `y`, and `z`.
+
+ See Also
+ --------
+ chebval, chebval2d, chebgrid2d, chebgrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._valnd(chebval, c, x, y, z)
+
+
+def chebgrid3d(x, y, z, c):
+ """
+ Evaluate a 3-D Chebyshev series on the Cartesian product of x, y, and z.
+
+ This function returns the values:
+
+ .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * T_i(a) * T_j(b) * T_k(c)
+
+ where the points `(a, b, c)` consist of all triples formed by taking
+ `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
+ a grid with `x` in the first dimension, `y` in the second, and `z` in
+ the third.
+
+ The parameters `x`, `y`, and `z` are converted to arrays only if they
+ are tuples or a lists, otherwise they are treated as a scalars. In
+ either case, either `x`, `y`, and `z` or their elements must support
+ multiplication and addition both with themselves and with the elements
+ of `c`.
+
+ If `c` has fewer than three dimensions, ones are implicitly appended to
+ its shape to make it 3-D. The shape of the result will be c.shape[3:] +
+ x.shape + y.shape + z.shape.
+
+ Parameters
+ ----------
+ x, y, z : array_like, compatible objects
+ The three dimensional series is evaluated at the points in the
+ Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
+ list or tuple, it is first converted to an ndarray, otherwise it is
+ left unchanged and, if it isn't an ndarray, it is treated as a
+ scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficients for terms of
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
+ greater than two the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional polynomial at points in the Cartesian
+ product of `x` and `y`.
+
+ See Also
+ --------
+ chebval, chebval2d, chebgrid2d, chebval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._gridnd(chebval, c, x, y, z)
+
+
+def chebvander(x, deg):
+ """Pseudo-Vandermonde matrix of given degree.
+
+ Returns the pseudo-Vandermonde matrix of degree `deg` and sample points
+ `x`. The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., i] = T_i(x),
+
+ where `0 <= i <= deg`. The leading indices of `V` index the elements of
+ `x` and the last index is the degree of the Chebyshev polynomial.
+
+ If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
+ matrix ``V = chebvander(x, n)``, then ``np.dot(V, c)`` and
+ ``chebval(x, c)`` are the same up to roundoff. This equivalence is
+ useful both for least squares fitting and for the evaluation of a large
+ number of Chebyshev series of the same degree and sample points.
+
+ Parameters
+ ----------
+ x : array_like
+ Array of points. The dtype is converted to float64 or complex128
+ depending on whether any of the elements are complex. If `x` is
+ scalar it is converted to a 1-D array.
+ deg : int
+ Degree of the resulting matrix.
+
+ Returns
+ -------
+ vander : ndarray
+ The pseudo Vandermonde matrix. The shape of the returned matrix is
+ ``x.shape + (deg + 1,)``, where The last index is the degree of the
+ corresponding Chebyshev polynomial. The dtype will be the same as
+ the converted `x`.
+
+ """
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg < 0:
+ raise ValueError("deg must be non-negative")
+
+ x = np.array(x, copy=False, ndmin=1) + 0.0
+ dims = (ideg + 1,) + x.shape
+ dtyp = x.dtype
+ v = np.empty(dims, dtype=dtyp)
+ # Use forward recursion to generate the entries.
+ v[0] = x*0 + 1
+ if ideg > 0:
+ x2 = 2*x
+ v[1] = x
+ for i in range(2, ideg + 1):
+ v[i] = v[i-1]*x2 - v[i-2]
+ return np.moveaxis(v, 0, -1)
+
+
+def chebvander2d(x, y, deg):
+ """Pseudo-Vandermonde matrix of given degrees.
+
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
+ points `(x, y)`. The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., (deg[1] + 1)*i + j] = T_i(x) * T_j(y),
+
+ where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
+ `V` index the points `(x, y)` and the last index encodes the degrees of
+ the Chebyshev polynomials.
+
+ If ``V = chebvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
+ correspond to the elements of a 2-D coefficient array `c` of shape
+ (xdeg + 1, ydeg + 1) in the order
+
+ .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
+
+ and ``np.dot(V, c.flat)`` and ``chebval2d(x, y, c)`` will be the same
+ up to roundoff. This equivalence is useful both for least squares
+ fitting and for the evaluation of a large number of 2-D Chebyshev
+ series of the same degrees and sample points.
+
+ Parameters
+ ----------
+ x, y : array_like
+ Arrays of point coordinates, all of the same shape. The dtypes
+ will be converted to either float64 or complex128 depending on
+ whether any of the elements are complex. Scalars are converted to
+ 1-D arrays.
+ deg : list of ints
+ List of maximum degrees of the form [x_deg, y_deg].
+
+ Returns
+ -------
+ vander2d : ndarray
+ The shape of the returned matrix is ``x.shape + (order,)``, where
+ :math:`order = (deg[0]+1)*(deg[1]+1)`. The dtype will be the same
+ as the converted `x` and `y`.
+
+ See Also
+ --------
+ chebvander, chebvander3d, chebval2d, chebval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._vander_nd_flat((chebvander, chebvander), (x, y), deg)
+
+
+def chebvander3d(x, y, z, deg):
+ """Pseudo-Vandermonde matrix of given degrees.
+
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
+ points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
+ then The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = T_i(x)*T_j(y)*T_k(z),
+
+ where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
+ indices of `V` index the points `(x, y, z)` and the last index encodes
+ the degrees of the Chebyshev polynomials.
+
+ If ``V = chebvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
+ of `V` correspond to the elements of a 3-D coefficient array `c` of
+ shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
+
+ .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
+
+ and ``np.dot(V, c.flat)`` and ``chebval3d(x, y, z, c)`` will be the
+ same up to roundoff. This equivalence is useful both for least squares
+ fitting and for the evaluation of a large number of 3-D Chebyshev
+ series of the same degrees and sample points.
+
+ Parameters
+ ----------
+ x, y, z : array_like
+ Arrays of point coordinates, all of the same shape. The dtypes will
+ be converted to either float64 or complex128 depending on whether
+ any of the elements are complex. Scalars are converted to 1-D
+ arrays.
+ deg : list of ints
+ List of maximum degrees of the form [x_deg, y_deg, z_deg].
+
+ Returns
+ -------
+ vander3d : ndarray
+ The shape of the returned matrix is ``x.shape + (order,)``, where
+ :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`. The dtype will
+ be the same as the converted `x`, `y`, and `z`.
+
+ See Also
+ --------
+ chebvander, chebvander3d, chebval2d, chebval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._vander_nd_flat((chebvander, chebvander, chebvander), (x, y, z), deg)
+
+
+def chebfit(x, y, deg, rcond=None, full=False, w=None):
+ """
+ Least squares fit of Chebyshev series to data.
+
+ Return the coefficients of a Chebyshev series of degree `deg` that is the
+ least squares fit to the data values `y` given at points `x`. If `y` is
+ 1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
+ fits are done, one for each column of `y`, and the resulting
+ coefficients are stored in the corresponding columns of a 2-D return.
+ The fitted polynomial(s) are in the form
+
+ .. math:: p(x) = c_0 + c_1 * T_1(x) + ... + c_n * T_n(x),
+
+ where `n` is `deg`.
+
+ Parameters
+ ----------
+ x : array_like, shape (M,)
+ x-coordinates of the M sample points ``(x[i], y[i])``.
+ y : array_like, shape (M,) or (M, K)
+ y-coordinates of the sample points. Several data sets of sample
+ points sharing the same x-coordinates can be fitted at once by
+ passing in a 2D-array that contains one dataset per column.
+ deg : int or 1-D array_like
+ Degree(s) of the fitting polynomials. If `deg` is a single integer,
+ all terms up to and including the `deg`'th term are included in the
+ fit. For NumPy versions >= 1.11.0 a list of integers specifying the
+ degrees of the terms to include may be used instead.
+ rcond : float, optional
+ Relative condition number of the fit. Singular values smaller than
+ this relative to the largest singular value will be ignored. The
+ default value is len(x)*eps, where eps is the relative precision of
+ the float type, about 2e-16 in most cases.
+ full : bool, optional
+ Switch determining nature of return value. When it is False (the
+ default) just the coefficients are returned, when True diagnostic
+ information from the singular value decomposition is also returned.
+ w : array_like, shape (`M`,), optional
+ Weights. If not None, the weight ``w[i]`` applies to the unsquared
+ residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
+ chosen so that the errors of the products ``w[i]*y[i]`` all have the
+ same variance. When using inverse-variance weighting, use
+ ``w[i] = 1/sigma(y[i])``. The default value is None.
+
+ .. versionadded:: 1.5.0
+
+ Returns
+ -------
+ coef : ndarray, shape (M,) or (M, K)
+ Chebyshev coefficients ordered from low to high. If `y` was 2-D,
+ the coefficients for the data in column k of `y` are in column
+ `k`.
+
+ [residuals, rank, singular_values, rcond] : list
+ These values are only returned if ``full == True``
+
+ - residuals -- sum of squared residuals of the least squares fit
+ - rank -- the numerical rank of the scaled Vandermonde matrix
+ - singular_values -- singular values of the scaled Vandermonde matrix
+ - rcond -- value of `rcond`.
+
+ For more details, see `numpy.linalg.lstsq`.
+
+ Warns
+ -----
+ RankWarning
+ The rank of the coefficient matrix in the least-squares fit is
+ deficient. The warning is only raised if ``full == False``. The
+ warnings can be turned off by
+
+ >>> import warnings
+ >>> warnings.simplefilter('ignore', np.RankWarning)
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyfit
+ numpy.polynomial.legendre.legfit
+ numpy.polynomial.laguerre.lagfit
+ numpy.polynomial.hermite.hermfit
+ numpy.polynomial.hermite_e.hermefit
+ chebval : Evaluates a Chebyshev series.
+ chebvander : Vandermonde matrix of Chebyshev series.
+ chebweight : Chebyshev weight function.
+ numpy.linalg.lstsq : Computes a least-squares fit from the matrix.
+ scipy.interpolate.UnivariateSpline : Computes spline fits.
+
+ Notes
+ -----
+ The solution is the coefficients of the Chebyshev series `p` that
+ minimizes the sum of the weighted squared errors
+
+ .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
+
+ where :math:`w_j` are the weights. This problem is solved by setting up
+ as the (typically) overdetermined matrix equation
+
+ .. math:: V(x) * c = w * y,
+
+ where `V` is the weighted pseudo Vandermonde matrix of `x`, `c` are the
+ coefficients to be solved for, `w` are the weights, and `y` are the
+ observed values. This equation is then solved using the singular value
+ decomposition of `V`.
+
+ If some of the singular values of `V` are so small that they are
+ neglected, then a `RankWarning` will be issued. This means that the
+ coefficient values may be poorly determined. Using a lower order fit
+ will usually get rid of the warning. The `rcond` parameter can also be
+ set to a value smaller than its default, but the resulting fit may be
+ spurious and have large contributions from roundoff error.
+
+ Fits using Chebyshev series are usually better conditioned than fits
+ using power series, but much can depend on the distribution of the
+ sample points and the smoothness of the data. If the quality of the fit
+ is inadequate splines may be a good alternative.
+
+ References
+ ----------
+ .. [1] Wikipedia, "Curve fitting",
+ https://en.wikipedia.org/wiki/Curve_fitting
+
+ Examples
+ --------
+
+ """
+ return pu._fit(chebvander, x, y, deg, rcond, full, w)
+
+
+def chebcompanion(c):
+ """Return the scaled companion matrix of c.
+
+ The basis polynomials are scaled so that the companion matrix is
+ symmetric when `c` is a Chebyshev basis polynomial. This provides
+ better eigenvalue estimates than the unscaled case and for basis
+ polynomials the eigenvalues are guaranteed to be real if
+ `numpy.linalg.eigvalsh` is used to obtain them.
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of Chebyshev series coefficients ordered from low to high
+ degree.
+
+ Returns
+ -------
+ mat : ndarray
+ Scaled companion matrix of dimensions (deg, deg).
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ if len(c) < 2:
+ raise ValueError('Series must have maximum degree of at least 1.')
+ if len(c) == 2:
+ return np.array([[-c[0]/c[1]]])
+
+ n = len(c) - 1
+ mat = np.zeros((n, n), dtype=c.dtype)
+ scl = np.array([1.] + [np.sqrt(.5)]*(n-1))
+ top = mat.reshape(-1)[1::n+1]
+ bot = mat.reshape(-1)[n::n+1]
+ top[0] = np.sqrt(.5)
+ top[1:] = 1/2
+ bot[...] = top
+ mat[:, -1] -= (c[:-1]/c[-1])*(scl/scl[-1])*.5
+ return mat
+
+
+def chebroots(c):
+ """
+ Compute the roots of a Chebyshev series.
+
+ Return the roots (a.k.a. "zeros") of the polynomial
+
+ .. math:: p(x) = \\sum_i c[i] * T_i(x).
+
+ Parameters
+ ----------
+ c : 1-D array_like
+ 1-D array of coefficients.
+
+ Returns
+ -------
+ out : ndarray
+ Array of the roots of the series. If all the roots are real,
+ then `out` is also real, otherwise it is complex.
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyroots
+ numpy.polynomial.legendre.legroots
+ numpy.polynomial.laguerre.lagroots
+ numpy.polynomial.hermite.hermroots
+ numpy.polynomial.hermite_e.hermeroots
+
+ Notes
+ -----
+ The root estimates are obtained as the eigenvalues of the companion
+ matrix, Roots far from the origin of the complex plane may have large
+ errors due to the numerical instability of the series for such
+ values. Roots with multiplicity greater than 1 will also show larger
+ errors as the value of the series near such points is relatively
+ insensitive to errors in the roots. Isolated roots near the origin can
+ be improved by a few iterations of Newton's method.
+
+ The Chebyshev series basis polynomials aren't powers of `x` so the
+ results of this function may seem unintuitive.
+
+ Examples
+ --------
+ >>> import numpy.polynomial.chebyshev as cheb
+ >>> cheb.chebroots((-1, 1,-1, 1)) # T3 - T2 + T1 - T0 has real roots
+ array([ -5.00000000e-01, 2.60860684e-17, 1.00000000e+00]) # may vary
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ if len(c) < 2:
+ return np.array([], dtype=c.dtype)
+ if len(c) == 2:
+ return np.array([-c[0]/c[1]])
+
+ # rotated companion matrix reduces error
+ m = chebcompanion(c)[::-1,::-1]
+ r = la.eigvals(m)
+ r.sort()
+ return r
+
+
+def chebinterpolate(func, deg, args=()):
+ """Interpolate a function at the Chebyshev points of the first kind.
+
+ Returns the Chebyshev series that interpolates `func` at the Chebyshev
+ points of the first kind in the interval [-1, 1]. The interpolating
+ series tends to a minmax approximation to `func` with increasing `deg`
+ if the function is continuous in the interval.
+
+ .. versionadded:: 1.14.0
+
+ Parameters
+ ----------
+ func : function
+ The function to be approximated. It must be a function of a single
+ variable of the form ``f(x, a, b, c...)``, where ``a, b, c...`` are
+ extra arguments passed in the `args` parameter.
+ deg : int
+ Degree of the interpolating polynomial
+ args : tuple, optional
+ Extra arguments to be used in the function call. Default is no extra
+ arguments.
+
+ Returns
+ -------
+ coef : ndarray, shape (deg + 1,)
+ Chebyshev coefficients of the interpolating series ordered from low to
+ high.
+
+ Examples
+ --------
+ >>> import numpy.polynomial.chebyshev as C
+ >>> C.chebfromfunction(lambda x: np.tanh(x) + 0.5, 8)
+ array([ 5.00000000e-01, 8.11675684e-01, -9.86864911e-17,
+ -5.42457905e-02, -2.71387850e-16, 4.51658839e-03,
+ 2.46716228e-17, -3.79694221e-04, -3.26899002e-16])
+
+ Notes
+ -----
+
+ The Chebyshev polynomials used in the interpolation are orthogonal when
+ sampled at the Chebyshev points of the first kind. If it is desired to
+ constrain some of the coefficients they can simply be set to the desired
+ value after the interpolation, no new interpolation or fit is needed. This
+ is especially useful if it is known apriori that some of coefficients are
+ zero. For instance, if the function is even then the coefficients of the
+ terms of odd degree in the result can be set to zero.
+
+ """
+ deg = np.asarray(deg)
+
+ # check arguments.
+ if deg.ndim > 0 or deg.dtype.kind not in 'iu' or deg.size == 0:
+ raise TypeError("deg must be an int")
+ if deg < 0:
+ raise ValueError("expected deg >= 0")
+
+ order = deg + 1
+ xcheb = chebpts1(order)
+ yfunc = func(xcheb, *args)
+ m = chebvander(xcheb, deg)
+ c = np.dot(m.T, yfunc)
+ c[0] /= order
+ c[1:] /= 0.5*order
+
+ return c
+
+
+def chebgauss(deg):
+ """
+ Gauss-Chebyshev quadrature.
+
+ Computes the sample points and weights for Gauss-Chebyshev quadrature.
+ These sample points and weights will correctly integrate polynomials of
+ degree :math:`2*deg - 1` or less over the interval :math:`[-1, 1]` with
+ the weight function :math:`f(x) = 1/\\sqrt{1 - x^2}`.
+
+ Parameters
+ ----------
+ deg : int
+ Number of sample points and weights. It must be >= 1.
+
+ Returns
+ -------
+ x : ndarray
+ 1-D ndarray containing the sample points.
+ y : ndarray
+ 1-D ndarray containing the weights.
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ The results have only been tested up to degree 100, higher degrees may
+ be problematic. For Gauss-Chebyshev there are closed form solutions for
+ the sample points and weights. If n = `deg`, then
+
+ .. math:: x_i = \\cos(\\pi (2 i - 1) / (2 n))
+
+ .. math:: w_i = \\pi / n
+
+ """
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg <= 0:
+ raise ValueError("deg must be a positive integer")
+
+ x = np.cos(np.pi * np.arange(1, 2*ideg, 2) / (2.0*ideg))
+ w = np.ones(ideg)*(np.pi/ideg)
+
+ return x, w
+
+
+def chebweight(x):
+ """
+ The weight function of the Chebyshev polynomials.
+
+ The weight function is :math:`1/\\sqrt{1 - x^2}` and the interval of
+ integration is :math:`[-1, 1]`. The Chebyshev polynomials are
+ orthogonal, but not normalized, with respect to this weight function.
+
+ Parameters
+ ----------
+ x : array_like
+ Values at which the weight function will be computed.
+
+ Returns
+ -------
+ w : ndarray
+ The weight function at `x`.
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ w = 1./(np.sqrt(1. + x) * np.sqrt(1. - x))
+ return w
+
+
+def chebpts1(npts):
+ """
+ Chebyshev points of the first kind.
+
+ The Chebyshev points of the first kind are the points ``cos(x)``,
+ where ``x = [pi*(k + .5)/npts for k in range(npts)]``.
+
+ Parameters
+ ----------
+ npts : int
+ Number of sample points desired.
+
+ Returns
+ -------
+ pts : ndarray
+ The Chebyshev points of the first kind.
+
+ See Also
+ --------
+ chebpts2
+
+ Notes
+ -----
+
+ .. versionadded:: 1.5.0
+
+ """
+ _npts = int(npts)
+ if _npts != npts:
+ raise ValueError("npts must be integer")
+ if _npts < 1:
+ raise ValueError("npts must be >= 1")
+
+ x = 0.5 * np.pi / _npts * np.arange(-_npts+1, _npts+1, 2)
+ return np.sin(x)
+
+
+def chebpts2(npts):
+ """
+ Chebyshev points of the second kind.
+
+ The Chebyshev points of the second kind are the points ``cos(x)``,
+ where ``x = [pi*k/(npts - 1) for k in range(npts)]`` sorted in ascending
+ order.
+
+ Parameters
+ ----------
+ npts : int
+ Number of sample points desired.
+
+ Returns
+ -------
+ pts : ndarray
+ The Chebyshev points of the second kind.
+
+ Notes
+ -----
+
+ .. versionadded:: 1.5.0
+
+ """
+ _npts = int(npts)
+ if _npts != npts:
+ raise ValueError("npts must be integer")
+ if _npts < 2:
+ raise ValueError("npts must be >= 2")
+
+ x = np.linspace(-np.pi, 0, _npts)
+ return np.cos(x)
+
+
+#
+# Chebyshev series class
+#
+
+class Chebyshev(ABCPolyBase):
+ """A Chebyshev series class.
+
+ The Chebyshev class provides the standard Python numerical methods
+ '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
+ methods listed below.
+
+ Parameters
+ ----------
+ coef : array_like
+ Chebyshev coefficients in order of increasing degree, i.e.,
+ ``(1, 2, 3)`` gives ``1*T_0(x) + 2*T_1(x) + 3*T_2(x)``.
+ domain : (2,) array_like, optional
+ Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
+ to the interval ``[window[0], window[1]]`` by shifting and scaling.
+ The default value is [-1, 1].
+ window : (2,) array_like, optional
+ Window, see `domain` for its use. The default value is [-1, 1].
+
+ .. versionadded:: 1.6.0
+ symbol : str, optional
+ Symbol used to represent the independent variable in string
+ representations of the polynomial expression, e.g. for printing.
+ The symbol must be a valid Python identifier. Default value is 'x'.
+
+ .. versionadded:: 1.24
+
+ """
+ # Virtual Functions
+ _add = staticmethod(chebadd)
+ _sub = staticmethod(chebsub)
+ _mul = staticmethod(chebmul)
+ _div = staticmethod(chebdiv)
+ _pow = staticmethod(chebpow)
+ _val = staticmethod(chebval)
+ _int = staticmethod(chebint)
+ _der = staticmethod(chebder)
+ _fit = staticmethod(chebfit)
+ _line = staticmethod(chebline)
+ _roots = staticmethod(chebroots)
+ _fromroots = staticmethod(chebfromroots)
+
+ @classmethod
+ def interpolate(cls, func, deg, domain=None, args=()):
+ """Interpolate a function at the Chebyshev points of the first kind.
+
+ Returns the series that interpolates `func` at the Chebyshev points of
+ the first kind scaled and shifted to the `domain`. The resulting series
+ tends to a minmax approximation of `func` when the function is
+ continuous in the domain.
+
+ .. versionadded:: 1.14.0
+
+ Parameters
+ ----------
+ func : function
+ The function to be interpolated. It must be a function of a single
+ variable of the form ``f(x, a, b, c...)``, where ``a, b, c...`` are
+ extra arguments passed in the `args` parameter.
+ deg : int
+ Degree of the interpolating polynomial.
+ domain : {None, [beg, end]}, optional
+ Domain over which `func` is interpolated. The default is None, in
+ which case the domain is [-1, 1].
+ args : tuple, optional
+ Extra arguments to be used in the function call. Default is no
+ extra arguments.
+
+ Returns
+ -------
+ polynomial : Chebyshev instance
+ Interpolating Chebyshev instance.
+
+ Notes
+ -----
+ See `numpy.polynomial.chebfromfunction` for more details.
+
+ """
+ if domain is None:
+ domain = cls.domain
+ xfunc = lambda x: func(pu.mapdomain(x, cls.window, domain), *args)
+ coef = chebinterpolate(xfunc, deg)
+ return cls(coef, domain=domain)
+
+ # Virtual properties
+ domain = np.array(chebdomain)
+ window = np.array(chebdomain)
+ basis_name = 'T'
diff --git a/lib/python3.12/site-packages/numpy/polynomial/chebyshev.pyi b/lib/python3.12/site-packages/numpy/polynomial/chebyshev.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..e8113dbae780263de1bd99ae841df16a4646d761
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/chebyshev.pyi
@@ -0,0 +1,51 @@
+from typing import Any
+
+from numpy import ndarray, dtype, int_
+from numpy.polynomial._polybase import ABCPolyBase
+from numpy.polynomial.polyutils import trimcoef
+
+__all__: list[str]
+
+chebtrim = trimcoef
+
+def poly2cheb(pol): ...
+def cheb2poly(c): ...
+
+chebdomain: ndarray[Any, dtype[int_]]
+chebzero: ndarray[Any, dtype[int_]]
+chebone: ndarray[Any, dtype[int_]]
+chebx: ndarray[Any, dtype[int_]]
+
+def chebline(off, scl): ...
+def chebfromroots(roots): ...
+def chebadd(c1, c2): ...
+def chebsub(c1, c2): ...
+def chebmulx(c): ...
+def chebmul(c1, c2): ...
+def chebdiv(c1, c2): ...
+def chebpow(c, pow, maxpower=...): ...
+def chebder(c, m=..., scl=..., axis=...): ...
+def chebint(c, m=..., k = ..., lbnd=..., scl=..., axis=...): ...
+def chebval(x, c, tensor=...): ...
+def chebval2d(x, y, c): ...
+def chebgrid2d(x, y, c): ...
+def chebval3d(x, y, z, c): ...
+def chebgrid3d(x, y, z, c): ...
+def chebvander(x, deg): ...
+def chebvander2d(x, y, deg): ...
+def chebvander3d(x, y, z, deg): ...
+def chebfit(x, y, deg, rcond=..., full=..., w=...): ...
+def chebcompanion(c): ...
+def chebroots(c): ...
+def chebinterpolate(func, deg, args = ...): ...
+def chebgauss(deg): ...
+def chebweight(x): ...
+def chebpts1(npts): ...
+def chebpts2(npts): ...
+
+class Chebyshev(ABCPolyBase):
+ @classmethod
+ def interpolate(cls, func, deg, domain=..., args = ...): ...
+ domain: Any
+ window: Any
+ basis_name: Any
diff --git a/lib/python3.12/site-packages/numpy/polynomial/hermite.py b/lib/python3.12/site-packages/numpy/polynomial/hermite.py
new file mode 100644
index 0000000000000000000000000000000000000000..210df25f5ca3ace7aaa8c7614936e305097a6195
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/hermite.py
@@ -0,0 +1,1703 @@
+"""
+==============================================================
+Hermite Series, "Physicists" (:mod:`numpy.polynomial.hermite`)
+==============================================================
+
+This module provides a number of objects (mostly functions) useful for
+dealing with Hermite series, including a `Hermite` class that
+encapsulates the usual arithmetic operations. (General information
+on how this module represents and works with such polynomials is in the
+docstring for its "parent" sub-package, `numpy.polynomial`).
+
+Classes
+-------
+.. autosummary::
+ :toctree: generated/
+
+ Hermite
+
+Constants
+---------
+.. autosummary::
+ :toctree: generated/
+
+ hermdomain
+ hermzero
+ hermone
+ hermx
+
+Arithmetic
+----------
+.. autosummary::
+ :toctree: generated/
+
+ hermadd
+ hermsub
+ hermmulx
+ hermmul
+ hermdiv
+ hermpow
+ hermval
+ hermval2d
+ hermval3d
+ hermgrid2d
+ hermgrid3d
+
+Calculus
+--------
+.. autosummary::
+ :toctree: generated/
+
+ hermder
+ hermint
+
+Misc Functions
+--------------
+.. autosummary::
+ :toctree: generated/
+
+ hermfromroots
+ hermroots
+ hermvander
+ hermvander2d
+ hermvander3d
+ hermgauss
+ hermweight
+ hermcompanion
+ hermfit
+ hermtrim
+ hermline
+ herm2poly
+ poly2herm
+
+See also
+--------
+`numpy.polynomial`
+
+"""
+import numpy as np
+import numpy.linalg as la
+from numpy.core.multiarray import normalize_axis_index
+
+from . import polyutils as pu
+from ._polybase import ABCPolyBase
+
+__all__ = [
+ 'hermzero', 'hermone', 'hermx', 'hermdomain', 'hermline', 'hermadd',
+ 'hermsub', 'hermmulx', 'hermmul', 'hermdiv', 'hermpow', 'hermval',
+ 'hermder', 'hermint', 'herm2poly', 'poly2herm', 'hermfromroots',
+ 'hermvander', 'hermfit', 'hermtrim', 'hermroots', 'Hermite',
+ 'hermval2d', 'hermval3d', 'hermgrid2d', 'hermgrid3d', 'hermvander2d',
+ 'hermvander3d', 'hermcompanion', 'hermgauss', 'hermweight']
+
+hermtrim = pu.trimcoef
+
+
+def poly2herm(pol):
+ """
+ poly2herm(pol)
+
+ Convert a polynomial to a Hermite series.
+
+ Convert an array representing the coefficients of a polynomial (relative
+ to the "standard" basis) ordered from lowest degree to highest, to an
+ array of the coefficients of the equivalent Hermite series, ordered
+ from lowest to highest degree.
+
+ Parameters
+ ----------
+ pol : array_like
+ 1-D array containing the polynomial coefficients
+
+ Returns
+ -------
+ c : ndarray
+ 1-D array containing the coefficients of the equivalent Hermite
+ series.
+
+ See Also
+ --------
+ herm2poly
+
+ Notes
+ -----
+ The easy way to do conversions between polynomial basis sets
+ is to use the convert method of a class instance.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import poly2herm
+ >>> poly2herm(np.arange(4))
+ array([1. , 2.75 , 0.5 , 0.375])
+
+ """
+ [pol] = pu.as_series([pol])
+ deg = len(pol) - 1
+ res = 0
+ for i in range(deg, -1, -1):
+ res = hermadd(hermmulx(res), pol[i])
+ return res
+
+
+def herm2poly(c):
+ """
+ Convert a Hermite series to a polynomial.
+
+ Convert an array representing the coefficients of a Hermite series,
+ ordered from lowest degree to highest, to an array of the coefficients
+ of the equivalent polynomial (relative to the "standard" basis) ordered
+ from lowest to highest degree.
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array containing the Hermite series coefficients, ordered
+ from lowest order term to highest.
+
+ Returns
+ -------
+ pol : ndarray
+ 1-D array containing the coefficients of the equivalent polynomial
+ (relative to the "standard" basis) ordered from lowest order term
+ to highest.
+
+ See Also
+ --------
+ poly2herm
+
+ Notes
+ -----
+ The easy way to do conversions between polynomial basis sets
+ is to use the convert method of a class instance.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import herm2poly
+ >>> herm2poly([ 1. , 2.75 , 0.5 , 0.375])
+ array([0., 1., 2., 3.])
+
+ """
+ from .polynomial import polyadd, polysub, polymulx
+
+ [c] = pu.as_series([c])
+ n = len(c)
+ if n == 1:
+ return c
+ if n == 2:
+ c[1] *= 2
+ return c
+ else:
+ c0 = c[-2]
+ c1 = c[-1]
+ # i is the current degree of c1
+ for i in range(n - 1, 1, -1):
+ tmp = c0
+ c0 = polysub(c[i - 2], c1*(2*(i - 1)))
+ c1 = polyadd(tmp, polymulx(c1)*2)
+ return polyadd(c0, polymulx(c1)*2)
+
+#
+# These are constant arrays are of integer type so as to be compatible
+# with the widest range of other types, such as Decimal.
+#
+
+# Hermite
+hermdomain = np.array([-1, 1])
+
+# Hermite coefficients representing zero.
+hermzero = np.array([0])
+
+# Hermite coefficients representing one.
+hermone = np.array([1])
+
+# Hermite coefficients representing the identity x.
+hermx = np.array([0, 1/2])
+
+
+def hermline(off, scl):
+ """
+ Hermite series whose graph is a straight line.
+
+
+
+ Parameters
+ ----------
+ off, scl : scalars
+ The specified line is given by ``off + scl*x``.
+
+ Returns
+ -------
+ y : ndarray
+ This module's representation of the Hermite series for
+ ``off + scl*x``.
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyline
+ numpy.polynomial.chebyshev.chebline
+ numpy.polynomial.legendre.legline
+ numpy.polynomial.laguerre.lagline
+ numpy.polynomial.hermite_e.hermeline
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import hermline, hermval
+ >>> hermval(0,hermline(3, 2))
+ 3.0
+ >>> hermval(1,hermline(3, 2))
+ 5.0
+
+ """
+ if scl != 0:
+ return np.array([off, scl/2])
+ else:
+ return np.array([off])
+
+
+def hermfromroots(roots):
+ """
+ Generate a Hermite series with given roots.
+
+ The function returns the coefficients of the polynomial
+
+ .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
+
+ in Hermite form, where the `r_n` are the roots specified in `roots`.
+ If a zero has multiplicity n, then it must appear in `roots` n times.
+ For instance, if 2 is a root of multiplicity three and 3 is a root of
+ multiplicity 2, then `roots` looks something like [2, 2, 2, 3, 3]. The
+ roots can appear in any order.
+
+ If the returned coefficients are `c`, then
+
+ .. math:: p(x) = c_0 + c_1 * H_1(x) + ... + c_n * H_n(x)
+
+ The coefficient of the last term is not generally 1 for monic
+ polynomials in Hermite form.
+
+ Parameters
+ ----------
+ roots : array_like
+ Sequence containing the roots.
+
+ Returns
+ -------
+ out : ndarray
+ 1-D array of coefficients. If all roots are real then `out` is a
+ real array, if some of the roots are complex, then `out` is complex
+ even if all the coefficients in the result are real (see Examples
+ below).
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyfromroots
+ numpy.polynomial.legendre.legfromroots
+ numpy.polynomial.laguerre.lagfromroots
+ numpy.polynomial.chebyshev.chebfromroots
+ numpy.polynomial.hermite_e.hermefromroots
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import hermfromroots, hermval
+ >>> coef = hermfromroots((-1, 0, 1))
+ >>> hermval((-1, 0, 1), coef)
+ array([0., 0., 0.])
+ >>> coef = hermfromroots((-1j, 1j))
+ >>> hermval((-1j, 1j), coef)
+ array([0.+0.j, 0.+0.j])
+
+ """
+ return pu._fromroots(hermline, hermmul, roots)
+
+
+def hermadd(c1, c2):
+ """
+ Add one Hermite series to another.
+
+ Returns the sum of two Hermite series `c1` + `c2`. The arguments
+ are sequences of coefficients ordered from lowest order term to
+ highest, i.e., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Hermite series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Array representing the Hermite series of their sum.
+
+ See Also
+ --------
+ hermsub, hermmulx, hermmul, hermdiv, hermpow
+
+ Notes
+ -----
+ Unlike multiplication, division, etc., the sum of two Hermite series
+ is a Hermite series (without having to "reproject" the result onto
+ the basis set) so addition, just like that of "standard" polynomials,
+ is simply "component-wise."
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import hermadd
+ >>> hermadd([1, 2, 3], [1, 2, 3, 4])
+ array([2., 4., 6., 4.])
+
+ """
+ return pu._add(c1, c2)
+
+
+def hermsub(c1, c2):
+ """
+ Subtract one Hermite series from another.
+
+ Returns the difference of two Hermite series `c1` - `c2`. The
+ sequences of coefficients are from lowest order term to highest, i.e.,
+ [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Hermite series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Of Hermite series coefficients representing their difference.
+
+ See Also
+ --------
+ hermadd, hermmulx, hermmul, hermdiv, hermpow
+
+ Notes
+ -----
+ Unlike multiplication, division, etc., the difference of two Hermite
+ series is a Hermite series (without having to "reproject" the result
+ onto the basis set) so subtraction, just like that of "standard"
+ polynomials, is simply "component-wise."
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import hermsub
+ >>> hermsub([1, 2, 3, 4], [1, 2, 3])
+ array([0., 0., 0., 4.])
+
+ """
+ return pu._sub(c1, c2)
+
+
+def hermmulx(c):
+ """Multiply a Hermite series by x.
+
+ Multiply the Hermite series `c` by x, where x is the independent
+ variable.
+
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of Hermite series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Array representing the result of the multiplication.
+
+ See Also
+ --------
+ hermadd, hermsub, hermmul, hermdiv, hermpow
+
+ Notes
+ -----
+ The multiplication uses the recursion relationship for Hermite
+ polynomials in the form
+
+ .. math::
+
+ xP_i(x) = (P_{i + 1}(x)/2 + i*P_{i - 1}(x))
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import hermmulx
+ >>> hermmulx([1, 2, 3])
+ array([2. , 6.5, 1. , 1.5])
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ # The zero series needs special treatment
+ if len(c) == 1 and c[0] == 0:
+ return c
+
+ prd = np.empty(len(c) + 1, dtype=c.dtype)
+ prd[0] = c[0]*0
+ prd[1] = c[0]/2
+ for i in range(1, len(c)):
+ prd[i + 1] = c[i]/2
+ prd[i - 1] += c[i]*i
+ return prd
+
+
+def hermmul(c1, c2):
+ """
+ Multiply one Hermite series by another.
+
+ Returns the product of two Hermite series `c1` * `c2`. The arguments
+ are sequences of coefficients, from lowest order "term" to highest,
+ e.g., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Hermite series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Of Hermite series coefficients representing their product.
+
+ See Also
+ --------
+ hermadd, hermsub, hermmulx, hermdiv, hermpow
+
+ Notes
+ -----
+ In general, the (polynomial) product of two C-series results in terms
+ that are not in the Hermite polynomial basis set. Thus, to express
+ the product as a Hermite series, it is necessary to "reproject" the
+ product onto said basis set, which may produce "unintuitive" (but
+ correct) results; see Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import hermmul
+ >>> hermmul([1, 2, 3], [0, 1, 2])
+ array([52., 29., 52., 7., 6.])
+
+ """
+ # s1, s2 are trimmed copies
+ [c1, c2] = pu.as_series([c1, c2])
+
+ if len(c1) > len(c2):
+ c = c2
+ xs = c1
+ else:
+ c = c1
+ xs = c2
+
+ if len(c) == 1:
+ c0 = c[0]*xs
+ c1 = 0
+ elif len(c) == 2:
+ c0 = c[0]*xs
+ c1 = c[1]*xs
+ else:
+ nd = len(c)
+ c0 = c[-2]*xs
+ c1 = c[-1]*xs
+ for i in range(3, len(c) + 1):
+ tmp = c0
+ nd = nd - 1
+ c0 = hermsub(c[-i]*xs, c1*(2*(nd - 1)))
+ c1 = hermadd(tmp, hermmulx(c1)*2)
+ return hermadd(c0, hermmulx(c1)*2)
+
+
+def hermdiv(c1, c2):
+ """
+ Divide one Hermite series by another.
+
+ Returns the quotient-with-remainder of two Hermite series
+ `c1` / `c2`. The arguments are sequences of coefficients from lowest
+ order "term" to highest, e.g., [1,2,3] represents the series
+ ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Hermite series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ [quo, rem] : ndarrays
+ Of Hermite series coefficients representing the quotient and
+ remainder.
+
+ See Also
+ --------
+ hermadd, hermsub, hermmulx, hermmul, hermpow
+
+ Notes
+ -----
+ In general, the (polynomial) division of one Hermite series by another
+ results in quotient and remainder terms that are not in the Hermite
+ polynomial basis set. Thus, to express these results as a Hermite
+ series, it is necessary to "reproject" the results onto the Hermite
+ basis set, which may produce "unintuitive" (but correct) results; see
+ Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import hermdiv
+ >>> hermdiv([ 52., 29., 52., 7., 6.], [0, 1, 2])
+ (array([1., 2., 3.]), array([0.]))
+ >>> hermdiv([ 54., 31., 52., 7., 6.], [0, 1, 2])
+ (array([1., 2., 3.]), array([2., 2.]))
+ >>> hermdiv([ 53., 30., 52., 7., 6.], [0, 1, 2])
+ (array([1., 2., 3.]), array([1., 1.]))
+
+ """
+ return pu._div(hermmul, c1, c2)
+
+
+def hermpow(c, pow, maxpower=16):
+ """Raise a Hermite series to a power.
+
+ Returns the Hermite series `c` raised to the power `pow`. The
+ argument `c` is a sequence of coefficients ordered from low to high.
+ i.e., [1,2,3] is the series ``P_0 + 2*P_1 + 3*P_2.``
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of Hermite series coefficients ordered from low to
+ high.
+ pow : integer
+ Power to which the series will be raised
+ maxpower : integer, optional
+ Maximum power allowed. This is mainly to limit growth of the series
+ to unmanageable size. Default is 16
+
+ Returns
+ -------
+ coef : ndarray
+ Hermite series of power.
+
+ See Also
+ --------
+ hermadd, hermsub, hermmulx, hermmul, hermdiv
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import hermpow
+ >>> hermpow([1, 2, 3], 2)
+ array([81., 52., 82., 12., 9.])
+
+ """
+ return pu._pow(hermmul, c, pow, maxpower)
+
+
+def hermder(c, m=1, scl=1, axis=0):
+ """
+ Differentiate a Hermite series.
+
+ Returns the Hermite series coefficients `c` differentiated `m` times
+ along `axis`. At each iteration the result is multiplied by `scl` (the
+ scaling factor is for use in a linear change of variable). The argument
+ `c` is an array of coefficients from low to high degree along each
+ axis, e.g., [1,2,3] represents the series ``1*H_0 + 2*H_1 + 3*H_2``
+ while [[1,2],[1,2]] represents ``1*H_0(x)*H_0(y) + 1*H_1(x)*H_0(y) +
+ 2*H_0(x)*H_1(y) + 2*H_1(x)*H_1(y)`` if axis=0 is ``x`` and axis=1 is
+ ``y``.
+
+ Parameters
+ ----------
+ c : array_like
+ Array of Hermite series coefficients. If `c` is multidimensional the
+ different axis correspond to different variables with the degree in
+ each axis given by the corresponding index.
+ m : int, optional
+ Number of derivatives taken, must be non-negative. (Default: 1)
+ scl : scalar, optional
+ Each differentiation is multiplied by `scl`. The end result is
+ multiplication by ``scl**m``. This is for use in a linear change of
+ variable. (Default: 1)
+ axis : int, optional
+ Axis over which the derivative is taken. (Default: 0).
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ der : ndarray
+ Hermite series of the derivative.
+
+ See Also
+ --------
+ hermint
+
+ Notes
+ -----
+ In general, the result of differentiating a Hermite series does not
+ resemble the same operation on a power series. Thus the result of this
+ function may be "unintuitive," albeit correct; see Examples section
+ below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import hermder
+ >>> hermder([ 1. , 0.5, 0.5, 0.5])
+ array([1., 2., 3.])
+ >>> hermder([-0.5, 1./2., 1./8., 1./12., 1./16.], m=2)
+ array([1., 2., 3.])
+
+ """
+ c = np.array(c, ndmin=1, copy=True)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ c = c.astype(np.double)
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
+ if cnt < 0:
+ raise ValueError("The order of derivation must be non-negative")
+ iaxis = normalize_axis_index(iaxis, c.ndim)
+
+ if cnt == 0:
+ return c
+
+ c = np.moveaxis(c, iaxis, 0)
+ n = len(c)
+ if cnt >= n:
+ c = c[:1]*0
+ else:
+ for i in range(cnt):
+ n = n - 1
+ c *= scl
+ der = np.empty((n,) + c.shape[1:], dtype=c.dtype)
+ for j in range(n, 0, -1):
+ der[j - 1] = (2*j)*c[j]
+ c = der
+ c = np.moveaxis(c, 0, iaxis)
+ return c
+
+
+def hermint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
+ """
+ Integrate a Hermite series.
+
+ Returns the Hermite series coefficients `c` integrated `m` times from
+ `lbnd` along `axis`. At each iteration the resulting series is
+ **multiplied** by `scl` and an integration constant, `k`, is added.
+ The scaling factor is for use in a linear change of variable. ("Buyer
+ beware": note that, depending on what one is doing, one may want `scl`
+ to be the reciprocal of what one might expect; for more information,
+ see the Notes section below.) The argument `c` is an array of
+ coefficients from low to high degree along each axis, e.g., [1,2,3]
+ represents the series ``H_0 + 2*H_1 + 3*H_2`` while [[1,2],[1,2]]
+ represents ``1*H_0(x)*H_0(y) + 1*H_1(x)*H_0(y) + 2*H_0(x)*H_1(y) +
+ 2*H_1(x)*H_1(y)`` if axis=0 is ``x`` and axis=1 is ``y``.
+
+ Parameters
+ ----------
+ c : array_like
+ Array of Hermite series coefficients. If c is multidimensional the
+ different axis correspond to different variables with the degree in
+ each axis given by the corresponding index.
+ m : int, optional
+ Order of integration, must be positive. (Default: 1)
+ k : {[], list, scalar}, optional
+ Integration constant(s). The value of the first integral at
+ ``lbnd`` is the first value in the list, the value of the second
+ integral at ``lbnd`` is the second value, etc. If ``k == []`` (the
+ default), all constants are set to zero. If ``m == 1``, a single
+ scalar can be given instead of a list.
+ lbnd : scalar, optional
+ The lower bound of the integral. (Default: 0)
+ scl : scalar, optional
+ Following each integration the result is *multiplied* by `scl`
+ before the integration constant is added. (Default: 1)
+ axis : int, optional
+ Axis over which the integral is taken. (Default: 0).
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ S : ndarray
+ Hermite series coefficients of the integral.
+
+ Raises
+ ------
+ ValueError
+ If ``m < 0``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
+ ``np.ndim(scl) != 0``.
+
+ See Also
+ --------
+ hermder
+
+ Notes
+ -----
+ Note that the result of each integration is *multiplied* by `scl`.
+ Why is this important to note? Say one is making a linear change of
+ variable :math:`u = ax + b` in an integral relative to `x`. Then
+ :math:`dx = du/a`, so one will need to set `scl` equal to
+ :math:`1/a` - perhaps not what one would have first thought.
+
+ Also note that, in general, the result of integrating a C-series needs
+ to be "reprojected" onto the C-series basis set. Thus, typically,
+ the result of this function is "unintuitive," albeit correct; see
+ Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import hermint
+ >>> hermint([1,2,3]) # integrate once, value 0 at 0.
+ array([1. , 0.5, 0.5, 0.5])
+ >>> hermint([1,2,3], m=2) # integrate twice, value & deriv 0 at 0
+ array([-0.5 , 0.5 , 0.125 , 0.08333333, 0.0625 ]) # may vary
+ >>> hermint([1,2,3], k=1) # integrate once, value 1 at 0.
+ array([2. , 0.5, 0.5, 0.5])
+ >>> hermint([1,2,3], lbnd=-1) # integrate once, value 0 at -1
+ array([-2. , 0.5, 0.5, 0.5])
+ >>> hermint([1,2,3], m=2, k=[1,2], lbnd=-1)
+ array([ 1.66666667, -0.5 , 0.125 , 0.08333333, 0.0625 ]) # may vary
+
+ """
+ c = np.array(c, ndmin=1, copy=True)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ c = c.astype(np.double)
+ if not np.iterable(k):
+ k = [k]
+ cnt = pu._deprecate_as_int(m, "the order of integration")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
+ if cnt < 0:
+ raise ValueError("The order of integration must be non-negative")
+ if len(k) > cnt:
+ raise ValueError("Too many integration constants")
+ if np.ndim(lbnd) != 0:
+ raise ValueError("lbnd must be a scalar.")
+ if np.ndim(scl) != 0:
+ raise ValueError("scl must be a scalar.")
+ iaxis = normalize_axis_index(iaxis, c.ndim)
+
+ if cnt == 0:
+ return c
+
+ c = np.moveaxis(c, iaxis, 0)
+ k = list(k) + [0]*(cnt - len(k))
+ for i in range(cnt):
+ n = len(c)
+ c *= scl
+ if n == 1 and np.all(c[0] == 0):
+ c[0] += k[i]
+ else:
+ tmp = np.empty((n + 1,) + c.shape[1:], dtype=c.dtype)
+ tmp[0] = c[0]*0
+ tmp[1] = c[0]/2
+ for j in range(1, n):
+ tmp[j + 1] = c[j]/(2*(j + 1))
+ tmp[0] += k[i] - hermval(lbnd, tmp)
+ c = tmp
+ c = np.moveaxis(c, 0, iaxis)
+ return c
+
+
+def hermval(x, c, tensor=True):
+ """
+ Evaluate an Hermite series at points x.
+
+ If `c` is of length `n + 1`, this function returns the value:
+
+ .. math:: p(x) = c_0 * H_0(x) + c_1 * H_1(x) + ... + c_n * H_n(x)
+
+ The parameter `x` is converted to an array only if it is a tuple or a
+ list, otherwise it is treated as a scalar. In either case, either `x`
+ or its elements must support multiplication and addition both with
+ themselves and with the elements of `c`.
+
+ If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
+ `c` is multidimensional, then the shape of the result depends on the
+ value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
+ x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
+ scalars have shape (,).
+
+ Trailing zeros in the coefficients will be used in the evaluation, so
+ they should be avoided if efficiency is a concern.
+
+ Parameters
+ ----------
+ x : array_like, compatible object
+ If `x` is a list or tuple, it is converted to an ndarray, otherwise
+ it is left unchanged and treated as a scalar. In either case, `x`
+ or its elements must support addition and multiplication with
+ themselves and with the elements of `c`.
+ c : array_like
+ Array of coefficients ordered so that the coefficients for terms of
+ degree n are contained in c[n]. If `c` is multidimensional the
+ remaining indices enumerate multiple polynomials. In the two
+ dimensional case the coefficients may be thought of as stored in
+ the columns of `c`.
+ tensor : boolean, optional
+ If True, the shape of the coefficient array is extended with ones
+ on the right, one for each dimension of `x`. Scalars have dimension 0
+ for this action. The result is that every column of coefficients in
+ `c` is evaluated for every element of `x`. If False, `x` is broadcast
+ over the columns of `c` for the evaluation. This keyword is useful
+ when `c` is multidimensional. The default value is True.
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ values : ndarray, algebra_like
+ The shape of the return value is described above.
+
+ See Also
+ --------
+ hermval2d, hermgrid2d, hermval3d, hermgrid3d
+
+ Notes
+ -----
+ The evaluation uses Clenshaw recursion, aka synthetic division.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import hermval
+ >>> coef = [1,2,3]
+ >>> hermval(1, coef)
+ 11.0
+ >>> hermval([[1,2],[3,4]], coef)
+ array([[ 11., 51.],
+ [115., 203.]])
+
+ """
+ c = np.array(c, ndmin=1, copy=False)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ c = c.astype(np.double)
+ if isinstance(x, (tuple, list)):
+ x = np.asarray(x)
+ if isinstance(x, np.ndarray) and tensor:
+ c = c.reshape(c.shape + (1,)*x.ndim)
+
+ x2 = x*2
+ if len(c) == 1:
+ c0 = c[0]
+ c1 = 0
+ elif len(c) == 2:
+ c0 = c[0]
+ c1 = c[1]
+ else:
+ nd = len(c)
+ c0 = c[-2]
+ c1 = c[-1]
+ for i in range(3, len(c) + 1):
+ tmp = c0
+ nd = nd - 1
+ c0 = c[-i] - c1*(2*(nd - 1))
+ c1 = tmp + c1*x2
+ return c0 + c1*x2
+
+
+def hermval2d(x, y, c):
+ """
+ Evaluate a 2-D Hermite series at points (x, y).
+
+ This function returns the values:
+
+ .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * H_i(x) * H_j(y)
+
+ The parameters `x` and `y` are converted to arrays only if they are
+ tuples or a lists, otherwise they are treated as a scalars and they
+ must have the same shape after conversion. In either case, either `x`
+ and `y` or their elements must support multiplication and addition both
+ with themselves and with the elements of `c`.
+
+ If `c` is a 1-D array a one is implicitly appended to its shape to make
+ it 2-D. The shape of the result will be c.shape[2:] + x.shape.
+
+ Parameters
+ ----------
+ x, y : array_like, compatible objects
+ The two dimensional series is evaluated at the points `(x, y)`,
+ where `x` and `y` must have the same shape. If `x` or `y` is a list
+ or tuple, it is first converted to an ndarray, otherwise it is left
+ unchanged and if it isn't an ndarray it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficient of the term
+ of multi-degree i,j is contained in ``c[i,j]``. If `c` has
+ dimension greater than two the remaining indices enumerate multiple
+ sets of coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional polynomial at points formed with
+ pairs of corresponding values from `x` and `y`.
+
+ See Also
+ --------
+ hermval, hermgrid2d, hermval3d, hermgrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._valnd(hermval, c, x, y)
+
+
+def hermgrid2d(x, y, c):
+ """
+ Evaluate a 2-D Hermite series on the Cartesian product of x and y.
+
+ This function returns the values:
+
+ .. math:: p(a,b) = \\sum_{i,j} c_{i,j} * H_i(a) * H_j(b)
+
+ where the points `(a, b)` consist of all pairs formed by taking
+ `a` from `x` and `b` from `y`. The resulting points form a grid with
+ `x` in the first dimension and `y` in the second.
+
+ The parameters `x` and `y` are converted to arrays only if they are
+ tuples or a lists, otherwise they are treated as a scalars. In either
+ case, either `x` and `y` or their elements must support multiplication
+ and addition both with themselves and with the elements of `c`.
+
+ If `c` has fewer than two dimensions, ones are implicitly appended to
+ its shape to make it 2-D. The shape of the result will be c.shape[2:] +
+ x.shape.
+
+ Parameters
+ ----------
+ x, y : array_like, compatible objects
+ The two dimensional series is evaluated at the points in the
+ Cartesian product of `x` and `y`. If `x` or `y` is a list or
+ tuple, it is first converted to an ndarray, otherwise it is left
+ unchanged and, if it isn't an ndarray, it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficients for terms of
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
+ greater than two the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional polynomial at points in the Cartesian
+ product of `x` and `y`.
+
+ See Also
+ --------
+ hermval, hermval2d, hermval3d, hermgrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._gridnd(hermval, c, x, y)
+
+
+def hermval3d(x, y, z, c):
+ """
+ Evaluate a 3-D Hermite series at points (x, y, z).
+
+ This function returns the values:
+
+ .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * H_i(x) * H_j(y) * H_k(z)
+
+ The parameters `x`, `y`, and `z` are converted to arrays only if
+ they are tuples or a lists, otherwise they are treated as a scalars and
+ they must have the same shape after conversion. In either case, either
+ `x`, `y`, and `z` or their elements must support multiplication and
+ addition both with themselves and with the elements of `c`.
+
+ If `c` has fewer than 3 dimensions, ones are implicitly appended to its
+ shape to make it 3-D. The shape of the result will be c.shape[3:] +
+ x.shape.
+
+ Parameters
+ ----------
+ x, y, z : array_like, compatible object
+ The three dimensional series is evaluated at the points
+ `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
+ any of `x`, `y`, or `z` is a list or tuple, it is first converted
+ to an ndarray, otherwise it is left unchanged and if it isn't an
+ ndarray it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficient of the term of
+ multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
+ greater than 3 the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the multidimensional polynomial on points formed with
+ triples of corresponding values from `x`, `y`, and `z`.
+
+ See Also
+ --------
+ hermval, hermval2d, hermgrid2d, hermgrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._valnd(hermval, c, x, y, z)
+
+
+def hermgrid3d(x, y, z, c):
+ """
+ Evaluate a 3-D Hermite series on the Cartesian product of x, y, and z.
+
+ This function returns the values:
+
+ .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * H_i(a) * H_j(b) * H_k(c)
+
+ where the points `(a, b, c)` consist of all triples formed by taking
+ `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
+ a grid with `x` in the first dimension, `y` in the second, and `z` in
+ the third.
+
+ The parameters `x`, `y`, and `z` are converted to arrays only if they
+ are tuples or a lists, otherwise they are treated as a scalars. In
+ either case, either `x`, `y`, and `z` or their elements must support
+ multiplication and addition both with themselves and with the elements
+ of `c`.
+
+ If `c` has fewer than three dimensions, ones are implicitly appended to
+ its shape to make it 3-D. The shape of the result will be c.shape[3:] +
+ x.shape + y.shape + z.shape.
+
+ Parameters
+ ----------
+ x, y, z : array_like, compatible objects
+ The three dimensional series is evaluated at the points in the
+ Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
+ list or tuple, it is first converted to an ndarray, otherwise it is
+ left unchanged and, if it isn't an ndarray, it is treated as a
+ scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficients for terms of
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
+ greater than two the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional polynomial at points in the Cartesian
+ product of `x` and `y`.
+
+ See Also
+ --------
+ hermval, hermval2d, hermgrid2d, hermval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._gridnd(hermval, c, x, y, z)
+
+
+def hermvander(x, deg):
+ """Pseudo-Vandermonde matrix of given degree.
+
+ Returns the pseudo-Vandermonde matrix of degree `deg` and sample points
+ `x`. The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., i] = H_i(x),
+
+ where `0 <= i <= deg`. The leading indices of `V` index the elements of
+ `x` and the last index is the degree of the Hermite polynomial.
+
+ If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
+ array ``V = hermvander(x, n)``, then ``np.dot(V, c)`` and
+ ``hermval(x, c)`` are the same up to roundoff. This equivalence is
+ useful both for least squares fitting and for the evaluation of a large
+ number of Hermite series of the same degree and sample points.
+
+ Parameters
+ ----------
+ x : array_like
+ Array of points. The dtype is converted to float64 or complex128
+ depending on whether any of the elements are complex. If `x` is
+ scalar it is converted to a 1-D array.
+ deg : int
+ Degree of the resulting matrix.
+
+ Returns
+ -------
+ vander : ndarray
+ The pseudo-Vandermonde matrix. The shape of the returned matrix is
+ ``x.shape + (deg + 1,)``, where The last index is the degree of the
+ corresponding Hermite polynomial. The dtype will be the same as
+ the converted `x`.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import hermvander
+ >>> x = np.array([-1, 0, 1])
+ >>> hermvander(x, 3)
+ array([[ 1., -2., 2., 4.],
+ [ 1., 0., -2., -0.],
+ [ 1., 2., 2., -4.]])
+
+ """
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg < 0:
+ raise ValueError("deg must be non-negative")
+
+ x = np.array(x, copy=False, ndmin=1) + 0.0
+ dims = (ideg + 1,) + x.shape
+ dtyp = x.dtype
+ v = np.empty(dims, dtype=dtyp)
+ v[0] = x*0 + 1
+ if ideg > 0:
+ x2 = x*2
+ v[1] = x2
+ for i in range(2, ideg + 1):
+ v[i] = (v[i-1]*x2 - v[i-2]*(2*(i - 1)))
+ return np.moveaxis(v, 0, -1)
+
+
+def hermvander2d(x, y, deg):
+ """Pseudo-Vandermonde matrix of given degrees.
+
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
+ points `(x, y)`. The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., (deg[1] + 1)*i + j] = H_i(x) * H_j(y),
+
+ where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
+ `V` index the points `(x, y)` and the last index encodes the degrees of
+ the Hermite polynomials.
+
+ If ``V = hermvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
+ correspond to the elements of a 2-D coefficient array `c` of shape
+ (xdeg + 1, ydeg + 1) in the order
+
+ .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
+
+ and ``np.dot(V, c.flat)`` and ``hermval2d(x, y, c)`` will be the same
+ up to roundoff. This equivalence is useful both for least squares
+ fitting and for the evaluation of a large number of 2-D Hermite
+ series of the same degrees and sample points.
+
+ Parameters
+ ----------
+ x, y : array_like
+ Arrays of point coordinates, all of the same shape. The dtypes
+ will be converted to either float64 or complex128 depending on
+ whether any of the elements are complex. Scalars are converted to 1-D
+ arrays.
+ deg : list of ints
+ List of maximum degrees of the form [x_deg, y_deg].
+
+ Returns
+ -------
+ vander2d : ndarray
+ The shape of the returned matrix is ``x.shape + (order,)``, where
+ :math:`order = (deg[0]+1)*(deg[1]+1)`. The dtype will be the same
+ as the converted `x` and `y`.
+
+ See Also
+ --------
+ hermvander, hermvander3d, hermval2d, hermval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._vander_nd_flat((hermvander, hermvander), (x, y), deg)
+
+
+def hermvander3d(x, y, z, deg):
+ """Pseudo-Vandermonde matrix of given degrees.
+
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
+ points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
+ then The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = H_i(x)*H_j(y)*H_k(z),
+
+ where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
+ indices of `V` index the points `(x, y, z)` and the last index encodes
+ the degrees of the Hermite polynomials.
+
+ If ``V = hermvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
+ of `V` correspond to the elements of a 3-D coefficient array `c` of
+ shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
+
+ .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
+
+ and ``np.dot(V, c.flat)`` and ``hermval3d(x, y, z, c)`` will be the
+ same up to roundoff. This equivalence is useful both for least squares
+ fitting and for the evaluation of a large number of 3-D Hermite
+ series of the same degrees and sample points.
+
+ Parameters
+ ----------
+ x, y, z : array_like
+ Arrays of point coordinates, all of the same shape. The dtypes will
+ be converted to either float64 or complex128 depending on whether
+ any of the elements are complex. Scalars are converted to 1-D
+ arrays.
+ deg : list of ints
+ List of maximum degrees of the form [x_deg, y_deg, z_deg].
+
+ Returns
+ -------
+ vander3d : ndarray
+ The shape of the returned matrix is ``x.shape + (order,)``, where
+ :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`. The dtype will
+ be the same as the converted `x`, `y`, and `z`.
+
+ See Also
+ --------
+ hermvander, hermvander3d, hermval2d, hermval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._vander_nd_flat((hermvander, hermvander, hermvander), (x, y, z), deg)
+
+
+def hermfit(x, y, deg, rcond=None, full=False, w=None):
+ """
+ Least squares fit of Hermite series to data.
+
+ Return the coefficients of a Hermite series of degree `deg` that is the
+ least squares fit to the data values `y` given at points `x`. If `y` is
+ 1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
+ fits are done, one for each column of `y`, and the resulting
+ coefficients are stored in the corresponding columns of a 2-D return.
+ The fitted polynomial(s) are in the form
+
+ .. math:: p(x) = c_0 + c_1 * H_1(x) + ... + c_n * H_n(x),
+
+ where `n` is `deg`.
+
+ Parameters
+ ----------
+ x : array_like, shape (M,)
+ x-coordinates of the M sample points ``(x[i], y[i])``.
+ y : array_like, shape (M,) or (M, K)
+ y-coordinates of the sample points. Several data sets of sample
+ points sharing the same x-coordinates can be fitted at once by
+ passing in a 2D-array that contains one dataset per column.
+ deg : int or 1-D array_like
+ Degree(s) of the fitting polynomials. If `deg` is a single integer
+ all terms up to and including the `deg`'th term are included in the
+ fit. For NumPy versions >= 1.11.0 a list of integers specifying the
+ degrees of the terms to include may be used instead.
+ rcond : float, optional
+ Relative condition number of the fit. Singular values smaller than
+ this relative to the largest singular value will be ignored. The
+ default value is len(x)*eps, where eps is the relative precision of
+ the float type, about 2e-16 in most cases.
+ full : bool, optional
+ Switch determining nature of return value. When it is False (the
+ default) just the coefficients are returned, when True diagnostic
+ information from the singular value decomposition is also returned.
+ w : array_like, shape (`M`,), optional
+ Weights. If not None, the weight ``w[i]`` applies to the unsquared
+ residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
+ chosen so that the errors of the products ``w[i]*y[i]`` all have the
+ same variance. When using inverse-variance weighting, use
+ ``w[i] = 1/sigma(y[i])``. The default value is None.
+
+ Returns
+ -------
+ coef : ndarray, shape (M,) or (M, K)
+ Hermite coefficients ordered from low to high. If `y` was 2-D,
+ the coefficients for the data in column k of `y` are in column
+ `k`.
+
+ [residuals, rank, singular_values, rcond] : list
+ These values are only returned if ``full == True``
+
+ - residuals -- sum of squared residuals of the least squares fit
+ - rank -- the numerical rank of the scaled Vandermonde matrix
+ - singular_values -- singular values of the scaled Vandermonde matrix
+ - rcond -- value of `rcond`.
+
+ For more details, see `numpy.linalg.lstsq`.
+
+ Warns
+ -----
+ RankWarning
+ The rank of the coefficient matrix in the least-squares fit is
+ deficient. The warning is only raised if ``full == False``. The
+ warnings can be turned off by
+
+ >>> import warnings
+ >>> warnings.simplefilter('ignore', np.RankWarning)
+
+ See Also
+ --------
+ numpy.polynomial.chebyshev.chebfit
+ numpy.polynomial.legendre.legfit
+ numpy.polynomial.laguerre.lagfit
+ numpy.polynomial.polynomial.polyfit
+ numpy.polynomial.hermite_e.hermefit
+ hermval : Evaluates a Hermite series.
+ hermvander : Vandermonde matrix of Hermite series.
+ hermweight : Hermite weight function
+ numpy.linalg.lstsq : Computes a least-squares fit from the matrix.
+ scipy.interpolate.UnivariateSpline : Computes spline fits.
+
+ Notes
+ -----
+ The solution is the coefficients of the Hermite series `p` that
+ minimizes the sum of the weighted squared errors
+
+ .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
+
+ where the :math:`w_j` are the weights. This problem is solved by
+ setting up the (typically) overdetermined matrix equation
+
+ .. math:: V(x) * c = w * y,
+
+ where `V` is the weighted pseudo Vandermonde matrix of `x`, `c` are the
+ coefficients to be solved for, `w` are the weights, `y` are the
+ observed values. This equation is then solved using the singular value
+ decomposition of `V`.
+
+ If some of the singular values of `V` are so small that they are
+ neglected, then a `RankWarning` will be issued. This means that the
+ coefficient values may be poorly determined. Using a lower order fit
+ will usually get rid of the warning. The `rcond` parameter can also be
+ set to a value smaller than its default, but the resulting fit may be
+ spurious and have large contributions from roundoff error.
+
+ Fits using Hermite series are probably most useful when the data can be
+ approximated by ``sqrt(w(x)) * p(x)``, where `w(x)` is the Hermite
+ weight. In that case the weight ``sqrt(w(x[i]))`` should be used
+ together with data values ``y[i]/sqrt(w(x[i]))``. The weight function is
+ available as `hermweight`.
+
+ References
+ ----------
+ .. [1] Wikipedia, "Curve fitting",
+ https://en.wikipedia.org/wiki/Curve_fitting
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import hermfit, hermval
+ >>> x = np.linspace(-10, 10)
+ >>> err = np.random.randn(len(x))/10
+ >>> y = hermval(x, [1, 2, 3]) + err
+ >>> hermfit(x, y, 2)
+ array([1.0218, 1.9986, 2.9999]) # may vary
+
+ """
+ return pu._fit(hermvander, x, y, deg, rcond, full, w)
+
+
+def hermcompanion(c):
+ """Return the scaled companion matrix of c.
+
+ The basis polynomials are scaled so that the companion matrix is
+ symmetric when `c` is an Hermite basis polynomial. This provides
+ better eigenvalue estimates than the unscaled case and for basis
+ polynomials the eigenvalues are guaranteed to be real if
+ `numpy.linalg.eigvalsh` is used to obtain them.
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of Hermite series coefficients ordered from low to high
+ degree.
+
+ Returns
+ -------
+ mat : ndarray
+ Scaled companion matrix of dimensions (deg, deg).
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ if len(c) < 2:
+ raise ValueError('Series must have maximum degree of at least 1.')
+ if len(c) == 2:
+ return np.array([[-.5*c[0]/c[1]]])
+
+ n = len(c) - 1
+ mat = np.zeros((n, n), dtype=c.dtype)
+ scl = np.hstack((1., 1./np.sqrt(2.*np.arange(n - 1, 0, -1))))
+ scl = np.multiply.accumulate(scl)[::-1]
+ top = mat.reshape(-1)[1::n+1]
+ bot = mat.reshape(-1)[n::n+1]
+ top[...] = np.sqrt(.5*np.arange(1, n))
+ bot[...] = top
+ mat[:, -1] -= scl*c[:-1]/(2.0*c[-1])
+ return mat
+
+
+def hermroots(c):
+ """
+ Compute the roots of a Hermite series.
+
+ Return the roots (a.k.a. "zeros") of the polynomial
+
+ .. math:: p(x) = \\sum_i c[i] * H_i(x).
+
+ Parameters
+ ----------
+ c : 1-D array_like
+ 1-D array of coefficients.
+
+ Returns
+ -------
+ out : ndarray
+ Array of the roots of the series. If all the roots are real,
+ then `out` is also real, otherwise it is complex.
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyroots
+ numpy.polynomial.legendre.legroots
+ numpy.polynomial.laguerre.lagroots
+ numpy.polynomial.chebyshev.chebroots
+ numpy.polynomial.hermite_e.hermeroots
+
+ Notes
+ -----
+ The root estimates are obtained as the eigenvalues of the companion
+ matrix, Roots far from the origin of the complex plane may have large
+ errors due to the numerical instability of the series for such
+ values. Roots with multiplicity greater than 1 will also show larger
+ errors as the value of the series near such points is relatively
+ insensitive to errors in the roots. Isolated roots near the origin can
+ be improved by a few iterations of Newton's method.
+
+ The Hermite series basis polynomials aren't powers of `x` so the
+ results of this function may seem unintuitive.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite import hermroots, hermfromroots
+ >>> coef = hermfromroots([-1, 0, 1])
+ >>> coef
+ array([0. , 0.25 , 0. , 0.125])
+ >>> hermroots(coef)
+ array([-1.00000000e+00, -1.38777878e-17, 1.00000000e+00])
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ if len(c) <= 1:
+ return np.array([], dtype=c.dtype)
+ if len(c) == 2:
+ return np.array([-.5*c[0]/c[1]])
+
+ # rotated companion matrix reduces error
+ m = hermcompanion(c)[::-1,::-1]
+ r = la.eigvals(m)
+ r.sort()
+ return r
+
+
+def _normed_hermite_n(x, n):
+ """
+ Evaluate a normalized Hermite polynomial.
+
+ Compute the value of the normalized Hermite polynomial of degree ``n``
+ at the points ``x``.
+
+
+ Parameters
+ ----------
+ x : ndarray of double.
+ Points at which to evaluate the function
+ n : int
+ Degree of the normalized Hermite function to be evaluated.
+
+ Returns
+ -------
+ values : ndarray
+ The shape of the return value is described above.
+
+ Notes
+ -----
+ .. versionadded:: 1.10.0
+
+ This function is needed for finding the Gauss points and integration
+ weights for high degrees. The values of the standard Hermite functions
+ overflow when n >= 207.
+
+ """
+ if n == 0:
+ return np.full(x.shape, 1/np.sqrt(np.sqrt(np.pi)))
+
+ c0 = 0.
+ c1 = 1./np.sqrt(np.sqrt(np.pi))
+ nd = float(n)
+ for i in range(n - 1):
+ tmp = c0
+ c0 = -c1*np.sqrt((nd - 1.)/nd)
+ c1 = tmp + c1*x*np.sqrt(2./nd)
+ nd = nd - 1.0
+ return c0 + c1*x*np.sqrt(2)
+
+
+def hermgauss(deg):
+ """
+ Gauss-Hermite quadrature.
+
+ Computes the sample points and weights for Gauss-Hermite quadrature.
+ These sample points and weights will correctly integrate polynomials of
+ degree :math:`2*deg - 1` or less over the interval :math:`[-\\inf, \\inf]`
+ with the weight function :math:`f(x) = \\exp(-x^2)`.
+
+ Parameters
+ ----------
+ deg : int
+ Number of sample points and weights. It must be >= 1.
+
+ Returns
+ -------
+ x : ndarray
+ 1-D ndarray containing the sample points.
+ y : ndarray
+ 1-D ndarray containing the weights.
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ The results have only been tested up to degree 100, higher degrees may
+ be problematic. The weights are determined by using the fact that
+
+ .. math:: w_k = c / (H'_n(x_k) * H_{n-1}(x_k))
+
+ where :math:`c` is a constant independent of :math:`k` and :math:`x_k`
+ is the k'th root of :math:`H_n`, and then scaling the results to get
+ the right value when integrating 1.
+
+ """
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg <= 0:
+ raise ValueError("deg must be a positive integer")
+
+ # first approximation of roots. We use the fact that the companion
+ # matrix is symmetric in this case in order to obtain better zeros.
+ c = np.array([0]*deg + [1], dtype=np.float64)
+ m = hermcompanion(c)
+ x = la.eigvalsh(m)
+
+ # improve roots by one application of Newton
+ dy = _normed_hermite_n(x, ideg)
+ df = _normed_hermite_n(x, ideg - 1) * np.sqrt(2*ideg)
+ x -= dy/df
+
+ # compute the weights. We scale the factor to avoid possible numerical
+ # overflow.
+ fm = _normed_hermite_n(x, ideg - 1)
+ fm /= np.abs(fm).max()
+ w = 1/(fm * fm)
+
+ # for Hermite we can also symmetrize
+ w = (w + w[::-1])/2
+ x = (x - x[::-1])/2
+
+ # scale w to get the right value
+ w *= np.sqrt(np.pi) / w.sum()
+
+ return x, w
+
+
+def hermweight(x):
+ """
+ Weight function of the Hermite polynomials.
+
+ The weight function is :math:`\\exp(-x^2)` and the interval of
+ integration is :math:`[-\\inf, \\inf]`. the Hermite polynomials are
+ orthogonal, but not normalized, with respect to this weight function.
+
+ Parameters
+ ----------
+ x : array_like
+ Values at which the weight function will be computed.
+
+ Returns
+ -------
+ w : ndarray
+ The weight function at `x`.
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ w = np.exp(-x**2)
+ return w
+
+
+#
+# Hermite series class
+#
+
+class Hermite(ABCPolyBase):
+ """An Hermite series class.
+
+ The Hermite class provides the standard Python numerical methods
+ '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
+ attributes and methods listed in the `ABCPolyBase` documentation.
+
+ Parameters
+ ----------
+ coef : array_like
+ Hermite coefficients in order of increasing degree, i.e,
+ ``(1, 2, 3)`` gives ``1*H_0(x) + 2*H_1(X) + 3*H_2(x)``.
+ domain : (2,) array_like, optional
+ Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
+ to the interval ``[window[0], window[1]]`` by shifting and scaling.
+ The default value is [-1, 1].
+ window : (2,) array_like, optional
+ Window, see `domain` for its use. The default value is [-1, 1].
+
+ .. versionadded:: 1.6.0
+ symbol : str, optional
+ Symbol used to represent the independent variable in string
+ representations of the polynomial expression, e.g. for printing.
+ The symbol must be a valid Python identifier. Default value is 'x'.
+
+ .. versionadded:: 1.24
+
+ """
+ # Virtual Functions
+ _add = staticmethod(hermadd)
+ _sub = staticmethod(hermsub)
+ _mul = staticmethod(hermmul)
+ _div = staticmethod(hermdiv)
+ _pow = staticmethod(hermpow)
+ _val = staticmethod(hermval)
+ _int = staticmethod(hermint)
+ _der = staticmethod(hermder)
+ _fit = staticmethod(hermfit)
+ _line = staticmethod(hermline)
+ _roots = staticmethod(hermroots)
+ _fromroots = staticmethod(hermfromroots)
+
+ # Virtual properties
+ domain = np.array(hermdomain)
+ window = np.array(hermdomain)
+ basis_name = 'H'
diff --git a/lib/python3.12/site-packages/numpy/polynomial/hermite.pyi b/lib/python3.12/site-packages/numpy/polynomial/hermite.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..0d3556d696410689b4614138ad4cf1f6c2283a9c
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/hermite.pyi
@@ -0,0 +1,46 @@
+from typing import Any
+
+from numpy import ndarray, dtype, int_, float_
+from numpy.polynomial._polybase import ABCPolyBase
+from numpy.polynomial.polyutils import trimcoef
+
+__all__: list[str]
+
+hermtrim = trimcoef
+
+def poly2herm(pol): ...
+def herm2poly(c): ...
+
+hermdomain: ndarray[Any, dtype[int_]]
+hermzero: ndarray[Any, dtype[int_]]
+hermone: ndarray[Any, dtype[int_]]
+hermx: ndarray[Any, dtype[float_]]
+
+def hermline(off, scl): ...
+def hermfromroots(roots): ...
+def hermadd(c1, c2): ...
+def hermsub(c1, c2): ...
+def hermmulx(c): ...
+def hermmul(c1, c2): ...
+def hermdiv(c1, c2): ...
+def hermpow(c, pow, maxpower=...): ...
+def hermder(c, m=..., scl=..., axis=...): ...
+def hermint(c, m=..., k = ..., lbnd=..., scl=..., axis=...): ...
+def hermval(x, c, tensor=...): ...
+def hermval2d(x, y, c): ...
+def hermgrid2d(x, y, c): ...
+def hermval3d(x, y, z, c): ...
+def hermgrid3d(x, y, z, c): ...
+def hermvander(x, deg): ...
+def hermvander2d(x, y, deg): ...
+def hermvander3d(x, y, z, deg): ...
+def hermfit(x, y, deg, rcond=..., full=..., w=...): ...
+def hermcompanion(c): ...
+def hermroots(c): ...
+def hermgauss(deg): ...
+def hermweight(x): ...
+
+class Hermite(ABCPolyBase):
+ domain: Any
+ window: Any
+ basis_name: Any
diff --git a/lib/python3.12/site-packages/numpy/polynomial/hermite_e.py b/lib/python3.12/site-packages/numpy/polynomial/hermite_e.py
new file mode 100644
index 0000000000000000000000000000000000000000..bdf29405bee7788d5ca6a8677b8402b9a7af393e
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/hermite_e.py
@@ -0,0 +1,1695 @@
+"""
+===================================================================
+HermiteE Series, "Probabilists" (:mod:`numpy.polynomial.hermite_e`)
+===================================================================
+
+This module provides a number of objects (mostly functions) useful for
+dealing with Hermite_e series, including a `HermiteE` class that
+encapsulates the usual arithmetic operations. (General information
+on how this module represents and works with such polynomials is in the
+docstring for its "parent" sub-package, `numpy.polynomial`).
+
+Classes
+-------
+.. autosummary::
+ :toctree: generated/
+
+ HermiteE
+
+Constants
+---------
+.. autosummary::
+ :toctree: generated/
+
+ hermedomain
+ hermezero
+ hermeone
+ hermex
+
+Arithmetic
+----------
+.. autosummary::
+ :toctree: generated/
+
+ hermeadd
+ hermesub
+ hermemulx
+ hermemul
+ hermediv
+ hermepow
+ hermeval
+ hermeval2d
+ hermeval3d
+ hermegrid2d
+ hermegrid3d
+
+Calculus
+--------
+.. autosummary::
+ :toctree: generated/
+
+ hermeder
+ hermeint
+
+Misc Functions
+--------------
+.. autosummary::
+ :toctree: generated/
+
+ hermefromroots
+ hermeroots
+ hermevander
+ hermevander2d
+ hermevander3d
+ hermegauss
+ hermeweight
+ hermecompanion
+ hermefit
+ hermetrim
+ hermeline
+ herme2poly
+ poly2herme
+
+See also
+--------
+`numpy.polynomial`
+
+"""
+import numpy as np
+import numpy.linalg as la
+from numpy.core.multiarray import normalize_axis_index
+
+from . import polyutils as pu
+from ._polybase import ABCPolyBase
+
+__all__ = [
+ 'hermezero', 'hermeone', 'hermex', 'hermedomain', 'hermeline',
+ 'hermeadd', 'hermesub', 'hermemulx', 'hermemul', 'hermediv',
+ 'hermepow', 'hermeval', 'hermeder', 'hermeint', 'herme2poly',
+ 'poly2herme', 'hermefromroots', 'hermevander', 'hermefit', 'hermetrim',
+ 'hermeroots', 'HermiteE', 'hermeval2d', 'hermeval3d', 'hermegrid2d',
+ 'hermegrid3d', 'hermevander2d', 'hermevander3d', 'hermecompanion',
+ 'hermegauss', 'hermeweight']
+
+hermetrim = pu.trimcoef
+
+
+def poly2herme(pol):
+ """
+ poly2herme(pol)
+
+ Convert a polynomial to a Hermite series.
+
+ Convert an array representing the coefficients of a polynomial (relative
+ to the "standard" basis) ordered from lowest degree to highest, to an
+ array of the coefficients of the equivalent Hermite series, ordered
+ from lowest to highest degree.
+
+ Parameters
+ ----------
+ pol : array_like
+ 1-D array containing the polynomial coefficients
+
+ Returns
+ -------
+ c : ndarray
+ 1-D array containing the coefficients of the equivalent Hermite
+ series.
+
+ See Also
+ --------
+ herme2poly
+
+ Notes
+ -----
+ The easy way to do conversions between polynomial basis sets
+ is to use the convert method of a class instance.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import poly2herme
+ >>> poly2herme(np.arange(4))
+ array([ 2., 10., 2., 3.])
+
+ """
+ [pol] = pu.as_series([pol])
+ deg = len(pol) - 1
+ res = 0
+ for i in range(deg, -1, -1):
+ res = hermeadd(hermemulx(res), pol[i])
+ return res
+
+
+def herme2poly(c):
+ """
+ Convert a Hermite series to a polynomial.
+
+ Convert an array representing the coefficients of a Hermite series,
+ ordered from lowest degree to highest, to an array of the coefficients
+ of the equivalent polynomial (relative to the "standard" basis) ordered
+ from lowest to highest degree.
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array containing the Hermite series coefficients, ordered
+ from lowest order term to highest.
+
+ Returns
+ -------
+ pol : ndarray
+ 1-D array containing the coefficients of the equivalent polynomial
+ (relative to the "standard" basis) ordered from lowest order term
+ to highest.
+
+ See Also
+ --------
+ poly2herme
+
+ Notes
+ -----
+ The easy way to do conversions between polynomial basis sets
+ is to use the convert method of a class instance.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import herme2poly
+ >>> herme2poly([ 2., 10., 2., 3.])
+ array([0., 1., 2., 3.])
+
+ """
+ from .polynomial import polyadd, polysub, polymulx
+
+ [c] = pu.as_series([c])
+ n = len(c)
+ if n == 1:
+ return c
+ if n == 2:
+ return c
+ else:
+ c0 = c[-2]
+ c1 = c[-1]
+ # i is the current degree of c1
+ for i in range(n - 1, 1, -1):
+ tmp = c0
+ c0 = polysub(c[i - 2], c1*(i - 1))
+ c1 = polyadd(tmp, polymulx(c1))
+ return polyadd(c0, polymulx(c1))
+
+#
+# These are constant arrays are of integer type so as to be compatible
+# with the widest range of other types, such as Decimal.
+#
+
+# Hermite
+hermedomain = np.array([-1, 1])
+
+# Hermite coefficients representing zero.
+hermezero = np.array([0])
+
+# Hermite coefficients representing one.
+hermeone = np.array([1])
+
+# Hermite coefficients representing the identity x.
+hermex = np.array([0, 1])
+
+
+def hermeline(off, scl):
+ """
+ Hermite series whose graph is a straight line.
+
+ Parameters
+ ----------
+ off, scl : scalars
+ The specified line is given by ``off + scl*x``.
+
+ Returns
+ -------
+ y : ndarray
+ This module's representation of the Hermite series for
+ ``off + scl*x``.
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyline
+ numpy.polynomial.chebyshev.chebline
+ numpy.polynomial.legendre.legline
+ numpy.polynomial.laguerre.lagline
+ numpy.polynomial.hermite.hermline
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import hermeline
+ >>> from numpy.polynomial.hermite_e import hermeline, hermeval
+ >>> hermeval(0,hermeline(3, 2))
+ 3.0
+ >>> hermeval(1,hermeline(3, 2))
+ 5.0
+
+ """
+ if scl != 0:
+ return np.array([off, scl])
+ else:
+ return np.array([off])
+
+
+def hermefromroots(roots):
+ """
+ Generate a HermiteE series with given roots.
+
+ The function returns the coefficients of the polynomial
+
+ .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
+
+ in HermiteE form, where the `r_n` are the roots specified in `roots`.
+ If a zero has multiplicity n, then it must appear in `roots` n times.
+ For instance, if 2 is a root of multiplicity three and 3 is a root of
+ multiplicity 2, then `roots` looks something like [2, 2, 2, 3, 3]. The
+ roots can appear in any order.
+
+ If the returned coefficients are `c`, then
+
+ .. math:: p(x) = c_0 + c_1 * He_1(x) + ... + c_n * He_n(x)
+
+ The coefficient of the last term is not generally 1 for monic
+ polynomials in HermiteE form.
+
+ Parameters
+ ----------
+ roots : array_like
+ Sequence containing the roots.
+
+ Returns
+ -------
+ out : ndarray
+ 1-D array of coefficients. If all roots are real then `out` is a
+ real array, if some of the roots are complex, then `out` is complex
+ even if all the coefficients in the result are real (see Examples
+ below).
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyfromroots
+ numpy.polynomial.legendre.legfromroots
+ numpy.polynomial.laguerre.lagfromroots
+ numpy.polynomial.hermite.hermfromroots
+ numpy.polynomial.chebyshev.chebfromroots
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import hermefromroots, hermeval
+ >>> coef = hermefromroots((-1, 0, 1))
+ >>> hermeval((-1, 0, 1), coef)
+ array([0., 0., 0.])
+ >>> coef = hermefromroots((-1j, 1j))
+ >>> hermeval((-1j, 1j), coef)
+ array([0.+0.j, 0.+0.j])
+
+ """
+ return pu._fromroots(hermeline, hermemul, roots)
+
+
+def hermeadd(c1, c2):
+ """
+ Add one Hermite series to another.
+
+ Returns the sum of two Hermite series `c1` + `c2`. The arguments
+ are sequences of coefficients ordered from lowest order term to
+ highest, i.e., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Hermite series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Array representing the Hermite series of their sum.
+
+ See Also
+ --------
+ hermesub, hermemulx, hermemul, hermediv, hermepow
+
+ Notes
+ -----
+ Unlike multiplication, division, etc., the sum of two Hermite series
+ is a Hermite series (without having to "reproject" the result onto
+ the basis set) so addition, just like that of "standard" polynomials,
+ is simply "component-wise."
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import hermeadd
+ >>> hermeadd([1, 2, 3], [1, 2, 3, 4])
+ array([2., 4., 6., 4.])
+
+ """
+ return pu._add(c1, c2)
+
+
+def hermesub(c1, c2):
+ """
+ Subtract one Hermite series from another.
+
+ Returns the difference of two Hermite series `c1` - `c2`. The
+ sequences of coefficients are from lowest order term to highest, i.e.,
+ [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Hermite series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Of Hermite series coefficients representing their difference.
+
+ See Also
+ --------
+ hermeadd, hermemulx, hermemul, hermediv, hermepow
+
+ Notes
+ -----
+ Unlike multiplication, division, etc., the difference of two Hermite
+ series is a Hermite series (without having to "reproject" the result
+ onto the basis set) so subtraction, just like that of "standard"
+ polynomials, is simply "component-wise."
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import hermesub
+ >>> hermesub([1, 2, 3, 4], [1, 2, 3])
+ array([0., 0., 0., 4.])
+
+ """
+ return pu._sub(c1, c2)
+
+
+def hermemulx(c):
+ """Multiply a Hermite series by x.
+
+ Multiply the Hermite series `c` by x, where x is the independent
+ variable.
+
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of Hermite series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Array representing the result of the multiplication.
+
+ Notes
+ -----
+ The multiplication uses the recursion relationship for Hermite
+ polynomials in the form
+
+ .. math::
+
+ xP_i(x) = (P_{i + 1}(x) + iP_{i - 1}(x)))
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import hermemulx
+ >>> hermemulx([1, 2, 3])
+ array([2., 7., 2., 3.])
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ # The zero series needs special treatment
+ if len(c) == 1 and c[0] == 0:
+ return c
+
+ prd = np.empty(len(c) + 1, dtype=c.dtype)
+ prd[0] = c[0]*0
+ prd[1] = c[0]
+ for i in range(1, len(c)):
+ prd[i + 1] = c[i]
+ prd[i - 1] += c[i]*i
+ return prd
+
+
+def hermemul(c1, c2):
+ """
+ Multiply one Hermite series by another.
+
+ Returns the product of two Hermite series `c1` * `c2`. The arguments
+ are sequences of coefficients, from lowest order "term" to highest,
+ e.g., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Hermite series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Of Hermite series coefficients representing their product.
+
+ See Also
+ --------
+ hermeadd, hermesub, hermemulx, hermediv, hermepow
+
+ Notes
+ -----
+ In general, the (polynomial) product of two C-series results in terms
+ that are not in the Hermite polynomial basis set. Thus, to express
+ the product as a Hermite series, it is necessary to "reproject" the
+ product onto said basis set, which may produce "unintuitive" (but
+ correct) results; see Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import hermemul
+ >>> hermemul([1, 2, 3], [0, 1, 2])
+ array([14., 15., 28., 7., 6.])
+
+ """
+ # s1, s2 are trimmed copies
+ [c1, c2] = pu.as_series([c1, c2])
+
+ if len(c1) > len(c2):
+ c = c2
+ xs = c1
+ else:
+ c = c1
+ xs = c2
+
+ if len(c) == 1:
+ c0 = c[0]*xs
+ c1 = 0
+ elif len(c) == 2:
+ c0 = c[0]*xs
+ c1 = c[1]*xs
+ else:
+ nd = len(c)
+ c0 = c[-2]*xs
+ c1 = c[-1]*xs
+ for i in range(3, len(c) + 1):
+ tmp = c0
+ nd = nd - 1
+ c0 = hermesub(c[-i]*xs, c1*(nd - 1))
+ c1 = hermeadd(tmp, hermemulx(c1))
+ return hermeadd(c0, hermemulx(c1))
+
+
+def hermediv(c1, c2):
+ """
+ Divide one Hermite series by another.
+
+ Returns the quotient-with-remainder of two Hermite series
+ `c1` / `c2`. The arguments are sequences of coefficients from lowest
+ order "term" to highest, e.g., [1,2,3] represents the series
+ ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Hermite series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ [quo, rem] : ndarrays
+ Of Hermite series coefficients representing the quotient and
+ remainder.
+
+ See Also
+ --------
+ hermeadd, hermesub, hermemulx, hermemul, hermepow
+
+ Notes
+ -----
+ In general, the (polynomial) division of one Hermite series by another
+ results in quotient and remainder terms that are not in the Hermite
+ polynomial basis set. Thus, to express these results as a Hermite
+ series, it is necessary to "reproject" the results onto the Hermite
+ basis set, which may produce "unintuitive" (but correct) results; see
+ Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import hermediv
+ >>> hermediv([ 14., 15., 28., 7., 6.], [0, 1, 2])
+ (array([1., 2., 3.]), array([0.]))
+ >>> hermediv([ 15., 17., 28., 7., 6.], [0, 1, 2])
+ (array([1., 2., 3.]), array([1., 2.]))
+
+ """
+ return pu._div(hermemul, c1, c2)
+
+
+def hermepow(c, pow, maxpower=16):
+ """Raise a Hermite series to a power.
+
+ Returns the Hermite series `c` raised to the power `pow`. The
+ argument `c` is a sequence of coefficients ordered from low to high.
+ i.e., [1,2,3] is the series ``P_0 + 2*P_1 + 3*P_2.``
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of Hermite series coefficients ordered from low to
+ high.
+ pow : integer
+ Power to which the series will be raised
+ maxpower : integer, optional
+ Maximum power allowed. This is mainly to limit growth of the series
+ to unmanageable size. Default is 16
+
+ Returns
+ -------
+ coef : ndarray
+ Hermite series of power.
+
+ See Also
+ --------
+ hermeadd, hermesub, hermemulx, hermemul, hermediv
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import hermepow
+ >>> hermepow([1, 2, 3], 2)
+ array([23., 28., 46., 12., 9.])
+
+ """
+ return pu._pow(hermemul, c, pow, maxpower)
+
+
+def hermeder(c, m=1, scl=1, axis=0):
+ """
+ Differentiate a Hermite_e series.
+
+ Returns the series coefficients `c` differentiated `m` times along
+ `axis`. At each iteration the result is multiplied by `scl` (the
+ scaling factor is for use in a linear change of variable). The argument
+ `c` is an array of coefficients from low to high degree along each
+ axis, e.g., [1,2,3] represents the series ``1*He_0 + 2*He_1 + 3*He_2``
+ while [[1,2],[1,2]] represents ``1*He_0(x)*He_0(y) + 1*He_1(x)*He_0(y)
+ + 2*He_0(x)*He_1(y) + 2*He_1(x)*He_1(y)`` if axis=0 is ``x`` and axis=1
+ is ``y``.
+
+ Parameters
+ ----------
+ c : array_like
+ Array of Hermite_e series coefficients. If `c` is multidimensional
+ the different axis correspond to different variables with the
+ degree in each axis given by the corresponding index.
+ m : int, optional
+ Number of derivatives taken, must be non-negative. (Default: 1)
+ scl : scalar, optional
+ Each differentiation is multiplied by `scl`. The end result is
+ multiplication by ``scl**m``. This is for use in a linear change of
+ variable. (Default: 1)
+ axis : int, optional
+ Axis over which the derivative is taken. (Default: 0).
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ der : ndarray
+ Hermite series of the derivative.
+
+ See Also
+ --------
+ hermeint
+
+ Notes
+ -----
+ In general, the result of differentiating a Hermite series does not
+ resemble the same operation on a power series. Thus the result of this
+ function may be "unintuitive," albeit correct; see Examples section
+ below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import hermeder
+ >>> hermeder([ 1., 1., 1., 1.])
+ array([1., 2., 3.])
+ >>> hermeder([-0.25, 1., 1./2., 1./3., 1./4 ], m=2)
+ array([1., 2., 3.])
+
+ """
+ c = np.array(c, ndmin=1, copy=True)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ c = c.astype(np.double)
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
+ if cnt < 0:
+ raise ValueError("The order of derivation must be non-negative")
+ iaxis = normalize_axis_index(iaxis, c.ndim)
+
+ if cnt == 0:
+ return c
+
+ c = np.moveaxis(c, iaxis, 0)
+ n = len(c)
+ if cnt >= n:
+ return c[:1]*0
+ else:
+ for i in range(cnt):
+ n = n - 1
+ c *= scl
+ der = np.empty((n,) + c.shape[1:], dtype=c.dtype)
+ for j in range(n, 0, -1):
+ der[j - 1] = j*c[j]
+ c = der
+ c = np.moveaxis(c, 0, iaxis)
+ return c
+
+
+def hermeint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
+ """
+ Integrate a Hermite_e series.
+
+ Returns the Hermite_e series coefficients `c` integrated `m` times from
+ `lbnd` along `axis`. At each iteration the resulting series is
+ **multiplied** by `scl` and an integration constant, `k`, is added.
+ The scaling factor is for use in a linear change of variable. ("Buyer
+ beware": note that, depending on what one is doing, one may want `scl`
+ to be the reciprocal of what one might expect; for more information,
+ see the Notes section below.) The argument `c` is an array of
+ coefficients from low to high degree along each axis, e.g., [1,2,3]
+ represents the series ``H_0 + 2*H_1 + 3*H_2`` while [[1,2],[1,2]]
+ represents ``1*H_0(x)*H_0(y) + 1*H_1(x)*H_0(y) + 2*H_0(x)*H_1(y) +
+ 2*H_1(x)*H_1(y)`` if axis=0 is ``x`` and axis=1 is ``y``.
+
+ Parameters
+ ----------
+ c : array_like
+ Array of Hermite_e series coefficients. If c is multidimensional
+ the different axis correspond to different variables with the
+ degree in each axis given by the corresponding index.
+ m : int, optional
+ Order of integration, must be positive. (Default: 1)
+ k : {[], list, scalar}, optional
+ Integration constant(s). The value of the first integral at
+ ``lbnd`` is the first value in the list, the value of the second
+ integral at ``lbnd`` is the second value, etc. If ``k == []`` (the
+ default), all constants are set to zero. If ``m == 1``, a single
+ scalar can be given instead of a list.
+ lbnd : scalar, optional
+ The lower bound of the integral. (Default: 0)
+ scl : scalar, optional
+ Following each integration the result is *multiplied* by `scl`
+ before the integration constant is added. (Default: 1)
+ axis : int, optional
+ Axis over which the integral is taken. (Default: 0).
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ S : ndarray
+ Hermite_e series coefficients of the integral.
+
+ Raises
+ ------
+ ValueError
+ If ``m < 0``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
+ ``np.ndim(scl) != 0``.
+
+ See Also
+ --------
+ hermeder
+
+ Notes
+ -----
+ Note that the result of each integration is *multiplied* by `scl`.
+ Why is this important to note? Say one is making a linear change of
+ variable :math:`u = ax + b` in an integral relative to `x`. Then
+ :math:`dx = du/a`, so one will need to set `scl` equal to
+ :math:`1/a` - perhaps not what one would have first thought.
+
+ Also note that, in general, the result of integrating a C-series needs
+ to be "reprojected" onto the C-series basis set. Thus, typically,
+ the result of this function is "unintuitive," albeit correct; see
+ Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import hermeint
+ >>> hermeint([1, 2, 3]) # integrate once, value 0 at 0.
+ array([1., 1., 1., 1.])
+ >>> hermeint([1, 2, 3], m=2) # integrate twice, value & deriv 0 at 0
+ array([-0.25 , 1. , 0.5 , 0.33333333, 0.25 ]) # may vary
+ >>> hermeint([1, 2, 3], k=1) # integrate once, value 1 at 0.
+ array([2., 1., 1., 1.])
+ >>> hermeint([1, 2, 3], lbnd=-1) # integrate once, value 0 at -1
+ array([-1., 1., 1., 1.])
+ >>> hermeint([1, 2, 3], m=2, k=[1, 2], lbnd=-1)
+ array([ 1.83333333, 0. , 0.5 , 0.33333333, 0.25 ]) # may vary
+
+ """
+ c = np.array(c, ndmin=1, copy=True)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ c = c.astype(np.double)
+ if not np.iterable(k):
+ k = [k]
+ cnt = pu._deprecate_as_int(m, "the order of integration")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
+ if cnt < 0:
+ raise ValueError("The order of integration must be non-negative")
+ if len(k) > cnt:
+ raise ValueError("Too many integration constants")
+ if np.ndim(lbnd) != 0:
+ raise ValueError("lbnd must be a scalar.")
+ if np.ndim(scl) != 0:
+ raise ValueError("scl must be a scalar.")
+ iaxis = normalize_axis_index(iaxis, c.ndim)
+
+ if cnt == 0:
+ return c
+
+ c = np.moveaxis(c, iaxis, 0)
+ k = list(k) + [0]*(cnt - len(k))
+ for i in range(cnt):
+ n = len(c)
+ c *= scl
+ if n == 1 and np.all(c[0] == 0):
+ c[0] += k[i]
+ else:
+ tmp = np.empty((n + 1,) + c.shape[1:], dtype=c.dtype)
+ tmp[0] = c[0]*0
+ tmp[1] = c[0]
+ for j in range(1, n):
+ tmp[j + 1] = c[j]/(j + 1)
+ tmp[0] += k[i] - hermeval(lbnd, tmp)
+ c = tmp
+ c = np.moveaxis(c, 0, iaxis)
+ return c
+
+
+def hermeval(x, c, tensor=True):
+ """
+ Evaluate an HermiteE series at points x.
+
+ If `c` is of length `n + 1`, this function returns the value:
+
+ .. math:: p(x) = c_0 * He_0(x) + c_1 * He_1(x) + ... + c_n * He_n(x)
+
+ The parameter `x` is converted to an array only if it is a tuple or a
+ list, otherwise it is treated as a scalar. In either case, either `x`
+ or its elements must support multiplication and addition both with
+ themselves and with the elements of `c`.
+
+ If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
+ `c` is multidimensional, then the shape of the result depends on the
+ value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
+ x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
+ scalars have shape (,).
+
+ Trailing zeros in the coefficients will be used in the evaluation, so
+ they should be avoided if efficiency is a concern.
+
+ Parameters
+ ----------
+ x : array_like, compatible object
+ If `x` is a list or tuple, it is converted to an ndarray, otherwise
+ it is left unchanged and treated as a scalar. In either case, `x`
+ or its elements must support addition and multiplication with
+ with themselves and with the elements of `c`.
+ c : array_like
+ Array of coefficients ordered so that the coefficients for terms of
+ degree n are contained in c[n]. If `c` is multidimensional the
+ remaining indices enumerate multiple polynomials. In the two
+ dimensional case the coefficients may be thought of as stored in
+ the columns of `c`.
+ tensor : boolean, optional
+ If True, the shape of the coefficient array is extended with ones
+ on the right, one for each dimension of `x`. Scalars have dimension 0
+ for this action. The result is that every column of coefficients in
+ `c` is evaluated for every element of `x`. If False, `x` is broadcast
+ over the columns of `c` for the evaluation. This keyword is useful
+ when `c` is multidimensional. The default value is True.
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ values : ndarray, algebra_like
+ The shape of the return value is described above.
+
+ See Also
+ --------
+ hermeval2d, hermegrid2d, hermeval3d, hermegrid3d
+
+ Notes
+ -----
+ The evaluation uses Clenshaw recursion, aka synthetic division.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import hermeval
+ >>> coef = [1,2,3]
+ >>> hermeval(1, coef)
+ 3.0
+ >>> hermeval([[1,2],[3,4]], coef)
+ array([[ 3., 14.],
+ [31., 54.]])
+
+ """
+ c = np.array(c, ndmin=1, copy=False)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ c = c.astype(np.double)
+ if isinstance(x, (tuple, list)):
+ x = np.asarray(x)
+ if isinstance(x, np.ndarray) and tensor:
+ c = c.reshape(c.shape + (1,)*x.ndim)
+
+ if len(c) == 1:
+ c0 = c[0]
+ c1 = 0
+ elif len(c) == 2:
+ c0 = c[0]
+ c1 = c[1]
+ else:
+ nd = len(c)
+ c0 = c[-2]
+ c1 = c[-1]
+ for i in range(3, len(c) + 1):
+ tmp = c0
+ nd = nd - 1
+ c0 = c[-i] - c1*(nd - 1)
+ c1 = tmp + c1*x
+ return c0 + c1*x
+
+
+def hermeval2d(x, y, c):
+ """
+ Evaluate a 2-D HermiteE series at points (x, y).
+
+ This function returns the values:
+
+ .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * He_i(x) * He_j(y)
+
+ The parameters `x` and `y` are converted to arrays only if they are
+ tuples or a lists, otherwise they are treated as a scalars and they
+ must have the same shape after conversion. In either case, either `x`
+ and `y` or their elements must support multiplication and addition both
+ with themselves and with the elements of `c`.
+
+ If `c` is a 1-D array a one is implicitly appended to its shape to make
+ it 2-D. The shape of the result will be c.shape[2:] + x.shape.
+
+ Parameters
+ ----------
+ x, y : array_like, compatible objects
+ The two dimensional series is evaluated at the points `(x, y)`,
+ where `x` and `y` must have the same shape. If `x` or `y` is a list
+ or tuple, it is first converted to an ndarray, otherwise it is left
+ unchanged and if it isn't an ndarray it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficient of the term
+ of multi-degree i,j is contained in ``c[i,j]``. If `c` has
+ dimension greater than two the remaining indices enumerate multiple
+ sets of coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional polynomial at points formed with
+ pairs of corresponding values from `x` and `y`.
+
+ See Also
+ --------
+ hermeval, hermegrid2d, hermeval3d, hermegrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._valnd(hermeval, c, x, y)
+
+
+def hermegrid2d(x, y, c):
+ """
+ Evaluate a 2-D HermiteE series on the Cartesian product of x and y.
+
+ This function returns the values:
+
+ .. math:: p(a,b) = \\sum_{i,j} c_{i,j} * H_i(a) * H_j(b)
+
+ where the points `(a, b)` consist of all pairs formed by taking
+ `a` from `x` and `b` from `y`. The resulting points form a grid with
+ `x` in the first dimension and `y` in the second.
+
+ The parameters `x` and `y` are converted to arrays only if they are
+ tuples or a lists, otherwise they are treated as a scalars. In either
+ case, either `x` and `y` or their elements must support multiplication
+ and addition both with themselves and with the elements of `c`.
+
+ If `c` has fewer than two dimensions, ones are implicitly appended to
+ its shape to make it 2-D. The shape of the result will be c.shape[2:] +
+ x.shape.
+
+ Parameters
+ ----------
+ x, y : array_like, compatible objects
+ The two dimensional series is evaluated at the points in the
+ Cartesian product of `x` and `y`. If `x` or `y` is a list or
+ tuple, it is first converted to an ndarray, otherwise it is left
+ unchanged and, if it isn't an ndarray, it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficients for terms of
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
+ greater than two the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional polynomial at points in the Cartesian
+ product of `x` and `y`.
+
+ See Also
+ --------
+ hermeval, hermeval2d, hermeval3d, hermegrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._gridnd(hermeval, c, x, y)
+
+
+def hermeval3d(x, y, z, c):
+ """
+ Evaluate a 3-D Hermite_e series at points (x, y, z).
+
+ This function returns the values:
+
+ .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * He_i(x) * He_j(y) * He_k(z)
+
+ The parameters `x`, `y`, and `z` are converted to arrays only if
+ they are tuples or a lists, otherwise they are treated as a scalars and
+ they must have the same shape after conversion. In either case, either
+ `x`, `y`, and `z` or their elements must support multiplication and
+ addition both with themselves and with the elements of `c`.
+
+ If `c` has fewer than 3 dimensions, ones are implicitly appended to its
+ shape to make it 3-D. The shape of the result will be c.shape[3:] +
+ x.shape.
+
+ Parameters
+ ----------
+ x, y, z : array_like, compatible object
+ The three dimensional series is evaluated at the points
+ `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
+ any of `x`, `y`, or `z` is a list or tuple, it is first converted
+ to an ndarray, otherwise it is left unchanged and if it isn't an
+ ndarray it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficient of the term of
+ multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
+ greater than 3 the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the multidimensional polynomial on points formed with
+ triples of corresponding values from `x`, `y`, and `z`.
+
+ See Also
+ --------
+ hermeval, hermeval2d, hermegrid2d, hermegrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._valnd(hermeval, c, x, y, z)
+
+
+def hermegrid3d(x, y, z, c):
+ """
+ Evaluate a 3-D HermiteE series on the Cartesian product of x, y, and z.
+
+ This function returns the values:
+
+ .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * He_i(a) * He_j(b) * He_k(c)
+
+ where the points `(a, b, c)` consist of all triples formed by taking
+ `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
+ a grid with `x` in the first dimension, `y` in the second, and `z` in
+ the third.
+
+ The parameters `x`, `y`, and `z` are converted to arrays only if they
+ are tuples or a lists, otherwise they are treated as a scalars. In
+ either case, either `x`, `y`, and `z` or their elements must support
+ multiplication and addition both with themselves and with the elements
+ of `c`.
+
+ If `c` has fewer than three dimensions, ones are implicitly appended to
+ its shape to make it 3-D. The shape of the result will be c.shape[3:] +
+ x.shape + y.shape + z.shape.
+
+ Parameters
+ ----------
+ x, y, z : array_like, compatible objects
+ The three dimensional series is evaluated at the points in the
+ Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
+ list or tuple, it is first converted to an ndarray, otherwise it is
+ left unchanged and, if it isn't an ndarray, it is treated as a
+ scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficients for terms of
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
+ greater than two the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional polynomial at points in the Cartesian
+ product of `x` and `y`.
+
+ See Also
+ --------
+ hermeval, hermeval2d, hermegrid2d, hermeval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._gridnd(hermeval, c, x, y, z)
+
+
+def hermevander(x, deg):
+ """Pseudo-Vandermonde matrix of given degree.
+
+ Returns the pseudo-Vandermonde matrix of degree `deg` and sample points
+ `x`. The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., i] = He_i(x),
+
+ where `0 <= i <= deg`. The leading indices of `V` index the elements of
+ `x` and the last index is the degree of the HermiteE polynomial.
+
+ If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
+ array ``V = hermevander(x, n)``, then ``np.dot(V, c)`` and
+ ``hermeval(x, c)`` are the same up to roundoff. This equivalence is
+ useful both for least squares fitting and for the evaluation of a large
+ number of HermiteE series of the same degree and sample points.
+
+ Parameters
+ ----------
+ x : array_like
+ Array of points. The dtype is converted to float64 or complex128
+ depending on whether any of the elements are complex. If `x` is
+ scalar it is converted to a 1-D array.
+ deg : int
+ Degree of the resulting matrix.
+
+ Returns
+ -------
+ vander : ndarray
+ The pseudo-Vandermonde matrix. The shape of the returned matrix is
+ ``x.shape + (deg + 1,)``, where The last index is the degree of the
+ corresponding HermiteE polynomial. The dtype will be the same as
+ the converted `x`.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import hermevander
+ >>> x = np.array([-1, 0, 1])
+ >>> hermevander(x, 3)
+ array([[ 1., -1., 0., 2.],
+ [ 1., 0., -1., -0.],
+ [ 1., 1., 0., -2.]])
+
+ """
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg < 0:
+ raise ValueError("deg must be non-negative")
+
+ x = np.array(x, copy=False, ndmin=1) + 0.0
+ dims = (ideg + 1,) + x.shape
+ dtyp = x.dtype
+ v = np.empty(dims, dtype=dtyp)
+ v[0] = x*0 + 1
+ if ideg > 0:
+ v[1] = x
+ for i in range(2, ideg + 1):
+ v[i] = (v[i-1]*x - v[i-2]*(i - 1))
+ return np.moveaxis(v, 0, -1)
+
+
+def hermevander2d(x, y, deg):
+ """Pseudo-Vandermonde matrix of given degrees.
+
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
+ points `(x, y)`. The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., (deg[1] + 1)*i + j] = He_i(x) * He_j(y),
+
+ where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
+ `V` index the points `(x, y)` and the last index encodes the degrees of
+ the HermiteE polynomials.
+
+ If ``V = hermevander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
+ correspond to the elements of a 2-D coefficient array `c` of shape
+ (xdeg + 1, ydeg + 1) in the order
+
+ .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
+
+ and ``np.dot(V, c.flat)`` and ``hermeval2d(x, y, c)`` will be the same
+ up to roundoff. This equivalence is useful both for least squares
+ fitting and for the evaluation of a large number of 2-D HermiteE
+ series of the same degrees and sample points.
+
+ Parameters
+ ----------
+ x, y : array_like
+ Arrays of point coordinates, all of the same shape. The dtypes
+ will be converted to either float64 or complex128 depending on
+ whether any of the elements are complex. Scalars are converted to
+ 1-D arrays.
+ deg : list of ints
+ List of maximum degrees of the form [x_deg, y_deg].
+
+ Returns
+ -------
+ vander2d : ndarray
+ The shape of the returned matrix is ``x.shape + (order,)``, where
+ :math:`order = (deg[0]+1)*(deg[1]+1)`. The dtype will be the same
+ as the converted `x` and `y`.
+
+ See Also
+ --------
+ hermevander, hermevander3d, hermeval2d, hermeval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._vander_nd_flat((hermevander, hermevander), (x, y), deg)
+
+
+def hermevander3d(x, y, z, deg):
+ """Pseudo-Vandermonde matrix of given degrees.
+
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
+ points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
+ then Hehe pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = He_i(x)*He_j(y)*He_k(z),
+
+ where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
+ indices of `V` index the points `(x, y, z)` and the last index encodes
+ the degrees of the HermiteE polynomials.
+
+ If ``V = hermevander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
+ of `V` correspond to the elements of a 3-D coefficient array `c` of
+ shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
+
+ .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
+
+ and ``np.dot(V, c.flat)`` and ``hermeval3d(x, y, z, c)`` will be the
+ same up to roundoff. This equivalence is useful both for least squares
+ fitting and for the evaluation of a large number of 3-D HermiteE
+ series of the same degrees and sample points.
+
+ Parameters
+ ----------
+ x, y, z : array_like
+ Arrays of point coordinates, all of the same shape. The dtypes will
+ be converted to either float64 or complex128 depending on whether
+ any of the elements are complex. Scalars are converted to 1-D
+ arrays.
+ deg : list of ints
+ List of maximum degrees of the form [x_deg, y_deg, z_deg].
+
+ Returns
+ -------
+ vander3d : ndarray
+ The shape of the returned matrix is ``x.shape + (order,)``, where
+ :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`. The dtype will
+ be the same as the converted `x`, `y`, and `z`.
+
+ See Also
+ --------
+ hermevander, hermevander3d, hermeval2d, hermeval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._vander_nd_flat((hermevander, hermevander, hermevander), (x, y, z), deg)
+
+
+def hermefit(x, y, deg, rcond=None, full=False, w=None):
+ """
+ Least squares fit of Hermite series to data.
+
+ Return the coefficients of a HermiteE series of degree `deg` that is
+ the least squares fit to the data values `y` given at points `x`. If
+ `y` is 1-D the returned coefficients will also be 1-D. If `y` is 2-D
+ multiple fits are done, one for each column of `y`, and the resulting
+ coefficients are stored in the corresponding columns of a 2-D return.
+ The fitted polynomial(s) are in the form
+
+ .. math:: p(x) = c_0 + c_1 * He_1(x) + ... + c_n * He_n(x),
+
+ where `n` is `deg`.
+
+ Parameters
+ ----------
+ x : array_like, shape (M,)
+ x-coordinates of the M sample points ``(x[i], y[i])``.
+ y : array_like, shape (M,) or (M, K)
+ y-coordinates of the sample points. Several data sets of sample
+ points sharing the same x-coordinates can be fitted at once by
+ passing in a 2D-array that contains one dataset per column.
+ deg : int or 1-D array_like
+ Degree(s) of the fitting polynomials. If `deg` is a single integer
+ all terms up to and including the `deg`'th term are included in the
+ fit. For NumPy versions >= 1.11.0 a list of integers specifying the
+ degrees of the terms to include may be used instead.
+ rcond : float, optional
+ Relative condition number of the fit. Singular values smaller than
+ this relative to the largest singular value will be ignored. The
+ default value is len(x)*eps, where eps is the relative precision of
+ the float type, about 2e-16 in most cases.
+ full : bool, optional
+ Switch determining nature of return value. When it is False (the
+ default) just the coefficients are returned, when True diagnostic
+ information from the singular value decomposition is also returned.
+ w : array_like, shape (`M`,), optional
+ Weights. If not None, the weight ``w[i]`` applies to the unsquared
+ residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
+ chosen so that the errors of the products ``w[i]*y[i]`` all have the
+ same variance. When using inverse-variance weighting, use
+ ``w[i] = 1/sigma(y[i])``. The default value is None.
+
+ Returns
+ -------
+ coef : ndarray, shape (M,) or (M, K)
+ Hermite coefficients ordered from low to high. If `y` was 2-D,
+ the coefficients for the data in column k of `y` are in column
+ `k`.
+
+ [residuals, rank, singular_values, rcond] : list
+ These values are only returned if ``full == True``
+
+ - residuals -- sum of squared residuals of the least squares fit
+ - rank -- the numerical rank of the scaled Vandermonde matrix
+ - singular_values -- singular values of the scaled Vandermonde matrix
+ - rcond -- value of `rcond`.
+
+ For more details, see `numpy.linalg.lstsq`.
+
+ Warns
+ -----
+ RankWarning
+ The rank of the coefficient matrix in the least-squares fit is
+ deficient. The warning is only raised if ``full = False``. The
+ warnings can be turned off by
+
+ >>> import warnings
+ >>> warnings.simplefilter('ignore', np.RankWarning)
+
+ See Also
+ --------
+ numpy.polynomial.chebyshev.chebfit
+ numpy.polynomial.legendre.legfit
+ numpy.polynomial.polynomial.polyfit
+ numpy.polynomial.hermite.hermfit
+ numpy.polynomial.laguerre.lagfit
+ hermeval : Evaluates a Hermite series.
+ hermevander : pseudo Vandermonde matrix of Hermite series.
+ hermeweight : HermiteE weight function.
+ numpy.linalg.lstsq : Computes a least-squares fit from the matrix.
+ scipy.interpolate.UnivariateSpline : Computes spline fits.
+
+ Notes
+ -----
+ The solution is the coefficients of the HermiteE series `p` that
+ minimizes the sum of the weighted squared errors
+
+ .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
+
+ where the :math:`w_j` are the weights. This problem is solved by
+ setting up the (typically) overdetermined matrix equation
+
+ .. math:: V(x) * c = w * y,
+
+ where `V` is the pseudo Vandermonde matrix of `x`, the elements of `c`
+ are the coefficients to be solved for, and the elements of `y` are the
+ observed values. This equation is then solved using the singular value
+ decomposition of `V`.
+
+ If some of the singular values of `V` are so small that they are
+ neglected, then a `RankWarning` will be issued. This means that the
+ coefficient values may be poorly determined. Using a lower order fit
+ will usually get rid of the warning. The `rcond` parameter can also be
+ set to a value smaller than its default, but the resulting fit may be
+ spurious and have large contributions from roundoff error.
+
+ Fits using HermiteE series are probably most useful when the data can
+ be approximated by ``sqrt(w(x)) * p(x)``, where `w(x)` is the HermiteE
+ weight. In that case the weight ``sqrt(w(x[i]))`` should be used
+ together with data values ``y[i]/sqrt(w(x[i]))``. The weight function is
+ available as `hermeweight`.
+
+ References
+ ----------
+ .. [1] Wikipedia, "Curve fitting",
+ https://en.wikipedia.org/wiki/Curve_fitting
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import hermefit, hermeval
+ >>> x = np.linspace(-10, 10)
+ >>> np.random.seed(123)
+ >>> err = np.random.randn(len(x))/10
+ >>> y = hermeval(x, [1, 2, 3]) + err
+ >>> hermefit(x, y, 2)
+ array([ 1.01690445, 1.99951418, 2.99948696]) # may vary
+
+ """
+ return pu._fit(hermevander, x, y, deg, rcond, full, w)
+
+
+def hermecompanion(c):
+ """
+ Return the scaled companion matrix of c.
+
+ The basis polynomials are scaled so that the companion matrix is
+ symmetric when `c` is an HermiteE basis polynomial. This provides
+ better eigenvalue estimates than the unscaled case and for basis
+ polynomials the eigenvalues are guaranteed to be real if
+ `numpy.linalg.eigvalsh` is used to obtain them.
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of HermiteE series coefficients ordered from low to high
+ degree.
+
+ Returns
+ -------
+ mat : ndarray
+ Scaled companion matrix of dimensions (deg, deg).
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ if len(c) < 2:
+ raise ValueError('Series must have maximum degree of at least 1.')
+ if len(c) == 2:
+ return np.array([[-c[0]/c[1]]])
+
+ n = len(c) - 1
+ mat = np.zeros((n, n), dtype=c.dtype)
+ scl = np.hstack((1., 1./np.sqrt(np.arange(n - 1, 0, -1))))
+ scl = np.multiply.accumulate(scl)[::-1]
+ top = mat.reshape(-1)[1::n+1]
+ bot = mat.reshape(-1)[n::n+1]
+ top[...] = np.sqrt(np.arange(1, n))
+ bot[...] = top
+ mat[:, -1] -= scl*c[:-1]/c[-1]
+ return mat
+
+
+def hermeroots(c):
+ """
+ Compute the roots of a HermiteE series.
+
+ Return the roots (a.k.a. "zeros") of the polynomial
+
+ .. math:: p(x) = \\sum_i c[i] * He_i(x).
+
+ Parameters
+ ----------
+ c : 1-D array_like
+ 1-D array of coefficients.
+
+ Returns
+ -------
+ out : ndarray
+ Array of the roots of the series. If all the roots are real,
+ then `out` is also real, otherwise it is complex.
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyroots
+ numpy.polynomial.legendre.legroots
+ numpy.polynomial.laguerre.lagroots
+ numpy.polynomial.hermite.hermroots
+ numpy.polynomial.chebyshev.chebroots
+
+ Notes
+ -----
+ The root estimates are obtained as the eigenvalues of the companion
+ matrix, Roots far from the origin of the complex plane may have large
+ errors due to the numerical instability of the series for such
+ values. Roots with multiplicity greater than 1 will also show larger
+ errors as the value of the series near such points is relatively
+ insensitive to errors in the roots. Isolated roots near the origin can
+ be improved by a few iterations of Newton's method.
+
+ The HermiteE series basis polynomials aren't powers of `x` so the
+ results of this function may seem unintuitive.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.hermite_e import hermeroots, hermefromroots
+ >>> coef = hermefromroots([-1, 0, 1])
+ >>> coef
+ array([0., 2., 0., 1.])
+ >>> hermeroots(coef)
+ array([-1., 0., 1.]) # may vary
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ if len(c) <= 1:
+ return np.array([], dtype=c.dtype)
+ if len(c) == 2:
+ return np.array([-c[0]/c[1]])
+
+ # rotated companion matrix reduces error
+ m = hermecompanion(c)[::-1,::-1]
+ r = la.eigvals(m)
+ r.sort()
+ return r
+
+
+def _normed_hermite_e_n(x, n):
+ """
+ Evaluate a normalized HermiteE polynomial.
+
+ Compute the value of the normalized HermiteE polynomial of degree ``n``
+ at the points ``x``.
+
+
+ Parameters
+ ----------
+ x : ndarray of double.
+ Points at which to evaluate the function
+ n : int
+ Degree of the normalized HermiteE function to be evaluated.
+
+ Returns
+ -------
+ values : ndarray
+ The shape of the return value is described above.
+
+ Notes
+ -----
+ .. versionadded:: 1.10.0
+
+ This function is needed for finding the Gauss points and integration
+ weights for high degrees. The values of the standard HermiteE functions
+ overflow when n >= 207.
+
+ """
+ if n == 0:
+ return np.full(x.shape, 1/np.sqrt(np.sqrt(2*np.pi)))
+
+ c0 = 0.
+ c1 = 1./np.sqrt(np.sqrt(2*np.pi))
+ nd = float(n)
+ for i in range(n - 1):
+ tmp = c0
+ c0 = -c1*np.sqrt((nd - 1.)/nd)
+ c1 = tmp + c1*x*np.sqrt(1./nd)
+ nd = nd - 1.0
+ return c0 + c1*x
+
+
+def hermegauss(deg):
+ """
+ Gauss-HermiteE quadrature.
+
+ Computes the sample points and weights for Gauss-HermiteE quadrature.
+ These sample points and weights will correctly integrate polynomials of
+ degree :math:`2*deg - 1` or less over the interval :math:`[-\\inf, \\inf]`
+ with the weight function :math:`f(x) = \\exp(-x^2/2)`.
+
+ Parameters
+ ----------
+ deg : int
+ Number of sample points and weights. It must be >= 1.
+
+ Returns
+ -------
+ x : ndarray
+ 1-D ndarray containing the sample points.
+ y : ndarray
+ 1-D ndarray containing the weights.
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ The results have only been tested up to degree 100, higher degrees may
+ be problematic. The weights are determined by using the fact that
+
+ .. math:: w_k = c / (He'_n(x_k) * He_{n-1}(x_k))
+
+ where :math:`c` is a constant independent of :math:`k` and :math:`x_k`
+ is the k'th root of :math:`He_n`, and then scaling the results to get
+ the right value when integrating 1.
+
+ """
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg <= 0:
+ raise ValueError("deg must be a positive integer")
+
+ # first approximation of roots. We use the fact that the companion
+ # matrix is symmetric in this case in order to obtain better zeros.
+ c = np.array([0]*deg + [1])
+ m = hermecompanion(c)
+ x = la.eigvalsh(m)
+
+ # improve roots by one application of Newton
+ dy = _normed_hermite_e_n(x, ideg)
+ df = _normed_hermite_e_n(x, ideg - 1) * np.sqrt(ideg)
+ x -= dy/df
+
+ # compute the weights. We scale the factor to avoid possible numerical
+ # overflow.
+ fm = _normed_hermite_e_n(x, ideg - 1)
+ fm /= np.abs(fm).max()
+ w = 1/(fm * fm)
+
+ # for Hermite_e we can also symmetrize
+ w = (w + w[::-1])/2
+ x = (x - x[::-1])/2
+
+ # scale w to get the right value
+ w *= np.sqrt(2*np.pi) / w.sum()
+
+ return x, w
+
+
+def hermeweight(x):
+ """Weight function of the Hermite_e polynomials.
+
+ The weight function is :math:`\\exp(-x^2/2)` and the interval of
+ integration is :math:`[-\\inf, \\inf]`. the HermiteE polynomials are
+ orthogonal, but not normalized, with respect to this weight function.
+
+ Parameters
+ ----------
+ x : array_like
+ Values at which the weight function will be computed.
+
+ Returns
+ -------
+ w : ndarray
+ The weight function at `x`.
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ w = np.exp(-.5*x**2)
+ return w
+
+
+#
+# HermiteE series class
+#
+
+class HermiteE(ABCPolyBase):
+ """An HermiteE series class.
+
+ The HermiteE class provides the standard Python numerical methods
+ '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
+ attributes and methods listed in the `ABCPolyBase` documentation.
+
+ Parameters
+ ----------
+ coef : array_like
+ HermiteE coefficients in order of increasing degree, i.e,
+ ``(1, 2, 3)`` gives ``1*He_0(x) + 2*He_1(X) + 3*He_2(x)``.
+ domain : (2,) array_like, optional
+ Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
+ to the interval ``[window[0], window[1]]`` by shifting and scaling.
+ The default value is [-1, 1].
+ window : (2,) array_like, optional
+ Window, see `domain` for its use. The default value is [-1, 1].
+
+ .. versionadded:: 1.6.0
+ symbol : str, optional
+ Symbol used to represent the independent variable in string
+ representations of the polynomial expression, e.g. for printing.
+ The symbol must be a valid Python identifier. Default value is 'x'.
+
+ .. versionadded:: 1.24
+
+ """
+ # Virtual Functions
+ _add = staticmethod(hermeadd)
+ _sub = staticmethod(hermesub)
+ _mul = staticmethod(hermemul)
+ _div = staticmethod(hermediv)
+ _pow = staticmethod(hermepow)
+ _val = staticmethod(hermeval)
+ _int = staticmethod(hermeint)
+ _der = staticmethod(hermeder)
+ _fit = staticmethod(hermefit)
+ _line = staticmethod(hermeline)
+ _roots = staticmethod(hermeroots)
+ _fromroots = staticmethod(hermefromroots)
+
+ # Virtual properties
+ domain = np.array(hermedomain)
+ window = np.array(hermedomain)
+ basis_name = 'He'
diff --git a/lib/python3.12/site-packages/numpy/polynomial/hermite_e.pyi b/lib/python3.12/site-packages/numpy/polynomial/hermite_e.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..0b7152a253b654da2c069711a1bfdbd4e084cf6f
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/hermite_e.pyi
@@ -0,0 +1,46 @@
+from typing import Any
+
+from numpy import ndarray, dtype, int_
+from numpy.polynomial._polybase import ABCPolyBase
+from numpy.polynomial.polyutils import trimcoef
+
+__all__: list[str]
+
+hermetrim = trimcoef
+
+def poly2herme(pol): ...
+def herme2poly(c): ...
+
+hermedomain: ndarray[Any, dtype[int_]]
+hermezero: ndarray[Any, dtype[int_]]
+hermeone: ndarray[Any, dtype[int_]]
+hermex: ndarray[Any, dtype[int_]]
+
+def hermeline(off, scl): ...
+def hermefromroots(roots): ...
+def hermeadd(c1, c2): ...
+def hermesub(c1, c2): ...
+def hermemulx(c): ...
+def hermemul(c1, c2): ...
+def hermediv(c1, c2): ...
+def hermepow(c, pow, maxpower=...): ...
+def hermeder(c, m=..., scl=..., axis=...): ...
+def hermeint(c, m=..., k = ..., lbnd=..., scl=..., axis=...): ...
+def hermeval(x, c, tensor=...): ...
+def hermeval2d(x, y, c): ...
+def hermegrid2d(x, y, c): ...
+def hermeval3d(x, y, z, c): ...
+def hermegrid3d(x, y, z, c): ...
+def hermevander(x, deg): ...
+def hermevander2d(x, y, deg): ...
+def hermevander3d(x, y, z, deg): ...
+def hermefit(x, y, deg, rcond=..., full=..., w=...): ...
+def hermecompanion(c): ...
+def hermeroots(c): ...
+def hermegauss(deg): ...
+def hermeweight(x): ...
+
+class HermiteE(ABCPolyBase):
+ domain: Any
+ window: Any
+ basis_name: Any
diff --git a/lib/python3.12/site-packages/numpy/polynomial/laguerre.py b/lib/python3.12/site-packages/numpy/polynomial/laguerre.py
new file mode 100644
index 0000000000000000000000000000000000000000..925d4898ec07673f221937fff1082711a9851df9
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/laguerre.py
@@ -0,0 +1,1651 @@
+"""
+==================================================
+Laguerre Series (:mod:`numpy.polynomial.laguerre`)
+==================================================
+
+This module provides a number of objects (mostly functions) useful for
+dealing with Laguerre series, including a `Laguerre` class that
+encapsulates the usual arithmetic operations. (General information
+on how this module represents and works with such polynomials is in the
+docstring for its "parent" sub-package, `numpy.polynomial`).
+
+Classes
+-------
+.. autosummary::
+ :toctree: generated/
+
+ Laguerre
+
+Constants
+---------
+.. autosummary::
+ :toctree: generated/
+
+ lagdomain
+ lagzero
+ lagone
+ lagx
+
+Arithmetic
+----------
+.. autosummary::
+ :toctree: generated/
+
+ lagadd
+ lagsub
+ lagmulx
+ lagmul
+ lagdiv
+ lagpow
+ lagval
+ lagval2d
+ lagval3d
+ laggrid2d
+ laggrid3d
+
+Calculus
+--------
+.. autosummary::
+ :toctree: generated/
+
+ lagder
+ lagint
+
+Misc Functions
+--------------
+.. autosummary::
+ :toctree: generated/
+
+ lagfromroots
+ lagroots
+ lagvander
+ lagvander2d
+ lagvander3d
+ laggauss
+ lagweight
+ lagcompanion
+ lagfit
+ lagtrim
+ lagline
+ lag2poly
+ poly2lag
+
+See also
+--------
+`numpy.polynomial`
+
+"""
+import numpy as np
+import numpy.linalg as la
+from numpy.core.multiarray import normalize_axis_index
+
+from . import polyutils as pu
+from ._polybase import ABCPolyBase
+
+__all__ = [
+ 'lagzero', 'lagone', 'lagx', 'lagdomain', 'lagline', 'lagadd',
+ 'lagsub', 'lagmulx', 'lagmul', 'lagdiv', 'lagpow', 'lagval', 'lagder',
+ 'lagint', 'lag2poly', 'poly2lag', 'lagfromroots', 'lagvander',
+ 'lagfit', 'lagtrim', 'lagroots', 'Laguerre', 'lagval2d', 'lagval3d',
+ 'laggrid2d', 'laggrid3d', 'lagvander2d', 'lagvander3d', 'lagcompanion',
+ 'laggauss', 'lagweight']
+
+lagtrim = pu.trimcoef
+
+
+def poly2lag(pol):
+ """
+ poly2lag(pol)
+
+ Convert a polynomial to a Laguerre series.
+
+ Convert an array representing the coefficients of a polynomial (relative
+ to the "standard" basis) ordered from lowest degree to highest, to an
+ array of the coefficients of the equivalent Laguerre series, ordered
+ from lowest to highest degree.
+
+ Parameters
+ ----------
+ pol : array_like
+ 1-D array containing the polynomial coefficients
+
+ Returns
+ -------
+ c : ndarray
+ 1-D array containing the coefficients of the equivalent Laguerre
+ series.
+
+ See Also
+ --------
+ lag2poly
+
+ Notes
+ -----
+ The easy way to do conversions between polynomial basis sets
+ is to use the convert method of a class instance.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import poly2lag
+ >>> poly2lag(np.arange(4))
+ array([ 23., -63., 58., -18.])
+
+ """
+ [pol] = pu.as_series([pol])
+ res = 0
+ for p in pol[::-1]:
+ res = lagadd(lagmulx(res), p)
+ return res
+
+
+def lag2poly(c):
+ """
+ Convert a Laguerre series to a polynomial.
+
+ Convert an array representing the coefficients of a Laguerre series,
+ ordered from lowest degree to highest, to an array of the coefficients
+ of the equivalent polynomial (relative to the "standard" basis) ordered
+ from lowest to highest degree.
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array containing the Laguerre series coefficients, ordered
+ from lowest order term to highest.
+
+ Returns
+ -------
+ pol : ndarray
+ 1-D array containing the coefficients of the equivalent polynomial
+ (relative to the "standard" basis) ordered from lowest order term
+ to highest.
+
+ See Also
+ --------
+ poly2lag
+
+ Notes
+ -----
+ The easy way to do conversions between polynomial basis sets
+ is to use the convert method of a class instance.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import lag2poly
+ >>> lag2poly([ 23., -63., 58., -18.])
+ array([0., 1., 2., 3.])
+
+ """
+ from .polynomial import polyadd, polysub, polymulx
+
+ [c] = pu.as_series([c])
+ n = len(c)
+ if n == 1:
+ return c
+ else:
+ c0 = c[-2]
+ c1 = c[-1]
+ # i is the current degree of c1
+ for i in range(n - 1, 1, -1):
+ tmp = c0
+ c0 = polysub(c[i - 2], (c1*(i - 1))/i)
+ c1 = polyadd(tmp, polysub((2*i - 1)*c1, polymulx(c1))/i)
+ return polyadd(c0, polysub(c1, polymulx(c1)))
+
+#
+# These are constant arrays are of integer type so as to be compatible
+# with the widest range of other types, such as Decimal.
+#
+
+# Laguerre
+lagdomain = np.array([0, 1])
+
+# Laguerre coefficients representing zero.
+lagzero = np.array([0])
+
+# Laguerre coefficients representing one.
+lagone = np.array([1])
+
+# Laguerre coefficients representing the identity x.
+lagx = np.array([1, -1])
+
+
+def lagline(off, scl):
+ """
+ Laguerre series whose graph is a straight line.
+
+ Parameters
+ ----------
+ off, scl : scalars
+ The specified line is given by ``off + scl*x``.
+
+ Returns
+ -------
+ y : ndarray
+ This module's representation of the Laguerre series for
+ ``off + scl*x``.
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyline
+ numpy.polynomial.chebyshev.chebline
+ numpy.polynomial.legendre.legline
+ numpy.polynomial.hermite.hermline
+ numpy.polynomial.hermite_e.hermeline
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import lagline, lagval
+ >>> lagval(0,lagline(3, 2))
+ 3.0
+ >>> lagval(1,lagline(3, 2))
+ 5.0
+
+ """
+ if scl != 0:
+ return np.array([off + scl, -scl])
+ else:
+ return np.array([off])
+
+
+def lagfromroots(roots):
+ """
+ Generate a Laguerre series with given roots.
+
+ The function returns the coefficients of the polynomial
+
+ .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
+
+ in Laguerre form, where the `r_n` are the roots specified in `roots`.
+ If a zero has multiplicity n, then it must appear in `roots` n times.
+ For instance, if 2 is a root of multiplicity three and 3 is a root of
+ multiplicity 2, then `roots` looks something like [2, 2, 2, 3, 3]. The
+ roots can appear in any order.
+
+ If the returned coefficients are `c`, then
+
+ .. math:: p(x) = c_0 + c_1 * L_1(x) + ... + c_n * L_n(x)
+
+ The coefficient of the last term is not generally 1 for monic
+ polynomials in Laguerre form.
+
+ Parameters
+ ----------
+ roots : array_like
+ Sequence containing the roots.
+
+ Returns
+ -------
+ out : ndarray
+ 1-D array of coefficients. If all roots are real then `out` is a
+ real array, if some of the roots are complex, then `out` is complex
+ even if all the coefficients in the result are real (see Examples
+ below).
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyfromroots
+ numpy.polynomial.legendre.legfromroots
+ numpy.polynomial.chebyshev.chebfromroots
+ numpy.polynomial.hermite.hermfromroots
+ numpy.polynomial.hermite_e.hermefromroots
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import lagfromroots, lagval
+ >>> coef = lagfromroots((-1, 0, 1))
+ >>> lagval((-1, 0, 1), coef)
+ array([0., 0., 0.])
+ >>> coef = lagfromroots((-1j, 1j))
+ >>> lagval((-1j, 1j), coef)
+ array([0.+0.j, 0.+0.j])
+
+ """
+ return pu._fromroots(lagline, lagmul, roots)
+
+
+def lagadd(c1, c2):
+ """
+ Add one Laguerre series to another.
+
+ Returns the sum of two Laguerre series `c1` + `c2`. The arguments
+ are sequences of coefficients ordered from lowest order term to
+ highest, i.e., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Laguerre series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Array representing the Laguerre series of their sum.
+
+ See Also
+ --------
+ lagsub, lagmulx, lagmul, lagdiv, lagpow
+
+ Notes
+ -----
+ Unlike multiplication, division, etc., the sum of two Laguerre series
+ is a Laguerre series (without having to "reproject" the result onto
+ the basis set) so addition, just like that of "standard" polynomials,
+ is simply "component-wise."
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import lagadd
+ >>> lagadd([1, 2, 3], [1, 2, 3, 4])
+ array([2., 4., 6., 4.])
+
+
+ """
+ return pu._add(c1, c2)
+
+
+def lagsub(c1, c2):
+ """
+ Subtract one Laguerre series from another.
+
+ Returns the difference of two Laguerre series `c1` - `c2`. The
+ sequences of coefficients are from lowest order term to highest, i.e.,
+ [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Laguerre series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Of Laguerre series coefficients representing their difference.
+
+ See Also
+ --------
+ lagadd, lagmulx, lagmul, lagdiv, lagpow
+
+ Notes
+ -----
+ Unlike multiplication, division, etc., the difference of two Laguerre
+ series is a Laguerre series (without having to "reproject" the result
+ onto the basis set) so subtraction, just like that of "standard"
+ polynomials, is simply "component-wise."
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import lagsub
+ >>> lagsub([1, 2, 3, 4], [1, 2, 3])
+ array([0., 0., 0., 4.])
+
+ """
+ return pu._sub(c1, c2)
+
+
+def lagmulx(c):
+ """Multiply a Laguerre series by x.
+
+ Multiply the Laguerre series `c` by x, where x is the independent
+ variable.
+
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of Laguerre series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Array representing the result of the multiplication.
+
+ See Also
+ --------
+ lagadd, lagsub, lagmul, lagdiv, lagpow
+
+ Notes
+ -----
+ The multiplication uses the recursion relationship for Laguerre
+ polynomials in the form
+
+ .. math::
+
+ xP_i(x) = (-(i + 1)*P_{i + 1}(x) + (2i + 1)P_{i}(x) - iP_{i - 1}(x))
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import lagmulx
+ >>> lagmulx([1, 2, 3])
+ array([-1., -1., 11., -9.])
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ # The zero series needs special treatment
+ if len(c) == 1 and c[0] == 0:
+ return c
+
+ prd = np.empty(len(c) + 1, dtype=c.dtype)
+ prd[0] = c[0]
+ prd[1] = -c[0]
+ for i in range(1, len(c)):
+ prd[i + 1] = -c[i]*(i + 1)
+ prd[i] += c[i]*(2*i + 1)
+ prd[i - 1] -= c[i]*i
+ return prd
+
+
+def lagmul(c1, c2):
+ """
+ Multiply one Laguerre series by another.
+
+ Returns the product of two Laguerre series `c1` * `c2`. The arguments
+ are sequences of coefficients, from lowest order "term" to highest,
+ e.g., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Laguerre series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Of Laguerre series coefficients representing their product.
+
+ See Also
+ --------
+ lagadd, lagsub, lagmulx, lagdiv, lagpow
+
+ Notes
+ -----
+ In general, the (polynomial) product of two C-series results in terms
+ that are not in the Laguerre polynomial basis set. Thus, to express
+ the product as a Laguerre series, it is necessary to "reproject" the
+ product onto said basis set, which may produce "unintuitive" (but
+ correct) results; see Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import lagmul
+ >>> lagmul([1, 2, 3], [0, 1, 2])
+ array([ 8., -13., 38., -51., 36.])
+
+ """
+ # s1, s2 are trimmed copies
+ [c1, c2] = pu.as_series([c1, c2])
+
+ if len(c1) > len(c2):
+ c = c2
+ xs = c1
+ else:
+ c = c1
+ xs = c2
+
+ if len(c) == 1:
+ c0 = c[0]*xs
+ c1 = 0
+ elif len(c) == 2:
+ c0 = c[0]*xs
+ c1 = c[1]*xs
+ else:
+ nd = len(c)
+ c0 = c[-2]*xs
+ c1 = c[-1]*xs
+ for i in range(3, len(c) + 1):
+ tmp = c0
+ nd = nd - 1
+ c0 = lagsub(c[-i]*xs, (c1*(nd - 1))/nd)
+ c1 = lagadd(tmp, lagsub((2*nd - 1)*c1, lagmulx(c1))/nd)
+ return lagadd(c0, lagsub(c1, lagmulx(c1)))
+
+
+def lagdiv(c1, c2):
+ """
+ Divide one Laguerre series by another.
+
+ Returns the quotient-with-remainder of two Laguerre series
+ `c1` / `c2`. The arguments are sequences of coefficients from lowest
+ order "term" to highest, e.g., [1,2,3] represents the series
+ ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Laguerre series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ [quo, rem] : ndarrays
+ Of Laguerre series coefficients representing the quotient and
+ remainder.
+
+ See Also
+ --------
+ lagadd, lagsub, lagmulx, lagmul, lagpow
+
+ Notes
+ -----
+ In general, the (polynomial) division of one Laguerre series by another
+ results in quotient and remainder terms that are not in the Laguerre
+ polynomial basis set. Thus, to express these results as a Laguerre
+ series, it is necessary to "reproject" the results onto the Laguerre
+ basis set, which may produce "unintuitive" (but correct) results; see
+ Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import lagdiv
+ >>> lagdiv([ 8., -13., 38., -51., 36.], [0, 1, 2])
+ (array([1., 2., 3.]), array([0.]))
+ >>> lagdiv([ 9., -12., 38., -51., 36.], [0, 1, 2])
+ (array([1., 2., 3.]), array([1., 1.]))
+
+ """
+ return pu._div(lagmul, c1, c2)
+
+
+def lagpow(c, pow, maxpower=16):
+ """Raise a Laguerre series to a power.
+
+ Returns the Laguerre series `c` raised to the power `pow`. The
+ argument `c` is a sequence of coefficients ordered from low to high.
+ i.e., [1,2,3] is the series ``P_0 + 2*P_1 + 3*P_2.``
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of Laguerre series coefficients ordered from low to
+ high.
+ pow : integer
+ Power to which the series will be raised
+ maxpower : integer, optional
+ Maximum power allowed. This is mainly to limit growth of the series
+ to unmanageable size. Default is 16
+
+ Returns
+ -------
+ coef : ndarray
+ Laguerre series of power.
+
+ See Also
+ --------
+ lagadd, lagsub, lagmulx, lagmul, lagdiv
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import lagpow
+ >>> lagpow([1, 2, 3], 2)
+ array([ 14., -16., 56., -72., 54.])
+
+ """
+ return pu._pow(lagmul, c, pow, maxpower)
+
+
+def lagder(c, m=1, scl=1, axis=0):
+ """
+ Differentiate a Laguerre series.
+
+ Returns the Laguerre series coefficients `c` differentiated `m` times
+ along `axis`. At each iteration the result is multiplied by `scl` (the
+ scaling factor is for use in a linear change of variable). The argument
+ `c` is an array of coefficients from low to high degree along each
+ axis, e.g., [1,2,3] represents the series ``1*L_0 + 2*L_1 + 3*L_2``
+ while [[1,2],[1,2]] represents ``1*L_0(x)*L_0(y) + 1*L_1(x)*L_0(y) +
+ 2*L_0(x)*L_1(y) + 2*L_1(x)*L_1(y)`` if axis=0 is ``x`` and axis=1 is
+ ``y``.
+
+ Parameters
+ ----------
+ c : array_like
+ Array of Laguerre series coefficients. If `c` is multidimensional
+ the different axis correspond to different variables with the
+ degree in each axis given by the corresponding index.
+ m : int, optional
+ Number of derivatives taken, must be non-negative. (Default: 1)
+ scl : scalar, optional
+ Each differentiation is multiplied by `scl`. The end result is
+ multiplication by ``scl**m``. This is for use in a linear change of
+ variable. (Default: 1)
+ axis : int, optional
+ Axis over which the derivative is taken. (Default: 0).
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ der : ndarray
+ Laguerre series of the derivative.
+
+ See Also
+ --------
+ lagint
+
+ Notes
+ -----
+ In general, the result of differentiating a Laguerre series does not
+ resemble the same operation on a power series. Thus the result of this
+ function may be "unintuitive," albeit correct; see Examples section
+ below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import lagder
+ >>> lagder([ 1., 1., 1., -3.])
+ array([1., 2., 3.])
+ >>> lagder([ 1., 0., 0., -4., 3.], m=2)
+ array([1., 2., 3.])
+
+ """
+ c = np.array(c, ndmin=1, copy=True)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ c = c.astype(np.double)
+
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
+ if cnt < 0:
+ raise ValueError("The order of derivation must be non-negative")
+ iaxis = normalize_axis_index(iaxis, c.ndim)
+
+ if cnt == 0:
+ return c
+
+ c = np.moveaxis(c, iaxis, 0)
+ n = len(c)
+ if cnt >= n:
+ c = c[:1]*0
+ else:
+ for i in range(cnt):
+ n = n - 1
+ c *= scl
+ der = np.empty((n,) + c.shape[1:], dtype=c.dtype)
+ for j in range(n, 1, -1):
+ der[j - 1] = -c[j]
+ c[j - 1] += c[j]
+ der[0] = -c[1]
+ c = der
+ c = np.moveaxis(c, 0, iaxis)
+ return c
+
+
+def lagint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
+ """
+ Integrate a Laguerre series.
+
+ Returns the Laguerre series coefficients `c` integrated `m` times from
+ `lbnd` along `axis`. At each iteration the resulting series is
+ **multiplied** by `scl` and an integration constant, `k`, is added.
+ The scaling factor is for use in a linear change of variable. ("Buyer
+ beware": note that, depending on what one is doing, one may want `scl`
+ to be the reciprocal of what one might expect; for more information,
+ see the Notes section below.) The argument `c` is an array of
+ coefficients from low to high degree along each axis, e.g., [1,2,3]
+ represents the series ``L_0 + 2*L_1 + 3*L_2`` while [[1,2],[1,2]]
+ represents ``1*L_0(x)*L_0(y) + 1*L_1(x)*L_0(y) + 2*L_0(x)*L_1(y) +
+ 2*L_1(x)*L_1(y)`` if axis=0 is ``x`` and axis=1 is ``y``.
+
+
+ Parameters
+ ----------
+ c : array_like
+ Array of Laguerre series coefficients. If `c` is multidimensional
+ the different axis correspond to different variables with the
+ degree in each axis given by the corresponding index.
+ m : int, optional
+ Order of integration, must be positive. (Default: 1)
+ k : {[], list, scalar}, optional
+ Integration constant(s). The value of the first integral at
+ ``lbnd`` is the first value in the list, the value of the second
+ integral at ``lbnd`` is the second value, etc. If ``k == []`` (the
+ default), all constants are set to zero. If ``m == 1``, a single
+ scalar can be given instead of a list.
+ lbnd : scalar, optional
+ The lower bound of the integral. (Default: 0)
+ scl : scalar, optional
+ Following each integration the result is *multiplied* by `scl`
+ before the integration constant is added. (Default: 1)
+ axis : int, optional
+ Axis over which the integral is taken. (Default: 0).
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ S : ndarray
+ Laguerre series coefficients of the integral.
+
+ Raises
+ ------
+ ValueError
+ If ``m < 0``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
+ ``np.ndim(scl) != 0``.
+
+ See Also
+ --------
+ lagder
+
+ Notes
+ -----
+ Note that the result of each integration is *multiplied* by `scl`.
+ Why is this important to note? Say one is making a linear change of
+ variable :math:`u = ax + b` in an integral relative to `x`. Then
+ :math:`dx = du/a`, so one will need to set `scl` equal to
+ :math:`1/a` - perhaps not what one would have first thought.
+
+ Also note that, in general, the result of integrating a C-series needs
+ to be "reprojected" onto the C-series basis set. Thus, typically,
+ the result of this function is "unintuitive," albeit correct; see
+ Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import lagint
+ >>> lagint([1,2,3])
+ array([ 1., 1., 1., -3.])
+ >>> lagint([1,2,3], m=2)
+ array([ 1., 0., 0., -4., 3.])
+ >>> lagint([1,2,3], k=1)
+ array([ 2., 1., 1., -3.])
+ >>> lagint([1,2,3], lbnd=-1)
+ array([11.5, 1. , 1. , -3. ])
+ >>> lagint([1,2], m=2, k=[1,2], lbnd=-1)
+ array([ 11.16666667, -5. , -3. , 2. ]) # may vary
+
+ """
+ c = np.array(c, ndmin=1, copy=True)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ c = c.astype(np.double)
+ if not np.iterable(k):
+ k = [k]
+ cnt = pu._deprecate_as_int(m, "the order of integration")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
+ if cnt < 0:
+ raise ValueError("The order of integration must be non-negative")
+ if len(k) > cnt:
+ raise ValueError("Too many integration constants")
+ if np.ndim(lbnd) != 0:
+ raise ValueError("lbnd must be a scalar.")
+ if np.ndim(scl) != 0:
+ raise ValueError("scl must be a scalar.")
+ iaxis = normalize_axis_index(iaxis, c.ndim)
+
+ if cnt == 0:
+ return c
+
+ c = np.moveaxis(c, iaxis, 0)
+ k = list(k) + [0]*(cnt - len(k))
+ for i in range(cnt):
+ n = len(c)
+ c *= scl
+ if n == 1 and np.all(c[0] == 0):
+ c[0] += k[i]
+ else:
+ tmp = np.empty((n + 1,) + c.shape[1:], dtype=c.dtype)
+ tmp[0] = c[0]
+ tmp[1] = -c[0]
+ for j in range(1, n):
+ tmp[j] += c[j]
+ tmp[j + 1] = -c[j]
+ tmp[0] += k[i] - lagval(lbnd, tmp)
+ c = tmp
+ c = np.moveaxis(c, 0, iaxis)
+ return c
+
+
+def lagval(x, c, tensor=True):
+ """
+ Evaluate a Laguerre series at points x.
+
+ If `c` is of length `n + 1`, this function returns the value:
+
+ .. math:: p(x) = c_0 * L_0(x) + c_1 * L_1(x) + ... + c_n * L_n(x)
+
+ The parameter `x` is converted to an array only if it is a tuple or a
+ list, otherwise it is treated as a scalar. In either case, either `x`
+ or its elements must support multiplication and addition both with
+ themselves and with the elements of `c`.
+
+ If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
+ `c` is multidimensional, then the shape of the result depends on the
+ value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
+ x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
+ scalars have shape (,).
+
+ Trailing zeros in the coefficients will be used in the evaluation, so
+ they should be avoided if efficiency is a concern.
+
+ Parameters
+ ----------
+ x : array_like, compatible object
+ If `x` is a list or tuple, it is converted to an ndarray, otherwise
+ it is left unchanged and treated as a scalar. In either case, `x`
+ or its elements must support addition and multiplication with
+ themselves and with the elements of `c`.
+ c : array_like
+ Array of coefficients ordered so that the coefficients for terms of
+ degree n are contained in c[n]. If `c` is multidimensional the
+ remaining indices enumerate multiple polynomials. In the two
+ dimensional case the coefficients may be thought of as stored in
+ the columns of `c`.
+ tensor : boolean, optional
+ If True, the shape of the coefficient array is extended with ones
+ on the right, one for each dimension of `x`. Scalars have dimension 0
+ for this action. The result is that every column of coefficients in
+ `c` is evaluated for every element of `x`. If False, `x` is broadcast
+ over the columns of `c` for the evaluation. This keyword is useful
+ when `c` is multidimensional. The default value is True.
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ values : ndarray, algebra_like
+ The shape of the return value is described above.
+
+ See Also
+ --------
+ lagval2d, laggrid2d, lagval3d, laggrid3d
+
+ Notes
+ -----
+ The evaluation uses Clenshaw recursion, aka synthetic division.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import lagval
+ >>> coef = [1,2,3]
+ >>> lagval(1, coef)
+ -0.5
+ >>> lagval([[1,2],[3,4]], coef)
+ array([[-0.5, -4. ],
+ [-4.5, -2. ]])
+
+ """
+ c = np.array(c, ndmin=1, copy=False)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ c = c.astype(np.double)
+ if isinstance(x, (tuple, list)):
+ x = np.asarray(x)
+ if isinstance(x, np.ndarray) and tensor:
+ c = c.reshape(c.shape + (1,)*x.ndim)
+
+ if len(c) == 1:
+ c0 = c[0]
+ c1 = 0
+ elif len(c) == 2:
+ c0 = c[0]
+ c1 = c[1]
+ else:
+ nd = len(c)
+ c0 = c[-2]
+ c1 = c[-1]
+ for i in range(3, len(c) + 1):
+ tmp = c0
+ nd = nd - 1
+ c0 = c[-i] - (c1*(nd - 1))/nd
+ c1 = tmp + (c1*((2*nd - 1) - x))/nd
+ return c0 + c1*(1 - x)
+
+
+def lagval2d(x, y, c):
+ """
+ Evaluate a 2-D Laguerre series at points (x, y).
+
+ This function returns the values:
+
+ .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * L_i(x) * L_j(y)
+
+ The parameters `x` and `y` are converted to arrays only if they are
+ tuples or a lists, otherwise they are treated as a scalars and they
+ must have the same shape after conversion. In either case, either `x`
+ and `y` or their elements must support multiplication and addition both
+ with themselves and with the elements of `c`.
+
+ If `c` is a 1-D array a one is implicitly appended to its shape to make
+ it 2-D. The shape of the result will be c.shape[2:] + x.shape.
+
+ Parameters
+ ----------
+ x, y : array_like, compatible objects
+ The two dimensional series is evaluated at the points `(x, y)`,
+ where `x` and `y` must have the same shape. If `x` or `y` is a list
+ or tuple, it is first converted to an ndarray, otherwise it is left
+ unchanged and if it isn't an ndarray it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficient of the term
+ of multi-degree i,j is contained in ``c[i,j]``. If `c` has
+ dimension greater than two the remaining indices enumerate multiple
+ sets of coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional polynomial at points formed with
+ pairs of corresponding values from `x` and `y`.
+
+ See Also
+ --------
+ lagval, laggrid2d, lagval3d, laggrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._valnd(lagval, c, x, y)
+
+
+def laggrid2d(x, y, c):
+ """
+ Evaluate a 2-D Laguerre series on the Cartesian product of x and y.
+
+ This function returns the values:
+
+ .. math:: p(a,b) = \\sum_{i,j} c_{i,j} * L_i(a) * L_j(b)
+
+ where the points `(a, b)` consist of all pairs formed by taking
+ `a` from `x` and `b` from `y`. The resulting points form a grid with
+ `x` in the first dimension and `y` in the second.
+
+ The parameters `x` and `y` are converted to arrays only if they are
+ tuples or a lists, otherwise they are treated as a scalars. In either
+ case, either `x` and `y` or their elements must support multiplication
+ and addition both with themselves and with the elements of `c`.
+
+ If `c` has fewer than two dimensions, ones are implicitly appended to
+ its shape to make it 2-D. The shape of the result will be c.shape[2:] +
+ x.shape + y.shape.
+
+ Parameters
+ ----------
+ x, y : array_like, compatible objects
+ The two dimensional series is evaluated at the points in the
+ Cartesian product of `x` and `y`. If `x` or `y` is a list or
+ tuple, it is first converted to an ndarray, otherwise it is left
+ unchanged and, if it isn't an ndarray, it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficient of the term of
+ multi-degree i,j is contained in `c[i,j]`. If `c` has dimension
+ greater than two the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional Chebyshev series at points in the
+ Cartesian product of `x` and `y`.
+
+ See Also
+ --------
+ lagval, lagval2d, lagval3d, laggrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._gridnd(lagval, c, x, y)
+
+
+def lagval3d(x, y, z, c):
+ """
+ Evaluate a 3-D Laguerre series at points (x, y, z).
+
+ This function returns the values:
+
+ .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * L_i(x) * L_j(y) * L_k(z)
+
+ The parameters `x`, `y`, and `z` are converted to arrays only if
+ they are tuples or a lists, otherwise they are treated as a scalars and
+ they must have the same shape after conversion. In either case, either
+ `x`, `y`, and `z` or their elements must support multiplication and
+ addition both with themselves and with the elements of `c`.
+
+ If `c` has fewer than 3 dimensions, ones are implicitly appended to its
+ shape to make it 3-D. The shape of the result will be c.shape[3:] +
+ x.shape.
+
+ Parameters
+ ----------
+ x, y, z : array_like, compatible object
+ The three dimensional series is evaluated at the points
+ `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
+ any of `x`, `y`, or `z` is a list or tuple, it is first converted
+ to an ndarray, otherwise it is left unchanged and if it isn't an
+ ndarray it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficient of the term of
+ multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
+ greater than 3 the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the multidimensional polynomial on points formed with
+ triples of corresponding values from `x`, `y`, and `z`.
+
+ See Also
+ --------
+ lagval, lagval2d, laggrid2d, laggrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._valnd(lagval, c, x, y, z)
+
+
+def laggrid3d(x, y, z, c):
+ """
+ Evaluate a 3-D Laguerre series on the Cartesian product of x, y, and z.
+
+ This function returns the values:
+
+ .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * L_i(a) * L_j(b) * L_k(c)
+
+ where the points `(a, b, c)` consist of all triples formed by taking
+ `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
+ a grid with `x` in the first dimension, `y` in the second, and `z` in
+ the third.
+
+ The parameters `x`, `y`, and `z` are converted to arrays only if they
+ are tuples or a lists, otherwise they are treated as a scalars. In
+ either case, either `x`, `y`, and `z` or their elements must support
+ multiplication and addition both with themselves and with the elements
+ of `c`.
+
+ If `c` has fewer than three dimensions, ones are implicitly appended to
+ its shape to make it 3-D. The shape of the result will be c.shape[3:] +
+ x.shape + y.shape + z.shape.
+
+ Parameters
+ ----------
+ x, y, z : array_like, compatible objects
+ The three dimensional series is evaluated at the points in the
+ Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
+ list or tuple, it is first converted to an ndarray, otherwise it is
+ left unchanged and, if it isn't an ndarray, it is treated as a
+ scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficients for terms of
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
+ greater than two the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional polynomial at points in the Cartesian
+ product of `x` and `y`.
+
+ See Also
+ --------
+ lagval, lagval2d, laggrid2d, lagval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._gridnd(lagval, c, x, y, z)
+
+
+def lagvander(x, deg):
+ """Pseudo-Vandermonde matrix of given degree.
+
+ Returns the pseudo-Vandermonde matrix of degree `deg` and sample points
+ `x`. The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., i] = L_i(x)
+
+ where `0 <= i <= deg`. The leading indices of `V` index the elements of
+ `x` and the last index is the degree of the Laguerre polynomial.
+
+ If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
+ array ``V = lagvander(x, n)``, then ``np.dot(V, c)`` and
+ ``lagval(x, c)`` are the same up to roundoff. This equivalence is
+ useful both for least squares fitting and for the evaluation of a large
+ number of Laguerre series of the same degree and sample points.
+
+ Parameters
+ ----------
+ x : array_like
+ Array of points. The dtype is converted to float64 or complex128
+ depending on whether any of the elements are complex. If `x` is
+ scalar it is converted to a 1-D array.
+ deg : int
+ Degree of the resulting matrix.
+
+ Returns
+ -------
+ vander : ndarray
+ The pseudo-Vandermonde matrix. The shape of the returned matrix is
+ ``x.shape + (deg + 1,)``, where The last index is the degree of the
+ corresponding Laguerre polynomial. The dtype will be the same as
+ the converted `x`.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import lagvander
+ >>> x = np.array([0, 1, 2])
+ >>> lagvander(x, 3)
+ array([[ 1. , 1. , 1. , 1. ],
+ [ 1. , 0. , -0.5 , -0.66666667],
+ [ 1. , -1. , -1. , -0.33333333]])
+
+ """
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg < 0:
+ raise ValueError("deg must be non-negative")
+
+ x = np.array(x, copy=False, ndmin=1) + 0.0
+ dims = (ideg + 1,) + x.shape
+ dtyp = x.dtype
+ v = np.empty(dims, dtype=dtyp)
+ v[0] = x*0 + 1
+ if ideg > 0:
+ v[1] = 1 - x
+ for i in range(2, ideg + 1):
+ v[i] = (v[i-1]*(2*i - 1 - x) - v[i-2]*(i - 1))/i
+ return np.moveaxis(v, 0, -1)
+
+
+def lagvander2d(x, y, deg):
+ """Pseudo-Vandermonde matrix of given degrees.
+
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
+ points `(x, y)`. The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., (deg[1] + 1)*i + j] = L_i(x) * L_j(y),
+
+ where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
+ `V` index the points `(x, y)` and the last index encodes the degrees of
+ the Laguerre polynomials.
+
+ If ``V = lagvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
+ correspond to the elements of a 2-D coefficient array `c` of shape
+ (xdeg + 1, ydeg + 1) in the order
+
+ .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
+
+ and ``np.dot(V, c.flat)`` and ``lagval2d(x, y, c)`` will be the same
+ up to roundoff. This equivalence is useful both for least squares
+ fitting and for the evaluation of a large number of 2-D Laguerre
+ series of the same degrees and sample points.
+
+ Parameters
+ ----------
+ x, y : array_like
+ Arrays of point coordinates, all of the same shape. The dtypes
+ will be converted to either float64 or complex128 depending on
+ whether any of the elements are complex. Scalars are converted to
+ 1-D arrays.
+ deg : list of ints
+ List of maximum degrees of the form [x_deg, y_deg].
+
+ Returns
+ -------
+ vander2d : ndarray
+ The shape of the returned matrix is ``x.shape + (order,)``, where
+ :math:`order = (deg[0]+1)*(deg[1]+1)`. The dtype will be the same
+ as the converted `x` and `y`.
+
+ See Also
+ --------
+ lagvander, lagvander3d, lagval2d, lagval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._vander_nd_flat((lagvander, lagvander), (x, y), deg)
+
+
+def lagvander3d(x, y, z, deg):
+ """Pseudo-Vandermonde matrix of given degrees.
+
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
+ points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
+ then The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = L_i(x)*L_j(y)*L_k(z),
+
+ where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
+ indices of `V` index the points `(x, y, z)` and the last index encodes
+ the degrees of the Laguerre polynomials.
+
+ If ``V = lagvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
+ of `V` correspond to the elements of a 3-D coefficient array `c` of
+ shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
+
+ .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
+
+ and ``np.dot(V, c.flat)`` and ``lagval3d(x, y, z, c)`` will be the
+ same up to roundoff. This equivalence is useful both for least squares
+ fitting and for the evaluation of a large number of 3-D Laguerre
+ series of the same degrees and sample points.
+
+ Parameters
+ ----------
+ x, y, z : array_like
+ Arrays of point coordinates, all of the same shape. The dtypes will
+ be converted to either float64 or complex128 depending on whether
+ any of the elements are complex. Scalars are converted to 1-D
+ arrays.
+ deg : list of ints
+ List of maximum degrees of the form [x_deg, y_deg, z_deg].
+
+ Returns
+ -------
+ vander3d : ndarray
+ The shape of the returned matrix is ``x.shape + (order,)``, where
+ :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`. The dtype will
+ be the same as the converted `x`, `y`, and `z`.
+
+ See Also
+ --------
+ lagvander, lagvander3d, lagval2d, lagval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._vander_nd_flat((lagvander, lagvander, lagvander), (x, y, z), deg)
+
+
+def lagfit(x, y, deg, rcond=None, full=False, w=None):
+ """
+ Least squares fit of Laguerre series to data.
+
+ Return the coefficients of a Laguerre series of degree `deg` that is the
+ least squares fit to the data values `y` given at points `x`. If `y` is
+ 1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
+ fits are done, one for each column of `y`, and the resulting
+ coefficients are stored in the corresponding columns of a 2-D return.
+ The fitted polynomial(s) are in the form
+
+ .. math:: p(x) = c_0 + c_1 * L_1(x) + ... + c_n * L_n(x),
+
+ where ``n`` is `deg`.
+
+ Parameters
+ ----------
+ x : array_like, shape (M,)
+ x-coordinates of the M sample points ``(x[i], y[i])``.
+ y : array_like, shape (M,) or (M, K)
+ y-coordinates of the sample points. Several data sets of sample
+ points sharing the same x-coordinates can be fitted at once by
+ passing in a 2D-array that contains one dataset per column.
+ deg : int or 1-D array_like
+ Degree(s) of the fitting polynomials. If `deg` is a single integer
+ all terms up to and including the `deg`'th term are included in the
+ fit. For NumPy versions >= 1.11.0 a list of integers specifying the
+ degrees of the terms to include may be used instead.
+ rcond : float, optional
+ Relative condition number of the fit. Singular values smaller than
+ this relative to the largest singular value will be ignored. The
+ default value is len(x)*eps, where eps is the relative precision of
+ the float type, about 2e-16 in most cases.
+ full : bool, optional
+ Switch determining nature of return value. When it is False (the
+ default) just the coefficients are returned, when True diagnostic
+ information from the singular value decomposition is also returned.
+ w : array_like, shape (`M`,), optional
+ Weights. If not None, the weight ``w[i]`` applies to the unsquared
+ residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
+ chosen so that the errors of the products ``w[i]*y[i]`` all have the
+ same variance. When using inverse-variance weighting, use
+ ``w[i] = 1/sigma(y[i])``. The default value is None.
+
+ Returns
+ -------
+ coef : ndarray, shape (M,) or (M, K)
+ Laguerre coefficients ordered from low to high. If `y` was 2-D,
+ the coefficients for the data in column *k* of `y` are in column
+ *k*.
+
+ [residuals, rank, singular_values, rcond] : list
+ These values are only returned if ``full == True``
+
+ - residuals -- sum of squared residuals of the least squares fit
+ - rank -- the numerical rank of the scaled Vandermonde matrix
+ - singular_values -- singular values of the scaled Vandermonde matrix
+ - rcond -- value of `rcond`.
+
+ For more details, see `numpy.linalg.lstsq`.
+
+ Warns
+ -----
+ RankWarning
+ The rank of the coefficient matrix in the least-squares fit is
+ deficient. The warning is only raised if ``full == False``. The
+ warnings can be turned off by
+
+ >>> import warnings
+ >>> warnings.simplefilter('ignore', np.RankWarning)
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyfit
+ numpy.polynomial.legendre.legfit
+ numpy.polynomial.chebyshev.chebfit
+ numpy.polynomial.hermite.hermfit
+ numpy.polynomial.hermite_e.hermefit
+ lagval : Evaluates a Laguerre series.
+ lagvander : pseudo Vandermonde matrix of Laguerre series.
+ lagweight : Laguerre weight function.
+ numpy.linalg.lstsq : Computes a least-squares fit from the matrix.
+ scipy.interpolate.UnivariateSpline : Computes spline fits.
+
+ Notes
+ -----
+ The solution is the coefficients of the Laguerre series ``p`` that
+ minimizes the sum of the weighted squared errors
+
+ .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
+
+ where the :math:`w_j` are the weights. This problem is solved by
+ setting up as the (typically) overdetermined matrix equation
+
+ .. math:: V(x) * c = w * y,
+
+ where ``V`` is the weighted pseudo Vandermonde matrix of `x`, ``c`` are the
+ coefficients to be solved for, `w` are the weights, and `y` are the
+ observed values. This equation is then solved using the singular value
+ decomposition of ``V``.
+
+ If some of the singular values of `V` are so small that they are
+ neglected, then a `RankWarning` will be issued. This means that the
+ coefficient values may be poorly determined. Using a lower order fit
+ will usually get rid of the warning. The `rcond` parameter can also be
+ set to a value smaller than its default, but the resulting fit may be
+ spurious and have large contributions from roundoff error.
+
+ Fits using Laguerre series are probably most useful when the data can
+ be approximated by ``sqrt(w(x)) * p(x)``, where ``w(x)`` is the Laguerre
+ weight. In that case the weight ``sqrt(w(x[i]))`` should be used
+ together with data values ``y[i]/sqrt(w(x[i]))``. The weight function is
+ available as `lagweight`.
+
+ References
+ ----------
+ .. [1] Wikipedia, "Curve fitting",
+ https://en.wikipedia.org/wiki/Curve_fitting
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import lagfit, lagval
+ >>> x = np.linspace(0, 10)
+ >>> err = np.random.randn(len(x))/10
+ >>> y = lagval(x, [1, 2, 3]) + err
+ >>> lagfit(x, y, 2)
+ array([ 0.96971004, 2.00193749, 3.00288744]) # may vary
+
+ """
+ return pu._fit(lagvander, x, y, deg, rcond, full, w)
+
+
+def lagcompanion(c):
+ """
+ Return the companion matrix of c.
+
+ The usual companion matrix of the Laguerre polynomials is already
+ symmetric when `c` is a basis Laguerre polynomial, so no scaling is
+ applied.
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of Laguerre series coefficients ordered from low to high
+ degree.
+
+ Returns
+ -------
+ mat : ndarray
+ Companion matrix of dimensions (deg, deg).
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ if len(c) < 2:
+ raise ValueError('Series must have maximum degree of at least 1.')
+ if len(c) == 2:
+ return np.array([[1 + c[0]/c[1]]])
+
+ n = len(c) - 1
+ mat = np.zeros((n, n), dtype=c.dtype)
+ top = mat.reshape(-1)[1::n+1]
+ mid = mat.reshape(-1)[0::n+1]
+ bot = mat.reshape(-1)[n::n+1]
+ top[...] = -np.arange(1, n)
+ mid[...] = 2.*np.arange(n) + 1.
+ bot[...] = top
+ mat[:, -1] += (c[:-1]/c[-1])*n
+ return mat
+
+
+def lagroots(c):
+ """
+ Compute the roots of a Laguerre series.
+
+ Return the roots (a.k.a. "zeros") of the polynomial
+
+ .. math:: p(x) = \\sum_i c[i] * L_i(x).
+
+ Parameters
+ ----------
+ c : 1-D array_like
+ 1-D array of coefficients.
+
+ Returns
+ -------
+ out : ndarray
+ Array of the roots of the series. If all the roots are real,
+ then `out` is also real, otherwise it is complex.
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyroots
+ numpy.polynomial.legendre.legroots
+ numpy.polynomial.chebyshev.chebroots
+ numpy.polynomial.hermite.hermroots
+ numpy.polynomial.hermite_e.hermeroots
+
+ Notes
+ -----
+ The root estimates are obtained as the eigenvalues of the companion
+ matrix, Roots far from the origin of the complex plane may have large
+ errors due to the numerical instability of the series for such
+ values. Roots with multiplicity greater than 1 will also show larger
+ errors as the value of the series near such points is relatively
+ insensitive to errors in the roots. Isolated roots near the origin can
+ be improved by a few iterations of Newton's method.
+
+ The Laguerre series basis polynomials aren't powers of `x` so the
+ results of this function may seem unintuitive.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.laguerre import lagroots, lagfromroots
+ >>> coef = lagfromroots([0, 1, 2])
+ >>> coef
+ array([ 2., -8., 12., -6.])
+ >>> lagroots(coef)
+ array([-4.4408921e-16, 1.0000000e+00, 2.0000000e+00])
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ if len(c) <= 1:
+ return np.array([], dtype=c.dtype)
+ if len(c) == 2:
+ return np.array([1 + c[0]/c[1]])
+
+ # rotated companion matrix reduces error
+ m = lagcompanion(c)[::-1,::-1]
+ r = la.eigvals(m)
+ r.sort()
+ return r
+
+
+def laggauss(deg):
+ """
+ Gauss-Laguerre quadrature.
+
+ Computes the sample points and weights for Gauss-Laguerre quadrature.
+ These sample points and weights will correctly integrate polynomials of
+ degree :math:`2*deg - 1` or less over the interval :math:`[0, \\inf]`
+ with the weight function :math:`f(x) = \\exp(-x)`.
+
+ Parameters
+ ----------
+ deg : int
+ Number of sample points and weights. It must be >= 1.
+
+ Returns
+ -------
+ x : ndarray
+ 1-D ndarray containing the sample points.
+ y : ndarray
+ 1-D ndarray containing the weights.
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ The results have only been tested up to degree 100 higher degrees may
+ be problematic. The weights are determined by using the fact that
+
+ .. math:: w_k = c / (L'_n(x_k) * L_{n-1}(x_k))
+
+ where :math:`c` is a constant independent of :math:`k` and :math:`x_k`
+ is the k'th root of :math:`L_n`, and then scaling the results to get
+ the right value when integrating 1.
+
+ """
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg <= 0:
+ raise ValueError("deg must be a positive integer")
+
+ # first approximation of roots. We use the fact that the companion
+ # matrix is symmetric in this case in order to obtain better zeros.
+ c = np.array([0]*deg + [1])
+ m = lagcompanion(c)
+ x = la.eigvalsh(m)
+
+ # improve roots by one application of Newton
+ dy = lagval(x, c)
+ df = lagval(x, lagder(c))
+ x -= dy/df
+
+ # compute the weights. We scale the factor to avoid possible numerical
+ # overflow.
+ fm = lagval(x, c[1:])
+ fm /= np.abs(fm).max()
+ df /= np.abs(df).max()
+ w = 1/(fm * df)
+
+ # scale w to get the right value, 1 in this case
+ w /= w.sum()
+
+ return x, w
+
+
+def lagweight(x):
+ """Weight function of the Laguerre polynomials.
+
+ The weight function is :math:`exp(-x)` and the interval of integration
+ is :math:`[0, \\inf]`. The Laguerre polynomials are orthogonal, but not
+ normalized, with respect to this weight function.
+
+ Parameters
+ ----------
+ x : array_like
+ Values at which the weight function will be computed.
+
+ Returns
+ -------
+ w : ndarray
+ The weight function at `x`.
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ w = np.exp(-x)
+ return w
+
+#
+# Laguerre series class
+#
+
+class Laguerre(ABCPolyBase):
+ """A Laguerre series class.
+
+ The Laguerre class provides the standard Python numerical methods
+ '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
+ attributes and methods listed in the `ABCPolyBase` documentation.
+
+ Parameters
+ ----------
+ coef : array_like
+ Laguerre coefficients in order of increasing degree, i.e,
+ ``(1, 2, 3)`` gives ``1*L_0(x) + 2*L_1(X) + 3*L_2(x)``.
+ domain : (2,) array_like, optional
+ Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
+ to the interval ``[window[0], window[1]]`` by shifting and scaling.
+ The default value is [0, 1].
+ window : (2,) array_like, optional
+ Window, see `domain` for its use. The default value is [0, 1].
+
+ .. versionadded:: 1.6.0
+ symbol : str, optional
+ Symbol used to represent the independent variable in string
+ representations of the polynomial expression, e.g. for printing.
+ The symbol must be a valid Python identifier. Default value is 'x'.
+
+ .. versionadded:: 1.24
+
+ """
+ # Virtual Functions
+ _add = staticmethod(lagadd)
+ _sub = staticmethod(lagsub)
+ _mul = staticmethod(lagmul)
+ _div = staticmethod(lagdiv)
+ _pow = staticmethod(lagpow)
+ _val = staticmethod(lagval)
+ _int = staticmethod(lagint)
+ _der = staticmethod(lagder)
+ _fit = staticmethod(lagfit)
+ _line = staticmethod(lagline)
+ _roots = staticmethod(lagroots)
+ _fromroots = staticmethod(lagfromroots)
+
+ # Virtual properties
+ domain = np.array(lagdomain)
+ window = np.array(lagdomain)
+ basis_name = 'L'
diff --git a/lib/python3.12/site-packages/numpy/polynomial/laguerre.pyi b/lib/python3.12/site-packages/numpy/polynomial/laguerre.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..e546bc20a54c0e522cd7ea851ad8e8a42d895980
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/laguerre.pyi
@@ -0,0 +1,46 @@
+from typing import Any
+
+from numpy import ndarray, dtype, int_
+from numpy.polynomial._polybase import ABCPolyBase
+from numpy.polynomial.polyutils import trimcoef
+
+__all__: list[str]
+
+lagtrim = trimcoef
+
+def poly2lag(pol): ...
+def lag2poly(c): ...
+
+lagdomain: ndarray[Any, dtype[int_]]
+lagzero: ndarray[Any, dtype[int_]]
+lagone: ndarray[Any, dtype[int_]]
+lagx: ndarray[Any, dtype[int_]]
+
+def lagline(off, scl): ...
+def lagfromroots(roots): ...
+def lagadd(c1, c2): ...
+def lagsub(c1, c2): ...
+def lagmulx(c): ...
+def lagmul(c1, c2): ...
+def lagdiv(c1, c2): ...
+def lagpow(c, pow, maxpower=...): ...
+def lagder(c, m=..., scl=..., axis=...): ...
+def lagint(c, m=..., k = ..., lbnd=..., scl=..., axis=...): ...
+def lagval(x, c, tensor=...): ...
+def lagval2d(x, y, c): ...
+def laggrid2d(x, y, c): ...
+def lagval3d(x, y, z, c): ...
+def laggrid3d(x, y, z, c): ...
+def lagvander(x, deg): ...
+def lagvander2d(x, y, deg): ...
+def lagvander3d(x, y, z, deg): ...
+def lagfit(x, y, deg, rcond=..., full=..., w=...): ...
+def lagcompanion(c): ...
+def lagroots(c): ...
+def laggauss(deg): ...
+def lagweight(x): ...
+
+class Laguerre(ABCPolyBase):
+ domain: Any
+ window: Any
+ basis_name: Any
diff --git a/lib/python3.12/site-packages/numpy/polynomial/legendre.py b/lib/python3.12/site-packages/numpy/polynomial/legendre.py
new file mode 100644
index 0000000000000000000000000000000000000000..8e9c19d94ff60c7d314231e8bfbc1c200f12653e
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/legendre.py
@@ -0,0 +1,1664 @@
+"""
+==================================================
+Legendre Series (:mod:`numpy.polynomial.legendre`)
+==================================================
+
+This module provides a number of objects (mostly functions) useful for
+dealing with Legendre series, including a `Legendre` class that
+encapsulates the usual arithmetic operations. (General information
+on how this module represents and works with such polynomials is in the
+docstring for its "parent" sub-package, `numpy.polynomial`).
+
+Classes
+-------
+.. autosummary::
+ :toctree: generated/
+
+ Legendre
+
+Constants
+---------
+
+.. autosummary::
+ :toctree: generated/
+
+ legdomain
+ legzero
+ legone
+ legx
+
+Arithmetic
+----------
+
+.. autosummary::
+ :toctree: generated/
+
+ legadd
+ legsub
+ legmulx
+ legmul
+ legdiv
+ legpow
+ legval
+ legval2d
+ legval3d
+ leggrid2d
+ leggrid3d
+
+Calculus
+--------
+
+.. autosummary::
+ :toctree: generated/
+
+ legder
+ legint
+
+Misc Functions
+--------------
+
+.. autosummary::
+ :toctree: generated/
+
+ legfromroots
+ legroots
+ legvander
+ legvander2d
+ legvander3d
+ leggauss
+ legweight
+ legcompanion
+ legfit
+ legtrim
+ legline
+ leg2poly
+ poly2leg
+
+See also
+--------
+numpy.polynomial
+
+"""
+import numpy as np
+import numpy.linalg as la
+from numpy.core.multiarray import normalize_axis_index
+
+from . import polyutils as pu
+from ._polybase import ABCPolyBase
+
+__all__ = [
+ 'legzero', 'legone', 'legx', 'legdomain', 'legline', 'legadd',
+ 'legsub', 'legmulx', 'legmul', 'legdiv', 'legpow', 'legval', 'legder',
+ 'legint', 'leg2poly', 'poly2leg', 'legfromroots', 'legvander',
+ 'legfit', 'legtrim', 'legroots', 'Legendre', 'legval2d', 'legval3d',
+ 'leggrid2d', 'leggrid3d', 'legvander2d', 'legvander3d', 'legcompanion',
+ 'leggauss', 'legweight']
+
+legtrim = pu.trimcoef
+
+
+def poly2leg(pol):
+ """
+ Convert a polynomial to a Legendre series.
+
+ Convert an array representing the coefficients of a polynomial (relative
+ to the "standard" basis) ordered from lowest degree to highest, to an
+ array of the coefficients of the equivalent Legendre series, ordered
+ from lowest to highest degree.
+
+ Parameters
+ ----------
+ pol : array_like
+ 1-D array containing the polynomial coefficients
+
+ Returns
+ -------
+ c : ndarray
+ 1-D array containing the coefficients of the equivalent Legendre
+ series.
+
+ See Also
+ --------
+ leg2poly
+
+ Notes
+ -----
+ The easy way to do conversions between polynomial basis sets
+ is to use the convert method of a class instance.
+
+ Examples
+ --------
+ >>> from numpy import polynomial as P
+ >>> p = P.Polynomial(np.arange(4))
+ >>> p
+ Polynomial([0., 1., 2., 3.], domain=[-1, 1], window=[-1, 1])
+ >>> c = P.Legendre(P.legendre.poly2leg(p.coef))
+ >>> c
+ Legendre([ 1. , 3.25, 1. , 0.75], domain=[-1, 1], window=[-1, 1]) # may vary
+
+ """
+ [pol] = pu.as_series([pol])
+ deg = len(pol) - 1
+ res = 0
+ for i in range(deg, -1, -1):
+ res = legadd(legmulx(res), pol[i])
+ return res
+
+
+def leg2poly(c):
+ """
+ Convert a Legendre series to a polynomial.
+
+ Convert an array representing the coefficients of a Legendre series,
+ ordered from lowest degree to highest, to an array of the coefficients
+ of the equivalent polynomial (relative to the "standard" basis) ordered
+ from lowest to highest degree.
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array containing the Legendre series coefficients, ordered
+ from lowest order term to highest.
+
+ Returns
+ -------
+ pol : ndarray
+ 1-D array containing the coefficients of the equivalent polynomial
+ (relative to the "standard" basis) ordered from lowest order term
+ to highest.
+
+ See Also
+ --------
+ poly2leg
+
+ Notes
+ -----
+ The easy way to do conversions between polynomial basis sets
+ is to use the convert method of a class instance.
+
+ Examples
+ --------
+ >>> from numpy import polynomial as P
+ >>> c = P.Legendre(range(4))
+ >>> c
+ Legendre([0., 1., 2., 3.], domain=[-1, 1], window=[-1, 1])
+ >>> p = c.convert(kind=P.Polynomial)
+ >>> p
+ Polynomial([-1. , -3.5, 3. , 7.5], domain=[-1., 1.], window=[-1., 1.])
+ >>> P.legendre.leg2poly(range(4))
+ array([-1. , -3.5, 3. , 7.5])
+
+
+ """
+ from .polynomial import polyadd, polysub, polymulx
+
+ [c] = pu.as_series([c])
+ n = len(c)
+ if n < 3:
+ return c
+ else:
+ c0 = c[-2]
+ c1 = c[-1]
+ # i is the current degree of c1
+ for i in range(n - 1, 1, -1):
+ tmp = c0
+ c0 = polysub(c[i - 2], (c1*(i - 1))/i)
+ c1 = polyadd(tmp, (polymulx(c1)*(2*i - 1))/i)
+ return polyadd(c0, polymulx(c1))
+
+#
+# These are constant arrays are of integer type so as to be compatible
+# with the widest range of other types, such as Decimal.
+#
+
+# Legendre
+legdomain = np.array([-1, 1])
+
+# Legendre coefficients representing zero.
+legzero = np.array([0])
+
+# Legendre coefficients representing one.
+legone = np.array([1])
+
+# Legendre coefficients representing the identity x.
+legx = np.array([0, 1])
+
+
+def legline(off, scl):
+ """
+ Legendre series whose graph is a straight line.
+
+
+
+ Parameters
+ ----------
+ off, scl : scalars
+ The specified line is given by ``off + scl*x``.
+
+ Returns
+ -------
+ y : ndarray
+ This module's representation of the Legendre series for
+ ``off + scl*x``.
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyline
+ numpy.polynomial.chebyshev.chebline
+ numpy.polynomial.laguerre.lagline
+ numpy.polynomial.hermite.hermline
+ numpy.polynomial.hermite_e.hermeline
+
+ Examples
+ --------
+ >>> import numpy.polynomial.legendre as L
+ >>> L.legline(3,2)
+ array([3, 2])
+ >>> L.legval(-3, L.legline(3,2)) # should be -3
+ -3.0
+
+ """
+ if scl != 0:
+ return np.array([off, scl])
+ else:
+ return np.array([off])
+
+
+def legfromroots(roots):
+ """
+ Generate a Legendre series with given roots.
+
+ The function returns the coefficients of the polynomial
+
+ .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
+
+ in Legendre form, where the `r_n` are the roots specified in `roots`.
+ If a zero has multiplicity n, then it must appear in `roots` n times.
+ For instance, if 2 is a root of multiplicity three and 3 is a root of
+ multiplicity 2, then `roots` looks something like [2, 2, 2, 3, 3]. The
+ roots can appear in any order.
+
+ If the returned coefficients are `c`, then
+
+ .. math:: p(x) = c_0 + c_1 * L_1(x) + ... + c_n * L_n(x)
+
+ The coefficient of the last term is not generally 1 for monic
+ polynomials in Legendre form.
+
+ Parameters
+ ----------
+ roots : array_like
+ Sequence containing the roots.
+
+ Returns
+ -------
+ out : ndarray
+ 1-D array of coefficients. If all roots are real then `out` is a
+ real array, if some of the roots are complex, then `out` is complex
+ even if all the coefficients in the result are real (see Examples
+ below).
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyfromroots
+ numpy.polynomial.chebyshev.chebfromroots
+ numpy.polynomial.laguerre.lagfromroots
+ numpy.polynomial.hermite.hermfromroots
+ numpy.polynomial.hermite_e.hermefromroots
+
+ Examples
+ --------
+ >>> import numpy.polynomial.legendre as L
+ >>> L.legfromroots((-1,0,1)) # x^3 - x relative to the standard basis
+ array([ 0. , -0.4, 0. , 0.4])
+ >>> j = complex(0,1)
+ >>> L.legfromroots((-j,j)) # x^2 + 1 relative to the standard basis
+ array([ 1.33333333+0.j, 0.00000000+0.j, 0.66666667+0.j]) # may vary
+
+ """
+ return pu._fromroots(legline, legmul, roots)
+
+
+def legadd(c1, c2):
+ """
+ Add one Legendre series to another.
+
+ Returns the sum of two Legendre series `c1` + `c2`. The arguments
+ are sequences of coefficients ordered from lowest order term to
+ highest, i.e., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Legendre series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Array representing the Legendre series of their sum.
+
+ See Also
+ --------
+ legsub, legmulx, legmul, legdiv, legpow
+
+ Notes
+ -----
+ Unlike multiplication, division, etc., the sum of two Legendre series
+ is a Legendre series (without having to "reproject" the result onto
+ the basis set) so addition, just like that of "standard" polynomials,
+ is simply "component-wise."
+
+ Examples
+ --------
+ >>> from numpy.polynomial import legendre as L
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> L.legadd(c1,c2)
+ array([4., 4., 4.])
+
+ """
+ return pu._add(c1, c2)
+
+
+def legsub(c1, c2):
+ """
+ Subtract one Legendre series from another.
+
+ Returns the difference of two Legendre series `c1` - `c2`. The
+ sequences of coefficients are from lowest order term to highest, i.e.,
+ [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Legendre series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Of Legendre series coefficients representing their difference.
+
+ See Also
+ --------
+ legadd, legmulx, legmul, legdiv, legpow
+
+ Notes
+ -----
+ Unlike multiplication, division, etc., the difference of two Legendre
+ series is a Legendre series (without having to "reproject" the result
+ onto the basis set) so subtraction, just like that of "standard"
+ polynomials, is simply "component-wise."
+
+ Examples
+ --------
+ >>> from numpy.polynomial import legendre as L
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> L.legsub(c1,c2)
+ array([-2., 0., 2.])
+ >>> L.legsub(c2,c1) # -C.legsub(c1,c2)
+ array([ 2., 0., -2.])
+
+ """
+ return pu._sub(c1, c2)
+
+
+def legmulx(c):
+ """Multiply a Legendre series by x.
+
+ Multiply the Legendre series `c` by x, where x is the independent
+ variable.
+
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of Legendre series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Array representing the result of the multiplication.
+
+ See Also
+ --------
+ legadd, legmul, legdiv, legpow
+
+ Notes
+ -----
+ The multiplication uses the recursion relationship for Legendre
+ polynomials in the form
+
+ .. math::
+
+ xP_i(x) = ((i + 1)*P_{i + 1}(x) + i*P_{i - 1}(x))/(2i + 1)
+
+ Examples
+ --------
+ >>> from numpy.polynomial import legendre as L
+ >>> L.legmulx([1,2,3])
+ array([ 0.66666667, 2.2, 1.33333333, 1.8]) # may vary
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ # The zero series needs special treatment
+ if len(c) == 1 and c[0] == 0:
+ return c
+
+ prd = np.empty(len(c) + 1, dtype=c.dtype)
+ prd[0] = c[0]*0
+ prd[1] = c[0]
+ for i in range(1, len(c)):
+ j = i + 1
+ k = i - 1
+ s = i + j
+ prd[j] = (c[i]*j)/s
+ prd[k] += (c[i]*i)/s
+ return prd
+
+
+def legmul(c1, c2):
+ """
+ Multiply one Legendre series by another.
+
+ Returns the product of two Legendre series `c1` * `c2`. The arguments
+ are sequences of coefficients, from lowest order "term" to highest,
+ e.g., [1,2,3] represents the series ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Legendre series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Of Legendre series coefficients representing their product.
+
+ See Also
+ --------
+ legadd, legsub, legmulx, legdiv, legpow
+
+ Notes
+ -----
+ In general, the (polynomial) product of two C-series results in terms
+ that are not in the Legendre polynomial basis set. Thus, to express
+ the product as a Legendre series, it is necessary to "reproject" the
+ product onto said basis set, which may produce "unintuitive" (but
+ correct) results; see Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial import legendre as L
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2)
+ >>> L.legmul(c1,c2) # multiplication requires "reprojection"
+ array([ 4.33333333, 10.4 , 11.66666667, 3.6 ]) # may vary
+
+ """
+ # s1, s2 are trimmed copies
+ [c1, c2] = pu.as_series([c1, c2])
+
+ if len(c1) > len(c2):
+ c = c2
+ xs = c1
+ else:
+ c = c1
+ xs = c2
+
+ if len(c) == 1:
+ c0 = c[0]*xs
+ c1 = 0
+ elif len(c) == 2:
+ c0 = c[0]*xs
+ c1 = c[1]*xs
+ else:
+ nd = len(c)
+ c0 = c[-2]*xs
+ c1 = c[-1]*xs
+ for i in range(3, len(c) + 1):
+ tmp = c0
+ nd = nd - 1
+ c0 = legsub(c[-i]*xs, (c1*(nd - 1))/nd)
+ c1 = legadd(tmp, (legmulx(c1)*(2*nd - 1))/nd)
+ return legadd(c0, legmulx(c1))
+
+
+def legdiv(c1, c2):
+ """
+ Divide one Legendre series by another.
+
+ Returns the quotient-with-remainder of two Legendre series
+ `c1` / `c2`. The arguments are sequences of coefficients from lowest
+ order "term" to highest, e.g., [1,2,3] represents the series
+ ``P_0 + 2*P_1 + 3*P_2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of Legendre series coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ quo, rem : ndarrays
+ Of Legendre series coefficients representing the quotient and
+ remainder.
+
+ See Also
+ --------
+ legadd, legsub, legmulx, legmul, legpow
+
+ Notes
+ -----
+ In general, the (polynomial) division of one Legendre series by another
+ results in quotient and remainder terms that are not in the Legendre
+ polynomial basis set. Thus, to express these results as a Legendre
+ series, it is necessary to "reproject" the results onto the Legendre
+ basis set, which may produce "unintuitive" (but correct) results; see
+ Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial import legendre as L
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> L.legdiv(c1,c2) # quotient "intuitive," remainder not
+ (array([3.]), array([-8., -4.]))
+ >>> c2 = (0,1,2,3)
+ >>> L.legdiv(c2,c1) # neither "intuitive"
+ (array([-0.07407407, 1.66666667]), array([-1.03703704, -2.51851852])) # may vary
+
+ """
+ return pu._div(legmul, c1, c2)
+
+
+def legpow(c, pow, maxpower=16):
+ """Raise a Legendre series to a power.
+
+ Returns the Legendre series `c` raised to the power `pow`. The
+ argument `c` is a sequence of coefficients ordered from low to high.
+ i.e., [1,2,3] is the series ``P_0 + 2*P_1 + 3*P_2.``
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of Legendre series coefficients ordered from low to
+ high.
+ pow : integer
+ Power to which the series will be raised
+ maxpower : integer, optional
+ Maximum power allowed. This is mainly to limit growth of the series
+ to unmanageable size. Default is 16
+
+ Returns
+ -------
+ coef : ndarray
+ Legendre series of power.
+
+ See Also
+ --------
+ legadd, legsub, legmulx, legmul, legdiv
+
+ """
+ return pu._pow(legmul, c, pow, maxpower)
+
+
+def legder(c, m=1, scl=1, axis=0):
+ """
+ Differentiate a Legendre series.
+
+ Returns the Legendre series coefficients `c` differentiated `m` times
+ along `axis`. At each iteration the result is multiplied by `scl` (the
+ scaling factor is for use in a linear change of variable). The argument
+ `c` is an array of coefficients from low to high degree along each
+ axis, e.g., [1,2,3] represents the series ``1*L_0 + 2*L_1 + 3*L_2``
+ while [[1,2],[1,2]] represents ``1*L_0(x)*L_0(y) + 1*L_1(x)*L_0(y) +
+ 2*L_0(x)*L_1(y) + 2*L_1(x)*L_1(y)`` if axis=0 is ``x`` and axis=1 is
+ ``y``.
+
+ Parameters
+ ----------
+ c : array_like
+ Array of Legendre series coefficients. If c is multidimensional the
+ different axis correspond to different variables with the degree in
+ each axis given by the corresponding index.
+ m : int, optional
+ Number of derivatives taken, must be non-negative. (Default: 1)
+ scl : scalar, optional
+ Each differentiation is multiplied by `scl`. The end result is
+ multiplication by ``scl**m``. This is for use in a linear change of
+ variable. (Default: 1)
+ axis : int, optional
+ Axis over which the derivative is taken. (Default: 0).
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ der : ndarray
+ Legendre series of the derivative.
+
+ See Also
+ --------
+ legint
+
+ Notes
+ -----
+ In general, the result of differentiating a Legendre series does not
+ resemble the same operation on a power series. Thus the result of this
+ function may be "unintuitive," albeit correct; see Examples section
+ below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial import legendre as L
+ >>> c = (1,2,3,4)
+ >>> L.legder(c)
+ array([ 6., 9., 20.])
+ >>> L.legder(c, 3)
+ array([60.])
+ >>> L.legder(c, scl=-1)
+ array([ -6., -9., -20.])
+ >>> L.legder(c, 2,-1)
+ array([ 9., 60.])
+
+ """
+ c = np.array(c, ndmin=1, copy=True)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ c = c.astype(np.double)
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
+ if cnt < 0:
+ raise ValueError("The order of derivation must be non-negative")
+ iaxis = normalize_axis_index(iaxis, c.ndim)
+
+ if cnt == 0:
+ return c
+
+ c = np.moveaxis(c, iaxis, 0)
+ n = len(c)
+ if cnt >= n:
+ c = c[:1]*0
+ else:
+ for i in range(cnt):
+ n = n - 1
+ c *= scl
+ der = np.empty((n,) + c.shape[1:], dtype=c.dtype)
+ for j in range(n, 2, -1):
+ der[j - 1] = (2*j - 1)*c[j]
+ c[j - 2] += c[j]
+ if n > 1:
+ der[1] = 3*c[2]
+ der[0] = c[1]
+ c = der
+ c = np.moveaxis(c, 0, iaxis)
+ return c
+
+
+def legint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
+ """
+ Integrate a Legendre series.
+
+ Returns the Legendre series coefficients `c` integrated `m` times from
+ `lbnd` along `axis`. At each iteration the resulting series is
+ **multiplied** by `scl` and an integration constant, `k`, is added.
+ The scaling factor is for use in a linear change of variable. ("Buyer
+ beware": note that, depending on what one is doing, one may want `scl`
+ to be the reciprocal of what one might expect; for more information,
+ see the Notes section below.) The argument `c` is an array of
+ coefficients from low to high degree along each axis, e.g., [1,2,3]
+ represents the series ``L_0 + 2*L_1 + 3*L_2`` while [[1,2],[1,2]]
+ represents ``1*L_0(x)*L_0(y) + 1*L_1(x)*L_0(y) + 2*L_0(x)*L_1(y) +
+ 2*L_1(x)*L_1(y)`` if axis=0 is ``x`` and axis=1 is ``y``.
+
+ Parameters
+ ----------
+ c : array_like
+ Array of Legendre series coefficients. If c is multidimensional the
+ different axis correspond to different variables with the degree in
+ each axis given by the corresponding index.
+ m : int, optional
+ Order of integration, must be positive. (Default: 1)
+ k : {[], list, scalar}, optional
+ Integration constant(s). The value of the first integral at
+ ``lbnd`` is the first value in the list, the value of the second
+ integral at ``lbnd`` is the second value, etc. If ``k == []`` (the
+ default), all constants are set to zero. If ``m == 1``, a single
+ scalar can be given instead of a list.
+ lbnd : scalar, optional
+ The lower bound of the integral. (Default: 0)
+ scl : scalar, optional
+ Following each integration the result is *multiplied* by `scl`
+ before the integration constant is added. (Default: 1)
+ axis : int, optional
+ Axis over which the integral is taken. (Default: 0).
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ S : ndarray
+ Legendre series coefficient array of the integral.
+
+ Raises
+ ------
+ ValueError
+ If ``m < 0``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
+ ``np.ndim(scl) != 0``.
+
+ See Also
+ --------
+ legder
+
+ Notes
+ -----
+ Note that the result of each integration is *multiplied* by `scl`.
+ Why is this important to note? Say one is making a linear change of
+ variable :math:`u = ax + b` in an integral relative to `x`. Then
+ :math:`dx = du/a`, so one will need to set `scl` equal to
+ :math:`1/a` - perhaps not what one would have first thought.
+
+ Also note that, in general, the result of integrating a C-series needs
+ to be "reprojected" onto the C-series basis set. Thus, typically,
+ the result of this function is "unintuitive," albeit correct; see
+ Examples section below.
+
+ Examples
+ --------
+ >>> from numpy.polynomial import legendre as L
+ >>> c = (1,2,3)
+ >>> L.legint(c)
+ array([ 0.33333333, 0.4 , 0.66666667, 0.6 ]) # may vary
+ >>> L.legint(c, 3)
+ array([ 1.66666667e-02, -1.78571429e-02, 4.76190476e-02, # may vary
+ -1.73472348e-18, 1.90476190e-02, 9.52380952e-03])
+ >>> L.legint(c, k=3)
+ array([ 3.33333333, 0.4 , 0.66666667, 0.6 ]) # may vary
+ >>> L.legint(c, lbnd=-2)
+ array([ 7.33333333, 0.4 , 0.66666667, 0.6 ]) # may vary
+ >>> L.legint(c, scl=2)
+ array([ 0.66666667, 0.8 , 1.33333333, 1.2 ]) # may vary
+
+ """
+ c = np.array(c, ndmin=1, copy=True)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ c = c.astype(np.double)
+ if not np.iterable(k):
+ k = [k]
+ cnt = pu._deprecate_as_int(m, "the order of integration")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
+ if cnt < 0:
+ raise ValueError("The order of integration must be non-negative")
+ if len(k) > cnt:
+ raise ValueError("Too many integration constants")
+ if np.ndim(lbnd) != 0:
+ raise ValueError("lbnd must be a scalar.")
+ if np.ndim(scl) != 0:
+ raise ValueError("scl must be a scalar.")
+ iaxis = normalize_axis_index(iaxis, c.ndim)
+
+ if cnt == 0:
+ return c
+
+ c = np.moveaxis(c, iaxis, 0)
+ k = list(k) + [0]*(cnt - len(k))
+ for i in range(cnt):
+ n = len(c)
+ c *= scl
+ if n == 1 and np.all(c[0] == 0):
+ c[0] += k[i]
+ else:
+ tmp = np.empty((n + 1,) + c.shape[1:], dtype=c.dtype)
+ tmp[0] = c[0]*0
+ tmp[1] = c[0]
+ if n > 1:
+ tmp[2] = c[1]/3
+ for j in range(2, n):
+ t = c[j]/(2*j + 1)
+ tmp[j + 1] = t
+ tmp[j - 1] -= t
+ tmp[0] += k[i] - legval(lbnd, tmp)
+ c = tmp
+ c = np.moveaxis(c, 0, iaxis)
+ return c
+
+
+def legval(x, c, tensor=True):
+ """
+ Evaluate a Legendre series at points x.
+
+ If `c` is of length `n + 1`, this function returns the value:
+
+ .. math:: p(x) = c_0 * L_0(x) + c_1 * L_1(x) + ... + c_n * L_n(x)
+
+ The parameter `x` is converted to an array only if it is a tuple or a
+ list, otherwise it is treated as a scalar. In either case, either `x`
+ or its elements must support multiplication and addition both with
+ themselves and with the elements of `c`.
+
+ If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
+ `c` is multidimensional, then the shape of the result depends on the
+ value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
+ x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
+ scalars have shape (,).
+
+ Trailing zeros in the coefficients will be used in the evaluation, so
+ they should be avoided if efficiency is a concern.
+
+ Parameters
+ ----------
+ x : array_like, compatible object
+ If `x` is a list or tuple, it is converted to an ndarray, otherwise
+ it is left unchanged and treated as a scalar. In either case, `x`
+ or its elements must support addition and multiplication with
+ themselves and with the elements of `c`.
+ c : array_like
+ Array of coefficients ordered so that the coefficients for terms of
+ degree n are contained in c[n]. If `c` is multidimensional the
+ remaining indices enumerate multiple polynomials. In the two
+ dimensional case the coefficients may be thought of as stored in
+ the columns of `c`.
+ tensor : boolean, optional
+ If True, the shape of the coefficient array is extended with ones
+ on the right, one for each dimension of `x`. Scalars have dimension 0
+ for this action. The result is that every column of coefficients in
+ `c` is evaluated for every element of `x`. If False, `x` is broadcast
+ over the columns of `c` for the evaluation. This keyword is useful
+ when `c` is multidimensional. The default value is True.
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ values : ndarray, algebra_like
+ The shape of the return value is described above.
+
+ See Also
+ --------
+ legval2d, leggrid2d, legval3d, leggrid3d
+
+ Notes
+ -----
+ The evaluation uses Clenshaw recursion, aka synthetic division.
+
+ """
+ c = np.array(c, ndmin=1, copy=False)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ c = c.astype(np.double)
+ if isinstance(x, (tuple, list)):
+ x = np.asarray(x)
+ if isinstance(x, np.ndarray) and tensor:
+ c = c.reshape(c.shape + (1,)*x.ndim)
+
+ if len(c) == 1:
+ c0 = c[0]
+ c1 = 0
+ elif len(c) == 2:
+ c0 = c[0]
+ c1 = c[1]
+ else:
+ nd = len(c)
+ c0 = c[-2]
+ c1 = c[-1]
+ for i in range(3, len(c) + 1):
+ tmp = c0
+ nd = nd - 1
+ c0 = c[-i] - (c1*(nd - 1))/nd
+ c1 = tmp + (c1*x*(2*nd - 1))/nd
+ return c0 + c1*x
+
+
+def legval2d(x, y, c):
+ """
+ Evaluate a 2-D Legendre series at points (x, y).
+
+ This function returns the values:
+
+ .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * L_i(x) * L_j(y)
+
+ The parameters `x` and `y` are converted to arrays only if they are
+ tuples or a lists, otherwise they are treated as a scalars and they
+ must have the same shape after conversion. In either case, either `x`
+ and `y` or their elements must support multiplication and addition both
+ with themselves and with the elements of `c`.
+
+ If `c` is a 1-D array a one is implicitly appended to its shape to make
+ it 2-D. The shape of the result will be c.shape[2:] + x.shape.
+
+ Parameters
+ ----------
+ x, y : array_like, compatible objects
+ The two dimensional series is evaluated at the points `(x, y)`,
+ where `x` and `y` must have the same shape. If `x` or `y` is a list
+ or tuple, it is first converted to an ndarray, otherwise it is left
+ unchanged and if it isn't an ndarray it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficient of the term
+ of multi-degree i,j is contained in ``c[i,j]``. If `c` has
+ dimension greater than two the remaining indices enumerate multiple
+ sets of coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional Legendre series at points formed
+ from pairs of corresponding values from `x` and `y`.
+
+ See Also
+ --------
+ legval, leggrid2d, legval3d, leggrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._valnd(legval, c, x, y)
+
+
+def leggrid2d(x, y, c):
+ """
+ Evaluate a 2-D Legendre series on the Cartesian product of x and y.
+
+ This function returns the values:
+
+ .. math:: p(a,b) = \\sum_{i,j} c_{i,j} * L_i(a) * L_j(b)
+
+ where the points `(a, b)` consist of all pairs formed by taking
+ `a` from `x` and `b` from `y`. The resulting points form a grid with
+ `x` in the first dimension and `y` in the second.
+
+ The parameters `x` and `y` are converted to arrays only if they are
+ tuples or a lists, otherwise they are treated as a scalars. In either
+ case, either `x` and `y` or their elements must support multiplication
+ and addition both with themselves and with the elements of `c`.
+
+ If `c` has fewer than two dimensions, ones are implicitly appended to
+ its shape to make it 2-D. The shape of the result will be c.shape[2:] +
+ x.shape + y.shape.
+
+ Parameters
+ ----------
+ x, y : array_like, compatible objects
+ The two dimensional series is evaluated at the points in the
+ Cartesian product of `x` and `y`. If `x` or `y` is a list or
+ tuple, it is first converted to an ndarray, otherwise it is left
+ unchanged and, if it isn't an ndarray, it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficient of the term of
+ multi-degree i,j is contained in `c[i,j]`. If `c` has dimension
+ greater than two the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional Chebyshev series at points in the
+ Cartesian product of `x` and `y`.
+
+ See Also
+ --------
+ legval, legval2d, legval3d, leggrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._gridnd(legval, c, x, y)
+
+
+def legval3d(x, y, z, c):
+ """
+ Evaluate a 3-D Legendre series at points (x, y, z).
+
+ This function returns the values:
+
+ .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * L_i(x) * L_j(y) * L_k(z)
+
+ The parameters `x`, `y`, and `z` are converted to arrays only if
+ they are tuples or a lists, otherwise they are treated as a scalars and
+ they must have the same shape after conversion. In either case, either
+ `x`, `y`, and `z` or their elements must support multiplication and
+ addition both with themselves and with the elements of `c`.
+
+ If `c` has fewer than 3 dimensions, ones are implicitly appended to its
+ shape to make it 3-D. The shape of the result will be c.shape[3:] +
+ x.shape.
+
+ Parameters
+ ----------
+ x, y, z : array_like, compatible object
+ The three dimensional series is evaluated at the points
+ `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
+ any of `x`, `y`, or `z` is a list or tuple, it is first converted
+ to an ndarray, otherwise it is left unchanged and if it isn't an
+ ndarray it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficient of the term of
+ multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
+ greater than 3 the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the multidimensional polynomial on points formed with
+ triples of corresponding values from `x`, `y`, and `z`.
+
+ See Also
+ --------
+ legval, legval2d, leggrid2d, leggrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._valnd(legval, c, x, y, z)
+
+
+def leggrid3d(x, y, z, c):
+ """
+ Evaluate a 3-D Legendre series on the Cartesian product of x, y, and z.
+
+ This function returns the values:
+
+ .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * L_i(a) * L_j(b) * L_k(c)
+
+ where the points `(a, b, c)` consist of all triples formed by taking
+ `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
+ a grid with `x` in the first dimension, `y` in the second, and `z` in
+ the third.
+
+ The parameters `x`, `y`, and `z` are converted to arrays only if they
+ are tuples or a lists, otherwise they are treated as a scalars. In
+ either case, either `x`, `y`, and `z` or their elements must support
+ multiplication and addition both with themselves and with the elements
+ of `c`.
+
+ If `c` has fewer than three dimensions, ones are implicitly appended to
+ its shape to make it 3-D. The shape of the result will be c.shape[3:] +
+ x.shape + y.shape + z.shape.
+
+ Parameters
+ ----------
+ x, y, z : array_like, compatible objects
+ The three dimensional series is evaluated at the points in the
+ Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
+ list or tuple, it is first converted to an ndarray, otherwise it is
+ left unchanged and, if it isn't an ndarray, it is treated as a
+ scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficients for terms of
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
+ greater than two the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional polynomial at points in the Cartesian
+ product of `x` and `y`.
+
+ See Also
+ --------
+ legval, legval2d, leggrid2d, legval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._gridnd(legval, c, x, y, z)
+
+
+def legvander(x, deg):
+ """Pseudo-Vandermonde matrix of given degree.
+
+ Returns the pseudo-Vandermonde matrix of degree `deg` and sample points
+ `x`. The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., i] = L_i(x)
+
+ where `0 <= i <= deg`. The leading indices of `V` index the elements of
+ `x` and the last index is the degree of the Legendre polynomial.
+
+ If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
+ array ``V = legvander(x, n)``, then ``np.dot(V, c)`` and
+ ``legval(x, c)`` are the same up to roundoff. This equivalence is
+ useful both for least squares fitting and for the evaluation of a large
+ number of Legendre series of the same degree and sample points.
+
+ Parameters
+ ----------
+ x : array_like
+ Array of points. The dtype is converted to float64 or complex128
+ depending on whether any of the elements are complex. If `x` is
+ scalar it is converted to a 1-D array.
+ deg : int
+ Degree of the resulting matrix.
+
+ Returns
+ -------
+ vander : ndarray
+ The pseudo-Vandermonde matrix. The shape of the returned matrix is
+ ``x.shape + (deg + 1,)``, where The last index is the degree of the
+ corresponding Legendre polynomial. The dtype will be the same as
+ the converted `x`.
+
+ """
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg < 0:
+ raise ValueError("deg must be non-negative")
+
+ x = np.array(x, copy=False, ndmin=1) + 0.0
+ dims = (ideg + 1,) + x.shape
+ dtyp = x.dtype
+ v = np.empty(dims, dtype=dtyp)
+ # Use forward recursion to generate the entries. This is not as accurate
+ # as reverse recursion in this application but it is more efficient.
+ v[0] = x*0 + 1
+ if ideg > 0:
+ v[1] = x
+ for i in range(2, ideg + 1):
+ v[i] = (v[i-1]*x*(2*i - 1) - v[i-2]*(i - 1))/i
+ return np.moveaxis(v, 0, -1)
+
+
+def legvander2d(x, y, deg):
+ """Pseudo-Vandermonde matrix of given degrees.
+
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
+ points `(x, y)`. The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., (deg[1] + 1)*i + j] = L_i(x) * L_j(y),
+
+ where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
+ `V` index the points `(x, y)` and the last index encodes the degrees of
+ the Legendre polynomials.
+
+ If ``V = legvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
+ correspond to the elements of a 2-D coefficient array `c` of shape
+ (xdeg + 1, ydeg + 1) in the order
+
+ .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
+
+ and ``np.dot(V, c.flat)`` and ``legval2d(x, y, c)`` will be the same
+ up to roundoff. This equivalence is useful both for least squares
+ fitting and for the evaluation of a large number of 2-D Legendre
+ series of the same degrees and sample points.
+
+ Parameters
+ ----------
+ x, y : array_like
+ Arrays of point coordinates, all of the same shape. The dtypes
+ will be converted to either float64 or complex128 depending on
+ whether any of the elements are complex. Scalars are converted to
+ 1-D arrays.
+ deg : list of ints
+ List of maximum degrees of the form [x_deg, y_deg].
+
+ Returns
+ -------
+ vander2d : ndarray
+ The shape of the returned matrix is ``x.shape + (order,)``, where
+ :math:`order = (deg[0]+1)*(deg[1]+1)`. The dtype will be the same
+ as the converted `x` and `y`.
+
+ See Also
+ --------
+ legvander, legvander3d, legval2d, legval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._vander_nd_flat((legvander, legvander), (x, y), deg)
+
+
+def legvander3d(x, y, z, deg):
+ """Pseudo-Vandermonde matrix of given degrees.
+
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
+ points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
+ then The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = L_i(x)*L_j(y)*L_k(z),
+
+ where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
+ indices of `V` index the points `(x, y, z)` and the last index encodes
+ the degrees of the Legendre polynomials.
+
+ If ``V = legvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
+ of `V` correspond to the elements of a 3-D coefficient array `c` of
+ shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
+
+ .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
+
+ and ``np.dot(V, c.flat)`` and ``legval3d(x, y, z, c)`` will be the
+ same up to roundoff. This equivalence is useful both for least squares
+ fitting and for the evaluation of a large number of 3-D Legendre
+ series of the same degrees and sample points.
+
+ Parameters
+ ----------
+ x, y, z : array_like
+ Arrays of point coordinates, all of the same shape. The dtypes will
+ be converted to either float64 or complex128 depending on whether
+ any of the elements are complex. Scalars are converted to 1-D
+ arrays.
+ deg : list of ints
+ List of maximum degrees of the form [x_deg, y_deg, z_deg].
+
+ Returns
+ -------
+ vander3d : ndarray
+ The shape of the returned matrix is ``x.shape + (order,)``, where
+ :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`. The dtype will
+ be the same as the converted `x`, `y`, and `z`.
+
+ See Also
+ --------
+ legvander, legvander3d, legval2d, legval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._vander_nd_flat((legvander, legvander, legvander), (x, y, z), deg)
+
+
+def legfit(x, y, deg, rcond=None, full=False, w=None):
+ """
+ Least squares fit of Legendre series to data.
+
+ Return the coefficients of a Legendre series of degree `deg` that is the
+ least squares fit to the data values `y` given at points `x`. If `y` is
+ 1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
+ fits are done, one for each column of `y`, and the resulting
+ coefficients are stored in the corresponding columns of a 2-D return.
+ The fitted polynomial(s) are in the form
+
+ .. math:: p(x) = c_0 + c_1 * L_1(x) + ... + c_n * L_n(x),
+
+ where `n` is `deg`.
+
+ Parameters
+ ----------
+ x : array_like, shape (M,)
+ x-coordinates of the M sample points ``(x[i], y[i])``.
+ y : array_like, shape (M,) or (M, K)
+ y-coordinates of the sample points. Several data sets of sample
+ points sharing the same x-coordinates can be fitted at once by
+ passing in a 2D-array that contains one dataset per column.
+ deg : int or 1-D array_like
+ Degree(s) of the fitting polynomials. If `deg` is a single integer
+ all terms up to and including the `deg`'th term are included in the
+ fit. For NumPy versions >= 1.11.0 a list of integers specifying the
+ degrees of the terms to include may be used instead.
+ rcond : float, optional
+ Relative condition number of the fit. Singular values smaller than
+ this relative to the largest singular value will be ignored. The
+ default value is len(x)*eps, where eps is the relative precision of
+ the float type, about 2e-16 in most cases.
+ full : bool, optional
+ Switch determining nature of return value. When it is False (the
+ default) just the coefficients are returned, when True diagnostic
+ information from the singular value decomposition is also returned.
+ w : array_like, shape (`M`,), optional
+ Weights. If not None, the weight ``w[i]`` applies to the unsquared
+ residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
+ chosen so that the errors of the products ``w[i]*y[i]`` all have the
+ same variance. When using inverse-variance weighting, use
+ ``w[i] = 1/sigma(y[i])``. The default value is None.
+
+ .. versionadded:: 1.5.0
+
+ Returns
+ -------
+ coef : ndarray, shape (M,) or (M, K)
+ Legendre coefficients ordered from low to high. If `y` was
+ 2-D, the coefficients for the data in column k of `y` are in
+ column `k`. If `deg` is specified as a list, coefficients for
+ terms not included in the fit are set equal to zero in the
+ returned `coef`.
+
+ [residuals, rank, singular_values, rcond] : list
+ These values are only returned if ``full == True``
+
+ - residuals -- sum of squared residuals of the least squares fit
+ - rank -- the numerical rank of the scaled Vandermonde matrix
+ - singular_values -- singular values of the scaled Vandermonde matrix
+ - rcond -- value of `rcond`.
+
+ For more details, see `numpy.linalg.lstsq`.
+
+ Warns
+ -----
+ RankWarning
+ The rank of the coefficient matrix in the least-squares fit is
+ deficient. The warning is only raised if ``full == False``. The
+ warnings can be turned off by
+
+ >>> import warnings
+ >>> warnings.simplefilter('ignore', np.RankWarning)
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyfit
+ numpy.polynomial.chebyshev.chebfit
+ numpy.polynomial.laguerre.lagfit
+ numpy.polynomial.hermite.hermfit
+ numpy.polynomial.hermite_e.hermefit
+ legval : Evaluates a Legendre series.
+ legvander : Vandermonde matrix of Legendre series.
+ legweight : Legendre weight function (= 1).
+ numpy.linalg.lstsq : Computes a least-squares fit from the matrix.
+ scipy.interpolate.UnivariateSpline : Computes spline fits.
+
+ Notes
+ -----
+ The solution is the coefficients of the Legendre series `p` that
+ minimizes the sum of the weighted squared errors
+
+ .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
+
+ where :math:`w_j` are the weights. This problem is solved by setting up
+ as the (typically) overdetermined matrix equation
+
+ .. math:: V(x) * c = w * y,
+
+ where `V` is the weighted pseudo Vandermonde matrix of `x`, `c` are the
+ coefficients to be solved for, `w` are the weights, and `y` are the
+ observed values. This equation is then solved using the singular value
+ decomposition of `V`.
+
+ If some of the singular values of `V` are so small that they are
+ neglected, then a `RankWarning` will be issued. This means that the
+ coefficient values may be poorly determined. Using a lower order fit
+ will usually get rid of the warning. The `rcond` parameter can also be
+ set to a value smaller than its default, but the resulting fit may be
+ spurious and have large contributions from roundoff error.
+
+ Fits using Legendre series are usually better conditioned than fits
+ using power series, but much can depend on the distribution of the
+ sample points and the smoothness of the data. If the quality of the fit
+ is inadequate splines may be a good alternative.
+
+ References
+ ----------
+ .. [1] Wikipedia, "Curve fitting",
+ https://en.wikipedia.org/wiki/Curve_fitting
+
+ Examples
+ --------
+
+ """
+ return pu._fit(legvander, x, y, deg, rcond, full, w)
+
+
+def legcompanion(c):
+ """Return the scaled companion matrix of c.
+
+ The basis polynomials are scaled so that the companion matrix is
+ symmetric when `c` is an Legendre basis polynomial. This provides
+ better eigenvalue estimates than the unscaled case and for basis
+ polynomials the eigenvalues are guaranteed to be real if
+ `numpy.linalg.eigvalsh` is used to obtain them.
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of Legendre series coefficients ordered from low to high
+ degree.
+
+ Returns
+ -------
+ mat : ndarray
+ Scaled companion matrix of dimensions (deg, deg).
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ if len(c) < 2:
+ raise ValueError('Series must have maximum degree of at least 1.')
+ if len(c) == 2:
+ return np.array([[-c[0]/c[1]]])
+
+ n = len(c) - 1
+ mat = np.zeros((n, n), dtype=c.dtype)
+ scl = 1./np.sqrt(2*np.arange(n) + 1)
+ top = mat.reshape(-1)[1::n+1]
+ bot = mat.reshape(-1)[n::n+1]
+ top[...] = np.arange(1, n)*scl[:n-1]*scl[1:n]
+ bot[...] = top
+ mat[:, -1] -= (c[:-1]/c[-1])*(scl/scl[-1])*(n/(2*n - 1))
+ return mat
+
+
+def legroots(c):
+ """
+ Compute the roots of a Legendre series.
+
+ Return the roots (a.k.a. "zeros") of the polynomial
+
+ .. math:: p(x) = \\sum_i c[i] * L_i(x).
+
+ Parameters
+ ----------
+ c : 1-D array_like
+ 1-D array of coefficients.
+
+ Returns
+ -------
+ out : ndarray
+ Array of the roots of the series. If all the roots are real,
+ then `out` is also real, otherwise it is complex.
+
+ See Also
+ --------
+ numpy.polynomial.polynomial.polyroots
+ numpy.polynomial.chebyshev.chebroots
+ numpy.polynomial.laguerre.lagroots
+ numpy.polynomial.hermite.hermroots
+ numpy.polynomial.hermite_e.hermeroots
+
+ Notes
+ -----
+ The root estimates are obtained as the eigenvalues of the companion
+ matrix, Roots far from the origin of the complex plane may have large
+ errors due to the numerical instability of the series for such values.
+ Roots with multiplicity greater than 1 will also show larger errors as
+ the value of the series near such points is relatively insensitive to
+ errors in the roots. Isolated roots near the origin can be improved by
+ a few iterations of Newton's method.
+
+ The Legendre series basis polynomials aren't powers of ``x`` so the
+ results of this function may seem unintuitive.
+
+ Examples
+ --------
+ >>> import numpy.polynomial.legendre as leg
+ >>> leg.legroots((1, 2, 3, 4)) # 4L_3 + 3L_2 + 2L_1 + 1L_0, all real roots
+ array([-0.85099543, -0.11407192, 0.51506735]) # may vary
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ if len(c) < 2:
+ return np.array([], dtype=c.dtype)
+ if len(c) == 2:
+ return np.array([-c[0]/c[1]])
+
+ # rotated companion matrix reduces error
+ m = legcompanion(c)[::-1,::-1]
+ r = la.eigvals(m)
+ r.sort()
+ return r
+
+
+def leggauss(deg):
+ """
+ Gauss-Legendre quadrature.
+
+ Computes the sample points and weights for Gauss-Legendre quadrature.
+ These sample points and weights will correctly integrate polynomials of
+ degree :math:`2*deg - 1` or less over the interval :math:`[-1, 1]` with
+ the weight function :math:`f(x) = 1`.
+
+ Parameters
+ ----------
+ deg : int
+ Number of sample points and weights. It must be >= 1.
+
+ Returns
+ -------
+ x : ndarray
+ 1-D ndarray containing the sample points.
+ y : ndarray
+ 1-D ndarray containing the weights.
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ The results have only been tested up to degree 100, higher degrees may
+ be problematic. The weights are determined by using the fact that
+
+ .. math:: w_k = c / (L'_n(x_k) * L_{n-1}(x_k))
+
+ where :math:`c` is a constant independent of :math:`k` and :math:`x_k`
+ is the k'th root of :math:`L_n`, and then scaling the results to get
+ the right value when integrating 1.
+
+ """
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg <= 0:
+ raise ValueError("deg must be a positive integer")
+
+ # first approximation of roots. We use the fact that the companion
+ # matrix is symmetric in this case in order to obtain better zeros.
+ c = np.array([0]*deg + [1])
+ m = legcompanion(c)
+ x = la.eigvalsh(m)
+
+ # improve roots by one application of Newton
+ dy = legval(x, c)
+ df = legval(x, legder(c))
+ x -= dy/df
+
+ # compute the weights. We scale the factor to avoid possible numerical
+ # overflow.
+ fm = legval(x, c[1:])
+ fm /= np.abs(fm).max()
+ df /= np.abs(df).max()
+ w = 1/(fm * df)
+
+ # for Legendre we can also symmetrize
+ w = (w + w[::-1])/2
+ x = (x - x[::-1])/2
+
+ # scale w to get the right value
+ w *= 2. / w.sum()
+
+ return x, w
+
+
+def legweight(x):
+ """
+ Weight function of the Legendre polynomials.
+
+ The weight function is :math:`1` and the interval of integration is
+ :math:`[-1, 1]`. The Legendre polynomials are orthogonal, but not
+ normalized, with respect to this weight function.
+
+ Parameters
+ ----------
+ x : array_like
+ Values at which the weight function will be computed.
+
+ Returns
+ -------
+ w : ndarray
+ The weight function at `x`.
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ w = x*0.0 + 1.0
+ return w
+
+#
+# Legendre series class
+#
+
+class Legendre(ABCPolyBase):
+ """A Legendre series class.
+
+ The Legendre class provides the standard Python numerical methods
+ '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
+ attributes and methods listed in the `ABCPolyBase` documentation.
+
+ Parameters
+ ----------
+ coef : array_like
+ Legendre coefficients in order of increasing degree, i.e.,
+ ``(1, 2, 3)`` gives ``1*P_0(x) + 2*P_1(x) + 3*P_2(x)``.
+ domain : (2,) array_like, optional
+ Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
+ to the interval ``[window[0], window[1]]`` by shifting and scaling.
+ The default value is [-1, 1].
+ window : (2,) array_like, optional
+ Window, see `domain` for its use. The default value is [-1, 1].
+
+ .. versionadded:: 1.6.0
+ symbol : str, optional
+ Symbol used to represent the independent variable in string
+ representations of the polynomial expression, e.g. for printing.
+ The symbol must be a valid Python identifier. Default value is 'x'.
+
+ .. versionadded:: 1.24
+
+ """
+ # Virtual Functions
+ _add = staticmethod(legadd)
+ _sub = staticmethod(legsub)
+ _mul = staticmethod(legmul)
+ _div = staticmethod(legdiv)
+ _pow = staticmethod(legpow)
+ _val = staticmethod(legval)
+ _int = staticmethod(legint)
+ _der = staticmethod(legder)
+ _fit = staticmethod(legfit)
+ _line = staticmethod(legline)
+ _roots = staticmethod(legroots)
+ _fromroots = staticmethod(legfromroots)
+
+ # Virtual properties
+ domain = np.array(legdomain)
+ window = np.array(legdomain)
+ basis_name = 'P'
diff --git a/lib/python3.12/site-packages/numpy/polynomial/legendre.pyi b/lib/python3.12/site-packages/numpy/polynomial/legendre.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..63a1c3f3a1f89c2c2da61e385f7dba1e7be16c06
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/legendre.pyi
@@ -0,0 +1,46 @@
+from typing import Any
+
+from numpy import ndarray, dtype, int_
+from numpy.polynomial._polybase import ABCPolyBase
+from numpy.polynomial.polyutils import trimcoef
+
+__all__: list[str]
+
+legtrim = trimcoef
+
+def poly2leg(pol): ...
+def leg2poly(c): ...
+
+legdomain: ndarray[Any, dtype[int_]]
+legzero: ndarray[Any, dtype[int_]]
+legone: ndarray[Any, dtype[int_]]
+legx: ndarray[Any, dtype[int_]]
+
+def legline(off, scl): ...
+def legfromroots(roots): ...
+def legadd(c1, c2): ...
+def legsub(c1, c2): ...
+def legmulx(c): ...
+def legmul(c1, c2): ...
+def legdiv(c1, c2): ...
+def legpow(c, pow, maxpower=...): ...
+def legder(c, m=..., scl=..., axis=...): ...
+def legint(c, m=..., k = ..., lbnd=..., scl=..., axis=...): ...
+def legval(x, c, tensor=...): ...
+def legval2d(x, y, c): ...
+def leggrid2d(x, y, c): ...
+def legval3d(x, y, z, c): ...
+def leggrid3d(x, y, z, c): ...
+def legvander(x, deg): ...
+def legvander2d(x, y, deg): ...
+def legvander3d(x, y, z, deg): ...
+def legfit(x, y, deg, rcond=..., full=..., w=...): ...
+def legcompanion(c): ...
+def legroots(c): ...
+def leggauss(deg): ...
+def legweight(x): ...
+
+class Legendre(ABCPolyBase):
+ domain: Any
+ window: Any
+ basis_name: Any
diff --git a/lib/python3.12/site-packages/numpy/polynomial/polynomial.py b/lib/python3.12/site-packages/numpy/polynomial/polynomial.py
new file mode 100644
index 0000000000000000000000000000000000000000..ceadff0bf4ed32f8bbbb9f208bf4d84946efe195
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/polynomial.py
@@ -0,0 +1,1542 @@
+"""
+=================================================
+Power Series (:mod:`numpy.polynomial.polynomial`)
+=================================================
+
+This module provides a number of objects (mostly functions) useful for
+dealing with polynomials, including a `Polynomial` class that
+encapsulates the usual arithmetic operations. (General information
+on how this module represents and works with polynomial objects is in
+the docstring for its "parent" sub-package, `numpy.polynomial`).
+
+Classes
+-------
+.. autosummary::
+ :toctree: generated/
+
+ Polynomial
+
+Constants
+---------
+.. autosummary::
+ :toctree: generated/
+
+ polydomain
+ polyzero
+ polyone
+ polyx
+
+Arithmetic
+----------
+.. autosummary::
+ :toctree: generated/
+
+ polyadd
+ polysub
+ polymulx
+ polymul
+ polydiv
+ polypow
+ polyval
+ polyval2d
+ polyval3d
+ polygrid2d
+ polygrid3d
+
+Calculus
+--------
+.. autosummary::
+ :toctree: generated/
+
+ polyder
+ polyint
+
+Misc Functions
+--------------
+.. autosummary::
+ :toctree: generated/
+
+ polyfromroots
+ polyroots
+ polyvalfromroots
+ polyvander
+ polyvander2d
+ polyvander3d
+ polycompanion
+ polyfit
+ polytrim
+ polyline
+
+See Also
+--------
+`numpy.polynomial`
+
+"""
+__all__ = [
+ 'polyzero', 'polyone', 'polyx', 'polydomain', 'polyline', 'polyadd',
+ 'polysub', 'polymulx', 'polymul', 'polydiv', 'polypow', 'polyval',
+ 'polyvalfromroots', 'polyder', 'polyint', 'polyfromroots', 'polyvander',
+ 'polyfit', 'polytrim', 'polyroots', 'Polynomial', 'polyval2d', 'polyval3d',
+ 'polygrid2d', 'polygrid3d', 'polyvander2d', 'polyvander3d']
+
+import numpy as np
+import numpy.linalg as la
+from numpy.core.multiarray import normalize_axis_index
+
+from . import polyutils as pu
+from ._polybase import ABCPolyBase
+
+polytrim = pu.trimcoef
+
+#
+# These are constant arrays are of integer type so as to be compatible
+# with the widest range of other types, such as Decimal.
+#
+
+# Polynomial default domain.
+polydomain = np.array([-1, 1])
+
+# Polynomial coefficients representing zero.
+polyzero = np.array([0])
+
+# Polynomial coefficients representing one.
+polyone = np.array([1])
+
+# Polynomial coefficients representing the identity x.
+polyx = np.array([0, 1])
+
+#
+# Polynomial series functions
+#
+
+
+def polyline(off, scl):
+ """
+ Returns an array representing a linear polynomial.
+
+ Parameters
+ ----------
+ off, scl : scalars
+ The "y-intercept" and "slope" of the line, respectively.
+
+ Returns
+ -------
+ y : ndarray
+ This module's representation of the linear polynomial ``off +
+ scl*x``.
+
+ See Also
+ --------
+ numpy.polynomial.chebyshev.chebline
+ numpy.polynomial.legendre.legline
+ numpy.polynomial.laguerre.lagline
+ numpy.polynomial.hermite.hermline
+ numpy.polynomial.hermite_e.hermeline
+
+ Examples
+ --------
+ >>> from numpy.polynomial import polynomial as P
+ >>> P.polyline(1,-1)
+ array([ 1, -1])
+ >>> P.polyval(1, P.polyline(1,-1)) # should be 0
+ 0.0
+
+ """
+ if scl != 0:
+ return np.array([off, scl])
+ else:
+ return np.array([off])
+
+
+def polyfromroots(roots):
+ """
+ Generate a monic polynomial with given roots.
+
+ Return the coefficients of the polynomial
+
+ .. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
+
+ where the ``r_n`` are the roots specified in `roots`. If a zero has
+ multiplicity n, then it must appear in `roots` n times. For instance,
+ if 2 is a root of multiplicity three and 3 is a root of multiplicity 2,
+ then `roots` looks something like [2, 2, 2, 3, 3]. The roots can appear
+ in any order.
+
+ If the returned coefficients are `c`, then
+
+ .. math:: p(x) = c_0 + c_1 * x + ... + x^n
+
+ The coefficient of the last term is 1 for monic polynomials in this
+ form.
+
+ Parameters
+ ----------
+ roots : array_like
+ Sequence containing the roots.
+
+ Returns
+ -------
+ out : ndarray
+ 1-D array of the polynomial's coefficients If all the roots are
+ real, then `out` is also real, otherwise it is complex. (see
+ Examples below).
+
+ See Also
+ --------
+ numpy.polynomial.chebyshev.chebfromroots
+ numpy.polynomial.legendre.legfromroots
+ numpy.polynomial.laguerre.lagfromroots
+ numpy.polynomial.hermite.hermfromroots
+ numpy.polynomial.hermite_e.hermefromroots
+
+ Notes
+ -----
+ The coefficients are determined by multiplying together linear factors
+ of the form ``(x - r_i)``, i.e.
+
+ .. math:: p(x) = (x - r_0) (x - r_1) ... (x - r_n)
+
+ where ``n == len(roots) - 1``; note that this implies that ``1`` is always
+ returned for :math:`a_n`.
+
+ Examples
+ --------
+ >>> from numpy.polynomial import polynomial as P
+ >>> P.polyfromroots((-1,0,1)) # x(x - 1)(x + 1) = x^3 - x
+ array([ 0., -1., 0., 1.])
+ >>> j = complex(0,1)
+ >>> P.polyfromroots((-j,j)) # complex returned, though values are real
+ array([1.+0.j, 0.+0.j, 1.+0.j])
+
+ """
+ return pu._fromroots(polyline, polymul, roots)
+
+
+def polyadd(c1, c2):
+ """
+ Add one polynomial to another.
+
+ Returns the sum of two polynomials `c1` + `c2`. The arguments are
+ sequences of coefficients from lowest order term to highest, i.e.,
+ [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of polynomial coefficients ordered from low to high.
+
+ Returns
+ -------
+ out : ndarray
+ The coefficient array representing their sum.
+
+ See Also
+ --------
+ polysub, polymulx, polymul, polydiv, polypow
+
+ Examples
+ --------
+ >>> from numpy.polynomial import polynomial as P
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> sum = P.polyadd(c1,c2); sum
+ array([4., 4., 4.])
+ >>> P.polyval(2, sum) # 4 + 4(2) + 4(2**2)
+ 28.0
+
+ """
+ return pu._add(c1, c2)
+
+
+def polysub(c1, c2):
+ """
+ Subtract one polynomial from another.
+
+ Returns the difference of two polynomials `c1` - `c2`. The arguments
+ are sequences of coefficients from lowest order term to highest, i.e.,
+ [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of polynomial coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Of coefficients representing their difference.
+
+ See Also
+ --------
+ polyadd, polymulx, polymul, polydiv, polypow
+
+ Examples
+ --------
+ >>> from numpy.polynomial import polynomial as P
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> P.polysub(c1,c2)
+ array([-2., 0., 2.])
+ >>> P.polysub(c2,c1) # -P.polysub(c1,c2)
+ array([ 2., 0., -2.])
+
+ """
+ return pu._sub(c1, c2)
+
+
+def polymulx(c):
+ """Multiply a polynomial by x.
+
+ Multiply the polynomial `c` by x, where x is the independent
+ variable.
+
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of polynomial coefficients ordered from low to
+ high.
+
+ Returns
+ -------
+ out : ndarray
+ Array representing the result of the multiplication.
+
+ See Also
+ --------
+ polyadd, polysub, polymul, polydiv, polypow
+
+ Notes
+ -----
+
+ .. versionadded:: 1.5.0
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ # The zero series needs special treatment
+ if len(c) == 1 and c[0] == 0:
+ return c
+
+ prd = np.empty(len(c) + 1, dtype=c.dtype)
+ prd[0] = c[0]*0
+ prd[1:] = c
+ return prd
+
+
+def polymul(c1, c2):
+ """
+ Multiply one polynomial by another.
+
+ Returns the product of two polynomials `c1` * `c2`. The arguments are
+ sequences of coefficients, from lowest order term to highest, e.g.,
+ [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2.``
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of coefficients representing a polynomial, relative to the
+ "standard" basis, and ordered from lowest order term to highest.
+
+ Returns
+ -------
+ out : ndarray
+ Of the coefficients of their product.
+
+ See Also
+ --------
+ polyadd, polysub, polymulx, polydiv, polypow
+
+ Examples
+ --------
+ >>> from numpy.polynomial import polynomial as P
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> P.polymul(c1,c2)
+ array([ 3., 8., 14., 8., 3.])
+
+ """
+ # c1, c2 are trimmed copies
+ [c1, c2] = pu.as_series([c1, c2])
+ ret = np.convolve(c1, c2)
+ return pu.trimseq(ret)
+
+
+def polydiv(c1, c2):
+ """
+ Divide one polynomial by another.
+
+ Returns the quotient-with-remainder of two polynomials `c1` / `c2`.
+ The arguments are sequences of coefficients, from lowest order term
+ to highest, e.g., [1,2,3] represents ``1 + 2*x + 3*x**2``.
+
+ Parameters
+ ----------
+ c1, c2 : array_like
+ 1-D arrays of polynomial coefficients ordered from low to high.
+
+ Returns
+ -------
+ [quo, rem] : ndarrays
+ Of coefficient series representing the quotient and remainder.
+
+ See Also
+ --------
+ polyadd, polysub, polymulx, polymul, polypow
+
+ Examples
+ --------
+ >>> from numpy.polynomial import polynomial as P
+ >>> c1 = (1,2,3)
+ >>> c2 = (3,2,1)
+ >>> P.polydiv(c1,c2)
+ (array([3.]), array([-8., -4.]))
+ >>> P.polydiv(c2,c1)
+ (array([ 0.33333333]), array([ 2.66666667, 1.33333333])) # may vary
+
+ """
+ # c1, c2 are trimmed copies
+ [c1, c2] = pu.as_series([c1, c2])
+ if c2[-1] == 0:
+ raise ZeroDivisionError()
+
+ # note: this is more efficient than `pu._div(polymul, c1, c2)`
+ lc1 = len(c1)
+ lc2 = len(c2)
+ if lc1 < lc2:
+ return c1[:1]*0, c1
+ elif lc2 == 1:
+ return c1/c2[-1], c1[:1]*0
+ else:
+ dlen = lc1 - lc2
+ scl = c2[-1]
+ c2 = c2[:-1]/scl
+ i = dlen
+ j = lc1 - 1
+ while i >= 0:
+ c1[i:j] -= c2*c1[j]
+ i -= 1
+ j -= 1
+ return c1[j+1:]/scl, pu.trimseq(c1[:j+1])
+
+
+def polypow(c, pow, maxpower=None):
+ """Raise a polynomial to a power.
+
+ Returns the polynomial `c` raised to the power `pow`. The argument
+ `c` is a sequence of coefficients ordered from low to high. i.e.,
+ [1,2,3] is the series ``1 + 2*x + 3*x**2.``
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of array of series coefficients ordered from low to
+ high degree.
+ pow : integer
+ Power to which the series will be raised
+ maxpower : integer, optional
+ Maximum power allowed. This is mainly to limit growth of the series
+ to unmanageable size. Default is 16
+
+ Returns
+ -------
+ coef : ndarray
+ Power series of power.
+
+ See Also
+ --------
+ polyadd, polysub, polymulx, polymul, polydiv
+
+ Examples
+ --------
+ >>> from numpy.polynomial import polynomial as P
+ >>> P.polypow([1,2,3], 2)
+ array([ 1., 4., 10., 12., 9.])
+
+ """
+ # note: this is more efficient than `pu._pow(polymul, c1, c2)`, as it
+ # avoids calling `as_series` repeatedly
+ return pu._pow(np.convolve, c, pow, maxpower)
+
+
+def polyder(c, m=1, scl=1, axis=0):
+ """
+ Differentiate a polynomial.
+
+ Returns the polynomial coefficients `c` differentiated `m` times along
+ `axis`. At each iteration the result is multiplied by `scl` (the
+ scaling factor is for use in a linear change of variable). The
+ argument `c` is an array of coefficients from low to high degree along
+ each axis, e.g., [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``
+ while [[1,2],[1,2]] represents ``1 + 1*x + 2*y + 2*x*y`` if axis=0 is
+ ``x`` and axis=1 is ``y``.
+
+ Parameters
+ ----------
+ c : array_like
+ Array of polynomial coefficients. If c is multidimensional the
+ different axis correspond to different variables with the degree
+ in each axis given by the corresponding index.
+ m : int, optional
+ Number of derivatives taken, must be non-negative. (Default: 1)
+ scl : scalar, optional
+ Each differentiation is multiplied by `scl`. The end result is
+ multiplication by ``scl**m``. This is for use in a linear change
+ of variable. (Default: 1)
+ axis : int, optional
+ Axis over which the derivative is taken. (Default: 0).
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ der : ndarray
+ Polynomial coefficients of the derivative.
+
+ See Also
+ --------
+ polyint
+
+ Examples
+ --------
+ >>> from numpy.polynomial import polynomial as P
+ >>> c = (1,2,3,4) # 1 + 2x + 3x**2 + 4x**3
+ >>> P.polyder(c) # (d/dx)(c) = 2 + 6x + 12x**2
+ array([ 2., 6., 12.])
+ >>> P.polyder(c,3) # (d**3/dx**3)(c) = 24
+ array([24.])
+ >>> P.polyder(c,scl=-1) # (d/d(-x))(c) = -2 - 6x - 12x**2
+ array([ -2., -6., -12.])
+ >>> P.polyder(c,2,-1) # (d**2/d(-x)**2)(c) = 6 + 24x
+ array([ 6., 24.])
+
+ """
+ c = np.array(c, ndmin=1, copy=True)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ # astype fails with NA
+ c = c + 0.0
+ cdt = c.dtype
+ cnt = pu._deprecate_as_int(m, "the order of derivation")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
+ if cnt < 0:
+ raise ValueError("The order of derivation must be non-negative")
+ iaxis = normalize_axis_index(iaxis, c.ndim)
+
+ if cnt == 0:
+ return c
+
+ c = np.moveaxis(c, iaxis, 0)
+ n = len(c)
+ if cnt >= n:
+ c = c[:1]*0
+ else:
+ for i in range(cnt):
+ n = n - 1
+ c *= scl
+ der = np.empty((n,) + c.shape[1:], dtype=cdt)
+ for j in range(n, 0, -1):
+ der[j - 1] = j*c[j]
+ c = der
+ c = np.moveaxis(c, 0, iaxis)
+ return c
+
+
+def polyint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
+ """
+ Integrate a polynomial.
+
+ Returns the polynomial coefficients `c` integrated `m` times from
+ `lbnd` along `axis`. At each iteration the resulting series is
+ **multiplied** by `scl` and an integration constant, `k`, is added.
+ The scaling factor is for use in a linear change of variable. ("Buyer
+ beware": note that, depending on what one is doing, one may want `scl`
+ to be the reciprocal of what one might expect; for more information,
+ see the Notes section below.) The argument `c` is an array of
+ coefficients, from low to high degree along each axis, e.g., [1,2,3]
+ represents the polynomial ``1 + 2*x + 3*x**2`` while [[1,2],[1,2]]
+ represents ``1 + 1*x + 2*y + 2*x*y`` if axis=0 is ``x`` and axis=1 is
+ ``y``.
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of polynomial coefficients, ordered from low to high.
+ m : int, optional
+ Order of integration, must be positive. (Default: 1)
+ k : {[], list, scalar}, optional
+ Integration constant(s). The value of the first integral at zero
+ is the first value in the list, the value of the second integral
+ at zero is the second value, etc. If ``k == []`` (the default),
+ all constants are set to zero. If ``m == 1``, a single scalar can
+ be given instead of a list.
+ lbnd : scalar, optional
+ The lower bound of the integral. (Default: 0)
+ scl : scalar, optional
+ Following each integration the result is *multiplied* by `scl`
+ before the integration constant is added. (Default: 1)
+ axis : int, optional
+ Axis over which the integral is taken. (Default: 0).
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ S : ndarray
+ Coefficient array of the integral.
+
+ Raises
+ ------
+ ValueError
+ If ``m < 1``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
+ ``np.ndim(scl) != 0``.
+
+ See Also
+ --------
+ polyder
+
+ Notes
+ -----
+ Note that the result of each integration is *multiplied* by `scl`. Why
+ is this important to note? Say one is making a linear change of
+ variable :math:`u = ax + b` in an integral relative to `x`. Then
+ :math:`dx = du/a`, so one will need to set `scl` equal to
+ :math:`1/a` - perhaps not what one would have first thought.
+
+ Examples
+ --------
+ >>> from numpy.polynomial import polynomial as P
+ >>> c = (1,2,3)
+ >>> P.polyint(c) # should return array([0, 1, 1, 1])
+ array([0., 1., 1., 1.])
+ >>> P.polyint(c,3) # should return array([0, 0, 0, 1/6, 1/12, 1/20])
+ array([ 0. , 0. , 0. , 0.16666667, 0.08333333, # may vary
+ 0.05 ])
+ >>> P.polyint(c,k=3) # should return array([3, 1, 1, 1])
+ array([3., 1., 1., 1.])
+ >>> P.polyint(c,lbnd=-2) # should return array([6, 1, 1, 1])
+ array([6., 1., 1., 1.])
+ >>> P.polyint(c,scl=-2) # should return array([0, -2, -2, -2])
+ array([ 0., -2., -2., -2.])
+
+ """
+ c = np.array(c, ndmin=1, copy=True)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ # astype doesn't preserve mask attribute.
+ c = c + 0.0
+ cdt = c.dtype
+ if not np.iterable(k):
+ k = [k]
+ cnt = pu._deprecate_as_int(m, "the order of integration")
+ iaxis = pu._deprecate_as_int(axis, "the axis")
+ if cnt < 0:
+ raise ValueError("The order of integration must be non-negative")
+ if len(k) > cnt:
+ raise ValueError("Too many integration constants")
+ if np.ndim(lbnd) != 0:
+ raise ValueError("lbnd must be a scalar.")
+ if np.ndim(scl) != 0:
+ raise ValueError("scl must be a scalar.")
+ iaxis = normalize_axis_index(iaxis, c.ndim)
+
+ if cnt == 0:
+ return c
+
+ k = list(k) + [0]*(cnt - len(k))
+ c = np.moveaxis(c, iaxis, 0)
+ for i in range(cnt):
+ n = len(c)
+ c *= scl
+ if n == 1 and np.all(c[0] == 0):
+ c[0] += k[i]
+ else:
+ tmp = np.empty((n + 1,) + c.shape[1:], dtype=cdt)
+ tmp[0] = c[0]*0
+ tmp[1] = c[0]
+ for j in range(1, n):
+ tmp[j + 1] = c[j]/(j + 1)
+ tmp[0] += k[i] - polyval(lbnd, tmp)
+ c = tmp
+ c = np.moveaxis(c, 0, iaxis)
+ return c
+
+
+def polyval(x, c, tensor=True):
+ """
+ Evaluate a polynomial at points x.
+
+ If `c` is of length `n + 1`, this function returns the value
+
+ .. math:: p(x) = c_0 + c_1 * x + ... + c_n * x^n
+
+ The parameter `x` is converted to an array only if it is a tuple or a
+ list, otherwise it is treated as a scalar. In either case, either `x`
+ or its elements must support multiplication and addition both with
+ themselves and with the elements of `c`.
+
+ If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
+ `c` is multidimensional, then the shape of the result depends on the
+ value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
+ x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
+ scalars have shape (,).
+
+ Trailing zeros in the coefficients will be used in the evaluation, so
+ they should be avoided if efficiency is a concern.
+
+ Parameters
+ ----------
+ x : array_like, compatible object
+ If `x` is a list or tuple, it is converted to an ndarray, otherwise
+ it is left unchanged and treated as a scalar. In either case, `x`
+ or its elements must support addition and multiplication with
+ with themselves and with the elements of `c`.
+ c : array_like
+ Array of coefficients ordered so that the coefficients for terms of
+ degree n are contained in c[n]. If `c` is multidimensional the
+ remaining indices enumerate multiple polynomials. In the two
+ dimensional case the coefficients may be thought of as stored in
+ the columns of `c`.
+ tensor : boolean, optional
+ If True, the shape of the coefficient array is extended with ones
+ on the right, one for each dimension of `x`. Scalars have dimension 0
+ for this action. The result is that every column of coefficients in
+ `c` is evaluated for every element of `x`. If False, `x` is broadcast
+ over the columns of `c` for the evaluation. This keyword is useful
+ when `c` is multidimensional. The default value is True.
+
+ .. versionadded:: 1.7.0
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The shape of the returned array is described above.
+
+ See Also
+ --------
+ polyval2d, polygrid2d, polyval3d, polygrid3d
+
+ Notes
+ -----
+ The evaluation uses Horner's method.
+
+ Examples
+ --------
+ >>> from numpy.polynomial.polynomial import polyval
+ >>> polyval(1, [1,2,3])
+ 6.0
+ >>> a = np.arange(4).reshape(2,2)
+ >>> a
+ array([[0, 1],
+ [2, 3]])
+ >>> polyval(a, [1,2,3])
+ array([[ 1., 6.],
+ [17., 34.]])
+ >>> coef = np.arange(4).reshape(2,2) # multidimensional coefficients
+ >>> coef
+ array([[0, 1],
+ [2, 3]])
+ >>> polyval([1,2], coef, tensor=True)
+ array([[2., 4.],
+ [4., 7.]])
+ >>> polyval([1,2], coef, tensor=False)
+ array([2., 7.])
+
+ """
+ c = np.array(c, ndmin=1, copy=False)
+ if c.dtype.char in '?bBhHiIlLqQpP':
+ # astype fails with NA
+ c = c + 0.0
+ if isinstance(x, (tuple, list)):
+ x = np.asarray(x)
+ if isinstance(x, np.ndarray) and tensor:
+ c = c.reshape(c.shape + (1,)*x.ndim)
+
+ c0 = c[-1] + x*0
+ for i in range(2, len(c) + 1):
+ c0 = c[-i] + c0*x
+ return c0
+
+
+def polyvalfromroots(x, r, tensor=True):
+ """
+ Evaluate a polynomial specified by its roots at points x.
+
+ If `r` is of length `N`, this function returns the value
+
+ .. math:: p(x) = \\prod_{n=1}^{N} (x - r_n)
+
+ The parameter `x` is converted to an array only if it is a tuple or a
+ list, otherwise it is treated as a scalar. In either case, either `x`
+ or its elements must support multiplication and addition both with
+ themselves and with the elements of `r`.
+
+ If `r` is a 1-D array, then `p(x)` will have the same shape as `x`. If `r`
+ is multidimensional, then the shape of the result depends on the value of
+ `tensor`. If `tensor` is ``True`` the shape will be r.shape[1:] + x.shape;
+ that is, each polynomial is evaluated at every value of `x`. If `tensor` is
+ ``False``, the shape will be r.shape[1:]; that is, each polynomial is
+ evaluated only for the corresponding broadcast value of `x`. Note that
+ scalars have shape (,).
+
+ .. versionadded:: 1.12
+
+ Parameters
+ ----------
+ x : array_like, compatible object
+ If `x` is a list or tuple, it is converted to an ndarray, otherwise
+ it is left unchanged and treated as a scalar. In either case, `x`
+ or its elements must support addition and multiplication with
+ with themselves and with the elements of `r`.
+ r : array_like
+ Array of roots. If `r` is multidimensional the first index is the
+ root index, while the remaining indices enumerate multiple
+ polynomials. For instance, in the two dimensional case the roots
+ of each polynomial may be thought of as stored in the columns of `r`.
+ tensor : boolean, optional
+ If True, the shape of the roots array is extended with ones on the
+ right, one for each dimension of `x`. Scalars have dimension 0 for this
+ action. The result is that every column of coefficients in `r` is
+ evaluated for every element of `x`. If False, `x` is broadcast over the
+ columns of `r` for the evaluation. This keyword is useful when `r` is
+ multidimensional. The default value is True.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The shape of the returned array is described above.
+
+ See Also
+ --------
+ polyroots, polyfromroots, polyval
+
+ Examples
+ --------
+ >>> from numpy.polynomial.polynomial import polyvalfromroots
+ >>> polyvalfromroots(1, [1,2,3])
+ 0.0
+ >>> a = np.arange(4).reshape(2,2)
+ >>> a
+ array([[0, 1],
+ [2, 3]])
+ >>> polyvalfromroots(a, [-1, 0, 1])
+ array([[-0., 0.],
+ [ 6., 24.]])
+ >>> r = np.arange(-2, 2).reshape(2,2) # multidimensional coefficients
+ >>> r # each column of r defines one polynomial
+ array([[-2, -1],
+ [ 0, 1]])
+ >>> b = [-2, 1]
+ >>> polyvalfromroots(b, r, tensor=True)
+ array([[-0., 3.],
+ [ 3., 0.]])
+ >>> polyvalfromroots(b, r, tensor=False)
+ array([-0., 0.])
+ """
+ r = np.array(r, ndmin=1, copy=False)
+ if r.dtype.char in '?bBhHiIlLqQpP':
+ r = r.astype(np.double)
+ if isinstance(x, (tuple, list)):
+ x = np.asarray(x)
+ if isinstance(x, np.ndarray):
+ if tensor:
+ r = r.reshape(r.shape + (1,)*x.ndim)
+ elif x.ndim >= r.ndim:
+ raise ValueError("x.ndim must be < r.ndim when tensor == False")
+ return np.prod(x - r, axis=0)
+
+
+def polyval2d(x, y, c):
+ """
+ Evaluate a 2-D polynomial at points (x, y).
+
+ This function returns the value
+
+ .. math:: p(x,y) = \\sum_{i,j} c_{i,j} * x^i * y^j
+
+ The parameters `x` and `y` are converted to arrays only if they are
+ tuples or a lists, otherwise they are treated as a scalars and they
+ must have the same shape after conversion. In either case, either `x`
+ and `y` or their elements must support multiplication and addition both
+ with themselves and with the elements of `c`.
+
+ If `c` has fewer than two dimensions, ones are implicitly appended to
+ its shape to make it 2-D. The shape of the result will be c.shape[2:] +
+ x.shape.
+
+ Parameters
+ ----------
+ x, y : array_like, compatible objects
+ The two dimensional series is evaluated at the points `(x, y)`,
+ where `x` and `y` must have the same shape. If `x` or `y` is a list
+ or tuple, it is first converted to an ndarray, otherwise it is left
+ unchanged and, if it isn't an ndarray, it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficient of the term
+ of multi-degree i,j is contained in `c[i,j]`. If `c` has
+ dimension greater than two the remaining indices enumerate multiple
+ sets of coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional polynomial at points formed with
+ pairs of corresponding values from `x` and `y`.
+
+ See Also
+ --------
+ polyval, polygrid2d, polyval3d, polygrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._valnd(polyval, c, x, y)
+
+
+def polygrid2d(x, y, c):
+ """
+ Evaluate a 2-D polynomial on the Cartesian product of x and y.
+
+ This function returns the values:
+
+ .. math:: p(a,b) = \\sum_{i,j} c_{i,j} * a^i * b^j
+
+ where the points `(a, b)` consist of all pairs formed by taking
+ `a` from `x` and `b` from `y`. The resulting points form a grid with
+ `x` in the first dimension and `y` in the second.
+
+ The parameters `x` and `y` are converted to arrays only if they are
+ tuples or a lists, otherwise they are treated as a scalars. In either
+ case, either `x` and `y` or their elements must support multiplication
+ and addition both with themselves and with the elements of `c`.
+
+ If `c` has fewer than two dimensions, ones are implicitly appended to
+ its shape to make it 2-D. The shape of the result will be c.shape[2:] +
+ x.shape + y.shape.
+
+ Parameters
+ ----------
+ x, y : array_like, compatible objects
+ The two dimensional series is evaluated at the points in the
+ Cartesian product of `x` and `y`. If `x` or `y` is a list or
+ tuple, it is first converted to an ndarray, otherwise it is left
+ unchanged and, if it isn't an ndarray, it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficients for terms of
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
+ greater than two the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional polynomial at points in the Cartesian
+ product of `x` and `y`.
+
+ See Also
+ --------
+ polyval, polyval2d, polyval3d, polygrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._gridnd(polyval, c, x, y)
+
+
+def polyval3d(x, y, z, c):
+ """
+ Evaluate a 3-D polynomial at points (x, y, z).
+
+ This function returns the values:
+
+ .. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * x^i * y^j * z^k
+
+ The parameters `x`, `y`, and `z` are converted to arrays only if
+ they are tuples or a lists, otherwise they are treated as a scalars and
+ they must have the same shape after conversion. In either case, either
+ `x`, `y`, and `z` or their elements must support multiplication and
+ addition both with themselves and with the elements of `c`.
+
+ If `c` has fewer than 3 dimensions, ones are implicitly appended to its
+ shape to make it 3-D. The shape of the result will be c.shape[3:] +
+ x.shape.
+
+ Parameters
+ ----------
+ x, y, z : array_like, compatible object
+ The three dimensional series is evaluated at the points
+ `(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
+ any of `x`, `y`, or `z` is a list or tuple, it is first converted
+ to an ndarray, otherwise it is left unchanged and if it isn't an
+ ndarray it is treated as a scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficient of the term of
+ multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
+ greater than 3 the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the multidimensional polynomial on points formed with
+ triples of corresponding values from `x`, `y`, and `z`.
+
+ See Also
+ --------
+ polyval, polyval2d, polygrid2d, polygrid3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._valnd(polyval, c, x, y, z)
+
+
+def polygrid3d(x, y, z, c):
+ """
+ Evaluate a 3-D polynomial on the Cartesian product of x, y and z.
+
+ This function returns the values:
+
+ .. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * a^i * b^j * c^k
+
+ where the points `(a, b, c)` consist of all triples formed by taking
+ `a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
+ a grid with `x` in the first dimension, `y` in the second, and `z` in
+ the third.
+
+ The parameters `x`, `y`, and `z` are converted to arrays only if they
+ are tuples or a lists, otherwise they are treated as a scalars. In
+ either case, either `x`, `y`, and `z` or their elements must support
+ multiplication and addition both with themselves and with the elements
+ of `c`.
+
+ If `c` has fewer than three dimensions, ones are implicitly appended to
+ its shape to make it 3-D. The shape of the result will be c.shape[3:] +
+ x.shape + y.shape + z.shape.
+
+ Parameters
+ ----------
+ x, y, z : array_like, compatible objects
+ The three dimensional series is evaluated at the points in the
+ Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
+ list or tuple, it is first converted to an ndarray, otherwise it is
+ left unchanged and, if it isn't an ndarray, it is treated as a
+ scalar.
+ c : array_like
+ Array of coefficients ordered so that the coefficients for terms of
+ degree i,j are contained in ``c[i,j]``. If `c` has dimension
+ greater than two the remaining indices enumerate multiple sets of
+ coefficients.
+
+ Returns
+ -------
+ values : ndarray, compatible object
+ The values of the two dimensional polynomial at points in the Cartesian
+ product of `x` and `y`.
+
+ See Also
+ --------
+ polyval, polyval2d, polygrid2d, polyval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._gridnd(polyval, c, x, y, z)
+
+
+def polyvander(x, deg):
+ """Vandermonde matrix of given degree.
+
+ Returns the Vandermonde matrix of degree `deg` and sample points
+ `x`. The Vandermonde matrix is defined by
+
+ .. math:: V[..., i] = x^i,
+
+ where `0 <= i <= deg`. The leading indices of `V` index the elements of
+ `x` and the last index is the power of `x`.
+
+ If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
+ matrix ``V = polyvander(x, n)``, then ``np.dot(V, c)`` and
+ ``polyval(x, c)`` are the same up to roundoff. This equivalence is
+ useful both for least squares fitting and for the evaluation of a large
+ number of polynomials of the same degree and sample points.
+
+ Parameters
+ ----------
+ x : array_like
+ Array of points. The dtype is converted to float64 or complex128
+ depending on whether any of the elements are complex. If `x` is
+ scalar it is converted to a 1-D array.
+ deg : int
+ Degree of the resulting matrix.
+
+ Returns
+ -------
+ vander : ndarray.
+ The Vandermonde matrix. The shape of the returned matrix is
+ ``x.shape + (deg + 1,)``, where the last index is the power of `x`.
+ The dtype will be the same as the converted `x`.
+
+ See Also
+ --------
+ polyvander2d, polyvander3d
+
+ """
+ ideg = pu._deprecate_as_int(deg, "deg")
+ if ideg < 0:
+ raise ValueError("deg must be non-negative")
+
+ x = np.array(x, copy=False, ndmin=1) + 0.0
+ dims = (ideg + 1,) + x.shape
+ dtyp = x.dtype
+ v = np.empty(dims, dtype=dtyp)
+ v[0] = x*0 + 1
+ if ideg > 0:
+ v[1] = x
+ for i in range(2, ideg + 1):
+ v[i] = v[i-1]*x
+ return np.moveaxis(v, 0, -1)
+
+
+def polyvander2d(x, y, deg):
+ """Pseudo-Vandermonde matrix of given degrees.
+
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
+ points `(x, y)`. The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., (deg[1] + 1)*i + j] = x^i * y^j,
+
+ where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
+ `V` index the points `(x, y)` and the last index encodes the powers of
+ `x` and `y`.
+
+ If ``V = polyvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
+ correspond to the elements of a 2-D coefficient array `c` of shape
+ (xdeg + 1, ydeg + 1) in the order
+
+ .. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
+
+ and ``np.dot(V, c.flat)`` and ``polyval2d(x, y, c)`` will be the same
+ up to roundoff. This equivalence is useful both for least squares
+ fitting and for the evaluation of a large number of 2-D polynomials
+ of the same degrees and sample points.
+
+ Parameters
+ ----------
+ x, y : array_like
+ Arrays of point coordinates, all of the same shape. The dtypes
+ will be converted to either float64 or complex128 depending on
+ whether any of the elements are complex. Scalars are converted to
+ 1-D arrays.
+ deg : list of ints
+ List of maximum degrees of the form [x_deg, y_deg].
+
+ Returns
+ -------
+ vander2d : ndarray
+ The shape of the returned matrix is ``x.shape + (order,)``, where
+ :math:`order = (deg[0]+1)*(deg([1]+1)`. The dtype will be the same
+ as the converted `x` and `y`.
+
+ See Also
+ --------
+ polyvander, polyvander3d, polyval2d, polyval3d
+
+ """
+ return pu._vander_nd_flat((polyvander, polyvander), (x, y), deg)
+
+
+def polyvander3d(x, y, z, deg):
+ """Pseudo-Vandermonde matrix of given degrees.
+
+ Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
+ points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
+ then The pseudo-Vandermonde matrix is defined by
+
+ .. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = x^i * y^j * z^k,
+
+ where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
+ indices of `V` index the points `(x, y, z)` and the last index encodes
+ the powers of `x`, `y`, and `z`.
+
+ If ``V = polyvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
+ of `V` correspond to the elements of a 3-D coefficient array `c` of
+ shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
+
+ .. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
+
+ and ``np.dot(V, c.flat)`` and ``polyval3d(x, y, z, c)`` will be the
+ same up to roundoff. This equivalence is useful both for least squares
+ fitting and for the evaluation of a large number of 3-D polynomials
+ of the same degrees and sample points.
+
+ Parameters
+ ----------
+ x, y, z : array_like
+ Arrays of point coordinates, all of the same shape. The dtypes will
+ be converted to either float64 or complex128 depending on whether
+ any of the elements are complex. Scalars are converted to 1-D
+ arrays.
+ deg : list of ints
+ List of maximum degrees of the form [x_deg, y_deg, z_deg].
+
+ Returns
+ -------
+ vander3d : ndarray
+ The shape of the returned matrix is ``x.shape + (order,)``, where
+ :math:`order = (deg[0]+1)*(deg([1]+1)*(deg[2]+1)`. The dtype will
+ be the same as the converted `x`, `y`, and `z`.
+
+ See Also
+ --------
+ polyvander, polyvander3d, polyval2d, polyval3d
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ return pu._vander_nd_flat((polyvander, polyvander, polyvander), (x, y, z), deg)
+
+
+def polyfit(x, y, deg, rcond=None, full=False, w=None):
+ """
+ Least-squares fit of a polynomial to data.
+
+ Return the coefficients of a polynomial of degree `deg` that is the
+ least squares fit to the data values `y` given at points `x`. If `y` is
+ 1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
+ fits are done, one for each column of `y`, and the resulting
+ coefficients are stored in the corresponding columns of a 2-D return.
+ The fitted polynomial(s) are in the form
+
+ .. math:: p(x) = c_0 + c_1 * x + ... + c_n * x^n,
+
+ where `n` is `deg`.
+
+ Parameters
+ ----------
+ x : array_like, shape (`M`,)
+ x-coordinates of the `M` sample (data) points ``(x[i], y[i])``.
+ y : array_like, shape (`M`,) or (`M`, `K`)
+ y-coordinates of the sample points. Several sets of sample points
+ sharing the same x-coordinates can be (independently) fit with one
+ call to `polyfit` by passing in for `y` a 2-D array that contains
+ one data set per column.
+ deg : int or 1-D array_like
+ Degree(s) of the fitting polynomials. If `deg` is a single integer
+ all terms up to and including the `deg`'th term are included in the
+ fit. For NumPy versions >= 1.11.0 a list of integers specifying the
+ degrees of the terms to include may be used instead.
+ rcond : float, optional
+ Relative condition number of the fit. Singular values smaller
+ than `rcond`, relative to the largest singular value, will be
+ ignored. The default value is ``len(x)*eps``, where `eps` is the
+ relative precision of the platform's float type, about 2e-16 in
+ most cases.
+ full : bool, optional
+ Switch determining the nature of the return value. When ``False``
+ (the default) just the coefficients are returned; when ``True``,
+ diagnostic information from the singular value decomposition (used
+ to solve the fit's matrix equation) is also returned.
+ w : array_like, shape (`M`,), optional
+ Weights. If not None, the weight ``w[i]`` applies to the unsquared
+ residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
+ chosen so that the errors of the products ``w[i]*y[i]`` all have the
+ same variance. When using inverse-variance weighting, use
+ ``w[i] = 1/sigma(y[i])``. The default value is None.
+
+ .. versionadded:: 1.5.0
+
+ Returns
+ -------
+ coef : ndarray, shape (`deg` + 1,) or (`deg` + 1, `K`)
+ Polynomial coefficients ordered from low to high. If `y` was 2-D,
+ the coefficients in column `k` of `coef` represent the polynomial
+ fit to the data in `y`'s `k`-th column.
+
+ [residuals, rank, singular_values, rcond] : list
+ These values are only returned if ``full == True``
+
+ - residuals -- sum of squared residuals of the least squares fit
+ - rank -- the numerical rank of the scaled Vandermonde matrix
+ - singular_values -- singular values of the scaled Vandermonde matrix
+ - rcond -- value of `rcond`.
+
+ For more details, see `numpy.linalg.lstsq`.
+
+ Raises
+ ------
+ RankWarning
+ Raised if the matrix in the least-squares fit is rank deficient.
+ The warning is only raised if ``full == False``. The warnings can
+ be turned off by:
+
+ >>> import warnings
+ >>> warnings.simplefilter('ignore', np.RankWarning)
+
+ See Also
+ --------
+ numpy.polynomial.chebyshev.chebfit
+ numpy.polynomial.legendre.legfit
+ numpy.polynomial.laguerre.lagfit
+ numpy.polynomial.hermite.hermfit
+ numpy.polynomial.hermite_e.hermefit
+ polyval : Evaluates a polynomial.
+ polyvander : Vandermonde matrix for powers.
+ numpy.linalg.lstsq : Computes a least-squares fit from the matrix.
+ scipy.interpolate.UnivariateSpline : Computes spline fits.
+
+ Notes
+ -----
+ The solution is the coefficients of the polynomial `p` that minimizes
+ the sum of the weighted squared errors
+
+ .. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
+
+ where the :math:`w_j` are the weights. This problem is solved by
+ setting up the (typically) over-determined matrix equation:
+
+ .. math:: V(x) * c = w * y,
+
+ where `V` is the weighted pseudo Vandermonde matrix of `x`, `c` are the
+ coefficients to be solved for, `w` are the weights, and `y` are the
+ observed values. This equation is then solved using the singular value
+ decomposition of `V`.
+
+ If some of the singular values of `V` are so small that they are
+ neglected (and `full` == ``False``), a `RankWarning` will be raised.
+ This means that the coefficient values may be poorly determined.
+ Fitting to a lower order polynomial will usually get rid of the warning
+ (but may not be what you want, of course; if you have independent
+ reason(s) for choosing the degree which isn't working, you may have to:
+ a) reconsider those reasons, and/or b) reconsider the quality of your
+ data). The `rcond` parameter can also be set to a value smaller than
+ its default, but the resulting fit may be spurious and have large
+ contributions from roundoff error.
+
+ Polynomial fits using double precision tend to "fail" at about
+ (polynomial) degree 20. Fits using Chebyshev or Legendre series are
+ generally better conditioned, but much can still depend on the
+ distribution of the sample points and the smoothness of the data. If
+ the quality of the fit is inadequate, splines may be a good
+ alternative.
+
+ Examples
+ --------
+ >>> np.random.seed(123)
+ >>> from numpy.polynomial import polynomial as P
+ >>> x = np.linspace(-1,1,51) # x "data": [-1, -0.96, ..., 0.96, 1]
+ >>> y = x**3 - x + np.random.randn(len(x)) # x^3 - x + Gaussian noise
+ >>> c, stats = P.polyfit(x,y,3,full=True)
+ >>> np.random.seed(123)
+ >>> c # c[0], c[2] should be approx. 0, c[1] approx. -1, c[3] approx. 1
+ array([ 0.01909725, -1.30598256, -0.00577963, 1.02644286]) # may vary
+ >>> stats # note the large SSR, explaining the rather poor results
+ [array([ 38.06116253]), 4, array([ 1.38446749, 1.32119158, 0.50443316, # may vary
+ 0.28853036]), 1.1324274851176597e-014]
+
+ Same thing without the added noise
+
+ >>> y = x**3 - x
+ >>> c, stats = P.polyfit(x,y,3,full=True)
+ >>> c # c[0], c[2] should be "very close to 0", c[1] ~= -1, c[3] ~= 1
+ array([-6.36925336e-18, -1.00000000e+00, -4.08053781e-16, 1.00000000e+00])
+ >>> stats # note the minuscule SSR
+ [array([ 7.46346754e-31]), 4, array([ 1.38446749, 1.32119158, # may vary
+ 0.50443316, 0.28853036]), 1.1324274851176597e-014]
+
+ """
+ return pu._fit(polyvander, x, y, deg, rcond, full, w)
+
+
+def polycompanion(c):
+ """
+ Return the companion matrix of c.
+
+ The companion matrix for power series cannot be made symmetric by
+ scaling the basis, so this function differs from those for the
+ orthogonal polynomials.
+
+ Parameters
+ ----------
+ c : array_like
+ 1-D array of polynomial coefficients ordered from low to high
+ degree.
+
+ Returns
+ -------
+ mat : ndarray
+ Companion matrix of dimensions (deg, deg).
+
+ Notes
+ -----
+
+ .. versionadded:: 1.7.0
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ if len(c) < 2:
+ raise ValueError('Series must have maximum degree of at least 1.')
+ if len(c) == 2:
+ return np.array([[-c[0]/c[1]]])
+
+ n = len(c) - 1
+ mat = np.zeros((n, n), dtype=c.dtype)
+ bot = mat.reshape(-1)[n::n+1]
+ bot[...] = 1
+ mat[:, -1] -= c[:-1]/c[-1]
+ return mat
+
+
+def polyroots(c):
+ """
+ Compute the roots of a polynomial.
+
+ Return the roots (a.k.a. "zeros") of the polynomial
+
+ .. math:: p(x) = \\sum_i c[i] * x^i.
+
+ Parameters
+ ----------
+ c : 1-D array_like
+ 1-D array of polynomial coefficients.
+
+ Returns
+ -------
+ out : ndarray
+ Array of the roots of the polynomial. If all the roots are real,
+ then `out` is also real, otherwise it is complex.
+
+ See Also
+ --------
+ numpy.polynomial.chebyshev.chebroots
+ numpy.polynomial.legendre.legroots
+ numpy.polynomial.laguerre.lagroots
+ numpy.polynomial.hermite.hermroots
+ numpy.polynomial.hermite_e.hermeroots
+
+ Notes
+ -----
+ The root estimates are obtained as the eigenvalues of the companion
+ matrix, Roots far from the origin of the complex plane may have large
+ errors due to the numerical instability of the power series for such
+ values. Roots with multiplicity greater than 1 will also show larger
+ errors as the value of the series near such points is relatively
+ insensitive to errors in the roots. Isolated roots near the origin can
+ be improved by a few iterations of Newton's method.
+
+ Examples
+ --------
+ >>> import numpy.polynomial.polynomial as poly
+ >>> poly.polyroots(poly.polyfromroots((-1,0,1)))
+ array([-1., 0., 1.])
+ >>> poly.polyroots(poly.polyfromroots((-1,0,1))).dtype
+ dtype('float64')
+ >>> j = complex(0,1)
+ >>> poly.polyroots(poly.polyfromroots((-j,0,j)))
+ array([ 0.00000000e+00+0.j, 0.00000000e+00+1.j, 2.77555756e-17-1.j]) # may vary
+
+ """
+ # c is a trimmed copy
+ [c] = pu.as_series([c])
+ if len(c) < 2:
+ return np.array([], dtype=c.dtype)
+ if len(c) == 2:
+ return np.array([-c[0]/c[1]])
+
+ # rotated companion matrix reduces error
+ m = polycompanion(c)[::-1,::-1]
+ r = la.eigvals(m)
+ r.sort()
+ return r
+
+
+#
+# polynomial class
+#
+
+class Polynomial(ABCPolyBase):
+ """A power series class.
+
+ The Polynomial class provides the standard Python numerical methods
+ '+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
+ attributes and methods listed in the `ABCPolyBase` documentation.
+
+ Parameters
+ ----------
+ coef : array_like
+ Polynomial coefficients in order of increasing degree, i.e.,
+ ``(1, 2, 3)`` give ``1 + 2*x + 3*x**2``.
+ domain : (2,) array_like, optional
+ Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
+ to the interval ``[window[0], window[1]]`` by shifting and scaling.
+ The default value is [-1, 1].
+ window : (2,) array_like, optional
+ Window, see `domain` for its use. The default value is [-1, 1].
+
+ .. versionadded:: 1.6.0
+ symbol : str, optional
+ Symbol used to represent the independent variable in string
+ representations of the polynomial expression, e.g. for printing.
+ The symbol must be a valid Python identifier. Default value is 'x'.
+
+ .. versionadded:: 1.24
+
+ """
+ # Virtual Functions
+ _add = staticmethod(polyadd)
+ _sub = staticmethod(polysub)
+ _mul = staticmethod(polymul)
+ _div = staticmethod(polydiv)
+ _pow = staticmethod(polypow)
+ _val = staticmethod(polyval)
+ _int = staticmethod(polyint)
+ _der = staticmethod(polyder)
+ _fit = staticmethod(polyfit)
+ _line = staticmethod(polyline)
+ _roots = staticmethod(polyroots)
+ _fromroots = staticmethod(polyfromroots)
+
+ # Virtual properties
+ domain = np.array(polydomain)
+ window = np.array(polydomain)
+ basis_name = None
+
+ @classmethod
+ def _str_term_unicode(cls, i, arg_str):
+ if i == '1':
+ return f"·{arg_str}"
+ else:
+ return f"·{arg_str}{i.translate(cls._superscript_mapping)}"
+
+ @staticmethod
+ def _str_term_ascii(i, arg_str):
+ if i == '1':
+ return f" {arg_str}"
+ else:
+ return f" {arg_str}**{i}"
+
+ @staticmethod
+ def _repr_latex_term(i, arg_str, needs_parens):
+ if needs_parens:
+ arg_str = rf"\left({arg_str}\right)"
+ if i == 0:
+ return '1'
+ elif i == 1:
+ return arg_str
+ else:
+ return f"{arg_str}^{{{i}}}"
diff --git a/lib/python3.12/site-packages/numpy/polynomial/polynomial.pyi b/lib/python3.12/site-packages/numpy/polynomial/polynomial.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..3c87f9d2926615e09bffd03d00306b6f235ec1c2
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/polynomial.pyi
@@ -0,0 +1,41 @@
+from typing import Any
+
+from numpy import ndarray, dtype, int_
+from numpy.polynomial._polybase import ABCPolyBase
+from numpy.polynomial.polyutils import trimcoef
+
+__all__: list[str]
+
+polytrim = trimcoef
+
+polydomain: ndarray[Any, dtype[int_]]
+polyzero: ndarray[Any, dtype[int_]]
+polyone: ndarray[Any, dtype[int_]]
+polyx: ndarray[Any, dtype[int_]]
+
+def polyline(off, scl): ...
+def polyfromroots(roots): ...
+def polyadd(c1, c2): ...
+def polysub(c1, c2): ...
+def polymulx(c): ...
+def polymul(c1, c2): ...
+def polydiv(c1, c2): ...
+def polypow(c, pow, maxpower=...): ...
+def polyder(c, m=..., scl=..., axis=...): ...
+def polyint(c, m=..., k=..., lbnd=..., scl=..., axis=...): ...
+def polyval(x, c, tensor=...): ...
+def polyvalfromroots(x, r, tensor=...): ...
+def polyval2d(x, y, c): ...
+def polygrid2d(x, y, c): ...
+def polyval3d(x, y, z, c): ...
+def polygrid3d(x, y, z, c): ...
+def polyvander(x, deg): ...
+def polyvander2d(x, y, deg): ...
+def polyvander3d(x, y, z, deg): ...
+def polyfit(x, y, deg, rcond=..., full=..., w=...): ...
+def polyroots(c): ...
+
+class Polynomial(ABCPolyBase):
+ domain: Any
+ window: Any
+ basis_name: Any
diff --git a/lib/python3.12/site-packages/numpy/polynomial/polyutils.py b/lib/python3.12/site-packages/numpy/polynomial/polyutils.py
new file mode 100644
index 0000000000000000000000000000000000000000..4829138920169efc5b18b20be4a7d7c9509ba7fb
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/polyutils.py
@@ -0,0 +1,789 @@
+"""
+Utility classes and functions for the polynomial modules.
+
+This module provides: error and warning objects; a polynomial base class;
+and some routines used in both the `polynomial` and `chebyshev` modules.
+
+Warning objects
+---------------
+
+.. autosummary::
+ :toctree: generated/
+
+ RankWarning raised in least-squares fit for rank-deficient matrix.
+
+Functions
+---------
+
+.. autosummary::
+ :toctree: generated/
+
+ as_series convert list of array_likes into 1-D arrays of common type.
+ trimseq remove trailing zeros.
+ trimcoef remove small trailing coefficients.
+ getdomain return the domain appropriate for a given set of abscissae.
+ mapdomain maps points between domains.
+ mapparms parameters of the linear map between domains.
+
+"""
+import operator
+import functools
+import warnings
+
+import numpy as np
+
+from numpy.core.multiarray import dragon4_positional, dragon4_scientific
+from numpy.core.umath import absolute
+
+__all__ = [
+ 'RankWarning', 'as_series', 'trimseq',
+ 'trimcoef', 'getdomain', 'mapdomain', 'mapparms',
+ 'format_float']
+
+#
+# Warnings and Exceptions
+#
+
+class RankWarning(UserWarning):
+ """Issued by chebfit when the design matrix is rank deficient."""
+ pass
+
+#
+# Helper functions to convert inputs to 1-D arrays
+#
+def trimseq(seq):
+ """Remove small Poly series coefficients.
+
+ Parameters
+ ----------
+ seq : sequence
+ Sequence of Poly series coefficients. This routine fails for
+ empty sequences.
+
+ Returns
+ -------
+ series : sequence
+ Subsequence with trailing zeros removed. If the resulting sequence
+ would be empty, return the first element. The returned sequence may
+ or may not be a view.
+
+ Notes
+ -----
+ Do not lose the type info if the sequence contains unknown objects.
+
+ """
+ if len(seq) == 0:
+ return seq
+ else:
+ for i in range(len(seq) - 1, -1, -1):
+ if seq[i] != 0:
+ break
+ return seq[:i+1]
+
+
+def as_series(alist, trim=True):
+ """
+ Return argument as a list of 1-d arrays.
+
+ The returned list contains array(s) of dtype double, complex double, or
+ object. A 1-d argument of shape ``(N,)`` is parsed into ``N`` arrays of
+ size one; a 2-d argument of shape ``(M,N)`` is parsed into ``M`` arrays
+ of size ``N`` (i.e., is "parsed by row"); and a higher dimensional array
+ raises a Value Error if it is not first reshaped into either a 1-d or 2-d
+ array.
+
+ Parameters
+ ----------
+ alist : array_like
+ A 1- or 2-d array_like
+ trim : boolean, optional
+ When True, trailing zeros are removed from the inputs.
+ When False, the inputs are passed through intact.
+
+ Returns
+ -------
+ [a1, a2,...] : list of 1-D arrays
+ A copy of the input data as a list of 1-d arrays.
+
+ Raises
+ ------
+ ValueError
+ Raised when `as_series` cannot convert its input to 1-d arrays, or at
+ least one of the resulting arrays is empty.
+
+ Examples
+ --------
+ >>> from numpy.polynomial import polyutils as pu
+ >>> a = np.arange(4)
+ >>> pu.as_series(a)
+ [array([0.]), array([1.]), array([2.]), array([3.])]
+ >>> b = np.arange(6).reshape((2,3))
+ >>> pu.as_series(b)
+ [array([0., 1., 2.]), array([3., 4., 5.])]
+
+ >>> pu.as_series((1, np.arange(3), np.arange(2, dtype=np.float16)))
+ [array([1.]), array([0., 1., 2.]), array([0., 1.])]
+
+ >>> pu.as_series([2, [1.1, 0.]])
+ [array([2.]), array([1.1])]
+
+ >>> pu.as_series([2, [1.1, 0.]], trim=False)
+ [array([2.]), array([1.1, 0. ])]
+
+ """
+ arrays = [np.array(a, ndmin=1, copy=False) for a in alist]
+ if min([a.size for a in arrays]) == 0:
+ raise ValueError("Coefficient array is empty")
+ if any(a.ndim != 1 for a in arrays):
+ raise ValueError("Coefficient array is not 1-d")
+ if trim:
+ arrays = [trimseq(a) for a in arrays]
+
+ if any(a.dtype == np.dtype(object) for a in arrays):
+ ret = []
+ for a in arrays:
+ if a.dtype != np.dtype(object):
+ tmp = np.empty(len(a), dtype=np.dtype(object))
+ tmp[:] = a[:]
+ ret.append(tmp)
+ else:
+ ret.append(a.copy())
+ else:
+ try:
+ dtype = np.common_type(*arrays)
+ except Exception as e:
+ raise ValueError("Coefficient arrays have no common type") from e
+ ret = [np.array(a, copy=True, dtype=dtype) for a in arrays]
+ return ret
+
+
+def trimcoef(c, tol=0):
+ """
+ Remove "small" "trailing" coefficients from a polynomial.
+
+ "Small" means "small in absolute value" and is controlled by the
+ parameter `tol`; "trailing" means highest order coefficient(s), e.g., in
+ ``[0, 1, 1, 0, 0]`` (which represents ``0 + x + x**2 + 0*x**3 + 0*x**4``)
+ both the 3-rd and 4-th order coefficients would be "trimmed."
+
+ Parameters
+ ----------
+ c : array_like
+ 1-d array of coefficients, ordered from lowest order to highest.
+ tol : number, optional
+ Trailing (i.e., highest order) elements with absolute value less
+ than or equal to `tol` (default value is zero) are removed.
+
+ Returns
+ -------
+ trimmed : ndarray
+ 1-d array with trailing zeros removed. If the resulting series
+ would be empty, a series containing a single zero is returned.
+
+ Raises
+ ------
+ ValueError
+ If `tol` < 0
+
+ See Also
+ --------
+ trimseq
+
+ Examples
+ --------
+ >>> from numpy.polynomial import polyutils as pu
+ >>> pu.trimcoef((0,0,3,0,5,0,0))
+ array([0., 0., 3., 0., 5.])
+ >>> pu.trimcoef((0,0,1e-3,0,1e-5,0,0),1e-3) # item == tol is trimmed
+ array([0.])
+ >>> i = complex(0,1) # works for complex
+ >>> pu.trimcoef((3e-4,1e-3*(1-i),5e-4,2e-5*(1+i)), 1e-3)
+ array([0.0003+0.j , 0.001 -0.001j])
+
+ """
+ if tol < 0:
+ raise ValueError("tol must be non-negative")
+
+ [c] = as_series([c])
+ [ind] = np.nonzero(np.abs(c) > tol)
+ if len(ind) == 0:
+ return c[:1]*0
+ else:
+ return c[:ind[-1] + 1].copy()
+
+def getdomain(x):
+ """
+ Return a domain suitable for given abscissae.
+
+ Find a domain suitable for a polynomial or Chebyshev series
+ defined at the values supplied.
+
+ Parameters
+ ----------
+ x : array_like
+ 1-d array of abscissae whose domain will be determined.
+
+ Returns
+ -------
+ domain : ndarray
+ 1-d array containing two values. If the inputs are complex, then
+ the two returned points are the lower left and upper right corners
+ of the smallest rectangle (aligned with the axes) in the complex
+ plane containing the points `x`. If the inputs are real, then the
+ two points are the ends of the smallest interval containing the
+ points `x`.
+
+ See Also
+ --------
+ mapparms, mapdomain
+
+ Examples
+ --------
+ >>> from numpy.polynomial import polyutils as pu
+ >>> points = np.arange(4)**2 - 5; points
+ array([-5, -4, -1, 4])
+ >>> pu.getdomain(points)
+ array([-5., 4.])
+ >>> c = np.exp(complex(0,1)*np.pi*np.arange(12)/6) # unit circle
+ >>> pu.getdomain(c)
+ array([-1.-1.j, 1.+1.j])
+
+ """
+ [x] = as_series([x], trim=False)
+ if x.dtype.char in np.typecodes['Complex']:
+ rmin, rmax = x.real.min(), x.real.max()
+ imin, imax = x.imag.min(), x.imag.max()
+ return np.array((complex(rmin, imin), complex(rmax, imax)))
+ else:
+ return np.array((x.min(), x.max()))
+
+def mapparms(old, new):
+ """
+ Linear map parameters between domains.
+
+ Return the parameters of the linear map ``offset + scale*x`` that maps
+ `old` to `new` such that ``old[i] -> new[i]``, ``i = 0, 1``.
+
+ Parameters
+ ----------
+ old, new : array_like
+ Domains. Each domain must (successfully) convert to a 1-d array
+ containing precisely two values.
+
+ Returns
+ -------
+ offset, scale : scalars
+ The map ``L(x) = offset + scale*x`` maps the first domain to the
+ second.
+
+ See Also
+ --------
+ getdomain, mapdomain
+
+ Notes
+ -----
+ Also works for complex numbers, and thus can be used to calculate the
+ parameters required to map any line in the complex plane to any other
+ line therein.
+
+ Examples
+ --------
+ >>> from numpy.polynomial import polyutils as pu
+ >>> pu.mapparms((-1,1),(-1,1))
+ (0.0, 1.0)
+ >>> pu.mapparms((1,-1),(-1,1))
+ (-0.0, -1.0)
+ >>> i = complex(0,1)
+ >>> pu.mapparms((-i,-1),(1,i))
+ ((1+1j), (1-0j))
+
+ """
+ oldlen = old[1] - old[0]
+ newlen = new[1] - new[0]
+ off = (old[1]*new[0] - old[0]*new[1])/oldlen
+ scl = newlen/oldlen
+ return off, scl
+
+def mapdomain(x, old, new):
+ """
+ Apply linear map to input points.
+
+ The linear map ``offset + scale*x`` that maps the domain `old` to
+ the domain `new` is applied to the points `x`.
+
+ Parameters
+ ----------
+ x : array_like
+ Points to be mapped. If `x` is a subtype of ndarray the subtype
+ will be preserved.
+ old, new : array_like
+ The two domains that determine the map. Each must (successfully)
+ convert to 1-d arrays containing precisely two values.
+
+ Returns
+ -------
+ x_out : ndarray
+ Array of points of the same shape as `x`, after application of the
+ linear map between the two domains.
+
+ See Also
+ --------
+ getdomain, mapparms
+
+ Notes
+ -----
+ Effectively, this implements:
+
+ .. math::
+ x\\_out = new[0] + m(x - old[0])
+
+ where
+
+ .. math::
+ m = \\frac{new[1]-new[0]}{old[1]-old[0]}
+
+ Examples
+ --------
+ >>> from numpy.polynomial import polyutils as pu
+ >>> old_domain = (-1,1)
+ >>> new_domain = (0,2*np.pi)
+ >>> x = np.linspace(-1,1,6); x
+ array([-1. , -0.6, -0.2, 0.2, 0.6, 1. ])
+ >>> x_out = pu.mapdomain(x, old_domain, new_domain); x_out
+ array([ 0. , 1.25663706, 2.51327412, 3.76991118, 5.02654825, # may vary
+ 6.28318531])
+ >>> x - pu.mapdomain(x_out, new_domain, old_domain)
+ array([0., 0., 0., 0., 0., 0.])
+
+ Also works for complex numbers (and thus can be used to map any line in
+ the complex plane to any other line therein).
+
+ >>> i = complex(0,1)
+ >>> old = (-1 - i, 1 + i)
+ >>> new = (-1 + i, 1 - i)
+ >>> z = np.linspace(old[0], old[1], 6); z
+ array([-1. -1.j , -0.6-0.6j, -0.2-0.2j, 0.2+0.2j, 0.6+0.6j, 1. +1.j ])
+ >>> new_z = pu.mapdomain(z, old, new); new_z
+ array([-1.0+1.j , -0.6+0.6j, -0.2+0.2j, 0.2-0.2j, 0.6-0.6j, 1.0-1.j ]) # may vary
+
+ """
+ x = np.asanyarray(x)
+ off, scl = mapparms(old, new)
+ return off + scl*x
+
+
+def _nth_slice(i, ndim):
+ sl = [np.newaxis] * ndim
+ sl[i] = slice(None)
+ return tuple(sl)
+
+
+def _vander_nd(vander_fs, points, degrees):
+ r"""
+ A generalization of the Vandermonde matrix for N dimensions
+
+ The result is built by combining the results of 1d Vandermonde matrices,
+
+ .. math::
+ W[i_0, \ldots, i_M, j_0, \ldots, j_N] = \prod_{k=0}^N{V_k(x_k)[i_0, \ldots, i_M, j_k]}
+
+ where
+
+ .. math::
+ N &= \texttt{len(points)} = \texttt{len(degrees)} = \texttt{len(vander\_fs)} \\
+ M &= \texttt{points[k].ndim} \\
+ V_k &= \texttt{vander\_fs[k]} \\
+ x_k &= \texttt{points[k]} \\
+ 0 \le j_k &\le \texttt{degrees[k]}
+
+ Expanding the one-dimensional :math:`V_k` functions gives:
+
+ .. math::
+ W[i_0, \ldots, i_M, j_0, \ldots, j_N] = \prod_{k=0}^N{B_{k, j_k}(x_k[i_0, \ldots, i_M])}
+
+ where :math:`B_{k,m}` is the m'th basis of the polynomial construction used along
+ dimension :math:`k`. For a regular polynomial, :math:`B_{k, m}(x) = P_m(x) = x^m`.
+
+ Parameters
+ ----------
+ vander_fs : Sequence[function(array_like, int) -> ndarray]
+ The 1d vander function to use for each axis, such as ``polyvander``
+ points : Sequence[array_like]
+ Arrays of point coordinates, all of the same shape. The dtypes
+ will be converted to either float64 or complex128 depending on
+ whether any of the elements are complex. Scalars are converted to
+ 1-D arrays.
+ This must be the same length as `vander_fs`.
+ degrees : Sequence[int]
+ The maximum degree (inclusive) to use for each axis.
+ This must be the same length as `vander_fs`.
+
+ Returns
+ -------
+ vander_nd : ndarray
+ An array of shape ``points[0].shape + tuple(d + 1 for d in degrees)``.
+ """
+ n_dims = len(vander_fs)
+ if n_dims != len(points):
+ raise ValueError(
+ f"Expected {n_dims} dimensions of sample points, got {len(points)}")
+ if n_dims != len(degrees):
+ raise ValueError(
+ f"Expected {n_dims} dimensions of degrees, got {len(degrees)}")
+ if n_dims == 0:
+ raise ValueError("Unable to guess a dtype or shape when no points are given")
+
+ # convert to the same shape and type
+ points = tuple(np.array(tuple(points), copy=False) + 0.0)
+
+ # produce the vandermonde matrix for each dimension, placing the last
+ # axis of each in an independent trailing axis of the output
+ vander_arrays = (
+ vander_fs[i](points[i], degrees[i])[(...,) + _nth_slice(i, n_dims)]
+ for i in range(n_dims)
+ )
+
+ # we checked this wasn't empty already, so no `initial` needed
+ return functools.reduce(operator.mul, vander_arrays)
+
+
+def _vander_nd_flat(vander_fs, points, degrees):
+ """
+ Like `_vander_nd`, but flattens the last ``len(degrees)`` axes into a single axis
+
+ Used to implement the public ``vanderd`` functions.
+ """
+ v = _vander_nd(vander_fs, points, degrees)
+ return v.reshape(v.shape[:-len(degrees)] + (-1,))
+
+
+def _fromroots(line_f, mul_f, roots):
+ """
+ Helper function used to implement the ``fromroots`` functions.
+
+ Parameters
+ ----------
+ line_f : function(float, float) -> ndarray
+ The ``line`` function, such as ``polyline``
+ mul_f : function(array_like, array_like) -> ndarray
+ The ``mul`` function, such as ``polymul``
+ roots
+ See the ``fromroots`` functions for more detail
+ """
+ if len(roots) == 0:
+ return np.ones(1)
+ else:
+ [roots] = as_series([roots], trim=False)
+ roots.sort()
+ p = [line_f(-r, 1) for r in roots]
+ n = len(p)
+ while n > 1:
+ m, r = divmod(n, 2)
+ tmp = [mul_f(p[i], p[i+m]) for i in range(m)]
+ if r:
+ tmp[0] = mul_f(tmp[0], p[-1])
+ p = tmp
+ n = m
+ return p[0]
+
+
+def _valnd(val_f, c, *args):
+ """
+ Helper function used to implement the ``vald`` functions.
+
+ Parameters
+ ----------
+ val_f : function(array_like, array_like, tensor: bool) -> array_like
+ The ``val`` function, such as ``polyval``
+ c, args
+ See the ``vald`` functions for more detail
+ """
+ args = [np.asanyarray(a) for a in args]
+ shape0 = args[0].shape
+ if not all((a.shape == shape0 for a in args[1:])):
+ if len(args) == 3:
+ raise ValueError('x, y, z are incompatible')
+ elif len(args) == 2:
+ raise ValueError('x, y are incompatible')
+ else:
+ raise ValueError('ordinates are incompatible')
+ it = iter(args)
+ x0 = next(it)
+
+ # use tensor on only the first
+ c = val_f(x0, c)
+ for xi in it:
+ c = val_f(xi, c, tensor=False)
+ return c
+
+
+def _gridnd(val_f, c, *args):
+ """
+ Helper function used to implement the ``gridd`` functions.
+
+ Parameters
+ ----------
+ val_f : function(array_like, array_like, tensor: bool) -> array_like
+ The ``val`` function, such as ``polyval``
+ c, args
+ See the ``gridd`` functions for more detail
+ """
+ for xi in args:
+ c = val_f(xi, c)
+ return c
+
+
+def _div(mul_f, c1, c2):
+ """
+ Helper function used to implement the ``div`` functions.
+
+ Implementation uses repeated subtraction of c2 multiplied by the nth basis.
+ For some polynomial types, a more efficient approach may be possible.
+
+ Parameters
+ ----------
+ mul_f : function(array_like, array_like) -> array_like
+ The ``mul`` function, such as ``polymul``
+ c1, c2
+ See the ``div`` functions for more detail
+ """
+ # c1, c2 are trimmed copies
+ [c1, c2] = as_series([c1, c2])
+ if c2[-1] == 0:
+ raise ZeroDivisionError()
+
+ lc1 = len(c1)
+ lc2 = len(c2)
+ if lc1 < lc2:
+ return c1[:1]*0, c1
+ elif lc2 == 1:
+ return c1/c2[-1], c1[:1]*0
+ else:
+ quo = np.empty(lc1 - lc2 + 1, dtype=c1.dtype)
+ rem = c1
+ for i in range(lc1 - lc2, - 1, -1):
+ p = mul_f([0]*i + [1], c2)
+ q = rem[-1]/p[-1]
+ rem = rem[:-1] - q*p[:-1]
+ quo[i] = q
+ return quo, trimseq(rem)
+
+
+def _add(c1, c2):
+ """ Helper function used to implement the ``add`` functions. """
+ # c1, c2 are trimmed copies
+ [c1, c2] = as_series([c1, c2])
+ if len(c1) > len(c2):
+ c1[:c2.size] += c2
+ ret = c1
+ else:
+ c2[:c1.size] += c1
+ ret = c2
+ return trimseq(ret)
+
+
+def _sub(c1, c2):
+ """ Helper function used to implement the ``sub`` functions. """
+ # c1, c2 are trimmed copies
+ [c1, c2] = as_series([c1, c2])
+ if len(c1) > len(c2):
+ c1[:c2.size] -= c2
+ ret = c1
+ else:
+ c2 = -c2
+ c2[:c1.size] += c1
+ ret = c2
+ return trimseq(ret)
+
+
+def _fit(vander_f, x, y, deg, rcond=None, full=False, w=None):
+ """
+ Helper function used to implement the ``fit`` functions.
+
+ Parameters
+ ----------
+ vander_f : function(array_like, int) -> ndarray
+ The 1d vander function, such as ``polyvander``
+ c1, c2
+ See the ``fit`` functions for more detail
+ """
+ x = np.asarray(x) + 0.0
+ y = np.asarray(y) + 0.0
+ deg = np.asarray(deg)
+
+ # check arguments.
+ if deg.ndim > 1 or deg.dtype.kind not in 'iu' or deg.size == 0:
+ raise TypeError("deg must be an int or non-empty 1-D array of int")
+ if deg.min() < 0:
+ raise ValueError("expected deg >= 0")
+ if x.ndim != 1:
+ raise TypeError("expected 1D vector for x")
+ if x.size == 0:
+ raise TypeError("expected non-empty vector for x")
+ if y.ndim < 1 or y.ndim > 2:
+ raise TypeError("expected 1D or 2D array for y")
+ if len(x) != len(y):
+ raise TypeError("expected x and y to have same length")
+
+ if deg.ndim == 0:
+ lmax = deg
+ order = lmax + 1
+ van = vander_f(x, lmax)
+ else:
+ deg = np.sort(deg)
+ lmax = deg[-1]
+ order = len(deg)
+ van = vander_f(x, lmax)[:, deg]
+
+ # set up the least squares matrices in transposed form
+ lhs = van.T
+ rhs = y.T
+ if w is not None:
+ w = np.asarray(w) + 0.0
+ if w.ndim != 1:
+ raise TypeError("expected 1D vector for w")
+ if len(x) != len(w):
+ raise TypeError("expected x and w to have same length")
+ # apply weights. Don't use inplace operations as they
+ # can cause problems with NA.
+ lhs = lhs * w
+ rhs = rhs * w
+
+ # set rcond
+ if rcond is None:
+ rcond = len(x)*np.finfo(x.dtype).eps
+
+ # Determine the norms of the design matrix columns.
+ if issubclass(lhs.dtype.type, np.complexfloating):
+ scl = np.sqrt((np.square(lhs.real) + np.square(lhs.imag)).sum(1))
+ else:
+ scl = np.sqrt(np.square(lhs).sum(1))
+ scl[scl == 0] = 1
+
+ # Solve the least squares problem.
+ c, resids, rank, s = np.linalg.lstsq(lhs.T/scl, rhs.T, rcond)
+ c = (c.T/scl).T
+
+ # Expand c to include non-fitted coefficients which are set to zero
+ if deg.ndim > 0:
+ if c.ndim == 2:
+ cc = np.zeros((lmax+1, c.shape[1]), dtype=c.dtype)
+ else:
+ cc = np.zeros(lmax+1, dtype=c.dtype)
+ cc[deg] = c
+ c = cc
+
+ # warn on rank reduction
+ if rank != order and not full:
+ msg = "The fit may be poorly conditioned"
+ warnings.warn(msg, RankWarning, stacklevel=2)
+
+ if full:
+ return c, [resids, rank, s, rcond]
+ else:
+ return c
+
+
+def _pow(mul_f, c, pow, maxpower):
+ """
+ Helper function used to implement the ``pow`` functions.
+
+ Parameters
+ ----------
+ mul_f : function(array_like, array_like) -> ndarray
+ The ``mul`` function, such as ``polymul``
+ c : array_like
+ 1-D array of array of series coefficients
+ pow, maxpower
+ See the ``pow`` functions for more detail
+ """
+ # c is a trimmed copy
+ [c] = as_series([c])
+ power = int(pow)
+ if power != pow or power < 0:
+ raise ValueError("Power must be a non-negative integer.")
+ elif maxpower is not None and power > maxpower:
+ raise ValueError("Power is too large")
+ elif power == 0:
+ return np.array([1], dtype=c.dtype)
+ elif power == 1:
+ return c
+ else:
+ # This can be made more efficient by using powers of two
+ # in the usual way.
+ prd = c
+ for i in range(2, power + 1):
+ prd = mul_f(prd, c)
+ return prd
+
+
+def _deprecate_as_int(x, desc):
+ """
+ Like `operator.index`, but emits a deprecation warning when passed a float
+
+ Parameters
+ ----------
+ x : int-like, or float with integral value
+ Value to interpret as an integer
+ desc : str
+ description to include in any error message
+
+ Raises
+ ------
+ TypeError : if x is a non-integral float or non-numeric
+ DeprecationWarning : if x is an integral float
+ """
+ try:
+ return operator.index(x)
+ except TypeError as e:
+ # Numpy 1.17.0, 2019-03-11
+ try:
+ ix = int(x)
+ except TypeError:
+ pass
+ else:
+ if ix == x:
+ warnings.warn(
+ f"In future, this will raise TypeError, as {desc} will "
+ "need to be an integer not just an integral float.",
+ DeprecationWarning,
+ stacklevel=3
+ )
+ return ix
+
+ raise TypeError(f"{desc} must be an integer") from e
+
+
+def format_float(x, parens=False):
+ if not np.issubdtype(type(x), np.floating):
+ return str(x)
+
+ opts = np.get_printoptions()
+
+ if np.isnan(x):
+ return opts['nanstr']
+ elif np.isinf(x):
+ return opts['infstr']
+
+ exp_format = False
+ if x != 0:
+ a = absolute(x)
+ if a >= 1.e8 or a < 10**min(0, -(opts['precision']-1)//2):
+ exp_format = True
+
+ trim, unique = '0', True
+ if opts['floatmode'] == 'fixed':
+ trim, unique = 'k', False
+
+ if exp_format:
+ s = dragon4_scientific(x, precision=opts['precision'],
+ unique=unique, trim=trim,
+ sign=opts['sign'] == '+')
+ if parens:
+ s = '(' + s + ')'
+ else:
+ s = dragon4_positional(x, precision=opts['precision'],
+ fractional=True,
+ unique=unique, trim=trim,
+ sign=opts['sign'] == '+')
+ return s
diff --git a/lib/python3.12/site-packages/numpy/polynomial/polyutils.pyi b/lib/python3.12/site-packages/numpy/polynomial/polyutils.pyi
new file mode 100644
index 0000000000000000000000000000000000000000..c0bcc67847f6b466c8d4fcf6f9b323df736c1c5f
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/polyutils.pyi
@@ -0,0 +1,11 @@
+__all__: list[str]
+
+class RankWarning(UserWarning): ...
+
+def trimseq(seq): ...
+def as_series(alist, trim=...): ...
+def trimcoef(c, tol=...): ...
+def getdomain(x): ...
+def mapparms(old, new): ...
+def mapdomain(x, old, new): ...
+def format_float(x, parens=...): ...
diff --git a/lib/python3.12/site-packages/numpy/polynomial/setup.py b/lib/python3.12/site-packages/numpy/polynomial/setup.py
new file mode 100644
index 0000000000000000000000000000000000000000..b58e867a133f804fbaf0d31099258a11e29058aa
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/setup.py
@@ -0,0 +1,10 @@
+def configuration(parent_package='',top_path=None):
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('polynomial', parent_package, top_path)
+ config.add_subpackage('tests')
+ config.add_data_files('*.pyi')
+ return config
+
+if __name__ == '__main__':
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/__init__.py b/lib/python3.12/site-packages/numpy/polynomial/tests/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_classes.cpython-312.pyc b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_classes.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c5cbe356aff4342459b19e07858d86713fb4c310
Binary files /dev/null and b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_classes.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_hermite.cpython-312.pyc b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_hermite.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9151233caaec684242220631dca2f9efa35424a7
Binary files /dev/null and b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_hermite.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_laguerre.cpython-312.pyc b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_laguerre.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6aab650000f1c67ac5ee1264465213aad9da5084
Binary files /dev/null and b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_laguerre.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_legendre.cpython-312.pyc b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_legendre.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d64df9a94bb85290d0e8fba85d9ffb58dc66a402
Binary files /dev/null and b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_legendre.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_polynomial.cpython-312.pyc b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_polynomial.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c7d315be5eadd979c7796c89956fe1c762f264ba
Binary files /dev/null and b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_polynomial.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_polyutils.cpython-312.pyc b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_polyutils.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..94f0fe587b80446a73b9cea7ab65942193a0a3d1
Binary files /dev/null and b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_polyutils.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_printing.cpython-312.pyc b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_printing.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a0bf6db78bf6d5bfe8c81d8ca3c1f9fc73a598fb
Binary files /dev/null and b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_printing.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_symbol.cpython-312.pyc b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_symbol.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3a0bac3e12e3368faabce0e08eaea26cebec878d
Binary files /dev/null and b/lib/python3.12/site-packages/numpy/polynomial/tests/__pycache__/test_symbol.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/test_chebyshev.py b/lib/python3.12/site-packages/numpy/polynomial/tests/test_chebyshev.py
new file mode 100644
index 0000000000000000000000000000000000000000..2f54bebfdb27d54f436378e4ab6d6c8f2426dd90
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/tests/test_chebyshev.py
@@ -0,0 +1,619 @@
+"""Tests for chebyshev module.
+
+"""
+from functools import reduce
+
+import numpy as np
+import numpy.polynomial.chebyshev as cheb
+from numpy.polynomial.polynomial import polyval
+from numpy.testing import (
+ assert_almost_equal, assert_raises, assert_equal, assert_,
+ )
+
+
+def trim(x):
+ return cheb.chebtrim(x, tol=1e-6)
+
+T0 = [1]
+T1 = [0, 1]
+T2 = [-1, 0, 2]
+T3 = [0, -3, 0, 4]
+T4 = [1, 0, -8, 0, 8]
+T5 = [0, 5, 0, -20, 0, 16]
+T6 = [-1, 0, 18, 0, -48, 0, 32]
+T7 = [0, -7, 0, 56, 0, -112, 0, 64]
+T8 = [1, 0, -32, 0, 160, 0, -256, 0, 128]
+T9 = [0, 9, 0, -120, 0, 432, 0, -576, 0, 256]
+
+Tlist = [T0, T1, T2, T3, T4, T5, T6, T7, T8, T9]
+
+
+class TestPrivate:
+
+ def test__cseries_to_zseries(self):
+ for i in range(5):
+ inp = np.array([2] + [1]*i, np.double)
+ tgt = np.array([.5]*i + [2] + [.5]*i, np.double)
+ res = cheb._cseries_to_zseries(inp)
+ assert_equal(res, tgt)
+
+ def test__zseries_to_cseries(self):
+ for i in range(5):
+ inp = np.array([.5]*i + [2] + [.5]*i, np.double)
+ tgt = np.array([2] + [1]*i, np.double)
+ res = cheb._zseries_to_cseries(inp)
+ assert_equal(res, tgt)
+
+
+class TestConstants:
+
+ def test_chebdomain(self):
+ assert_equal(cheb.chebdomain, [-1, 1])
+
+ def test_chebzero(self):
+ assert_equal(cheb.chebzero, [0])
+
+ def test_chebone(self):
+ assert_equal(cheb.chebone, [1])
+
+ def test_chebx(self):
+ assert_equal(cheb.chebx, [0, 1])
+
+
+class TestArithmetic:
+
+ def test_chebadd(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ tgt = np.zeros(max(i, j) + 1)
+ tgt[i] += 1
+ tgt[j] += 1
+ res = cheb.chebadd([0]*i + [1], [0]*j + [1])
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_chebsub(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ tgt = np.zeros(max(i, j) + 1)
+ tgt[i] += 1
+ tgt[j] -= 1
+ res = cheb.chebsub([0]*i + [1], [0]*j + [1])
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_chebmulx(self):
+ assert_equal(cheb.chebmulx([0]), [0])
+ assert_equal(cheb.chebmulx([1]), [0, 1])
+ for i in range(1, 5):
+ ser = [0]*i + [1]
+ tgt = [0]*(i - 1) + [.5, 0, .5]
+ assert_equal(cheb.chebmulx(ser), tgt)
+
+ def test_chebmul(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ tgt = np.zeros(i + j + 1)
+ tgt[i + j] += .5
+ tgt[abs(i - j)] += .5
+ res = cheb.chebmul([0]*i + [1], [0]*j + [1])
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_chebdiv(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ ci = [0]*i + [1]
+ cj = [0]*j + [1]
+ tgt = cheb.chebadd(ci, cj)
+ quo, rem = cheb.chebdiv(tgt, ci)
+ res = cheb.chebadd(cheb.chebmul(quo, ci), rem)
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_chebpow(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ c = np.arange(i + 1)
+ tgt = reduce(cheb.chebmul, [c]*j, np.array([1]))
+ res = cheb.chebpow(c, j)
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+
+class TestEvaluation:
+ # coefficients of 1 + 2*x + 3*x**2
+ c1d = np.array([2.5, 2., 1.5])
+ c2d = np.einsum('i,j->ij', c1d, c1d)
+ c3d = np.einsum('i,j,k->ijk', c1d, c1d, c1d)
+
+ # some random values in [-1, 1)
+ x = np.random.random((3, 5))*2 - 1
+ y = polyval(x, [1., 2., 3.])
+
+ def test_chebval(self):
+ #check empty input
+ assert_equal(cheb.chebval([], [1]).size, 0)
+
+ #check normal input)
+ x = np.linspace(-1, 1)
+ y = [polyval(x, c) for c in Tlist]
+ for i in range(10):
+ msg = f"At i={i}"
+ tgt = y[i]
+ res = cheb.chebval(x, [0]*i + [1])
+ assert_almost_equal(res, tgt, err_msg=msg)
+
+ #check that shape is preserved
+ for i in range(3):
+ dims = [2]*i
+ x = np.zeros(dims)
+ assert_equal(cheb.chebval(x, [1]).shape, dims)
+ assert_equal(cheb.chebval(x, [1, 0]).shape, dims)
+ assert_equal(cheb.chebval(x, [1, 0, 0]).shape, dims)
+
+ def test_chebval2d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test exceptions
+ assert_raises(ValueError, cheb.chebval2d, x1, x2[:2], self.c2d)
+
+ #test values
+ tgt = y1*y2
+ res = cheb.chebval2d(x1, x2, self.c2d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = cheb.chebval2d(z, z, self.c2d)
+ assert_(res.shape == (2, 3))
+
+ def test_chebval3d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test exceptions
+ assert_raises(ValueError, cheb.chebval3d, x1, x2, x3[:2], self.c3d)
+
+ #test values
+ tgt = y1*y2*y3
+ res = cheb.chebval3d(x1, x2, x3, self.c3d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = cheb.chebval3d(z, z, z, self.c3d)
+ assert_(res.shape == (2, 3))
+
+ def test_chebgrid2d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test values
+ tgt = np.einsum('i,j->ij', y1, y2)
+ res = cheb.chebgrid2d(x1, x2, self.c2d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = cheb.chebgrid2d(z, z, self.c2d)
+ assert_(res.shape == (2, 3)*2)
+
+ def test_chebgrid3d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test values
+ tgt = np.einsum('i,j,k->ijk', y1, y2, y3)
+ res = cheb.chebgrid3d(x1, x2, x3, self.c3d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = cheb.chebgrid3d(z, z, z, self.c3d)
+ assert_(res.shape == (2, 3)*3)
+
+
+class TestIntegral:
+
+ def test_chebint(self):
+ # check exceptions
+ assert_raises(TypeError, cheb.chebint, [0], .5)
+ assert_raises(ValueError, cheb.chebint, [0], -1)
+ assert_raises(ValueError, cheb.chebint, [0], 1, [0, 0])
+ assert_raises(ValueError, cheb.chebint, [0], lbnd=[0])
+ assert_raises(ValueError, cheb.chebint, [0], scl=[0])
+ assert_raises(TypeError, cheb.chebint, [0], axis=.5)
+
+ # test integration of zero polynomial
+ for i in range(2, 5):
+ k = [0]*(i - 2) + [1]
+ res = cheb.chebint([0], m=i, k=k)
+ assert_almost_equal(res, [0, 1])
+
+ # check single integration with integration constant
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ tgt = [i] + [0]*i + [1/scl]
+ chebpol = cheb.poly2cheb(pol)
+ chebint = cheb.chebint(chebpol, m=1, k=[i])
+ res = cheb.cheb2poly(chebint)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check single integration with integration constant and lbnd
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ chebpol = cheb.poly2cheb(pol)
+ chebint = cheb.chebint(chebpol, m=1, k=[i], lbnd=-1)
+ assert_almost_equal(cheb.chebval(-1, chebint), i)
+
+ # check single integration with integration constant and scaling
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ tgt = [i] + [0]*i + [2/scl]
+ chebpol = cheb.poly2cheb(pol)
+ chebint = cheb.chebint(chebpol, m=1, k=[i], scl=2)
+ res = cheb.cheb2poly(chebint)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with default k
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = cheb.chebint(tgt, m=1)
+ res = cheb.chebint(pol, m=j)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with defined k
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = cheb.chebint(tgt, m=1, k=[k])
+ res = cheb.chebint(pol, m=j, k=list(range(j)))
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with lbnd
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = cheb.chebint(tgt, m=1, k=[k], lbnd=-1)
+ res = cheb.chebint(pol, m=j, k=list(range(j)), lbnd=-1)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with scaling
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = cheb.chebint(tgt, m=1, k=[k], scl=2)
+ res = cheb.chebint(pol, m=j, k=list(range(j)), scl=2)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_chebint_axis(self):
+ # check that axis keyword works
+ c2d = np.random.random((3, 4))
+
+ tgt = np.vstack([cheb.chebint(c) for c in c2d.T]).T
+ res = cheb.chebint(c2d, axis=0)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([cheb.chebint(c) for c in c2d])
+ res = cheb.chebint(c2d, axis=1)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([cheb.chebint(c, k=3) for c in c2d])
+ res = cheb.chebint(c2d, k=3, axis=1)
+ assert_almost_equal(res, tgt)
+
+
+class TestDerivative:
+
+ def test_chebder(self):
+ # check exceptions
+ assert_raises(TypeError, cheb.chebder, [0], .5)
+ assert_raises(ValueError, cheb.chebder, [0], -1)
+
+ # check that zeroth derivative does nothing
+ for i in range(5):
+ tgt = [0]*i + [1]
+ res = cheb.chebder(tgt, m=0)
+ assert_equal(trim(res), trim(tgt))
+
+ # check that derivation is the inverse of integration
+ for i in range(5):
+ for j in range(2, 5):
+ tgt = [0]*i + [1]
+ res = cheb.chebder(cheb.chebint(tgt, m=j), m=j)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check derivation with scaling
+ for i in range(5):
+ for j in range(2, 5):
+ tgt = [0]*i + [1]
+ res = cheb.chebder(cheb.chebint(tgt, m=j, scl=2), m=j, scl=.5)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_chebder_axis(self):
+ # check that axis keyword works
+ c2d = np.random.random((3, 4))
+
+ tgt = np.vstack([cheb.chebder(c) for c in c2d.T]).T
+ res = cheb.chebder(c2d, axis=0)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([cheb.chebder(c) for c in c2d])
+ res = cheb.chebder(c2d, axis=1)
+ assert_almost_equal(res, tgt)
+
+
+class TestVander:
+ # some random values in [-1, 1)
+ x = np.random.random((3, 5))*2 - 1
+
+ def test_chebvander(self):
+ # check for 1d x
+ x = np.arange(3)
+ v = cheb.chebvander(x, 3)
+ assert_(v.shape == (3, 4))
+ for i in range(4):
+ coef = [0]*i + [1]
+ assert_almost_equal(v[..., i], cheb.chebval(x, coef))
+
+ # check for 2d x
+ x = np.array([[1, 2], [3, 4], [5, 6]])
+ v = cheb.chebvander(x, 3)
+ assert_(v.shape == (3, 2, 4))
+ for i in range(4):
+ coef = [0]*i + [1]
+ assert_almost_equal(v[..., i], cheb.chebval(x, coef))
+
+ def test_chebvander2d(self):
+ # also tests chebval2d for non-square coefficient array
+ x1, x2, x3 = self.x
+ c = np.random.random((2, 3))
+ van = cheb.chebvander2d(x1, x2, [1, 2])
+ tgt = cheb.chebval2d(x1, x2, c)
+ res = np.dot(van, c.flat)
+ assert_almost_equal(res, tgt)
+
+ # check shape
+ van = cheb.chebvander2d([x1], [x2], [1, 2])
+ assert_(van.shape == (1, 5, 6))
+
+ def test_chebvander3d(self):
+ # also tests chebval3d for non-square coefficient array
+ x1, x2, x3 = self.x
+ c = np.random.random((2, 3, 4))
+ van = cheb.chebvander3d(x1, x2, x3, [1, 2, 3])
+ tgt = cheb.chebval3d(x1, x2, x3, c)
+ res = np.dot(van, c.flat)
+ assert_almost_equal(res, tgt)
+
+ # check shape
+ van = cheb.chebvander3d([x1], [x2], [x3], [1, 2, 3])
+ assert_(van.shape == (1, 5, 24))
+
+
+class TestFitting:
+
+ def test_chebfit(self):
+ def f(x):
+ return x*(x - 1)*(x - 2)
+
+ def f2(x):
+ return x**4 + x**2 + 1
+
+ # Test exceptions
+ assert_raises(ValueError, cheb.chebfit, [1], [1], -1)
+ assert_raises(TypeError, cheb.chebfit, [[1]], [1], 0)
+ assert_raises(TypeError, cheb.chebfit, [], [1], 0)
+ assert_raises(TypeError, cheb.chebfit, [1], [[[1]]], 0)
+ assert_raises(TypeError, cheb.chebfit, [1, 2], [1], 0)
+ assert_raises(TypeError, cheb.chebfit, [1], [1, 2], 0)
+ assert_raises(TypeError, cheb.chebfit, [1], [1], 0, w=[[1]])
+ assert_raises(TypeError, cheb.chebfit, [1], [1], 0, w=[1, 1])
+ assert_raises(ValueError, cheb.chebfit, [1], [1], [-1,])
+ assert_raises(ValueError, cheb.chebfit, [1], [1], [2, -1, 6])
+ assert_raises(TypeError, cheb.chebfit, [1], [1], [])
+
+ # Test fit
+ x = np.linspace(0, 2)
+ y = f(x)
+ #
+ coef3 = cheb.chebfit(x, y, 3)
+ assert_equal(len(coef3), 4)
+ assert_almost_equal(cheb.chebval(x, coef3), y)
+ coef3 = cheb.chebfit(x, y, [0, 1, 2, 3])
+ assert_equal(len(coef3), 4)
+ assert_almost_equal(cheb.chebval(x, coef3), y)
+ #
+ coef4 = cheb.chebfit(x, y, 4)
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(cheb.chebval(x, coef4), y)
+ coef4 = cheb.chebfit(x, y, [0, 1, 2, 3, 4])
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(cheb.chebval(x, coef4), y)
+ # check things still work if deg is not in strict increasing
+ coef4 = cheb.chebfit(x, y, [2, 3, 4, 1, 0])
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(cheb.chebval(x, coef4), y)
+ #
+ coef2d = cheb.chebfit(x, np.array([y, y]).T, 3)
+ assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
+ coef2d = cheb.chebfit(x, np.array([y, y]).T, [0, 1, 2, 3])
+ assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
+ # test weighting
+ w = np.zeros_like(x)
+ yw = y.copy()
+ w[1::2] = 1
+ y[0::2] = 0
+ wcoef3 = cheb.chebfit(x, yw, 3, w=w)
+ assert_almost_equal(wcoef3, coef3)
+ wcoef3 = cheb.chebfit(x, yw, [0, 1, 2, 3], w=w)
+ assert_almost_equal(wcoef3, coef3)
+ #
+ wcoef2d = cheb.chebfit(x, np.array([yw, yw]).T, 3, w=w)
+ assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
+ wcoef2d = cheb.chebfit(x, np.array([yw, yw]).T, [0, 1, 2, 3], w=w)
+ assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
+ # test scaling with complex values x points whose square
+ # is zero when summed.
+ x = [1, 1j, -1, -1j]
+ assert_almost_equal(cheb.chebfit(x, x, 1), [0, 1])
+ assert_almost_equal(cheb.chebfit(x, x, [0, 1]), [0, 1])
+ # test fitting only even polynomials
+ x = np.linspace(-1, 1)
+ y = f2(x)
+ coef1 = cheb.chebfit(x, y, 4)
+ assert_almost_equal(cheb.chebval(x, coef1), y)
+ coef2 = cheb.chebfit(x, y, [0, 2, 4])
+ assert_almost_equal(cheb.chebval(x, coef2), y)
+ assert_almost_equal(coef1, coef2)
+
+
+class TestInterpolate:
+
+ def f(self, x):
+ return x * (x - 1) * (x - 2)
+
+ def test_raises(self):
+ assert_raises(ValueError, cheb.chebinterpolate, self.f, -1)
+ assert_raises(TypeError, cheb.chebinterpolate, self.f, 10.)
+
+ def test_dimensions(self):
+ for deg in range(1, 5):
+ assert_(cheb.chebinterpolate(self.f, deg).shape == (deg + 1,))
+
+ def test_approximation(self):
+
+ def powx(x, p):
+ return x**p
+
+ x = np.linspace(-1, 1, 10)
+ for deg in range(0, 10):
+ for p in range(0, deg + 1):
+ c = cheb.chebinterpolate(powx, deg, (p,))
+ assert_almost_equal(cheb.chebval(x, c), powx(x, p), decimal=12)
+
+
+class TestCompanion:
+
+ def test_raises(self):
+ assert_raises(ValueError, cheb.chebcompanion, [])
+ assert_raises(ValueError, cheb.chebcompanion, [1])
+
+ def test_dimensions(self):
+ for i in range(1, 5):
+ coef = [0]*i + [1]
+ assert_(cheb.chebcompanion(coef).shape == (i, i))
+
+ def test_linear_root(self):
+ assert_(cheb.chebcompanion([1, 2])[0, 0] == -.5)
+
+
+class TestGauss:
+
+ def test_100(self):
+ x, w = cheb.chebgauss(100)
+
+ # test orthogonality. Note that the results need to be normalized,
+ # otherwise the huge values that can arise from fast growing
+ # functions like Laguerre can be very confusing.
+ v = cheb.chebvander(x, 99)
+ vv = np.dot(v.T * w, v)
+ vd = 1/np.sqrt(vv.diagonal())
+ vv = vd[:, None] * vv * vd
+ assert_almost_equal(vv, np.eye(100))
+
+ # check that the integral of 1 is correct
+ tgt = np.pi
+ assert_almost_equal(w.sum(), tgt)
+
+
+class TestMisc:
+
+ def test_chebfromroots(self):
+ res = cheb.chebfromroots([])
+ assert_almost_equal(trim(res), [1])
+ for i in range(1, 5):
+ roots = np.cos(np.linspace(-np.pi, 0, 2*i + 1)[1::2])
+ tgt = [0]*i + [1]
+ res = cheb.chebfromroots(roots)*2**(i-1)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_chebroots(self):
+ assert_almost_equal(cheb.chebroots([1]), [])
+ assert_almost_equal(cheb.chebroots([1, 2]), [-.5])
+ for i in range(2, 5):
+ tgt = np.linspace(-1, 1, i)
+ res = cheb.chebroots(cheb.chebfromroots(tgt))
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_chebtrim(self):
+ coef = [2, -1, 1, 0]
+
+ # Test exceptions
+ assert_raises(ValueError, cheb.chebtrim, coef, -1)
+
+ # Test results
+ assert_equal(cheb.chebtrim(coef), coef[:-1])
+ assert_equal(cheb.chebtrim(coef, 1), coef[:-3])
+ assert_equal(cheb.chebtrim(coef, 2), [0])
+
+ def test_chebline(self):
+ assert_equal(cheb.chebline(3, 4), [3, 4])
+
+ def test_cheb2poly(self):
+ for i in range(10):
+ assert_almost_equal(cheb.cheb2poly([0]*i + [1]), Tlist[i])
+
+ def test_poly2cheb(self):
+ for i in range(10):
+ assert_almost_equal(cheb.poly2cheb(Tlist[i]), [0]*i + [1])
+
+ def test_weight(self):
+ x = np.linspace(-1, 1, 11)[1:-1]
+ tgt = 1./(np.sqrt(1 + x) * np.sqrt(1 - x))
+ res = cheb.chebweight(x)
+ assert_almost_equal(res, tgt)
+
+ def test_chebpts1(self):
+ #test exceptions
+ assert_raises(ValueError, cheb.chebpts1, 1.5)
+ assert_raises(ValueError, cheb.chebpts1, 0)
+
+ #test points
+ tgt = [0]
+ assert_almost_equal(cheb.chebpts1(1), tgt)
+ tgt = [-0.70710678118654746, 0.70710678118654746]
+ assert_almost_equal(cheb.chebpts1(2), tgt)
+ tgt = [-0.86602540378443871, 0, 0.86602540378443871]
+ assert_almost_equal(cheb.chebpts1(3), tgt)
+ tgt = [-0.9238795325, -0.3826834323, 0.3826834323, 0.9238795325]
+ assert_almost_equal(cheb.chebpts1(4), tgt)
+
+ def test_chebpts2(self):
+ #test exceptions
+ assert_raises(ValueError, cheb.chebpts2, 1.5)
+ assert_raises(ValueError, cheb.chebpts2, 1)
+
+ #test points
+ tgt = [-1, 1]
+ assert_almost_equal(cheb.chebpts2(2), tgt)
+ tgt = [-1, 0, 1]
+ assert_almost_equal(cheb.chebpts2(3), tgt)
+ tgt = [-1, -0.5, .5, 1]
+ assert_almost_equal(cheb.chebpts2(4), tgt)
+ tgt = [-1.0, -0.707106781187, 0, 0.707106781187, 1.0]
+ assert_almost_equal(cheb.chebpts2(5), tgt)
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/test_classes.py b/lib/python3.12/site-packages/numpy/polynomial/tests/test_classes.py
new file mode 100644
index 0000000000000000000000000000000000000000..6322062f29ece2f52754ac7aedf2591b3a983709
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/tests/test_classes.py
@@ -0,0 +1,600 @@
+"""Test inter-conversion of different polynomial classes.
+
+This tests the convert and cast methods of all the polynomial classes.
+
+"""
+import operator as op
+from numbers import Number
+
+import pytest
+import numpy as np
+from numpy.polynomial import (
+ Polynomial, Legendre, Chebyshev, Laguerre, Hermite, HermiteE)
+from numpy.testing import (
+ assert_almost_equal, assert_raises, assert_equal, assert_,
+ )
+from numpy.polynomial.polyutils import RankWarning
+
+#
+# fixtures
+#
+
+classes = (
+ Polynomial, Legendre, Chebyshev, Laguerre,
+ Hermite, HermiteE
+ )
+classids = tuple(cls.__name__ for cls in classes)
+
+@pytest.fixture(params=classes, ids=classids)
+def Poly(request):
+ return request.param
+
+#
+# helper functions
+#
+random = np.random.random
+
+
+def assert_poly_almost_equal(p1, p2, msg=""):
+ try:
+ assert_(np.all(p1.domain == p2.domain))
+ assert_(np.all(p1.window == p2.window))
+ assert_almost_equal(p1.coef, p2.coef)
+ except AssertionError:
+ msg = f"Result: {p1}\nTarget: {p2}"
+ raise AssertionError(msg)
+
+
+#
+# Test conversion methods that depend on combinations of two classes.
+#
+
+Poly1 = Poly
+Poly2 = Poly
+
+
+def test_conversion(Poly1, Poly2):
+ x = np.linspace(0, 1, 10)
+ coef = random((3,))
+
+ d1 = Poly1.domain + random((2,))*.25
+ w1 = Poly1.window + random((2,))*.25
+ p1 = Poly1(coef, domain=d1, window=w1)
+
+ d2 = Poly2.domain + random((2,))*.25
+ w2 = Poly2.window + random((2,))*.25
+ p2 = p1.convert(kind=Poly2, domain=d2, window=w2)
+
+ assert_almost_equal(p2.domain, d2)
+ assert_almost_equal(p2.window, w2)
+ assert_almost_equal(p2(x), p1(x))
+
+
+def test_cast(Poly1, Poly2):
+ x = np.linspace(0, 1, 10)
+ coef = random((3,))
+
+ d1 = Poly1.domain + random((2,))*.25
+ w1 = Poly1.window + random((2,))*.25
+ p1 = Poly1(coef, domain=d1, window=w1)
+
+ d2 = Poly2.domain + random((2,))*.25
+ w2 = Poly2.window + random((2,))*.25
+ p2 = Poly2.cast(p1, domain=d2, window=w2)
+
+ assert_almost_equal(p2.domain, d2)
+ assert_almost_equal(p2.window, w2)
+ assert_almost_equal(p2(x), p1(x))
+
+
+#
+# test methods that depend on one class
+#
+
+
+def test_identity(Poly):
+ d = Poly.domain + random((2,))*.25
+ w = Poly.window + random((2,))*.25
+ x = np.linspace(d[0], d[1], 11)
+ p = Poly.identity(domain=d, window=w)
+ assert_equal(p.domain, d)
+ assert_equal(p.window, w)
+ assert_almost_equal(p(x), x)
+
+
+def test_basis(Poly):
+ d = Poly.domain + random((2,))*.25
+ w = Poly.window + random((2,))*.25
+ p = Poly.basis(5, domain=d, window=w)
+ assert_equal(p.domain, d)
+ assert_equal(p.window, w)
+ assert_equal(p.coef, [0]*5 + [1])
+
+
+def test_fromroots(Poly):
+ # check that requested roots are zeros of a polynomial
+ # of correct degree, domain, and window.
+ d = Poly.domain + random((2,))*.25
+ w = Poly.window + random((2,))*.25
+ r = random((5,))
+ p1 = Poly.fromroots(r, domain=d, window=w)
+ assert_equal(p1.degree(), len(r))
+ assert_equal(p1.domain, d)
+ assert_equal(p1.window, w)
+ assert_almost_equal(p1(r), 0)
+
+ # check that polynomial is monic
+ pdom = Polynomial.domain
+ pwin = Polynomial.window
+ p2 = Polynomial.cast(p1, domain=pdom, window=pwin)
+ assert_almost_equal(p2.coef[-1], 1)
+
+
+def test_bad_conditioned_fit(Poly):
+
+ x = [0., 0., 1.]
+ y = [1., 2., 3.]
+
+ # check RankWarning is raised
+ with pytest.warns(RankWarning) as record:
+ Poly.fit(x, y, 2)
+ assert record[0].message.args[0] == "The fit may be poorly conditioned"
+
+
+def test_fit(Poly):
+
+ def f(x):
+ return x*(x - 1)*(x - 2)
+ x = np.linspace(0, 3)
+ y = f(x)
+
+ # check default value of domain and window
+ p = Poly.fit(x, y, 3)
+ assert_almost_equal(p.domain, [0, 3])
+ assert_almost_equal(p(x), y)
+ assert_equal(p.degree(), 3)
+
+ # check with given domains and window
+ d = Poly.domain + random((2,))*.25
+ w = Poly.window + random((2,))*.25
+ p = Poly.fit(x, y, 3, domain=d, window=w)
+ assert_almost_equal(p(x), y)
+ assert_almost_equal(p.domain, d)
+ assert_almost_equal(p.window, w)
+ p = Poly.fit(x, y, [0, 1, 2, 3], domain=d, window=w)
+ assert_almost_equal(p(x), y)
+ assert_almost_equal(p.domain, d)
+ assert_almost_equal(p.window, w)
+
+ # check with class domain default
+ p = Poly.fit(x, y, 3, [])
+ assert_equal(p.domain, Poly.domain)
+ assert_equal(p.window, Poly.window)
+ p = Poly.fit(x, y, [0, 1, 2, 3], [])
+ assert_equal(p.domain, Poly.domain)
+ assert_equal(p.window, Poly.window)
+
+ # check that fit accepts weights.
+ w = np.zeros_like(x)
+ z = y + random(y.shape)*.25
+ w[::2] = 1
+ p1 = Poly.fit(x[::2], z[::2], 3)
+ p2 = Poly.fit(x, z, 3, w=w)
+ p3 = Poly.fit(x, z, [0, 1, 2, 3], w=w)
+ assert_almost_equal(p1(x), p2(x))
+ assert_almost_equal(p2(x), p3(x))
+
+
+def test_equal(Poly):
+ p1 = Poly([1, 2, 3], domain=[0, 1], window=[2, 3])
+ p2 = Poly([1, 1, 1], domain=[0, 1], window=[2, 3])
+ p3 = Poly([1, 2, 3], domain=[1, 2], window=[2, 3])
+ p4 = Poly([1, 2, 3], domain=[0, 1], window=[1, 2])
+ assert_(p1 == p1)
+ assert_(not p1 == p2)
+ assert_(not p1 == p3)
+ assert_(not p1 == p4)
+
+
+def test_not_equal(Poly):
+ p1 = Poly([1, 2, 3], domain=[0, 1], window=[2, 3])
+ p2 = Poly([1, 1, 1], domain=[0, 1], window=[2, 3])
+ p3 = Poly([1, 2, 3], domain=[1, 2], window=[2, 3])
+ p4 = Poly([1, 2, 3], domain=[0, 1], window=[1, 2])
+ assert_(not p1 != p1)
+ assert_(p1 != p2)
+ assert_(p1 != p3)
+ assert_(p1 != p4)
+
+
+def test_add(Poly):
+ # This checks commutation, not numerical correctness
+ c1 = list(random((4,)) + .5)
+ c2 = list(random((3,)) + .5)
+ p1 = Poly(c1)
+ p2 = Poly(c2)
+ p3 = p1 + p2
+ assert_poly_almost_equal(p2 + p1, p3)
+ assert_poly_almost_equal(p1 + c2, p3)
+ assert_poly_almost_equal(c2 + p1, p3)
+ assert_poly_almost_equal(p1 + tuple(c2), p3)
+ assert_poly_almost_equal(tuple(c2) + p1, p3)
+ assert_poly_almost_equal(p1 + np.array(c2), p3)
+ assert_poly_almost_equal(np.array(c2) + p1, p3)
+ assert_raises(TypeError, op.add, p1, Poly([0], domain=Poly.domain + 1))
+ assert_raises(TypeError, op.add, p1, Poly([0], window=Poly.window + 1))
+ if Poly is Polynomial:
+ assert_raises(TypeError, op.add, p1, Chebyshev([0]))
+ else:
+ assert_raises(TypeError, op.add, p1, Polynomial([0]))
+
+
+def test_sub(Poly):
+ # This checks commutation, not numerical correctness
+ c1 = list(random((4,)) + .5)
+ c2 = list(random((3,)) + .5)
+ p1 = Poly(c1)
+ p2 = Poly(c2)
+ p3 = p1 - p2
+ assert_poly_almost_equal(p2 - p1, -p3)
+ assert_poly_almost_equal(p1 - c2, p3)
+ assert_poly_almost_equal(c2 - p1, -p3)
+ assert_poly_almost_equal(p1 - tuple(c2), p3)
+ assert_poly_almost_equal(tuple(c2) - p1, -p3)
+ assert_poly_almost_equal(p1 - np.array(c2), p3)
+ assert_poly_almost_equal(np.array(c2) - p1, -p3)
+ assert_raises(TypeError, op.sub, p1, Poly([0], domain=Poly.domain + 1))
+ assert_raises(TypeError, op.sub, p1, Poly([0], window=Poly.window + 1))
+ if Poly is Polynomial:
+ assert_raises(TypeError, op.sub, p1, Chebyshev([0]))
+ else:
+ assert_raises(TypeError, op.sub, p1, Polynomial([0]))
+
+
+def test_mul(Poly):
+ c1 = list(random((4,)) + .5)
+ c2 = list(random((3,)) + .5)
+ p1 = Poly(c1)
+ p2 = Poly(c2)
+ p3 = p1 * p2
+ assert_poly_almost_equal(p2 * p1, p3)
+ assert_poly_almost_equal(p1 * c2, p3)
+ assert_poly_almost_equal(c2 * p1, p3)
+ assert_poly_almost_equal(p1 * tuple(c2), p3)
+ assert_poly_almost_equal(tuple(c2) * p1, p3)
+ assert_poly_almost_equal(p1 * np.array(c2), p3)
+ assert_poly_almost_equal(np.array(c2) * p1, p3)
+ assert_poly_almost_equal(p1 * 2, p1 * Poly([2]))
+ assert_poly_almost_equal(2 * p1, p1 * Poly([2]))
+ assert_raises(TypeError, op.mul, p1, Poly([0], domain=Poly.domain + 1))
+ assert_raises(TypeError, op.mul, p1, Poly([0], window=Poly.window + 1))
+ if Poly is Polynomial:
+ assert_raises(TypeError, op.mul, p1, Chebyshev([0]))
+ else:
+ assert_raises(TypeError, op.mul, p1, Polynomial([0]))
+
+
+def test_floordiv(Poly):
+ c1 = list(random((4,)) + .5)
+ c2 = list(random((3,)) + .5)
+ c3 = list(random((2,)) + .5)
+ p1 = Poly(c1)
+ p2 = Poly(c2)
+ p3 = Poly(c3)
+ p4 = p1 * p2 + p3
+ c4 = list(p4.coef)
+ assert_poly_almost_equal(p4 // p2, p1)
+ assert_poly_almost_equal(p4 // c2, p1)
+ assert_poly_almost_equal(c4 // p2, p1)
+ assert_poly_almost_equal(p4 // tuple(c2), p1)
+ assert_poly_almost_equal(tuple(c4) // p2, p1)
+ assert_poly_almost_equal(p4 // np.array(c2), p1)
+ assert_poly_almost_equal(np.array(c4) // p2, p1)
+ assert_poly_almost_equal(2 // p2, Poly([0]))
+ assert_poly_almost_equal(p2 // 2, 0.5*p2)
+ assert_raises(
+ TypeError, op.floordiv, p1, Poly([0], domain=Poly.domain + 1))
+ assert_raises(
+ TypeError, op.floordiv, p1, Poly([0], window=Poly.window + 1))
+ if Poly is Polynomial:
+ assert_raises(TypeError, op.floordiv, p1, Chebyshev([0]))
+ else:
+ assert_raises(TypeError, op.floordiv, p1, Polynomial([0]))
+
+
+def test_truediv(Poly):
+ # true division is valid only if the denominator is a Number and
+ # not a python bool.
+ p1 = Poly([1,2,3])
+ p2 = p1 * 5
+
+ for stype in np.ScalarType:
+ if not issubclass(stype, Number) or issubclass(stype, bool):
+ continue
+ s = stype(5)
+ assert_poly_almost_equal(op.truediv(p2, s), p1)
+ assert_raises(TypeError, op.truediv, s, p2)
+ for stype in (int, float):
+ s = stype(5)
+ assert_poly_almost_equal(op.truediv(p2, s), p1)
+ assert_raises(TypeError, op.truediv, s, p2)
+ for stype in [complex]:
+ s = stype(5, 0)
+ assert_poly_almost_equal(op.truediv(p2, s), p1)
+ assert_raises(TypeError, op.truediv, s, p2)
+ for s in [tuple(), list(), dict(), bool(), np.array([1])]:
+ assert_raises(TypeError, op.truediv, p2, s)
+ assert_raises(TypeError, op.truediv, s, p2)
+ for ptype in classes:
+ assert_raises(TypeError, op.truediv, p2, ptype(1))
+
+
+def test_mod(Poly):
+ # This checks commutation, not numerical correctness
+ c1 = list(random((4,)) + .5)
+ c2 = list(random((3,)) + .5)
+ c3 = list(random((2,)) + .5)
+ p1 = Poly(c1)
+ p2 = Poly(c2)
+ p3 = Poly(c3)
+ p4 = p1 * p2 + p3
+ c4 = list(p4.coef)
+ assert_poly_almost_equal(p4 % p2, p3)
+ assert_poly_almost_equal(p4 % c2, p3)
+ assert_poly_almost_equal(c4 % p2, p3)
+ assert_poly_almost_equal(p4 % tuple(c2), p3)
+ assert_poly_almost_equal(tuple(c4) % p2, p3)
+ assert_poly_almost_equal(p4 % np.array(c2), p3)
+ assert_poly_almost_equal(np.array(c4) % p2, p3)
+ assert_poly_almost_equal(2 % p2, Poly([2]))
+ assert_poly_almost_equal(p2 % 2, Poly([0]))
+ assert_raises(TypeError, op.mod, p1, Poly([0], domain=Poly.domain + 1))
+ assert_raises(TypeError, op.mod, p1, Poly([0], window=Poly.window + 1))
+ if Poly is Polynomial:
+ assert_raises(TypeError, op.mod, p1, Chebyshev([0]))
+ else:
+ assert_raises(TypeError, op.mod, p1, Polynomial([0]))
+
+
+def test_divmod(Poly):
+ # This checks commutation, not numerical correctness
+ c1 = list(random((4,)) + .5)
+ c2 = list(random((3,)) + .5)
+ c3 = list(random((2,)) + .5)
+ p1 = Poly(c1)
+ p2 = Poly(c2)
+ p3 = Poly(c3)
+ p4 = p1 * p2 + p3
+ c4 = list(p4.coef)
+ quo, rem = divmod(p4, p2)
+ assert_poly_almost_equal(quo, p1)
+ assert_poly_almost_equal(rem, p3)
+ quo, rem = divmod(p4, c2)
+ assert_poly_almost_equal(quo, p1)
+ assert_poly_almost_equal(rem, p3)
+ quo, rem = divmod(c4, p2)
+ assert_poly_almost_equal(quo, p1)
+ assert_poly_almost_equal(rem, p3)
+ quo, rem = divmod(p4, tuple(c2))
+ assert_poly_almost_equal(quo, p1)
+ assert_poly_almost_equal(rem, p3)
+ quo, rem = divmod(tuple(c4), p2)
+ assert_poly_almost_equal(quo, p1)
+ assert_poly_almost_equal(rem, p3)
+ quo, rem = divmod(p4, np.array(c2))
+ assert_poly_almost_equal(quo, p1)
+ assert_poly_almost_equal(rem, p3)
+ quo, rem = divmod(np.array(c4), p2)
+ assert_poly_almost_equal(quo, p1)
+ assert_poly_almost_equal(rem, p3)
+ quo, rem = divmod(p2, 2)
+ assert_poly_almost_equal(quo, 0.5*p2)
+ assert_poly_almost_equal(rem, Poly([0]))
+ quo, rem = divmod(2, p2)
+ assert_poly_almost_equal(quo, Poly([0]))
+ assert_poly_almost_equal(rem, Poly([2]))
+ assert_raises(TypeError, divmod, p1, Poly([0], domain=Poly.domain + 1))
+ assert_raises(TypeError, divmod, p1, Poly([0], window=Poly.window + 1))
+ if Poly is Polynomial:
+ assert_raises(TypeError, divmod, p1, Chebyshev([0]))
+ else:
+ assert_raises(TypeError, divmod, p1, Polynomial([0]))
+
+
+def test_roots(Poly):
+ d = Poly.domain * 1.25 + .25
+ w = Poly.window
+ tgt = np.linspace(d[0], d[1], 5)
+ res = np.sort(Poly.fromroots(tgt, domain=d, window=w).roots())
+ assert_almost_equal(res, tgt)
+ # default domain and window
+ res = np.sort(Poly.fromroots(tgt).roots())
+ assert_almost_equal(res, tgt)
+
+
+def test_degree(Poly):
+ p = Poly.basis(5)
+ assert_equal(p.degree(), 5)
+
+
+def test_copy(Poly):
+ p1 = Poly.basis(5)
+ p2 = p1.copy()
+ assert_(p1 == p2)
+ assert_(p1 is not p2)
+ assert_(p1.coef is not p2.coef)
+ assert_(p1.domain is not p2.domain)
+ assert_(p1.window is not p2.window)
+
+
+def test_integ(Poly):
+ P = Polynomial
+ # Check defaults
+ p0 = Poly.cast(P([1*2, 2*3, 3*4]))
+ p1 = P.cast(p0.integ())
+ p2 = P.cast(p0.integ(2))
+ assert_poly_almost_equal(p1, P([0, 2, 3, 4]))
+ assert_poly_almost_equal(p2, P([0, 0, 1, 1, 1]))
+ # Check with k
+ p0 = Poly.cast(P([1*2, 2*3, 3*4]))
+ p1 = P.cast(p0.integ(k=1))
+ p2 = P.cast(p0.integ(2, k=[1, 1]))
+ assert_poly_almost_equal(p1, P([1, 2, 3, 4]))
+ assert_poly_almost_equal(p2, P([1, 1, 1, 1, 1]))
+ # Check with lbnd
+ p0 = Poly.cast(P([1*2, 2*3, 3*4]))
+ p1 = P.cast(p0.integ(lbnd=1))
+ p2 = P.cast(p0.integ(2, lbnd=1))
+ assert_poly_almost_equal(p1, P([-9, 2, 3, 4]))
+ assert_poly_almost_equal(p2, P([6, -9, 1, 1, 1]))
+ # Check scaling
+ d = 2*Poly.domain
+ p0 = Poly.cast(P([1*2, 2*3, 3*4]), domain=d)
+ p1 = P.cast(p0.integ())
+ p2 = P.cast(p0.integ(2))
+ assert_poly_almost_equal(p1, P([0, 2, 3, 4]))
+ assert_poly_almost_equal(p2, P([0, 0, 1, 1, 1]))
+
+
+def test_deriv(Poly):
+ # Check that the derivative is the inverse of integration. It is
+ # assumes that the integration has been checked elsewhere.
+ d = Poly.domain + random((2,))*.25
+ w = Poly.window + random((2,))*.25
+ p1 = Poly([1, 2, 3], domain=d, window=w)
+ p2 = p1.integ(2, k=[1, 2])
+ p3 = p1.integ(1, k=[1])
+ assert_almost_equal(p2.deriv(1).coef, p3.coef)
+ assert_almost_equal(p2.deriv(2).coef, p1.coef)
+ # default domain and window
+ p1 = Poly([1, 2, 3])
+ p2 = p1.integ(2, k=[1, 2])
+ p3 = p1.integ(1, k=[1])
+ assert_almost_equal(p2.deriv(1).coef, p3.coef)
+ assert_almost_equal(p2.deriv(2).coef, p1.coef)
+
+
+def test_linspace(Poly):
+ d = Poly.domain + random((2,))*.25
+ w = Poly.window + random((2,))*.25
+ p = Poly([1, 2, 3], domain=d, window=w)
+ # check default domain
+ xtgt = np.linspace(d[0], d[1], 20)
+ ytgt = p(xtgt)
+ xres, yres = p.linspace(20)
+ assert_almost_equal(xres, xtgt)
+ assert_almost_equal(yres, ytgt)
+ # check specified domain
+ xtgt = np.linspace(0, 2, 20)
+ ytgt = p(xtgt)
+ xres, yres = p.linspace(20, domain=[0, 2])
+ assert_almost_equal(xres, xtgt)
+ assert_almost_equal(yres, ytgt)
+
+
+def test_pow(Poly):
+ d = Poly.domain + random((2,))*.25
+ w = Poly.window + random((2,))*.25
+ tgt = Poly([1], domain=d, window=w)
+ tst = Poly([1, 2, 3], domain=d, window=w)
+ for i in range(5):
+ assert_poly_almost_equal(tst**i, tgt)
+ tgt = tgt * tst
+ # default domain and window
+ tgt = Poly([1])
+ tst = Poly([1, 2, 3])
+ for i in range(5):
+ assert_poly_almost_equal(tst**i, tgt)
+ tgt = tgt * tst
+ # check error for invalid powers
+ assert_raises(ValueError, op.pow, tgt, 1.5)
+ assert_raises(ValueError, op.pow, tgt, -1)
+
+
+def test_call(Poly):
+ P = Polynomial
+ d = Poly.domain
+ x = np.linspace(d[0], d[1], 11)
+
+ # Check defaults
+ p = Poly.cast(P([1, 2, 3]))
+ tgt = 1 + x*(2 + 3*x)
+ res = p(x)
+ assert_almost_equal(res, tgt)
+
+
+def test_cutdeg(Poly):
+ p = Poly([1, 2, 3])
+ assert_raises(ValueError, p.cutdeg, .5)
+ assert_raises(ValueError, p.cutdeg, -1)
+ assert_equal(len(p.cutdeg(3)), 3)
+ assert_equal(len(p.cutdeg(2)), 3)
+ assert_equal(len(p.cutdeg(1)), 2)
+ assert_equal(len(p.cutdeg(0)), 1)
+
+
+def test_truncate(Poly):
+ p = Poly([1, 2, 3])
+ assert_raises(ValueError, p.truncate, .5)
+ assert_raises(ValueError, p.truncate, 0)
+ assert_equal(len(p.truncate(4)), 3)
+ assert_equal(len(p.truncate(3)), 3)
+ assert_equal(len(p.truncate(2)), 2)
+ assert_equal(len(p.truncate(1)), 1)
+
+
+def test_trim(Poly):
+ c = [1, 1e-6, 1e-12, 0]
+ p = Poly(c)
+ assert_equal(p.trim().coef, c[:3])
+ assert_equal(p.trim(1e-10).coef, c[:2])
+ assert_equal(p.trim(1e-5).coef, c[:1])
+
+
+def test_mapparms(Poly):
+ # check with defaults. Should be identity.
+ d = Poly.domain
+ w = Poly.window
+ p = Poly([1], domain=d, window=w)
+ assert_almost_equal([0, 1], p.mapparms())
+ #
+ w = 2*d + 1
+ p = Poly([1], domain=d, window=w)
+ assert_almost_equal([1, 2], p.mapparms())
+
+
+def test_ufunc_override(Poly):
+ p = Poly([1, 2, 3])
+ x = np.ones(3)
+ assert_raises(TypeError, np.add, p, x)
+ assert_raises(TypeError, np.add, x, p)
+
+
+#
+# Test class method that only exists for some classes
+#
+
+
+class TestInterpolate:
+
+ def f(self, x):
+ return x * (x - 1) * (x - 2)
+
+ def test_raises(self):
+ assert_raises(ValueError, Chebyshev.interpolate, self.f, -1)
+ assert_raises(TypeError, Chebyshev.interpolate, self.f, 10.)
+
+ def test_dimensions(self):
+ for deg in range(1, 5):
+ assert_(Chebyshev.interpolate(self.f, deg).degree() == deg)
+
+ def test_approximation(self):
+
+ def powx(x, p):
+ return x**p
+
+ x = np.linspace(0, 2, 10)
+ for deg in range(0, 10):
+ for t in range(0, deg + 1):
+ p = Chebyshev.interpolate(powx, deg, domain=[0, 2], args=(t,))
+ assert_almost_equal(p(x), powx(x, t), decimal=11)
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/test_hermite.py b/lib/python3.12/site-packages/numpy/polynomial/tests/test_hermite.py
new file mode 100644
index 0000000000000000000000000000000000000000..53ee0844e3c58456807bfd7828bdb9cf58f8ed76
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/tests/test_hermite.py
@@ -0,0 +1,555 @@
+"""Tests for hermite module.
+
+"""
+from functools import reduce
+
+import numpy as np
+import numpy.polynomial.hermite as herm
+from numpy.polynomial.polynomial import polyval
+from numpy.testing import (
+ assert_almost_equal, assert_raises, assert_equal, assert_,
+ )
+
+H0 = np.array([1])
+H1 = np.array([0, 2])
+H2 = np.array([-2, 0, 4])
+H3 = np.array([0, -12, 0, 8])
+H4 = np.array([12, 0, -48, 0, 16])
+H5 = np.array([0, 120, 0, -160, 0, 32])
+H6 = np.array([-120, 0, 720, 0, -480, 0, 64])
+H7 = np.array([0, -1680, 0, 3360, 0, -1344, 0, 128])
+H8 = np.array([1680, 0, -13440, 0, 13440, 0, -3584, 0, 256])
+H9 = np.array([0, 30240, 0, -80640, 0, 48384, 0, -9216, 0, 512])
+
+Hlist = [H0, H1, H2, H3, H4, H5, H6, H7, H8, H9]
+
+
+def trim(x):
+ return herm.hermtrim(x, tol=1e-6)
+
+
+class TestConstants:
+
+ def test_hermdomain(self):
+ assert_equal(herm.hermdomain, [-1, 1])
+
+ def test_hermzero(self):
+ assert_equal(herm.hermzero, [0])
+
+ def test_hermone(self):
+ assert_equal(herm.hermone, [1])
+
+ def test_hermx(self):
+ assert_equal(herm.hermx, [0, .5])
+
+
+class TestArithmetic:
+ x = np.linspace(-3, 3, 100)
+
+ def test_hermadd(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ tgt = np.zeros(max(i, j) + 1)
+ tgt[i] += 1
+ tgt[j] += 1
+ res = herm.hermadd([0]*i + [1], [0]*j + [1])
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_hermsub(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ tgt = np.zeros(max(i, j) + 1)
+ tgt[i] += 1
+ tgt[j] -= 1
+ res = herm.hermsub([0]*i + [1], [0]*j + [1])
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_hermmulx(self):
+ assert_equal(herm.hermmulx([0]), [0])
+ assert_equal(herm.hermmulx([1]), [0, .5])
+ for i in range(1, 5):
+ ser = [0]*i + [1]
+ tgt = [0]*(i - 1) + [i, 0, .5]
+ assert_equal(herm.hermmulx(ser), tgt)
+
+ def test_hermmul(self):
+ # check values of result
+ for i in range(5):
+ pol1 = [0]*i + [1]
+ val1 = herm.hermval(self.x, pol1)
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ pol2 = [0]*j + [1]
+ val2 = herm.hermval(self.x, pol2)
+ pol3 = herm.hermmul(pol1, pol2)
+ val3 = herm.hermval(self.x, pol3)
+ assert_(len(pol3) == i + j + 1, msg)
+ assert_almost_equal(val3, val1*val2, err_msg=msg)
+
+ def test_hermdiv(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ ci = [0]*i + [1]
+ cj = [0]*j + [1]
+ tgt = herm.hermadd(ci, cj)
+ quo, rem = herm.hermdiv(tgt, ci)
+ res = herm.hermadd(herm.hermmul(quo, ci), rem)
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_hermpow(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ c = np.arange(i + 1)
+ tgt = reduce(herm.hermmul, [c]*j, np.array([1]))
+ res = herm.hermpow(c, j)
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+
+class TestEvaluation:
+ # coefficients of 1 + 2*x + 3*x**2
+ c1d = np.array([2.5, 1., .75])
+ c2d = np.einsum('i,j->ij', c1d, c1d)
+ c3d = np.einsum('i,j,k->ijk', c1d, c1d, c1d)
+
+ # some random values in [-1, 1)
+ x = np.random.random((3, 5))*2 - 1
+ y = polyval(x, [1., 2., 3.])
+
+ def test_hermval(self):
+ #check empty input
+ assert_equal(herm.hermval([], [1]).size, 0)
+
+ #check normal input)
+ x = np.linspace(-1, 1)
+ y = [polyval(x, c) for c in Hlist]
+ for i in range(10):
+ msg = f"At i={i}"
+ tgt = y[i]
+ res = herm.hermval(x, [0]*i + [1])
+ assert_almost_equal(res, tgt, err_msg=msg)
+
+ #check that shape is preserved
+ for i in range(3):
+ dims = [2]*i
+ x = np.zeros(dims)
+ assert_equal(herm.hermval(x, [1]).shape, dims)
+ assert_equal(herm.hermval(x, [1, 0]).shape, dims)
+ assert_equal(herm.hermval(x, [1, 0, 0]).shape, dims)
+
+ def test_hermval2d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test exceptions
+ assert_raises(ValueError, herm.hermval2d, x1, x2[:2], self.c2d)
+
+ #test values
+ tgt = y1*y2
+ res = herm.hermval2d(x1, x2, self.c2d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = herm.hermval2d(z, z, self.c2d)
+ assert_(res.shape == (2, 3))
+
+ def test_hermval3d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test exceptions
+ assert_raises(ValueError, herm.hermval3d, x1, x2, x3[:2], self.c3d)
+
+ #test values
+ tgt = y1*y2*y3
+ res = herm.hermval3d(x1, x2, x3, self.c3d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = herm.hermval3d(z, z, z, self.c3d)
+ assert_(res.shape == (2, 3))
+
+ def test_hermgrid2d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test values
+ tgt = np.einsum('i,j->ij', y1, y2)
+ res = herm.hermgrid2d(x1, x2, self.c2d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = herm.hermgrid2d(z, z, self.c2d)
+ assert_(res.shape == (2, 3)*2)
+
+ def test_hermgrid3d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test values
+ tgt = np.einsum('i,j,k->ijk', y1, y2, y3)
+ res = herm.hermgrid3d(x1, x2, x3, self.c3d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = herm.hermgrid3d(z, z, z, self.c3d)
+ assert_(res.shape == (2, 3)*3)
+
+
+class TestIntegral:
+
+ def test_hermint(self):
+ # check exceptions
+ assert_raises(TypeError, herm.hermint, [0], .5)
+ assert_raises(ValueError, herm.hermint, [0], -1)
+ assert_raises(ValueError, herm.hermint, [0], 1, [0, 0])
+ assert_raises(ValueError, herm.hermint, [0], lbnd=[0])
+ assert_raises(ValueError, herm.hermint, [0], scl=[0])
+ assert_raises(TypeError, herm.hermint, [0], axis=.5)
+
+ # test integration of zero polynomial
+ for i in range(2, 5):
+ k = [0]*(i - 2) + [1]
+ res = herm.hermint([0], m=i, k=k)
+ assert_almost_equal(res, [0, .5])
+
+ # check single integration with integration constant
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ tgt = [i] + [0]*i + [1/scl]
+ hermpol = herm.poly2herm(pol)
+ hermint = herm.hermint(hermpol, m=1, k=[i])
+ res = herm.herm2poly(hermint)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check single integration with integration constant and lbnd
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ hermpol = herm.poly2herm(pol)
+ hermint = herm.hermint(hermpol, m=1, k=[i], lbnd=-1)
+ assert_almost_equal(herm.hermval(-1, hermint), i)
+
+ # check single integration with integration constant and scaling
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ tgt = [i] + [0]*i + [2/scl]
+ hermpol = herm.poly2herm(pol)
+ hermint = herm.hermint(hermpol, m=1, k=[i], scl=2)
+ res = herm.herm2poly(hermint)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with default k
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = herm.hermint(tgt, m=1)
+ res = herm.hermint(pol, m=j)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with defined k
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = herm.hermint(tgt, m=1, k=[k])
+ res = herm.hermint(pol, m=j, k=list(range(j)))
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with lbnd
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = herm.hermint(tgt, m=1, k=[k], lbnd=-1)
+ res = herm.hermint(pol, m=j, k=list(range(j)), lbnd=-1)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with scaling
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = herm.hermint(tgt, m=1, k=[k], scl=2)
+ res = herm.hermint(pol, m=j, k=list(range(j)), scl=2)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_hermint_axis(self):
+ # check that axis keyword works
+ c2d = np.random.random((3, 4))
+
+ tgt = np.vstack([herm.hermint(c) for c in c2d.T]).T
+ res = herm.hermint(c2d, axis=0)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([herm.hermint(c) for c in c2d])
+ res = herm.hermint(c2d, axis=1)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([herm.hermint(c, k=3) for c in c2d])
+ res = herm.hermint(c2d, k=3, axis=1)
+ assert_almost_equal(res, tgt)
+
+
+class TestDerivative:
+
+ def test_hermder(self):
+ # check exceptions
+ assert_raises(TypeError, herm.hermder, [0], .5)
+ assert_raises(ValueError, herm.hermder, [0], -1)
+
+ # check that zeroth derivative does nothing
+ for i in range(5):
+ tgt = [0]*i + [1]
+ res = herm.hermder(tgt, m=0)
+ assert_equal(trim(res), trim(tgt))
+
+ # check that derivation is the inverse of integration
+ for i in range(5):
+ for j in range(2, 5):
+ tgt = [0]*i + [1]
+ res = herm.hermder(herm.hermint(tgt, m=j), m=j)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check derivation with scaling
+ for i in range(5):
+ for j in range(2, 5):
+ tgt = [0]*i + [1]
+ res = herm.hermder(herm.hermint(tgt, m=j, scl=2), m=j, scl=.5)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_hermder_axis(self):
+ # check that axis keyword works
+ c2d = np.random.random((3, 4))
+
+ tgt = np.vstack([herm.hermder(c) for c in c2d.T]).T
+ res = herm.hermder(c2d, axis=0)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([herm.hermder(c) for c in c2d])
+ res = herm.hermder(c2d, axis=1)
+ assert_almost_equal(res, tgt)
+
+
+class TestVander:
+ # some random values in [-1, 1)
+ x = np.random.random((3, 5))*2 - 1
+
+ def test_hermvander(self):
+ # check for 1d x
+ x = np.arange(3)
+ v = herm.hermvander(x, 3)
+ assert_(v.shape == (3, 4))
+ for i in range(4):
+ coef = [0]*i + [1]
+ assert_almost_equal(v[..., i], herm.hermval(x, coef))
+
+ # check for 2d x
+ x = np.array([[1, 2], [3, 4], [5, 6]])
+ v = herm.hermvander(x, 3)
+ assert_(v.shape == (3, 2, 4))
+ for i in range(4):
+ coef = [0]*i + [1]
+ assert_almost_equal(v[..., i], herm.hermval(x, coef))
+
+ def test_hermvander2d(self):
+ # also tests hermval2d for non-square coefficient array
+ x1, x2, x3 = self.x
+ c = np.random.random((2, 3))
+ van = herm.hermvander2d(x1, x2, [1, 2])
+ tgt = herm.hermval2d(x1, x2, c)
+ res = np.dot(van, c.flat)
+ assert_almost_equal(res, tgt)
+
+ # check shape
+ van = herm.hermvander2d([x1], [x2], [1, 2])
+ assert_(van.shape == (1, 5, 6))
+
+ def test_hermvander3d(self):
+ # also tests hermval3d for non-square coefficient array
+ x1, x2, x3 = self.x
+ c = np.random.random((2, 3, 4))
+ van = herm.hermvander3d(x1, x2, x3, [1, 2, 3])
+ tgt = herm.hermval3d(x1, x2, x3, c)
+ res = np.dot(van, c.flat)
+ assert_almost_equal(res, tgt)
+
+ # check shape
+ van = herm.hermvander3d([x1], [x2], [x3], [1, 2, 3])
+ assert_(van.shape == (1, 5, 24))
+
+
+class TestFitting:
+
+ def test_hermfit(self):
+ def f(x):
+ return x*(x - 1)*(x - 2)
+
+ def f2(x):
+ return x**4 + x**2 + 1
+
+ # Test exceptions
+ assert_raises(ValueError, herm.hermfit, [1], [1], -1)
+ assert_raises(TypeError, herm.hermfit, [[1]], [1], 0)
+ assert_raises(TypeError, herm.hermfit, [], [1], 0)
+ assert_raises(TypeError, herm.hermfit, [1], [[[1]]], 0)
+ assert_raises(TypeError, herm.hermfit, [1, 2], [1], 0)
+ assert_raises(TypeError, herm.hermfit, [1], [1, 2], 0)
+ assert_raises(TypeError, herm.hermfit, [1], [1], 0, w=[[1]])
+ assert_raises(TypeError, herm.hermfit, [1], [1], 0, w=[1, 1])
+ assert_raises(ValueError, herm.hermfit, [1], [1], [-1,])
+ assert_raises(ValueError, herm.hermfit, [1], [1], [2, -1, 6])
+ assert_raises(TypeError, herm.hermfit, [1], [1], [])
+
+ # Test fit
+ x = np.linspace(0, 2)
+ y = f(x)
+ #
+ coef3 = herm.hermfit(x, y, 3)
+ assert_equal(len(coef3), 4)
+ assert_almost_equal(herm.hermval(x, coef3), y)
+ coef3 = herm.hermfit(x, y, [0, 1, 2, 3])
+ assert_equal(len(coef3), 4)
+ assert_almost_equal(herm.hermval(x, coef3), y)
+ #
+ coef4 = herm.hermfit(x, y, 4)
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(herm.hermval(x, coef4), y)
+ coef4 = herm.hermfit(x, y, [0, 1, 2, 3, 4])
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(herm.hermval(x, coef4), y)
+ # check things still work if deg is not in strict increasing
+ coef4 = herm.hermfit(x, y, [2, 3, 4, 1, 0])
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(herm.hermval(x, coef4), y)
+ #
+ coef2d = herm.hermfit(x, np.array([y, y]).T, 3)
+ assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
+ coef2d = herm.hermfit(x, np.array([y, y]).T, [0, 1, 2, 3])
+ assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
+ # test weighting
+ w = np.zeros_like(x)
+ yw = y.copy()
+ w[1::2] = 1
+ y[0::2] = 0
+ wcoef3 = herm.hermfit(x, yw, 3, w=w)
+ assert_almost_equal(wcoef3, coef3)
+ wcoef3 = herm.hermfit(x, yw, [0, 1, 2, 3], w=w)
+ assert_almost_equal(wcoef3, coef3)
+ #
+ wcoef2d = herm.hermfit(x, np.array([yw, yw]).T, 3, w=w)
+ assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
+ wcoef2d = herm.hermfit(x, np.array([yw, yw]).T, [0, 1, 2, 3], w=w)
+ assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
+ # test scaling with complex values x points whose square
+ # is zero when summed.
+ x = [1, 1j, -1, -1j]
+ assert_almost_equal(herm.hermfit(x, x, 1), [0, .5])
+ assert_almost_equal(herm.hermfit(x, x, [0, 1]), [0, .5])
+ # test fitting only even Legendre polynomials
+ x = np.linspace(-1, 1)
+ y = f2(x)
+ coef1 = herm.hermfit(x, y, 4)
+ assert_almost_equal(herm.hermval(x, coef1), y)
+ coef2 = herm.hermfit(x, y, [0, 2, 4])
+ assert_almost_equal(herm.hermval(x, coef2), y)
+ assert_almost_equal(coef1, coef2)
+
+
+class TestCompanion:
+
+ def test_raises(self):
+ assert_raises(ValueError, herm.hermcompanion, [])
+ assert_raises(ValueError, herm.hermcompanion, [1])
+
+ def test_dimensions(self):
+ for i in range(1, 5):
+ coef = [0]*i + [1]
+ assert_(herm.hermcompanion(coef).shape == (i, i))
+
+ def test_linear_root(self):
+ assert_(herm.hermcompanion([1, 2])[0, 0] == -.25)
+
+
+class TestGauss:
+
+ def test_100(self):
+ x, w = herm.hermgauss(100)
+
+ # test orthogonality. Note that the results need to be normalized,
+ # otherwise the huge values that can arise from fast growing
+ # functions like Laguerre can be very confusing.
+ v = herm.hermvander(x, 99)
+ vv = np.dot(v.T * w, v)
+ vd = 1/np.sqrt(vv.diagonal())
+ vv = vd[:, None] * vv * vd
+ assert_almost_equal(vv, np.eye(100))
+
+ # check that the integral of 1 is correct
+ tgt = np.sqrt(np.pi)
+ assert_almost_equal(w.sum(), tgt)
+
+
+class TestMisc:
+
+ def test_hermfromroots(self):
+ res = herm.hermfromroots([])
+ assert_almost_equal(trim(res), [1])
+ for i in range(1, 5):
+ roots = np.cos(np.linspace(-np.pi, 0, 2*i + 1)[1::2])
+ pol = herm.hermfromroots(roots)
+ res = herm.hermval(roots, pol)
+ tgt = 0
+ assert_(len(pol) == i + 1)
+ assert_almost_equal(herm.herm2poly(pol)[-1], 1)
+ assert_almost_equal(res, tgt)
+
+ def test_hermroots(self):
+ assert_almost_equal(herm.hermroots([1]), [])
+ assert_almost_equal(herm.hermroots([1, 1]), [-.5])
+ for i in range(2, 5):
+ tgt = np.linspace(-1, 1, i)
+ res = herm.hermroots(herm.hermfromroots(tgt))
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_hermtrim(self):
+ coef = [2, -1, 1, 0]
+
+ # Test exceptions
+ assert_raises(ValueError, herm.hermtrim, coef, -1)
+
+ # Test results
+ assert_equal(herm.hermtrim(coef), coef[:-1])
+ assert_equal(herm.hermtrim(coef, 1), coef[:-3])
+ assert_equal(herm.hermtrim(coef, 2), [0])
+
+ def test_hermline(self):
+ assert_equal(herm.hermline(3, 4), [3, 2])
+
+ def test_herm2poly(self):
+ for i in range(10):
+ assert_almost_equal(herm.herm2poly([0]*i + [1]), Hlist[i])
+
+ def test_poly2herm(self):
+ for i in range(10):
+ assert_almost_equal(herm.poly2herm(Hlist[i]), [0]*i + [1])
+
+ def test_weight(self):
+ x = np.linspace(-5, 5, 11)
+ tgt = np.exp(-x**2)
+ res = herm.hermweight(x)
+ assert_almost_equal(res, tgt)
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/test_hermite_e.py b/lib/python3.12/site-packages/numpy/polynomial/tests/test_hermite_e.py
new file mode 100644
index 0000000000000000000000000000000000000000..2d262a3306222bd79f682b09763b0bd2b90ba8fe
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/tests/test_hermite_e.py
@@ -0,0 +1,556 @@
+"""Tests for hermite_e module.
+
+"""
+from functools import reduce
+
+import numpy as np
+import numpy.polynomial.hermite_e as herme
+from numpy.polynomial.polynomial import polyval
+from numpy.testing import (
+ assert_almost_equal, assert_raises, assert_equal, assert_,
+ )
+
+He0 = np.array([1])
+He1 = np.array([0, 1])
+He2 = np.array([-1, 0, 1])
+He3 = np.array([0, -3, 0, 1])
+He4 = np.array([3, 0, -6, 0, 1])
+He5 = np.array([0, 15, 0, -10, 0, 1])
+He6 = np.array([-15, 0, 45, 0, -15, 0, 1])
+He7 = np.array([0, -105, 0, 105, 0, -21, 0, 1])
+He8 = np.array([105, 0, -420, 0, 210, 0, -28, 0, 1])
+He9 = np.array([0, 945, 0, -1260, 0, 378, 0, -36, 0, 1])
+
+Helist = [He0, He1, He2, He3, He4, He5, He6, He7, He8, He9]
+
+
+def trim(x):
+ return herme.hermetrim(x, tol=1e-6)
+
+
+class TestConstants:
+
+ def test_hermedomain(self):
+ assert_equal(herme.hermedomain, [-1, 1])
+
+ def test_hermezero(self):
+ assert_equal(herme.hermezero, [0])
+
+ def test_hermeone(self):
+ assert_equal(herme.hermeone, [1])
+
+ def test_hermex(self):
+ assert_equal(herme.hermex, [0, 1])
+
+
+class TestArithmetic:
+ x = np.linspace(-3, 3, 100)
+
+ def test_hermeadd(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ tgt = np.zeros(max(i, j) + 1)
+ tgt[i] += 1
+ tgt[j] += 1
+ res = herme.hermeadd([0]*i + [1], [0]*j + [1])
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_hermesub(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ tgt = np.zeros(max(i, j) + 1)
+ tgt[i] += 1
+ tgt[j] -= 1
+ res = herme.hermesub([0]*i + [1], [0]*j + [1])
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_hermemulx(self):
+ assert_equal(herme.hermemulx([0]), [0])
+ assert_equal(herme.hermemulx([1]), [0, 1])
+ for i in range(1, 5):
+ ser = [0]*i + [1]
+ tgt = [0]*(i - 1) + [i, 0, 1]
+ assert_equal(herme.hermemulx(ser), tgt)
+
+ def test_hermemul(self):
+ # check values of result
+ for i in range(5):
+ pol1 = [0]*i + [1]
+ val1 = herme.hermeval(self.x, pol1)
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ pol2 = [0]*j + [1]
+ val2 = herme.hermeval(self.x, pol2)
+ pol3 = herme.hermemul(pol1, pol2)
+ val3 = herme.hermeval(self.x, pol3)
+ assert_(len(pol3) == i + j + 1, msg)
+ assert_almost_equal(val3, val1*val2, err_msg=msg)
+
+ def test_hermediv(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ ci = [0]*i + [1]
+ cj = [0]*j + [1]
+ tgt = herme.hermeadd(ci, cj)
+ quo, rem = herme.hermediv(tgt, ci)
+ res = herme.hermeadd(herme.hermemul(quo, ci), rem)
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_hermepow(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ c = np.arange(i + 1)
+ tgt = reduce(herme.hermemul, [c]*j, np.array([1]))
+ res = herme.hermepow(c, j)
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+
+class TestEvaluation:
+ # coefficients of 1 + 2*x + 3*x**2
+ c1d = np.array([4., 2., 3.])
+ c2d = np.einsum('i,j->ij', c1d, c1d)
+ c3d = np.einsum('i,j,k->ijk', c1d, c1d, c1d)
+
+ # some random values in [-1, 1)
+ x = np.random.random((3, 5))*2 - 1
+ y = polyval(x, [1., 2., 3.])
+
+ def test_hermeval(self):
+ #check empty input
+ assert_equal(herme.hermeval([], [1]).size, 0)
+
+ #check normal input)
+ x = np.linspace(-1, 1)
+ y = [polyval(x, c) for c in Helist]
+ for i in range(10):
+ msg = f"At i={i}"
+ tgt = y[i]
+ res = herme.hermeval(x, [0]*i + [1])
+ assert_almost_equal(res, tgt, err_msg=msg)
+
+ #check that shape is preserved
+ for i in range(3):
+ dims = [2]*i
+ x = np.zeros(dims)
+ assert_equal(herme.hermeval(x, [1]).shape, dims)
+ assert_equal(herme.hermeval(x, [1, 0]).shape, dims)
+ assert_equal(herme.hermeval(x, [1, 0, 0]).shape, dims)
+
+ def test_hermeval2d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test exceptions
+ assert_raises(ValueError, herme.hermeval2d, x1, x2[:2], self.c2d)
+
+ #test values
+ tgt = y1*y2
+ res = herme.hermeval2d(x1, x2, self.c2d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = herme.hermeval2d(z, z, self.c2d)
+ assert_(res.shape == (2, 3))
+
+ def test_hermeval3d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test exceptions
+ assert_raises(ValueError, herme.hermeval3d, x1, x2, x3[:2], self.c3d)
+
+ #test values
+ tgt = y1*y2*y3
+ res = herme.hermeval3d(x1, x2, x3, self.c3d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = herme.hermeval3d(z, z, z, self.c3d)
+ assert_(res.shape == (2, 3))
+
+ def test_hermegrid2d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test values
+ tgt = np.einsum('i,j->ij', y1, y2)
+ res = herme.hermegrid2d(x1, x2, self.c2d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = herme.hermegrid2d(z, z, self.c2d)
+ assert_(res.shape == (2, 3)*2)
+
+ def test_hermegrid3d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test values
+ tgt = np.einsum('i,j,k->ijk', y1, y2, y3)
+ res = herme.hermegrid3d(x1, x2, x3, self.c3d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = herme.hermegrid3d(z, z, z, self.c3d)
+ assert_(res.shape == (2, 3)*3)
+
+
+class TestIntegral:
+
+ def test_hermeint(self):
+ # check exceptions
+ assert_raises(TypeError, herme.hermeint, [0], .5)
+ assert_raises(ValueError, herme.hermeint, [0], -1)
+ assert_raises(ValueError, herme.hermeint, [0], 1, [0, 0])
+ assert_raises(ValueError, herme.hermeint, [0], lbnd=[0])
+ assert_raises(ValueError, herme.hermeint, [0], scl=[0])
+ assert_raises(TypeError, herme.hermeint, [0], axis=.5)
+
+ # test integration of zero polynomial
+ for i in range(2, 5):
+ k = [0]*(i - 2) + [1]
+ res = herme.hermeint([0], m=i, k=k)
+ assert_almost_equal(res, [0, 1])
+
+ # check single integration with integration constant
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ tgt = [i] + [0]*i + [1/scl]
+ hermepol = herme.poly2herme(pol)
+ hermeint = herme.hermeint(hermepol, m=1, k=[i])
+ res = herme.herme2poly(hermeint)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check single integration with integration constant and lbnd
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ hermepol = herme.poly2herme(pol)
+ hermeint = herme.hermeint(hermepol, m=1, k=[i], lbnd=-1)
+ assert_almost_equal(herme.hermeval(-1, hermeint), i)
+
+ # check single integration with integration constant and scaling
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ tgt = [i] + [0]*i + [2/scl]
+ hermepol = herme.poly2herme(pol)
+ hermeint = herme.hermeint(hermepol, m=1, k=[i], scl=2)
+ res = herme.herme2poly(hermeint)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with default k
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = herme.hermeint(tgt, m=1)
+ res = herme.hermeint(pol, m=j)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with defined k
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = herme.hermeint(tgt, m=1, k=[k])
+ res = herme.hermeint(pol, m=j, k=list(range(j)))
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with lbnd
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = herme.hermeint(tgt, m=1, k=[k], lbnd=-1)
+ res = herme.hermeint(pol, m=j, k=list(range(j)), lbnd=-1)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with scaling
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = herme.hermeint(tgt, m=1, k=[k], scl=2)
+ res = herme.hermeint(pol, m=j, k=list(range(j)), scl=2)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_hermeint_axis(self):
+ # check that axis keyword works
+ c2d = np.random.random((3, 4))
+
+ tgt = np.vstack([herme.hermeint(c) for c in c2d.T]).T
+ res = herme.hermeint(c2d, axis=0)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([herme.hermeint(c) for c in c2d])
+ res = herme.hermeint(c2d, axis=1)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([herme.hermeint(c, k=3) for c in c2d])
+ res = herme.hermeint(c2d, k=3, axis=1)
+ assert_almost_equal(res, tgt)
+
+
+class TestDerivative:
+
+ def test_hermeder(self):
+ # check exceptions
+ assert_raises(TypeError, herme.hermeder, [0], .5)
+ assert_raises(ValueError, herme.hermeder, [0], -1)
+
+ # check that zeroth derivative does nothing
+ for i in range(5):
+ tgt = [0]*i + [1]
+ res = herme.hermeder(tgt, m=0)
+ assert_equal(trim(res), trim(tgt))
+
+ # check that derivation is the inverse of integration
+ for i in range(5):
+ for j in range(2, 5):
+ tgt = [0]*i + [1]
+ res = herme.hermeder(herme.hermeint(tgt, m=j), m=j)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check derivation with scaling
+ for i in range(5):
+ for j in range(2, 5):
+ tgt = [0]*i + [1]
+ res = herme.hermeder(
+ herme.hermeint(tgt, m=j, scl=2), m=j, scl=.5)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_hermeder_axis(self):
+ # check that axis keyword works
+ c2d = np.random.random((3, 4))
+
+ tgt = np.vstack([herme.hermeder(c) for c in c2d.T]).T
+ res = herme.hermeder(c2d, axis=0)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([herme.hermeder(c) for c in c2d])
+ res = herme.hermeder(c2d, axis=1)
+ assert_almost_equal(res, tgt)
+
+
+class TestVander:
+ # some random values in [-1, 1)
+ x = np.random.random((3, 5))*2 - 1
+
+ def test_hermevander(self):
+ # check for 1d x
+ x = np.arange(3)
+ v = herme.hermevander(x, 3)
+ assert_(v.shape == (3, 4))
+ for i in range(4):
+ coef = [0]*i + [1]
+ assert_almost_equal(v[..., i], herme.hermeval(x, coef))
+
+ # check for 2d x
+ x = np.array([[1, 2], [3, 4], [5, 6]])
+ v = herme.hermevander(x, 3)
+ assert_(v.shape == (3, 2, 4))
+ for i in range(4):
+ coef = [0]*i + [1]
+ assert_almost_equal(v[..., i], herme.hermeval(x, coef))
+
+ def test_hermevander2d(self):
+ # also tests hermeval2d for non-square coefficient array
+ x1, x2, x3 = self.x
+ c = np.random.random((2, 3))
+ van = herme.hermevander2d(x1, x2, [1, 2])
+ tgt = herme.hermeval2d(x1, x2, c)
+ res = np.dot(van, c.flat)
+ assert_almost_equal(res, tgt)
+
+ # check shape
+ van = herme.hermevander2d([x1], [x2], [1, 2])
+ assert_(van.shape == (1, 5, 6))
+
+ def test_hermevander3d(self):
+ # also tests hermeval3d for non-square coefficient array
+ x1, x2, x3 = self.x
+ c = np.random.random((2, 3, 4))
+ van = herme.hermevander3d(x1, x2, x3, [1, 2, 3])
+ tgt = herme.hermeval3d(x1, x2, x3, c)
+ res = np.dot(van, c.flat)
+ assert_almost_equal(res, tgt)
+
+ # check shape
+ van = herme.hermevander3d([x1], [x2], [x3], [1, 2, 3])
+ assert_(van.shape == (1, 5, 24))
+
+
+class TestFitting:
+
+ def test_hermefit(self):
+ def f(x):
+ return x*(x - 1)*(x - 2)
+
+ def f2(x):
+ return x**4 + x**2 + 1
+
+ # Test exceptions
+ assert_raises(ValueError, herme.hermefit, [1], [1], -1)
+ assert_raises(TypeError, herme.hermefit, [[1]], [1], 0)
+ assert_raises(TypeError, herme.hermefit, [], [1], 0)
+ assert_raises(TypeError, herme.hermefit, [1], [[[1]]], 0)
+ assert_raises(TypeError, herme.hermefit, [1, 2], [1], 0)
+ assert_raises(TypeError, herme.hermefit, [1], [1, 2], 0)
+ assert_raises(TypeError, herme.hermefit, [1], [1], 0, w=[[1]])
+ assert_raises(TypeError, herme.hermefit, [1], [1], 0, w=[1, 1])
+ assert_raises(ValueError, herme.hermefit, [1], [1], [-1,])
+ assert_raises(ValueError, herme.hermefit, [1], [1], [2, -1, 6])
+ assert_raises(TypeError, herme.hermefit, [1], [1], [])
+
+ # Test fit
+ x = np.linspace(0, 2)
+ y = f(x)
+ #
+ coef3 = herme.hermefit(x, y, 3)
+ assert_equal(len(coef3), 4)
+ assert_almost_equal(herme.hermeval(x, coef3), y)
+ coef3 = herme.hermefit(x, y, [0, 1, 2, 3])
+ assert_equal(len(coef3), 4)
+ assert_almost_equal(herme.hermeval(x, coef3), y)
+ #
+ coef4 = herme.hermefit(x, y, 4)
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(herme.hermeval(x, coef4), y)
+ coef4 = herme.hermefit(x, y, [0, 1, 2, 3, 4])
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(herme.hermeval(x, coef4), y)
+ # check things still work if deg is not in strict increasing
+ coef4 = herme.hermefit(x, y, [2, 3, 4, 1, 0])
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(herme.hermeval(x, coef4), y)
+ #
+ coef2d = herme.hermefit(x, np.array([y, y]).T, 3)
+ assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
+ coef2d = herme.hermefit(x, np.array([y, y]).T, [0, 1, 2, 3])
+ assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
+ # test weighting
+ w = np.zeros_like(x)
+ yw = y.copy()
+ w[1::2] = 1
+ y[0::2] = 0
+ wcoef3 = herme.hermefit(x, yw, 3, w=w)
+ assert_almost_equal(wcoef3, coef3)
+ wcoef3 = herme.hermefit(x, yw, [0, 1, 2, 3], w=w)
+ assert_almost_equal(wcoef3, coef3)
+ #
+ wcoef2d = herme.hermefit(x, np.array([yw, yw]).T, 3, w=w)
+ assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
+ wcoef2d = herme.hermefit(x, np.array([yw, yw]).T, [0, 1, 2, 3], w=w)
+ assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
+ # test scaling with complex values x points whose square
+ # is zero when summed.
+ x = [1, 1j, -1, -1j]
+ assert_almost_equal(herme.hermefit(x, x, 1), [0, 1])
+ assert_almost_equal(herme.hermefit(x, x, [0, 1]), [0, 1])
+ # test fitting only even Legendre polynomials
+ x = np.linspace(-1, 1)
+ y = f2(x)
+ coef1 = herme.hermefit(x, y, 4)
+ assert_almost_equal(herme.hermeval(x, coef1), y)
+ coef2 = herme.hermefit(x, y, [0, 2, 4])
+ assert_almost_equal(herme.hermeval(x, coef2), y)
+ assert_almost_equal(coef1, coef2)
+
+
+class TestCompanion:
+
+ def test_raises(self):
+ assert_raises(ValueError, herme.hermecompanion, [])
+ assert_raises(ValueError, herme.hermecompanion, [1])
+
+ def test_dimensions(self):
+ for i in range(1, 5):
+ coef = [0]*i + [1]
+ assert_(herme.hermecompanion(coef).shape == (i, i))
+
+ def test_linear_root(self):
+ assert_(herme.hermecompanion([1, 2])[0, 0] == -.5)
+
+
+class TestGauss:
+
+ def test_100(self):
+ x, w = herme.hermegauss(100)
+
+ # test orthogonality. Note that the results need to be normalized,
+ # otherwise the huge values that can arise from fast growing
+ # functions like Laguerre can be very confusing.
+ v = herme.hermevander(x, 99)
+ vv = np.dot(v.T * w, v)
+ vd = 1/np.sqrt(vv.diagonal())
+ vv = vd[:, None] * vv * vd
+ assert_almost_equal(vv, np.eye(100))
+
+ # check that the integral of 1 is correct
+ tgt = np.sqrt(2*np.pi)
+ assert_almost_equal(w.sum(), tgt)
+
+
+class TestMisc:
+
+ def test_hermefromroots(self):
+ res = herme.hermefromroots([])
+ assert_almost_equal(trim(res), [1])
+ for i in range(1, 5):
+ roots = np.cos(np.linspace(-np.pi, 0, 2*i + 1)[1::2])
+ pol = herme.hermefromroots(roots)
+ res = herme.hermeval(roots, pol)
+ tgt = 0
+ assert_(len(pol) == i + 1)
+ assert_almost_equal(herme.herme2poly(pol)[-1], 1)
+ assert_almost_equal(res, tgt)
+
+ def test_hermeroots(self):
+ assert_almost_equal(herme.hermeroots([1]), [])
+ assert_almost_equal(herme.hermeroots([1, 1]), [-1])
+ for i in range(2, 5):
+ tgt = np.linspace(-1, 1, i)
+ res = herme.hermeroots(herme.hermefromroots(tgt))
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_hermetrim(self):
+ coef = [2, -1, 1, 0]
+
+ # Test exceptions
+ assert_raises(ValueError, herme.hermetrim, coef, -1)
+
+ # Test results
+ assert_equal(herme.hermetrim(coef), coef[:-1])
+ assert_equal(herme.hermetrim(coef, 1), coef[:-3])
+ assert_equal(herme.hermetrim(coef, 2), [0])
+
+ def test_hermeline(self):
+ assert_equal(herme.hermeline(3, 4), [3, 4])
+
+ def test_herme2poly(self):
+ for i in range(10):
+ assert_almost_equal(herme.herme2poly([0]*i + [1]), Helist[i])
+
+ def test_poly2herme(self):
+ for i in range(10):
+ assert_almost_equal(herme.poly2herme(Helist[i]), [0]*i + [1])
+
+ def test_weight(self):
+ x = np.linspace(-5, 5, 11)
+ tgt = np.exp(-.5*x**2)
+ res = herme.hermeweight(x)
+ assert_almost_equal(res, tgt)
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/test_laguerre.py b/lib/python3.12/site-packages/numpy/polynomial/tests/test_laguerre.py
new file mode 100644
index 0000000000000000000000000000000000000000..227ef3c5576dd666e2eb76576eb260d5ba48cb0e
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/tests/test_laguerre.py
@@ -0,0 +1,537 @@
+"""Tests for laguerre module.
+
+"""
+from functools import reduce
+
+import numpy as np
+import numpy.polynomial.laguerre as lag
+from numpy.polynomial.polynomial import polyval
+from numpy.testing import (
+ assert_almost_equal, assert_raises, assert_equal, assert_,
+ )
+
+L0 = np.array([1])/1
+L1 = np.array([1, -1])/1
+L2 = np.array([2, -4, 1])/2
+L3 = np.array([6, -18, 9, -1])/6
+L4 = np.array([24, -96, 72, -16, 1])/24
+L5 = np.array([120, -600, 600, -200, 25, -1])/120
+L6 = np.array([720, -4320, 5400, -2400, 450, -36, 1])/720
+
+Llist = [L0, L1, L2, L3, L4, L5, L6]
+
+
+def trim(x):
+ return lag.lagtrim(x, tol=1e-6)
+
+
+class TestConstants:
+
+ def test_lagdomain(self):
+ assert_equal(lag.lagdomain, [0, 1])
+
+ def test_lagzero(self):
+ assert_equal(lag.lagzero, [0])
+
+ def test_lagone(self):
+ assert_equal(lag.lagone, [1])
+
+ def test_lagx(self):
+ assert_equal(lag.lagx, [1, -1])
+
+
+class TestArithmetic:
+ x = np.linspace(-3, 3, 100)
+
+ def test_lagadd(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ tgt = np.zeros(max(i, j) + 1)
+ tgt[i] += 1
+ tgt[j] += 1
+ res = lag.lagadd([0]*i + [1], [0]*j + [1])
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_lagsub(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ tgt = np.zeros(max(i, j) + 1)
+ tgt[i] += 1
+ tgt[j] -= 1
+ res = lag.lagsub([0]*i + [1], [0]*j + [1])
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_lagmulx(self):
+ assert_equal(lag.lagmulx([0]), [0])
+ assert_equal(lag.lagmulx([1]), [1, -1])
+ for i in range(1, 5):
+ ser = [0]*i + [1]
+ tgt = [0]*(i - 1) + [-i, 2*i + 1, -(i + 1)]
+ assert_almost_equal(lag.lagmulx(ser), tgt)
+
+ def test_lagmul(self):
+ # check values of result
+ for i in range(5):
+ pol1 = [0]*i + [1]
+ val1 = lag.lagval(self.x, pol1)
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ pol2 = [0]*j + [1]
+ val2 = lag.lagval(self.x, pol2)
+ pol3 = lag.lagmul(pol1, pol2)
+ val3 = lag.lagval(self.x, pol3)
+ assert_(len(pol3) == i + j + 1, msg)
+ assert_almost_equal(val3, val1*val2, err_msg=msg)
+
+ def test_lagdiv(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ ci = [0]*i + [1]
+ cj = [0]*j + [1]
+ tgt = lag.lagadd(ci, cj)
+ quo, rem = lag.lagdiv(tgt, ci)
+ res = lag.lagadd(lag.lagmul(quo, ci), rem)
+ assert_almost_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_lagpow(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ c = np.arange(i + 1)
+ tgt = reduce(lag.lagmul, [c]*j, np.array([1]))
+ res = lag.lagpow(c, j)
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+
+class TestEvaluation:
+ # coefficients of 1 + 2*x + 3*x**2
+ c1d = np.array([9., -14., 6.])
+ c2d = np.einsum('i,j->ij', c1d, c1d)
+ c3d = np.einsum('i,j,k->ijk', c1d, c1d, c1d)
+
+ # some random values in [-1, 1)
+ x = np.random.random((3, 5))*2 - 1
+ y = polyval(x, [1., 2., 3.])
+
+ def test_lagval(self):
+ #check empty input
+ assert_equal(lag.lagval([], [1]).size, 0)
+
+ #check normal input)
+ x = np.linspace(-1, 1)
+ y = [polyval(x, c) for c in Llist]
+ for i in range(7):
+ msg = f"At i={i}"
+ tgt = y[i]
+ res = lag.lagval(x, [0]*i + [1])
+ assert_almost_equal(res, tgt, err_msg=msg)
+
+ #check that shape is preserved
+ for i in range(3):
+ dims = [2]*i
+ x = np.zeros(dims)
+ assert_equal(lag.lagval(x, [1]).shape, dims)
+ assert_equal(lag.lagval(x, [1, 0]).shape, dims)
+ assert_equal(lag.lagval(x, [1, 0, 0]).shape, dims)
+
+ def test_lagval2d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test exceptions
+ assert_raises(ValueError, lag.lagval2d, x1, x2[:2], self.c2d)
+
+ #test values
+ tgt = y1*y2
+ res = lag.lagval2d(x1, x2, self.c2d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = lag.lagval2d(z, z, self.c2d)
+ assert_(res.shape == (2, 3))
+
+ def test_lagval3d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test exceptions
+ assert_raises(ValueError, lag.lagval3d, x1, x2, x3[:2], self.c3d)
+
+ #test values
+ tgt = y1*y2*y3
+ res = lag.lagval3d(x1, x2, x3, self.c3d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = lag.lagval3d(z, z, z, self.c3d)
+ assert_(res.shape == (2, 3))
+
+ def test_laggrid2d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test values
+ tgt = np.einsum('i,j->ij', y1, y2)
+ res = lag.laggrid2d(x1, x2, self.c2d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = lag.laggrid2d(z, z, self.c2d)
+ assert_(res.shape == (2, 3)*2)
+
+ def test_laggrid3d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test values
+ tgt = np.einsum('i,j,k->ijk', y1, y2, y3)
+ res = lag.laggrid3d(x1, x2, x3, self.c3d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = lag.laggrid3d(z, z, z, self.c3d)
+ assert_(res.shape == (2, 3)*3)
+
+
+class TestIntegral:
+
+ def test_lagint(self):
+ # check exceptions
+ assert_raises(TypeError, lag.lagint, [0], .5)
+ assert_raises(ValueError, lag.lagint, [0], -1)
+ assert_raises(ValueError, lag.lagint, [0], 1, [0, 0])
+ assert_raises(ValueError, lag.lagint, [0], lbnd=[0])
+ assert_raises(ValueError, lag.lagint, [0], scl=[0])
+ assert_raises(TypeError, lag.lagint, [0], axis=.5)
+
+ # test integration of zero polynomial
+ for i in range(2, 5):
+ k = [0]*(i - 2) + [1]
+ res = lag.lagint([0], m=i, k=k)
+ assert_almost_equal(res, [1, -1])
+
+ # check single integration with integration constant
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ tgt = [i] + [0]*i + [1/scl]
+ lagpol = lag.poly2lag(pol)
+ lagint = lag.lagint(lagpol, m=1, k=[i])
+ res = lag.lag2poly(lagint)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check single integration with integration constant and lbnd
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ lagpol = lag.poly2lag(pol)
+ lagint = lag.lagint(lagpol, m=1, k=[i], lbnd=-1)
+ assert_almost_equal(lag.lagval(-1, lagint), i)
+
+ # check single integration with integration constant and scaling
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ tgt = [i] + [0]*i + [2/scl]
+ lagpol = lag.poly2lag(pol)
+ lagint = lag.lagint(lagpol, m=1, k=[i], scl=2)
+ res = lag.lag2poly(lagint)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with default k
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = lag.lagint(tgt, m=1)
+ res = lag.lagint(pol, m=j)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with defined k
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = lag.lagint(tgt, m=1, k=[k])
+ res = lag.lagint(pol, m=j, k=list(range(j)))
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with lbnd
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = lag.lagint(tgt, m=1, k=[k], lbnd=-1)
+ res = lag.lagint(pol, m=j, k=list(range(j)), lbnd=-1)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with scaling
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = lag.lagint(tgt, m=1, k=[k], scl=2)
+ res = lag.lagint(pol, m=j, k=list(range(j)), scl=2)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_lagint_axis(self):
+ # check that axis keyword works
+ c2d = np.random.random((3, 4))
+
+ tgt = np.vstack([lag.lagint(c) for c in c2d.T]).T
+ res = lag.lagint(c2d, axis=0)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([lag.lagint(c) for c in c2d])
+ res = lag.lagint(c2d, axis=1)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([lag.lagint(c, k=3) for c in c2d])
+ res = lag.lagint(c2d, k=3, axis=1)
+ assert_almost_equal(res, tgt)
+
+
+class TestDerivative:
+
+ def test_lagder(self):
+ # check exceptions
+ assert_raises(TypeError, lag.lagder, [0], .5)
+ assert_raises(ValueError, lag.lagder, [0], -1)
+
+ # check that zeroth derivative does nothing
+ for i in range(5):
+ tgt = [0]*i + [1]
+ res = lag.lagder(tgt, m=0)
+ assert_equal(trim(res), trim(tgt))
+
+ # check that derivation is the inverse of integration
+ for i in range(5):
+ for j in range(2, 5):
+ tgt = [0]*i + [1]
+ res = lag.lagder(lag.lagint(tgt, m=j), m=j)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check derivation with scaling
+ for i in range(5):
+ for j in range(2, 5):
+ tgt = [0]*i + [1]
+ res = lag.lagder(lag.lagint(tgt, m=j, scl=2), m=j, scl=.5)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_lagder_axis(self):
+ # check that axis keyword works
+ c2d = np.random.random((3, 4))
+
+ tgt = np.vstack([lag.lagder(c) for c in c2d.T]).T
+ res = lag.lagder(c2d, axis=0)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([lag.lagder(c) for c in c2d])
+ res = lag.lagder(c2d, axis=1)
+ assert_almost_equal(res, tgt)
+
+
+class TestVander:
+ # some random values in [-1, 1)
+ x = np.random.random((3, 5))*2 - 1
+
+ def test_lagvander(self):
+ # check for 1d x
+ x = np.arange(3)
+ v = lag.lagvander(x, 3)
+ assert_(v.shape == (3, 4))
+ for i in range(4):
+ coef = [0]*i + [1]
+ assert_almost_equal(v[..., i], lag.lagval(x, coef))
+
+ # check for 2d x
+ x = np.array([[1, 2], [3, 4], [5, 6]])
+ v = lag.lagvander(x, 3)
+ assert_(v.shape == (3, 2, 4))
+ for i in range(4):
+ coef = [0]*i + [1]
+ assert_almost_equal(v[..., i], lag.lagval(x, coef))
+
+ def test_lagvander2d(self):
+ # also tests lagval2d for non-square coefficient array
+ x1, x2, x3 = self.x
+ c = np.random.random((2, 3))
+ van = lag.lagvander2d(x1, x2, [1, 2])
+ tgt = lag.lagval2d(x1, x2, c)
+ res = np.dot(van, c.flat)
+ assert_almost_equal(res, tgt)
+
+ # check shape
+ van = lag.lagvander2d([x1], [x2], [1, 2])
+ assert_(van.shape == (1, 5, 6))
+
+ def test_lagvander3d(self):
+ # also tests lagval3d for non-square coefficient array
+ x1, x2, x3 = self.x
+ c = np.random.random((2, 3, 4))
+ van = lag.lagvander3d(x1, x2, x3, [1, 2, 3])
+ tgt = lag.lagval3d(x1, x2, x3, c)
+ res = np.dot(van, c.flat)
+ assert_almost_equal(res, tgt)
+
+ # check shape
+ van = lag.lagvander3d([x1], [x2], [x3], [1, 2, 3])
+ assert_(van.shape == (1, 5, 24))
+
+
+class TestFitting:
+
+ def test_lagfit(self):
+ def f(x):
+ return x*(x - 1)*(x - 2)
+
+ # Test exceptions
+ assert_raises(ValueError, lag.lagfit, [1], [1], -1)
+ assert_raises(TypeError, lag.lagfit, [[1]], [1], 0)
+ assert_raises(TypeError, lag.lagfit, [], [1], 0)
+ assert_raises(TypeError, lag.lagfit, [1], [[[1]]], 0)
+ assert_raises(TypeError, lag.lagfit, [1, 2], [1], 0)
+ assert_raises(TypeError, lag.lagfit, [1], [1, 2], 0)
+ assert_raises(TypeError, lag.lagfit, [1], [1], 0, w=[[1]])
+ assert_raises(TypeError, lag.lagfit, [1], [1], 0, w=[1, 1])
+ assert_raises(ValueError, lag.lagfit, [1], [1], [-1,])
+ assert_raises(ValueError, lag.lagfit, [1], [1], [2, -1, 6])
+ assert_raises(TypeError, lag.lagfit, [1], [1], [])
+
+ # Test fit
+ x = np.linspace(0, 2)
+ y = f(x)
+ #
+ coef3 = lag.lagfit(x, y, 3)
+ assert_equal(len(coef3), 4)
+ assert_almost_equal(lag.lagval(x, coef3), y)
+ coef3 = lag.lagfit(x, y, [0, 1, 2, 3])
+ assert_equal(len(coef3), 4)
+ assert_almost_equal(lag.lagval(x, coef3), y)
+ #
+ coef4 = lag.lagfit(x, y, 4)
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(lag.lagval(x, coef4), y)
+ coef4 = lag.lagfit(x, y, [0, 1, 2, 3, 4])
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(lag.lagval(x, coef4), y)
+ #
+ coef2d = lag.lagfit(x, np.array([y, y]).T, 3)
+ assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
+ coef2d = lag.lagfit(x, np.array([y, y]).T, [0, 1, 2, 3])
+ assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
+ # test weighting
+ w = np.zeros_like(x)
+ yw = y.copy()
+ w[1::2] = 1
+ y[0::2] = 0
+ wcoef3 = lag.lagfit(x, yw, 3, w=w)
+ assert_almost_equal(wcoef3, coef3)
+ wcoef3 = lag.lagfit(x, yw, [0, 1, 2, 3], w=w)
+ assert_almost_equal(wcoef3, coef3)
+ #
+ wcoef2d = lag.lagfit(x, np.array([yw, yw]).T, 3, w=w)
+ assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
+ wcoef2d = lag.lagfit(x, np.array([yw, yw]).T, [0, 1, 2, 3], w=w)
+ assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
+ # test scaling with complex values x points whose square
+ # is zero when summed.
+ x = [1, 1j, -1, -1j]
+ assert_almost_equal(lag.lagfit(x, x, 1), [1, -1])
+ assert_almost_equal(lag.lagfit(x, x, [0, 1]), [1, -1])
+
+
+class TestCompanion:
+
+ def test_raises(self):
+ assert_raises(ValueError, lag.lagcompanion, [])
+ assert_raises(ValueError, lag.lagcompanion, [1])
+
+ def test_dimensions(self):
+ for i in range(1, 5):
+ coef = [0]*i + [1]
+ assert_(lag.lagcompanion(coef).shape == (i, i))
+
+ def test_linear_root(self):
+ assert_(lag.lagcompanion([1, 2])[0, 0] == 1.5)
+
+
+class TestGauss:
+
+ def test_100(self):
+ x, w = lag.laggauss(100)
+
+ # test orthogonality. Note that the results need to be normalized,
+ # otherwise the huge values that can arise from fast growing
+ # functions like Laguerre can be very confusing.
+ v = lag.lagvander(x, 99)
+ vv = np.dot(v.T * w, v)
+ vd = 1/np.sqrt(vv.diagonal())
+ vv = vd[:, None] * vv * vd
+ assert_almost_equal(vv, np.eye(100))
+
+ # check that the integral of 1 is correct
+ tgt = 1.0
+ assert_almost_equal(w.sum(), tgt)
+
+
+class TestMisc:
+
+ def test_lagfromroots(self):
+ res = lag.lagfromroots([])
+ assert_almost_equal(trim(res), [1])
+ for i in range(1, 5):
+ roots = np.cos(np.linspace(-np.pi, 0, 2*i + 1)[1::2])
+ pol = lag.lagfromroots(roots)
+ res = lag.lagval(roots, pol)
+ tgt = 0
+ assert_(len(pol) == i + 1)
+ assert_almost_equal(lag.lag2poly(pol)[-1], 1)
+ assert_almost_equal(res, tgt)
+
+ def test_lagroots(self):
+ assert_almost_equal(lag.lagroots([1]), [])
+ assert_almost_equal(lag.lagroots([0, 1]), [1])
+ for i in range(2, 5):
+ tgt = np.linspace(0, 3, i)
+ res = lag.lagroots(lag.lagfromroots(tgt))
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_lagtrim(self):
+ coef = [2, -1, 1, 0]
+
+ # Test exceptions
+ assert_raises(ValueError, lag.lagtrim, coef, -1)
+
+ # Test results
+ assert_equal(lag.lagtrim(coef), coef[:-1])
+ assert_equal(lag.lagtrim(coef, 1), coef[:-3])
+ assert_equal(lag.lagtrim(coef, 2), [0])
+
+ def test_lagline(self):
+ assert_equal(lag.lagline(3, 4), [7, -4])
+
+ def test_lag2poly(self):
+ for i in range(7):
+ assert_almost_equal(lag.lag2poly([0]*i + [1]), Llist[i])
+
+ def test_poly2lag(self):
+ for i in range(7):
+ assert_almost_equal(lag.poly2lag(Llist[i]), [0]*i + [1])
+
+ def test_weight(self):
+ x = np.linspace(0, 10, 11)
+ tgt = np.exp(-x)
+ res = lag.lagweight(x)
+ assert_almost_equal(res, tgt)
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/test_legendre.py b/lib/python3.12/site-packages/numpy/polynomial/tests/test_legendre.py
new file mode 100644
index 0000000000000000000000000000000000000000..92399c160ecb75fbb1f9a5a7f2bba0fe90d84a54
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/tests/test_legendre.py
@@ -0,0 +1,568 @@
+"""Tests for legendre module.
+
+"""
+from functools import reduce
+
+import numpy as np
+import numpy.polynomial.legendre as leg
+from numpy.polynomial.polynomial import polyval
+from numpy.testing import (
+ assert_almost_equal, assert_raises, assert_equal, assert_,
+ )
+
+L0 = np.array([1])
+L1 = np.array([0, 1])
+L2 = np.array([-1, 0, 3])/2
+L3 = np.array([0, -3, 0, 5])/2
+L4 = np.array([3, 0, -30, 0, 35])/8
+L5 = np.array([0, 15, 0, -70, 0, 63])/8
+L6 = np.array([-5, 0, 105, 0, -315, 0, 231])/16
+L7 = np.array([0, -35, 0, 315, 0, -693, 0, 429])/16
+L8 = np.array([35, 0, -1260, 0, 6930, 0, -12012, 0, 6435])/128
+L9 = np.array([0, 315, 0, -4620, 0, 18018, 0, -25740, 0, 12155])/128
+
+Llist = [L0, L1, L2, L3, L4, L5, L6, L7, L8, L9]
+
+
+def trim(x):
+ return leg.legtrim(x, tol=1e-6)
+
+
+class TestConstants:
+
+ def test_legdomain(self):
+ assert_equal(leg.legdomain, [-1, 1])
+
+ def test_legzero(self):
+ assert_equal(leg.legzero, [0])
+
+ def test_legone(self):
+ assert_equal(leg.legone, [1])
+
+ def test_legx(self):
+ assert_equal(leg.legx, [0, 1])
+
+
+class TestArithmetic:
+ x = np.linspace(-1, 1, 100)
+
+ def test_legadd(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ tgt = np.zeros(max(i, j) + 1)
+ tgt[i] += 1
+ tgt[j] += 1
+ res = leg.legadd([0]*i + [1], [0]*j + [1])
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_legsub(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ tgt = np.zeros(max(i, j) + 1)
+ tgt[i] += 1
+ tgt[j] -= 1
+ res = leg.legsub([0]*i + [1], [0]*j + [1])
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_legmulx(self):
+ assert_equal(leg.legmulx([0]), [0])
+ assert_equal(leg.legmulx([1]), [0, 1])
+ for i in range(1, 5):
+ tmp = 2*i + 1
+ ser = [0]*i + [1]
+ tgt = [0]*(i - 1) + [i/tmp, 0, (i + 1)/tmp]
+ assert_equal(leg.legmulx(ser), tgt)
+
+ def test_legmul(self):
+ # check values of result
+ for i in range(5):
+ pol1 = [0]*i + [1]
+ val1 = leg.legval(self.x, pol1)
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ pol2 = [0]*j + [1]
+ val2 = leg.legval(self.x, pol2)
+ pol3 = leg.legmul(pol1, pol2)
+ val3 = leg.legval(self.x, pol3)
+ assert_(len(pol3) == i + j + 1, msg)
+ assert_almost_equal(val3, val1*val2, err_msg=msg)
+
+ def test_legdiv(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ ci = [0]*i + [1]
+ cj = [0]*j + [1]
+ tgt = leg.legadd(ci, cj)
+ quo, rem = leg.legdiv(tgt, ci)
+ res = leg.legadd(leg.legmul(quo, ci), rem)
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_legpow(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ c = np.arange(i + 1)
+ tgt = reduce(leg.legmul, [c]*j, np.array([1]))
+ res = leg.legpow(c, j)
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+
+class TestEvaluation:
+ # coefficients of 1 + 2*x + 3*x**2
+ c1d = np.array([2., 2., 2.])
+ c2d = np.einsum('i,j->ij', c1d, c1d)
+ c3d = np.einsum('i,j,k->ijk', c1d, c1d, c1d)
+
+ # some random values in [-1, 1)
+ x = np.random.random((3, 5))*2 - 1
+ y = polyval(x, [1., 2., 3.])
+
+ def test_legval(self):
+ #check empty input
+ assert_equal(leg.legval([], [1]).size, 0)
+
+ #check normal input)
+ x = np.linspace(-1, 1)
+ y = [polyval(x, c) for c in Llist]
+ for i in range(10):
+ msg = f"At i={i}"
+ tgt = y[i]
+ res = leg.legval(x, [0]*i + [1])
+ assert_almost_equal(res, tgt, err_msg=msg)
+
+ #check that shape is preserved
+ for i in range(3):
+ dims = [2]*i
+ x = np.zeros(dims)
+ assert_equal(leg.legval(x, [1]).shape, dims)
+ assert_equal(leg.legval(x, [1, 0]).shape, dims)
+ assert_equal(leg.legval(x, [1, 0, 0]).shape, dims)
+
+ def test_legval2d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test exceptions
+ assert_raises(ValueError, leg.legval2d, x1, x2[:2], self.c2d)
+
+ #test values
+ tgt = y1*y2
+ res = leg.legval2d(x1, x2, self.c2d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = leg.legval2d(z, z, self.c2d)
+ assert_(res.shape == (2, 3))
+
+ def test_legval3d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test exceptions
+ assert_raises(ValueError, leg.legval3d, x1, x2, x3[:2], self.c3d)
+
+ #test values
+ tgt = y1*y2*y3
+ res = leg.legval3d(x1, x2, x3, self.c3d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = leg.legval3d(z, z, z, self.c3d)
+ assert_(res.shape == (2, 3))
+
+ def test_leggrid2d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test values
+ tgt = np.einsum('i,j->ij', y1, y2)
+ res = leg.leggrid2d(x1, x2, self.c2d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = leg.leggrid2d(z, z, self.c2d)
+ assert_(res.shape == (2, 3)*2)
+
+ def test_leggrid3d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test values
+ tgt = np.einsum('i,j,k->ijk', y1, y2, y3)
+ res = leg.leggrid3d(x1, x2, x3, self.c3d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = leg.leggrid3d(z, z, z, self.c3d)
+ assert_(res.shape == (2, 3)*3)
+
+
+class TestIntegral:
+
+ def test_legint(self):
+ # check exceptions
+ assert_raises(TypeError, leg.legint, [0], .5)
+ assert_raises(ValueError, leg.legint, [0], -1)
+ assert_raises(ValueError, leg.legint, [0], 1, [0, 0])
+ assert_raises(ValueError, leg.legint, [0], lbnd=[0])
+ assert_raises(ValueError, leg.legint, [0], scl=[0])
+ assert_raises(TypeError, leg.legint, [0], axis=.5)
+
+ # test integration of zero polynomial
+ for i in range(2, 5):
+ k = [0]*(i - 2) + [1]
+ res = leg.legint([0], m=i, k=k)
+ assert_almost_equal(res, [0, 1])
+
+ # check single integration with integration constant
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ tgt = [i] + [0]*i + [1/scl]
+ legpol = leg.poly2leg(pol)
+ legint = leg.legint(legpol, m=1, k=[i])
+ res = leg.leg2poly(legint)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check single integration with integration constant and lbnd
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ legpol = leg.poly2leg(pol)
+ legint = leg.legint(legpol, m=1, k=[i], lbnd=-1)
+ assert_almost_equal(leg.legval(-1, legint), i)
+
+ # check single integration with integration constant and scaling
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ tgt = [i] + [0]*i + [2/scl]
+ legpol = leg.poly2leg(pol)
+ legint = leg.legint(legpol, m=1, k=[i], scl=2)
+ res = leg.leg2poly(legint)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with default k
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = leg.legint(tgt, m=1)
+ res = leg.legint(pol, m=j)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with defined k
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = leg.legint(tgt, m=1, k=[k])
+ res = leg.legint(pol, m=j, k=list(range(j)))
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with lbnd
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = leg.legint(tgt, m=1, k=[k], lbnd=-1)
+ res = leg.legint(pol, m=j, k=list(range(j)), lbnd=-1)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with scaling
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = leg.legint(tgt, m=1, k=[k], scl=2)
+ res = leg.legint(pol, m=j, k=list(range(j)), scl=2)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_legint_axis(self):
+ # check that axis keyword works
+ c2d = np.random.random((3, 4))
+
+ tgt = np.vstack([leg.legint(c) for c in c2d.T]).T
+ res = leg.legint(c2d, axis=0)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([leg.legint(c) for c in c2d])
+ res = leg.legint(c2d, axis=1)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([leg.legint(c, k=3) for c in c2d])
+ res = leg.legint(c2d, k=3, axis=1)
+ assert_almost_equal(res, tgt)
+
+ def test_legint_zerointord(self):
+ assert_equal(leg.legint((1, 2, 3), 0), (1, 2, 3))
+
+
+class TestDerivative:
+
+ def test_legder(self):
+ # check exceptions
+ assert_raises(TypeError, leg.legder, [0], .5)
+ assert_raises(ValueError, leg.legder, [0], -1)
+
+ # check that zeroth derivative does nothing
+ for i in range(5):
+ tgt = [0]*i + [1]
+ res = leg.legder(tgt, m=0)
+ assert_equal(trim(res), trim(tgt))
+
+ # check that derivation is the inverse of integration
+ for i in range(5):
+ for j in range(2, 5):
+ tgt = [0]*i + [1]
+ res = leg.legder(leg.legint(tgt, m=j), m=j)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check derivation with scaling
+ for i in range(5):
+ for j in range(2, 5):
+ tgt = [0]*i + [1]
+ res = leg.legder(leg.legint(tgt, m=j, scl=2), m=j, scl=.5)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_legder_axis(self):
+ # check that axis keyword works
+ c2d = np.random.random((3, 4))
+
+ tgt = np.vstack([leg.legder(c) for c in c2d.T]).T
+ res = leg.legder(c2d, axis=0)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([leg.legder(c) for c in c2d])
+ res = leg.legder(c2d, axis=1)
+ assert_almost_equal(res, tgt)
+
+ def test_legder_orderhigherthancoeff(self):
+ c = (1, 2, 3, 4)
+ assert_equal(leg.legder(c, 4), [0])
+
+class TestVander:
+ # some random values in [-1, 1)
+ x = np.random.random((3, 5))*2 - 1
+
+ def test_legvander(self):
+ # check for 1d x
+ x = np.arange(3)
+ v = leg.legvander(x, 3)
+ assert_(v.shape == (3, 4))
+ for i in range(4):
+ coef = [0]*i + [1]
+ assert_almost_equal(v[..., i], leg.legval(x, coef))
+
+ # check for 2d x
+ x = np.array([[1, 2], [3, 4], [5, 6]])
+ v = leg.legvander(x, 3)
+ assert_(v.shape == (3, 2, 4))
+ for i in range(4):
+ coef = [0]*i + [1]
+ assert_almost_equal(v[..., i], leg.legval(x, coef))
+
+ def test_legvander2d(self):
+ # also tests polyval2d for non-square coefficient array
+ x1, x2, x3 = self.x
+ c = np.random.random((2, 3))
+ van = leg.legvander2d(x1, x2, [1, 2])
+ tgt = leg.legval2d(x1, x2, c)
+ res = np.dot(van, c.flat)
+ assert_almost_equal(res, tgt)
+
+ # check shape
+ van = leg.legvander2d([x1], [x2], [1, 2])
+ assert_(van.shape == (1, 5, 6))
+
+ def test_legvander3d(self):
+ # also tests polyval3d for non-square coefficient array
+ x1, x2, x3 = self.x
+ c = np.random.random((2, 3, 4))
+ van = leg.legvander3d(x1, x2, x3, [1, 2, 3])
+ tgt = leg.legval3d(x1, x2, x3, c)
+ res = np.dot(van, c.flat)
+ assert_almost_equal(res, tgt)
+
+ # check shape
+ van = leg.legvander3d([x1], [x2], [x3], [1, 2, 3])
+ assert_(van.shape == (1, 5, 24))
+
+ def test_legvander_negdeg(self):
+ assert_raises(ValueError, leg.legvander, (1, 2, 3), -1)
+
+
+class TestFitting:
+
+ def test_legfit(self):
+ def f(x):
+ return x*(x - 1)*(x - 2)
+
+ def f2(x):
+ return x**4 + x**2 + 1
+
+ # Test exceptions
+ assert_raises(ValueError, leg.legfit, [1], [1], -1)
+ assert_raises(TypeError, leg.legfit, [[1]], [1], 0)
+ assert_raises(TypeError, leg.legfit, [], [1], 0)
+ assert_raises(TypeError, leg.legfit, [1], [[[1]]], 0)
+ assert_raises(TypeError, leg.legfit, [1, 2], [1], 0)
+ assert_raises(TypeError, leg.legfit, [1], [1, 2], 0)
+ assert_raises(TypeError, leg.legfit, [1], [1], 0, w=[[1]])
+ assert_raises(TypeError, leg.legfit, [1], [1], 0, w=[1, 1])
+ assert_raises(ValueError, leg.legfit, [1], [1], [-1,])
+ assert_raises(ValueError, leg.legfit, [1], [1], [2, -1, 6])
+ assert_raises(TypeError, leg.legfit, [1], [1], [])
+
+ # Test fit
+ x = np.linspace(0, 2)
+ y = f(x)
+ #
+ coef3 = leg.legfit(x, y, 3)
+ assert_equal(len(coef3), 4)
+ assert_almost_equal(leg.legval(x, coef3), y)
+ coef3 = leg.legfit(x, y, [0, 1, 2, 3])
+ assert_equal(len(coef3), 4)
+ assert_almost_equal(leg.legval(x, coef3), y)
+ #
+ coef4 = leg.legfit(x, y, 4)
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(leg.legval(x, coef4), y)
+ coef4 = leg.legfit(x, y, [0, 1, 2, 3, 4])
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(leg.legval(x, coef4), y)
+ # check things still work if deg is not in strict increasing
+ coef4 = leg.legfit(x, y, [2, 3, 4, 1, 0])
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(leg.legval(x, coef4), y)
+ #
+ coef2d = leg.legfit(x, np.array([y, y]).T, 3)
+ assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
+ coef2d = leg.legfit(x, np.array([y, y]).T, [0, 1, 2, 3])
+ assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
+ # test weighting
+ w = np.zeros_like(x)
+ yw = y.copy()
+ w[1::2] = 1
+ y[0::2] = 0
+ wcoef3 = leg.legfit(x, yw, 3, w=w)
+ assert_almost_equal(wcoef3, coef3)
+ wcoef3 = leg.legfit(x, yw, [0, 1, 2, 3], w=w)
+ assert_almost_equal(wcoef3, coef3)
+ #
+ wcoef2d = leg.legfit(x, np.array([yw, yw]).T, 3, w=w)
+ assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
+ wcoef2d = leg.legfit(x, np.array([yw, yw]).T, [0, 1, 2, 3], w=w)
+ assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
+ # test scaling with complex values x points whose square
+ # is zero when summed.
+ x = [1, 1j, -1, -1j]
+ assert_almost_equal(leg.legfit(x, x, 1), [0, 1])
+ assert_almost_equal(leg.legfit(x, x, [0, 1]), [0, 1])
+ # test fitting only even Legendre polynomials
+ x = np.linspace(-1, 1)
+ y = f2(x)
+ coef1 = leg.legfit(x, y, 4)
+ assert_almost_equal(leg.legval(x, coef1), y)
+ coef2 = leg.legfit(x, y, [0, 2, 4])
+ assert_almost_equal(leg.legval(x, coef2), y)
+ assert_almost_equal(coef1, coef2)
+
+
+class TestCompanion:
+
+ def test_raises(self):
+ assert_raises(ValueError, leg.legcompanion, [])
+ assert_raises(ValueError, leg.legcompanion, [1])
+
+ def test_dimensions(self):
+ for i in range(1, 5):
+ coef = [0]*i + [1]
+ assert_(leg.legcompanion(coef).shape == (i, i))
+
+ def test_linear_root(self):
+ assert_(leg.legcompanion([1, 2])[0, 0] == -.5)
+
+
+class TestGauss:
+
+ def test_100(self):
+ x, w = leg.leggauss(100)
+
+ # test orthogonality. Note that the results need to be normalized,
+ # otherwise the huge values that can arise from fast growing
+ # functions like Laguerre can be very confusing.
+ v = leg.legvander(x, 99)
+ vv = np.dot(v.T * w, v)
+ vd = 1/np.sqrt(vv.diagonal())
+ vv = vd[:, None] * vv * vd
+ assert_almost_equal(vv, np.eye(100))
+
+ # check that the integral of 1 is correct
+ tgt = 2.0
+ assert_almost_equal(w.sum(), tgt)
+
+
+class TestMisc:
+
+ def test_legfromroots(self):
+ res = leg.legfromroots([])
+ assert_almost_equal(trim(res), [1])
+ for i in range(1, 5):
+ roots = np.cos(np.linspace(-np.pi, 0, 2*i + 1)[1::2])
+ pol = leg.legfromroots(roots)
+ res = leg.legval(roots, pol)
+ tgt = 0
+ assert_(len(pol) == i + 1)
+ assert_almost_equal(leg.leg2poly(pol)[-1], 1)
+ assert_almost_equal(res, tgt)
+
+ def test_legroots(self):
+ assert_almost_equal(leg.legroots([1]), [])
+ assert_almost_equal(leg.legroots([1, 2]), [-.5])
+ for i in range(2, 5):
+ tgt = np.linspace(-1, 1, i)
+ res = leg.legroots(leg.legfromroots(tgt))
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_legtrim(self):
+ coef = [2, -1, 1, 0]
+
+ # Test exceptions
+ assert_raises(ValueError, leg.legtrim, coef, -1)
+
+ # Test results
+ assert_equal(leg.legtrim(coef), coef[:-1])
+ assert_equal(leg.legtrim(coef, 1), coef[:-3])
+ assert_equal(leg.legtrim(coef, 2), [0])
+
+ def test_legline(self):
+ assert_equal(leg.legline(3, 4), [3, 4])
+
+ def test_legline_zeroscl(self):
+ assert_equal(leg.legline(3, 0), [3])
+
+ def test_leg2poly(self):
+ for i in range(10):
+ assert_almost_equal(leg.leg2poly([0]*i + [1]), Llist[i])
+
+ def test_poly2leg(self):
+ for i in range(10):
+ assert_almost_equal(leg.poly2leg(Llist[i]), [0]*i + [1])
+
+ def test_weight(self):
+ x = np.linspace(-1, 1, 11)
+ tgt = 1.
+ res = leg.legweight(x)
+ assert_almost_equal(res, tgt)
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/test_polynomial.py b/lib/python3.12/site-packages/numpy/polynomial/tests/test_polynomial.py
new file mode 100644
index 0000000000000000000000000000000000000000..6b3ef2388f630f0233c79f31a9a1f4039f4e4f4a
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/tests/test_polynomial.py
@@ -0,0 +1,611 @@
+"""Tests for polynomial module.
+
+"""
+from functools import reduce
+
+import numpy as np
+import numpy.polynomial.polynomial as poly
+import pickle
+from copy import deepcopy
+from numpy.testing import (
+ assert_almost_equal, assert_raises, assert_equal, assert_,
+ assert_warns, assert_array_equal, assert_raises_regex)
+
+
+def trim(x):
+ return poly.polytrim(x, tol=1e-6)
+
+T0 = [1]
+T1 = [0, 1]
+T2 = [-1, 0, 2]
+T3 = [0, -3, 0, 4]
+T4 = [1, 0, -8, 0, 8]
+T5 = [0, 5, 0, -20, 0, 16]
+T6 = [-1, 0, 18, 0, -48, 0, 32]
+T7 = [0, -7, 0, 56, 0, -112, 0, 64]
+T8 = [1, 0, -32, 0, 160, 0, -256, 0, 128]
+T9 = [0, 9, 0, -120, 0, 432, 0, -576, 0, 256]
+
+Tlist = [T0, T1, T2, T3, T4, T5, T6, T7, T8, T9]
+
+
+class TestConstants:
+
+ def test_polydomain(self):
+ assert_equal(poly.polydomain, [-1, 1])
+
+ def test_polyzero(self):
+ assert_equal(poly.polyzero, [0])
+
+ def test_polyone(self):
+ assert_equal(poly.polyone, [1])
+
+ def test_polyx(self):
+ assert_equal(poly.polyx, [0, 1])
+
+ def test_copy(self):
+ x = poly.Polynomial([1, 2, 3])
+ y = deepcopy(x)
+ assert_equal(x, y)
+
+ def test_pickle(self):
+ x = poly.Polynomial([1, 2, 3])
+ y = pickle.loads(pickle.dumps(x))
+ assert_equal(x, y)
+
+class TestArithmetic:
+
+ def test_polyadd(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ tgt = np.zeros(max(i, j) + 1)
+ tgt[i] += 1
+ tgt[j] += 1
+ res = poly.polyadd([0]*i + [1], [0]*j + [1])
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_polysub(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ tgt = np.zeros(max(i, j) + 1)
+ tgt[i] += 1
+ tgt[j] -= 1
+ res = poly.polysub([0]*i + [1], [0]*j + [1])
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_polymulx(self):
+ assert_equal(poly.polymulx([0]), [0])
+ assert_equal(poly.polymulx([1]), [0, 1])
+ for i in range(1, 5):
+ ser = [0]*i + [1]
+ tgt = [0]*(i + 1) + [1]
+ assert_equal(poly.polymulx(ser), tgt)
+
+ def test_polymul(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ tgt = np.zeros(i + j + 1)
+ tgt[i + j] += 1
+ res = poly.polymul([0]*i + [1], [0]*j + [1])
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+ def test_polydiv(self):
+ # check zero division
+ assert_raises(ZeroDivisionError, poly.polydiv, [1], [0])
+
+ # check scalar division
+ quo, rem = poly.polydiv([2], [2])
+ assert_equal((quo, rem), (1, 0))
+ quo, rem = poly.polydiv([2, 2], [2])
+ assert_equal((quo, rem), ((1, 1), 0))
+
+ # check rest.
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ ci = [0]*i + [1, 2]
+ cj = [0]*j + [1, 2]
+ tgt = poly.polyadd(ci, cj)
+ quo, rem = poly.polydiv(tgt, ci)
+ res = poly.polyadd(poly.polymul(quo, ci), rem)
+ assert_equal(res, tgt, err_msg=msg)
+
+ def test_polypow(self):
+ for i in range(5):
+ for j in range(5):
+ msg = f"At i={i}, j={j}"
+ c = np.arange(i + 1)
+ tgt = reduce(poly.polymul, [c]*j, np.array([1]))
+ res = poly.polypow(c, j)
+ assert_equal(trim(res), trim(tgt), err_msg=msg)
+
+
+class TestEvaluation:
+ # coefficients of 1 + 2*x + 3*x**2
+ c1d = np.array([1., 2., 3.])
+ c2d = np.einsum('i,j->ij', c1d, c1d)
+ c3d = np.einsum('i,j,k->ijk', c1d, c1d, c1d)
+
+ # some random values in [-1, 1)
+ x = np.random.random((3, 5))*2 - 1
+ y = poly.polyval(x, [1., 2., 3.])
+
+ def test_polyval(self):
+ #check empty input
+ assert_equal(poly.polyval([], [1]).size, 0)
+
+ #check normal input)
+ x = np.linspace(-1, 1)
+ y = [x**i for i in range(5)]
+ for i in range(5):
+ tgt = y[i]
+ res = poly.polyval(x, [0]*i + [1])
+ assert_almost_equal(res, tgt)
+ tgt = x*(x**2 - 1)
+ res = poly.polyval(x, [0, -1, 0, 1])
+ assert_almost_equal(res, tgt)
+
+ #check that shape is preserved
+ for i in range(3):
+ dims = [2]*i
+ x = np.zeros(dims)
+ assert_equal(poly.polyval(x, [1]).shape, dims)
+ assert_equal(poly.polyval(x, [1, 0]).shape, dims)
+ assert_equal(poly.polyval(x, [1, 0, 0]).shape, dims)
+
+ #check masked arrays are processed correctly
+ mask = [False, True, False]
+ mx = np.ma.array([1, 2, 3], mask=mask)
+ res = np.polyval([7, 5, 3], mx)
+ assert_array_equal(res.mask, mask)
+
+ #check subtypes of ndarray are preserved
+ class C(np.ndarray):
+ pass
+
+ cx = np.array([1, 2, 3]).view(C)
+ assert_equal(type(np.polyval([2, 3, 4], cx)), C)
+
+ def test_polyvalfromroots(self):
+ # check exception for broadcasting x values over root array with
+ # too few dimensions
+ assert_raises(ValueError, poly.polyvalfromroots,
+ [1], [1], tensor=False)
+
+ # check empty input
+ assert_equal(poly.polyvalfromroots([], [1]).size, 0)
+ assert_(poly.polyvalfromroots([], [1]).shape == (0,))
+
+ # check empty input + multidimensional roots
+ assert_equal(poly.polyvalfromroots([], [[1] * 5]).size, 0)
+ assert_(poly.polyvalfromroots([], [[1] * 5]).shape == (5, 0))
+
+ # check scalar input
+ assert_equal(poly.polyvalfromroots(1, 1), 0)
+ assert_(poly.polyvalfromroots(1, np.ones((3, 3))).shape == (3,))
+
+ # check normal input)
+ x = np.linspace(-1, 1)
+ y = [x**i for i in range(5)]
+ for i in range(1, 5):
+ tgt = y[i]
+ res = poly.polyvalfromroots(x, [0]*i)
+ assert_almost_equal(res, tgt)
+ tgt = x*(x - 1)*(x + 1)
+ res = poly.polyvalfromroots(x, [-1, 0, 1])
+ assert_almost_equal(res, tgt)
+
+ # check that shape is preserved
+ for i in range(3):
+ dims = [2]*i
+ x = np.zeros(dims)
+ assert_equal(poly.polyvalfromroots(x, [1]).shape, dims)
+ assert_equal(poly.polyvalfromroots(x, [1, 0]).shape, dims)
+ assert_equal(poly.polyvalfromroots(x, [1, 0, 0]).shape, dims)
+
+ # check compatibility with factorization
+ ptest = [15, 2, -16, -2, 1]
+ r = poly.polyroots(ptest)
+ x = np.linspace(-1, 1)
+ assert_almost_equal(poly.polyval(x, ptest),
+ poly.polyvalfromroots(x, r))
+
+ # check multidimensional arrays of roots and values
+ # check tensor=False
+ rshape = (3, 5)
+ x = np.arange(-3, 2)
+ r = np.random.randint(-5, 5, size=rshape)
+ res = poly.polyvalfromroots(x, r, tensor=False)
+ tgt = np.empty(r.shape[1:])
+ for ii in range(tgt.size):
+ tgt[ii] = poly.polyvalfromroots(x[ii], r[:, ii])
+ assert_equal(res, tgt)
+
+ # check tensor=True
+ x = np.vstack([x, 2*x])
+ res = poly.polyvalfromroots(x, r, tensor=True)
+ tgt = np.empty(r.shape[1:] + x.shape)
+ for ii in range(r.shape[1]):
+ for jj in range(x.shape[0]):
+ tgt[ii, jj, :] = poly.polyvalfromroots(x[jj], r[:, ii])
+ assert_equal(res, tgt)
+
+ def test_polyval2d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test exceptions
+ assert_raises_regex(ValueError, 'incompatible',
+ poly.polyval2d, x1, x2[:2], self.c2d)
+
+ #test values
+ tgt = y1*y2
+ res = poly.polyval2d(x1, x2, self.c2d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = poly.polyval2d(z, z, self.c2d)
+ assert_(res.shape == (2, 3))
+
+ def test_polyval3d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test exceptions
+ assert_raises_regex(ValueError, 'incompatible',
+ poly.polyval3d, x1, x2, x3[:2], self.c3d)
+
+ #test values
+ tgt = y1*y2*y3
+ res = poly.polyval3d(x1, x2, x3, self.c3d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = poly.polyval3d(z, z, z, self.c3d)
+ assert_(res.shape == (2, 3))
+
+ def test_polygrid2d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test values
+ tgt = np.einsum('i,j->ij', y1, y2)
+ res = poly.polygrid2d(x1, x2, self.c2d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = poly.polygrid2d(z, z, self.c2d)
+ assert_(res.shape == (2, 3)*2)
+
+ def test_polygrid3d(self):
+ x1, x2, x3 = self.x
+ y1, y2, y3 = self.y
+
+ #test values
+ tgt = np.einsum('i,j,k->ijk', y1, y2, y3)
+ res = poly.polygrid3d(x1, x2, x3, self.c3d)
+ assert_almost_equal(res, tgt)
+
+ #test shape
+ z = np.ones((2, 3))
+ res = poly.polygrid3d(z, z, z, self.c3d)
+ assert_(res.shape == (2, 3)*3)
+
+
+class TestIntegral:
+
+ def test_polyint(self):
+ # check exceptions
+ assert_raises(TypeError, poly.polyint, [0], .5)
+ assert_raises(ValueError, poly.polyint, [0], -1)
+ assert_raises(ValueError, poly.polyint, [0], 1, [0, 0])
+ assert_raises(ValueError, poly.polyint, [0], lbnd=[0])
+ assert_raises(ValueError, poly.polyint, [0], scl=[0])
+ assert_raises(TypeError, poly.polyint, [0], axis=.5)
+ with assert_warns(DeprecationWarning):
+ poly.polyint([1, 1], 1.)
+
+ # test integration of zero polynomial
+ for i in range(2, 5):
+ k = [0]*(i - 2) + [1]
+ res = poly.polyint([0], m=i, k=k)
+ assert_almost_equal(res, [0, 1])
+
+ # check single integration with integration constant
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ tgt = [i] + [0]*i + [1/scl]
+ res = poly.polyint(pol, m=1, k=[i])
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check single integration with integration constant and lbnd
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ res = poly.polyint(pol, m=1, k=[i], lbnd=-1)
+ assert_almost_equal(poly.polyval(-1, res), i)
+
+ # check single integration with integration constant and scaling
+ for i in range(5):
+ scl = i + 1
+ pol = [0]*i + [1]
+ tgt = [i] + [0]*i + [2/scl]
+ res = poly.polyint(pol, m=1, k=[i], scl=2)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with default k
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = poly.polyint(tgt, m=1)
+ res = poly.polyint(pol, m=j)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with defined k
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = poly.polyint(tgt, m=1, k=[k])
+ res = poly.polyint(pol, m=j, k=list(range(j)))
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with lbnd
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = poly.polyint(tgt, m=1, k=[k], lbnd=-1)
+ res = poly.polyint(pol, m=j, k=list(range(j)), lbnd=-1)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check multiple integrations with scaling
+ for i in range(5):
+ for j in range(2, 5):
+ pol = [0]*i + [1]
+ tgt = pol[:]
+ for k in range(j):
+ tgt = poly.polyint(tgt, m=1, k=[k], scl=2)
+ res = poly.polyint(pol, m=j, k=list(range(j)), scl=2)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_polyint_axis(self):
+ # check that axis keyword works
+ c2d = np.random.random((3, 4))
+
+ tgt = np.vstack([poly.polyint(c) for c in c2d.T]).T
+ res = poly.polyint(c2d, axis=0)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([poly.polyint(c) for c in c2d])
+ res = poly.polyint(c2d, axis=1)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([poly.polyint(c, k=3) for c in c2d])
+ res = poly.polyint(c2d, k=3, axis=1)
+ assert_almost_equal(res, tgt)
+
+
+class TestDerivative:
+
+ def test_polyder(self):
+ # check exceptions
+ assert_raises(TypeError, poly.polyder, [0], .5)
+ assert_raises(ValueError, poly.polyder, [0], -1)
+
+ # check that zeroth derivative does nothing
+ for i in range(5):
+ tgt = [0]*i + [1]
+ res = poly.polyder(tgt, m=0)
+ assert_equal(trim(res), trim(tgt))
+
+ # check that derivation is the inverse of integration
+ for i in range(5):
+ for j in range(2, 5):
+ tgt = [0]*i + [1]
+ res = poly.polyder(poly.polyint(tgt, m=j), m=j)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ # check derivation with scaling
+ for i in range(5):
+ for j in range(2, 5):
+ tgt = [0]*i + [1]
+ res = poly.polyder(poly.polyint(tgt, m=j, scl=2), m=j, scl=.5)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_polyder_axis(self):
+ # check that axis keyword works
+ c2d = np.random.random((3, 4))
+
+ tgt = np.vstack([poly.polyder(c) for c in c2d.T]).T
+ res = poly.polyder(c2d, axis=0)
+ assert_almost_equal(res, tgt)
+
+ tgt = np.vstack([poly.polyder(c) for c in c2d])
+ res = poly.polyder(c2d, axis=1)
+ assert_almost_equal(res, tgt)
+
+
+class TestVander:
+ # some random values in [-1, 1)
+ x = np.random.random((3, 5))*2 - 1
+
+ def test_polyvander(self):
+ # check for 1d x
+ x = np.arange(3)
+ v = poly.polyvander(x, 3)
+ assert_(v.shape == (3, 4))
+ for i in range(4):
+ coef = [0]*i + [1]
+ assert_almost_equal(v[..., i], poly.polyval(x, coef))
+
+ # check for 2d x
+ x = np.array([[1, 2], [3, 4], [5, 6]])
+ v = poly.polyvander(x, 3)
+ assert_(v.shape == (3, 2, 4))
+ for i in range(4):
+ coef = [0]*i + [1]
+ assert_almost_equal(v[..., i], poly.polyval(x, coef))
+
+ def test_polyvander2d(self):
+ # also tests polyval2d for non-square coefficient array
+ x1, x2, x3 = self.x
+ c = np.random.random((2, 3))
+ van = poly.polyvander2d(x1, x2, [1, 2])
+ tgt = poly.polyval2d(x1, x2, c)
+ res = np.dot(van, c.flat)
+ assert_almost_equal(res, tgt)
+
+ # check shape
+ van = poly.polyvander2d([x1], [x2], [1, 2])
+ assert_(van.shape == (1, 5, 6))
+
+ def test_polyvander3d(self):
+ # also tests polyval3d for non-square coefficient array
+ x1, x2, x3 = self.x
+ c = np.random.random((2, 3, 4))
+ van = poly.polyvander3d(x1, x2, x3, [1, 2, 3])
+ tgt = poly.polyval3d(x1, x2, x3, c)
+ res = np.dot(van, c.flat)
+ assert_almost_equal(res, tgt)
+
+ # check shape
+ van = poly.polyvander3d([x1], [x2], [x3], [1, 2, 3])
+ assert_(van.shape == (1, 5, 24))
+
+ def test_polyvandernegdeg(self):
+ x = np.arange(3)
+ assert_raises(ValueError, poly.polyvander, x, -1)
+
+
+class TestCompanion:
+
+ def test_raises(self):
+ assert_raises(ValueError, poly.polycompanion, [])
+ assert_raises(ValueError, poly.polycompanion, [1])
+
+ def test_dimensions(self):
+ for i in range(1, 5):
+ coef = [0]*i + [1]
+ assert_(poly.polycompanion(coef).shape == (i, i))
+
+ def test_linear_root(self):
+ assert_(poly.polycompanion([1, 2])[0, 0] == -.5)
+
+
+class TestMisc:
+
+ def test_polyfromroots(self):
+ res = poly.polyfromroots([])
+ assert_almost_equal(trim(res), [1])
+ for i in range(1, 5):
+ roots = np.cos(np.linspace(-np.pi, 0, 2*i + 1)[1::2])
+ tgt = Tlist[i]
+ res = poly.polyfromroots(roots)*2**(i-1)
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_polyroots(self):
+ assert_almost_equal(poly.polyroots([1]), [])
+ assert_almost_equal(poly.polyroots([1, 2]), [-.5])
+ for i in range(2, 5):
+ tgt = np.linspace(-1, 1, i)
+ res = poly.polyroots(poly.polyfromroots(tgt))
+ assert_almost_equal(trim(res), trim(tgt))
+
+ def test_polyfit(self):
+ def f(x):
+ return x*(x - 1)*(x - 2)
+
+ def f2(x):
+ return x**4 + x**2 + 1
+
+ # Test exceptions
+ assert_raises(ValueError, poly.polyfit, [1], [1], -1)
+ assert_raises(TypeError, poly.polyfit, [[1]], [1], 0)
+ assert_raises(TypeError, poly.polyfit, [], [1], 0)
+ assert_raises(TypeError, poly.polyfit, [1], [[[1]]], 0)
+ assert_raises(TypeError, poly.polyfit, [1, 2], [1], 0)
+ assert_raises(TypeError, poly.polyfit, [1], [1, 2], 0)
+ assert_raises(TypeError, poly.polyfit, [1], [1], 0, w=[[1]])
+ assert_raises(TypeError, poly.polyfit, [1], [1], 0, w=[1, 1])
+ assert_raises(ValueError, poly.polyfit, [1], [1], [-1,])
+ assert_raises(ValueError, poly.polyfit, [1], [1], [2, -1, 6])
+ assert_raises(TypeError, poly.polyfit, [1], [1], [])
+
+ # Test fit
+ x = np.linspace(0, 2)
+ y = f(x)
+ #
+ coef3 = poly.polyfit(x, y, 3)
+ assert_equal(len(coef3), 4)
+ assert_almost_equal(poly.polyval(x, coef3), y)
+ coef3 = poly.polyfit(x, y, [0, 1, 2, 3])
+ assert_equal(len(coef3), 4)
+ assert_almost_equal(poly.polyval(x, coef3), y)
+ #
+ coef4 = poly.polyfit(x, y, 4)
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(poly.polyval(x, coef4), y)
+ coef4 = poly.polyfit(x, y, [0, 1, 2, 3, 4])
+ assert_equal(len(coef4), 5)
+ assert_almost_equal(poly.polyval(x, coef4), y)
+ #
+ coef2d = poly.polyfit(x, np.array([y, y]).T, 3)
+ assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
+ coef2d = poly.polyfit(x, np.array([y, y]).T, [0, 1, 2, 3])
+ assert_almost_equal(coef2d, np.array([coef3, coef3]).T)
+ # test weighting
+ w = np.zeros_like(x)
+ yw = y.copy()
+ w[1::2] = 1
+ yw[0::2] = 0
+ wcoef3 = poly.polyfit(x, yw, 3, w=w)
+ assert_almost_equal(wcoef3, coef3)
+ wcoef3 = poly.polyfit(x, yw, [0, 1, 2, 3], w=w)
+ assert_almost_equal(wcoef3, coef3)
+ #
+ wcoef2d = poly.polyfit(x, np.array([yw, yw]).T, 3, w=w)
+ assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
+ wcoef2d = poly.polyfit(x, np.array([yw, yw]).T, [0, 1, 2, 3], w=w)
+ assert_almost_equal(wcoef2d, np.array([coef3, coef3]).T)
+ # test scaling with complex values x points whose square
+ # is zero when summed.
+ x = [1, 1j, -1, -1j]
+ assert_almost_equal(poly.polyfit(x, x, 1), [0, 1])
+ assert_almost_equal(poly.polyfit(x, x, [0, 1]), [0, 1])
+ # test fitting only even Polyendre polynomials
+ x = np.linspace(-1, 1)
+ y = f2(x)
+ coef1 = poly.polyfit(x, y, 4)
+ assert_almost_equal(poly.polyval(x, coef1), y)
+ coef2 = poly.polyfit(x, y, [0, 2, 4])
+ assert_almost_equal(poly.polyval(x, coef2), y)
+ assert_almost_equal(coef1, coef2)
+
+ def test_polytrim(self):
+ coef = [2, -1, 1, 0]
+
+ # Test exceptions
+ assert_raises(ValueError, poly.polytrim, coef, -1)
+
+ # Test results
+ assert_equal(poly.polytrim(coef), coef[:-1])
+ assert_equal(poly.polytrim(coef, 1), coef[:-3])
+ assert_equal(poly.polytrim(coef, 2), [0])
+
+ def test_polyline(self):
+ assert_equal(poly.polyline(3, 4), [3, 4])
+
+ def test_polyline_zero(self):
+ assert_equal(poly.polyline(3, 0), [3])
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/test_polyutils.py b/lib/python3.12/site-packages/numpy/polynomial/tests/test_polyutils.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc630790da1ce8fd1ca413cd530ae5636cce5aa8
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/tests/test_polyutils.py
@@ -0,0 +1,121 @@
+"""Tests for polyutils module.
+
+"""
+import numpy as np
+import numpy.polynomial.polyutils as pu
+from numpy.testing import (
+ assert_almost_equal, assert_raises, assert_equal, assert_,
+ )
+
+
+class TestMisc:
+
+ def test_trimseq(self):
+ for i in range(5):
+ tgt = [1]
+ res = pu.trimseq([1] + [0]*5)
+ assert_equal(res, tgt)
+
+ def test_as_series(self):
+ # check exceptions
+ assert_raises(ValueError, pu.as_series, [[]])
+ assert_raises(ValueError, pu.as_series, [[[1, 2]]])
+ assert_raises(ValueError, pu.as_series, [[1], ['a']])
+ # check common types
+ types = ['i', 'd', 'O']
+ for i in range(len(types)):
+ for j in range(i):
+ ci = np.ones(1, types[i])
+ cj = np.ones(1, types[j])
+ [resi, resj] = pu.as_series([ci, cj])
+ assert_(resi.dtype.char == resj.dtype.char)
+ assert_(resj.dtype.char == types[i])
+
+ def test_trimcoef(self):
+ coef = [2, -1, 1, 0]
+ # Test exceptions
+ assert_raises(ValueError, pu.trimcoef, coef, -1)
+ # Test results
+ assert_equal(pu.trimcoef(coef), coef[:-1])
+ assert_equal(pu.trimcoef(coef, 1), coef[:-3])
+ assert_equal(pu.trimcoef(coef, 2), [0])
+
+ def test_vander_nd_exception(self):
+ # n_dims != len(points)
+ assert_raises(ValueError, pu._vander_nd, (), (1, 2, 3), [90])
+ # n_dims != len(degrees)
+ assert_raises(ValueError, pu._vander_nd, (), (), [90.65])
+ # n_dims == 0
+ assert_raises(ValueError, pu._vander_nd, (), (), [])
+
+ def test_div_zerodiv(self):
+ # c2[-1] == 0
+ assert_raises(ZeroDivisionError, pu._div, pu._div, (1, 2, 3), [0])
+
+ def test_pow_too_large(self):
+ # power > maxpower
+ assert_raises(ValueError, pu._pow, (), [1, 2, 3], 5, 4)
+
+class TestDomain:
+
+ def test_getdomain(self):
+ # test for real values
+ x = [1, 10, 3, -1]
+ tgt = [-1, 10]
+ res = pu.getdomain(x)
+ assert_almost_equal(res, tgt)
+
+ # test for complex values
+ x = [1 + 1j, 1 - 1j, 0, 2]
+ tgt = [-1j, 2 + 1j]
+ res = pu.getdomain(x)
+ assert_almost_equal(res, tgt)
+
+ def test_mapdomain(self):
+ # test for real values
+ dom1 = [0, 4]
+ dom2 = [1, 3]
+ tgt = dom2
+ res = pu.mapdomain(dom1, dom1, dom2)
+ assert_almost_equal(res, tgt)
+
+ # test for complex values
+ dom1 = [0 - 1j, 2 + 1j]
+ dom2 = [-2, 2]
+ tgt = dom2
+ x = dom1
+ res = pu.mapdomain(x, dom1, dom2)
+ assert_almost_equal(res, tgt)
+
+ # test for multidimensional arrays
+ dom1 = [0, 4]
+ dom2 = [1, 3]
+ tgt = np.array([dom2, dom2])
+ x = np.array([dom1, dom1])
+ res = pu.mapdomain(x, dom1, dom2)
+ assert_almost_equal(res, tgt)
+
+ # test that subtypes are preserved.
+ class MyNDArray(np.ndarray):
+ pass
+
+ dom1 = [0, 4]
+ dom2 = [1, 3]
+ x = np.array([dom1, dom1]).view(MyNDArray)
+ res = pu.mapdomain(x, dom1, dom2)
+ assert_(isinstance(res, MyNDArray))
+
+ def test_mapparms(self):
+ # test for real values
+ dom1 = [0, 4]
+ dom2 = [1, 3]
+ tgt = [1, .5]
+ res = pu. mapparms(dom1, dom2)
+ assert_almost_equal(res, tgt)
+
+ # test for complex values
+ dom1 = [0 - 1j, 2 + 1j]
+ dom2 = [-2, 2]
+ tgt = [-1 + 1j, 1 - 1j]
+ res = pu.mapparms(dom1, dom2)
+ assert_almost_equal(res, tgt)
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/test_printing.py b/lib/python3.12/site-packages/numpy/polynomial/tests/test_printing.py
new file mode 100644
index 0000000000000000000000000000000000000000..6f2a5092d7225c797b60fd8f2602f2f9276cdd74
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/tests/test_printing.py
@@ -0,0 +1,530 @@
+from math import nan, inf
+import pytest
+from numpy.core import array, arange, printoptions
+import numpy.polynomial as poly
+from numpy.testing import assert_equal, assert_
+
+# For testing polynomial printing with object arrays
+from fractions import Fraction
+from decimal import Decimal
+
+
+class TestStrUnicodeSuperSubscripts:
+
+ @pytest.fixture(scope='class', autouse=True)
+ def use_unicode(self):
+ poly.set_default_printstyle('unicode')
+
+ @pytest.mark.parametrize(('inp', 'tgt'), (
+ ([1, 2, 3], "1.0 + 2.0·x + 3.0·x²"),
+ ([-1, 0, 3, -1], "-1.0 + 0.0·x + 3.0·x² - 1.0·x³"),
+ (arange(12), ("0.0 + 1.0·x + 2.0·x² + 3.0·x³ + 4.0·x⁴ + 5.0·x⁵ + "
+ "6.0·x⁶ + 7.0·x⁷ +\n8.0·x⁸ + 9.0·x⁹ + 10.0·x¹⁰ + "
+ "11.0·x¹¹")),
+ ))
+ def test_polynomial_str(self, inp, tgt):
+ res = str(poly.Polynomial(inp))
+ assert_equal(res, tgt)
+
+ @pytest.mark.parametrize(('inp', 'tgt'), (
+ ([1, 2, 3], "1.0 + 2.0·T₁(x) + 3.0·T₂(x)"),
+ ([-1, 0, 3, -1], "-1.0 + 0.0·T₁(x) + 3.0·T₂(x) - 1.0·T₃(x)"),
+ (arange(12), ("0.0 + 1.0·T₁(x) + 2.0·T₂(x) + 3.0·T₃(x) + 4.0·T₄(x) + "
+ "5.0·T₅(x) +\n6.0·T₆(x) + 7.0·T₇(x) + 8.0·T₈(x) + "
+ "9.0·T₉(x) + 10.0·T₁₀(x) + 11.0·T₁₁(x)")),
+ ))
+ def test_chebyshev_str(self, inp, tgt):
+ res = str(poly.Chebyshev(inp))
+ assert_equal(res, tgt)
+
+ @pytest.mark.parametrize(('inp', 'tgt'), (
+ ([1, 2, 3], "1.0 + 2.0·P₁(x) + 3.0·P₂(x)"),
+ ([-1, 0, 3, -1], "-1.0 + 0.0·P₁(x) + 3.0·P₂(x) - 1.0·P₃(x)"),
+ (arange(12), ("0.0 + 1.0·P₁(x) + 2.0·P₂(x) + 3.0·P₃(x) + 4.0·P₄(x) + "
+ "5.0·P₅(x) +\n6.0·P₆(x) + 7.0·P₇(x) + 8.0·P₈(x) + "
+ "9.0·P₉(x) + 10.0·P₁₀(x) + 11.0·P₁₁(x)")),
+ ))
+ def test_legendre_str(self, inp, tgt):
+ res = str(poly.Legendre(inp))
+ assert_equal(res, tgt)
+
+ @pytest.mark.parametrize(('inp', 'tgt'), (
+ ([1, 2, 3], "1.0 + 2.0·H₁(x) + 3.0·H₂(x)"),
+ ([-1, 0, 3, -1], "-1.0 + 0.0·H₁(x) + 3.0·H₂(x) - 1.0·H₃(x)"),
+ (arange(12), ("0.0 + 1.0·H₁(x) + 2.0·H₂(x) + 3.0·H₃(x) + 4.0·H₄(x) + "
+ "5.0·H₅(x) +\n6.0·H₆(x) + 7.0·H₇(x) + 8.0·H₈(x) + "
+ "9.0·H₉(x) + 10.0·H₁₀(x) + 11.0·H₁₁(x)")),
+ ))
+ def test_hermite_str(self, inp, tgt):
+ res = str(poly.Hermite(inp))
+ assert_equal(res, tgt)
+
+ @pytest.mark.parametrize(('inp', 'tgt'), (
+ ([1, 2, 3], "1.0 + 2.0·He₁(x) + 3.0·He₂(x)"),
+ ([-1, 0, 3, -1], "-1.0 + 0.0·He₁(x) + 3.0·He₂(x) - 1.0·He₃(x)"),
+ (arange(12), ("0.0 + 1.0·He₁(x) + 2.0·He₂(x) + 3.0·He₃(x) + "
+ "4.0·He₄(x) + 5.0·He₅(x) +\n6.0·He₆(x) + 7.0·He₇(x) + "
+ "8.0·He₈(x) + 9.0·He₉(x) + 10.0·He₁₀(x) +\n"
+ "11.0·He₁₁(x)")),
+ ))
+ def test_hermiteE_str(self, inp, tgt):
+ res = str(poly.HermiteE(inp))
+ assert_equal(res, tgt)
+
+ @pytest.mark.parametrize(('inp', 'tgt'), (
+ ([1, 2, 3], "1.0 + 2.0·L₁(x) + 3.0·L₂(x)"),
+ ([-1, 0, 3, -1], "-1.0 + 0.0·L₁(x) + 3.0·L₂(x) - 1.0·L₃(x)"),
+ (arange(12), ("0.0 + 1.0·L₁(x) + 2.0·L₂(x) + 3.0·L₃(x) + 4.0·L₄(x) + "
+ "5.0·L₅(x) +\n6.0·L₆(x) + 7.0·L₇(x) + 8.0·L₈(x) + "
+ "9.0·L₉(x) + 10.0·L₁₀(x) + 11.0·L₁₁(x)")),
+ ))
+ def test_laguerre_str(self, inp, tgt):
+ res = str(poly.Laguerre(inp))
+ assert_equal(res, tgt)
+
+
+class TestStrAscii:
+
+ @pytest.fixture(scope='class', autouse=True)
+ def use_ascii(self):
+ poly.set_default_printstyle('ascii')
+
+ @pytest.mark.parametrize(('inp', 'tgt'), (
+ ([1, 2, 3], "1.0 + 2.0 x + 3.0 x**2"),
+ ([-1, 0, 3, -1], "-1.0 + 0.0 x + 3.0 x**2 - 1.0 x**3"),
+ (arange(12), ("0.0 + 1.0 x + 2.0 x**2 + 3.0 x**3 + 4.0 x**4 + "
+ "5.0 x**5 + 6.0 x**6 +\n7.0 x**7 + 8.0 x**8 + "
+ "9.0 x**9 + 10.0 x**10 + 11.0 x**11")),
+ ))
+ def test_polynomial_str(self, inp, tgt):
+ res = str(poly.Polynomial(inp))
+ assert_equal(res, tgt)
+
+ @pytest.mark.parametrize(('inp', 'tgt'), (
+ ([1, 2, 3], "1.0 + 2.0 T_1(x) + 3.0 T_2(x)"),
+ ([-1, 0, 3, -1], "-1.0 + 0.0 T_1(x) + 3.0 T_2(x) - 1.0 T_3(x)"),
+ (arange(12), ("0.0 + 1.0 T_1(x) + 2.0 T_2(x) + 3.0 T_3(x) + "
+ "4.0 T_4(x) + 5.0 T_5(x) +\n6.0 T_6(x) + 7.0 T_7(x) + "
+ "8.0 T_8(x) + 9.0 T_9(x) + 10.0 T_10(x) +\n"
+ "11.0 T_11(x)")),
+ ))
+ def test_chebyshev_str(self, inp, tgt):
+ res = str(poly.Chebyshev(inp))
+ assert_equal(res, tgt)
+
+ @pytest.mark.parametrize(('inp', 'tgt'), (
+ ([1, 2, 3], "1.0 + 2.0 P_1(x) + 3.0 P_2(x)"),
+ ([-1, 0, 3, -1], "-1.0 + 0.0 P_1(x) + 3.0 P_2(x) - 1.0 P_3(x)"),
+ (arange(12), ("0.0 + 1.0 P_1(x) + 2.0 P_2(x) + 3.0 P_3(x) + "
+ "4.0 P_4(x) + 5.0 P_5(x) +\n6.0 P_6(x) + 7.0 P_7(x) + "
+ "8.0 P_8(x) + 9.0 P_9(x) + 10.0 P_10(x) +\n"
+ "11.0 P_11(x)")),
+ ))
+ def test_legendre_str(self, inp, tgt):
+ res = str(poly.Legendre(inp))
+ assert_equal(res, tgt)
+
+ @pytest.mark.parametrize(('inp', 'tgt'), (
+ ([1, 2, 3], "1.0 + 2.0 H_1(x) + 3.0 H_2(x)"),
+ ([-1, 0, 3, -1], "-1.0 + 0.0 H_1(x) + 3.0 H_2(x) - 1.0 H_3(x)"),
+ (arange(12), ("0.0 + 1.0 H_1(x) + 2.0 H_2(x) + 3.0 H_3(x) + "
+ "4.0 H_4(x) + 5.0 H_5(x) +\n6.0 H_6(x) + 7.0 H_7(x) + "
+ "8.0 H_8(x) + 9.0 H_9(x) + 10.0 H_10(x) +\n"
+ "11.0 H_11(x)")),
+ ))
+ def test_hermite_str(self, inp, tgt):
+ res = str(poly.Hermite(inp))
+ assert_equal(res, tgt)
+
+ @pytest.mark.parametrize(('inp', 'tgt'), (
+ ([1, 2, 3], "1.0 + 2.0 He_1(x) + 3.0 He_2(x)"),
+ ([-1, 0, 3, -1], "-1.0 + 0.0 He_1(x) + 3.0 He_2(x) - 1.0 He_3(x)"),
+ (arange(12), ("0.0 + 1.0 He_1(x) + 2.0 He_2(x) + 3.0 He_3(x) + "
+ "4.0 He_4(x) +\n5.0 He_5(x) + 6.0 He_6(x) + "
+ "7.0 He_7(x) + 8.0 He_8(x) + 9.0 He_9(x) +\n"
+ "10.0 He_10(x) + 11.0 He_11(x)")),
+ ))
+ def test_hermiteE_str(self, inp, tgt):
+ res = str(poly.HermiteE(inp))
+ assert_equal(res, tgt)
+
+ @pytest.mark.parametrize(('inp', 'tgt'), (
+ ([1, 2, 3], "1.0 + 2.0 L_1(x) + 3.0 L_2(x)"),
+ ([-1, 0, 3, -1], "-1.0 + 0.0 L_1(x) + 3.0 L_2(x) - 1.0 L_3(x)"),
+ (arange(12), ("0.0 + 1.0 L_1(x) + 2.0 L_2(x) + 3.0 L_3(x) + "
+ "4.0 L_4(x) + 5.0 L_5(x) +\n6.0 L_6(x) + 7.0 L_7(x) + "
+ "8.0 L_8(x) + 9.0 L_9(x) + 10.0 L_10(x) +\n"
+ "11.0 L_11(x)")),
+ ))
+ def test_laguerre_str(self, inp, tgt):
+ res = str(poly.Laguerre(inp))
+ assert_equal(res, tgt)
+
+
+class TestLinebreaking:
+
+ @pytest.fixture(scope='class', autouse=True)
+ def use_ascii(self):
+ poly.set_default_printstyle('ascii')
+
+ def test_single_line_one_less(self):
+ # With 'ascii' style, len(str(p)) is default linewidth - 1 (i.e. 74)
+ p = poly.Polynomial([12345678, 12345678, 12345678, 12345678, 123])
+ assert_equal(len(str(p)), 74)
+ assert_equal(str(p), (
+ '12345678.0 + 12345678.0 x + 12345678.0 x**2 + '
+ '12345678.0 x**3 + 123.0 x**4'
+ ))
+
+ def test_num_chars_is_linewidth(self):
+ # len(str(p)) == default linewidth == 75
+ p = poly.Polynomial([12345678, 12345678, 12345678, 12345678, 1234])
+ assert_equal(len(str(p)), 75)
+ assert_equal(str(p), (
+ '12345678.0 + 12345678.0 x + 12345678.0 x**2 + '
+ '12345678.0 x**3 +\n1234.0 x**4'
+ ))
+
+ def test_first_linebreak_multiline_one_less_than_linewidth(self):
+ # Multiline str where len(first_line) + len(next_term) == lw - 1 == 74
+ p = poly.Polynomial(
+ [12345678, 12345678, 12345678, 12345678, 1, 12345678]
+ )
+ assert_equal(len(str(p).split('\n')[0]), 74)
+ assert_equal(str(p), (
+ '12345678.0 + 12345678.0 x + 12345678.0 x**2 + '
+ '12345678.0 x**3 + 1.0 x**4 +\n12345678.0 x**5'
+ ))
+
+ def test_first_linebreak_multiline_on_linewidth(self):
+ # First line is one character longer than previous test
+ p = poly.Polynomial(
+ [12345678, 12345678, 12345678, 12345678.12, 1, 12345678]
+ )
+ assert_equal(str(p), (
+ '12345678.0 + 12345678.0 x + 12345678.0 x**2 + '
+ '12345678.12 x**3 +\n1.0 x**4 + 12345678.0 x**5'
+ ))
+
+ @pytest.mark.parametrize(('lw', 'tgt'), (
+ (75, ('0.0 + 10.0 x + 200.0 x**2 + 3000.0 x**3 + 40000.0 x**4 + '
+ '500000.0 x**5 +\n600000.0 x**6 + 70000.0 x**7 + 8000.0 x**8 + '
+ '900.0 x**9')),
+ (45, ('0.0 + 10.0 x + 200.0 x**2 + 3000.0 x**3 +\n40000.0 x**4 + '
+ '500000.0 x**5 +\n600000.0 x**6 + 70000.0 x**7 + 8000.0 x**8 +\n'
+ '900.0 x**9')),
+ (132, ('0.0 + 10.0 x + 200.0 x**2 + 3000.0 x**3 + 40000.0 x**4 + '
+ '500000.0 x**5 + 600000.0 x**6 + 70000.0 x**7 + 8000.0 x**8 + '
+ '900.0 x**9')),
+ ))
+ def test_linewidth_printoption(self, lw, tgt):
+ p = poly.Polynomial(
+ [0, 10, 200, 3000, 40000, 500000, 600000, 70000, 8000, 900]
+ )
+ with printoptions(linewidth=lw):
+ assert_equal(str(p), tgt)
+ for line in str(p).split('\n'):
+ assert_(len(line) < lw)
+
+
+def test_set_default_printoptions():
+ p = poly.Polynomial([1, 2, 3])
+ c = poly.Chebyshev([1, 2, 3])
+ poly.set_default_printstyle('ascii')
+ assert_equal(str(p), "1.0 + 2.0 x + 3.0 x**2")
+ assert_equal(str(c), "1.0 + 2.0 T_1(x) + 3.0 T_2(x)")
+ poly.set_default_printstyle('unicode')
+ assert_equal(str(p), "1.0 + 2.0·x + 3.0·x²")
+ assert_equal(str(c), "1.0 + 2.0·T₁(x) + 3.0·T₂(x)")
+ with pytest.raises(ValueError):
+ poly.set_default_printstyle('invalid_input')
+
+
+def test_complex_coefficients():
+ """Test both numpy and built-in complex."""
+ coefs = [0+1j, 1+1j, -2+2j, 3+0j]
+ # numpy complex
+ p1 = poly.Polynomial(coefs)
+ # Python complex
+ p2 = poly.Polynomial(array(coefs, dtype=object))
+ poly.set_default_printstyle('unicode')
+ assert_equal(str(p1), "1j + (1+1j)·x - (2-2j)·x² + (3+0j)·x³")
+ assert_equal(str(p2), "1j + (1+1j)·x + (-2+2j)·x² + (3+0j)·x³")
+ poly.set_default_printstyle('ascii')
+ assert_equal(str(p1), "1j + (1+1j) x - (2-2j) x**2 + (3+0j) x**3")
+ assert_equal(str(p2), "1j + (1+1j) x + (-2+2j) x**2 + (3+0j) x**3")
+
+
+@pytest.mark.parametrize(('coefs', 'tgt'), (
+ (array([Fraction(1, 2), Fraction(3, 4)], dtype=object), (
+ "1/2 + 3/4·x"
+ )),
+ (array([1, 2, Fraction(5, 7)], dtype=object), (
+ "1 + 2·x + 5/7·x²"
+ )),
+ (array([Decimal('1.00'), Decimal('2.2'), 3], dtype=object), (
+ "1.00 + 2.2·x + 3·x²"
+ )),
+))
+def test_numeric_object_coefficients(coefs, tgt):
+ p = poly.Polynomial(coefs)
+ poly.set_default_printstyle('unicode')
+ assert_equal(str(p), tgt)
+
+
+@pytest.mark.parametrize(('coefs', 'tgt'), (
+ (array([1, 2, 'f'], dtype=object), '1 + 2·x + f·x²'),
+ (array([1, 2, [3, 4]], dtype=object), '1 + 2·x + [3, 4]·x²'),
+))
+def test_nonnumeric_object_coefficients(coefs, tgt):
+ """
+ Test coef fallback for object arrays of non-numeric coefficients.
+ """
+ p = poly.Polynomial(coefs)
+ poly.set_default_printstyle('unicode')
+ assert_equal(str(p), tgt)
+
+
+class TestFormat:
+ def test_format_unicode(self):
+ poly.set_default_printstyle('ascii')
+ p = poly.Polynomial([1, 2, 0, -1])
+ assert_equal(format(p, 'unicode'), "1.0 + 2.0·x + 0.0·x² - 1.0·x³")
+
+ def test_format_ascii(self):
+ poly.set_default_printstyle('unicode')
+ p = poly.Polynomial([1, 2, 0, -1])
+ assert_equal(
+ format(p, 'ascii'), "1.0 + 2.0 x + 0.0 x**2 - 1.0 x**3"
+ )
+
+ def test_empty_formatstr(self):
+ poly.set_default_printstyle('ascii')
+ p = poly.Polynomial([1, 2, 3])
+ assert_equal(format(p), "1.0 + 2.0 x + 3.0 x**2")
+ assert_equal(f"{p}", "1.0 + 2.0 x + 3.0 x**2")
+
+ def test_bad_formatstr(self):
+ p = poly.Polynomial([1, 2, 0, -1])
+ with pytest.raises(ValueError):
+ format(p, '.2f')
+
+
+@pytest.mark.parametrize(('poly', 'tgt'), (
+ (poly.Polynomial, '1.0 + 2.0·z + 3.0·z²'),
+ (poly.Chebyshev, '1.0 + 2.0·T₁(z) + 3.0·T₂(z)'),
+ (poly.Hermite, '1.0 + 2.0·H₁(z) + 3.0·H₂(z)'),
+ (poly.HermiteE, '1.0 + 2.0·He₁(z) + 3.0·He₂(z)'),
+ (poly.Laguerre, '1.0 + 2.0·L₁(z) + 3.0·L₂(z)'),
+ (poly.Legendre, '1.0 + 2.0·P₁(z) + 3.0·P₂(z)'),
+))
+def test_symbol(poly, tgt):
+ p = poly([1, 2, 3], symbol='z')
+ assert_equal(f"{p:unicode}", tgt)
+
+
+class TestRepr:
+ def test_polynomial_str(self):
+ res = repr(poly.Polynomial([0, 1]))
+ tgt = (
+ "Polynomial([0., 1.], domain=[-1, 1], window=[-1, 1], "
+ "symbol='x')"
+ )
+ assert_equal(res, tgt)
+
+ def test_chebyshev_str(self):
+ res = repr(poly.Chebyshev([0, 1]))
+ tgt = (
+ "Chebyshev([0., 1.], domain=[-1, 1], window=[-1, 1], "
+ "symbol='x')"
+ )
+ assert_equal(res, tgt)
+
+ def test_legendre_repr(self):
+ res = repr(poly.Legendre([0, 1]))
+ tgt = (
+ "Legendre([0., 1.], domain=[-1, 1], window=[-1, 1], "
+ "symbol='x')"
+ )
+ assert_equal(res, tgt)
+
+ def test_hermite_repr(self):
+ res = repr(poly.Hermite([0, 1]))
+ tgt = (
+ "Hermite([0., 1.], domain=[-1, 1], window=[-1, 1], "
+ "symbol='x')"
+ )
+ assert_equal(res, tgt)
+
+ def test_hermiteE_repr(self):
+ res = repr(poly.HermiteE([0, 1]))
+ tgt = (
+ "HermiteE([0., 1.], domain=[-1, 1], window=[-1, 1], "
+ "symbol='x')"
+ )
+ assert_equal(res, tgt)
+
+ def test_laguerre_repr(self):
+ res = repr(poly.Laguerre([0, 1]))
+ tgt = (
+ "Laguerre([0., 1.], domain=[0, 1], window=[0, 1], "
+ "symbol='x')"
+ )
+ assert_equal(res, tgt)
+
+
+class TestLatexRepr:
+ """Test the latex repr used by Jupyter"""
+
+ def as_latex(self, obj):
+ # right now we ignore the formatting of scalars in our tests, since
+ # it makes them too verbose. Ideally, the formatting of scalars will
+ # be fixed such that tests below continue to pass
+ obj._repr_latex_scalar = lambda x, parens=False: str(x)
+ try:
+ return obj._repr_latex_()
+ finally:
+ del obj._repr_latex_scalar
+
+ def test_simple_polynomial(self):
+ # default input
+ p = poly.Polynomial([1, 2, 3])
+ assert_equal(self.as_latex(p),
+ r'$x \mapsto 1.0 + 2.0\,x + 3.0\,x^{2}$')
+
+ # translated input
+ p = poly.Polynomial([1, 2, 3], domain=[-2, 0])
+ assert_equal(self.as_latex(p),
+ r'$x \mapsto 1.0 + 2.0\,\left(1.0 + x\right) + 3.0\,\left(1.0 + x\right)^{2}$')
+
+ # scaled input
+ p = poly.Polynomial([1, 2, 3], domain=[-0.5, 0.5])
+ assert_equal(self.as_latex(p),
+ r'$x \mapsto 1.0 + 2.0\,\left(2.0x\right) + 3.0\,\left(2.0x\right)^{2}$')
+
+ # affine input
+ p = poly.Polynomial([1, 2, 3], domain=[-1, 0])
+ assert_equal(self.as_latex(p),
+ r'$x \mapsto 1.0 + 2.0\,\left(1.0 + 2.0x\right) + 3.0\,\left(1.0 + 2.0x\right)^{2}$')
+
+ def test_basis_func(self):
+ p = poly.Chebyshev([1, 2, 3])
+ assert_equal(self.as_latex(p),
+ r'$x \mapsto 1.0\,{T}_{0}(x) + 2.0\,{T}_{1}(x) + 3.0\,{T}_{2}(x)$')
+ # affine input - check no surplus parens are added
+ p = poly.Chebyshev([1, 2, 3], domain=[-1, 0])
+ assert_equal(self.as_latex(p),
+ r'$x \mapsto 1.0\,{T}_{0}(1.0 + 2.0x) + 2.0\,{T}_{1}(1.0 + 2.0x) + 3.0\,{T}_{2}(1.0 + 2.0x)$')
+
+ def test_multichar_basis_func(self):
+ p = poly.HermiteE([1, 2, 3])
+ assert_equal(self.as_latex(p),
+ r'$x \mapsto 1.0\,{He}_{0}(x) + 2.0\,{He}_{1}(x) + 3.0\,{He}_{2}(x)$')
+
+ def test_symbol_basic(self):
+ # default input
+ p = poly.Polynomial([1, 2, 3], symbol='z')
+ assert_equal(self.as_latex(p),
+ r'$z \mapsto 1.0 + 2.0\,z + 3.0\,z^{2}$')
+
+ # translated input
+ p = poly.Polynomial([1, 2, 3], domain=[-2, 0], symbol='z')
+ assert_equal(
+ self.as_latex(p),
+ (
+ r'$z \mapsto 1.0 + 2.0\,\left(1.0 + z\right) + 3.0\,'
+ r'\left(1.0 + z\right)^{2}$'
+ ),
+ )
+
+ # scaled input
+ p = poly.Polynomial([1, 2, 3], domain=[-0.5, 0.5], symbol='z')
+ assert_equal(
+ self.as_latex(p),
+ (
+ r'$z \mapsto 1.0 + 2.0\,\left(2.0z\right) + 3.0\,'
+ r'\left(2.0z\right)^{2}$'
+ ),
+ )
+
+ # affine input
+ p = poly.Polynomial([1, 2, 3], domain=[-1, 0], symbol='z')
+ assert_equal(
+ self.as_latex(p),
+ (
+ r'$z \mapsto 1.0 + 2.0\,\left(1.0 + 2.0z\right) + 3.0\,'
+ r'\left(1.0 + 2.0z\right)^{2}$'
+ ),
+ )
+
+
+SWITCH_TO_EXP = (
+ '1.0 + (1.0e-01) x + (1.0e-02) x**2',
+ '1.2 + (1.2e-01) x + (1.2e-02) x**2',
+ '1.23 + 0.12 x + (1.23e-02) x**2 + (1.23e-03) x**3',
+ '1.235 + 0.123 x + (1.235e-02) x**2 + (1.235e-03) x**3',
+ '1.2346 + 0.1235 x + 0.0123 x**2 + (1.2346e-03) x**3 + (1.2346e-04) x**4',
+ '1.23457 + 0.12346 x + 0.01235 x**2 + (1.23457e-03) x**3 + '
+ '(1.23457e-04) x**4',
+ '1.234568 + 0.123457 x + 0.012346 x**2 + 0.001235 x**3 + '
+ '(1.234568e-04) x**4 + (1.234568e-05) x**5',
+ '1.2345679 + 0.1234568 x + 0.0123457 x**2 + 0.0012346 x**3 + '
+ '(1.2345679e-04) x**4 + (1.2345679e-05) x**5')
+
+class TestPrintOptions:
+ """
+ Test the output is properly configured via printoptions.
+ The exponential notation is enabled automatically when the values
+ are too small or too large.
+ """
+
+ @pytest.fixture(scope='class', autouse=True)
+ def use_ascii(self):
+ poly.set_default_printstyle('ascii')
+
+ def test_str(self):
+ p = poly.Polynomial([1/2, 1/7, 1/7*10**8, 1/7*10**9])
+ assert_equal(str(p), '0.5 + 0.14285714 x + 14285714.28571429 x**2 '
+ '+ (1.42857143e+08) x**3')
+
+ with printoptions(precision=3):
+ assert_equal(str(p), '0.5 + 0.143 x + 14285714.286 x**2 '
+ '+ (1.429e+08) x**3')
+
+ def test_latex(self):
+ p = poly.Polynomial([1/2, 1/7, 1/7*10**8, 1/7*10**9])
+ assert_equal(p._repr_latex_(),
+ r'$x \mapsto \text{0.5} + \text{0.14285714}\,x + '
+ r'\text{14285714.28571429}\,x^{2} + '
+ r'\text{(1.42857143e+08)}\,x^{3}$')
+
+ with printoptions(precision=3):
+ assert_equal(p._repr_latex_(),
+ r'$x \mapsto \text{0.5} + \text{0.143}\,x + '
+ r'\text{14285714.286}\,x^{2} + \text{(1.429e+08)}\,x^{3}$')
+
+ def test_fixed(self):
+ p = poly.Polynomial([1/2])
+ assert_equal(str(p), '0.5')
+
+ with printoptions(floatmode='fixed'):
+ assert_equal(str(p), '0.50000000')
+
+ with printoptions(floatmode='fixed', precision=4):
+ assert_equal(str(p), '0.5000')
+
+ def test_switch_to_exp(self):
+ for i, s in enumerate(SWITCH_TO_EXP):
+ with printoptions(precision=i):
+ p = poly.Polynomial([1.23456789*10**-i
+ for i in range(i//2+3)])
+ assert str(p).replace('\n', ' ') == s
+
+ def test_non_finite(self):
+ p = poly.Polynomial([nan, inf])
+ assert str(p) == 'nan + inf x'
+ assert p._repr_latex_() == r'$x \mapsto \text{nan} + \text{inf}\,x$'
+ with printoptions(nanstr='NAN', infstr='INF'):
+ assert str(p) == 'NAN + INF x'
+ assert p._repr_latex_() == \
+ r'$x \mapsto \text{NAN} + \text{INF}\,x$'
diff --git a/lib/python3.12/site-packages/numpy/polynomial/tests/test_symbol.py b/lib/python3.12/site-packages/numpy/polynomial/tests/test_symbol.py
new file mode 100644
index 0000000000000000000000000000000000000000..4ea6035ef7a75e6807634ba894e42015c83edb7d
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/polynomial/tests/test_symbol.py
@@ -0,0 +1,216 @@
+"""
+Tests related to the ``symbol`` attribute of the ABCPolyBase class.
+"""
+
+import pytest
+import numpy.polynomial as poly
+from numpy.core import array
+from numpy.testing import assert_equal, assert_raises, assert_
+
+
+class TestInit:
+ """
+ Test polynomial creation with symbol kwarg.
+ """
+ c = [1, 2, 3]
+
+ def test_default_symbol(self):
+ p = poly.Polynomial(self.c)
+ assert_equal(p.symbol, 'x')
+
+ @pytest.mark.parametrize(('bad_input', 'exception'), (
+ ('', ValueError),
+ ('3', ValueError),
+ (None, TypeError),
+ (1, TypeError),
+ ))
+ def test_symbol_bad_input(self, bad_input, exception):
+ with pytest.raises(exception):
+ p = poly.Polynomial(self.c, symbol=bad_input)
+
+ @pytest.mark.parametrize('symbol', (
+ 'x',
+ 'x_1',
+ 'A',
+ 'xyz',
+ 'β',
+ ))
+ def test_valid_symbols(self, symbol):
+ """
+ Values for symbol that should pass input validation.
+ """
+ p = poly.Polynomial(self.c, symbol=symbol)
+ assert_equal(p.symbol, symbol)
+
+ def test_property(self):
+ """
+ 'symbol' attribute is read only.
+ """
+ p = poly.Polynomial(self.c, symbol='x')
+ with pytest.raises(AttributeError):
+ p.symbol = 'z'
+
+ def test_change_symbol(self):
+ p = poly.Polynomial(self.c, symbol='y')
+ # Create new polynomial from p with different symbol
+ pt = poly.Polynomial(p.coef, symbol='t')
+ assert_equal(pt.symbol, 't')
+
+
+class TestUnaryOperators:
+ p = poly.Polynomial([1, 2, 3], symbol='z')
+
+ def test_neg(self):
+ n = -self.p
+ assert_equal(n.symbol, 'z')
+
+ def test_scalarmul(self):
+ out = self.p * 10
+ assert_equal(out.symbol, 'z')
+
+ def test_rscalarmul(self):
+ out = 10 * self.p
+ assert_equal(out.symbol, 'z')
+
+ def test_pow(self):
+ out = self.p ** 3
+ assert_equal(out.symbol, 'z')
+
+
+@pytest.mark.parametrize(
+ 'rhs',
+ (
+ poly.Polynomial([4, 5, 6], symbol='z'),
+ array([4, 5, 6]),
+ ),
+)
+class TestBinaryOperatorsSameSymbol:
+ """
+ Ensure symbol is preserved for numeric operations on polynomials with
+ the same symbol
+ """
+ p = poly.Polynomial([1, 2, 3], symbol='z')
+
+ def test_add(self, rhs):
+ out = self.p + rhs
+ assert_equal(out.symbol, 'z')
+
+ def test_sub(self, rhs):
+ out = self.p - rhs
+ assert_equal(out.symbol, 'z')
+
+ def test_polymul(self, rhs):
+ out = self.p * rhs
+ assert_equal(out.symbol, 'z')
+
+ def test_divmod(self, rhs):
+ for out in divmod(self.p, rhs):
+ assert_equal(out.symbol, 'z')
+
+ def test_radd(self, rhs):
+ out = rhs + self.p
+ assert_equal(out.symbol, 'z')
+
+ def test_rsub(self, rhs):
+ out = rhs - self.p
+ assert_equal(out.symbol, 'z')
+
+ def test_rmul(self, rhs):
+ out = rhs * self.p
+ assert_equal(out.symbol, 'z')
+
+ def test_rdivmod(self, rhs):
+ for out in divmod(rhs, self.p):
+ assert_equal(out.symbol, 'z')
+
+
+class TestBinaryOperatorsDifferentSymbol:
+ p = poly.Polynomial([1, 2, 3], symbol='x')
+ other = poly.Polynomial([4, 5, 6], symbol='y')
+ ops = (p.__add__, p.__sub__, p.__mul__, p.__floordiv__, p.__mod__)
+
+ @pytest.mark.parametrize('f', ops)
+ def test_binops_fails(self, f):
+ assert_raises(ValueError, f, self.other)
+
+
+class TestEquality:
+ p = poly.Polynomial([1, 2, 3], symbol='x')
+
+ def test_eq(self):
+ other = poly.Polynomial([1, 2, 3], symbol='x')
+ assert_(self.p == other)
+
+ def test_neq(self):
+ other = poly.Polynomial([1, 2, 3], symbol='y')
+ assert_(not self.p == other)
+
+
+class TestExtraMethods:
+ """
+ Test other methods for manipulating/creating polynomial objects.
+ """
+ p = poly.Polynomial([1, 2, 3, 0], symbol='z')
+
+ def test_copy(self):
+ other = self.p.copy()
+ assert_equal(other.symbol, 'z')
+
+ def test_trim(self):
+ other = self.p.trim()
+ assert_equal(other.symbol, 'z')
+
+ def test_truncate(self):
+ other = self.p.truncate(2)
+ assert_equal(other.symbol, 'z')
+
+ @pytest.mark.parametrize('kwarg', (
+ {'domain': [-10, 10]},
+ {'window': [-10, 10]},
+ {'kind': poly.Chebyshev},
+ ))
+ def test_convert(self, kwarg):
+ other = self.p.convert(**kwarg)
+ assert_equal(other.symbol, 'z')
+
+ def test_integ(self):
+ other = self.p.integ()
+ assert_equal(other.symbol, 'z')
+
+ def test_deriv(self):
+ other = self.p.deriv()
+ assert_equal(other.symbol, 'z')
+
+
+def test_composition():
+ p = poly.Polynomial([3, 2, 1], symbol="t")
+ q = poly.Polynomial([5, 1, 0, -1], symbol="λ_1")
+ r = p(q)
+ assert r.symbol == "λ_1"
+
+
+#
+# Class methods that result in new polynomial class instances
+#
+
+
+def test_fit():
+ x, y = (range(10),)*2
+ p = poly.Polynomial.fit(x, y, deg=1, symbol='z')
+ assert_equal(p.symbol, 'z')
+
+
+def test_froomroots():
+ roots = [-2, 2]
+ p = poly.Polynomial.fromroots(roots, symbol='z')
+ assert_equal(p.symbol, 'z')
+
+
+def test_identity():
+ p = poly.Polynomial.identity(domain=[-1, 1], window=[5, 20], symbol='z')
+ assert_equal(p.symbol, 'z')
+
+
+def test_basis():
+ p = poly.Polynomial.basis(3, symbol='z')
+ assert_equal(p.symbol, 'z')
diff --git a/lib/python3.12/site-packages/numpy/py.typed b/lib/python3.12/site-packages/numpy/py.typed
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/lib/python3.12/site-packages/numpy/version.py b/lib/python3.12/site-packages/numpy/version.py
new file mode 100644
index 0000000000000000000000000000000000000000..fb108fcb4742144d1255ea5f3364fb6cb1c1752f
--- /dev/null
+++ b/lib/python3.12/site-packages/numpy/version.py
@@ -0,0 +1,8 @@
+
+version = "1.26.4"
+__version__ = version
+full_version = version
+
+git_revision = "9815c16f449e12915ef35a8255329ba26dacd5c0"
+release = 'dev' not in version and '+' not in version
+short_version = version.split("+")[0]
diff --git a/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/INSTALLER b/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/INSTALLER
new file mode 100644
index 0000000000000000000000000000000000000000..a1b589e38a32041e49332e5e81c2d363dc418d68
--- /dev/null
+++ b/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/LICENSE b/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..754db5afcb8260c5539b1e0ede3990b8ddbc3e29
--- /dev/null
+++ b/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/LICENSE
@@ -0,0 +1,20 @@
+ISC LICENSE
+
+ This license is approved by the OSI and FSF as GPL-compatible.
+ http://opensource.org/licenses/isc-license.txt
+
+ Copyright (c) 2013-2014, Pexpect development team
+ Copyright (c) 2012, Noah Spurrier
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
diff --git a/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/METADATA b/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/METADATA
new file mode 100644
index 0000000000000000000000000000000000000000..c5ea4a1a59ae2f7d7d1bdb4efcc4c3d40caeb85e
--- /dev/null
+++ b/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/METADATA
@@ -0,0 +1,52 @@
+Metadata-Version: 2.1
+Name: pexpect
+Version: 4.9.0
+Summary: Pexpect allows easy control of interactive console applications.
+Home-page: https://pexpect.readthedocs.io/
+Author: Noah Spurrier; Thomas Kluyver; Jeff Quast
+Author-email: noah@noah.org, thomas@kluyver.me.uk, contact@jeffquast.com
+License: ISC license
+Project-URL: Bug Tracker, https://github.com/pexpect/pexpect/issues
+Project-URL: Documentation, https://pexpect.readthedocs.io/
+Project-URL: Source Code, https://github.com/pexpect/pexpect
+Project-URL: History, https://pexpect.readthedocs.io/en/stable/history.html
+Platform: UNIX
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Console
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: System Administrators
+Classifier: License :: OSI Approved :: ISC License (ISCL)
+Classifier: Operating System :: POSIX
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Topic :: Software Development
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Software Development :: Quality Assurance
+Classifier: Topic :: Software Development :: Testing
+Classifier: Topic :: System
+Classifier: Topic :: System :: Archiving :: Packaging
+Classifier: Topic :: System :: Installation/Setup
+Classifier: Topic :: System :: Shells
+Classifier: Topic :: System :: Software Distribution
+Classifier: Topic :: Terminals
+License-File: LICENSE
+Requires-Dist: ptyprocess (>=0.5)
+
+
+Pexpect is a pure Python module for spawning child applications; controlling
+them; and responding to expected patterns in their output. Pexpect works like
+Don Libes' Expect. Pexpect allows your script to spawn a child application and
+control it as if a human were typing commands.
+
+Pexpect can be used for automating interactive applications such as ssh, ftp,
+passwd, telnet, etc. It can be used to automate setup scripts for duplicating
+software package installations on different servers. It can be used for
+automated software testing. Pexpect is in the spirit of Don Libes' Expect, but
+Pexpect is pure Python.
+
+The main features of Pexpect require the pty module in the Python standard
+library, which is only available on Unix-like systems. Some features—waiting
+for patterns from file descriptors or subprocesses—are also available on
+Windows.
diff --git a/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/RECORD b/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/RECORD
new file mode 100644
index 0000000000000000000000000000000000000000..1a346cf153a3e766a7c3eaf160ea9bf1e48a25e1
--- /dev/null
+++ b/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/RECORD
@@ -0,0 +1,43 @@
+pexpect-4.9.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+pexpect-4.9.0.dist-info/LICENSE,sha256=Skg64cTcc4psi3P-tJB04YNdoCq1qmhvJnUCmQb6Nk0,987
+pexpect-4.9.0.dist-info/METADATA,sha256=LXxaxf3v3koBlOxSL7zAynDpnhoqlW7qREFo-FkWUKo,2463
+pexpect-4.9.0.dist-info/RECORD,,
+pexpect-4.9.0.dist-info/WHEEL,sha256=bb2Ot9scclHKMOLDEHY6B2sicWOgugjFKaJsT7vwMQo,110
+pexpect-4.9.0.dist-info/top_level.txt,sha256=O-b3UY9VQZkW3yDAeFNatUOKO4GojVWO4TTHoI9-E7k,8
+pexpect/ANSI.py,sha256=aA-3tdXz_FZ4G7PAqFZi5g1KBGQ6PzJzS0gm3ALZKZw,12177
+pexpect/FSM.py,sha256=tluiyUGMyIH3q_wLG6Ak1NZVuXUAGNDjq6k6BK1q8RY,13419
+pexpect/__init__.py,sha256=SuQYzpVxpzqLwZ1f68ov5Tvcy8Qv_eD1_NyuSIDibaU,4089
+pexpect/__pycache__/ANSI.cpython-312.pyc,,
+pexpect/__pycache__/FSM.cpython-312.pyc,,
+pexpect/__pycache__/__init__.cpython-312.pyc,,
+pexpect/__pycache__/_async.cpython-312.pyc,,
+pexpect/__pycache__/_async_pre_await.cpython-312.pyc,,
+pexpect/__pycache__/_async_w_await.cpython-312.pyc,,
+pexpect/__pycache__/exceptions.cpython-312.pyc,,
+pexpect/__pycache__/expect.cpython-312.pyc,,
+pexpect/__pycache__/fdpexpect.cpython-312.pyc,,
+pexpect/__pycache__/popen_spawn.cpython-312.pyc,,
+pexpect/__pycache__/pty_spawn.cpython-312.pyc,,
+pexpect/__pycache__/pxssh.cpython-312.pyc,,
+pexpect/__pycache__/replwrap.cpython-312.pyc,,
+pexpect/__pycache__/run.cpython-312.pyc,,
+pexpect/__pycache__/screen.cpython-312.pyc,,
+pexpect/__pycache__/socket_pexpect.cpython-312.pyc,,
+pexpect/__pycache__/spawnbase.cpython-312.pyc,,
+pexpect/__pycache__/utils.cpython-312.pyc,,
+pexpect/_async.py,sha256=kNQ073RymFLQgpmNzseyIC50jhBsLtoxsEW-7TRrxys,907
+pexpect/_async_pre_await.py,sha256=vkv3IAhRhVKzxvXydnl7Q7m9MjVC24E0OuveVsKoYRs,3465
+pexpect/_async_w_await.py,sha256=3QtNwnRSxz5L6pCEA8-aYTzSx647cmALPYwk8A_fTt0,3802
+pexpect/bashrc.sh,sha256=uPuvSvtNmi1ZYW1--6L5deebMjfUEq_LE3-A25zwDyo,419
+pexpect/exceptions.py,sha256=A9C1PWbBc2j9AKvnv7UkPCawhFTEGYmeULW0vwbMvXQ,1068
+pexpect/expect.py,sha256=KKtBmx2MYa-yDE715XlHUcloKe5ndBD359a4OYVXD84,13827
+pexpect/fdpexpect.py,sha256=zdSiPvZlBSuqMk_BNBcpXWb3kGJk6MIVI-1NWZv2lU4,5991
+pexpect/popen_spawn.py,sha256=bxLlZLG8BBbRFmv3YLeR38g2ZxoLRIhE_-RJt8dorgE,6159
+pexpect/pty_spawn.py,sha256=ZygSYsdnVJ5acxiNM9gLvLrT2AVqgwJvbDcPaTxxv9E,37382
+pexpect/pxssh.py,sha256=808mJbdWlDocew12LrvNHz9-ba_a1ZfwB8XFRrcest4,24445
+pexpect/replwrap.py,sha256=_I5PDohJ5qWWiXzO9pS32kfcVllJyungubrn5_ATcVY,5951
+pexpect/run.py,sha256=PkTA_IGOHzLVK89tVIzpLJ7I2jANN5o7GDcH5k1Ly8c,6629
+pexpect/screen.py,sha256=-twD4sIEp83nzuYH9lRDzwHfesoTgVGWglsBYWOK7Ks,13704
+pexpect/socket_pexpect.py,sha256=SV1strRUbcplsL-VbMXgL3sn_q4TB_wRFzGyMzxjzRY,4814
+pexpect/spawnbase.py,sha256=SThkQQ25wiSA-7uqveL3hbkS8FnLFAfk-iXgX2OtOY8,21685
+pexpect/utils.py,sha256=1jIhzU7eBvY3pbW3LZoJhCOU2KWqgty5HgQ6VBYIp5U,6019
diff --git a/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/WHEEL b/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/WHEEL
new file mode 100644
index 0000000000000000000000000000000000000000..9d8f872bbf2275e6d1785238e90b0321f4b6f323
--- /dev/null
+++ b/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/WHEEL
@@ -0,0 +1,6 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.38.4)
+Root-Is-Purelib: true
+Tag: py2-none-any
+Tag: py3-none-any
+
diff --git a/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/top_level.txt b/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/top_level.txt
new file mode 100644
index 0000000000000000000000000000000000000000..808fb07afdc86c2930ec8c3be7eb2a49d669a046
--- /dev/null
+++ b/lib/python3.12/site-packages/pexpect-4.9.0.dist-info/top_level.txt
@@ -0,0 +1 @@
+pexpect
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/__init__.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1e42f33b0ca9773db51ef9b0fc8d5cc62da23a6c
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/__init__.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/_compute_docstrings.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/_compute_docstrings.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..888af159df1f03729e91fffb27b072514ebda49e
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/_compute_docstrings.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/_generated_version.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/_generated_version.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d507c17fef24d6278ff0bcce720b442b3f83f49d
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/_generated_version.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/acero.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/acero.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0d0e6c54f562346c1a13648f233e980f2b309677
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/acero.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/benchmark.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/benchmark.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1e29003a26970365b808313104911148aa91268f
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/benchmark.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/cffi.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/cffi.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9a9cf798510c7bc196e2183518aa0f2e6836c7e3
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/cffi.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/compute.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/compute.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6c7891306d184a609c6ad3d4e9809d560a4dda2a
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/compute.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/conftest.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/conftest.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e08098d0157bb7f7e78a58ee267f1993cf855068
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/conftest.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/csv.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/csv.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e2fb3f5bebf1d922a285528fb36eb4ee22dd327b
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/csv.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/cuda.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/cuda.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..98dfbc0dc4d477c4dcfe0fcfe295e780083d1604
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/cuda.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/dataset.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/dataset.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d6e8911db507e550e78066d456cddc4c37426b98
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/dataset.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/feather.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/feather.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f3d65af2364cb44ec05f4a8b3eb1fc65434d8555
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/feather.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/flight.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/flight.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..bb36b1fd0682f5224cc4a9cf9c08c65e8c082237
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/flight.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/fs.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/fs.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..bbf99ef3f59beded39aeddd96402bd39b167dcdf
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/fs.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/ipc.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/ipc.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9111a8713d143bc6ecd147f2dec30638655176df
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/ipc.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/json.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/json.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f6fbff15d3d2b3773bbbe6639f18a9338610a211
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/json.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/jvm.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/jvm.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..15718fe9d6fa1bc3374107a48e9c8bc314a5dd5b
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/jvm.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/orc.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/orc.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..5a915d4c17ec50c5efc98c744f0bdadf2664912f
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/orc.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/pandas_compat.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/pandas_compat.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..337e656f2c37a8babc1f23eb081972f60756ce22
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/pandas_compat.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/substrait.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/substrait.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..327965c18b9c6d8c0f40d4bd1b2b88118fd118cb
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/substrait.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/types.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/types.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2c5384202c6317d7a32f5361576108d182d6e3c1
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/types.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/__pycache__/util.cpython-312.pyc b/lib/python3.12/site-packages/pyarrow/__pycache__/util.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..889e6111f37ff9129cc84d107ab1738f44be81a0
Binary files /dev/null and b/lib/python3.12/site-packages/pyarrow/__pycache__/util.cpython-312.pyc differ
diff --git a/lib/python3.12/site-packages/pyarrow/include/parquet/api/io.h b/lib/python3.12/site-packages/pyarrow/include/parquet/api/io.h
new file mode 100644
index 0000000000000000000000000000000000000000..28a00f12a7a616136beb328d20120d6458294eab
--- /dev/null
+++ b/lib/python3.12/site-packages/pyarrow/include/parquet/api/io.h
@@ -0,0 +1,20 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include "parquet/exception.h"
diff --git a/lib/python3.12/site-packages/pyarrow/include/parquet/api/reader.h b/lib/python3.12/site-packages/pyarrow/include/parquet/api/reader.h
new file mode 100644
index 0000000000000000000000000000000000000000..7e746e8c5bbf551e84431552f688a493e2d62bc4
--- /dev/null
+++ b/lib/python3.12/site-packages/pyarrow/include/parquet/api/reader.h
@@ -0,0 +1,35 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+// Column reader API
+#include "parquet/column_reader.h"
+#include "parquet/column_scanner.h"
+#include "parquet/exception.h"
+#include "parquet/file_reader.h"
+#include "parquet/metadata.h"
+#include "parquet/platform.h"
+#include "parquet/printer.h"
+#include "parquet/properties.h"
+#include "parquet/statistics.h"
+
+// Schemas
+#include "parquet/api/schema.h"
+
+// IO
+#include "parquet/api/io.h"
diff --git a/lib/python3.12/site-packages/pyarrow/include/parquet/api/schema.h b/lib/python3.12/site-packages/pyarrow/include/parquet/api/schema.h
new file mode 100644
index 0000000000000000000000000000000000000000..7ca714f47b5448974c460e424ab3821d10f7a384
--- /dev/null
+++ b/lib/python3.12/site-packages/pyarrow/include/parquet/api/schema.h
@@ -0,0 +1,21 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+// Schemas
+#include "parquet/schema.h"
diff --git a/lib/python3.12/site-packages/pyarrow/include/parquet/api/writer.h b/lib/python3.12/site-packages/pyarrow/include/parquet/api/writer.h
new file mode 100644
index 0000000000000000000000000000000000000000..b072dcf74dea7233723ae55599d95be47c674716
--- /dev/null
+++ b/lib/python3.12/site-packages/pyarrow/include/parquet/api/writer.h
@@ -0,0 +1,25 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include "parquet/api/io.h"
+#include "parquet/api/schema.h"
+#include "parquet/column_writer.h"
+#include "parquet/exception.h"
+#include "parquet/file_writer.h"
+#include "parquet/statistics.h"
diff --git a/lib/python3.12/site-packages/pyarrow/include/parquet/arrow/reader.h b/lib/python3.12/site-packages/pyarrow/include/parquet/arrow/reader.h
new file mode 100644
index 0000000000000000000000000000000000000000..54620b3d0f564bb3e6680193c61a8fa843f38f63
--- /dev/null
+++ b/lib/python3.12/site-packages/pyarrow/include/parquet/arrow/reader.h
@@ -0,0 +1,392 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include
+// N.B. we don't include async_generator.h as it's relatively heavy
+#include
+#include
+#include
+
+#include "parquet/file_reader.h"
+#include "parquet/platform.h"
+#include "parquet/properties.h"
+
+namespace arrow {
+
+class ChunkedArray;
+class KeyValueMetadata;
+class RecordBatchReader;
+struct Scalar;
+class Schema;
+class Table;
+class RecordBatch;
+
+} // namespace arrow
+
+namespace parquet {
+
+class FileMetaData;
+class SchemaDescriptor;
+
+namespace arrow {
+
+class ColumnChunkReader;
+class ColumnReader;
+struct SchemaManifest;
+class RowGroupReader;
+
+/// \brief Arrow read adapter class for deserializing Parquet files as Arrow row batches.
+///
+/// This interfaces caters for different use cases and thus provides different
+/// interfaces. In its most simplistic form, we cater for a user that wants to
+/// read the whole Parquet at once with the `FileReader::ReadTable` method.
+///
+/// More advanced users that also want to implement parallelism on top of each
+/// single Parquet files should do this on the RowGroup level. For this, they can
+/// call `FileReader::RowGroup(i)->ReadTable` to receive only the specified
+/// RowGroup as a table.
+///
+/// In the most advanced situation, where a consumer wants to independently read
+/// RowGroups in parallel and consume each column individually, they can call
+/// `FileReader::RowGroup(i)->Column(j)->Read` and receive an `arrow::Column`
+/// instance.
+///
+/// Finally, one can also get a stream of record batches using
+/// `FileReader::GetRecordBatchReader()`. This can internally decode columns
+/// in parallel if use_threads was enabled in the ArrowReaderProperties.
+///
+/// The parquet format supports an optional integer field_id which can be assigned
+/// to a field. Arrow will convert these field IDs to a metadata key named
+/// PARQUET:field_id on the appropriate field.
+// TODO(wesm): nested data does not always make sense with this user
+// interface unless you are only reading a single leaf node from a branch of
+// a table. For example:
+//
+// repeated group data {
+// optional group record {
+// optional int32 val1;
+// optional byte_array val2;
+// optional bool val3;
+// }
+// optional int32 val4;
+// }
+//
+// In the Parquet file, there are 4 leaf nodes:
+//
+// * data.record.val1
+// * data.record.val2
+// * data.record.val3
+// * data.val4
+//
+// When materializing this data in an Arrow array, we would have:
+//
+// data: list),
+// val3: bool,
+// >,
+// val4: int32
+// >>
+//
+// However, in the Parquet format, each leaf node has its own repetition and
+// definition levels describing the structure of the intermediate nodes in
+// this array structure. Thus, we will need to scan the leaf data for a group
+// of leaf nodes part of the same type tree to create a single result Arrow
+// nested array structure.
+//
+// This is additionally complicated "chunky" repeated fields or very large byte
+// arrays
+class PARQUET_EXPORT FileReader {
+ public:
+ /// Factory function to create a FileReader from a ParquetFileReader and properties
+ /// \deprecated Deprecated in 23.0.0. Use arrow::Result version instead.
+ ARROW_DEPRECATED("Deprecated in 23.0.0. Use arrow::Result version instead.")
+ static ::arrow::Status Make(::arrow::MemoryPool* pool,
+ std::unique_ptr reader,
+ const ArrowReaderProperties& properties,
+ std::unique_ptr* out);
+
+ /// Factory function to create a FileReader from a ParquetFileReader
+ /// \deprecated Deprecated in 23.0.0. Use arrow::Result version instead.
+ ARROW_DEPRECATED("Deprecated in 23.0.0. Use arrow::Result version instead.")
+ static ::arrow::Status Make(::arrow::MemoryPool* pool,
+ std::unique_ptr reader,
+ std::unique_ptr* out);
+
+ /// Factory function to create a FileReader from a ParquetFileReader and properties
+ static ::arrow::Result> Make(
+ ::arrow::MemoryPool* pool, std::unique_ptr reader,
+ const ArrowReaderProperties& properties);
+
+ /// Factory function to create a FileReader from a ParquetFileReader
+ static ::arrow::Result> Make(
+ ::arrow::MemoryPool* pool, std::unique_ptr reader);
+
+ // Since the distribution of columns amongst a Parquet file's row groups may
+ // be uneven (the number of values in each column chunk can be different), we
+ // provide a column-oriented read interface. The ColumnReader hides the
+ // details of paging through the file's row groups and yielding
+ // fully-materialized arrow::Array instances
+ //
+ // Returns error status if the column of interest is not flat.
+ // The indicated column index is relative to the schema
+ virtual ::arrow::Status GetColumn(int i, std::unique_ptr* out) = 0;
+
+ /// \brief Return arrow schema for all the columns.
+ virtual ::arrow::Status GetSchema(std::shared_ptr<::arrow::Schema>* out) = 0;
+
+ /// \brief Read column as a whole into a chunked array.
+ ///
+ /// The index i refers the index of the top level schema field, which may
+ /// be nested or flat - e.g.
+ ///
+ /// 0 foo.bar
+ /// foo.bar.baz
+ /// foo.qux
+ /// 1 foo2
+ /// 2 foo3
+ ///
+ /// i=0 will read the entire foo struct, i=1 the foo2 primitive column etc
+ virtual ::arrow::Status ReadColumn(int i,
+ std::shared_ptr<::arrow::ChunkedArray>* out) = 0;
+
+ /// \brief Return a RecordBatchReader of all row groups and columns.
+ virtual ::arrow::Result>
+ GetRecordBatchReader() = 0;
+
+ /// \brief Return a RecordBatchReader of row groups selected from row_group_indices.
+ ///
+ /// Note that the ordering in row_group_indices matters. FileReaders must outlive
+ /// their RecordBatchReaders.
+ ///
+ /// \returns error Result if row_group_indices contains an invalid index
+ virtual ::arrow::Result>
+ GetRecordBatchReader(const std::vector& row_group_indices) = 0;
+
+ /// \brief Return a RecordBatchReader of row groups selected from
+ /// row_group_indices, whose columns are selected by column_indices.
+ ///
+ /// Note that the ordering in row_group_indices and column_indices
+ /// matter. FileReaders must outlive their RecordBatchReaders.
+ ///
+ /// \returns error Result if either row_group_indices or column_indices
+ /// contains an invalid index
+ virtual ::arrow::Result>
+ GetRecordBatchReader(const std::vector& row_group_indices,
+ const std::vector& column_indices) = 0;
+
+ /// \brief Return a RecordBatchReader of row groups selected from
+ /// row_group_indices, whose columns are selected by column_indices.
+ ///
+ /// Note that the ordering in row_group_indices and column_indices
+ /// matter. FileReaders must outlive their RecordBatchReaders.
+ ///
+ /// \param row_group_indices which row groups to read (order determines read order).
+ /// \param column_indices which columns to read (order determines output schema).
+ /// \param[out] out record batch stream from parquet data.
+ ///
+ /// \returns error Status if either row_group_indices or column_indices
+ /// contains an invalid index
+ /// \deprecated Deprecated in 21.0.0. Use arrow::Result version instead.
+ ARROW_DEPRECATED("Deprecated in 21.0.0. Use arrow::Result version instead.")
+ ::arrow::Status GetRecordBatchReader(const std::vector& row_group_indices,
+ const std::vector& column_indices,
+ std::shared_ptr<::arrow::RecordBatchReader>* out);
+
+ /// \deprecated Deprecated in 21.0.0. Use arrow::Result version instead.
+ ARROW_DEPRECATED("Deprecated in 21.0.0. Use arrow::Result version instead.")
+ ::arrow::Status GetRecordBatchReader(const std::vector& row_group_indices,
+ std::shared_ptr<::arrow::RecordBatchReader>* out);
+
+ /// \deprecated Deprecated in 21.0.0. Use arrow::Result version instead.
+ ARROW_DEPRECATED("Deprecated in 21.0.0. Use arrow::Result version instead.")
+ ::arrow::Status GetRecordBatchReader(std::shared_ptr<::arrow::RecordBatchReader>* out);
+
+ /// \brief Return a generator of record batches.
+ ///
+ /// The FileReader must outlive the generator, so this requires that you pass in a
+ /// shared_ptr.
+ ///
+ /// \returns error Result if either row_group_indices or column_indices contains an
+ /// invalid index
+ virtual ::arrow::Result<
+ std::function<::arrow::Future>()>>
+ GetRecordBatchGenerator(std::shared_ptr reader,
+ const std::vector row_group_indices,
+ const std::vector column_indices,
+ ::arrow::internal::Executor* cpu_executor = NULLPTR,
+ int64_t rows_to_readahead = 0) = 0;
+
+ /// Read all columns into a Table
+ virtual ::arrow::Status ReadTable(std::shared_ptr<::arrow::Table>* out) = 0;
+
+ /// \brief Read the given columns into a Table
+ ///
+ /// The indicated column indices are relative to the internal representation
+ /// of the parquet table. For instance :
+ /// 0 foo.bar
+ /// foo.bar.baz 0
+ /// foo.bar.baz2 1
+ /// foo.qux 2
+ /// 1 foo2 3
+ /// 2 foo3 4
+ ///
+ /// i=0 will read foo.bar.baz, i=1 will read only foo.bar.baz2 and so on.
+ /// Only leaf fields have indices; foo itself doesn't have an index.
+ /// To get the index for a particular leaf field, one can use
+ /// manifest().schema_fields to get the top level fields, and then walk the
+ /// tree to identify the relevant leaf fields and access its column_index.
+ /// To get the total number of leaf fields, use FileMetadata.num_columns().
+ virtual ::arrow::Status ReadTable(const std::vector& column_indices,
+ std::shared_ptr<::arrow::Table>* out) = 0;
+
+ virtual ::arrow::Status ReadRowGroup(int i, const std::vector& column_indices,
+ std::shared_ptr<::arrow::Table>* out) = 0;
+
+ virtual ::arrow::Status ReadRowGroup(int i, std::shared_ptr<::arrow::Table>* out) = 0;
+
+ virtual ::arrow::Status ReadRowGroups(const std::vector& row_groups,
+ const std::vector& column_indices,
+ std::shared_ptr<::arrow::Table>* out) = 0;
+
+ virtual ::arrow::Status ReadRowGroups(const std::vector& row_groups,
+ std::shared_ptr<::arrow::Table>* out) = 0;
+
+ /// \brief Scan file contents with one thread, return number of rows
+ virtual ::arrow::Status ScanContents(std::vector columns,
+ const int32_t column_batch_size,
+ int64_t* num_rows) = 0;
+
+ /// \brief Return a reader for the RowGroup, this object must not outlive the
+ /// FileReader.
+ virtual std::shared_ptr RowGroup(int row_group_index) = 0;
+
+ /// \brief The number of row groups in the file
+ virtual int num_row_groups() const = 0;
+
+ virtual ParquetFileReader* parquet_reader() const = 0;
+
+ /// Set whether to use multiple threads during reads of multiple columns.
+ /// By default only one thread is used.
+ virtual void set_use_threads(bool use_threads) = 0;
+
+ /// Set number of records to read per batch for the RecordBatchReader.
+ virtual void set_batch_size(int64_t batch_size) = 0;
+
+ virtual const ArrowReaderProperties& properties() const = 0;
+
+ virtual const SchemaManifest& manifest() const = 0;
+
+ virtual ~FileReader() = default;
+};
+
+class RowGroupReader {
+ public:
+ virtual ~RowGroupReader() = default;
+ virtual std::shared_ptr Column(int column_index) = 0;
+ virtual ::arrow::Status ReadTable(const std::vector& column_indices,
+ std::shared_ptr<::arrow::Table>* out) = 0;
+ virtual ::arrow::Status ReadTable(std::shared_ptr<::arrow::Table>* out) = 0;
+
+ private:
+ struct Iterator;
+};
+
+class ColumnChunkReader {
+ public:
+ virtual ~ColumnChunkReader() = default;
+ virtual ::arrow::Status Read(std::shared_ptr<::arrow::ChunkedArray>* out) = 0;
+};
+
+// At this point, the column reader is a stream iterator. It only knows how to
+// read the next batch of values for a particular column from the file until it
+// runs out.
+//
+// We also do not expose any internal Parquet details, such as row groups. This
+// might change in the future.
+class PARQUET_EXPORT ColumnReader {
+ public:
+ virtual ~ColumnReader() = default;
+
+ // Scan the next array of the indicated size. The actual size of the
+ // returned array may be less than the passed size depending how much data is
+ // available in the file.
+ //
+ // When all the data in the file has been exhausted, the result is set to
+ // nullptr.
+ //
+ // Returns Status::OK on a successful read, including if you have exhausted
+ // the data available in the file.
+ virtual ::arrow::Status NextBatch(int64_t batch_size,
+ std::shared_ptr<::arrow::ChunkedArray>* out) = 0;
+};
+
+/// \brief Experimental helper class for bindings (like Python) that struggle
+/// either with std::move or C++ exceptions
+class PARQUET_EXPORT FileReaderBuilder {
+ public:
+ FileReaderBuilder();
+
+ /// Create FileReaderBuilder from Arrow file and optional properties / metadata
+ ::arrow::Status Open(std::shared_ptr<::arrow::io::RandomAccessFile> file,
+ const ReaderProperties& properties = default_reader_properties(),
+ std::shared_ptr metadata = NULLPTR);
+
+ /// Create FileReaderBuilder from file path and optional properties / metadata
+ ::arrow::Status OpenFile(const std::string& path, bool memory_map = false,
+ const ReaderProperties& props = default_reader_properties(),
+ std::shared_ptr metadata = NULLPTR);
+
+ ParquetFileReader* raw_reader() { return raw_reader_.get(); }
+
+ /// Set Arrow MemoryPool for memory allocation
+ FileReaderBuilder* memory_pool(::arrow::MemoryPool* pool);
+ /// Set Arrow reader properties
+ FileReaderBuilder* properties(const ArrowReaderProperties& arg_properties);
+ /// Build FileReader instance
+ ::arrow::Status Build(std::unique_ptr* out);
+ ::arrow::Result> Build();
+
+ private:
+ ::arrow::MemoryPool* pool_;
+ ArrowReaderProperties properties_;
+ std::unique_ptr raw_reader_;
+};
+
+/// \defgroup parquet-arrow-reader-factories Factory functions for Parquet Arrow readers
+///
+/// @{
+
+/// \brief Build FileReader from Arrow file and MemoryPool
+///
+/// Advanced settings are supported through the FileReaderBuilder class.
+PARQUET_EXPORT
+::arrow::Result> OpenFile(
+ std::shared_ptr<::arrow::io::RandomAccessFile>, ::arrow::MemoryPool* allocator);
+
+/// @}
+
+PARQUET_EXPORT
+::arrow::Status StatisticsAsScalars(const Statistics& Statistics,
+ std::shared_ptr<::arrow::Scalar>* min,
+ std::shared_ptr<::arrow::Scalar>* max);
+
+} // namespace arrow
+} // namespace parquet
diff --git a/lib/python3.12/site-packages/pyarrow/include/parquet/arrow/schema.h b/lib/python3.12/site-packages/pyarrow/include/parquet/arrow/schema.h
new file mode 100644
index 0000000000000000000000000000000000000000..dd60fde43422889c53ebd7cf86fbac99c8c6f282
--- /dev/null
+++ b/lib/python3.12/site-packages/pyarrow/include/parquet/arrow/schema.h
@@ -0,0 +1,184 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+#include "arrow/result.h"
+#include "arrow/status.h"
+#include "arrow/type.h"
+#include "arrow/type_fwd.h"
+
+#include "parquet/level_conversion.h"
+#include "parquet/platform.h"
+#include "parquet/schema.h"
+
+namespace parquet {
+
+class ArrowReaderProperties;
+class ArrowWriterProperties;
+class WriterProperties;
+
+namespace arrow {
+
+/// \defgroup arrow-to-parquet-schema-conversion Functions to convert an Arrow
+/// schema into a Parquet schema.
+///
+/// @{
+
+PARQUET_EXPORT
+::arrow::Status FieldToNode(const std::shared_ptr<::arrow::Field>& field,
+ const WriterProperties& properties,
+ const ArrowWriterProperties& arrow_properties,
+ schema::NodePtr* out);
+
+PARQUET_EXPORT
+::arrow::Status ToParquetSchema(const ::arrow::Schema* arrow_schema,
+ const WriterProperties& properties,
+ const ArrowWriterProperties& arrow_properties,
+ std::shared_ptr* out);
+
+PARQUET_EXPORT
+::arrow::Status ToParquetSchema(const ::arrow::Schema* arrow_schema,
+ const WriterProperties& properties,
+ std::shared_ptr* out);
+
+/// @}
+
+/// \defgroup parquet-to-arrow-schema-conversion Functions to convert a Parquet
+/// schema into an Arrow schema.
+///
+/// @{
+
+PARQUET_EXPORT
+::arrow::Status FromParquetSchema(
+ const SchemaDescriptor* parquet_schema, const ArrowReaderProperties& properties,
+ const std::shared_ptr& key_value_metadata,
+ std::shared_ptr<::arrow::Schema>* out);
+
+PARQUET_EXPORT
+::arrow::Status FromParquetSchema(const SchemaDescriptor* parquet_schema,
+ const ArrowReaderProperties& properties,
+ std::shared_ptr<::arrow::Schema>* out);
+
+PARQUET_EXPORT
+::arrow::Status FromParquetSchema(const SchemaDescriptor* parquet_schema,
+ std::shared_ptr<::arrow::Schema>* out);
+
+/// @}
+
+/// \brief Bridge between an arrow::Field and parquet column indices.
+struct PARQUET_EXPORT SchemaField {
+ std::shared_ptr<::arrow::Field> field;
+ std::vector children;
+
+ // Only set for leaf nodes
+ int column_index = -1;
+
+ parquet::internal::LevelInfo level_info;
+
+ bool is_leaf() const { return column_index != -1; }
+};
+
+/// \brief Bridge between a parquet Schema and an arrow Schema.
+///
+/// Expose parquet columns as a tree structure. Useful traverse and link
+/// between arrow's Schema and parquet's Schema.
+struct PARQUET_EXPORT SchemaManifest {
+ static ::arrow::Status Make(
+ const SchemaDescriptor* schema,
+ const std::shared_ptr& metadata,
+ const ArrowReaderProperties& properties, SchemaManifest* manifest);
+
+ const SchemaDescriptor* descr;
+ std::shared_ptr<::arrow::Schema> origin_schema;
+ std::shared_ptr schema_metadata;
+ std::vector schema_fields;
+
+ std::unordered_map column_index_to_field;
+ std::unordered_map child_to_parent;
+
+ ::arrow::Status GetColumnField(int column_index, const SchemaField** out) const {
+ auto it = column_index_to_field.find(column_index);
+ if (it == column_index_to_field.end()) {
+ return ::arrow::Status::KeyError("Column index ", column_index,
+ " not found in schema manifest, may be malformed");
+ }
+ *out = it->second;
+ return ::arrow::Status::OK();
+ }
+
+ const SchemaField* GetParent(const SchemaField* field) const {
+ // Returns nullptr also if not found
+ auto it = child_to_parent.find(field);
+ if (it == child_to_parent.end()) {
+ return NULLPTR;
+ }
+ return it->second;
+ }
+
+ /// Coalesce a list of field indices (relative to the equivalent arrow::Schema) which
+ /// correspond to the column root (first node below the parquet schema's root group) of
+ /// each leaf referenced in column_indices.
+ ///
+ /// For example, for leaves `a.b.c`, `a.b.d.e`, and `i.j.k` (column_indices=[0,1,3])
+ /// the roots are `a` and `i` (return=[0,2]).
+ ///
+ /// root
+ /// -- a <------
+ /// -- -- b | |
+ /// -- -- -- c |
+ /// -- -- -- d |
+ /// -- -- -- -- e
+ /// -- f
+ /// -- -- g
+ /// -- -- -- h
+ /// -- i <---
+ /// -- -- j |
+ /// -- -- -- k
+ ::arrow::Result> GetFieldIndices(
+ const std::vector& column_indices) const {
+ const schema::GroupNode* group = descr->group_node();
+ std::unordered_set already_added;
+
+ std::vector out;
+ for (int column_idx : column_indices) {
+ if (column_idx < 0 || column_idx >= descr->num_columns()) {
+ return ::arrow::Status::IndexError("Column index ", column_idx, " is not valid");
+ }
+
+ auto field_node = descr->GetColumnRoot(column_idx);
+ auto field_idx = group->FieldIndex(*field_node);
+ if (field_idx == -1) {
+ return ::arrow::Status::IndexError("Column index ", column_idx, " is not valid");
+ }
+
+ if (already_added.insert(field_idx).second) {
+ out.push_back(field_idx);
+ }
+ }
+ return out;
+ }
+};
+
+} // namespace arrow
+} // namespace parquet
diff --git a/lib/python3.12/site-packages/pyarrow/include/parquet/arrow/test_util.h b/lib/python3.12/site-packages/pyarrow/include/parquet/arrow/test_util.h
new file mode 100644
index 0000000000000000000000000000000000000000..05f6fd24ac038e4609f5f182dbff64dae4d21e4d
--- /dev/null
+++ b/lib/python3.12/site-packages/pyarrow/include/parquet/arrow/test_util.h
@@ -0,0 +1,487 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "arrow/array.h"
+#include "arrow/array/builder_binary.h"
+#include "arrow/array/builder_decimal.h"
+#include "arrow/array/builder_primitive.h"
+#include "arrow/testing/gtest_util.h"
+#include "arrow/testing/random.h"
+#include "arrow/type_fwd.h"
+#include "arrow/type_traits.h"
+#include "arrow/util/decimal.h"
+#include "arrow/util/float16.h"
+#include "parquet/column_reader.h"
+#include "parquet/test_util.h"
+
+namespace parquet {
+
+using internal::RecordReader;
+
+namespace arrow {
+
+using ::arrow::Array;
+using ::arrow::ChunkedArray;
+using ::arrow::Status;
+
+template >
+struct DecimalWithPrecisionAndScale {
+ using type = T;
+ static_assert(PRECISION >= T::kMinPrecision && PRECISION <= T::kMaxPrecision,
+ "Invalid precision value");
+ static constexpr ::arrow::Type::type type_id = T::type_id;
+ static constexpr int32_t precision = PRECISION;
+ static constexpr int32_t scale = PRECISION - 1;
+};
+template
+using Decimal32WithPrecisionAndScale =
+ DecimalWithPrecisionAndScale<::arrow::Decimal32Type, PRECISION>;
+template
+using Decimal64WithPrecisionAndScale =
+ DecimalWithPrecisionAndScale<::arrow::Decimal64Type, PRECISION>;
+template
+using Decimal128WithPrecisionAndScale =
+ DecimalWithPrecisionAndScale<::arrow::Decimal128Type, PRECISION>;
+template
+using Decimal256WithPrecisionAndScale =
+ DecimalWithPrecisionAndScale<::arrow::Decimal256Type, PRECISION>;
+
+template
+::arrow::enable_if_floating_point NonNullArray(
+ size_t size, std::shared_ptr* out) {
+ using c_type = typename ArrowType::c_type;
+ std::vector values;
+ if constexpr (::arrow::is_half_float_type::value) {
+ values.resize(size);
+ test::random_float16_numbers(static_cast(size), 0, ::arrow::util::Float16(0.0f),
+ ::arrow::util::Float16(1.0f), values.data());
+ } else {
+ ::arrow::random_real(size, 0, static_cast(0), static_cast(1),
+ &values);
+ }
+ ::arrow::NumericBuilder builder;
+ RETURN_NOT_OK(builder.AppendValues(values.data(), values.size()));
+ return builder.Finish(out);
+}
+
+template
+::arrow::enable_if_integer NonNullArray(size_t size,
+ std::shared_ptr* out) {
+ std::vector values;
+ ::arrow::randint(size, 0, 64, &values);
+
+ // Passing data type so this will work with TimestampType too
+ ::arrow::NumericBuilder builder(std::make_shared(),
+ ::arrow::default_memory_pool());
+ RETURN_NOT_OK(builder.AppendValues(values.data(), values.size()));
+ return builder.Finish(out);
+}
+
+template
+::arrow::enable_if_date NonNullArray(size_t size,
+ std::shared_ptr* out) {
+ std::vector values;
+ ::arrow::randint(size, 0, 24, &values);
+ for (size_t i = 0; i < size; i++) {
+ values[i] *= 86400000;
+ }
+
+ // Passing data type so this will work with TimestampType too
+ ::arrow::NumericBuilder builder(std::make_shared(),
+ ::arrow::default_memory_pool());
+ RETURN_NOT_OK(builder.AppendValues(values.data(), values.size()));
+ return builder.Finish(out);
+}
+
+template
+::arrow::enable_if_base_binary NonNullArray(
+ size_t size, std::shared_ptr* out) {
+ using BuilderType = typename ::arrow::TypeTraits::BuilderType;
+ BuilderType builder;
+ for (size_t i = 0; i < size; i++) {
+ RETURN_NOT_OK(builder.Append("test-string"));
+ }
+ return builder.Finish(out);
+}
+
+template
+::arrow::enable_if_fixed_size_binary NonNullArray(
+ size_t size, std::shared_ptr* out) {
+ using BuilderType = typename ::arrow::TypeTraits::BuilderType;
+ // set byte_width to the length of "fixed": 5
+ // todo: find a way to generate test data with more diversity.
+ BuilderType builder(::arrow::fixed_size_binary(5));
+ for (size_t i = 0; i < size; i++) {
+ RETURN_NOT_OK(builder.Append("fixed"));
+ }
+ return builder.Finish(out);
+}
+
+template
+static void random_decimals(int64_t n, uint32_t seed, int32_t precision, uint8_t* out) {
+ auto gen = ::arrow::random::RandomArrayGenerator(seed);
+ std::shared_ptr decimals;
+ if constexpr (byte_width == 4) {
+ decimals = gen.Decimal32(::arrow::decimal32(precision, 0), n);
+ } else if constexpr (byte_width == 8) {
+ decimals = gen.Decimal64(::arrow::decimal64(precision, 0), n);
+ } else if constexpr (byte_width == 16) {
+ decimals = gen.Decimal128(::arrow::decimal128(precision, 0), n);
+ } else {
+ decimals = gen.Decimal256(::arrow::decimal256(precision, 0), n);
+ }
+ std::memcpy(out, decimals->data()->GetValues(1, 0), byte_width * n);
+}
+
+template
+::arrow::enable_if_t>,
+ Status>
+NonNullArray(size_t size, std::shared_ptr* out) {
+ constexpr int32_t kDecimalPrecision = precision;
+ constexpr int32_t kDecimalScale = ArrowType::scale;
+
+ const auto type =
+ std::make_shared(kDecimalPrecision, kDecimalScale);
+ const int32_t byte_width = type->byte_width();
+
+ constexpr int32_t seed = 0;
+
+ ARROW_ASSIGN_OR_RAISE(auto out_buf, ::arrow::AllocateBuffer(size * byte_width));
+ random_decimals(size, seed, kDecimalPrecision,
+ out_buf->mutable_data());
+
+ using Builder = typename ::arrow::TypeTraits::BuilderType;
+ Builder builder(type);
+ RETURN_NOT_OK(builder.AppendValues(out_buf->data(), size));
+ return builder.Finish(out);
+}
+
+template
+::arrow::enable_if_boolean NonNullArray(size_t size,
+ std::shared_ptr* out) {
+ std::vector values;
+ ::arrow::randint(size, 0, 1, &values);
+ ::arrow::BooleanBuilder builder;
+ RETURN_NOT_OK(builder.AppendValues(values.data(), values.size()));
+ return builder.Finish(out);
+}
+
+// This helper function only supports (size/2) nulls.
+template
+::arrow::enable_if_floating_point NullableArray(
+ size_t size, size_t num_nulls, uint32_t seed, std::shared_ptr* out) {
+ using c_type = typename ArrowType::c_type;
+ std::vector values;
+ if constexpr (::arrow::is_half_float_type::value) {
+ values.resize(size);
+ test::random_float16_numbers(static_cast(size), 0, ::arrow::util::Float16(-1e4f),
+ ::arrow::util::Float16(1e4f), values.data());
+ } else {
+ ::arrow::random_real(size, seed, static_cast(-1e10),
+ static_cast(1e10), &values);
+ }
+ std::vector valid_bytes(size, 1);
+
+ for (size_t i = 0; i < num_nulls; i++) {
+ valid_bytes[i * 2] = 0;
+ }
+
+ ::arrow::NumericBuilder builder;
+ if (values.size() > 0) {
+ RETURN_NOT_OK(builder.AppendValues(values.data(), values.size(), valid_bytes.data()));
+ }
+ return builder.Finish(out);
+}
+
+// This helper function only supports (size/2) nulls.
+template
+::arrow::enable_if_integer NullableArray(size_t size, size_t num_nulls,
+ uint32_t seed,
+ std::shared_ptr* out) {
+ std::vector values;
+
+ // Seed is random in Arrow right now
+ (void)seed;
+ ::arrow::randint(size, 0, 64, &values);
+ std::vector valid_bytes(size, 1);
+
+ for (size_t i = 0; i < num_nulls; i++) {
+ valid_bytes[i * 2] = 0;
+ }
+
+ // Passing data type so this will work with TimestampType too
+ ::arrow::NumericBuilder builder(std::make_shared(),
+ ::arrow::default_memory_pool());
+ RETURN_NOT_OK(builder.AppendValues(values.data(), values.size(), valid_bytes.data()));
+ return builder.Finish(out);
+}
+
+template
+::arrow::enable_if_date NullableArray(size_t size, size_t num_nulls,
+ uint32_t seed,
+ std::shared_ptr* out) {
+ std::vector values;
+
+ // Seed is random in Arrow right now
+ (void)seed;
+ ::arrow::randint(size, 0, 24, &values);
+ for (size_t i = 0; i < size; i++) {
+ values[i] *= 86400000;
+ }
+ std::vector valid_bytes(size, 1);
+
+ for (size_t i = 0; i < num_nulls; i++) {
+ valid_bytes[i * 2] = 0;
+ }
+
+ // Passing data type so this will work with TimestampType too
+ ::arrow::NumericBuilder builder(std::make_shared(),
+ ::arrow::default_memory_pool());
+ RETURN_NOT_OK(builder.AppendValues(values.data(), values.size(), valid_bytes.data()));
+ return builder.Finish(out);
+}
+
+// This helper function only supports (size/2) nulls yet.
+template
+::arrow::enable_if_base_binary NullableArray(
+ size_t size, size_t num_nulls, uint32_t seed, std::shared_ptr<::arrow::Array>* out) {
+ std::vector valid_bytes(size, 1);
+
+ for (size_t i = 0; i < num_nulls; i++) {
+ valid_bytes[i * 2] = 0;
+ }
+
+ using BuilderType = typename ::arrow::TypeTraits::BuilderType;
+ BuilderType builder;
+
+ const int kBufferSize = 10;
+ uint8_t buffer[kBufferSize];
+ for (size_t i = 0; i < size; i++) {
+ if (!valid_bytes[i]) {
+ RETURN_NOT_OK(builder.AppendNull());
+ } else {
+ ::arrow::random_bytes(kBufferSize, seed + static_cast(i), buffer);
+ if (ArrowType::is_utf8) {
+ // Trivially force data to be valid UTF8 by making it all ASCII
+ for (auto& byte : buffer) {
+ byte &= 0x7f;
+ }
+ }
+ RETURN_NOT_OK(builder.Append(buffer, kBufferSize));
+ }
+ }
+ return builder.Finish(out);
+}
+
+// This helper function only supports (size/2) nulls yet,
+// same as NullableArray(..)
+template
+::arrow::enable_if_fixed_size_binary NullableArray(
+ size_t size, size_t num_nulls, uint32_t seed, std::shared_ptr<::arrow::Array>* out) {
+ std::vector valid_bytes(size, 1);
+
+ for (size_t i = 0; i < num_nulls; i++) {
+ valid_bytes[i * 2] = 0;
+ }
+
+ using BuilderType = typename ::arrow::TypeTraits::BuilderType;
+ const int byte_width = 10;
+ BuilderType builder(::arrow::fixed_size_binary(byte_width));
+
+ const int kBufferSize = byte_width;
+ uint8_t buffer[kBufferSize];
+ for (size_t i = 0; i < size; i++) {
+ if (!valid_bytes[i]) {
+ RETURN_NOT_OK(builder.AppendNull());
+ } else {
+ ::arrow::random_bytes(kBufferSize, seed + static_cast(i), buffer);
+ RETURN_NOT_OK(builder.Append(buffer));
+ }
+ }
+ return builder.Finish(out);
+}
+
+template
+::arrow::enable_if_t>,
+ Status>
+NullableArray(size_t size, size_t num_nulls, uint32_t seed,
+ std::shared_ptr<::arrow::Array>* out) {
+ std::vector valid_bytes(size, '\1');
+
+ for (size_t i = 0; i < num_nulls; ++i) {
+ valid_bytes[i * 2] = '\0';
+ }
+
+ constexpr int32_t kDecimalPrecision = precision;
+ constexpr int32_t kDecimalScale = ArrowType::scale;
+
+ const auto type =
+ std::make_shared(kDecimalPrecision, kDecimalScale);
+ const int32_t byte_width = type->byte_width();
+
+ ARROW_ASSIGN_OR_RAISE(auto out_buf, ::arrow::AllocateBuffer(size * byte_width));
+ random_decimals(size, seed, precision,
+ out_buf->mutable_data());
+
+ using Builder = typename ::arrow::TypeTraits::BuilderType;
+ Builder builder(type);
+ RETURN_NOT_OK(builder.AppendValues(out_buf->data(), size, valid_bytes.data()));
+ return builder.Finish(out);
+}
+
+// This helper function only supports (size/2) nulls yet.
+template
+::arrow::enable_if_boolean NullableArray(size_t size, size_t num_nulls,
+ uint32_t seed,
+ std::shared_ptr* out) {
+ std::vector values;
+
+ // Seed is random in Arrow right now
+ (void)seed;
+
+ ::arrow::randint(size, 0, 1, &values);
+ std::vector valid_bytes(size, 1);
+
+ for (size_t i = 0; i < num_nulls; i++) {
+ valid_bytes[i * 2] = 0;
+ }
+
+ ::arrow::BooleanBuilder builder;
+ RETURN_NOT_OK(builder.AppendValues(values.data(), values.size(), valid_bytes.data()));
+ return builder.Finish(out);
+}
+
+/// Wrap an Array into a ListArray by splitting it up into size lists.
+///
+/// This helper function only supports (size/2) nulls.
+Status MakeListArray(const std::shared_ptr& values, int64_t size,
+ int64_t null_count, const std::string& item_name,
+ bool nullable_values, std::shared_ptr<::arrow::ListArray>* out) {
+ // We always include an empty list
+ int64_t non_null_entries = size - null_count - 1;
+ int64_t length_per_entry = values->length() / non_null_entries;
+
+ auto offsets = AllocateBuffer();
+ RETURN_NOT_OK(offsets->Resize((size + 1) * sizeof(int32_t)));
+ int32_t* offsets_ptr = reinterpret_cast(offsets->mutable_data());
+
+ auto null_bitmap = AllocateBuffer();
+ int64_t bitmap_size = ::arrow::bit_util::BytesForBits(size);
+ RETURN_NOT_OK(null_bitmap->Resize(bitmap_size));
+ uint8_t* null_bitmap_ptr = null_bitmap->mutable_data();
+ memset(null_bitmap_ptr, 0, bitmap_size);
+
+ int32_t current_offset = 0;
+ for (int64_t i = 0; i < size; i++) {
+ offsets_ptr[i] = current_offset;
+ if (!(((i % 2) == 0) && ((i / 2) < null_count))) {
+ // Non-null list (list with index 1 is always empty).
+ ::arrow::bit_util::SetBit(null_bitmap_ptr, i);
+ if (i != 1) {
+ current_offset += static_cast(length_per_entry);
+ }
+ }
+ }
+ offsets_ptr[size] = static_cast